feat!: use smarter setters, remove the need for Some(...) and String::from() in setters

This commit is contained in:
Loric ANDRE 2026-02-11 18:18:35 +01:00
parent 495b9ae611
commit d11e627ba6
34 changed files with 642 additions and 230 deletions

View file

@ -57,6 +57,8 @@ jobs:
tool: cargo-llvm-cov@0.8
- name: Cache
uses: Swatinem/rust-cache@v2
- name: Run doctests
run: cargo test --doc
- name: Run tests
run: cargo llvm-cov nextest --release --features test-utils --all-targets --codecov --output-path codecov.json
env:

View file

@ -4,12 +4,12 @@ use skim::{prelude::*, reader::CommandCollector};
pub fn main() {
env_logger::init();
let glogm = Some(String::from("git log --oneline --color=always | head -n10"));
let glogm = "git log --oneline --color=always | head -n10";
let options = SkimOptionsBuilder::default()
.height(String::from("50%"))
.height("50%")
.cmd(glogm)
.preview(Some(String::from("echo {}")))
.preview("echo {}")
.multi(true)
.reverse(true)
.cmd_collector(Rc::new(RefCell::new(SkimItemReader::new(
@ -25,6 +25,6 @@ pub fn main() {
.unwrap_or_default();
for item in selected_items.iter() {
print!("selected: {}{}", item.output(), "\n");
println!("selected: {}", item.output());
}
}

View file

@ -10,7 +10,6 @@ use std::io::Cursor;
/// 1. Create custom action callbacks
/// 2. Bind them to specific key combinations
/// 3. Use them interactively in skim
fn main() {
// Create a custom callback that adds a prefix to the query
let add_prefix_callback = ActionCallback::new(|app: &mut skim::tui::App<'static>| {
@ -46,10 +45,8 @@ fn main() {
// Build basic options
let mut options = SkimOptionsBuilder::default()
.multi(true)
.prompt("Select> ".to_string())
.header(Some(String::from(
"<C-p>: add prefix to prompt\t<C-a>: select all and exit with count",
)))
.prompt("Select> ")
.header("<C-p>: add prefix to prompt\t<C-a>: select all and exit with count")
.build()
.unwrap();
@ -69,7 +66,7 @@ fn main() {
);
// Create sample items
let items = vec![
let items = [
"Write documentation",
"Fix bug #123",
"Implement feature X",

View file

@ -21,9 +21,9 @@ impl SkimItem for MyItem {
fn main() {
let options = SkimOptionsBuilder::default()
.height(String::from("50%"))
.height("50%")
.multi(true)
.preview(Some(String::new())) // preview should be specified to enable preview window
.preview(String::new()) // preview should be specified to enable preview window
.build()
.unwrap();

View file

@ -30,9 +30,9 @@ impl SkimItem for Item {
pub fn main() {
let options = SkimOptionsBuilder::default()
.height(String::from("50%"))
.height("50%")
.multi(true)
.preview(Some(String::new()))
.preview("")
.build()
.unwrap();
@ -40,15 +40,15 @@ pub fn main() {
tx.send(vec![
Arc::new(Item {
text: "a".to_string(),
text: "a".into(),
index: 0,
}) as Arc<dyn SkimItem>,
Arc::new(Item {
text: "b".to_string(),
text: "b".into(),
index: 1,
}) as Arc<dyn SkimItem>,
Arc::new(Item {
text: "c".to_string(),
text: "c".into(),
index: 2,
}) as Arc<dyn SkimItem>,
])

View file

@ -23,7 +23,7 @@ pub fn main() {
}
}
if &pattern == "" {
if pattern.is_empty() {
eprintln!("Usage: echo <piped_input> | fz --algo [skim|clangd] <pattern>");
exit(1);
}
@ -36,10 +36,10 @@ pub fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
if let Ok(line) = line {
if let Some((score, indices)) = matcher.fuzzy_indices(&line, &pattern) {
println!("{:8}: {}", score, wrap_matches(&line, &indices));
}
if let Ok(line) = line
&& let Some((score, indices)) = matcher.fuzzy_indices(&line, &pattern)
{
println!("{:8}: {}", score, wrap_matches(&line, &indices));
}
}
}

View file

@ -5,13 +5,13 @@ use skim::{Skim, prelude::SkimOptionsBuilder};
fn main() {
for i in 0..3 {
let opts = SkimOptionsBuilder::default()
.header(Some(format!("run {i}")))
.header(format!("run {i}"))
.build()
.unwrap();
let res = Skim::run_with(opts, None).unwrap();
println!(
"run {i}: {:?}, sleeping for 5 secs",
res.selected_items.iter().next().map(|x| x.output())
res.selected_items.first().map(|x| x.output())
);
std::thread::sleep(std::time::Duration::from_secs(5));
}

View file

@ -7,10 +7,7 @@ use std::io::Cursor;
pub fn main() {
let input = "foo 123";
let options = SkimOptionsBuilder::default()
.query(Some(String::from("f")))
.build()
.unwrap();
let options = SkimOptionsBuilder::default().query("f").build().unwrap();
let item_reader = SkimItemReader::new(SkimItemReaderOption::default().nth(vec!["2"].into_iter()).build());
let items = item_reader.of_bufread(Cursor::new(input));

View file

@ -7,11 +7,7 @@ pub fn main() {
//==================================================
// first run
let options = SkimOptionsBuilder::default()
.height(String::from("50%"))
.multi(true)
.build()
.unwrap();
let options = SkimOptionsBuilder::default().height("50%").multi(true).build().unwrap();
let input = "aaaaa\nbbbb\nccc";
let items = item_reader.of_bufread(Cursor::new(input));
let selected_items = Skim::run_with(options, Some(items))
@ -24,11 +20,7 @@ pub fn main() {
//==================================================
// second run
let options = SkimOptionsBuilder::default()
.height(String::from("50%"))
.multi(true)
.build()
.unwrap();
let options = SkimOptionsBuilder::default().height("50%").multi(true).build().unwrap();
let input = "11111\n22222\n333333333";
let items = item_reader.of_bufread(Cursor::new(input));
let selected_items = Skim::run_with(options, Some(items))

View file

@ -6,12 +6,9 @@ pub fn main() {
env_logger::init();
let options = SkimOptionsBuilder::default()
.multi(true)
.preview_fn(Some(PreviewCallback::from(|items: Vec<Arc<dyn SkimItem>>| {
items
.iter()
.map(|s| s.text().to_ascii_uppercase().into())
.collect::<Vec<_>>()
})))
.preview_fn(PreviewCallback::from(|items: Vec<Arc<dyn SkimItem>>| {
items.iter().map(|s| s.text().to_ascii_uppercase()).collect::<Vec<_>>()
}))
.build()
.unwrap();
let item_reader = SkimItemReader::default();

View file

@ -12,10 +12,7 @@ fn main() {
drop(sender); // bug replicates even without this
let _ = Skim::run_with(
SkimOptions {
multi: true,
..Default::default()
},
SkimOptionsBuilder::default().multi(true).build().unwrap(),
Some(receiver),
);
}

View file

@ -17,8 +17,8 @@ pub fn main() {
};
let options = SkimOptionsBuilder::default()
.multi(true)
.selector(Some(Rc::from(selector)))
.query(Some(String::from("skim/")))
.selector(Rc::from(selector))
.query("skim/")
.build()
.unwrap();

View file

@ -23,6 +23,6 @@ release version: (bump-version version) generate-files (changelog version) test
auto-release:
just release $(git cliff --bumped-version | sed 's/v\(.*\)/\1/')
test target="":
test target="--all-targets":
-cargo nextest run --release --features test-utils {{ target }}
tmux kill-session -t skim_e2e

View file

@ -307,12 +307,12 @@ When using skim as a library, this has no effect and ansi parsing should be enab
use skim::prelude::*;
let _options = SkimOptionsBuilder::default()
.cmd(ls \-\-color)
.cmd("ls \-\-color")
.cmd_collector(Rc::new(RefCell::new(SkimItemReader::new(
SkimItemReaderOption::default().ansi(true),
))) as Rc<RefCell<dyn CommandCollector>>)
.build()
.unwrap()
.unwrap();
.TP
\fB\-\-tabstop\fR \fI<TABSTOP>\fR [default: 8]
@ -321,9 +321,9 @@ Number of spaces that make up a tab
\fB\-\-info\fR \fI<INFO>\fR [default: default]
Set matching result count display position
hidden: do not display info
inline: display info in the same row as the input
default: display info in a dedicated row above the input
\- hidden: do not display info
\- inline: display info in the same row as the input
\- default: display info in a dedicated row above the input
.br
.br
@ -428,6 +428,7 @@ Examples:
sk \-\-delimiter : \\
\-\-preview \*(Aqbat \-\-style=numbers \-\-color=always \-\-highlight\-line {2} {1}\*(Aq \\
\-\-preview\-window +{2}\-/2
.SH SCRIPTING
.TP
\fB\-q\fR, \fB\-\-query\fR \fI<QUERY>\fR
@ -466,9 +467,7 @@ Do not enter the TUI if the query passed in \-q does not match any item
\fB\-\-sync\fR
Synchronous search for multi\-staged filtering
Synchronous search for multi\-staged filtering. If specified, skim will launch ncurses finder only after the input stream is complete.
e.g. sk \-\-multi | sk \-\-sync
Synchronous search for multi\-staged filtering. If specified, skim will launch ncurses finder only after the input stream is complete. e.g. sk \-\-multi | sk \-\-sync
.TP
\fB\-\-pre\-select\-n\fR \fI<PRE_SELECT_N>\fR [default: 0]
Pre\-select the first n items in multi\-selection mode

View file

@ -23,7 +23,7 @@ _sk() {
case "${cmd}" in
sk)
opts="-t -n -d -e -b -m -c -i -I -p -q -1 -0 -f -x -h -V --tac --min-query-length --no-sort --tiebreak --nth --with-nth --delimiter --exact --regex --algo --case --normalize --split-match --bind --multi --no-multi --no-mouse --cmd --interactive --color --no-hscroll --keep-right --skip-to-pattern --no-clear-if-empty --no-clear-start --no-clear --show-cmd-error --cycle --disabled --layout --reverse --height --no-height --min-height --margin --prompt --cmd-prompt --selector --multi-selector --ansi --tabstop --info --no-info --inline-info --header --header-lines --border --wrap --history --history-size --cmd-history --cmd-history-size --preview --preview-window --query --cmd-query --read0 --print0 --print-query --print-cmd --print-score --print-header --no-strip-ansi --select-1 --exit-0 --sync --pre-select-n --pre-select-pat --pre-select-items --pre-select-file --filter --shell --shell-bindings --man --listen --remote --tmux --log-file --flags --extended --literal --hscroll-off --filepath-word --jump-labels --no-bold --phony --expect --help --version"
opts="-t -n -d -e -b -m -c -i -I -p -q -1 -0 -f -x -h -V --tac --min-query-length --no-sort --tiebreak --nth --with-nth --delimiter --exact --regex --algo --case --normalize --split-match --bind --multi --no-multi --no-mouse --cmd --interactive --color --no-hscroll --keep-right --skip-to-pattern --no-clear-if-empty --no-clear-start --no-clear --show-cmd-error --cycle --disabled --layout --reverse --height --no-height --min-height --margin --prompt --cmd-prompt --selector --multi-selector --ansi --tabstop --info --no-info --inline-info --header --header-lines --border --wrap --history --history-size --cmd-history --cmd-history-size --preview --preview-window --query --cmd-query --read0 --print0 --print-query --print-cmd --print-score --print-header --no-strip-ansi --select-1 --exit-0 --sync --pre-select-n --pre-select-pat --pre-select-items --pre-select-file --filter --shell --shell-bindings --man --listen --remote --tmux --log-file --flags --extended --literal --hscroll-off --filepath-word --jump-labels --no-bold --phony --scheme --tail --style --no-color --padding --border-label --border-label-pos --highlight-line --wrap-sign --no-multi-line --raw --track --gap --gap-line --freeze-left --freeze-right --scroll-off --gutter --gutter-raw --marker-multi-line --ellipsis --scrollbar --no-scrollbar --list-border --list-label --list-label-pos --no-input --info-command --separator --no-separator --ghost --input-border --input-label --input-label-pos --preview-label --preview-label-pos --header-first --header-border --header-lines-border --footer --footer-border --footer-label --footer-label-pos --with-shell --expect --help --version"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -249,6 +249,146 @@ _sk() {
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--scheme)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--tail)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--style)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--padding)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--border-label)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--border-label-pos)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--wrap-sign)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--gap)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--gap-line)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--freeze-left)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--freeze-right)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--scroll-off)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--gutter)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--gutter-raw)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--marker-multi-line)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--ellipsis)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--scrollbar)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--list-border)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--list-label)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--list-label-pos)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--info-command)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--separator)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--ghost)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--input-border)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--input-label)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--input-label-pos)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--preview-label)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--preview-label-pos)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--header-border)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--header-lines-border)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--footer)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--footer-border)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--footer-label)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--footer-label-pos)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--with-shell)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--expect)
COMPREPLY=($(compgen -f "${cur}"))
return 0

View file

@ -77,8 +77,43 @@ complete -c sk -l remote -d 'Send commands to an IPC socket with optional name (
complete -c sk -l tmux -d 'Run in a tmux popup' -r
complete -c sk -l log-file -d 'Pipe log output to a file' -r
complete -c sk -l flags -d 'Feature flags' -r -f -a "no-preview-pty\t'Disable preview PTY on linux'"
complete -c sk -l hscroll-off -d 'Reserved for later use' -r
complete -c sk -l jump-labels -d 'Reserved for later use' -r
complete -c sk -l hscroll-off -r
complete -c sk -l jump-labels -r
complete -c sk -l scheme -r
complete -c sk -l tail -r
complete -c sk -l style -r
complete -c sk -l padding -r
complete -c sk -l border-label -r
complete -c sk -l border-label-pos -r
complete -c sk -l wrap-sign -r
complete -c sk -l gap -r
complete -c sk -l gap-line -r
complete -c sk -l freeze-left -r
complete -c sk -l freeze-right -r
complete -c sk -l scroll-off -r
complete -c sk -l gutter -r
complete -c sk -l gutter-raw -r
complete -c sk -l marker-multi-line -r
complete -c sk -l ellipsis -r
complete -c sk -l scrollbar -r
complete -c sk -l list-border -r
complete -c sk -l list-label -r
complete -c sk -l list-label-pos -r
complete -c sk -l info-command -r
complete -c sk -l separator -r
complete -c sk -l ghost -r
complete -c sk -l input-border -r
complete -c sk -l input-label -r
complete -c sk -l input-label-pos -r
complete -c sk -l preview-label -r
complete -c sk -l preview-label-pos -r
complete -c sk -l header-border -r
complete -c sk -l header-lines-border -r
complete -c sk -l footer -r
complete -c sk -l footer-border -r
complete -c sk -l footer-label -r
complete -c sk -l footer-label-pos -r
complete -c sk -l with-shell -r
complete -c sk -l expect -d 'Deprecated, kept for compatibility purposes. See accept() bind instead' -r
complete -c sk -l tac -d 'Show results in reverse order'
complete -c sk -l no-sort -d 'Do not sort the results'
@ -115,10 +150,19 @@ complete -c sk -s 0 -l exit-0 -d 'Do not enter the TUI if the query passed in -q
complete -c sk -l sync -d 'Synchronous search for multi-staged filtering'
complete -c sk -l shell-bindings -d 'Generate shell key bindings - only for bash, zsh and fish'
complete -c sk -l man -d 'Generate man page and output it to stdout'
complete -c sk -s x -l extended -d 'Reserved for later use'
complete -c sk -l literal -d 'Reserved for later use'
complete -c sk -l filepath-word -d 'Reserved for later use'
complete -c sk -l no-bold -d 'Reserved for later use'
complete -c sk -l phony -d 'Reserved for later use'
complete -c sk -s x -l extended
complete -c sk -l literal
complete -c sk -l filepath-word
complete -c sk -l no-bold
complete -c sk -l phony
complete -c sk -l no-color
complete -c sk -l highlight-line
complete -c sk -l no-multi-line
complete -c sk -l raw
complete -c sk -l track
complete -c sk -l no-scrollbar
complete -c sk -l no-input
complete -c sk -l no-separator
complete -c sk -l header-first
complete -c sk -s h -l help -d 'Print help (see more with \'--help\')'
complete -c sk -s V -l version -d 'Print version'

