mirror of
https://github.com/FliegendeWurst/tmux-thumbs.git
synced 2024-11-09 16:00:35 +00:00
Adds OSC52 copy escape sequence support
Currently I can only get the copied content in the tmux copy buffer, not in the system clipboard. This commit adds an option to print the copied text as a OSC52 copy escape sequence, which in supported terminals (tested in iTerm) will be copied to the system clipboard.
This commit is contained in:
parent
794621f526
commit
25ed6dc78f
@ -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:
|
||||||
|
36
src/main.rs
36
src/main.rs
@ -1,3 +1,4 @@
|
|||||||
|
extern crate base64;
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate termion;
|
extern crate termion;
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ 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::prelude::*;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
fn app_args<'a>() -> clap::ArgMatches<'a> {
|
fn app_args<'a>() -> clap::ArgMatches<'a> {
|
||||||
App::new("thumbs")
|
App::new("thumbs")
|
||||||
@ -84,6 +85,12 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
|
|||||||
.long("unique")
|
.long("unique")
|
||||||
.short("u"),
|
.short("u"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("osc52")
|
||||||
|
.help("Print OSC52 copy escape sequence in addition to running the pick command")
|
||||||
|
.long("osc52")
|
||||||
|
.short("o"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("position")
|
Arg::with_name("position")
|
||||||
.help("Hint position")
|
.help("Hint position")
|
||||||
@ -124,6 +131,7 @@ fn main() {
|
|||||||
let multi = args.is_present("multi");
|
let multi = args.is_present("multi");
|
||||||
let reverse = args.is_present("reverse");
|
let reverse = args.is_present("reverse");
|
||||||
let unique = args.is_present("unique");
|
let unique = args.is_present("unique");
|
||||||
|
let osc52 = args.is_present("osc52");
|
||||||
let contrast = args.is_present("contrast");
|
let contrast = args.is_present("contrast");
|
||||||
let regexp = if let Some(items) = args.values_of("regexp") {
|
let regexp = if let Some(items) = args.values_of("regexp") {
|
||||||
items.collect::<Vec<_>>()
|
items.collect::<Vec<_>>()
|
||||||
@ -182,6 +190,32 @@ fn main() {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
|
if 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"));
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
Loading…
Reference in New Issue
Block a user