mirror of
https://github.com/FliegendeWurst/tmux-thumbs.git
synced 2024-11-24 05:45:00 +00:00
Capture pane with ANSI escape codes
Co-Authored-By: Ian Henry <ianthehenry@gmail.com>
This commit is contained in:
parent
ae91d5f7c0
commit
c0ed78beee
60
Cargo.lock
generated
60
Cargo.lock
generated
@ -91,6 +91,24 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.66"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
@ -126,6 +144,15 @@ version = "0.6.28"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strip-ansi-escapes"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa"
|
||||||
|
dependencies = [
|
||||||
|
"vte",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -161,22 +188,55 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"regex",
|
"regex",
|
||||||
|
"strip-ansi-escapes",
|
||||||
"termion",
|
"termion",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vte"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
"vte_generate_state_changes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vte_generate_state_changes"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -15,6 +15,7 @@ clap = "2.34.0"
|
|||||||
base64 = "0.13.1"
|
base64 = "0.13.1"
|
||||||
unicode-width = "0.1.10"
|
unicode-width = "0.1.10"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
strip-ansi-escapes = "0.2.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "thumbs"
|
name = "thumbs"
|
||||||
|
36
README.md
36
README.md
@ -106,6 +106,7 @@ NOTE: for changes to take effect, you'll need to source again your `.tmux.conf`
|
|||||||
* [@thumbs-multi-bg-color](#thumbs-multi-bg-color)
|
* [@thumbs-multi-bg-color](#thumbs-multi-bg-color)
|
||||||
* [@thumbs-contrast](#thumbs-contrast)
|
* [@thumbs-contrast](#thumbs-contrast)
|
||||||
* [@thumbs-osc52](#thumbs-osc52)
|
* [@thumbs-osc52](#thumbs-osc52)
|
||||||
|
* [@thumbs-keep-colors](#thumbs-keep-colors)
|
||||||
|
|
||||||
### @thumbs-key
|
### @thumbs-key
|
||||||
|
|
||||||
@ -344,6 +345,18 @@ For example:
|
|||||||
set -g @thumbs-osc52 1
|
set -g @thumbs-osc52 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### @thumbs-keep-colors
|
||||||
|
|
||||||
|
`default: 0`
|
||||||
|
|
||||||
|
Keep text styling of the input when displaying matches.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @thumbs-keep-colors 1
|
||||||
|
```
|
||||||
|
|
||||||
#### Colors
|
#### Colors
|
||||||
|
|
||||||
This is the list of predefined colors:
|
This is the list of predefined colors:
|
||||||
@ -433,19 +446,20 @@ cargo install thumbs
|
|||||||
And those are all available options:
|
And those are all available options:
|
||||||
|
|
||||||
```
|
```
|
||||||
thumbs 0.7.1
|
thumbs 0.8.0
|
||||||
A lightning fast version copy/pasting like vimium/vimperator
|
A lightning fast version copy/pasting like vimium/vimperator
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
thumbs [FLAGS] [OPTIONS]
|
thumbs [FLAGS] [OPTIONS]
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-c, --contrast Put square brackets around hint for visibility
|
-c, --contrast Put square brackets around hint for visibility
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-m, --multi Enable multi-selection
|
--keep-colors Preserve text styling of input
|
||||||
-r, --reverse Reverse the order for assigned hints
|
-m, --multi Enable multi-selection
|
||||||
-u, --unique Don't show duplicated hints for the same match
|
-r, --reverse Reverse the order for assigned hints
|
||||||
-V, --version Prints version information
|
-u, --unique Don't show duplicated hints for the same match
|
||||||
|
-V, --version Prints version information
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-a, --alphabet <alphabet> Sets the alphabet [default: qwerty]
|
-a, --alphabet <alphabet> Sets the alphabet [default: qwerty]
|
||||||
@ -456,12 +470,16 @@ OPTIONS:
|
|||||||
|
|
||||||
--hint-bg-color <hint_background_color> Sets the background color for hints [default: black]
|
--hint-bg-color <hint_background_color> Sets the background color for hints [default: black]
|
||||||
--hint-fg-color <hint_foreground_color> Sets the foregroud color for hints [default: yellow]
|
--hint-fg-color <hint_foreground_color> Sets the foregroud color for hints [default: yellow]
|
||||||
|
--multi-bg-color <multi_background_color>
|
||||||
|
Sets the background color for a multi selected item [default: black]
|
||||||
|
|
||||||
|
--multi-fg-color <multi_foreground_color>
|
||||||
|
Sets the foreground color for a multi selected item [default: yellow]
|
||||||
|
|
||||||
-p, --position <position> Hint position [default: left]
|
-p, --position <position> Hint position [default: left]
|
||||||
-x, --regexp <regexp>... Use this regexp as extra pattern to match
|
-x, --regexp <regexp>... Use this regexp as extra pattern to match
|
||||||
--select-bg-color <select_background_color> Sets the background color for selection [default: black]
|
--select-bg-color <select_background_color> Sets the background color for selection [default: black]
|
||||||
--select-fg-color <select_foreground_color> Sets the foreground color for selection [default: blue]
|
--select-fg-color <select_foreground_color> Sets the foreground color for selection [default: blue]
|
||||||
--multi-bg-color <multi_background_color> Sets the background color for a multi selected item [default: black]
|
|
||||||
--multi-fg-color <multi_foreground_color> Sets the foreground color for a multi selected item [default: cyan]
|
|
||||||
-t, --target <target> Stores the hint in the specified path
|
-t, --target <target> Stores the hint in the specified path
|
||||||
```
|
```
|
||||||
|
|
||||||
|
20
src/main.rs
20
src/main.rs
@ -136,6 +136,11 @@ fn app_args<'a>() -> clap::ArgMatches<'a> {
|
|||||||
.short("t")
|
.short("t")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("keep-colors")
|
||||||
|
.help("Preserve text styling of input")
|
||||||
|
.long("keep-colors"),
|
||||||
|
)
|
||||||
.get_matches()
|
.get_matches()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +154,7 @@ fn main() {
|
|||||||
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 contrast = args.is_present("contrast");
|
let contrast = args.is_present("contrast");
|
||||||
|
let keep_colors = args.is_present("keep-colors");
|
||||||
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<_>>()
|
||||||
} else {
|
} else {
|
||||||
@ -172,7 +178,19 @@ fn main() {
|
|||||||
|
|
||||||
let lines = output.split('\n').collect::<Vec<&str>>();
|
let lines = output.split('\n').collect::<Vec<&str>>();
|
||||||
|
|
||||||
let mut state = state::State::new(&lines, alphabet, ®exp);
|
let mut state;
|
||||||
|
// strip ansi color codes for match searching
|
||||||
|
let unescaped: Vec<_> = lines
|
||||||
|
.iter()
|
||||||
|
.map(|line| String::from_utf8(strip_ansi_escapes::strip(line)).unwrap())
|
||||||
|
.collect();
|
||||||
|
let reference = unescaped.iter().map(|x| &**x).collect();
|
||||||
|
|
||||||
|
if keep_colors {
|
||||||
|
state = state::State::new_extended(&lines, reference, alphabet, ®exp);
|
||||||
|
} else {
|
||||||
|
state = state::State::new_extended(&reference, reference.clone(), alphabet, ®exp);
|
||||||
|
}
|
||||||
|
|
||||||
let selected = {
|
let selected = {
|
||||||
let mut viewbox = view::View::new(
|
let mut viewbox = view::View::new(
|
||||||
|
20
src/state.rs
20
src/state.rs
@ -56,19 +56,36 @@ impl<'a> PartialEq for Match<'a> {
|
|||||||
|
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
pub lines: &'a Vec<&'a str>,
|
pub lines: &'a Vec<&'a str>,
|
||||||
|
pub unescaped: Vec<&'a str>,
|
||||||
alphabet: &'a str,
|
alphabet: &'a str,
|
||||||
regexp: &'a Vec<&'a str>,
|
regexp: &'a Vec<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
|
#[cfg(test)]
|
||||||
pub fn new(lines: &'a Vec<&'a str>, alphabet: &'a str, regexp: &'a Vec<&'a str>) -> State<'a> {
|
pub fn new(lines: &'a Vec<&'a str>, alphabet: &'a str, regexp: &'a Vec<&'a str>) -> State<'a> {
|
||||||
State {
|
State {
|
||||||
|
unescaped: lines.clone(),
|
||||||
lines,
|
lines,
|
||||||
alphabet,
|
alphabet,
|
||||||
regexp,
|
regexp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_extended(
|
||||||
|
lines: &'a Vec<&'a str>,
|
||||||
|
unescaped: Vec<&'a str>,
|
||||||
|
alphabet: &'a str,
|
||||||
|
regexp: &'a Vec<&'a str>,
|
||||||
|
) -> State<'a> {
|
||||||
|
State {
|
||||||
|
lines,
|
||||||
|
unescaped,
|
||||||
|
alphabet,
|
||||||
|
regexp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn matches(&self, reverse: bool, unique: bool) -> Vec<Match<'a>> {
|
pub fn matches(&self, reverse: bool, unique: bool) -> Vec<Match<'a>> {
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
|
|
||||||
@ -91,8 +108,7 @@ impl<'a> State<'a> {
|
|||||||
// This order determines the priority of pattern matching
|
// This order determines the priority of pattern matching
|
||||||
let all_patterns = [exclude_patterns, custom_patterns, patterns].concat();
|
let all_patterns = [exclude_patterns, custom_patterns, patterns].concat();
|
||||||
|
|
||||||
for (index, line) in self.lines.iter().enumerate() {
|
for (index, &(mut chunk)) in self.unescaped.iter().enumerate() {
|
||||||
let mut chunk: &str = line;
|
|
||||||
let mut offset: i32 = 0;
|
let mut offset: i32 = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -164,7 +164,7 @@ impl<'a> Swapper<'a> {
|
|||||||
let name = captures.get(1).unwrap().as_str();
|
let name = captures.get(1).unwrap().as_str();
|
||||||
let value = captures.get(2).unwrap().as_str();
|
let value = captures.get(2).unwrap().as_str();
|
||||||
|
|
||||||
let boolean_params = vec!["reverse", "unique", "contrast"];
|
let boolean_params = vec!["reverse", "unique", "contrast", "keep-colors"];
|
||||||
|
|
||||||
if boolean_params.iter().any(|&x| x == name) {
|
if boolean_params.iter().any(|&x| x == name) {
|
||||||
return vec![format!("--{}", name)];
|
return vec![format!("--{}", name)];
|
||||||
@ -215,7 +215,7 @@ impl<'a> Swapper<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let pane_command = format!(
|
let pane_command = format!(
|
||||||
"tmux capture-pane -J -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 -J -et {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}",
|
||||||
active_pane_id = active_pane_id,
|
active_pane_id = active_pane_id,
|
||||||
scroll_params = scroll_params,
|
scroll_params = scroll_params,
|
||||||
height = self.active_pane_height.unwrap_or(i32::MAX),
|
height = self.active_pane_height.unwrap_or(i32::MAX),
|
||||||
|
@ -124,7 +124,7 @@ impl<'a> View<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Find long utf sequences and extract it from mat.x
|
// Find long utf sequences and extract it from mat.x
|
||||||
let line = &self.state.lines[mat.y as usize];
|
let line = &self.state.unescaped[mat.y as usize];
|
||||||
let prefix = &line[0..mat.x as usize];
|
let prefix = &line[0..mat.x as usize];
|
||||||
let extra = prefix.width_cjk() - prefix.chars().count();
|
let extra = prefix.width_cjk() - prefix.chars().count();
|
||||||
let offset = (mat.x as u16) - (extra as u16);
|
let offset = (mat.x as u16) - (extra as u16);
|
||||||
|
Loading…
Reference in New Issue
Block a user