View file

@ -114,13 +114,57 @@ module completions {
--tmux: string # Run in a tmux popup
--log-file: string # Pipe log output to a file
--flags: string@"nu-complete sk flags" # Feature flags
--extended(-x) # Reserved for later use
--literal # Reserved for later use
--hscroll-off: string # Reserved for later use
--filepath-word # Reserved for later use
--jump-labels: string # Reserved for later use
--no-bold # Reserved for later use
--phony # Reserved for later use
--extended(-x)
--literal
--hscroll-off: string
--filepath-word
--jump-labels: string
--no-bold
--phony
--scheme: string
--tail: string
--style: string
--no-color
--padding: string
--border-label: string
--border-label-pos: string
--highlight-line
--wrap-sign: string
--no-multi-line
--raw
--track
--gap: string
--gap-line: string
--freeze-left: string
--freeze-right: string
--scroll-off: string
--gutter: string
--gutter-raw: string
--marker-multi-line: string
--ellipsis: string
--scrollbar: string
--no-scrollbar
--list-border: string
--list-label: string
--list-label-pos: string
--no-input
--info-command: string
--separator: string
--no-separator
--ghost: string
--input-border: string
--input-label: string
--input-label-pos: string
--preview-label: string
--preview-label-pos: string
--header-first
--header-border: string
--header-lines-border: string
--footer: string
--footer-border: string
--footer-label: string
--footer-label-pos: string
--with-shell: string
--expect: string # Deprecated, kept for compatibility purposes. See accept() bind instead
--help(-h) # Print help (see more with '--help')
--version(-V) # Print version

View file

@ -80,8 +80,43 @@ zsh\:"Zsh"))' \
'--tmux=[Run in a tmux popup]::TMUX:_default' \
'--log-file=[Pipe log output to a file]:LOG_FILE:_default' \
'*--flags=[Feature flags]:FLAGS:((no-preview-pty\:"Disable preview PTY on linux"))' \
'--hscroll-off=[Reserved for later use]:HSCROLL_OFF:_default' \
'--jump-labels=[Reserved for later use]:JUMP_LABELS:_default' \
'--hscroll-off=[]:HSCROLL_OFF:_default' \
'--jump-labels=[]:JUMP_LABELS:_default' \
'--scheme=[]:SCHEME:_default' \
'--tail=[]:TAIL:_default' \
'--style=[]:STYLE:_default' \
'--padding=[]:PADDING:_default' \
'--border-label=[]:BORDER_LABEL:_default' \
'--border-label-pos=[]:BORDER_LABEL_POS:_default' \
'--wrap-sign=[]:WRAP_SIGN:_default' \
'--gap=[]:GAP:_default' \
'--gap-line=[]:GAP_LINE:_default' \
'--freeze-left=[]:FREEZE_LEFT:_default' \
'--freeze-right=[]:FREEZE_RIGHT:_default' \
'--scroll-off=[]:SCROLL_OFF:_default' \
'--gutter=[]:GUTTER:_default' \
'--gutter-raw=[]:GUTTER_RAW:_default' \
'--marker-multi-line=[]:MARKER_MULTI_LINE:_default' \
'--ellipsis=[]:ELLIPSIS:_default' \
'--scrollbar=[]:SCROLLBAR:_default' \
'--list-border=[]:LIST_BORDER:_default' \
'--list-label=[]:LIST_LABEL:_default' \
'--list-label-pos=[]:LIST_LABEL_POS:_default' \
'--info-command=[]:INFO_COMMAND:_default' \
'--separator=[]:SEPARATOR:_default' \
'--ghost=[]:GHOST:_default' \
'--input-border=[]:INPUT_BORDER:_default' \
'--input-label=[]:INPUT_LABEL:_default' \
'--input-label-pos=[]:INPUT_LABEL_POS:_default' \
'--preview-label=[]:PREVIEW_LABEL:_default' \
'--preview-label-pos=[]:PREVIEW_LABEL_POS:_default' \
'--header-border=[]:HEADER_BORDER:_default' \
'--header-lines-border=[]:HEADER_LINES_BORDER:_default' \
'--footer=[]:FOOTER:_default' \
'--footer-border=[]:FOOTER_BORDER:_default' \
'--footer-label=[]:FOOTER_LABEL:_default' \
'--footer-label-pos=[]:FOOTER_LABEL_POS:_default' \
'--with-shell=[]:WITH_SHELL:_default' \
'--expect=[Deprecated, kept for compatibility purposes. See accept() bind instead]:EXPECT:_default' \
'--tac[Show results in reverse order]' \
'--no-sort[Do not sort the results]' \
@ -123,12 +158,21 @@ zsh\:"Zsh"))' \
'--sync[Synchronous search for multi-staged filtering]' \
'--shell-bindings[Generate shell key bindings - only for bash, zsh and fish]' \
'--man[Generate man page and output it to stdout]' \
'-x[Reserved for later use]' \
'--extended[Reserved for later use]' \
'--literal[Reserved for later use]' \
'--filepath-word[Reserved for later use]' \
'--no-bold[Reserved for later use]' \
'--phony[Reserved for later use]' \
'-x[]' \
'--extended[]' \
'--literal[]' \
'--filepath-word[]' \
'--no-bold[]' \
'--phony[]' \
'--no-color[]' \
'--highlight-line[]' \
'--no-multi-line[]' \
'--raw[]' \
'--track[]' \
'--no-scrollbar[]' \
'--no-input[]' \
'--no-separator[]' \
'--header-first[]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'-V[Print version]' \

