Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
387 changes: 232 additions & 155 deletions benches/filter.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion benches/matcher_micro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use skim::fuzzy_matcher::frizbee::FrizbeeMatcher;
use skim::prelude::SkimMatcherV2;

fn load_lines() -> Vec<String> {
let data = fs::read_to_string("benches/fixtures/1M.txt").expect("1M.txt missing");
let data = fs::read_to_string("benches/fixtures/100K.txt").expect("100K.txt missing");
data.lines().map(|l| l.to_string()).collect()
}

Expand Down
2 changes: 1 addition & 1 deletion examples/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn main() -> color_eyre::Result<()> {
let res = Skim::run_items(opts, ["hello", "world"])?;

for item in res.selected_items {
println!("Selected {} (id {})", item.output(), item.get_index());
println!("Selected {} (id {})", item.output(), item.rank.index);
}

Ok(())
Expand Down
22 changes: 13 additions & 9 deletions examples/custom_action_keybinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use std::io::Cursor;
/// This example demonstrates how to bind custom action callbacks to keyboard shortcuts.
///
/// It shows how to:
/// 1. Create custom action callbacks
/// 1. Create custom action callbacks (both sync and async)
/// 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| {
// Create a synchronous callback that adds a prefix to the query.
// Use `new_sync` for plain closures that do not need to await anything.
let add_prefix_callback = ActionCallback::new_sync(|app: &mut skim::tui::App| {
// Get current query and add prefix
let current_query = app.input.value.clone();

Expand All @@ -32,14 +33,17 @@ fn main() {
Ok(events)
});

// Create a callback that selects all and exits
// Create an async callback that selects all and exits.
// Use `new` for async closures or blocks that may await futures.
let select_all_callback = ActionCallback::new(|app: &mut skim::tui::App| {
let count = app.item_pool.len();

Ok(vec![
Event::Action(Action::SelectAll),
Event::Action(Action::Accept(Some(format!("Selected {count} items")))),
])
async move {
// Async work could go here (e.g. HTTP requests, file I/O, …).
Ok(vec![
Event::Action(Action::SelectAll),
Event::Action(Action::Accept(Some(format!("Selected {count} items")))),
])
}
});

// Build basic options
Expand Down
4 changes: 3 additions & 1 deletion examples/custom_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ fn main() {
let options = SkimOptionsBuilder::default()
.height("50%")
.multi(true)
.preview(String::new()) // preview should be specified to enable preview window
.preview("") // preview should be specified to enable preview window
.build()
.unwrap();

env_logger::init();

let (tx_item, rx_item): (SkimItemSender, SkimItemReceiver) = unbounded();
let _ = tx_item.send(vec![
Arc::new(MyItem {
Expand Down
26 changes: 4 additions & 22 deletions examples/downcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use skim::prelude::*;
#[derive(Debug, Clone)]
struct Item {
text: String,
index: usize,
}

impl SkimItem for Item {
Expand All @@ -18,14 +17,6 @@ impl SkimItem for Item {
fn preview(&self, _context: PreviewContext) -> ItemPreview {
ItemPreview::Text(self.text.to_owned())
}

fn get_index(&self) -> usize {
self.index
}

fn set_index(&mut self, index: usize) {
self.index = index
}
}

pub fn main() {
Expand All @@ -39,18 +30,9 @@ pub fn main() {
let (tx, rx): (SkimItemSender, SkimItemReceiver) = unbounded();

tx.send(vec![
Arc::new(Item {
text: "a".into(),
index: 0,
}) as Arc<dyn SkimItem>,
Arc::new(Item {
text: "b".into(),
index: 1,
}) as Arc<dyn SkimItem>,
Arc::new(Item {
text: "c".into(),
index: 2,
}) as Arc<dyn SkimItem>,
Arc::new(Item { text: "a".into() }) as Arc<dyn SkimItem>,
Arc::new(Item { text: "b".into() }) as Arc<dyn SkimItem>,
Arc::new(Item { text: "c".into() }) as Arc<dyn SkimItem>,
])
.unwrap();

Expand All @@ -60,7 +42,7 @@ pub fn main() {
.map(|out| out.selected_items)
.unwrap_or_default()
.iter()
.map(|selected_item| (**selected_item).as_any().downcast_ref::<Item>().unwrap().to_owned())
.map(|selected_item| selected_item.downcast_item::<Item>().unwrap().to_owned())
.collect::<Vec<Item>>();

for item in selected_items {
Expand Down
2 changes: 1 addition & 1 deletion shell/completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ _sk() {
return 0
;;
--flags)
COMPREPLY=($(compgen -W "no-preview-pty show-score" -- "${cur}"))
COMPREPLY=($(compgen -W "no-preview-pty show-score show-index" -- "${cur}"))
return 0
;;
--hscroll-off)
Expand Down
3 changes: 2 additions & 1 deletion shell/completion.fish
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ complete -c sk -l tmux -d 'Run in a tmux popup' -r
complete -c sk -l log-level -d 'Set the log level' -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'
show-score\t'Display the item\'s match score before its value in the item list (for matcher debugging)'"
show-score\t'Display the item\'s match score before its value in the item list (for matcher debugging)'
show-index\t'Display the item\'s index before its value in the item list'"
complete -c sk -l hscroll-off -r
complete -c sk -l jump-labels -r
complete -c sk -l tail -r
Expand Down
2 changes: 1 addition & 1 deletion shell/completion.nu
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module completions {
}

def "nu-complete sk flags" [] {
[ "no-preview-pty" "show-score" ]
[ "no-preview-pty" "show-score" "show-index" ]
}

# Fuzzy Finder in rust!
Expand Down
3 changes: 2 additions & 1 deletion shell/completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ zsh\:"Zsh"))' \
'--log-level=[Set the log level]:LOG_LEVEL:_default' \
'--log-file=[Pipe log output to a file]:LOG_FILE:_default' \
'*--flags=[Feature flags]:FLAGS:((no-preview-pty\:"Disable preview PTY on linux"
show-score\:"Display the item'\''s match score before its value in the item list (for matcher debugging)"))' \
show-score\:"Display the item'\''s match score before its value in the item list (for matcher debugging)"
show-index\:"Display the item'\''s index before its value in the item list"))' \
'--hscroll-off=[]:HSCROLL_OFF:_default' \
'--jump-labels=[]:JUMP_LABELS:_default' \
'--tail=[]:TAIL:_default' \
Expand Down
2 changes: 1 addition & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ fn sk_main(mut opts: SkimOptions) -> Result<i32> {
output_format,
&bin_options.delimiter,
&bin_options.replstr,
result.selected_items.iter().map(|x| x.item.clone()),
result.selected_items.iter(),
result.current,
&result.query,
&result.cmd,
Expand Down
2 changes: 1 addition & 1 deletion src/engine/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl MatchEngine for MatchAllEngine {
fn match_item(&self, item: &dyn SkimItem) -> Option<MatchResult> {
let item_text = item.text();
Some(MatchResult {
rank: self.rank_builder.build_rank(0, 0, 0, &item_text, item.get_index()),
rank: self.rank_builder.build_rank(0, 0, 0, &item_text),
matched_range: MatchRange::ByteRange(0, 0),
})
}
Expand Down
4 changes: 1 addition & 3 deletions src/engine/exact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ impl MatchEngine for ExactEngine {
let (begin, end) = matched_result?;
let score = (end - begin) as i32;
Some(MatchResult {
rank: self
.rank_builder
.build_rank(score, begin, end, &item_text, item.get_index()),
rank: self.rank_builder.build_rank(score, begin, end, &item_text),
matched_range: MatchRange::ByteRange(begin, end),
})
}
Expand Down
8 changes: 2 additions & 6 deletions src/engine/fuzzy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,7 @@ impl MatchEngine for FuzzyEngine {

let (score, begin, end) = best?;
Some(MatchResult {
rank: self
.rank_builder
.build_rank(score as i32, begin, end, &item_text, item.get_index()),
rank: self.rank_builder.build_rank(score as i32, begin, end, &item_text),
matched_range: MatchRange::ByteRange(begin, end),
})
} else {
Expand Down Expand Up @@ -254,9 +252,7 @@ impl MatchEngine for FuzzyEngine {
let matched_range = MatchRange::Chars(matched_indices);

Some(MatchResult {
rank: self
.rank_builder
.build_rank(score as i32, begin, end, &item_text, item.get_index()),
rank: self.rank_builder.build_rank(score as i32, begin, end, &item_text),
matched_range,
})
}
Expand Down
4 changes: 1 addition & 3 deletions src/engine/regexp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ impl MatchEngine for RegexEngine {
let score = (end - begin) as i32;

Some(MatchResult {
rank: self
.rank_builder
.build_rank(score, begin, end, &item_text, item.get_index()),
rank: self.rank_builder.build_rank(score, begin, end, &item_text),
matched_range: MatchRange::ByteRange(begin, end),
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/fuzzy_matcher/arinae/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub(super) const TYPO_BAND_SLACK: usize = 4;
/// (standard bonus). Entries that are `0` are not considered separators.
pub(super) const SEPARATOR_TABLE: [Score; 128] = {
let mut t = [0 as Score; 128];
t[b' ' as usize] = 12; // space
t[b' ' as usize] = 16; // space
t[b'-' as usize] = 10; // hyphen / kebab-case
t[b'.' as usize] = 12; // dot (file extensions, domain names)
t[b'/' as usize] = 16; // forward slash (path separator — higher bonus)
Expand Down
31 changes: 9 additions & 22 deletions src/helper/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ pub struct DefaultSkimItem {
/// The text that will be shown on screen.
text: Box<str>,

/// The index, for use in matching
index: usize,

/// Metadata containing miscellaneous fields when special options are used
metadata: Option<Box<DefaultSkimItemMetadata>>,
}
Expand Down Expand Up @@ -60,7 +57,6 @@ impl DefaultSkimItem {
trans_fields: &[FieldRange],
matching_fields: &[FieldRange],
delimiter: &Regex,
index: usize,
) -> Self {
let using_transform_fields = !trans_fields.is_empty();
let contains_ansi = Self::contains_ansi_escape(orig_text);
Expand Down Expand Up @@ -169,7 +165,6 @@ impl DefaultSkimItem {

DefaultSkimItem {
text: temp_text,
index,
metadata,
}
}
Expand Down Expand Up @@ -230,6 +225,15 @@ impl DefaultSkimItem {
}
}

impl From<String> for DefaultSkimItem {
fn from(value: String) -> Self {
Self {
text: Box::from(value),
metadata: None,
}
}
}

impl SkimItem for DefaultSkimItem {
#[inline]
fn text(&self) -> Cow<'_, str> {
Expand Down Expand Up @@ -433,14 +437,6 @@ impl SkimItem for DefaultSkimItem {
context.to_line(Cow::Borrowed(&self.text))
}
}

fn get_index(&self) -> usize {
self.index
}

fn set_index(&mut self, index: usize) {
self.index = index;
}
}

/// Strip ANSI escape sequences from a string
Expand Down Expand Up @@ -651,7 +647,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);

// text() should return stripped text for matching
Expand Down Expand Up @@ -693,7 +688,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);

// text() should return "😀text"
Expand Down Expand Up @@ -727,7 +721,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);
assert_eq!(
item_ansi.text(),
Expand All @@ -742,7 +735,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);
assert_eq!(
item_no_ansi.text(),
Expand All @@ -766,7 +758,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);

// Create display context with yellow background highlight for character 0 (the 'g')
Expand Down Expand Up @@ -805,7 +796,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);

// Create display context with yellow background highlight for characters 1-3 ('re')
Expand Down Expand Up @@ -846,7 +836,6 @@ mod test {
&[],
&[],
&delimiter,
0,
);

// Create display context with yellow background highlight for bytes 1-3 ('re' in stripped text)
Expand Down Expand Up @@ -886,7 +875,6 @@ mod test {
&[],
&[], // no matching fields restriction
&delimiter,
0,
);

// text() should return stripped text "green_text"
Expand Down Expand Up @@ -918,7 +906,6 @@ mod test {
&[], // no transform fields
&[FieldRange::Single(2)], // match field 2
&delimiter,
0,
);

// text() should return text with null bytes stripped for display
Expand Down
Loading