mirror of
https://github.com/TECHNOFAB11/tmux-copyrat.git
synced 2025-12-12 16:10:07 +01:00
commit
afa36d0c8f
29 changed files with 972 additions and 1116 deletions
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [1.56.0, stable, beta, nightly]
|
||||
rust: [1.60.0, stable, beta, nightly]
|
||||
steps:
|
||||
- name: Rust install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
- name: Rust install
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.56.0
|
||||
toolchain: 1.60.0
|
||||
profile: minimal
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
|
|
|||
4
.github/workflows/main.yaml
vendored
4
.github/workflows/main.yaml
vendored
|
|
@ -3,8 +3,6 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # 00:00 Sunday
|
||||
|
||||
jobs:
|
||||
|
||||
|
|
@ -13,7 +11,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [1.56.0, stable]
|
||||
rust: [1.60.0, stable]
|
||||
steps:
|
||||
- name: Rust install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
|
|||
4
.github/workflows/pr.yaml
vendored
4
.github/workflows/pr.yaml
vendored
|
|
@ -9,7 +9,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust: [1.56.0, stable]
|
||||
rust: [1.60.0, stable]
|
||||
steps:
|
||||
- name: Rust install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
- name: Rust install
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.56.0
|
||||
toolchain: 1.60.0
|
||||
profile: minimal
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
|
|
|
|||
241
CONFIGURATION.md
Normal file
241
CONFIGURATION.md
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
# Configuration
|
||||
|
||||
If you want to customize how is shown your tmux-copyrat hints those all available
|
||||
parameters to set your perfect profile.
|
||||
|
||||
NOTE: for changes to take effect, you'll need to source again your `.tmux.conf` file.
|
||||
|
||||
- [@copyrat-key](#thumbs-key)
|
||||
- [@copyrat-alphabet](#thumbs-alphabet)
|
||||
- [@copyrat-reverse](#thumbs-reverse)
|
||||
- [@copyrat-unique](#thumbs-unique)
|
||||
- [@copyrat-position](#thumbs-position)
|
||||
- [@copyrat-regexp-N](#thumbs-regexp-N)
|
||||
- [@copyrat-command](#thumbs-command)
|
||||
- [@copyrat-upcase-command](#thumbs-upcase-command)
|
||||
- [@copyrat-bg-color](#thumbs-bg-color)
|
||||
- [@copyrat-fg-color](#thumbs-fg-color)
|
||||
- [@copyrat-hint-bg-color](#thumbs-hint-bg-color)
|
||||
- [@copyrat-hint-fg-color](#thumbs-hint-fg-color)
|
||||
- [@copyrat-select-fg-color](#thumbs-select-fg-color)
|
||||
- [@copyrat-select-bg-color](#thumbs-select-bg-color)
|
||||
- [@copyrat-contrast](#thumbs-contrast)
|
||||
|
||||
### @thumbs-key
|
||||
|
||||
`default: space`
|
||||
|
||||
Choose which key is used to enter in thumbs mode.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-key F
|
||||
```
|
||||
|
||||
### @thumbs-alphabet
|
||||
|
||||
`default: qwerty`
|
||||
|
||||
Choose which set of characters is used to build hints. Review all [available alphabets](#Alphabets)
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-alphabet dvorak-homerow
|
||||
```
|
||||
|
||||
### @thumbs-reverse
|
||||
|
||||
`default: disabled`
|
||||
|
||||
Choose in which direction you want to assign hints. Useful to get shorter hints closer to the cursor.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-reverse
|
||||
```
|
||||
|
||||
### @thumbs-unique
|
||||
|
||||
`default: disabled`
|
||||
|
||||
Choose if you want to assign the same hint for the same text spans.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-unique
|
||||
```
|
||||
|
||||
### @thumbs-position
|
||||
|
||||
`default: left`
|
||||
|
||||
Choose where do you want to show the hint in the text spans. Options (left, right).
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-position right
|
||||
```
|
||||
|
||||
### @thumbs-regexp-N
|
||||
|
||||
Add extra patterns to match. This parameter can have multiple instances.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-regexp-1 '[a-z]+@[a-z]+.com' # Match emails
|
||||
set -g @thumbs-regexp-2 '[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:' # Match MAC addresses
|
||||
```
|
||||
|
||||
### @thumbs-command
|
||||
|
||||
`default: 'tmux set-buffer {}'`
|
||||
|
||||
Choose which command execute when you press a hint. `tmux-thumbs` will replace `{}` with the picked hint.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-command 'echo -n {} | pbcopy'
|
||||
```
|
||||
|
||||
### @thumbs-upcase-command
|
||||
|
||||
`default: 'tmux set-buffer {} && tmux paste-buffer'`
|
||||
|
||||
Choose which command execute when you press a upcase hint. `tmux-thumbs` will replace `{}` with the picked hint.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-upcase-command 'echo -n {} | pbcopy'
|
||||
```
|
||||
|
||||
### @thumbs-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for spans
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-bg-color blue
|
||||
```
|
||||
|
||||
### @thumbs-fg-color
|
||||
|
||||
`default: green`
|
||||
|
||||
Sets the foreground color for spans
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-fg-color green
|
||||
```
|
||||
|
||||
### @thumbs-hint-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for hints
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-hint-bg-color blue
|
||||
```
|
||||
|
||||
### @thumbs-hint-fg-color
|
||||
|
||||
`default: yellow`
|
||||
|
||||
Sets the foreground color for hints
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-hint-fg-color green
|
||||
```
|
||||
|
||||
### @thumbs-select-fg-color
|
||||
|
||||
`default: blue`
|
||||
|
||||
Sets the foreground color for selection
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-select-fg-color red
|
||||
```
|
||||
|
||||
### @thumbs-select-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for selection
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-select-bg-color red
|
||||
```
|
||||
|
||||
### @thumbs-contrast
|
||||
|
||||
`default: 0`
|
||||
|
||||
Displays hint character in square brackets for extra visibility.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-contrast 1
|
||||
```
|
||||
|
||||
#### Colors
|
||||
|
||||
This is the list of available colors:
|
||||
|
||||
- black
|
||||
- red
|
||||
- green
|
||||
- yellow
|
||||
- blue
|
||||
- magenta
|
||||
- cyan
|
||||
- white
|
||||
- default
|
||||
|
||||
#### Alphabets
|
||||
|
||||
This is the list of available alphabets:
|
||||
|
||||
- `qwerty`: asdfqwerzxcvjklmiuopghtybn
|
||||
- `qwerty-homerow`: asdfjklgh
|
||||
- `qwerty-left-hand`: asdfqwerzcxv
|
||||
- `qwerty-right-hand`: jkluiopmyhn
|
||||
- `azerty`: qsdfazerwxcvjklmuiopghtybn
|
||||
- `azerty-homerow`: qsdfjkmgh
|
||||
- `azerty-left-hand`: qsdfazerwxcv
|
||||
- `azerty-right-hand`: jklmuiophyn
|
||||
- `qwertz`: asdfqweryxcvjkluiopmghtzbn
|
||||
- `qwertz-homerow`: asdfghjkl
|
||||
- `qwertz-left-hand`: asdfqweryxcv
|
||||
- `qwertz-right-hand`: jkluiopmhzn
|
||||
- `dvorak`: aoeuqjkxpyhtnsgcrlmwvzfidb
|
||||
- `dvorak-homerow`: aoeuhtnsid
|
||||
- `dvorak-left-hand`: aoeupqjkyix
|
||||
- `dvorak-right-hand`: htnsgcrlmwvz
|
||||
- `colemak`: arstqwfpzxcvneioluymdhgjbk
|
||||
- `colemak-homerow`: arstneiodh
|
||||
- `colemak-left-hand`: arstqwfpzxcv
|
||||
- `colemak-right-hand`: neioluymjhk
|
||||
|
||||
381
Cargo.lock
generated
381
Cargo.lock
generated
|
|
@ -1,381 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "copyrat"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"duct",
|
||||
"regex",
|
||||
"sequence_trie",
|
||||
"termion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "duct"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc6a0a59ed0888e0041cf708e66357b7ae1a82f1c67247e1f93b5e0818f7d8d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"os_pipe",
|
||||
"shared_child",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb233f06c2307e1f5ce2ecad9f8121cffbbee2c95428f44ea85222e460d0d213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||
dependencies = [
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "sequence_trie"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee22067b7ccd072eeb64454b9c6e1b33b61cd0d49e895fd48676a184580e0c3"
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6be9f7d5565b1483af3e72975e2dee33879b3b86bd48c0929fccf6585d79e65a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"numtoa",
|
||||
"redox_syscall",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
|
||||
dependencies = [
|
||||
"terminal_size",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
48
Cargo.toml
48
Cargo.toml
|
|
@ -1,17 +1,26 @@
|
|||
[package]
|
||||
name = "copyrat"
|
||||
version = "0.4.1"
|
||||
authors = ["graelo <graelo@graelo.cc>"]
|
||||
edition = "2018"
|
||||
description = "This is tmux-copycat on Rust steroids."
|
||||
repository = "https://github.com/graelo/tmux-copyrat"
|
||||
keywords = ["rust", "tmux", "tmux-plugin", "tmux-copycat"]
|
||||
edition = "2021"
|
||||
description = "A tmux plugin for copy-pasting within tmux panes."
|
||||
readme = "README.md"
|
||||
|
||||
license = "MIT"
|
||||
authors = ["graelo <graelo@graelo.cc>"]
|
||||
repository = "https://github.com/graelo/tmux-copyrat"
|
||||
homepage = "https://github.com/graelo/tmux-copyrat"
|
||||
documentation = "https://docs.rs/tmux-copyrat"
|
||||
|
||||
keywords = ["rust", "tmux", "tmux-plugin", "tmux-copycat"]
|
||||
categories = ["command-line-utilities"]
|
||||
exclude = ["/.github"]
|
||||
|
||||
[dependencies]
|
||||
termion = "1.5"
|
||||
regex = "1.4"
|
||||
clap = { version = "3.0.0-beta.2", features = ["suggestions", "color", "wrap_help"]}
|
||||
thiserror = "1"
|
||||
|
||||
termion = "2"
|
||||
regex = "1.6"
|
||||
clap = { version = "4.0", features = ["derive", "wrap_help"]}
|
||||
sequence_trie = "0.3.6"
|
||||
duct = "0.13"
|
||||
|
||||
|
|
@ -22,3 +31,26 @@ path = "src/bin/copyrat.rs"
|
|||
[[bin]]
|
||||
name = "tmux-copyrat"
|
||||
path = "src/bin/tmux_copyrat.rs"
|
||||
|
||||
[profile.release]
|
||||
# Enable link-time optimization (LTO). It’s a kind of whole-program or
|
||||
# inter-module optimization as it runs as the very last step when linking the
|
||||
# different parts of your binary together. You can think of it as allowing
|
||||
# better inlining across dependency boundaries (but it’s of course more
|
||||
# complicated that that).
|
||||
#
|
||||
# Rust can use multiple linker flavors, and the one we want is “optimize across
|
||||
# all crates”, which is called “fat”. To set this, add the lto flag to your
|
||||
# profile:
|
||||
lto = "fat"
|
||||
|
||||
# To speed up compile times, Rust tries to split your crates into small chunks
|
||||
# and compile as many in parallel as possible. The downside is that there’s
|
||||
# less opportunities for the compiler to optimize code across these chunks. So,
|
||||
# let’s tell it to do one chunk per crate:
|
||||
codegen-units = 1
|
||||
|
||||
# Rust by default uses stack unwinding (on the most common platforms). That
|
||||
# costs performance, so let’s skip stack traces and the ability to catch panics
|
||||
# for reduced code size and better cache usage:
|
||||
panic = "abort"
|
||||
|
|
|
|||
100
INSTALLATION.md
Normal file
100
INSTALLATION.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Installation
|
||||
|
||||
## A note on extending tmux functionality
|
||||
|
||||
Extending [tmux] functionality is easy: it boils down to adding key-bindings
|
||||
which call internal commands or external programs that you provide.
|
||||
|
||||
The minimalistic way to add functionality is simply to add your key-bindings
|
||||
directly inside `~/.tmux.conf`. I don't do this because it ends up being messy,
|
||||
but it's still an option described below.
|
||||
|
||||
In contrast, the most flexible way to extend is via plugins. You declare your
|
||||
bindings in a plugin file often located in
|
||||
`~/.tmux/plugins/your-plugin-dir/plugin-file.tmux`, and optionally provide your
|
||||
external programs in the same folder or elsewhere. You then simply ask tmux to
|
||||
_run_ your plugin file by adding `run-shell
|
||||
~/.tmux/plugins/your-plugin-dir/plugin-file.tmux` inside your `tmux.conf`. Your
|
||||
key-bindings will be registered on tmux initial start.
|
||||
|
||||
[TPM], the tmux plugin manager, is an integrated way of doing the same. It adds
|
||||
a level of indirection: when tmux first starts, it runs TPM, which asks tmux to
|
||||
_run_ all the plugin files in `~/.tmux/plugins/**/` as executables.
|
||||
When run, each plugin file registers their key-bindings with tmux. TPM also has
|
||||
an installation mechanism for plugins.
|
||||
|
||||
|
||||
## Minimalistic installation
|
||||
|
||||
As described above, a valid option is to ignore the [`copyrat.tmux`] plugin
|
||||
file simply add a few key bindings to tmux. You just have to create
|
||||
key-bindings which launch the `tmux-copyrat` binary with its command line
|
||||
options. Notice you probably need the absolute path to the binary.
|
||||
|
||||
However, when creating your bindings, avoid using `run-shell` to run `tmux-copyrat`
|
||||
because by design tmux launches processes without attaching them to a pty.
|
||||
Take inspiration from [`copyrat.tmux`] for correct syntax.
|
||||
|
||||
|
||||
## Standard installation (recommended)
|
||||
|
||||
The easiest way to install is to copy the config file [`copyrat.tmux`] into `~/.tmux/plugins/tmux-copyrat/` and tell tmux to source it either via
|
||||
|
||||
- sourcing it directly from your `~/.tmux.conf`: you simply add the line `source-file ~/.tmux/plugins/tmux-copyrat/copyrat.tmux`
|
||||
- or, if you use [TPM], registering it with TPM in your `~/.tmux.conf`: you simply add the line
|
||||
|
||||
|
||||
```tmux
|
||||
set -g @tpm_plugins ' \
|
||||
tmux-plugins/tpm \
|
||||
tmux-plugins/tmux-copyrat \ <- line added
|
||||
tmux-plugins/tmux-yank \
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
second style of tmux integration is more declarative: you configure the tmux key bindings to pass none or very few command line arguments to `tmux-copyrat`, and ask `tmux-copyrat` to query back tmux for the rest of the configuration.
|
||||
|
||||
|
||||
|
||||
## Tmux integration
|
||||
|
||||
Clone the repo:
|
||||
|
||||
```
|
||||
git clone https://github.com/graelo/tmux-copyrat ~/.tmux/plugins/tmux-copyrat
|
||||
```
|
||||
|
||||
Compile it with [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html):
|
||||
|
||||
```
|
||||
cd ~/.tmux/plugins/tmux-copyrat
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
Source it in your `.tmux.conf`:
|
||||
|
||||
```
|
||||
run-shell ~/.tmux/plugins/tmux-copyrat/copyrat.tmux
|
||||
```
|
||||
|
||||
Reload TMUX conf by running:
|
||||
|
||||
```
|
||||
tmux source-file ~/.tmux.conf
|
||||
```
|
||||
|
||||
## Using Tmux Plugin Manager
|
||||
|
||||
You can add this line to your list of [TPM](https://github.com/tmux-plugins/tpm) plugins in `.tmux.conf`:
|
||||
|
||||
```
|
||||
set -g @plugin 'graelo/tmux-copyrat'
|
||||
```
|
||||
|
||||
To be able to install the plugin just hit <kbd>prefix</kbd> + <kbd>I</kbd>. You should now be able to use
|
||||
the plugin!
|
||||
|
||||
[`copyrat.tmux`]: https://raw.githubusercontent.com/graelo/tmux-copyrat/main/copyrat.tmux
|
||||
[tmux]: https://tmux.github.io
|
||||
[TPM]: https://github.com/tmux-plugins/tpm
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ferran Basora
|
||||
Copyright (c) 2022 graelo@grael.cc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
2
Makefile
Normal file
2
Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
release:
|
||||
RUSTFLAGS="-Ctarget-cpu=native" cargo build --release
|
||||
498
README.md
498
README.md
|
|
@ -2,345 +2,144 @@
|
|||
|
||||
[](https://crates.io/crates/tmux-copyrat)
|
||||
[](https://docs.rs/tmux-copyrat)
|
||||
[](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[](https://doc.rust-lang.org/edition-guide/rust-2021/index.html)
|
||||
[](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[](https://doc.rust-lang.org/edition-guide/rust-2021/index.html)
|
||||
[](https://tmux.github.io)
|
||||
[](https://github.com/graelo/tmux-copyrat/actions)
|
||||
|
||||
A tmux-plugin for copy-pasting spans of text from the [tmux] pane's history
|
||||
into a clipboard.
|
||||
|
||||
A hommage to [tmux-copyrat](https://github.com/tmux-plugins/tmux-copycat), written in [Rust](https://www.rust-lang.org/) for copy pasting within [tmux](http://tmux.github.io).
|
||||
**Use case**: you're in tmux and press the key binding to highlight, say dates.
|
||||
This makes `tmux-copyrat` search within tmux's current pane history and
|
||||
highlight all spans of text which correspond to a date. All spans are displayed
|
||||
with a one or two key _hint_, which you can then press to copy-paste the span
|
||||
into the tmux clipboard or the system clipboard. Check out the demo below.
|
||||
|
||||
## Usage
|
||||
The name is a tribute to [tmux-copyrat], which I used for many years for that
|
||||
same functionality. For this Rust implementation, I got inspired by
|
||||
[tmux-thumbs], and I even borrowed some parts of his regex tests.
|
||||
|
||||
Press ( <kbd>prefix</kbd> + <kbd>Space</kbd> ) to highlist in you current tmux
|
||||
visible pane all text that match specific pattern. Then press the highlighted
|
||||
letter hint to yank the text in your tmux buffer.
|
||||
|
||||
### Matched patterns
|
||||
|
||||
- File paths
|
||||
- File in diff
|
||||
- Git SHAs
|
||||
- IPFS CID's
|
||||
- Colors in hex
|
||||
- Numbers ( 4+ digits )
|
||||
- Hex numbers
|
||||
- Markdown urls
|
||||
- IP4 addresses
|
||||
- Docker images
|
||||
- kubernetes resources
|
||||
- UUIDs
|
||||
|
||||
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.
|
||||
|
||||
## Demo
|
||||
|
||||
[](https://asciinema.org/a/232775?autoplay=1)
|
||||
|
||||
## Tmux integration
|
||||
|
||||
Clone the repo:
|
||||
## Usage
|
||||
|
||||
First install and optionally customize the plugin (see both [INSTALLATION.md]
|
||||
and [CONFIGURATION.md] pages) and restart tmux.
|
||||
|
||||
Press one of the pre-defined tmux key-bindings (see table below) in order to
|
||||
highlight spans of text matching a specific pattern. To yank some text span in
|
||||
the tmux buffer, press the corresponding _hint_, or press <kbd>Esc</kbd> to
|
||||
cancel and exit.
|
||||
|
||||
If instead you want to yank the text span into the system clipboard, either
|
||||
press the caps version of the key hint (for instance <kbd>E</kbd> instead of
|
||||
<kbd>e</kbd>), or first toggle the destination buffer with the <kbd>space</kbd>
|
||||
key and press the hint with no caps.
|
||||
|
||||
You can also use the <kbd>n</kbd> and <kbd>N</kbd> (or <kbd>Up</kbd> and
|
||||
<kbd>Down</kbd>) keys to move focus across the highlighted spans. Press
|
||||
<kbd>y</kbd> to yank the focused span into the tmux buffer, or press
|
||||
<kbd>Y</kbd> to yank it into the system clipboard.
|
||||
|
||||
By default, span highlighting starts from the bottom of the terminal, but you
|
||||
can reverse that behavior with the `--reverse` option. The
|
||||
`--focus-wrap-around` option makes navigation go back to the first span. Many
|
||||
more options are described in [CONFIGURATION.md].
|
||||
|
||||
|
||||
### Matched patterns and default key-bindings
|
||||
|
||||
tmux-copyrat can match one or more pre-defined (named) patterns, but you can
|
||||
add your own too (see [CONFIGURATION.md]).
|
||||
|
||||
The default configuration provided in the [`copyrat.tmux`](copyrat.tmux) plugin
|
||||
file provides the following key-bindings. Because they all start with
|
||||
<kbd>prefix</kbd> + <kbd>t</kbd>, the table below only lists the keyboard key
|
||||
that comes after. For instance, for URLs, the key is <kbd>u</kbd>, but you
|
||||
should type <kbd>prefix</kbd> + <kbd>t</kbd> + <kbd>u</kbd>.
|
||||
|
||||
| key binding | searches for | pattern name |
|
||||
| --- | --- | --- |
|
||||
| <kbd>c</kbd> | Hex color codes | `hexcolor` |
|
||||
| <kbd>d</kbd> | Dates or datetimes | `datetime` |
|
||||
| <kbd>D</kbd> | Docker/Podman IDs | `docker` |
|
||||
| <kbd>e</kbd> | Emails | `email` |
|
||||
| <kbd>G</kbd> | String of 4+ digits | `digits` |
|
||||
| <kbd>h</kbd> | SHA-1/-2 short & long | `sha` |
|
||||
| <kbd>m</kbd> | Markdown URLs `[..](matched-url)` | `markdown-url` |
|
||||
| <kbd>p</kbd> | Abs. and rel. filepaths | `path` |
|
||||
| <kbd>P</kbd> | Hex numbers and pointer addresses | `pointer-address` |
|
||||
| | strings inside single quotes | `quoted-single` |
|
||||
| | strings inside double quotes | `quoted-double` |
|
||||
| | strings inside backticks | `quoted-backtick` |
|
||||
| <kbd>q</kbd> | strings inside single/double/backticks | |
|
||||
| <kbd>u</kbd> | URLs | `url` |
|
||||
| <kbd>U</kbd> | UUIDs | `uuid` |
|
||||
| <kbd>v</kbd> | version numbers | `version` |
|
||||
| <kbd>4</kbd> | IPv4 addresses | `4` |
|
||||
| <kbd>6</kbd> | IPv6 addresses | `6` |
|
||||
| <kbd>space</kbd> | All patterns | |
|
||||
|
||||
```
|
||||
git clone https://github.com/graelo/tmux-copyrat ~/.tmux/plugins/tmux-copyrat
|
||||
```
|
||||
|
||||
Compile it with [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html):
|
||||
|
||||
```
|
||||
cd ~/.tmux/plugins/tmux-copyrat
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
Source it in your `.tmux.conf`:
|
||||
|
||||
```
|
||||
run-shell ~/.tmux/plugins/tmux-copyrat/copyrat.tmux
|
||||
```
|
||||
|
||||
Reload TMUX conf by running:
|
||||
|
||||
```
|
||||
tmux source-file ~/.tmux.conf
|
||||
```
|
||||
|
||||
## Using Tmux Plugin Manager
|
||||
|
||||
You can add this line to your list of [TPM](https://github.com/tmux-plugins/tpm) plugins in `.tmux.conf`:
|
||||
|
||||
```
|
||||
set -g @plugin 'graelo/tmux-copyrat'
|
||||
```
|
||||
|
||||
To be able to install the plugin just hit <kbd>prefix</kbd> + <kbd>I</kbd>. You should now be able to use
|
||||
the plugin!
|
||||
|
||||
## Configuration
|
||||
|
||||
If you want to customize how is shown your tmux-copyrat hints those all available
|
||||
parameters to set your perfect profile.
|
||||
|
||||
NOTE: for changes to take effect, you'll need to source again your `.tmux.conf` file.
|
||||
|
||||
- [@copyrat-key](#thumbs-key)
|
||||
- [@copyrat-alphabet](#thumbs-alphabet)
|
||||
- [@copyrat-reverse](#thumbs-reverse)
|
||||
- [@copyrat-unique](#thumbs-unique)
|
||||
- [@copyrat-position](#thumbs-position)
|
||||
- [@copyrat-regexp-N](#thumbs-regexp-N)
|
||||
- [@copyrat-command](#thumbs-command)
|
||||
- [@copyrat-upcase-command](#thumbs-upcase-command)
|
||||
- [@copyrat-bg-color](#thumbs-bg-color)
|
||||
- [@copyrat-fg-color](#thumbs-fg-color)
|
||||
- [@copyrat-hint-bg-color](#thumbs-hint-bg-color)
|
||||
- [@copyrat-hint-fg-color](#thumbs-hint-fg-color)
|
||||
- [@copyrat-select-fg-color](#thumbs-select-fg-color)
|
||||
- [@copyrat-select-bg-color](#thumbs-select-bg-color)
|
||||
- [@copyrat-contrast](#thumbs-contrast)
|
||||
|
||||
### @thumbs-key
|
||||
|
||||
`default: space`
|
||||
|
||||
Choose which key is used to enter in thumbs mode.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-key F
|
||||
```
|
||||
|
||||
### @thumbs-alphabet
|
||||
|
||||
`default: qwerty`
|
||||
|
||||
Choose which set of characters is used to build hints. Review all [available alphabets](#Alphabets)
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-alphabet dvorak-homerow
|
||||
```
|
||||
|
||||
### @thumbs-reverse
|
||||
|
||||
`default: disabled`
|
||||
|
||||
Choose in which direction you want to assign hints. Useful to get shorter hints closer to the cursor.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-reverse
|
||||
```
|
||||
|
||||
### @thumbs-unique
|
||||
|
||||
`default: disabled`
|
||||
|
||||
Choose if you want to assign the same hint for the same text spans.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-unique
|
||||
```
|
||||
|
||||
### @thumbs-position
|
||||
|
||||
`default: left`
|
||||
|
||||
Choose where do you want to show the hint in the text spans. Options (left, right).
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-position right
|
||||
```
|
||||
|
||||
### @thumbs-regexp-N
|
||||
|
||||
Add extra patterns to match. This parameter can have multiple instances.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-regexp-1 '[a-z]+@[a-z]+.com' # Match emails
|
||||
set -g @thumbs-regexp-2 '[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:' # Match MAC addresses
|
||||
```
|
||||
|
||||
### @thumbs-command
|
||||
|
||||
`default: 'tmux set-buffer {}'`
|
||||
|
||||
Choose which command execute when you press a hint. `tmux-thumbs` will replace `{}` with the picked hint.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-command 'echo -n {} | pbcopy'
|
||||
```
|
||||
|
||||
### @thumbs-upcase-command
|
||||
|
||||
`default: 'tmux set-buffer {} && tmux paste-buffer'`
|
||||
|
||||
Choose which command execute when you press a upcase hint. `tmux-thumbs` will replace `{}` with the picked hint.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-upcase-command 'echo -n {} | pbcopy'
|
||||
```
|
||||
|
||||
### @thumbs-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for spans
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-bg-color blue
|
||||
```
|
||||
|
||||
### @thumbs-fg-color
|
||||
|
||||
`default: green`
|
||||
|
||||
Sets the foreground color for spans
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-fg-color green
|
||||
```
|
||||
|
||||
### @thumbs-hint-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for hints
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-hint-bg-color blue
|
||||
```
|
||||
|
||||
### @thumbs-hint-fg-color
|
||||
|
||||
`default: yellow`
|
||||
|
||||
Sets the foreground color for hints
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-hint-fg-color green
|
||||
```
|
||||
|
||||
### @thumbs-select-fg-color
|
||||
|
||||
`default: blue`
|
||||
|
||||
Sets the foreground color for selection
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-select-fg-color red
|
||||
```
|
||||
|
||||
### @thumbs-select-bg-color
|
||||
|
||||
`default: black`
|
||||
|
||||
Sets the background color for selection
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-select-bg-color red
|
||||
```
|
||||
|
||||
### @thumbs-contrast
|
||||
|
||||
`default: 0`
|
||||
|
||||
Displays hint character in square brackets for extra visibility.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
set -g @thumbs-contrast 1
|
||||
```
|
||||
|
||||
#### Colors
|
||||
|
||||
This is the list of available colors:
|
||||
|
||||
- black
|
||||
- red
|
||||
- green
|
||||
- yellow
|
||||
- blue
|
||||
- magenta
|
||||
- cyan
|
||||
- white
|
||||
- default
|
||||
|
||||
#### Alphabets
|
||||
|
||||
This is the list of available alphabets:
|
||||
|
||||
- `qwerty`: asdfqwerzxcvjklmiuopghtybn
|
||||
- `qwerty-homerow`: asdfjklgh
|
||||
- `qwerty-left-hand`: asdfqwerzcxv
|
||||
- `qwerty-right-hand`: jkluiopmyhn
|
||||
- `azerty`: qsdfazerwxcvjklmuiopghtybn
|
||||
- `azerty-homerow`: qsdfjkmgh
|
||||
- `azerty-left-hand`: qsdfazerwxcv
|
||||
- `azerty-right-hand`: jklmuiophyn
|
||||
- `qwertz`: asdfqweryxcvjkluiopmghtzbn
|
||||
- `qwertz-homerow`: asdfghjkl
|
||||
- `qwertz-left-hand`: asdfqweryxcv
|
||||
- `qwertz-right-hand`: jkluiopmhzn
|
||||
- `dvorak`: aoeuqjkxpyhtnsgcrlmwvzfidb
|
||||
- `dvorak-homerow`: aoeuhtnsid
|
||||
- `dvorak-left-hand`: aoeupqjkyix
|
||||
- `dvorak-right-hand`: htnsgcrlmwvz
|
||||
- `colemak`: arstqwfpzxcvneioluymdhgjbk
|
||||
- `colemak-homerow`: arstneiodh
|
||||
- `colemak-left-hand`: arstqwfpzxcv
|
||||
- `colemak-right-hand`: neioluymjhk
|
||||
|
||||
## Extra features
|
||||
|
||||
- **Arrow navigation:** You can use the arrows to move around between all spans.
|
||||
- **Auto paste:** If your last typed hint character is uppercase, you are going to pick and paste the desired hint.
|
||||
- **Multi selection:** If you run thumb with multi selection mode you will be able to choose multiple hints pressing the desired letter and `Space` to finalize the selection.
|
||||
|
||||
## Tmux compatibility
|
||||
|
||||
This is the known list of versions of `tmux` compatible with `tmux-thumbs`:
|
||||
`tmux-copyrat` is known to be compatible with tmux 3.0 onwards.
|
||||
|
||||
| Version | Compatible |
|
||||
|:-------:|:----------:|
|
||||
| 3.0b | ✅ |
|
||||
| 2.9a | ✅ |
|
||||
| 2.8 | ❓ |
|
||||
| 2.7 | ❓ |
|
||||
| 2.6 | ✅ |
|
||||
| 2.5 | ❓ |
|
||||
| 2.4 | ❓ |
|
||||
| 2.3 | ❓ |
|
||||
| 1.8 | ❓ |
|
||||
| 1.7 | ❓ |
|
||||
Testing this kind of integration with tmux is time consuming, so I'll be
|
||||
grateful if you report incompatibilities as you find them.
|
||||
|
||||
|
||||
## The `copyrat` standalone executable
|
||||
|
||||
Although the central binary of this crate is `tmux-copyrat`, the crate also
|
||||
ships with the `copyrat` executable which provides the same functionality,
|
||||
minus any tmux dependency or integration and instead reads from stdin.
|
||||
|
||||
You can use `copyrat` to search a span of text that you provide to stdin, à la
|
||||
[FZF] but more focused and less interactive.
|
||||
|
||||
For instance here is a bunch of text, with dates and git hashes which you can
|
||||
search with copyrat.
|
||||
|
||||
```text
|
||||
* e006b06 - (12 days ago = 2021-03-04T12:23:34) e006b06 e006b06 swapper: Make quotes
|
||||
/usr/local/bin/git
|
||||
|
||||
lorem
|
||||
/usr/local/bin
|
||||
lorem
|
||||
The error was `Error no such file`
|
||||
```
|
||||
|
||||
Let's imagine you want a quick way to always search for SHA-1/2, datetimes, strings within backticks, you would define once the following alias
|
||||
|
||||
```zsh
|
||||
$ alias pick='copyrat -r --unique-hint -s bold -x sha -x datetime -x quoted-backtick | pbcopy'
|
||||
```
|
||||
|
||||
and simply
|
||||
|
||||
```console
|
||||
$ git log | pick
|
||||
```
|
||||
|
||||
You will see the following in your terminal
|
||||
|
||||
](images/copyrat-output.png)
|
||||
|
||||
You may have noticed that all identical spans share the same _hint_, this is
|
||||
due to the `-unique-hint` option (`-u`). The hints are in bold text, due to the
|
||||
`--hint-style bold` option (`-s`). Hints start from the bottom, due to the
|
||||
`--reverse` option (`-r`). A custom pattern was provided for matching any
|
||||
"loca", due to the `--custom-regex-pattern` option (`-X`). The sha, datetime
|
||||
and content inside backticks were highlighted due to the `--named-pattern`
|
||||
option (`-x`).
|
||||
|
||||
If you can check hat `tmux-thumbs` is or is not compatible with some specific version of `tmux`, let me know.
|
||||
|
||||
## Standalone `thumbs`
|
||||
|
||||
|
|
@ -393,38 +192,51 @@ If you want to enjoy terminal hints, you can do things like this without `tmux`:
|
|||
> git log | pick
|
||||
```
|
||||
|
||||
Or multi selection:
|
||||
|
||||
```
|
||||
> git log | thumbs -m
|
||||
1df9fa69c8831ac042c6466af81e65402ee2a007
|
||||
4897dc4ecbd2ac90b17de95e00e9e75bb540e37f
|
||||
## Run code-coverage
|
||||
|
||||
Install the llvm-tools-preview component and grcov
|
||||
|
||||
```sh
|
||||
rustup component add llvm-tools-preview
|
||||
cargo install grcov
|
||||
```
|
||||
|
||||
Standalone `thumbs` has some similarities to [FZF](https://github.com/junegunn/fzf).
|
||||
Install nightly
|
||||
|
||||
## Background
|
||||
```sh
|
||||
rustup toolchain install nightly
|
||||
```
|
||||
|
||||
As I said, this project is based in [tmux-fingers](https://github.com/Morantron/tmux-fingers). Morantron did an extraordinary job, building all necessary pieces in Bash to achieve the text picker behaviour. He only deserves my gratitude for all the time I have been using [tmux-fingers](https://github.com/Morantron/tmux-fingers).
|
||||
The following make invocation will switch to nigthly run the tests using
|
||||
Cargo, and output coverage HTML report in `./coverage/`
|
||||
|
||||
During a [Fosdem](https://fosdem.org/) conf, we had the idea to rewrite it to another language. He had these thoughts many times ago but it was hard to start from scratch. So, we decided to start playing with Node.js and [react-blessed](https://github.com/Yomguithereal/react-blessed), but we detected some unacceptable latency when the program booted. We didn't investigate much about this latency.
|
||||
```sh
|
||||
make coverage
|
||||
```
|
||||
|
||||
During those days another alternative appeared, called [tmux-picker](https://github.com/RTBHOUSE/tmux-picker), implemented in python and reusing many parts from [tmux-fingers](https://github.com/Morantron/tmux-fingers). It was nice, because it was fast and added original terminal color support.
|
||||
The coverage report is located in `./coverage/index.html`
|
||||
|
||||
I was curious to know if this was possible to be written in [Rust](https://www.rust-lang.org/), and soon I realized that was something doable. The ability to implement tests for all critic parts of the application give you a great confidence about it. On the other hand, Rust has an awesome community that lets you achieve this kind of project in a short period of time.
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [X] Support multi selection
|
||||
- [X] Decouple `tmux-thumbs` from `tmux`
|
||||
- [ ] Code [Kitty](https://github.com/kovidgoyal/kitty) plugin, now that `thumbs` can run standalone
|
||||
## License
|
||||
|
||||
## Contribute
|
||||
This project is licensed under the [MIT license]
|
||||
|
||||
This project started as a side project to learn Rust, so I'm sure that is full
|
||||
of mistakes and areas to be improve. If you think you can tweak the code to
|
||||
make it better, I'll really appreaciate a pull request. ;)
|
||||
at your option.
|
||||
|
||||
# License
|
||||
|
||||
[MIT](https://github.com/fcsonline/tmux-thumbs/blob/master/LICENSE)
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the MIT license, shall
|
||||
be licensed as MIT, without any additional terms or conditions.
|
||||
|
||||
[tmux]: https://tmux.github.io
|
||||
[tmux-copyrat]: https://github.com/tmux-plugins/tmux-copycat
|
||||
[CONFIGURATION.md]: CONFIGURATION.md
|
||||
[INSTALLATION.md]: INSTALLATION.md
|
||||
[tmux-thumbs]: https://crates.io/crates/tmux-thumbs
|
||||
[FZF]: https://github.com/junegunn/fzf
|
||||
[xsel]: https://ostechnix.com/access-clipboard-contents-using-xclip-and-xsel-in-linux/
|
||||
[MIT license]: http://opensource.org/licenses/MIT
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
set -ex
|
||||
|
||||
ci=$(dirname $0)
|
||||
for version in 1.56.0 stable beta nightly; do
|
||||
for version in 1.60.0 stable beta nightly; do
|
||||
rustup run "$version" "$ci/test_full.sh"
|
||||
done
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
|
||||
CRATE=tmux-copyrat
|
||||
MSRV=1.56
|
||||
MSRV=1.60
|
||||
|
||||
get_rust_version() {
|
||||
local array=($(rustc --version));
|
||||
|
|
|
|||
41
copyrat.tmux
41
copyrat.tmux
|
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/env zsh
|
||||
|
||||
# This scripts provides a default configuration for tmux-copyrat options and key bindings.
|
||||
# It is run only once at tmux launch.
|
||||
# This scripts provides a default configuration for tmux-copyrat options and
|
||||
# key bindings. It is run only once at tmux launch.
|
||||
#
|
||||
# Each option and binding can be overridden in your `tmux.conf` by defining options like
|
||||
# Each option and binding can be overridden in your `tmux.conf` by defining
|
||||
# options like
|
||||
#
|
||||
# set -g @copyrat-keytable "foobar"
|
||||
# set -g @copyrat-keyswitch "z"
|
||||
|
|
@ -14,9 +15,10 @@
|
|||
# bind-key -T foobar h new-window -d -n "[copyrat]" '/path/to/tmux-copyrat --window-name "[copyrat]" --pattern-name urls'
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# changing this script may break integration with `tmux-copyrat`.
|
||||
# Please avoid modifying this script as it may break the integration with
|
||||
# `tmux-copyrat`.
|
||||
#
|
||||
#
|
||||
|
||||
# Just make sure you first open a named window in the background and provide
|
||||
# that name to the binary `tmux-copyrat`.
|
||||
#
|
||||
|
|
@ -27,7 +29,7 @@
|
|||
# options and bindings in your `tmux.conf`.
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "$0" )" && pwd )"
|
||||
BINARY="${CURRENT_DIR}/tmux-copyrat"
|
||||
BINARY=${CURRENT_DIR}/tmux-copyrat
|
||||
|
||||
|
||||
#
|
||||
|
|
@ -35,11 +37,11 @@ BINARY="${CURRENT_DIR}/tmux-copyrat"
|
|||
#
|
||||
|
||||
setup_option() {
|
||||
local opt_name=$1
|
||||
local default_value=$2
|
||||
local current_value=$(tmux show-option -gqv @copyrat-${opt_name})
|
||||
value=${current_value:-${default_value}}
|
||||
tmux set-option -g @copyrat-${opt_name} ${value}
|
||||
local opt_name=$1
|
||||
local default_value=$2
|
||||
local current_value=$(tmux show-option -gqv @copyrat-${opt_name})
|
||||
value=${current_value:-${default_value}}
|
||||
tmux set-option -g @copyrat-${opt_name} ${value}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -50,8 +52,9 @@ setup_option "window-name" "[copyrat]"
|
|||
# Get that window name as a local variable for use in pattern bindings below.
|
||||
window_name=$(tmux show-option -gqv @copyrat-window-name)
|
||||
|
||||
# Sets the keytable for all bindings, providing a default if @copyrat-keytable was not defined.
|
||||
# Keytables open a new shortcut space: if 't' is the switcher (see below), prefix + t + <your-shortcut>
|
||||
# Sets the keytable for all bindings, providing a default if @copyrat-keytable
|
||||
# was not defined. Keytables open a new shortcut space: if 't' is the switcher
|
||||
# (see below), prefix + t + <your-shortcut>
|
||||
setup_option "keytable" "cpyrt"
|
||||
|
||||
# Sets the key to access the keytable: prefix + <key> + <your-shortcut>
|
||||
|
|
@ -68,11 +71,11 @@ tmux bind-key ${keyswitch} switch-client -T ${keytable}
|
|||
#
|
||||
|
||||
setup_pattern_binding() {
|
||||
local key=$1
|
||||
local pattern_arg="$2"
|
||||
# The default window name `[copyrat]` has to be single quoted because it is
|
||||
# interpreted by the shell when launched by tmux.
|
||||
tmux bind-key -T ${keytable} ${key} new-window -d -n ${window_name} "${BINARY} --window-name '"${window_name}"' --reverse --unique-hint ${pattern_arg}"
|
||||
local key=$1
|
||||
local pattern_arg="$2"
|
||||
# The default window name `[copyrat]` has to be single quoted because it is
|
||||
# interpreted by the shell when launched by tmux.
|
||||
tmux bind-key -T ${keytable} ${key} new-window -d -n ${window_name} "${BINARY} --window-name '"${window_name}"' --reverse --unique-hint ${pattern_arg}"
|
||||
}
|
||||
|
||||
# prefix + t + c searches for hex colors #aa00f5
|
||||
|
|
@ -94,7 +97,7 @@ setup_pattern_binding "p" "--pattern-name path"
|
|||
# prefix + t + P searches for hex numbers: 0xbedead
|
||||
setup_pattern_binding "P" "--pattern-name pointer-address"
|
||||
# prefix + t + q searches for strings inside single|double|backticks
|
||||
setup_pattern_binding "q" "-x quoted-single -x quoted-double -x quoted-tick"
|
||||
setup_pattern_binding "q" "-x quoted-single -x quoted-double -x quoted-backtick"
|
||||
# prefix + t + u searches for URLs
|
||||
setup_pattern_binding "u" "--pattern-name url"
|
||||
# prefix + t + U searches for UUIDs
|
||||
|
|
|
|||
BIN
images/copyrat-output.png
Normal file
BIN
images/copyrat-output.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
|
|
@ -1,4 +1,4 @@
|
|||
use clap::Clap;
|
||||
use clap::Parser;
|
||||
use std::io::{self, Read};
|
||||
|
||||
use copyrat::{config::basic, run, ui::Selection};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use copyrat::{
|
||||
config::extended::{ConfigExt, OutputDestination},
|
||||
error, tmux,
|
||||
tmux,
|
||||
ui::Selection,
|
||||
Result,
|
||||
};
|
||||
|
||||
///
|
||||
fn main() -> Result<(), error::ParseError> {
|
||||
fn main() -> Result<()> {
|
||||
let config = ConfigExt::initialize()?;
|
||||
|
||||
// Identify active pane and capture its content.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use clap::Clap;
|
||||
use std::str::FromStr;
|
||||
use std::fmt::Display;
|
||||
|
||||
use clap::{ArgAction, Parser, ValueEnum};
|
||||
|
||||
use crate::{
|
||||
error,
|
||||
textbuf::{alphabet, regexes},
|
||||
ui,
|
||||
ui, Error, Result,
|
||||
};
|
||||
|
||||
/// Main configuration, parsed from command line.
|
||||
#[derive(Clap, Debug)]
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, about, version)]
|
||||
pub struct Config {
|
||||
/// Alphabet to draw hints from.
|
||||
|
|
@ -20,57 +20,70 @@ pub struct Config {
|
|||
/// # Examples
|
||||
///
|
||||
/// "qwerty", "dvorak-homerow", "azerty-right-hand".
|
||||
#[clap(short = 'k', long, default_value = "dvorak",
|
||||
parse(try_from_str = alphabet::parse_alphabet))]
|
||||
#[arg(
|
||||
short = 'k',
|
||||
long,
|
||||
default_value = "dvorak",
|
||||
value_parser(alphabet::parse_alphabet)
|
||||
)]
|
||||
pub alphabet: alphabet::Alphabet,
|
||||
|
||||
/// Use all available regex patterns.
|
||||
#[clap(short = 'A', long = "--all-patterns")]
|
||||
#[arg(short = 'A', long = "all-patterns")]
|
||||
pub use_all_patterns: bool,
|
||||
|
||||
/// Pattern names to use ("email", ... see doc).
|
||||
#[clap(short = 'x', long = "--pattern-name", parse(try_from_str = regexes::parse_pattern_name))]
|
||||
#[arg(
|
||||
short = 'x',
|
||||
long = "pattern-name",
|
||||
value_parser(regexes::parse_pattern_name)
|
||||
)]
|
||||
pub named_patterns: Vec<regexes::NamedPattern>,
|
||||
|
||||
/// Additional regex patterns ("foo*bar", etc).
|
||||
#[clap(short = 'X', long = "--custom-pattern")]
|
||||
/// Additional regex patterns ("(foo.*)bar", etc). Must have a capture
|
||||
/// group.
|
||||
#[arg(short = 'X', long)]
|
||||
pub custom_patterns: Vec<String>,
|
||||
|
||||
/// Assign hints starting from the bottom of the screen.
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long, action = ArgAction::SetTrue)]
|
||||
pub reverse: bool,
|
||||
|
||||
/// Keep the same hint for identical spans.
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long, action = ArgAction::SetTrue)]
|
||||
pub unique_hint: bool,
|
||||
|
||||
/// Move focus back to first/last span.
|
||||
#[clap(short = 'w', long)]
|
||||
#[arg(short = 'w', long, action = ArgAction::SetTrue)]
|
||||
pub focus_wrap_around: bool,
|
||||
|
||||
#[clap(flatten)]
|
||||
#[command(flatten)]
|
||||
pub colors: ui::colors::UiColors,
|
||||
|
||||
/// Align hint with its span.
|
||||
#[clap(long, arg_enum, default_value = "leading")]
|
||||
#[arg(long, value_enum, default_value_t = ui::HintAlignment::Leading)]
|
||||
pub hint_alignment: ui::HintAlignment,
|
||||
|
||||
/// Optional hint styling.
|
||||
///
|
||||
/// Underline or surround the hint for increased visibility.
|
||||
/// If not provided, only the hint colors will be used.
|
||||
#[clap(short = 's', long, arg_enum)]
|
||||
pub hint_style: Option<HintStyleArg>,
|
||||
#[arg(short = 's', long = "hint-style", rename_all = "lowercase", value_enum)]
|
||||
pub hint_style_arg: Option<HintStyleArg>,
|
||||
|
||||
/// Chars surrounding each hint, used with `Surround` style.
|
||||
#[clap(long, default_value = "{}",
|
||||
parse(try_from_str = parse_chars))]
|
||||
pub hint_surroundings: (char, char),
|
||||
#[clap(
|
||||
long,
|
||||
// default_value_t = HintSurroundingsArg{open: '{', close: '}'},
|
||||
default_value = "{}",
|
||||
value_parser(try_parse_chars)
|
||||
)]
|
||||
pub hint_surroundings: HintSurroundingsArg,
|
||||
}
|
||||
|
||||
/// Type introduced due to parsing limitation,
|
||||
/// as we cannot directly parse into ui::HintStyle.
|
||||
#[derive(Debug, Clap)]
|
||||
/// as we cannot directly parse tuples into ui::HintStyle.
|
||||
#[derive(Debug, Clone, ValueEnum)]
|
||||
pub enum HintStyleArg {
|
||||
Bold,
|
||||
Italic,
|
||||
|
|
@ -78,28 +91,44 @@ pub enum HintStyleArg {
|
|||
Surround,
|
||||
}
|
||||
|
||||
impl FromStr for HintStyleArg {
|
||||
type Err = error::ParseError;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HintSurroundingsArg {
|
||||
pub open: char,
|
||||
pub close: char,
|
||||
}
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, error::ParseError> {
|
||||
match s {
|
||||
"bold" => Ok(HintStyleArg::Bold),
|
||||
"italic" => Ok(HintStyleArg::Italic),
|
||||
"underline" => Ok(HintStyleArg::Underline),
|
||||
"surrond" => Ok(HintStyleArg::Surround),
|
||||
_ => Err(error::ParseError::ExpectedString(String::from(
|
||||
"bold, italic, underline or surround",
|
||||
))),
|
||||
}
|
||||
impl Display for HintSurroundingsArg {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}{}", self.open, self.close)
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to parse a `&str` into a tuple of `char`s.
|
||||
fn parse_chars(src: &str) -> Result<(char, char), error::ParseError> {
|
||||
fn try_parse_chars(src: &str) -> Result<HintSurroundingsArg> {
|
||||
if src.chars().count() != 2 {
|
||||
return Err(error::ParseError::ExpectedSurroundingPair);
|
||||
return Err(Error::ExpectedSurroundingPair);
|
||||
}
|
||||
|
||||
let chars: Vec<char> = src.chars().collect();
|
||||
Ok((chars[0], chars[1]))
|
||||
Ok(HintSurroundingsArg {
|
||||
open: chars[0],
|
||||
close: chars[1],
|
||||
})
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn hint_style(&self) -> Option<ui::HintStyle> {
|
||||
match &self.hint_style_arg {
|
||||
None => None,
|
||||
Some(style) => match style {
|
||||
HintStyleArg::Bold => Some(ui::HintStyle::Bold),
|
||||
HintStyleArg::Italic => Some(ui::HintStyle::Italic),
|
||||
HintStyleArg::Underline => Some(ui::HintStyle::Underline),
|
||||
HintStyleArg::Surround => {
|
||||
let HintSurroundingsArg { open, close } = self.hint_surroundings;
|
||||
Some(ui::HintStyle::Surround(open, close))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use clap::Clap;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::{Parser, ValueEnum};
|
||||
|
||||
use super::basic;
|
||||
use crate::{error, textbuf::alphabet, tmux, ui};
|
||||
use crate::{textbuf::alphabet, tmux, ui, Error, Result};
|
||||
|
||||
/// Extended configuration for handling Tmux-specific configuration (options
|
||||
/// and outputs). This is only used by `tmux-copyrat` and parsed from command
|
||||
/// line..
|
||||
#[derive(Clap, Debug)]
|
||||
/// line.
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, about, version)]
|
||||
pub struct ConfigExt {
|
||||
/// Don't read options from Tmux.
|
||||
|
|
@ -30,13 +30,19 @@ pub struct ConfigExt {
|
|||
pub window_name: String,
|
||||
|
||||
/// Capture visible area or entire pane history.
|
||||
#[clap(long, arg_enum, default_value = "visible-area")]
|
||||
#[clap(
|
||||
value_enum,
|
||||
long,
|
||||
rename_all = "kebab-case",
|
||||
default_value = "visible-area"
|
||||
)]
|
||||
pub capture_region: CaptureRegion,
|
||||
|
||||
/// Name of the copy-to-clipboard executable.
|
||||
///
|
||||
/// If during execution, the output destination is set to be clipboard,
|
||||
/// then copyrat will pipe the selected text to this executable.
|
||||
/// On macOS, this is `pbcopy`, on Linux, this is `xclip`.
|
||||
#[clap(long, default_value = "pbcopy")]
|
||||
pub clipboard_exe: String,
|
||||
|
||||
|
|
@ -46,46 +52,54 @@ pub struct ConfigExt {
|
|||
}
|
||||
|
||||
impl ConfigExt {
|
||||
pub fn initialize() -> Result<ConfigExt, error::ParseError> {
|
||||
pub fn initialize() -> Result<ConfigExt> {
|
||||
let mut config_ext = ConfigExt::parse();
|
||||
|
||||
if !config_ext.ignore_tmux_options {
|
||||
let tmux_options: HashMap<String, String> = tmux::get_options("@copyrat-")?;
|
||||
|
||||
// Override default values with those coming from tmux.
|
||||
let wrapped = &mut config_ext.basic_config;
|
||||
let inner = &mut config_ext.basic_config;
|
||||
|
||||
for (name, value) in &tmux_options {
|
||||
match name.as_ref() {
|
||||
"@copyrat-capture-region" => {
|
||||
config_ext.capture_region = CaptureRegion::from_str(&value)?
|
||||
let case_insensitive = true;
|
||||
config_ext.capture_region = CaptureRegion::from_str(value, case_insensitive)
|
||||
.map_err(Error::ExpectedEnumVariant)?
|
||||
}
|
||||
"@copyrat-alphabet" => {
|
||||
wrapped.alphabet = alphabet::parse_alphabet(value)?;
|
||||
inner.alphabet = alphabet::parse_alphabet(value)?;
|
||||
}
|
||||
"@copyrat-reverse" => {
|
||||
wrapped.reverse = value.parse::<bool>()?;
|
||||
inner.reverse = value.parse::<bool>()?;
|
||||
}
|
||||
"@copyrat-unique-hint" => {
|
||||
wrapped.unique_hint = value.parse::<bool>()?;
|
||||
inner.unique_hint = value.parse::<bool>()?;
|
||||
}
|
||||
|
||||
"@copyrat-span-fg" => wrapped.colors.span_fg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-span-bg" => wrapped.colors.span_bg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-span-fg" => inner.colors.span_fg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-span-bg" => inner.colors.span_bg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-focused-fg" => {
|
||||
wrapped.colors.focused_fg = ui::colors::parse_color(value)?
|
||||
inner.colors.focused_fg = ui::colors::parse_color(value)?
|
||||
}
|
||||
"@copyrat-focused-bg" => {
|
||||
wrapped.colors.focused_bg = ui::colors::parse_color(value)?
|
||||
inner.colors.focused_bg = ui::colors::parse_color(value)?
|
||||
}
|
||||
"@copyrat-hint-fg" => wrapped.colors.hint_fg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-hint-bg" => wrapped.colors.hint_bg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-hint-fg" => inner.colors.hint_fg = ui::colors::parse_color(value)?,
|
||||
"@copyrat-hint-bg" => inner.colors.hint_bg = ui::colors::parse_color(value)?,
|
||||
|
||||
"@copyrat-hint-alignment" => {
|
||||
wrapped.hint_alignment = ui::HintAlignment::from_str(&value)?
|
||||
let case_insensitive = true;
|
||||
inner.hint_alignment = ui::HintAlignment::from_str(value, case_insensitive)
|
||||
.map_err(Error::ExpectedEnumVariant)?
|
||||
}
|
||||
"@copyrat-hint-style" => {
|
||||
wrapped.hint_style = Some(basic::HintStyleArg::from_str(&value)?)
|
||||
let case_insensitive = true;
|
||||
inner.hint_style_arg = Some(
|
||||
basic::HintStyleArg::from_str(value, case_insensitive)
|
||||
.map_err(Error::ExpectedEnumVariant)?,
|
||||
)
|
||||
}
|
||||
|
||||
// Ignore unknown options.
|
||||
|
|
@ -98,11 +112,11 @@ impl ConfigExt {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
/// Specifies which region of the terminal buffer to capture.
|
||||
#[derive(Debug, Clone, ValueEnum, Parser)]
|
||||
pub enum CaptureRegion {
|
||||
/// The entire history.
|
||||
///
|
||||
/// This will end up sending `-S - -E -` to `tmux capture-pane`.
|
||||
// This will end up sending `-S - -E -` to `tmux capture-pane`.
|
||||
EntireHistory,
|
||||
/// The visible area.
|
||||
VisibleArea,
|
||||
|
|
@ -112,20 +126,6 @@ pub enum CaptureRegion {
|
|||
//Region(i32, i32),
|
||||
}
|
||||
|
||||
impl FromStr for CaptureRegion {
|
||||
type Err = error::ParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, error::ParseError> {
|
||||
match s {
|
||||
"entire-history" => Ok(CaptureRegion::EntireHistory),
|
||||
"visible-area" => Ok(CaptureRegion::VisibleArea),
|
||||
_ => Err(error::ParseError::ExpectedString(String::from(
|
||||
"entire-history or visible-area",
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the type of buffer the selected should be copied to: either a
|
||||
/// tmux buffer or the system clipboard.
|
||||
#[derive(Clone)]
|
||||
|
|
|
|||
73
src/error.rs
73
src/error.rs
|
|
@ -1,50 +1,43 @@
|
|||
use std::fmt;
|
||||
// use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Expected 2 chars")]
|
||||
ExpectedSurroundingPair,
|
||||
|
||||
#[error("Unknown alphabet")]
|
||||
UnknownAlphabet,
|
||||
|
||||
#[error("Unknown ANSI color name: allowed values are magenta, cyan, black, ...")]
|
||||
UnknownColor,
|
||||
|
||||
#[error("Unknown pattern name")]
|
||||
UnknownPatternName,
|
||||
|
||||
#[error("Expected a pane id marker")]
|
||||
ExpectedPaneIdMarker,
|
||||
ExpectedInt(std::num::ParseIntError),
|
||||
ExpectedBool(std::str::ParseBoolError),
|
||||
|
||||
#[error("Failed parsing integer")]
|
||||
ExpectedInt {
|
||||
#[from]
|
||||
source: std::num::ParseIntError,
|
||||
},
|
||||
|
||||
#[error("Failed to parse bool")]
|
||||
ExpectedBool {
|
||||
#[from]
|
||||
source: std::str::ParseBoolError,
|
||||
},
|
||||
|
||||
#[error("Expected the string `{0}`")]
|
||||
ExpectedString(String),
|
||||
ProcessFailure(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ParseError::ExpectedSurroundingPair => write!(f, "Expected 2 chars"),
|
||||
ParseError::UnknownAlphabet => write!(f, "Expected a known alphabet"),
|
||||
ParseError::UnknownColor => {
|
||||
write!(f, "Expected ANSI color name (magenta, cyan, black, ...)")
|
||||
}
|
||||
ParseError::UnknownPatternName => write!(f, "Expected a known pattern name"),
|
||||
ParseError::ExpectedPaneIdMarker => write!(f, "Expected pane id marker"),
|
||||
ParseError::ExpectedInt(msg) => write!(f, "Expected an int: {}", msg),
|
||||
ParseError::ExpectedBool(msg) => write!(f, "Expected a bool: {}", msg),
|
||||
ParseError::ExpectedString(msg) => write!(f, "Expected {}", msg),
|
||||
ParseError::ProcessFailure(msg) => write!(f, "{}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[error("Expected the value to be within `{0}`")]
|
||||
ExpectedEnumVariant(String),
|
||||
|
||||
impl From<std::num::ParseIntError> for ParseError {
|
||||
fn from(error: std::num::ParseIntError) -> Self {
|
||||
ParseError::ExpectedInt(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::ParseBoolError> for ParseError {
|
||||
fn from(error: std::str::ParseBoolError) -> Self {
|
||||
ParseError::ExpectedBool(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for ParseError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
ParseError::ProcessFailure(error.to_string())
|
||||
}
|
||||
#[error("IOError: `{source}`")]
|
||||
Io {
|
||||
#[from]
|
||||
source: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
20
src/lib.rs
20
src/lib.rs
|
|
@ -4,6 +4,9 @@ pub mod textbuf;
|
|||
pub mod tmux;
|
||||
pub mod ui;
|
||||
|
||||
pub use error::Error;
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Run copyrat on an input string `buffer`, configured by `Opt`.
|
||||
///
|
||||
/// # Note
|
||||
|
|
@ -11,7 +14,7 @@ pub mod ui;
|
|||
/// Maybe the decision to take ownership of the buffer is a bit bold.
|
||||
pub fn run(lines: &[&str], opt: &config::basic::Config) -> Option<ui::Selection> {
|
||||
let model = textbuf::Model::new(
|
||||
&lines,
|
||||
lines,
|
||||
&opt.alphabet,
|
||||
opt.use_all_patterns,
|
||||
&opt.named_patterns,
|
||||
|
|
@ -24,19 +27,6 @@ pub fn run(lines: &[&str], opt: &config::basic::Config) -> Option<ui::Selection>
|
|||
return None;
|
||||
}
|
||||
|
||||
let hint_style = match &opt.hint_style {
|
||||
None => None,
|
||||
Some(style) => match style {
|
||||
config::basic::HintStyleArg::Bold => Some(ui::HintStyle::Bold),
|
||||
config::basic::HintStyleArg::Italic => Some(ui::HintStyle::Italic),
|
||||
config::basic::HintStyleArg::Underline => Some(ui::HintStyle::Underline),
|
||||
config::basic::HintStyleArg::Surround => {
|
||||
let (open, close) = opt.hint_surroundings;
|
||||
Some(ui::HintStyle::Surround(open, close))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let default_output_destination = config::extended::OutputDestination::Tmux;
|
||||
|
||||
let selection: Option<ui::Selection> = {
|
||||
|
|
@ -46,7 +36,7 @@ pub fn run(lines: &[&str], opt: &config::basic::Config) -> Option<ui::Selection>
|
|||
default_output_destination,
|
||||
&opt.colors,
|
||||
&opt.hint_alignment,
|
||||
hint_style,
|
||||
opt.hint_style(),
|
||||
);
|
||||
|
||||
ui.present()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::error;
|
||||
use crate::{Error, Result};
|
||||
|
||||
/// Catalog of available alphabets.
|
||||
///
|
||||
|
|
@ -41,7 +41,7 @@ const ALPHABETS: [(&str, &str); 21] = [
|
|||
/// Letters 'n' and 'N' are systematically removed to prevent conflict with
|
||||
/// navigation keys (arrows and 'n' 'N'). Letters 'y' and 'Y' are also removed
|
||||
/// to prevent conflict with yank/copy.
|
||||
pub fn parse_alphabet(src: &str) -> Result<Alphabet, error::ParseError> {
|
||||
pub fn parse_alphabet(src: &str) -> Result<Alphabet> {
|
||||
let alphabet_pair = ALPHABETS.iter().find(|&(name, _letters)| name == &src);
|
||||
|
||||
match alphabet_pair {
|
||||
|
|
@ -49,12 +49,12 @@ pub fn parse_alphabet(src: &str) -> Result<Alphabet, error::ParseError> {
|
|||
let letters = letters.replace(&['n', 'N', 'y', 'Y'][..], "");
|
||||
Ok(Alphabet(letters))
|
||||
}
|
||||
None => Err(error::ParseError::UnknownAlphabet),
|
||||
None => Err(Error::UnknownAlphabet),
|
||||
}
|
||||
}
|
||||
|
||||
/// Type-safe string alphabet (newtype).
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Alphabet(pub String);
|
||||
|
||||
impl Alphabet {
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ mod tests {
|
|||
let named_pat = vec![
|
||||
parse_pattern_name("quoted-single").unwrap(),
|
||||
parse_pattern_name("quoted-double").unwrap(),
|
||||
parse_pattern_name("quoted-tick").unwrap(),
|
||||
parse_pattern_name("quoted-backtick").unwrap(),
|
||||
];
|
||||
|
||||
let custom = vec![];
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl<'a> Model<'a> {
|
|||
unique_hint: bool,
|
||||
) -> Model<'a> {
|
||||
let mut raw_spans =
|
||||
find_raw_spans(&lines, named_patterns, custom_patterns, use_all_patterns);
|
||||
find_raw_spans(lines, named_patterns, custom_patterns, use_all_patterns);
|
||||
|
||||
if reverse {
|
||||
raw_spans.reverse();
|
||||
|
|
@ -113,9 +113,10 @@ fn find_raw_spans<'a>(
|
|||
// the start and end byte indices with respect to the chunk.
|
||||
let chunk_matches = all_regexes
|
||||
.iter()
|
||||
.filter_map(|(&ref pat_name, reg)| match reg.find_iter(chunk).next() {
|
||||
Some(reg_match) => Some((pat_name, reg, reg_match)),
|
||||
None => None,
|
||||
.filter_map(|(&ref pat_name, reg)| {
|
||||
reg.find_iter(chunk)
|
||||
.next()
|
||||
.map(|reg_match| (pat_name, reg, reg_match))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! All patterns must have one capture group. The first group is used.
|
||||
|
||||
use crate::error;
|
||||
use crate::{Error, Result};
|
||||
|
||||
pub(super) const EXCLUDE_PATTERNS: [(&str, &str); 1] =
|
||||
[("ansi_colors", r"[[:cntrl:]]\[([0-9]{1,2};)?([0-9]{1,2})?m")];
|
||||
|
|
@ -15,7 +15,7 @@ pub(super) const PATTERNS: [(&str, &str); 20] = [
|
|||
("markdown-url", r"\[[^]]*\]\(([^)]+)\)"),
|
||||
(
|
||||
"url",
|
||||
r"((https?://|git@|git://|ssh://|ftp://|file:///)[^ \(\)\[\]\{\}]+)",
|
||||
r"((https?://|git@|git://|ssh://|ftp://|file:///)[^ \(\)\[\]\{\}>]+)",
|
||||
),
|
||||
("email", r"\b([A-z0-9._%+-]+@[A-z0-9.-]+\.[A-z]{2,})\b"),
|
||||
("diff-a", r"--- a/([^ ]+)"),
|
||||
|
|
@ -42,18 +42,18 @@ pub(super) const PATTERNS: [(&str, &str); 20] = [
|
|||
),
|
||||
("quoted-single", r#"'([^']+)'"#),
|
||||
("quoted-double", r#""([^"]+)""#),
|
||||
("quoted-tick", r#"`([^`]+)`"#),
|
||||
("quoted-backtick", r#"`([^`]+)`"#),
|
||||
("digits", r"([0-9]{4,})"),
|
||||
];
|
||||
|
||||
/// Type-safe string Pattern Name (newtype).
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NamedPattern(pub String, pub String);
|
||||
|
||||
/// Parse a name string into `NamedPattern`, used during CLI parsing.
|
||||
pub(crate) fn parse_pattern_name(src: &str) -> Result<NamedPattern, error::ParseError> {
|
||||
pub(crate) fn parse_pattern_name(src: &str) -> Result<NamedPattern> {
|
||||
match PATTERNS.iter().find(|&(name, _pattern)| name == &src) {
|
||||
Some((name, pattern)) => Ok(NamedPattern(name.to_string(), pattern.to_string())),
|
||||
None => Err(error::ParseError::UnknownPatternName),
|
||||
None => Err(Error::UnknownPatternName),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
48
src/tmux.rs
48
src/tmux.rs
|
|
@ -3,15 +3,18 @@
|
|||
//! The main use cases are running Tmux commands & parsing Tmux panes
|
||||
//! information.
|
||||
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::config::extended::CaptureRegion;
|
||||
use crate::error::ParseError;
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
use crate::config::extended::CaptureRegion;
|
||||
use crate::{Error, Result};
|
||||
|
||||
/// Represents a simplified Tmux Pane, only holding the properties needed in
|
||||
/// this crate.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Pane {
|
||||
/// Pane identifier, e.g. `%37`.
|
||||
pub id: PaneId,
|
||||
|
|
@ -30,7 +33,7 @@ pub struct Pane {
|
|||
}
|
||||
|
||||
impl FromStr for Pane {
|
||||
type Err = ParseError;
|
||||
type Err = Error;
|
||||
|
||||
/// Parse a string containing tmux panes status into a new `Pane`.
|
||||
///
|
||||
|
|
@ -44,7 +47,7 @@ impl FromStr for Pane {
|
|||
///
|
||||
/// For definitions, look at `Pane` type,
|
||||
/// and at the tmux man page for definitions.
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
fn from_str(src: &str) -> std::result::Result<Self, Self::Err> {
|
||||
let items: Vec<&str> = src.split(':').collect();
|
||||
assert_eq!(items.len(), 5, "tmux should have returned 5 items per line");
|
||||
|
||||
|
|
@ -98,7 +101,7 @@ impl Pane {
|
|||
/// scrolled up by 3 lines. It is necessarily in copy mode. Its start line
|
||||
/// index is `-3`. The index of the last line is `(40-1) - 3 = 36`.
|
||||
///
|
||||
pub fn capture(&self, region: &CaptureRegion) -> Result<String, ParseError> {
|
||||
pub fn capture(&self, region: &CaptureRegion) -> Result<String> {
|
||||
let mut args_str = format!("capture-pane -t {pane_id} -J -p", pane_id = self.id);
|
||||
|
||||
let region_str = match region {
|
||||
|
|
@ -125,17 +128,17 @@ impl Pane {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PaneId(String);
|
||||
|
||||
impl FromStr for PaneId {
|
||||
type Err = ParseError;
|
||||
type Err = Error;
|
||||
|
||||
/// Parse into PaneId. The `&str` must be start with '%'
|
||||
/// followed by a `u16`.
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
fn from_str(src: &str) -> std::result::Result<Self, Self::Err> {
|
||||
if !src.starts_with('%') {
|
||||
return Err(ParseError::ExpectedPaneIdMarker);
|
||||
return Err(Error::ExpectedPaneIdMarker);
|
||||
}
|
||||
let id = src[1..].parse::<u16>()?;
|
||||
let id = format!("%{}", id);
|
||||
|
|
@ -156,7 +159,7 @@ impl fmt::Display for PaneId {
|
|||
}
|
||||
|
||||
/// Returns a list of `Pane` from the current tmux session.
|
||||
pub fn available_panes() -> Result<Vec<Pane>, ParseError> {
|
||||
pub fn available_panes() -> Result<Vec<Pane>> {
|
||||
let args = vec![
|
||||
"list-panes",
|
||||
"-F",
|
||||
|
|
@ -165,12 +168,12 @@ pub fn available_panes() -> Result<Vec<Pane>, ParseError> {
|
|||
|
||||
let output = duct::cmd("tmux", &args).read()?;
|
||||
|
||||
// Each call to `Pane::parse` returns a `Result<Pane, _>`. All results
|
||||
// are collected into a Result<Vec<Pane>, _>, thanks to `collect()`.
|
||||
let result: Result<Vec<Pane>, ParseError> = output
|
||||
// Each call to `Pane::parse` returns a `Result<Pane>`. All results
|
||||
// are collected into a Result<Vec<Pane>>, thanks to `collect()`.
|
||||
let result: Result<Vec<Pane>> = output
|
||||
.trim_end() // trim last '\n' as it would create an empty line
|
||||
.split('\n')
|
||||
.map(|line| Pane::from_str(line))
|
||||
.map(Pane::from_str) // .map(|line| Pane::from_str(line))
|
||||
.collect();
|
||||
|
||||
result
|
||||
|
|
@ -182,7 +185,7 @@ pub fn available_panes() -> Result<Vec<Pane>, ParseError> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```get_options("@copyrat-")```
|
||||
pub fn get_options(prefix: &str) -> Result<HashMap<String, String>, ParseError> {
|
||||
pub fn get_options(prefix: &str) -> Result<HashMap<String, String>> {
|
||||
let output = duct::cmd!("tmux", "show-options", "-g").read()?;
|
||||
let lines: Vec<&str> = output.split('\n').collect();
|
||||
|
||||
|
|
@ -204,8 +207,8 @@ pub fn get_options(prefix: &str) -> Result<HashMap<String, String>, ParseError>
|
|||
Ok(args)
|
||||
}
|
||||
|
||||
/// Ask tmux to swap the current Pane with the target_pane (uses Tmux format).
|
||||
pub fn swap_pane_with(target_pane: &str) -> Result<(), ParseError> {
|
||||
/// Asks tmux to swap the current Pane with the target_pane (uses Tmux format).
|
||||
pub fn swap_pane_with(target_pane: &str) -> Result<()> {
|
||||
// -Z: keep the window zoomed if it was zoomed.
|
||||
duct::cmd!("tmux", "swap-pane", "-Z", "-s", target_pane).run()?;
|
||||
|
||||
|
|
@ -214,16 +217,13 @@ pub fn swap_pane_with(target_pane: &str) -> Result<(), ParseError> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Pane;
|
||||
use super::PaneId;
|
||||
use crate::error;
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_parse_pass() {
|
||||
let output = vec!["%52:false:62:3:false", "%53:false:23::true"];
|
||||
let panes: Result<Vec<Pane>, error::ParseError> =
|
||||
output.iter().map(|&line| Pane::from_str(line)).collect();
|
||||
let panes: Result<Vec<Pane>> = output.iter().map(|&line| Pane::from_str(line)).collect();
|
||||
let panes = panes.expect("Could not parse tmux panes");
|
||||
|
||||
let expected = vec![
|
||||
|
|
|
|||
164
src/ui/colors.rs
164
src/ui/colors.rs
|
|
@ -1,28 +1,79 @@
|
|||
use crate::error;
|
||||
use clap::Clap;
|
||||
use termion::color;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn parse_color(src: &str) -> Result<Box<dyn color::Color>, error::ParseError> {
|
||||
match src {
|
||||
"black" => Ok(Box::new(color::Black)),
|
||||
"red" => Ok(Box::new(color::Red)),
|
||||
"green" => Ok(Box::new(color::Green)),
|
||||
"yellow" => Ok(Box::new(color::Yellow)),
|
||||
"blue" => Ok(Box::new(color::Blue)),
|
||||
"magenta" => Ok(Box::new(color::Magenta)),
|
||||
"cyan" => Ok(Box::new(color::Cyan)),
|
||||
"white" => Ok(Box::new(color::White)),
|
||||
"bright-black" | "brightblack" => Ok(Box::new(color::LightBlack)),
|
||||
"bright-red" | "brightred" => Ok(Box::new(color::LightRed)),
|
||||
"bright-green" | "brightgreen" => Ok(Box::new(color::LightGreen)),
|
||||
"bright-yellow" | "brightyellow" => Ok(Box::new(color::LightYellow)),
|
||||
"bright-blue" | "brightblue" => Ok(Box::new(color::LightBlue)),
|
||||
"bright-magenta" | "brightmagenta" => Ok(Box::new(color::LightMagenta)),
|
||||
"bright-cyan" | "brightcyan" => Ok(Box::new(color::LightCyan)),
|
||||
"bright-white" | "brightwhite" => Ok(Box::new(color::LightWhite)),
|
||||
"none" => Ok(Box::new(color::Reset)),
|
||||
_ => Err(error::ParseError::UnknownColor),
|
||||
use clap::Args;
|
||||
use termion::color as tcolor;
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Color(Option<u8>);
|
||||
|
||||
impl tcolor::Color for Color {
|
||||
#[inline]
|
||||
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.0 {
|
||||
Some(value) => write!(f, "\x1B[38;5;{}m", value),
|
||||
None => write!(f, "\x1B[39m"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.0 {
|
||||
Some(value) => write!(f, "\x1B[48;5;{}m", value),
|
||||
None => write!(f, "\x1B[49m"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) static BLACK: Color = Color(Some(0));
|
||||
pub(crate) static RED: Color = Color(Some(1));
|
||||
pub(crate) static GREEN: Color = Color(Some(2));
|
||||
pub(crate) static YELLOW: Color = Color(Some(3));
|
||||
pub(crate) static BLUE: Color = Color(Some(4));
|
||||
pub(crate) static MAGENTA: Color = Color(Some(5));
|
||||
pub(crate) static CYAN: Color = Color(Some(6));
|
||||
pub(crate) static WHITE: Color = Color(Some(7));
|
||||
pub(crate) static BRIGHTBLACK: Color = Color(Some(8));
|
||||
pub(crate) static BRIGHTRED: Color = Color(Some(9));
|
||||
pub(crate) static BRIGHTGREEN: Color = Color(Some(10));
|
||||
pub(crate) static BRIGHTYELLOW: Color = Color(Some(11));
|
||||
pub(crate) static BRIGHTBLUE: Color = Color(Some(12));
|
||||
pub(crate) static BRIGHTMAGENTA: Color = Color(Some(13));
|
||||
pub(crate) static BRIGHTCYAN: Color = Color(Some(14));
|
||||
pub(crate) static BRIGHTWHITE: Color = Color(Some(15));
|
||||
pub(crate) static RESET: Color = Color(None);
|
||||
|
||||
impl FromStr for Color {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(src: &str) -> std::result::Result<Self, Self::Err> {
|
||||
match src {
|
||||
"black" => Ok(BLACK),
|
||||
"red" => Ok(RED),
|
||||
"green" => Ok(GREEN),
|
||||
"yellow" => Ok(YELLOW),
|
||||
"blue" => Ok(BLUE),
|
||||
"magenta" => Ok(MAGENTA),
|
||||
"cyan" => Ok(CYAN),
|
||||
"white" => Ok(WHITE),
|
||||
"bright-black" | "brightblack" => Ok(BRIGHTBLACK),
|
||||
"bright-red" | "brightred" => Ok(BRIGHTRED),
|
||||
"bright-green" | "brightgreen" => Ok(BRIGHTGREEN),
|
||||
"bright-yellow" | "brightyellow" => Ok(BRIGHTYELLOW),
|
||||
"bright-blue" | "brightblue" => Ok(BRIGHTBLUE),
|
||||
"bright-magenta" | "brightmagenta" => Ok(BRIGHTMAGENTA),
|
||||
"bright-cyan" | "brightcyan" => Ok(BRIGHTCYAN),
|
||||
"bright-white" | "brightwhite" => Ok(BRIGHTWHITE),
|
||||
"none" => Ok(RESET),
|
||||
_ => Err(Error::UnknownColor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_color(src: &str) -> Result<Color> {
|
||||
Color::from_str(src)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -30,20 +81,27 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn span_color() {
|
||||
let text1 = format!(
|
||||
"{}{}",
|
||||
color::Fg(parse_color("green").unwrap().as_ref()),
|
||||
"foo"
|
||||
);
|
||||
let text2 = format!("{}{}", color::Fg(color::Green), "foo");
|
||||
fn span_color_fg() {
|
||||
let actual = format!("{}{}", tcolor::Fg(Color::from_str("green").unwrap()), "foo");
|
||||
let expected = format!("{}{}", tcolor::Fg(tcolor::Green), "foo");
|
||||
|
||||
assert_eq!(text1, text2);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn span_color_bg() {
|
||||
let actual = format!("{}{}", tcolor::Bg(Color::from_str("green").unwrap()), "foo");
|
||||
let expected = format!("{}{}", tcolor::Bg(tcolor::Green), "foo");
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_span_color() {
|
||||
assert!(parse_color("wat").is_err(), "this color should not exist");
|
||||
assert!(
|
||||
Color::from_str("wat").is_err(),
|
||||
"this color should not exist"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,44 +110,38 @@ mod tests {
|
|||
/// - `focus_*` colors are used to render the currently focused text span.
|
||||
/// - `normal_*` colors are used to render other text spans.
|
||||
/// - `hint_*` colors are used to render the hints.
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(about)] // Needed to avoid this doc comment to be used as overall `about`.
|
||||
#[derive(Args, Debug)]
|
||||
// #[clap(about)] // Needed to avoid this doc comment to be used as overall `about`.
|
||||
pub struct UiColors {
|
||||
/// Foreground color for base text.
|
||||
#[clap(long, default_value = "bright-cyan", parse(try_from_str = parse_color))]
|
||||
pub text_fg: Box<dyn color::Color>,
|
||||
#[arg(long, default_value = "bright-cyan", value_parser(parse_color))]
|
||||
pub text_fg: Color,
|
||||
|
||||
/// Background color for base text.
|
||||
#[clap(long, default_value = "none", parse(try_from_str = parse_color))]
|
||||
pub text_bg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "none", value_parser(parse_color))]
|
||||
pub text_bg: Color,
|
||||
|
||||
/// Foreground color for spans.
|
||||
#[clap(long, default_value = "blue",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub span_fg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "blue", value_parser(parse_color))]
|
||||
pub span_fg: Color,
|
||||
|
||||
/// Background color for spans.
|
||||
#[clap(long, default_value = "none",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub span_bg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "none", value_parser(parse_color))]
|
||||
pub span_bg: Color,
|
||||
|
||||
/// Foreground color for the focused span.
|
||||
#[clap(long, default_value = "magenta",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub focused_fg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "magenta", value_parser(parse_color))]
|
||||
pub focused_fg: Color,
|
||||
|
||||
/// Background color for the focused span.
|
||||
#[clap(long, default_value = "none",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub focused_bg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "none", value_parser(parse_color))]
|
||||
pub focused_bg: Color,
|
||||
|
||||
/// Foreground color for hints.
|
||||
#[clap(long, default_value = "yellow",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub hint_fg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "yellow", value_parser(parse_color))]
|
||||
pub hint_fg: Color,
|
||||
|
||||
/// Background color for hints.
|
||||
#[clap(long, default_value = "none",
|
||||
parse(try_from_str = parse_color))]
|
||||
pub hint_bg: Box<dyn color::Color>,
|
||||
#[clap(long, default_value = "none", value_parser(parse_color))]
|
||||
pub hint_bg: Color,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
use clap::Clap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::error::ParseError;
|
||||
use clap::{Parser, ValueEnum};
|
||||
|
||||
/// Describes if, during rendering, a hint should aligned to the leading edge of
|
||||
/// the matched text, or to its trailing edge.
|
||||
#[derive(Debug, Clap)]
|
||||
#[derive(Debug, Clone, ValueEnum, Parser)]
|
||||
pub enum HintAlignment {
|
||||
Leading,
|
||||
Trailing,
|
||||
}
|
||||
|
||||
impl FromStr for HintAlignment {
|
||||
type Err = ParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<HintAlignment, ParseError> {
|
||||
match s {
|
||||
"leading" => Ok(HintAlignment::Leading),
|
||||
"trailing" => Ok(HintAlignment::Trailing),
|
||||
_ => Err(ParseError::ExpectedString(String::from(
|
||||
"leading or trailing",
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
214
src/ui/vc.rs
214
src/ui/vc.rs
|
|
@ -1,8 +1,9 @@
|
|||
use std::char;
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
|
||||
use termion::{self, color, cursor, event, style};
|
||||
use termion::{self, color, cursor, event, screen::IntoAlternateScreen, style};
|
||||
|
||||
use super::colors::UiColors;
|
||||
use super::Selection;
|
||||
|
|
@ -63,7 +64,7 @@ impl<'a> ViewController<'a> {
|
|||
};
|
||||
|
||||
let (term_width, _) = termion::terminal_size().unwrap_or((80u16, 30u16)); // .expect("Cannot read the terminal size.");
|
||||
let wrapped_lines = compute_wrapped_lines(&model.lines, term_width);
|
||||
let wrapped_lines = compute_wrapped_lines(model.lines, term_width);
|
||||
|
||||
ViewController {
|
||||
model,
|
||||
|
|
@ -177,8 +178,8 @@ impl<'a> ViewController<'a> {
|
|||
write!(
|
||||
stdout,
|
||||
"{bg_color}{fg_color}",
|
||||
fg_color = color::Fg(colors.text_fg.as_ref()),
|
||||
bg_color = color::Bg(colors.text_bg.as_ref()),
|
||||
fg_color = color::Fg(colors.text_fg),
|
||||
bg_color = color::Bg(colors.text_bg),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -233,8 +234,8 @@ impl<'a> ViewController<'a> {
|
|||
stdout,
|
||||
"{goto}{bg_color}{fg_color}{text}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(pos.0 as u16 + 1, pos.1 as u16 + 1),
|
||||
fg_color = color::Fg(fg_color.as_ref()),
|
||||
bg_color = color::Bg(bg_color.as_ref()),
|
||||
fg_color = color::Fg(*fg_color),
|
||||
bg_color = color::Bg(*bg_color),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
text = &text,
|
||||
|
|
@ -260,8 +261,8 @@ impl<'a> ViewController<'a> {
|
|||
colors: &UiColors,
|
||||
hint_style: &Option<HintStyle>,
|
||||
) {
|
||||
let fg_color = color::Fg(colors.hint_fg.as_ref());
|
||||
let bg_color = color::Bg(colors.hint_bg.as_ref());
|
||||
let fg_color = color::Fg(colors.hint_fg);
|
||||
let bg_color = color::Bg(colors.hint_bg);
|
||||
let fg_reset = color::Fg(color::Reset);
|
||||
let bg_reset = color::Bg(color::Reset);
|
||||
let goto = cursor::Goto(pos.0 as u16 + 1, pos.1 as u16 + 1);
|
||||
|
|
@ -358,7 +359,7 @@ impl<'a> ViewController<'a> {
|
|||
text,
|
||||
focused,
|
||||
(pos_x, pos_y),
|
||||
&self.rendering_colors,
|
||||
self.rendering_colors,
|
||||
);
|
||||
|
||||
if !focused {
|
||||
|
|
@ -374,7 +375,7 @@ impl<'a> ViewController<'a> {
|
|||
stdout,
|
||||
&span.hint,
|
||||
(pos_x + offset, pos_y),
|
||||
&self.rendering_colors,
|
||||
self.rendering_colors,
|
||||
&self.hint_style,
|
||||
);
|
||||
}
|
||||
|
|
@ -399,9 +400,9 @@ impl<'a> ViewController<'a> {
|
|||
// 1. Trim all lines and render non-empty ones.
|
||||
ViewController::render_base_text(
|
||||
stdout,
|
||||
&self.model.lines,
|
||||
self.model.lines,
|
||||
&self.wrapped_lines,
|
||||
&self.rendering_colors,
|
||||
self.rendering_colors,
|
||||
);
|
||||
|
||||
for (index, span) in self.model.spans.iter().enumerate() {
|
||||
|
|
@ -598,17 +599,16 @@ impl<'a> ViewController<'a> {
|
|||
/// - Setup steps: switch to alternate screen, switch to raw mode, hide the cursor.
|
||||
/// - Teardown steps: show cursor, back to main screen.
|
||||
pub fn present(&mut self) -> Option<Selection> {
|
||||
use std::io::Write;
|
||||
use termion::raw::IntoRawMode;
|
||||
use termion::screen::AlternateScreen;
|
||||
|
||||
let mut stdin = termion::async_stdin();
|
||||
let mut stdout = AlternateScreen::from(
|
||||
io::stdout()
|
||||
.into_raw_mode()
|
||||
.expect("Cannot access alternate screen."),
|
||||
);
|
||||
let mut stdout = io::stdout()
|
||||
.into_alternate_screen()
|
||||
.expect("Cannot access alternate screen.")
|
||||
.into_raw_mode()
|
||||
.expect("Cannot access alternate screen.");
|
||||
|
||||
// stdout.write(cursor::Hide.into()).unwrap();
|
||||
write!(stdout, "{}", cursor::Hide).unwrap();
|
||||
|
||||
let selection = match self.listen(&mut stdin, &mut stdout) {
|
||||
|
|
@ -663,7 +663,7 @@ enum Event {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::textbuf::alphabet;
|
||||
use crate::{textbuf::alphabet, ui::colors};
|
||||
|
||||
#[test]
|
||||
fn test_render_all_lines() {
|
||||
|
|
@ -684,14 +684,14 @@ path: /usr/local/bin/cargo";
|
|||
];
|
||||
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
let mut writer = vec![];
|
||||
|
|
@ -706,8 +706,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{bg}{fg}{g1}some text{g2}* e006b06 - (12 days ago) swapper: Make quotes{g3}path: /usr/local/bin/git{g6}path: /usr/local/bin/cargo{fg_reset}{bg_reset}",
|
||||
g1 = goto1, g2 = goto2, g3 = goto3, g6 = goto6,
|
||||
fg = color::Fg(colors.text_fg.as_ref()),
|
||||
bg = color::Bg(colors.text_bg.as_ref()),
|
||||
fg = color::Fg(colors.text_fg),
|
||||
bg = color::Bg(colors.text_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
)
|
||||
|
|
@ -722,14 +722,14 @@ path: /usr/local/bin/cargo";
|
|||
let focused = true;
|
||||
let position: (usize, usize) = (3, 1);
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
ViewController::render_span_text(&mut writer, text, focused, position, &colors);
|
||||
|
|
@ -739,8 +739,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{goto}{bg}{fg}{text}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(4, 2),
|
||||
fg = color::Fg(colors.focused_fg.as_ref()),
|
||||
bg = color::Bg(colors.focused_bg.as_ref()),
|
||||
fg = color::Fg(colors.focused_fg),
|
||||
bg = color::Bg(colors.focused_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
text = &text,
|
||||
|
|
@ -756,14 +756,14 @@ path: /usr/local/bin/cargo";
|
|||
let focused = false;
|
||||
let position: (usize, usize) = (3, 1);
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
ViewController::render_span_text(&mut writer, text, focused, position, &colors);
|
||||
|
|
@ -773,8 +773,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{goto}{bg}{fg}{text}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(4, 2),
|
||||
fg = color::Fg(colors.span_fg.as_ref()),
|
||||
bg = color::Bg(colors.span_bg.as_ref()),
|
||||
fg = color::Fg(colors.span_fg),
|
||||
bg = color::Bg(colors.span_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
text = &text,
|
||||
|
|
@ -789,14 +789,14 @@ path: /usr/local/bin/cargo";
|
|||
let hint_text = "eo";
|
||||
let position: (usize, usize) = (3, 1);
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
let offset = 0;
|
||||
|
|
@ -815,8 +815,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{goto}{bg}{fg}{text}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(4, 2),
|
||||
fg = color::Fg(colors.hint_fg.as_ref()),
|
||||
bg = color::Bg(colors.hint_bg.as_ref()),
|
||||
fg = color::Fg(colors.hint_fg),
|
||||
bg = color::Bg(colors.hint_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
text = "eo",
|
||||
|
|
@ -831,14 +831,14 @@ path: /usr/local/bin/cargo";
|
|||
let hint_text = "eo";
|
||||
let position: (usize, usize) = (3, 1);
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
let offset = 0;
|
||||
|
|
@ -857,8 +857,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{goto}{bg}{fg}{sty}{text}{sty_reset}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(4, 2),
|
||||
fg = color::Fg(colors.hint_fg.as_ref()),
|
||||
bg = color::Bg(colors.hint_bg.as_ref()),
|
||||
fg = color::Fg(colors.hint_fg),
|
||||
bg = color::Bg(colors.hint_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
sty = style::Underline,
|
||||
|
|
@ -875,14 +875,14 @@ path: /usr/local/bin/cargo";
|
|||
let hint_text = "eo";
|
||||
let position: (usize, usize) = (3, 1);
|
||||
let colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
|
||||
let offset = 0;
|
||||
|
|
@ -901,8 +901,8 @@ path: /usr/local/bin/cargo";
|
|||
format!(
|
||||
"{goto}{bg}{fg}{bra}{text}{bra_close}{fg_reset}{bg_reset}",
|
||||
goto = cursor::Goto(4, 2),
|
||||
fg = color::Fg(colors.hint_fg.as_ref()),
|
||||
bg = color::Bg(colors.hint_bg.as_ref()),
|
||||
fg = color::Fg(colors.hint_fg),
|
||||
bg = color::Bg(colors.hint_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
bra = '{',
|
||||
|
|
@ -937,16 +937,16 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
unique_hint,
|
||||
);
|
||||
let term_width: u16 = 80;
|
||||
let wrapped_lines = compute_wrapped_lines(&model.lines, term_width);
|
||||
let wrapped_lines = compute_wrapped_lines(model.lines, term_width);
|
||||
let rendering_colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
let hint_alignment = HintAlignment::Leading;
|
||||
|
||||
|
|
@ -974,8 +974,8 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
{goto3}Barcelona https://en.wikipedia.org/wiki/Barcelona -{fg_reset}{bg_reset}",
|
||||
goto1 = goto1,
|
||||
goto3 = goto3,
|
||||
fg = color::Fg(rendering_colors.text_fg.as_ref()),
|
||||
bg = color::Bg(rendering_colors.text_bg.as_ref()),
|
||||
fg = color::Fg(rendering_colors.text_fg),
|
||||
bg = color::Bg(rendering_colors.text_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset),
|
||||
);
|
||||
|
|
@ -1013,14 +1013,14 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
let default_output_destination = OutputDestination::Tmux;
|
||||
|
||||
let rendering_colors = UiColors {
|
||||
text_fg: Box::new(color::Black),
|
||||
text_bg: Box::new(color::White),
|
||||
focused_fg: Box::new(color::Red),
|
||||
focused_bg: Box::new(color::Blue),
|
||||
span_fg: Box::new(color::Green),
|
||||
span_bg: Box::new(color::Magenta),
|
||||
hint_fg: Box::new(color::Yellow),
|
||||
hint_bg: Box::new(color::Cyan),
|
||||
text_fg: colors::BLACK,
|
||||
text_bg: colors::WHITE,
|
||||
focused_fg: colors::RED,
|
||||
focused_bg: colors::BLUE,
|
||||
span_fg: colors::GREEN,
|
||||
span_bg: colors::MAGENTA,
|
||||
hint_fg: colors::YELLOW,
|
||||
hint_bg: colors::CYAN,
|
||||
};
|
||||
let hint_alignment = HintAlignment::Leading;
|
||||
let hint_style = None;
|
||||
|
|
@ -1046,8 +1046,8 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
{goto3}Barcelona https://en.wikipedia.org/wiki/Barcelona -{fg_reset}{bg_reset}",
|
||||
goto1 = goto1,
|
||||
goto3 = goto3,
|
||||
fg = color::Fg(rendering_colors.text_fg.as_ref()),
|
||||
bg = color::Bg(rendering_colors.text_bg.as_ref()),
|
||||
fg = color::Fg(rendering_colors.text_fg),
|
||||
bg = color::Bg(rendering_colors.text_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset)
|
||||
)
|
||||
|
|
@ -1058,8 +1058,8 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
format!(
|
||||
"{goto7_1}{span_bg}{span_fg}127.0.0.1{fg_reset}{bg_reset}",
|
||||
goto7_1 = goto7_1,
|
||||
span_fg = color::Fg(rendering_colors.span_fg.as_ref()),
|
||||
span_bg = color::Bg(rendering_colors.span_bg.as_ref()),
|
||||
span_fg = color::Fg(rendering_colors.span_fg),
|
||||
span_bg = color::Bg(rendering_colors.span_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset)
|
||||
)
|
||||
|
|
@ -1071,8 +1071,8 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
format!(
|
||||
"{goto7_1}{hint_bg}{hint_fg}b{fg_reset}{bg_reset}",
|
||||
goto7_1 = goto7_1,
|
||||
hint_fg = color::Fg(rendering_colors.hint_fg.as_ref()),
|
||||
hint_bg = color::Bg(rendering_colors.hint_bg.as_ref()),
|
||||
hint_fg = color::Fg(rendering_colors.hint_fg),
|
||||
hint_bg = color::Bg(rendering_colors.hint_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset)
|
||||
)
|
||||
|
|
@ -1083,8 +1083,8 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
format!(
|
||||
"{goto11_3}{focus_bg}{focus_fg}https://en.wikipedia.org/wiki/Barcelona{fg_reset}{bg_reset}",
|
||||
goto11_3 = goto11_3,
|
||||
focus_fg = color::Fg(rendering_colors.focused_fg.as_ref()),
|
||||
focus_bg = color::Bg(rendering_colors.focused_bg.as_ref()),
|
||||
focus_fg = color::Fg(rendering_colors.focused_fg),
|
||||
focus_bg = color::Bg(rendering_colors.focused_bg),
|
||||
fg_reset = color::Fg(color::Reset),
|
||||
bg_reset = color::Bg(color::Reset)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue