fix: compile without the cli feature (#834)

* fix: compile without the cli feature

* chore: clippy

* chore: fmt
This commit is contained in:
LoricAndre 2025-08-09 19:07:13 +02:00 committed by GitHub
parent 706620c5b7
commit cbd1765881
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 324 additions and 202 deletions

View file

@ -24,26 +24,26 @@ impl Display for TuikitError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
TuikitError::UnknownSequence(sequence) => {
write!(f, "unsupported esc sequence: {}", sequence)
write!(f, "unsupported esc sequence: {sequence}")
}
TuikitError::NoCursorReportResponse => {
write!(f, "buffer did not contain cursor position response")
}
TuikitError::IndexOutOfBound(row, col) => {
write!(f, "({}, {}) is out of bound", row, col)
write!(f, "({row}, {col}) is out of bound")
}
TuikitError::Timeout(duration) => write!(f, "timeout with duration: {:?}", duration),
TuikitError::Timeout(duration) => write!(f, "timeout with duration: {duration:?}"),
TuikitError::Interrupted => write!(f, "interrupted"),
TuikitError::TerminalNotStarted => {
write!(f, "terminal not started, call `restart` to start it")
}
TuikitError::DrawError(error) => write!(f, "draw error: {}", error),
TuikitError::SendEventError(error) => write!(f, "send event error: {}", error),
TuikitError::FromUtf8Error(error) => write!(f, "{}", error),
TuikitError::ParseIntError(error) => write!(f, "{}", error),
TuikitError::IOError(error) => write!(f, "{}", error),
TuikitError::NixError(error) => write!(f, "{}", error),
TuikitError::ChannelReceiveError(error) => write!(f, "{}", error),
TuikitError::DrawError(error) => write!(f, "draw error: {error}"),
TuikitError::SendEventError(error) => write!(f, "send event error: {error}"),
TuikitError::FromUtf8Error(error) => write!(f, "{error}"),
TuikitError::ParseIntError(error) => write!(f, "{error}"),
TuikitError::IOError(error) => write!(f, "{error}"),
TuikitError::NixError(error) => write!(f, "{error}"),
TuikitError::ChannelReceiveError(error) => write!(f, "{error}"),
}
}
}

View file

@ -116,7 +116,7 @@ impl KeyBoard {
}
fn next_byte_timeout(&mut self, timeout: Duration) -> Result<u8> {
trace!("next_byte_timeout: timeout: {:?}", timeout);
trace!("next_byte_timeout: timeout: {timeout:?}");
if self.byte_buf.is_empty() {
self.fetch_bytes(timeout)?;
}
@ -131,7 +131,7 @@ impl KeyBoard {
}
fn next_char_timeout(&mut self, timeout: Duration) -> Result<char> {
trace!("next_char_timeout: timeout: {:?}", timeout);
trace!("next_char_timeout: timeout: {timeout:?}");
if self.byte_buf.is_empty() {
self.fetch_bytes(timeout)?;
}
@ -236,7 +236,7 @@ impl KeyBoard {
/// Wait `timeout` until next key stroke
fn next_raw_key_timeout(&mut self, timeout: Duration) -> Result<Key> {
trace!("next_raw_key_timeout: {:?}", timeout);
trace!("next_raw_key_timeout: {timeout:?}");
let ch = self.next_char_timeout(timeout)?;
match ch {
'\u{00}' => Ok(Ctrl(' ')),
@ -287,7 +287,7 @@ impl KeyBoard {
match self.next_byte_timeout(KEY_WAIT) {
Ok(b'[') => {}
Ok(c) => {
return Err(TuikitError::UnknownSequence(format!("ESC ESC {}", c)));
return Err(TuikitError::UnknownSequence(format!("ESC ESC {c}")));
}
Err(_) => return Ok(ESC),
}
@ -342,7 +342,7 @@ impl KeyBoard {
let seq2 = self.next_byte_timeout(KEY_WAIT)?;
match seq2 {
b'0' | b'9' => Err(TuikitError::UnknownSequence(format!("ESC [ {:x?}", seq2))),
b'0' | b'9' => Err(TuikitError::UnknownSequence(format!("ESC [ {seq2:x?}"))),
b'1'..=b'8' => self.extended_escape(seq2),
b'[' => {
// Linux Console ESC [ [ _
@ -353,7 +353,7 @@ impl KeyBoard {
b'C' => Ok(F(3)),
b'D' => Ok(F(4)),
b'E' => Ok(F(5)),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ [ {:x?}", seq3))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ [ {seq3:x?}"))),
}
}
b'A' => Ok(Up), // kcuu1
@ -386,7 +386,7 @@ impl KeyBoard {
}
2 => Ok(MousePress(MouseButton::Right, cy, cx)),
3 => Ok(MouseRelease(cy, cx)),
_ => Err(TuikitError::UnknownSequence(format!("ESC M {:?}{:?}{:?}", cb, cx, cy))),
_ => Err(TuikitError::UnknownSequence(format!("ESC M {cb:?}{cx:?}{cy:?}"))),
}
}
b'<' => {
@ -420,21 +420,21 @@ impl KeyBoard {
64 => MouseButton::WheelUp,
65 => MouseButton::WheelDown,
_ => {
return Err(TuikitError::UnknownSequence(format!("ESC [ < {} {}", str_buf, c)));
return Err(TuikitError::UnknownSequence(format!("ESC [ < {str_buf} {c}")));
}
};
match c {
'M' => Ok(MousePress(button, cy, cx)),
'm' => Ok(MouseRelease(cy, cx)),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ < {} {}", str_buf, c))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ < {str_buf} {c}"))),
}
}
32 => Ok(MouseHold(cy, cx)),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ < {} {}", str_buf, c))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ < {str_buf} {c}"))),
}
}
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {:?}", seq2))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {seq2:?}"))),
}
}
@ -465,7 +465,7 @@ impl KeyBoard {
}
}
return Err(TuikitError::NoCursorReportResponse);
Err(TuikitError::NoCursorReportResponse)
}
fn extended_escape(&mut self, seq2: u8) -> Result<Key> {
@ -478,7 +478,7 @@ impl KeyBoard {
b'4' | b'8' => Ok(End), // tmux, xrvt
b'5' => Ok(PageUp), // kpp
b'6' => Ok(PageDown), // knp
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {} ~", seq2))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {seq2} ~"))),
}
} else if seq3.is_ascii_digit() {
let mut str_buf = String::new();
@ -508,7 +508,7 @@ impl KeyBoard {
35 => Ok(MouseRelease(cy, cx)),
64 => Ok(MouseHold(cy, cx)),
96 | 97 => Ok(MousePress(MouseButton::WheelUp, cy, cx)),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {} M", str_buf))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {str_buf} M"))),
}
}
b'~' => {
@ -519,7 +519,7 @@ impl KeyBoard {
v @ 23..=24 => Ok(F(v - 12)),
200 => Ok(BracketedPasteStart),
201 => Ok(BracketedPasteEnd),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {} ~", str_buf))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {str_buf} ~"))),
}
}
_ => unreachable!(),
@ -544,19 +544,15 @@ impl KeyBoard {
(b'2', b'B') => Ok(ShiftDown),
(b'2', b'C') => Ok(ShiftRight),
(b'2', b'D') => Ok(ShiftLeft),
_ => Err(TuikitError::UnknownSequence(format!(
"ESC [ 1 ; {:x?} {:x?}",
seq4, seq5
))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ 1 ; {seq4:x?} {seq5:x?}"))),
}
} else {
Err(TuikitError::UnknownSequence(format!(
"ESC [ {:x?} ; {:x?} {:x?}",
seq2, seq4, seq5
"ESC [ {seq2:x?} ; {seq4:x?} {seq5:x?}"
)))
}
} else {
Err(TuikitError::UnknownSequence(format!("ESC [ {:x?} ; {:x?}", seq2, seq4)))
Err(TuikitError::UnknownSequence(format!("ESC [ {seq2:x?} ; {seq4:x?}")))
}
} else {
match (seq2, seq3) {
@ -564,7 +560,7 @@ impl KeyBoard {
(b'5', b'B') => Ok(CtrlDown),
(b'5', b'C') => Ok(CtrlRight),
(b'5', b'D') => Ok(CtrlLeft),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {:x?} {:x?}", seq2, seq3))),
_ => Err(TuikitError::UnknownSequence(format!("ESC [ {seq2:x?} {seq3:x?}"))),
}
}
}
@ -587,7 +583,7 @@ impl KeyBoard {
b'b' => Ok(CtrlDown),
b'c' => Ok(CtrlRight), // rxvt
b'd' => Ok(CtrlLeft), // rxvt
_ => Err(TuikitError::UnknownSequence(format!("ESC O {:x?}", seq2))),
_ => Err(TuikitError::UnknownSequence(format!("ESC O {seq2:x?}"))),
}
}
}

View file

@ -89,7 +89,7 @@ impl Output {
}
let title = title.replace("\x1b", "").replace("\x07", "");
self.write_raw(format!("\x1b]2;{}\x07", title).as_bytes());
self.write_raw(format!("\x1b]2;{title}\x07").as_bytes());
}
/// Clear title again. (or restore previous title.)
@ -164,7 +164,7 @@ impl Output {
self.write_cap_with_params("setaf", &[Param::Number(x as i32)]);
}
Color::Rgb(r, g, b) => {
self.write_raw(format!("\x1b[38;2;{};{};{}m", r, g, b).as_bytes());
self.write_raw(format!("\x1b[38;2;{r};{g};{b}m").as_bytes());
}
}
}
@ -179,7 +179,7 @@ impl Output {
self.write_cap_with_params("setab", &[Param::Number(x as i32)]);
}
Color::Rgb(r, g, b) => {
self.write_raw(format!("\x1b[48;2;{};{};{}m", r, g, b).as_bytes());
self.write_raw(format!("\x1b[48;2;{r};{g};{b}m").as_bytes());
}
}
}

View file

@ -286,7 +286,7 @@ impl<UserEvent: Send + 'static> Term<UserEvent> {
debug!("key listener start");
loop {
let next_key = keyboard.next_key();
trace!("next key: {:?}", next_key);
trace!("next key: {next_key:?}");
match next_key {
Ok(key) => {
let event_tx = event_tx_clone.lock();

View file

@ -5,11 +5,11 @@ use skim::prelude::*;
// This example only produce friendly print statements!
fn fake_delete_item(item: &str) {
println!("Deleting item `{}`...", item);
println!("Deleting item `{item}`...");
}
fn fake_create_item(item: &str) {
println!("Creating a new item `{}`...", item);
println!("Creating a new item `{item}`...");
}
pub fn main() {

View file

@ -64,6 +64,6 @@ pub fn main() {
.collect::<Vec<Item>>();
for item in selected_items {
println!("{:?}", item);
println!("{item:?}");
}
}

View file

@ -34,16 +34,16 @@ impl Perform for ANSIParser {
// put back \0 \r \n \t
0x00 | 0x0d | 0x0A | 0x09 => self.partial_str.push(byte as char),
// ignore all others
_ => trace!("AnsiParser:execute ignored {:?}", byte),
_ => trace!("AnsiParser:execute ignored {byte:?}"),
}
}
fn hook(&mut self, params: &Params, _intermediates: &[u8], _ignore: bool, _action: char) {
trace!("AnsiParser:hook ignored {:?}", params);
trace!("AnsiParser:hook ignored {params:?}");
}
fn put(&mut self, byte: u8) {
trace!("AnsiParser:put ignored {:?}", byte);
trace!("AnsiParser:put ignored {byte:?}");
}
fn unhook(&mut self) {
@ -51,7 +51,7 @@ impl Perform for ANSIParser {
}
fn osc_dispatch(&mut self, params: &[&[u8]], _bell_terminated: bool) {
trace!("AnsiParser:osc ignored {:?}", params);
trace!("AnsiParser:osc ignored {params:?}");
}
fn csi_dispatch(&mut self, params: &Params, _intermediates: &[u8], _ignore: bool, action: char) {
@ -59,7 +59,7 @@ impl Perform for ANSIParser {
// Only care about graphic modes, ignore all others
if action != 'm' {
trace!("ignore: params: {:?}, action : {:?}", params, action);
trace!("ignore: params: {params:?}, action : {action:?}");
return;
}
@ -86,7 +86,7 @@ impl Perform for ANSIParser {
let (r, g, b) = match (iter.next(), iter.next(), iter.next()) {
(Some(r), Some(g), Some(b)) => (r[0] as u8, g[0] as u8, b[0] as u8),
_ => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
continue;
}
};
@ -98,7 +98,7 @@ impl Perform for ANSIParser {
let color = match iter.next() {
Some(color) => color[0] as u8,
None => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
continue;
}
};
@ -106,7 +106,7 @@ impl Perform for ANSIParser {
attr.fg = Color::AnsiValue(color);
}
_ => {
trace!("error on parsing CSI {:?} m", params);
trace!("error on parsing CSI {params:?} m");
}
},
39 => attr.fg = Color::Default,
@ -117,7 +117,7 @@ impl Perform for ANSIParser {
let (r, g, b) = match (iter.next(), iter.next(), iter.next()) {
(Some(r), Some(g), Some(b)) => (r[0] as u8, g[0] as u8, b[0] as u8),
_ => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
continue;
}
};
@ -129,7 +129,7 @@ impl Perform for ANSIParser {
let color = match iter.next() {
Some(color) => color[0] as u8,
None => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
continue;
}
};
@ -137,14 +137,14 @@ impl Perform for ANSIParser {
attr.bg = Color::AnsiValue(color);
}
_ => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
}
},
49 => attr.bg = Color::Default,
num @ 90..=97 => attr.fg = Color::AnsiValue((num - 82) as u8),
num @ 100..=107 => attr.bg = Color::AnsiValue((num - 92) as u8),
_ => {
trace!("ignore CSI {:?} m", params);
trace!("ignore CSI {params:?} m");
}
}
}

View file

@ -44,7 +44,7 @@ impl Display for OrEngine {
"(Or: {})",
self.engines
.iter()
.map(|e| format!("{}", e))
.map(|e| format!("{e}"))
.collect::<Vec<_>>()
.join(", ")
)
@ -118,7 +118,7 @@ impl Display for AndEngine {
"(And: {})",
self.engines
.iter()
.map(|e| format!("{}", e))
.map(|e| format!("{e}"))
.collect::<Vec<_>>()
.join(", ")
)

View file

@ -234,39 +234,39 @@ mod test {
use super::*;
let exact_or_fuzzy = ExactOrFuzzyEngineFactory::builder().build();
let x = exact_or_fuzzy.create_engine("'abc");
assert_eq!(format!("{}", x), "(Exact|(?i)abc)");
assert_eq!(format!("{x}"), "(Exact|(?i)abc)");
let x = exact_or_fuzzy.create_engine("^abc");
assert_eq!(format!("{}", x), "(Exact|(?i)^abc)");
assert_eq!(format!("{x}"), "(Exact|(?i)^abc)");
let x = exact_or_fuzzy.create_engine("abc$");
assert_eq!(format!("{}", x), "(Exact|(?i)abc$)");
assert_eq!(format!("{x}"), "(Exact|(?i)abc$)");
let x = exact_or_fuzzy.create_engine("^abc$");
assert_eq!(format!("{}", x), "(Exact|(?i)^abc$)");
assert_eq!(format!("{x}"), "(Exact|(?i)^abc$)");
let x = exact_or_fuzzy.create_engine("!abc");
assert_eq!(format!("{}", x), "(Exact|!(?i)abc)");
assert_eq!(format!("{x}"), "(Exact|!(?i)abc)");
let x = exact_or_fuzzy.create_engine("!^abc");
assert_eq!(format!("{}", x), "(Exact|!(?i)^abc)");
assert_eq!(format!("{x}"), "(Exact|!(?i)^abc)");
let x = exact_or_fuzzy.create_engine("!abc$");
assert_eq!(format!("{}", x), "(Exact|!(?i)abc$)");
assert_eq!(format!("{x}"), "(Exact|!(?i)abc$)");
let x = exact_or_fuzzy.create_engine("!^abc$");
assert_eq!(format!("{}", x), "(Exact|!(?i)^abc$)");
assert_eq!(format!("{x}"), "(Exact|!(?i)^abc$)");
let regex_factory = RegexEngineFactory::builder();
let and_or_factory = AndOrEngineFactory::new(exact_or_fuzzy);
let x = and_or_factory.create_engine("'abc | def ^gh ij | kl mn");
assert_eq!(
format!("{}", x),
format!("{x}"),
"(Or: (And: (Exact|(?i)abc)), (And: (Fuzzy: def), (Exact|(?i)^gh), (Fuzzy: ij)), (And: (Fuzzy: kl), (Fuzzy: mn)))"
);
let x = regex_factory.create_engine("'abc | def ^gh ij | kl mn");
assert_eq!(format!("{}", x), "(Regex: 'abc | def ^gh ij | kl mn)");
assert_eq!(format!("{x}"), "(Regex: 'abc | def ^gh ij | kl mn)");
}
}

View file

@ -2,7 +2,6 @@ use std::cmp::min;
use std::fmt::{Display, Error, Formatter};
use std::sync::Arc;
use clap::ValueEnum;
use fuzzy_matcher::FuzzyMatcher;
use fuzzy_matcher::clangd::ClangdMatcher;
use fuzzy_matcher::skim::SkimMatcherV2;
@ -12,8 +11,9 @@ use crate::{CaseMatching, MatchEngine};
use crate::{MatchRange, MatchResult, SkimItem};
//------------------------------------------------------------------------------
#[derive(ValueEnum, Debug, Copy, Clone, Default)]
#[clap(rename_all = "snake_case")]
#[derive(Debug, Copy, Clone, Default)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
#[cfg_attr(feature = "cli", clap(rename_all = "snake_case"))]
pub enum FuzzyAlgorithm {
SkimV1,
#[default]
@ -136,7 +136,7 @@ impl MatchEngine for FuzzyEngine {
let (score, matched_range) = matched_result.unwrap();
trace!("matched range {:?}", matched_range);
trace!("matched range {matched_range:?}");
let begin = *matched_range.first().unwrap_or(&0);
let end = *matched_range.last().unwrap_or(&0);

View file

@ -13,7 +13,7 @@ pub struct DefaultSkimSelector {
impl DefaultSkimSelector {
pub fn first_n(mut self, first_n: usize) -> Self {
trace!("select first_n: {}", first_n);
trace!("select first_n: {first_n}");
self.first_n = first_n;
self
}
@ -30,7 +30,7 @@ impl DefaultSkimSelector {
}
pub fn regex(mut self, regex: &str) -> Self {
trace!("select regex: {}", regex);
trace!("select regex: {regex}");
if !regex.is_empty() {
self.regex = Regex::new(regex).ok();
}

View file

@ -62,9 +62,9 @@ impl Input {
// key_action is comma separated: 'ctrl-j:accept,ctrl-k:kill-line'
pub fn parse_keymap(&mut self, key_action: &str) {
debug!("got key_action: {:?}", key_action);
debug!("got key_action: {key_action:?}");
for (key, action_chain) in parse_key_action(key_action).into_iter() {
debug!("parsed key_action: {:?}: {:?}", key, action_chain);
debug!("parsed key_action: {key:?}: {action_chain:?}");
let action_chain = action_chain
.into_iter()
.filter_map(|(action, arg)| parse_event(action, arg))
@ -102,12 +102,12 @@ pub fn parse_key_action(key_action: &str) -> Vec<KeyActions> {
RE.captures_iter(key_action)
.map(|caps| {
debug!("RE: caps: {:?}", caps);
debug!("RE: caps: {caps:?}");
let key = caps.get(1).unwrap().as_str();
let actions = RE_BIND
.captures_iter(caps.get(2).unwrap().as_str())
.map(|caps| {
debug!("RE_BIND: caps: {:?}", caps);
debug!("RE_BIND: caps: {caps:?}");
(
caps.get(1).unwrap().as_str(),
caps.get(2).map(|s| {
@ -130,7 +130,7 @@ pub fn parse_key_action(key_action: &str) -> Vec<KeyActions> {
/// e.g. execute(...) => Some(Event::EvActExecute, Box::new(Option("...")))
pub fn parse_action_arg(action_arg: &str) -> Option<Event> {
// construct a fake key_action: `fake_key:action(arg)`
let fake_key_action = format!("fake_key:{}", action_arg);
let fake_key_action = format!("fake_key:{action_arg}");
// get keys: [(key, [(action, arg), (action, arg)]), ...]
let keys = parse_key_action(&fake_key_action);
// only get the first key(since it is faked), and get the first action
@ -207,7 +207,7 @@ mod test {
{}
FZF-EOF";
let key_action_str = format!("ctrl-s:toggle-sort,ctrl-m:execute:{},ctrl-t:toggle", cmd);
let key_action_str = format!("ctrl-s:toggle-sort,ctrl-m:execute:{cmd},ctrl-t:toggle");
let key_action = parse_key_action(&key_action_str);
assert_eq!(("ctrl-s", vec![("toggle-sort", None)]), key_action[0]);

View file

@ -6,7 +6,9 @@ use std::ops::Deref;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
#[cfg(feature = "cli")]
use clap::ValueEnum;
#[cfg(feature = "cli")]
use clap::builder::PossibleValue;
use crate::spinlock::{SpinLock, SpinLockGuard};
@ -62,7 +64,7 @@ impl RankBuilder {
rank[priority] = value;
}
trace!("ranks: {:?}", rank);
trace!("ranks: {rank:?}");
rank
}
}
@ -176,7 +178,7 @@ impl ItemPool {
/// append the items and return the new_size of the pool
pub fn append(&self, mut items: Vec<Arc<dyn SkimItem>>) -> usize {
let len = items.len();
trace!("item pool, append {} items", len);
trace!("item pool, append {len} items");
let mut pool = self.pool.lock();
let mut header_items = self.reserved_items.lock();
@ -189,7 +191,7 @@ impl ItemPool {
pool.append(&mut items);
}
self.length.store(pool.len(), Ordering::SeqCst);
trace!("item pool, done append {} items", len);
trace!("item pool, done append {len} items");
pool.len()
}
@ -233,6 +235,7 @@ pub enum RankCriteria {
NegIndex,
}
#[cfg(feature = "cli")]
impl ValueEnum for RankCriteria {
fn value_variants<'a>() -> &'a [Self] {
use RankCriteria::*;

View file

@ -8,7 +8,6 @@ use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;
use clap::ValueEnum;
use crossbeam::channel::{Receiver, Sender};
use skim_tuikit::prelude::{Event as TermEvent, *};
@ -234,8 +233,9 @@ pub enum ItemPreview {
//==============================================================================
// A match engine will execute the matching algorithm
#[derive(ValueEnum, Eq, PartialEq, Debug, Copy, Clone, Default)]
#[clap(rename_all = "snake_case")]
#[derive(Eq, PartialEq, Debug, Copy, Clone, Default)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
#[cfg_attr(feature = "cli", clap(rename_all = "snake_case"))]
pub enum CaseMatching {
Respect,
Ignore,

View file

@ -72,7 +72,7 @@ impl Matcher {
C: Fn(Arc<SpinLock<Vec<MatchedItem>>>) + Send + 'static,
{
let matcher_engine = self.engine_factory.create_engine_with_case(query, self.case_matching);
debug!("engine: {}", matcher_engine);
debug!("engine: {matcher_engine}");
let stopped = Arc::new(AtomicBool::new(false));
let stopped_clone = stopped.clone();
let processed = Arc::new(AtomicUsize::new(0));

View file

@ -459,7 +459,7 @@ impl Model {
let item = self.selection.get_current_item();
if depends_on_items(cmd) && item.is_none() {
debug!("act_execute: command refers to items and there is no item for now");
debug!("command to execute: [{}]", cmd);
debug!("command to execute: [{cmd}]");
return;
}
@ -473,7 +473,7 @@ impl Model {
let current_item = self.selection.get_current_item();
if depends_on_items(cmd) && current_item.is_none() {
debug!("act_execute_silent: command refers to items and there is no item for now");
debug!("command to execute: [{}]", cmd);
debug!("command to execute: [{cmd}]");
return;
}
@ -505,7 +505,7 @@ impl Model {
Some(s) => s,
None => self.query.get_cmd(),
};
debug!("command to execute: [{}]", cmd);
debug!("command to execute: [{cmd}]");
let mut env = ModelEnv {
cmd: cmd.to_string(),
cmd_query: self.query.get_cmd_query(),
@ -563,7 +563,7 @@ impl Model {
loop {
let (key, ev) = next_event.take().or_else(|| self.rx.recv().ok())?;
debug!("handle event: {:?}", ev);
debug!("handle event: {ev:?}");
match ev {
Event::EvHeartBeat => {

View file

@ -1,4 +1,6 @@
#[cfg(feature = "cli")]
use clap::ValueEnum;
#[cfg(feature = "cli")]
use clap::builder::PossibleValue;
#[derive(Debug, Clone, Default, Eq, PartialEq)]
@ -9,6 +11,7 @@ pub enum InfoDisplay {
Hidden,
}
#[cfg(feature = "cli")]
impl ValueEnum for InfoDisplay {
fn value_variants<'a>() -> &'a [Self] {
use InfoDisplay::*;

View file

@ -1,6 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
#[cfg(feature = "cli")]
use clap::Parser;
use derive_builder::Builder;
@ -82,20 +83,20 @@ use crate::{CaseMatching, FuzzyAlgorithm, Selector};
#[derive(Builder)]
#[builder(build_fn(name = "final_build"))]
#[builder(default)]
#[derive(Parser)]
#[command(name = "sk", args_override_self = true, version)]
#[cfg_attr(feature = "cli", derive(Parser))]
#[cfg_attr(feature = "cli", command(name = "sk", args_override_self = true, version))]
pub struct SkimOptions {
// --- Search ---
/// Show results in reverse order
///
/// *Often used in combination with `--no-sort`*
#[arg(long, help_heading = "Search")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Search"))]
pub tac: bool,
/// Minimum query length to start showing results
///
/// Only show results when the query is at least this many characters long
#[arg(long, help_heading = "Search")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Search"))]
pub min_query_length: Option<usize>,
/// Do not sort the results
@ -103,7 +104,7 @@ pub struct SkimOptions {
/// *Often used in combination with `--tac`*
///
/// **Example**: `history | sk --tac --no-sort`
#[arg(long, help_heading = "Search")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Search"))]
pub no_sort: bool,
/// Comma-separated list of sort criteria to apply when the scores are tied.
@ -123,13 +124,16 @@ pub struct SkimOptions {
/// * Each criterion could be negated, e.g. (-index)
///
/// * Each criterion should appear only once in the list
#[arg(
short,
long,
default_value = "score,begin,end",
value_enum,
value_delimiter = ',',
help_heading = "Search"
#[cfg_attr(
feature = "cli",
arg(
short,
long,
default_value = "score,begin,end",
value_enum,
value_delimiter = ',',
help_heading = "Search"
)
)]
pub tiebreak: Vec<RankCriteria>,
@ -155,27 +159,36 @@ pub struct SkimOptions {
/// * `..-3`: From the 1st field to the 3rd to the last field
///
/// * `..`: All the fields
#[arg(short, long, default_value = "", help_heading = "Search", value_delimiter = ',')]
#[cfg_attr(
feature = "cli",
arg(short, long, default_value = "", help_heading = "Search", value_delimiter = ',')
)]
pub nth: Vec<String>,
/// Fields to be transformed
///
/// See **nth** for the details
#[arg(long, default_value = "", help_heading = "Search", value_delimiter = ',')]
#[cfg_attr(
feature = "cli",
arg(long, default_value = "", help_heading = "Search", value_delimiter = ',')
)]
pub with_nth: Vec<String>,
/// Delimiter between fields
///
/// In regex format, default to AWK-style
#[arg(short, long, default_value = r"[\t\n ]+", help_heading = "Search")]
#[cfg_attr(
feature = "cli",
arg(short, long, default_value = r"[\t\n ]+", help_heading = "Search")
)]
pub delimiter: String,
/// Run in exact mode
#[arg(short, long, help_heading = "Search")]
#[cfg_attr(feature = "cli", arg(short, long, help_heading = "Search"))]
pub exact: bool,
/// Start in regex mode instead of fuzzy-match
#[arg(long, help_heading = "Search")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Search"))]
pub regex: bool,
/// Fuzzy matching algorithm
@ -185,13 +198,19 @@ pub struct SkimOptions {
/// * **skim_v1**: Legacy skim algorithm
///
/// * **clangd**: Used in clangd for keyword completion
#[arg(long = "algo", default_value = "skim_v2", value_enum, help_heading = "Search")]
#[cfg_attr(
feature = "cli",
arg(long = "algo", default_value = "skim_v2", value_enum, help_heading = "Search")
)]
pub algorithm: FuzzyAlgorithm,
/// Case sensitivity
///
/// Determines whether or not to ignore case while matching
#[arg(long, default_value = "smart", value_enum, help_heading = "Search")]
#[cfg_attr(
feature = "cli",
arg(long, default_value = "smart", value_enum, help_heading = "Search")
)]
pub case: CaseMatching,
// --- Interface ---
@ -429,35 +448,38 @@ pub struct SkimOptions {
///
/// If the query is empty, skim will execute abort action, otherwise execute delete-char action. It
/// is equal to delete-char/eof.
#[arg(short, long, help_heading = "Interface", value_delimiter = ',')]
#[cfg_attr(feature = "cli", arg(short, long, help_heading = "Interface", value_delimiter = ','))]
pub bind: Vec<String>,
/// Enable multiple selection
///
/// Uses Tab and S-Tab by default for selection
#[arg(short, long, overrides_with = "no_multi", help_heading = "Interface")]
#[cfg_attr(
feature = "cli",
arg(short, long, overrides_with = "no_multi", help_heading = "Interface")
)]
pub multi: bool,
/// Disable multiple selection
#[arg(long, conflicts_with = "multi", help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, conflicts_with = "multi", help_heading = "Interface"))]
pub no_multi: bool,
/// Disable mouse
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub no_mouse: bool,
/// Command to invoke dynamically in interactive mode
///
/// Will be invoked using `sh -c`
#[arg(short, long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(short, long, help_heading = "Interface"))]
pub cmd: Option<String>,
/// Run in interactive mode
#[arg(short, long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(short, long, help_heading = "Interface"))]
pub interactive: bool,
/// Replace replstr with the selected item in commands
#[arg(short = 'I', default_value = "{}", help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(short = 'I', default_value = "{}", help_heading = "Interface"))]
pub replstr: String,
/// Set color theme
@ -506,17 +528,17 @@ pub struct SkimOptions {
/// - `--color=current_bg:24`: Default scheme with custom current line background
/// - `--color=dark,matched:#00FF00`: Green matched text on dark theme
/// - `--color=fg:#FFFFFF,bg:#000000`: Custom white-on-black color scheme
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub color: Option<String>,
/// Disable horizontal scroll
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub no_hscroll: bool,
/// Keep the right end of the line visible on overflow
///
/// Effective only when the query string is empty
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub keep_right: bool,
/// Show the matched pattern at the line start
@ -525,7 +547,7 @@ pub struct SkimOptions {
/// string is empty. Was designed to skip showing starts of paths of rg/grep results.
///
/// **Example**: `sk -i -c "rg {} --color=always" --skip-to-pattern '[^/]*:' --ansi`
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub skip_to_pattern: Option<String>,
/// Do not clear previous line if the command returns an empty result
@ -536,11 +558,11 @@ pub struct SkimOptions {
/// This is not the default behavior because similar use cases for grep and rg have already been op
/// timized where empty query results actually mean "empty" and previous results should be
/// cleared.
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub no_clear_if_empty: bool,
/// Do not clear items on start
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub no_clear_start: bool,
/// Do not clear screen on exit
@ -548,11 +570,11 @@ pub struct SkimOptions {
/// Do not clear finder interface on exit. If skim was started in full screen mode, it will not switch back to the
/// original screen, so you'll have to manually run tput rmcup to return. This option can be used to avoid
/// flickering of the screen when your application needs to start skim multiple times in order.
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub no_clear: bool,
/// Show error message if command fails
#[arg(long, help_heading = "Interface")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Interface"))]
pub show_cmd_error: bool,
// --- Layout ---
@ -563,28 +585,28 @@ pub struct SkimOptions {
/// *reverse: Display from the top of the screen
///
/// *reverse-list: Display from the top of the screen, prompt at the bottom
#[arg(
#[cfg_attr(feature = "cli", arg(
long,
default_value = "default",
value_parser = clap::builder::PossibleValuesParser::new(
["default", "reverse", "reverse-list"]
),
help_heading = "Layout",
)]
))]
pub layout: String,
/// Shorthand for reverse layout
#[arg(long, help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Layout"))]
pub reverse: bool,
/// Height of skim's window
///
/// Can either be a row count or a percentage
#[arg(long, default_value = "100%", help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, default_value = "100%", help_heading = "Layout"))]
pub height: String,
/// Disable height feature
#[arg(long, help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Layout"))]
pub no_height: bool,
/// Minimum height of skim's window
@ -592,7 +614,7 @@ pub struct SkimOptions {
/// Useful when the height is set as a percentage
///
/// Ignored when `--height` is not specified
#[arg(long, default_value = "10", help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, default_value = "10", help_heading = "Layout"))]
pub min_height: String,
/// Screen margin
@ -610,24 +632,24 @@ pub struct SkimOptions {
/// * T,R,B,L
///
/// **Example**: 1,10%
#[arg(long, default_value = "0", help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, default_value = "0", help_heading = "Layout"))]
pub margin: String,
/// Set prompt
#[arg(long, short, default_value = "> ", help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, short, default_value = "> ", help_heading = "Layout"))]
pub prompt: String,
/// Set prompt in command mode
#[arg(long, default_value = "c> ", help_heading = "Layout")]
#[cfg_attr(feature = "cli", arg(long, default_value = "c> ", help_heading = "Layout"))]
pub cmd_prompt: String,
// --- Display ---
/// Parse ANSI color codes in input strings
#[arg(long, help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display"))]
pub ansi: bool,
/// Number of spaces that make up a tab
#[arg(long, default_value = "8", help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, default_value = "8", help_heading = "Display"))]
pub tabstop: usize,
/// Set matching result count display position
@ -635,15 +657,18 @@ pub struct SkimOptions {
/// * 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
#[arg(long, help_heading = "Display", value_enum, default_value = "default")]
#[cfg_attr(
feature = "cli",
arg(long, help_heading = "Display", value_enum, default_value = "default")
)]
pub info: InfoDisplay,
/// Alias for --info=hidden
#[arg(long, help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display"))]
pub no_info: bool,
/// Alias for --info=inline
#[arg(long, help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display"))]
pub inline_info: bool,
/// Set header, displayed next to the info
@ -651,14 +676,14 @@ pub struct SkimOptions {
/// The given string will be printed as the sticky header. The lines are displayed in the
/// given order from top to bottom regardless of `--layout` option, and are not affected by
/// `--with-nth`. ANSI color codes are processed even when `--ansi` is not set.
#[arg(long, help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display"))]
pub header: Option<String>,
/// Number of lines of the input treated as header
///
/// The first N lines of the input are treated as the sticky header. When `--with-nth` is set,
/// the lines are transformed just like the other lines that follow.
#[arg(long, default_value = "0", help_heading = "Display")]
#[cfg_attr(feature = "cli", arg(long, default_value = "0", help_heading = "Display"))]
pub header_lines: usize,
// --- History ---
@ -668,11 +693,11 @@ pub struct SkimOptions {
///
/// When enabled, CTRL-N and CTRL-P are automatically remapped
/// to next-history and previous-history.
#[arg(long = "history", help_heading = "History")]
#[cfg_attr(feature = "cli", arg(long = "history", help_heading = "History"))]
pub history_file: Option<String>,
/// Maximum number of query history entries to keep
#[arg(long, default_value = "1000", help_heading = "History")]
#[cfg_attr(feature = "cli", arg(long, default_value = "1000", help_heading = "History"))]
pub history_size: usize,
/// Command history file
@ -681,11 +706,11 @@ pub struct SkimOptions {
///
/// When enabled, CTRL-N and CTRL-P are automatically remapped
/// to next-history and previous-history.
#[arg(long = "cmd-history", help_heading = "History")]
#[cfg_attr(feature = "cli", arg(long = "cmd-history", help_heading = "History"))]
pub cmd_history_file: Option<String>,
/// Maximum number of query history entries to keep
#[arg(long, default_value = "1000", help_heading = "History")]
#[cfg_attr(feature = "cli", arg(long, default_value = "1000", help_heading = "History"))]
pub cmd_history_size: usize,
// --- Preview ---
@ -721,7 +746,7 @@ pub struct SkimOptions {
///
/// Preview window will be updated even when there is no match for the current query if any of the placeholder ex
/// pressions evaluates to a non-empty string.
#[arg(long, help_heading = "Preview")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Preview"))]
pub preview: Option<String>,
/// Preview window layout
@ -756,16 +781,16 @@ pub struct SkimOptions {
/// --preview 'bat --style=numbers --color=always --highlight-line {2} {1}' \
/// --preview-window +{2}-/2
/// ```
#[arg(long, default_value = "right:50%", help_heading = "Preview")]
#[cfg_attr(feature = "cli", arg(long, default_value = "right:50%", help_heading = "Preview"))]
pub preview_window: String,
// --- Scripting ---
/// Initial query
#[arg(long, short, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, short, help_heading = "Scripting"))]
pub query: Option<String>,
/// Initial query in interactive mode
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub cmd_query: Option<String>,
/// [Deprecated: Use `--bind=<key>:accept(<key>)` instead] Comma separated list of keys used to complete skim
@ -777,35 +802,35 @@ pub struct SkimOptions {
/// list.
///
/// **Example**: `sk --expect=ctrl-v,ctrl-t,alt-s --expect=f1,f2,~,@`
#[arg(long, help_heading = "Scripting", value_delimiter = ',')]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting", value_delimiter = ','))]
pub expect: Vec<String>,
/// Read input delimited by ASCII NUL(\\0) characters
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub read0: bool,
/// Print output delimited by ASCII NUL(\\0) characters
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub print0: bool,
/// Print the query as the first line
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub print_query: bool,
/// Print the command as the first line (after print-query)
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub print_cmd: bool,
/// Print the command as the first line (after print-cmd)
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub print_score: bool,
/// Automatically select the match if there is only one
#[arg(long, short = '1', help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, short = '1', help_heading = "Scripting"))]
pub select_1: bool,
/// Automatically exit when no match is left
#[arg(long, short = '0', help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, short = '0', help_heading = "Scripting"))]
pub exit_0: bool,
/// Synchronous search for multi-staged filtering
@ -814,32 +839,32 @@ pub struct SkimOptions {
/// skim will launch ncurses finder only after the input stream is complete.
///
/// **Example**: `sk --multi | sk --sync`
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub sync: bool,
/// Pre-select the first n items in multi-selection mode
#[arg(long, default_value = "0", help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, default_value = "0", help_heading = "Scripting"))]
pub pre_select_n: usize,
/// Pre-select the matched items in multi-selection mode
///
/// Check the doc for the detailed syntax:
/// https://docs.rs/regex/1.4.1/regex/
#[arg(long, default_value = "", help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, default_value = "", help_heading = "Scripting"))]
pub pre_select_pat: String,
/// Pre-select the items separated by newline character
///
/// **Example**: `item1\nitem2`
#[arg(long, default_value = "", help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, default_value = "", help_heading = "Scripting"))]
pub pre_select_items: String,
/// Pre-select the items read from this file
#[arg(long, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting"))]
pub pre_select_file: Option<String>,
/// Query for filter mode
#[arg(long, short, help_heading = "Scripting")]
#[cfg_attr(feature = "cli", arg(long, short, help_heading = "Scripting"))]
pub filter: Option<String>,
/// Generate shell completion script
@ -852,8 +877,11 @@ pub struct SkimOptions {
/// Supported shells: bash, zsh, fish, powershell, elvish
///
/// Note: While PowerShell completions are supported, Windows is not supported for now.
#[arg(long, value_name = "SHELL", help_heading = "Scripting")]
#[arg(value_enum)]
#[cfg(feature = "cli")]
#[cfg_attr(
feature = "cli",
arg(long, value_name = "SHELL", help_heading = "Scripting", value_enum)
)]
pub shell: Option<clap_complete::Shell>,
/// Run in a tmux popup
@ -870,65 +898,74 @@ pub struct SkimOptions {
///
/// Note: env vars are only passed to the tmux command if they are either `PATH` or prefixed with
/// `RUST` or `SKIM`
#[arg(long, help_heading = "Display", default_missing_value = "center,50%", num_args=0..)]
#[cfg_attr(feature = "cli", arg(long, help_heading = "Display", default_missing_value = "center,50%", num_args=0..))]
pub tmux: Option<String>,
/// Reserved for later use
#[arg(short = 'x', long, hide = true, help_heading = "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
#[arg(long, hide = true, help_heading = "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
#[arg(long, hide = true, help_heading = "Reserved for later use")]
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub cycle: bool,
/// Reserved for later use
#[arg(long, hide = true, default_value = "10", help_heading = "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
#[arg(long, hide = true, help_heading = "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
#[arg(
long,
hide = true,
default_value = "abcdefghijklmnopqrstuvwxyz",
help_heading = "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
#[arg(long, hide = true, help_heading = "Reserved for later use", default_missing_value="Hi", num_args=0..=1)]
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use", default_missing_value="Hi", num_args=0..=1))]
pub border: Option<String>,
/// Reserved for later use
#[arg(long, hide = true, help_heading = "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
#[arg(long, hide = true, help_heading = "Reserved for later use")]
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub pointer: bool,
/// Reserved for later use
#[arg(long, hide = true, help_heading = "Reserved for later use")]
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub marker: bool,
/// Reserved for later use
#[arg(long, hide = true, help_heading = "Reserved for later use")]
#[cfg_attr(feature = "cli", arg(long, hide = true, help_heading = "Reserved for later use"))]
pub phony: bool,
#[clap(skip = Rc::new(RefCell::new(SkimItemReader::default())) as Rc<RefCell<dyn CommandCollector>>)]
#[cfg_attr(feature = "cli", clap(skip = Rc::new(RefCell::new(SkimItemReader::default())) as Rc<RefCell<dyn CommandCollector>>))]
pub cmd_collector: Rc<RefCell<dyn CommandCollector>>,
#[clap(skip)]
#[cfg_attr(feature = "cli", clap(skip))]
pub query_history: Vec<String>,
#[clap(skip)]
#[cfg_attr(feature = "cli", clap(skip))]
pub cmd_history: Vec<String>,
#[clap(skip)]
#[cfg_attr(feature = "cli", clap(skip))]
pub selector: Option<Rc<dyn Selector>>,
/// Preview Callback
///
@ -936,13 +973,96 @@ pub struct SkimOptions {
///
/// The function will take a `Vec<Arc<dyn SkimItem>>>` containing the currently selected items
/// and return a Vec<String> with the lines to display in UTF-8
#[clap(skip)]
#[cfg_attr(feature = "cli", clap(skip))]
pub preview_fn: Option<PreviewCallback>,
}
impl Default for SkimOptions {
fn default() -> Self {
Self::parse_from::<_, &str>([])
Self {
tac: Default::default(),
min_query_length: Default::default(),
no_sort: Default::default(),
tiebreak: vec![RankCriteria::Score, RankCriteria::Begin, RankCriteria::End],
nth: Default::default(),
with_nth: Default::default(),
delimiter: String::from(r"[\t\n ]+"),
exact: Default::default(),
regex: Default::default(),
algorithm: Default::default(),
case: Default::default(),
bind: Default::default(),
multi: Default::default(),
no_multi: Default::default(),
no_mouse: Default::default(),
cmd: Default::default(),
interactive: Default::default(),
replstr: String::from("{}"),
color: Default::default(),
no_hscroll: Default::default(),
keep_right: Default::default(),
skip_to_pattern: Default::default(),
no_clear_if_empty: Default::default(),
no_clear_start: Default::default(),
no_clear: Default::default(),
show_cmd_error: Default::default(),
layout: String::from("default"),
reverse: Default::default(),
height: String::from("100%"),
no_height: Default::default(),
min_height: String::from("10"),
margin: Default::default(),
prompt: String::from("> "),
cmd_prompt: String::from("c> "),
ansi: Default::default(),
tabstop: 8,
info: Default::default(),
no_info: Default::default(),
inline_info: Default::default(),
header: Default::default(),
header_lines: Default::default(),
history_file: Default::default(),
history_size: 1000,
cmd_history_file: Default::default(),
cmd_history_size: 1000,
preview: Default::default(),
preview_window: String::from("right:50%"),
query: Default::default(),
cmd_query: Default::default(),
expect: Default::default(),
read0: Default::default(),
print0: Default::default(),
print_query: Default::default(),
print_cmd: Default::default(),
print_score: Default::default(),
select_1: Default::default(),
exit_0: Default::default(),
sync: Default::default(),
pre_select_n: Default::default(),
pre_select_pat: Default::default(),
pre_select_items: Default::default(),
pre_select_file: Default::default(),
filter: Default::default(),
#[cfg(feature = "cli")]
shell: Default::default(),
tmux: Default::default(),
extended: Default::default(),
literal: Default::default(),
cycle: Default::default(),
hscroll_off: 10,
filepath_word: Default::default(),
jump_labels: String::from("abcdefghijklmnopqrstuvwxyz"),
border: Default::default(),
no_bold: Default::default(),
pointer: Default::default(),
marker: Default::default(),
phony: Default::default(),
cmd_collector: Rc::new(RefCell::new(SkimItemReader::default())) as Rc<RefCell<dyn CommandCollector>>,
query_history: Default::default(),
cmd_history: Default::default(),
selector: Default::default(),
preview_fn: Default::default(),
}
}
}

View file

@ -240,7 +240,7 @@ impl Previewer {
(ItemPreview::Command(cmd), pos) | (ItemPreview::CommandWithPos(cmd, pos), _) => {
if depends_on_items(&cmd) && self.prev_item.is_none() {
debug!("the command for preview refers to items and currently there is no item");
debug!("command to execute: [{}]", cmd);
debug!("command to execute: [{cmd}]");
PreviewEvent::PreviewPlainText("no item matched".to_string(), Default::default())
} else {
let cmd = inject_command(&cmd, inject_context).to_string();
@ -252,7 +252,7 @@ impl Previewer {
PreviewSource::Command(cmd) => {
if depends_on_items(cmd) && self.prev_item.is_none() {
debug!("the command for preview refers to items and currently there is no item");
debug!("command to execute: [{}]", cmd);
debug!("command to execute: [{cmd}]");
PreviewEvent::PreviewPlainText("no item matched".to_string(), Default::default())
} else {
let cmd = inject_command(cmd, inject_context).to_string();
@ -511,7 +511,7 @@ where
match spawned {
Err(err) => {
let astdout = AnsiString::parse(format!("Failed to spawn: {} / {}", cmd, err).as_str());
let astdout = AnsiString::parse(format!("Failed to spawn: {cmd} / {err}").as_str());
callback(vec![astdout], pos);
preview_thread = None;
}

View file

@ -128,12 +128,12 @@ impl Query {
if let Some(file) = &options.history_file {
self.fz_query_history_before =
read_file_lines(file).unwrap_or_else(|_| panic!("Failed to open history file {}", file));
read_file_lines(file).unwrap_or_else(|_| panic!("Failed to open history file {file}"));
}
if let Some(file) = &options.cmd_history_file {
self.cmd_history_before =
read_file_lines(file).unwrap_or_else(|_| panic!("Failed to open command history file {}", file));
read_file_lines(file).unwrap_or_else(|_| panic!("Failed to open command history file {file}"));
}
}

View file

@ -257,7 +257,7 @@ impl Selection {
let current_item = self
.items
.get(cursor)
.unwrap_or_else(|| panic!("model:act_toggle: failed to get item {}", cursor));
.unwrap_or_else(|| panic!("model:act_toggle: failed to get item {cursor}"));
trace!(
"Toggling item {} with idx {}",
current_item.item.text(),
@ -330,7 +330,7 @@ impl Selection {
let current_item = self
.items
.get(cursor)
.unwrap_or_else(|| panic!("model:act_output: failed to get item {}", cursor));
.unwrap_or_else(|| panic!("model:act_output: failed to get item {cursor}"));
let item = current_item.item.clone();
item_indices.push(cursor);
selected.push(item);
@ -587,7 +587,7 @@ impl Draw for Selection {
let item = self
.items
.get(item_idx)
.unwrap_or_else(|| panic!("model:draw_items: failed to get item at {}", item_idx));
.unwrap_or_else(|| panic!("model:draw_items: failed to get item at {item_idx}"));
let _ = self.draw_item(canvas, line_no, &item, line_cursor == self.line_cursor);
}

View file

@ -129,7 +129,7 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
debug!("Read {n} bytes from stdin");
stdin_writer.write_all(&buf).unwrap();
}
Err(e) => panic!("Failed to read from stdin: {}", e),
Err(e) => panic!("Failed to read from stdin: {e}"),
}
}
}))
@ -142,7 +142,7 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
let mut prev_is_tmux_flag = false;
// We keep argv[0] to use in the popup's command
for arg in std::env::args() {
debug!("Got arg {}", arg);
debug!("Got arg {arg}");
if prev_is_tmux_flag {
prev_is_tmux_flag = false;
if !arg.starts_with("-") {
@ -169,7 +169,7 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
// Run downstream sk in tmux
let raw_tmux_opts = &opts.tmux.clone().unwrap();
let tmux_opts = TmuxOptions::from(raw_tmux_opts);
let mut tmux_cmd = Command::new(which("tmux").unwrap_or_else(|e| panic!("Failed to find tmux in path: {}", e)));
let mut tmux_cmd = Command::new(which("tmux").unwrap_or_else(|e| panic!("Failed to find tmux in path: {e}")));
tmux_cmd
.arg("display-popup")
@ -182,21 +182,21 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
for (name, value) in std::env::vars() {
if name.starts_with("SKIM") || name == "PATH" || name.starts_with("RUST") {
debug!("adding {} = {} to the command's env", name, value);
tmux_cmd.args(["-e", &format!("{}={}", name, value)]);
debug!("adding {name} = {value} to the command's env");
tmux_cmd.args(["-e", &format!("{name}={value}")]);
}
}
tmux_cmd.args(["sh", "-c", &tmux_shell_cmd]);
debug!("tmux command: {:?}", tmux_cmd);
debug!("tmux command: {tmux_cmd:?}");
let status = tmux_cmd
.stdout(Stdio::null())
.stderr(Stdio::null())
.stdin(Stdio::null())
.status()
.unwrap_or_else(|e| panic!("Tmux invocation failed with {}", e));
.unwrap_or_else(|e| panic!("Tmux invocation failed with {e}"));
if let Some(h) = stdin_handle {
h.join().unwrap_or(());
@ -222,7 +222,7 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
let mut output_lines: Vec<Arc<dyn SkimItem>> = vec![];
for line in stdout {
debug!("Adding output line: {}", line);
debug!("Adding output line: {line}");
output_lines.push(Arc::new(SkimTmuxOutput { line: line.to_string() }));
}

View file

@ -370,7 +370,7 @@ pub fn inject_command<'a>(cmd: &'a str, context: InjectContext<'a>) -> Cow<'a, s
.zip(indices.iter())
.map(|(&s, &i)| {
let rest = &range[1..];
let index_str = format!("{}", i);
let index_str = format!("{i}");
let replacement = match rest {
"" => s,
"n" => &index_str,
@ -407,7 +407,7 @@ pub fn atoi<T: FromStr>(string: &str) -> Option<T> {
pub fn read_file_lines(filename: &str) -> std::result::Result<Vec<String>, std::io::Error> {
let file = File::open(filename)?;
let ret = BufReader::new(file).lines().collect();
debug!("file content: {:?}", ret);
debug!("file content: {ret:?}");
ret
}