Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New set of available keys (Ctrl, Alt) #120

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ These are the list of matched patterns that will be highlighted by default. If
you want to highlight a pattern that is not in this list you can add one or
more with `--regexp` parameter.


## Key shortcuts

While in **[thumbs]** mode, you can use the following shortcuts:

* <kbd>a</kbd>-<kbd>z</kbd>: copies selected match to the clipboard
* <kbd>CTRL</kbd> + <kbd>a</kbd>-<kbd>z</kbd>: copies selected match to the clipboard and triggers [@thumbs-ctrl-action](#thumbs-ctrl-action).
* <kbd>SHIFT</kbd> + <kbd>a</kbd>-<kbd>z</kbd>: copies selected match to the clipboard and triggers [@thumbs-shift-action](#thumbs-shift-action).
* <kbd>ALT</kbd> + <kbd>a</kbd>-<kbd>z</kbd>: copies selected match to the clipboard and triggers [@thumbs-alt-action](#thumbs-alt-action).
* <kbd>CTRL</kbd> + <kbd>c</kbd>: exit **[thumbs]** mode
* <kbd>ESC</kbd>: exit help or **[thumbs]** mode
* <kbd>?</kbd>: show help.

## Demo

[![demo](https://asciinema.org/a/232775.png?ts=1)](https://asciinema.org/a/232775?autoplay=1)
Expand Down Expand Up @@ -93,9 +106,13 @@ NOTE: for changes to take effect, you'll need to source again your `.tmux.conf`
* [@thumbs-unique](#thumbs-unique)
* [@thumbs-position](#thumbs-position)
* [@thumbs-regexp-N](#thumbs-regexp-N)
* [@thumbs-command](#thumbs-command)
* [@thumbs-upcase-command](#thumbs-upcase-command)
* [@thumbs-multi-command](#thumbs-multi-command)

* [@thumbs-main-action](#thumbs-main-action)
* [@thumbs-shift-action](#thumbs-shift-action)
* [@thumbs-ctrl-action](#thumbs-ctrl-action)
* [@thumbs-alt-action](#thumbs-alt-action)
* [@thumbs-multi-action](#thumbs-multi-action)

* [@thumbs-bg-color](#thumbs-bg-color)
* [@thumbs-fg-color](#thumbs-fg-color)
* [@thumbs-hint-bg-color](#thumbs-hint-bg-color)
Expand All @@ -106,6 +123,9 @@ NOTE: for changes to take effect, you'll need to source again your `.tmux.conf`
* [@thumbs-multi-bg-color](#thumbs-multi-bg-color)
* [@thumbs-contrast](#thumbs-contrast)
* [@thumbs-osc52](#thumbs-osc52)
* deprecated: [@thumbs-command](#thumbs-command)
* deprecated: [@thumbs-upcase-command](#thumbs-upcase-command)
* deprecated: [@thumbs-multi-command](#thumbs-multi-command)

### @thumbs-key

Expand Down
8 changes: 3 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
)
.arg(
Arg::with_name("format")
.help("Specifies the out format for the picked hint. (%U: Upcase, %H: Hint)")
.help("Specifies the out format for the picked hint. (%K: Key, %H: Hint)")
.long("format")
.short("f")
.default_value("%H"),
Expand Down Expand Up @@ -198,12 +198,10 @@ fn main() {
if !selected.is_empty() {
let output = selected
.iter()
.map(|(text, upcase)| {
let upcase_value = if *upcase { "true" } else { "false" };

.map(|(text, modkey)| {
let mut output = format.to_string();

output = str::replace(&output, "%U", upcase_value);
output = str::replace(&output, "%K", modkey);
output = str::replace(&output, "%H", text.as_str());
output
})
Expand Down
117 changes: 79 additions & 38 deletions src/swapper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
extern crate clap;

mod view;

use self::clap::{App, Arg};
use clap::crate_version;
use regex::Regex;
Expand Down Expand Up @@ -58,9 +60,11 @@ fn dbg(msg: &str) {
pub struct Swapper<'a> {
executor: Box<&'a mut dyn Executor>,
dir: String,
command: String,
upcase_command: String,
multi_command: String,
main_action: String,
shift_action: String,
ctrl_action: String,
alt_action: String,
multi_action: String,
osc52: bool,
active_pane_id: Option<String>,
active_pane_height: Option<i32>,
Expand All @@ -75,9 +79,11 @@ impl<'a> Swapper<'a> {
fn new(
executor: Box<&'a mut dyn Executor>,
dir: String,
command: String,
upcase_command: String,
multi_command: String,
main_action: String,
shift_action: String,
ctrl_action: String,
alt_action: String,
multi_action: String,
osc52: bool,
) -> Swapper {
let since_the_epoch = SystemTime::now()
Expand All @@ -88,9 +94,11 @@ impl<'a> Swapper<'a> {
Swapper {
executor,
dir,
command,
upcase_command,
multi_command,
main_action,
shift_action,
ctrl_action,
alt_action,
multi_action,
osc52,
active_pane_id: None,
active_pane_height: None,
Expand Down Expand Up @@ -215,7 +223,7 @@ impl<'a> Swapper<'a> {
};

let pane_command = format!(
"tmux capture-pane -t {active_pane_id} -p{scroll_params} | tail -n {height} | {dir}/target/release/thumbs -f '%U:%H' -t {tmp} {args}; tmux swap-pane -t {active_pane_id}; {zoom_command} tmux wait-for -S {signal}",
"tmux capture-pane -t {active_pane_id} -p{scroll_params} | tail -n {height} | {dir}/target/release/thumbs -f '%K:%H' -t {tmp} {args}; tmux swap-pane -t {active_pane_id}; {zoom_command} tmux wait-for -S {signal}",
active_pane_id = active_pane_id,
scroll_params = scroll_params,
height = self.active_pane_height.unwrap_or(i32::MAX),
Expand Down Expand Up @@ -320,7 +328,8 @@ impl<'a> Swapper<'a> {
.collect::<Vec<&str>>()
.join(" ");

self.execute_final_command(&text, &self.multi_command.clone());
// REVIEW: Not sure about the ModifierKeys here
self.execute_final_command(&text, &view::ModifierKeys::Main.to_string(), &self.multi_action.clone());

return;
}
Expand All @@ -330,7 +339,7 @@ impl<'a> Swapper<'a> {

let mut splitter = item.splitn(2, ':');

if let Some(upcase) = splitter.next() {
if let Some(modkey) = splitter.next() {
if let Some(text) = splitter.next() {
if self.osc52 {
let base64_text = base64::encode(text.as_bytes());
Expand Down Expand Up @@ -360,10 +369,17 @@ impl<'a> Swapper<'a> {
std::io::stdout().flush().unwrap();
}

let execute_command = if upcase.trim_end() == "true" {
self.upcase_command.clone()
} else {
self.command.clone()
let modkey = modkey.trim_end();

let shift = view::ModifierKeys::Shift.to_string();
let ctrl = view::ModifierKeys::Ctrl.to_string();
let alt = view::ModifierKeys::Alt.to_string();

let execute_command = match modkey {
shift => self.shift_action.clone(),
ctrl => self.ctrl_action.clone(),
alt => self.alt_action.clone(),
_ => self.main_action.clone(),
};

// The command we run has two arguments:
Expand All @@ -389,19 +405,20 @@ impl<'a> Swapper<'a> {
// Ideally user commands would just use "${THUMB}" to begin with rather than having any
// sort of ad-hoc string splicing here at all, and then they could specify the quoting they
// want, but that would break backwards compatibility.
self.execute_final_command(text.trim_end(), &execute_command);
self.execute_final_command(text.trim_end(), modkey, &execute_command);
}
}
}

pub fn execute_final_command(&mut self, text: &str, execute_command: &str) {
pub fn execute_final_command(&mut self, text: &str, modkey: &str, execute_command: &str) {
let final_command = str::replace(execute_command, "{}", "${THUMB}");
let retrieve_command = vec![
"bash",
"-c",
"THUMB=\"$1\"; eval \"$2\"",
"THUMB=\"$1\"; MODIFIER=\"$2\"; eval \"$3\"",
"--",
text,
modkey,
final_command.as_str(),
];

Expand Down Expand Up @@ -450,6 +467,8 @@ mod tests {
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
false,
);

Expand All @@ -473,6 +492,8 @@ mod tests {
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
false,
);

Expand All @@ -490,15 +511,19 @@ mod tests {
let last_command_outputs = vec!["Blah blah blah, the ignored user script output".to_string()];
let mut executor = TestShell::new(last_command_outputs);

let user_command = "echo \"{}\"".to_string();
let upcase_command = "open \"{}\"".to_string();
let multi_command = "open \"{}\"".to_string();
let main_action = "echo \"{}\"".to_string();
let shift_action = "open \"{}\"".to_string();
let ctrl_action = "echo \"{}\"".to_string();
let alt_action = "echo \"{}\"".to_string();
let multi_action = "open \"{}\"".to_string();
let mut swapper = Swapper::new(
Box::new(&mut executor),
"".to_string(),
user_command,
upcase_command,
multi_command,
main_action,
shift_action,
ctrl_action,
alt_action,
multi_action,
false,
);

Expand Down Expand Up @@ -539,21 +564,33 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
.default_value(""),
)
.arg(
Arg::with_name("command")
Arg::with_name("main-action")
.help("Command to execute after choose a hint")
.long("command")
.long("main-action")
.default_value("tmux set-buffer -- \"{}\" && tmux display-message \"Copied {}\""),
)
.arg(
Arg::with_name("upcase_command")
.help("Command to execute after choose a hint, in upcase")
.long("upcase-command")
Arg::with_name("shift-action")
.help("Command to execute after choose a hint with SHIFT key pressed (Upcase)")
.long("shift-action")
.default_value("tmux set-buffer -- \"{}\" && tmux paste-buffer && tmux display-message \"Copied {}\""),
)
.arg(
Arg::with_name("multi_command")
Arg::with_name("ctrl-action")
.help("Command to execute after choose a hint with CTRL key pressed")
.long("ctrl-action")
.default_value("tmux display-message \"No CTRL action configured! Hint: {}\""),
)
.arg(
Arg::with_name("alt-action")
.help("Command to execute after choose a hint with ALT key pressed")
.long("alt-action")
.default_value("tmux display-message \"No ALT action configured! Hint: {}\" && echo \"FOO $MODIFIER ~ $HINT BAR\" > /tmp/tx.txt"),
)
.arg(
Arg::with_name("multi-action")
.help("Command to execute after choose multiple hints")
.long("multi-command")
.long("multi-action")
.default_value("tmux set-buffer -- \"{}\" && tmux paste-buffer && tmux display-message \"Multi copied {}\""),
)
.arg(
Expand All @@ -568,9 +605,11 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
fn main() -> std::io::Result<()> {
let args = app_args();
let dir = args.value_of("dir").unwrap();
let command = args.value_of("command").unwrap();
let upcase_command = args.value_of("upcase_command").unwrap();
let multi_command = args.value_of("multi_command").unwrap();
let main_action = args.value_of("main-action").unwrap();
let shift_action = args.value_of("shift-action").unwrap();
let ctrl_action = args.value_of("ctrl-action").unwrap();
let alt_action = args.value_of("alt-action").unwrap();
let multi_action = args.value_of("multi-action").unwrap();
let osc52 = args.is_present("osc52");

if dir.is_empty() {
Expand All @@ -581,9 +620,11 @@ fn main() -> std::io::Result<()> {
let mut swapper = Swapper::new(
Box::new(&mut executor),
dir.to_string(),
command.to_string(),
upcase_command.to_string(),
multi_command.to_string(),
main_action.to_string(),
shift_action.to_string(),
ctrl_action.to_string(),
alt_action.to_string(),
multi_action.to_string(),
osc52,
);

Expand Down
Loading