View file

@ -2,9 +2,9 @@
//! https://github.com/llvm-mirror/clang-tools-extra/blob/master/clangd/FuzzyMatch.cpp
//!
//! # Example:
//! ```edition2018
//! use crate::fuzzy_matcher::FuzzyMatcher;
//! use crate::fuzzy_matcher::clangd::ClangdMatcher;
//! ```
//! use skim::fuzzy_matcher::FuzzyMatcher;
//! use skim::fuzzy_matcher::clangd::ClangdMatcher;
//!
//! let matcher = ClangdMatcher::default();
//!
@ -419,6 +419,38 @@ fn match_bonus(
score
}
#[allow(dead_code)]
fn print_dp(line: &str, pattern: &str, dp: &[Vec<Score>]) {
let num_line_chars = line.chars().count();
let num_pattern_chars = pattern.chars().count();
print!("\t");
for (idx, ch) in line.chars().enumerate() {
print!("\t\t{}/{}", idx + 1, ch);
}
for (row_num, row) in dp.iter().enumerate().take(num_pattern_chars + 1) {
print!("\n{}\t", row_num);
for cell in row.iter().take(num_line_chars + 1) {
print!(
"({},{})/({},{})\t",
cell.miss_score,
if cell.last_action_miss == Action::Miss {
'X'
} else {
'O'
},
cell.match_score,
if cell.last_action_match == Action::Miss {
'X'
} else {
'O'
}
);
}
}
}
#[cfg(test)]
#[cfg_attr(coverage, coverage(off))]
mod tests {
@ -474,35 +506,3 @@ mod tests {
assert_order(&matcher, "Int", &["int", "INT", "PRINT"]);
}
}
#[allow(dead_code)]
fn print_dp(line: &str, pattern: &str, dp: &[Vec<Score>]) {
let num_line_chars = line.chars().count();
let num_pattern_chars = pattern.chars().count();
print!("\t");
for (idx, ch) in line.chars().enumerate() {
print!("\t\t{}/{}", idx + 1, ch);
}
for (row_num, row) in dp.iter().enumerate().take(num_pattern_chars + 1) {
print!("\n{}\t", row_num);
for cell in row.iter().take(num_line_chars + 1) {
print!(
"({},{})/({},{})\t",
cell.miss_score,
if cell.last_action_miss == Action::Miss {
'X'
} else {
'O'
},
cell.match_score,
if cell.last_action_match == Action::Miss {
'X'
} else {
'O'
}
);
}
}
}

