mirror of
https://github.com/FliegendeWurst/tmux-thumbs.git
synced 2024-11-22 21:05:00 +00:00
Merge branch 'osc52'
This commit is contained in:
commit
a3c057e875
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -26,6 +26,11 @@ dependencies = [
|
|||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -138,6 +143,7 @@ dependencies = [
|
|||||||
name = "thumbs"
|
name = "thumbs"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -176,6 +182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
||||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||||
"checksum hermit-abi 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
|
"checksum hermit-abi 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
|
||||||
|
@ -12,6 +12,7 @@ license = "MIT"
|
|||||||
termion = "1.5"
|
termion = "1.5"
|
||||||
regex = "1.3.1"
|
regex = "1.3.1"
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
|
base64 = "0.11.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "thumbs"
|
name = "thumbs"
|
||||||
|
13
README.md
13
README.md
@ -93,6 +93,7 @@ NOTE: for changes to take effect, you'll need to source again your `.tmux.conf`
|
|||||||
* [@thumbs-select-fg-color](#thumbs-select-fg-color)
|
* [@thumbs-select-fg-color](#thumbs-select-fg-color)
|
||||||
* [@thumbs-select-bg-color](#thumbs-select-bg-color)
|
* [@thumbs-select-bg-color](#thumbs-select-bg-color)
|
||||||
* [@thumbs-contrast](#thumbs-contrast)
|
* [@thumbs-contrast](#thumbs-contrast)
|
||||||
|
* [@thumbs-osc52](#thumbs-osc52)
|
||||||
|
|
||||||
### @thumbs-key
|
### @thumbs-key
|
||||||
|
|
||||||
@ -273,6 +274,18 @@ For example:
|
|||||||
set -g @thumbs-contrast 1
|
set -g @thumbs-contrast 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### @thumbs-osc52
|
||||||
|
|
||||||
|
`default: 0`
|
||||||
|
|
||||||
|
If this is set to `1`, `tmux-thumbs` will print a OSC52 copy escape sequence when you select a match, in addition to running the pick command. This sequence, in terminals that support it (e.g. iTerm), allows the content to be copied into the system clipboard in addition to the tmux copy buffer.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @thumbs-osc52 1
|
||||||
|
```
|
||||||
|
|
||||||
#### Colors
|
#### Colors
|
||||||
|
|
||||||
This is the list of available colors:
|
This is the list of available colors:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
extern crate base64;
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate termion;
|
extern crate termion;
|
||||||
|
|
||||||
@ -9,8 +10,7 @@ mod view;
|
|||||||
use self::clap::{App, Arg};
|
use self::clap::{App, Arg};
|
||||||
use clap::crate_version;
|
use clap::crate_version;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::prelude::*;
|
use std::io::{self, Read, Write};
|
||||||
use std::io::{self, Read};
|
|
||||||
|
|
||||||
fn app_args<'a>() -> clap::ArgMatches<'a> {
|
fn app_args<'a>() -> clap::ArgMatches<'a> {
|
||||||
App::new("thumbs")
|
App::new("thumbs")
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
use self::clap::{App, Arg};
|
use self::clap::{App, Arg};
|
||||||
use clap::crate_version;
|
use clap::crate_version;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@ -47,6 +50,7 @@ pub struct Swapper<'a> {
|
|||||||
dir: String,
|
dir: String,
|
||||||
command: String,
|
command: String,
|
||||||
upcase_command: String,
|
upcase_command: String,
|
||||||
|
osc52: bool,
|
||||||
active_pane_id: Option<String>,
|
active_pane_id: Option<String>,
|
||||||
active_pane_height: Option<i32>,
|
active_pane_height: Option<i32>,
|
||||||
active_pane_scroll_position: Option<i32>,
|
active_pane_scroll_position: Option<i32>,
|
||||||
@ -57,7 +61,7 @@ pub struct Swapper<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Swapper<'a> {
|
impl<'a> Swapper<'a> {
|
||||||
fn new(executor: Box<&'a mut dyn Executor>, dir: String, command: String, upcase_command: String) -> Swapper {
|
fn new(executor: Box<&'a mut dyn Executor>, dir: String, command: String, upcase_command: String, osc52: bool) -> Swapper {
|
||||||
let since_the_epoch = SystemTime::now()
|
let since_the_epoch = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.expect("Time went backwards");
|
.expect("Time went backwards");
|
||||||
@ -68,6 +72,7 @@ impl<'a> Swapper<'a> {
|
|||||||
dir,
|
dir,
|
||||||
command,
|
command,
|
||||||
upcase_command,
|
upcase_command,
|
||||||
|
osc52,
|
||||||
active_pane_id: None,
|
active_pane_id: None,
|
||||||
active_pane_height: None,
|
active_pane_height: None,
|
||||||
active_pane_scroll_position: None,
|
active_pane_scroll_position: None,
|
||||||
@ -247,12 +252,44 @@ impl<'a> Swapper<'a> {
|
|||||||
self.executor.execute(params);
|
self.executor.execute(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_osc52(&mut self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn execute_command(&mut self) {
|
pub fn execute_command(&mut self) {
|
||||||
let content = self.content.clone().unwrap();
|
let content = self.content.clone().unwrap();
|
||||||
let mut splitter = content.splitn(2, ':');
|
let mut splitter = content.splitn(2, ':');
|
||||||
|
|
||||||
if let Some(upcase) = splitter.next() {
|
if let Some(upcase) = splitter.next() {
|
||||||
if let Some(text) = splitter.next() {
|
if let Some(text) = splitter.next() {
|
||||||
|
if self.osc52 {
|
||||||
|
let base64_text = base64::encode(text.as_bytes());
|
||||||
|
let osc_seq = format!("\x1b]52;0;{}\x07", base64_text);
|
||||||
|
let tmux_seq = format!("\x1bPtmux;{}\x1b\\", osc_seq.replace("\x1b", "\x1b\x1b"));
|
||||||
|
|
||||||
|
// FIXME: Review if this comment is still rellevant
|
||||||
|
//
|
||||||
|
// When the user selects a match:
|
||||||
|
// 1. The `rustbox` object created in the `viewbox` above is dropped.
|
||||||
|
// 2. During its `drop`, the `rustbox` object sends a CSI 1049 escape
|
||||||
|
// sequence to tmux.
|
||||||
|
// 3. This escape sequence causes the `window_pane_alternate_off` function
|
||||||
|
// in tmux to be called.
|
||||||
|
// 4. In `window_pane_alternate_off`, tmux sets the needs-redraw flag in the
|
||||||
|
// pane.
|
||||||
|
// 5. If we print the OSC copy escape sequence before the redraw is completed,
|
||||||
|
// tmux will *not* send the sequence to the host terminal. See the following
|
||||||
|
// call chain in tmux: `input_dcs_dispatch` -> `screen_write_rawstring`
|
||||||
|
// -> `tty_write` -> `tty_client_ready`. In this case, `tty_client_ready`
|
||||||
|
// will return false, thus preventing the escape sequence from being sent.
|
||||||
|
//
|
||||||
|
// Therefore, for now we wait a little bit here for the redraw to finish.
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
|
std::io::stdout().write_all(tmux_seq.as_bytes()).unwrap();
|
||||||
|
std::io::stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let execute_command = if upcase.trim_end() == "true" {
|
let execute_command = if upcase.trim_end() == "true" {
|
||||||
self.upcase_command.clone()
|
self.upcase_command.clone()
|
||||||
} else {
|
} else {
|
||||||
@ -302,7 +339,7 @@ mod tests {
|
|||||||
fn retrieve_active_pane() {
|
fn retrieve_active_pane() {
|
||||||
let last_command_outputs = vec!["%97:100:24:1:active\n%106:100:24:1:nope\n%107:100:24:1:nope\n".to_string()];
|
let last_command_outputs = vec!["%97:100:24:1:active\n%106:100:24:1:nope\n%107:100:24:1:nope\n".to_string()];
|
||||||
let mut executor = TestShell::new(last_command_outputs);
|
let mut executor = TestShell::new(last_command_outputs);
|
||||||
let mut swapper = Swapper::new(Box::new(&mut executor), "".to_string(), "".to_string(), "".to_string());
|
let mut swapper = Swapper::new(Box::new(&mut executor), "".to_string(), "".to_string(), "".to_string(), false);
|
||||||
|
|
||||||
swapper.capture_active_pane();
|
swapper.capture_active_pane();
|
||||||
|
|
||||||
@ -318,7 +355,7 @@ mod tests {
|
|||||||
"%106:100:24:1:nope\n%98:100:24:1:active\n%107:100:24:1:nope\n".to_string(),
|
"%106:100:24:1:nope\n%98:100:24:1:active\n%107:100:24:1:nope\n".to_string(),
|
||||||
];
|
];
|
||||||
let mut executor = TestShell::new(last_command_outputs);
|
let mut executor = TestShell::new(last_command_outputs);
|
||||||
let mut swapper = Swapper::new(Box::new(&mut executor), "".to_string(), "".to_string(), "".to_string());
|
let mut swapper = Swapper::new(Box::new(&mut executor), "".to_string(), "".to_string(), "".to_string(), false);
|
||||||
|
|
||||||
swapper.capture_active_pane();
|
swapper.capture_active_pane();
|
||||||
swapper.execute_thumbs();
|
swapper.execute_thumbs();
|
||||||
@ -352,6 +389,12 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
|
|||||||
.long("upcase-command")
|
.long("upcase-command")
|
||||||
.default_value("tmux set-buffer {} && tmux paste-buffer"),
|
.default_value("tmux set-buffer {} && tmux paste-buffer"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("osc52")
|
||||||
|
.help("Print OSC52 copy escape sequence in addition to running the pick command")
|
||||||
|
.long("osc52")
|
||||||
|
.short("o"),
|
||||||
|
)
|
||||||
.get_matches()
|
.get_matches()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,6 +403,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let dir = args.value_of("dir").unwrap();
|
let dir = args.value_of("dir").unwrap();
|
||||||
let command = args.value_of("command").unwrap();
|
let command = args.value_of("command").unwrap();
|
||||||
let upcase_command = args.value_of("upcase_command").unwrap();
|
let upcase_command = args.value_of("upcase_command").unwrap();
|
||||||
|
let osc52 = args.is_present("osc52");
|
||||||
|
|
||||||
if dir.is_empty() {
|
if dir.is_empty() {
|
||||||
panic!("Invalid tmux-thumbs execution. Are you trying to execute tmux-thumbs directly?")
|
panic!("Invalid tmux-thumbs execution. Are you trying to execute tmux-thumbs directly?")
|
||||||
@ -371,6 +415,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
dir.to_string(),
|
dir.to_string(),
|
||||||
command.to_string(),
|
command.to_string(),
|
||||||
upcase_command.to_string(),
|
upcase_command.to_string(),
|
||||||
|
osc52,
|
||||||
);
|
);
|
||||||
|
|
||||||
swapper.capture_active_pane();
|
swapper.capture_active_pane();
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
PARAMS=()
|
PARAMS=()
|
||||||
|
|
||||||
|
function add-boolean-param {
|
||||||
|
VALUE=$(tmux show -vg @thumbs-$1 2> /dev/null)
|
||||||
|
|
||||||
|
if [[ "${VALUE}" == "1" ]]; then
|
||||||
|
PARAMS+=("--$1")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function add-option-param {
|
function add-option-param {
|
||||||
VALUE=$(tmux show -vg @thumbs-$1 2> /dev/null)
|
VALUE=$(tmux show -vg @thumbs-$1 2> /dev/null)
|
||||||
|
|
||||||
@ -14,6 +22,7 @@ function add-option-param {
|
|||||||
|
|
||||||
add-option-param "command"
|
add-option-param "command"
|
||||||
add-option-param "upcase-command"
|
add-option-param "upcase-command"
|
||||||
|
add-boolean-param "osc52"
|
||||||
|
|
||||||
# Remove empty arguments from PARAMS.
|
# Remove empty arguments from PARAMS.
|
||||||
# Otherwise, they would choke up tmux-thumbs when passed to it.
|
# Otherwise, they would choke up tmux-thumbs when passed to it.
|
||||||
|
Loading…
Reference in New Issue
Block a user