View file

@ -1,9 +1,9 @@
//! The fuzzy matching algorithm used by skim
//!
//! # Example:
//! ```edition2018
//! use crate::fuzzy_matcher::FuzzyMatcher;
//! use crate::fuzzy_matcher::skim::SkimMatcherV2;
//! ```
//! use skim::fuzzy_matcher::FuzzyMatcher;
//! use skim::fuzzy_matcher::skim::SkimMatcherV2;
//!
//! let matcher = SkimMatcherV2::default();
//! assert_eq!(None, matcher.fuzzy_match("abc", "abx"));

View file

@ -49,7 +49,6 @@ pub struct DefaultSkimItemMetadata {
ansi_info: Option<Vec<(usize, usize)>>,
// The ranges on which to perform matching
#[allow(clippy::box_collection)]
matching_ranges: Option<Vec<(usize, usize)>>,
}
@ -852,7 +851,7 @@ mod test {
let line = item.display(context);
// Should have multiple spans for highlighting
assert!(line.spans.len() >= 1, "Should have spans");
assert!(!line.spans.is_empty(), "Should have spans");
// At least one span should have the yellow background (the highlighted portion)
let has_highlight = line.spans.iter().any(|span| span.style.bg == Some(Color::Yellow));

View file

@ -6,6 +6,8 @@
/// # Example with Option<Type>
///
/// ```rust
/// use skim::exhaustive_match;
///
/// enum Status { Active, Inactive, Pending }
/// enum Output { Success, Failure, Unknown }
///
@ -25,6 +27,8 @@
/// # Example with plain Type
///
/// ```rust
/// use skim::exhaustive_match;
///
/// enum KeyCode { Enter, Char(char) }
///
/// fn parse(key: &str) -> KeyCode {

View file

@ -1,4 +1,3 @@
#![cfg_attr(coverage, feature(coverage_attribute))]
//! Skim is a fuzzy finder library for Rust.
//!
//! It provides a fast and customizable way to filter and select items interactively,
@ -11,7 +10,7 @@
//! use std::io::Cursor;
//!
//! let options = SkimOptionsBuilder::default()
//! .height(Some("50%"))
//! .height("50%")
//! .multi(true)
//! .build()
//! .unwrap();
@ -20,10 +19,11 @@
//! let item_reader = SkimItemReader::default();
//! let items = item_reader.of_bufread(Cursor::new(input));
//!
//! let output = Skim::run_with(&options, Some(items)).unwrap();
//! let output = Skim::run_with(options, Some(items)).unwrap();
//! ```
#![warn(missing_docs)]
#![cfg_attr(coverage, feature(coverage_attribute))]
#[macro_use]
extern crate log;

View file

@ -33,7 +33,7 @@ fn parse_delimiter_value(s: &str) -> Result<Regex, String> {
///
/// sk is a general purpose command-line fuzzy finder.
#[derive(Builder)]
#[builder(build_fn(name = "final_build"))]
#[builder(build_fn(name = "final_build"), setter(into, strip_option))]
#[builder(default)]
#[cfg_attr(feature = "cli", derive(clap::Parser))]
#[cfg_attr(
@ -410,12 +410,12 @@ pub struct SkimOptions {
/// use skim::prelude::*;
///
/// let _options = SkimOptionsBuilder::default()
/// .cmd(ls --color)
/// .cmd("ls --color")
/// .cmd_collector(Rc::new(RefCell::new(SkimItemReader::new(
/// SkimItemReaderOption::default().ansi(true),
/// ))) as Rc<RefCell<dyn CommandCollector>>)
/// .build()
/// .unwrap()
/// .unwrap();
/// ```
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display"))]
pub ansi: bool,
@ -426,12 +426,18 @@ pub struct SkimOptions {
/// Set matching result count display position
///
/// hidden: do not display info
/// inline: display info in the same row as the input
/// default: display info in a dedicated row above the input
/// - hidden: do not display info
/// - inline: display info in the same row as the input
/// - default: display info in a dedicated row above the input
#[cfg_attr(
feature = "cli",
arg(long, help_heading = "Display", value_enum, default_value = "default")
arg(
long,
help_heading = "Display",
value_enum,
default_value = "default",
verbatim_doc_comment
)
)]
pub info: InfoDisplay,
@ -546,6 +552,7 @@ pub struct SkimOptions {
/// sk --delimiter : \
/// --preview 'bat --style=numbers --color=always --highlight-line {2} {1}' \
/// --preview-window +{2}-/2
/// ```
#[cfg_attr(
feature = "cli",
arg(
@ -606,8 +613,7 @@ pub struct SkimOptions {
///
/// Synchronous search for multi-staged filtering. If specified,
/// skim will launch ncurses finder only after the input stream is complete.
///
/// e.g. sk --multi | sk --sync
/// e.g. `sk --multi | sk --sync`
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub sync: bool,
@ -695,58 +701,172 @@ pub struct SkimOptions {
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub log_file: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Scripting"))]
/// Feature flags
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Scripting"))]
pub flags: Vec<FeatureFlag>,
/// Reserved for later use
#[cfg_attr(
feature = "cli",
arg(short = 'x', long, hide = true, help_heading = "Reserved for later use")
)]
pub extended: bool,
/// Reserved for later use
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub literal: bool,
/// Reserved for later use
#[cfg_attr(
feature = "cli",
arg(long, hide = true, default_value = "10", help_heading = "Reserved for later use")
)]
pub hscroll_off: usize,
/// Reserved for later use
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub filepath_word: bool,
/// Reserved for later use
#[cfg_attr(
feature = "cli",
arg(
long,
hide = true,
default_value = "abcdefghijklmnopqrstuvwxyz",
help_heading = "Reserved for later use"
)
)]
pub jump_labels: String,
/// Reserved for later use
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub no_bold: bool,
/// Reserved for later use
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub phony: bool,
// FZF compatibility args
#[cfg_attr(feature = "cli", arg(short = 'x', long, hide = true))]
#[builder(setter(skip))]
extended: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
literal: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true, default_value = "10"))]
#[builder(setter(skip))]
hscroll_off: usize,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
filepath_word: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true, default_value = ""))]
#[builder(setter(skip))]
jump_labels: String,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_bold: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
phony: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
scheme: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
tail: Option<usize>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
style: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_color: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
padding: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
border_label: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
border_label_pos: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
highlight_line: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
wrap_sign: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_multi_line: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
raw: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
track: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
gap: Option<usize>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
gap_line: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true, default_value = "0"))]
#[builder(setter(skip))]
freeze_left: usize,
#[cfg_attr(feature = "cli", arg(long, hide = true, default_value = "0"))]
#[builder(setter(skip))]
freeze_right: usize,
#[cfg_attr(feature = "cli", arg(long, hide = true, default_value = "0"))]
#[builder(setter(skip))]
scroll_off: usize,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
gutter: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
gutter_raw: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
marker_multi_line: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
ellipsis: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
scrollbar: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_scrollbar: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
list_border: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
list_label: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
list_label_pos: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_input: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
info_command: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
separator: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
no_separator: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
ghost: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
input_border: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
input_label: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
input_label_pos: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
preview_label: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
preview_label_pos: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
header_first: bool,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
header_border: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
header_lines_border: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
footer: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
footer_border: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
footer_label: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
footer_label_pos: Option<String>,
#[cfg_attr(feature = "cli", arg(long, hide = true))]
#[builder(setter(skip))]
with_shell: Option<String>,
/// Deprecated, kept for compatibility purposes. See accept() bind instead.
#[cfg_attr(feature = "cli", arg(long, help_heading = "Deprecated", default_value = ""))]
pub expect: String,
expect: String,
/// Command collector for reading items from commands
#[cfg_attr(feature = "cli", clap(skip = Rc::new(RefCell::new(SkimItemReader::default())) as Rc<RefCell<dyn CommandCollector>>))]
#[builder(setter(into = false))]
pub cmd_collector: Rc<RefCell<dyn CommandCollector>>,
/// Query history entries loaded from history file
#[cfg_attr(feature = "cli", clap(skip))]
@ -756,6 +876,7 @@ pub struct SkimOptions {
pub cmd_history: Vec<String>,
/// Selector for pre-selecting items
#[cfg_attr(feature = "cli", clap(skip))]
#[builder(setter(into = false))]
pub selector: Option<Rc<dyn Selector>>,
/// Preview Callback
///
@ -857,6 +978,50 @@ impl Default for SkimOptions {
border: Default::default(),
no_bold: Default::default(),
phony: Default::default(),
scheme: Default::default(),
tail: Default::default(),
style: Default::default(),
no_color: Default::default(),
padding: Default::default(),
border_label: Default::default(),
border_label_pos: Default::default(),
highlight_line: Default::default(),
wrap_sign: Default::default(),
no_multi_line: Default::default(),
raw: Default::default(),
track: Default::default(),
gap: Default::default(),
gap_line: Default::default(),
freeze_left: Default::default(),
freeze_right: Default::default(),
scroll_off: Default::default(),
gutter: Default::default(),
gutter_raw: Default::default(),
marker_multi_line: Default::default(),
ellipsis: Default::default(),
scrollbar: Default::default(),
no_scrollbar: Default::default(),
list_border: Default::default(),
list_label: Default::default(),
list_label_pos: Default::default(),
no_input: Default::default(),
info_command: Default::default(),
separator: Default::default(),
no_separator: Default::default(),
ghost: Default::default(),
input_border: Default::default(),
input_label: Default::default(),
input_label_pos: Default::default(),
preview_label: Default::default(),
preview_label_pos: Default::default(),
header_first: Default::default(),
header_border: Default::default(),
header_lines_border: Default::default(),
footer: Default::default(),
footer_border: Default::default(),
footer_label: Default::default(),
footer_label_pos: Default::default(),
with_shell: Default::default(),
expect: Default::default(),
cmd_collector: Rc::new(RefCell::new(SkimItemReader::default())) as Rc<RefCell<dyn CommandCollector>>,
query_history: Default::default(),

View file

@ -628,8 +628,10 @@ mod tests {
#[test]
fn test_init_from_options() {
// Test initialization from SkimOptions
let mut opts = crate::options::SkimOptionsBuilder::default().build().unwrap();
opts.color = Some("matched:108".to_string());
let opts = crate::options::SkimOptionsBuilder::default()
.color("matched:108")
.build()
.unwrap();
let theme = ColorTheme::init_from_options(&opts);
assert_eq!(theme.matched.fg, Some(Color::Indexed(108)));
}

View file

@ -167,8 +167,7 @@ mod size_test {
#[test]
fn fixed_neg() {
let SizeParseError::ParseError(err_value, internal_error) = Size::try_from("-10").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error.kind(), &IntErrorKind::InvalidDigit);
assert_eq!(err_value, String::from("-10"));
@ -176,8 +175,7 @@ mod size_test {
#[test]
fn percent_neg() {
let SizeParseError::ParseError(err_value, internal_error) = Size::try_from("-10%").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error.kind(), &IntErrorKind::InvalidDigit);
assert_eq!(err_value, String::from("-10%"));
@ -185,16 +183,14 @@ mod size_test {
#[test]
fn percent_over_100() {
let SizeParseError::InvalidPercent(internal_error) = Size::try_from("110%").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error, 110u16);
}
#[test]
fn fixed_invalid_char() {
let SizeParseError::ParseError(value, internal_error) = Size::try_from("1-0").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error.kind(), &IntErrorKind::InvalidDigit);
assert_eq!(value, String::from("1-0"));
@ -202,8 +198,7 @@ mod size_test {
#[test]
fn percent_invalid_char() {
let SizeParseError::ParseError(value, internal_error) = Size::try_from("1-0%").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error.kind(), &IntErrorKind::InvalidDigit);
assert_eq!(value, String::from("1-0%"));
@ -211,8 +206,7 @@ mod size_test {
#[test]
fn percent_empty() {
let SizeParseError::ParseError(value, internal_error) = Size::try_from("%").unwrap_err() else {
assert!(false);
return;
panic!();
};
assert_eq!(internal_error.kind(), &IntErrorKind::Empty);
assert_eq!(value, String::from("%"));

View file

@ -97,7 +97,7 @@ mod tests {
let layout = PreviewLayout::from("left");
assert_eq!(layout.direction, Direction::Left);
assert_eq!(layout.size, Size::Percent(50)); // default
assert_eq!(layout.hidden, false);
assert!(!layout.hidden);
assert_eq!(layout.offset, None);
let layout = PreviewLayout::from("right");
@ -115,7 +115,7 @@ mod tests {
let layout = PreviewLayout::from("left:30%");
assert_eq!(layout.direction, Direction::Left);
assert_eq!(layout.size, Size::Percent(30));
assert_eq!(layout.hidden, false);
assert!(!layout.hidden);
assert_eq!(layout.offset, None);
let layout = PreviewLayout::from("right:40");
@ -155,12 +155,12 @@ mod tests {
fn test_preview_layout_with_hidden() {
let layout = PreviewLayout::from("left:hidden");
assert_eq!(layout.direction, Direction::Left);
assert_eq!(layout.hidden, true);
assert!(layout.hidden);
let layout = PreviewLayout::from("right:50%:hidden");
assert_eq!(layout.direction, Direction::Right);
assert_eq!(layout.size, Size::Percent(50));
assert_eq!(layout.hidden, true);
assert!(layout.hidden);
}
#[test]
@ -169,6 +169,6 @@ mod tests {
assert_eq!(layout.direction, Direction::Left);
assert_eq!(layout.size, Size::Percent(30));
assert_eq!(layout.offset, Some("+{2}-5".to_string()));
assert_eq!(layout.hidden, true);
assert!(layout.hidden);
}
}

View file

@ -20,7 +20,7 @@ use std::sync::Arc;
///
/// # Examples
///
/// ```
/// ```ignore
/// use skim::util::unescape_delimiter;
///
/// assert_eq!(unescape_delimiter(r"\x00"), "\0");
@ -244,7 +244,7 @@ mod test {
pattern,
&delimiter,
"{}",
items.iter().map(|x| x.clone()),
items.iter().cloned(),
Some(Arc::new("item 2")),
"query",
"cmd query",
@ -260,7 +260,7 @@ mod test {
"{+}",
&Regex::new(" ").unwrap(),
"{}",
vec![Arc::new("1"), Arc::new("2")]
[Arc::new("1"), Arc::new("2")]
.iter()
.map(|x| x.clone() as Arc<dyn SkimItem>),
Some(Arc::new("1")),

View file

@ -253,7 +253,7 @@ impl<'a> TestHarness<'a> {
let items: Vec<Arc<dyn SkimItem>> = reader
.lines()
.filter_map(|line| line.ok())
.map_while(Result::ok)
.enumerate()
.map(|(idx, s)| {
Arc::new(DefaultSkimItem::new(
@ -344,18 +344,13 @@ impl<'a> TestHarness<'a> {
std::thread::sleep(std::time::Duration::from_millis(50));
// Try to process any pending events (including PreviewReady)
loop {
match self.tui.event_rx.try_recv() {
Ok(event) => {
let is_preview_ready = matches!(event, Event::PreviewReady);
self.process_event(event)?;
// If we got PreviewReady, render and return
if is_preview_ready {
self.render()?;
return Ok(());
}
}
Err(_) => break, // No more events
while let Ok(event) = self.tui.event_rx.try_recv() {
let is_preview_ready = matches!(event, Event::PreviewReady);
self.process_event(event)?;
// If we got PreviewReady, render and return
if is_preview_ready {
self.render()?;
return Ok(());
}
}
@ -457,7 +452,7 @@ pub fn enter_interactive<'a>(options: SkimOptions) -> Result<TestHarness<'a>> {
// Run initial command with current (empty) query
if let Some(ref cmd_template) = harness.app.options.cmd.clone() {
let expanded_cmd = harness.app.expand_cmd(&cmd_template, true);
let expanded_cmd = harness.app.expand_cmd(cmd_template, true);
harness.run_command(&expanded_cmd)?;
}

View file

@ -153,7 +153,7 @@ impl TmuxController {
print!("typing `");
for key in keys {
Self::run(&["send-keys", "-t", &self.window, &key.to_string()])?;
print!("{}", key.to_string());
print!("{}", key);
}
println!("`");
Ok(())
@ -236,10 +236,10 @@ impl TmuxController {
if pred(&lines) {
return Ok(true);
}
Err(std::io::Error::new(ErrorKind::Other, "pred not matched"))
Err(std::io::Error::other("pred not matched"))
}) {
Ok(true) => Ok(()),
Ok(false) => Err(std::io::Error::new(ErrorKind::Other, self.capture()?.join("\n"))),
Ok(false) => Err(std::io::Error::other(self.capture()?.join("\n"))),
_ => Err(std::io::Error::new(
std::io::ErrorKind::TimedOut,
self.capture()?.join("\n"),

View file

@ -14,7 +14,7 @@ fn query_history() -> Result<()> {
let mut tmux = TmuxController::new()?;
let histfile = tmux.tempfile()?;
File::create(&histfile)?.write(b"a\nb\nc")?;
File::create(&histfile)?.write_all(b"a\nb\nc")?;
tmux.start_sk(Some("echo -e -n 'a\\nb\\nc'"), &["--history", &histfile])?;
tmux.until(|l| l[0].starts_with(">"))?;
@ -55,7 +55,7 @@ fn cmd_history() -> Result<()> {
let mut tmux = TmuxController::new()?;
let histfile = tmux.tempfile()?;
File::create(&histfile)?.write(b"a\nb\nc")?;
File::create(&histfile)?.write_all(b"a\nb\nc")?;
tmux.start_sk(
Some("echo -e -n 'a\\nb\\nc'"),

View file

@ -16,7 +16,7 @@ use crate::common::SK;
fn connect(name: &str) -> Result<Child> {
Command::new("/bin/sh")
.arg("-c")
.arg(&format!("{SK} --remote {name}"))
.arg(format!("{SK} --remote {name}"))
.stdin(Stdio::piped())
.spawn()
}
@ -41,7 +41,7 @@ fn setup(name: &str, extra_args: &[&str]) -> Result<(TmuxController, Child)> {
Some(&format!("echo -n -e '{}'", "a\\nb\\nc\\nd")),
&[&["--listen", &socket_name], extra_args].concat(),
)?;
tmux.until(|l| l.len() > 0 && l[0].starts_with(">"))?;
tmux.until(|l| !l.is_empty() && l[0].starts_with(">"))?;
let stream = connect(&socket_name)?;
Ok((tmux, stream))
}

View file

@ -473,11 +473,11 @@ fn opt_select_1() -> std::io::Result<()> {
let res = Command::new("/bin/sh")
.arg("-c")
.env_clear()
.arg(&format!("printf '1\n2\n3' | {SK} --select-1 -q 3"))
.arg(format!("printf '1\n2\n3' | {SK} --select-1 -q 3"))
.stdin(std::process::Stdio::null())
.output()?;
assert_eq!(res.status.code(), Some(0));
assert_eq!(res.stdout, &[b'3', b'\n']);
assert_eq!(res.stdout, b"3\n");
Ok(())
}
@ -486,7 +486,7 @@ fn opt_exit_0() -> std::io::Result<()> {
let res = Command::new("/bin/sh")
.arg("-c")
.env_clear()
.arg(&format!("printf '1\n2\n3' | {SK} --exit-0 -q 4"))
.arg(format!("printf '1\n2\n3' | {SK} --exit-0 -q 4"))
.stdin(std::process::Stdio::null())
.output()?;
assert_eq!(res.status.code(), Some(1));

View file

@ -51,7 +51,7 @@ sk_test!(opt_read0, "a\\0b\\0c", &["--read0"], {
sk_test!(opt_print0, "a\\nb\\nc", &["-m", "--print0"], {
@lines |l| (l.len() > 4);
@keys BTab, BTab, Enter;
@lines |l| (l.len() > 0 && !l[0].starts_with(">"));
@lines |l| (!l.is_empty() && !l[0].starts_with(">"));
@output[0] trim().eq("a\0b\0");
});
@ -152,8 +152,8 @@ sk_test!(opt_reserved_options, "a\\nb", &[], tmux => {
for option in reserved_options {
println!("Starting sk with opt {}", option);
let mut tmux = TmuxController::new()?;
tmux.start_sk(Some(&format!("echo -n -e 'a\\nb'")), &[option])?;
tmux.until(|l| l.len() > 0 && l[0].starts_with(">"))?;
tmux.start_sk(Some("echo -n -e 'a\\nb'"), &[option])?;
tmux.until(|l| !l.is_empty() && l[0].starts_with(">"))?;
}
});
@ -197,8 +197,8 @@ sk_test!(opt_multiple_flags_basic, "a\\nb", &[], tmux => {
for cmd_flags in basic_flags {
let mut tmux = TmuxController::new()?;
tmux.start_sk(Some(&format!("echo -n -e 'a\\nb'")), &[cmd_flags])?;
tmux.until(|l| l.len() > 0 && l[0].starts_with(">"))?;
tmux.start_sk(Some("echo -n -e 'a\\nb'"), &[cmd_flags])?;
tmux.until(|l| !l.is_empty() && l[0].starts_with(">"))?;
}
});
@ -207,10 +207,10 @@ use tempfile::NamedTempFile;
sk_test!(opt_pre_select_file, "a\\nb\\nc", &[], tmux => {
let mut pre_select_file = NamedTempFile::new()?;
pre_select_file.write(b"b\nc")?;
pre_select_file.write_all(b"b\nc")?;
let mut tmux = TmuxController::new()?;
tmux.start_sk(
Some(&format!("echo -n -e 'a\\nb\\nc'")),
Some("echo -n -e 'a\\nb\\nc'"),
&["-m", "--pre-select-file", pre_select_file.path().to_str().unwrap()],
)?;
tmux.until(|l| l.len() > 4 && l[2] == "> a" && l[3].trim() == ">b" && l[4].trim() == ">c")?;