Skip to content

Commit

Permalink
feat: allow more flexibility for use as a library (#613)
Browse files Browse the repository at this point in the history
* fix: revert options and context split

* readd selector to options

* make RankCriteria public

* fmt

* fix selector override

* add examples

* clippy

* revert mangen & compgen

---------

Co-authored-by: LoricAndre <loric.andre@pm.me>
  • Loading branch information
LoricAndre and LoricAndre authored Nov 25, 2024
1 parent 53612a7 commit 33ca402
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 86 deletions.
48 changes: 48 additions & 0 deletions skim/examples/cmd_collector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
extern crate skim;
use reader::CommandCollector;
use skim::prelude::*;

struct BasicSkimItem {
value: String,
}

impl SkimItem for BasicSkimItem {
fn text(&self) -> Cow<str> {
return Cow::Borrowed(&self.value);
}
}

struct BasicCmdCollector {
pub items: Vec<String>,
}

impl CommandCollector for BasicCmdCollector {
fn invoke(&mut self, _cmd: &str, _components_to_stop: Arc<AtomicUsize>) -> (SkimItemReceiver, Sender<i32>) {
let (tx, rx) = unbounded();
let (tx_interrupt, _rx_interrupt) = unbounded();
while let Some(value) = self.items.pop() {
let item = BasicSkimItem { value };
tx.send(Arc::from(item) as Arc<dyn SkimItem>).unwrap();
}

(rx, tx_interrupt)
}
}

pub fn main() {
let cmd_collector = BasicCmdCollector {
items: vec![String::from("foo"), String::from("bar"), String::from("baz")],
};
let options = SkimOptionsBuilder::default()
.cmd_collector(Rc::from(RefCell::from(cmd_collector)))
.build()
.unwrap();

let selected_items = Skim::run_with(&options, None)
.map(|out| out.selected_items)
.unwrap_or_default();

for item in selected_items.iter() {
println!("{}", item.output());
}
}
32 changes: 32 additions & 0 deletions skim/examples/selector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
extern crate skim;
use skim::prelude::*;

struct BasicSelector {
pub pat: String,
}

impl Selector for BasicSelector {
fn should_select(&self, _index: usize, item: &dyn SkimItem) -> bool {
return item.text().contains(&self.pat);
}
}

pub fn main() {
let selector = BasicSelector {
pat: String::from("examples"),
};
let options = SkimOptionsBuilder::default()
.multi(true)
.selector(Some(Rc::from(selector)))
.query(Some(String::from("skim/")))
.build()
.unwrap();

let selected_items = Skim::run_with(&options, None)
.map(|out| out.selected_items)
.unwrap_or_default();

for item in selected_items.iter() {
println!("{}", item.output());
}
}
28 changes: 10 additions & 18 deletions skim/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ extern crate shlex;
extern crate skim;
extern crate time;

use self::context::SkimContext;
use self::reader::CommandCollector;
use clap::{Error, Parser};
use derive_builder::Builder;
use std::fs::File;
Expand Down Expand Up @@ -77,7 +75,7 @@ impl From<clap::Error> for SkMainError {
}

fn sk_main() -> Result<i32, SkMainError> {
let opts = parse_args()?;
let mut opts = parse_args()?;

let reader_opts = SkimItemReaderOption::default()
.ansi(opts.ansi)
Expand All @@ -86,13 +84,8 @@ fn sk_main() -> Result<i32, SkMainError> {
.nth(opts.nth.iter().map(|s| s.as_str()))
.read0(opts.read0)
.show_error(opts.show_cmd_error);
let mut ctx = SkimContext {
cmd_collector: Rc::new(RefCell::new(SkimItemReader::new(reader_opts))),
query_history: vec![],
cmd_history: vec![],
};
ctx.init_histories(&opts);

let cmd_collector = Rc::new(RefCell::new(SkimItemReader::new(reader_opts)));
opts.cmd_collector = cmd_collector.clone();
//------------------------------------------------------------------------------
let bin_options = BinOptions {
filter: opts.filter.clone(),
Expand All @@ -104,7 +97,7 @@ fn sk_main() -> Result<i32, SkMainError> {
//------------------------------------------------------------------------------
// read from pipe or command
let rx_item = if !io::stdin().is_terminal() {
let rx_item = ctx.cmd_collector.borrow().of_bufread(BufReader::new(std::io::stdin()));
let rx_item = cmd_collector.borrow().of_bufread(BufReader::new(std::io::stdin()));
Some(rx_item)
} else {
None
Expand All @@ -113,7 +106,7 @@ fn sk_main() -> Result<i32, SkMainError> {
//------------------------------------------------------------------------------
// filter mode
if opts.filter.is_some() {
return Ok(filter(&ctx, &bin_options, &opts, rx_item)?);
return Ok(filter(&bin_options, &opts, rx_item)?);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -156,14 +149,14 @@ fn sk_main() -> Result<i32, SkMainError> {

//------------------------------------------------------------------------------
// write the history with latest item
if let Some(file) = opts.history {
if let Some(file) = opts.history_file {
let limit = opts.history_size;
write_history_to_file(&ctx.query_history, &result.query, limit, &file)?;
write_history_to_file(&opts.query_history, &result.query, limit, &file)?;
}

if let Some(file) = opts.cmd_history {
if let Some(file) = opts.cmd_history_file {
let limit = opts.cmd_history_size;
write_history_to_file(&ctx.cmd_history, &result.cmd, limit, &file)?;
write_history_to_file(&opts.cmd_history, &result.cmd, limit, &file)?;
}

Ok(if result.selected_items.is_empty() { 1 } else { 0 })
Expand Down Expand Up @@ -204,7 +197,6 @@ pub struct BinOptions {
}

pub fn filter(
ctx: &SkimContext,
bin_option: &BinOptions,
options: &SkimOptions,
source: Option<SkimItemReceiver>,
Expand Down Expand Up @@ -244,7 +236,7 @@ pub fn filter(
let components_to_stop = Arc::new(AtomicUsize::new(0));

let stream_of_item = source.unwrap_or_else(|| {
let (ret, _control) = ctx.cmd_collector.borrow_mut().invoke(&cmd, components_to_stop);
let (ret, _control) = options.cmd_collector.borrow_mut().invoke(&cmd, components_to_stop);
ret
});

Expand Down
34 changes: 0 additions & 34 deletions skim/src/context.rs

This file was deleted.

4 changes: 2 additions & 2 deletions skim/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ use tuikit::prelude::{Event as TermEvent, *};
pub use crate::ansi::AnsiString;
pub use crate::engine::fuzzy::FuzzyAlgorithm;
use crate::event::{EventReceiver, EventSender};
pub use crate::item::RankCriteria;
use crate::model::Model;
pub use crate::options::SkimOptions;
pub use crate::output::SkimOutput;
use crate::reader::Reader;

mod ansi;
pub mod context;
mod engine;
mod event;
pub mod field;
Expand All @@ -34,7 +34,7 @@ mod input;
mod item;
mod matcher;
mod model;
mod options;
pub mod options;
mod orderedvec;
mod output;
pub mod prelude;
Expand Down
38 changes: 32 additions & 6 deletions skim/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use std::cell::RefCell;
use std::rc::Rc;

use clap::Parser;
use derive_builder::Builder;

use crate::item::RankCriteria;
use crate::{CaseMatching, FuzzyAlgorithm};
use crate::prelude::SkimItemReader;
use crate::reader::CommandCollector;
use crate::util::read_file_lines;
use crate::{CaseMatching, FuzzyAlgorithm, Selector};

/// sk - fuzzy finder in Rust
///
Expand Down Expand Up @@ -471,8 +477,8 @@ pub struct SkimOptions {
/// Load search history from the specified file and update the file on completion.
/// When enabled, CTRL-N and CTRL-P are automatically remapped
/// to next-history and previous-history.
#[arg(long, help_heading = "History")]
pub history: Option<String>,
#[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")]
Expand All @@ -483,8 +489,8 @@ pub struct SkimOptions {
/// Load command query history from the specified file and update the file on completion.
/// When enabled, CTRL-N and CTRL-P are automatically remapped
/// to next-history and previous-history.
#[arg(long, help_heading = "History")]
pub cmd_history: Option<String>,
#[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")]
Expand Down Expand Up @@ -702,6 +708,15 @@ pub struct SkimOptions {
/// Reserved for later use
#[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>>)]
pub cmd_collector: Rc<RefCell<dyn CommandCollector>>,
#[clap(skip)]
pub query_history: Vec<String>,
#[clap(skip)]
pub cmd_history: Vec<String>,
#[clap(skip)]
pub selector: Option<Rc<dyn Selector>>,
}

impl Default for SkimOptions {
Expand Down Expand Up @@ -734,10 +749,21 @@ impl SkimOptions {
self.layout = String::from("reverse");
}
let history_binds = String::from("ctrl-p:previous-history,ctrl-n:next-history");
if self.history.is_some() || self.cmd_history.is_some() {
if self.history_file.is_some() || self.cmd_history_file.is_some() {
self.init_histories();
self.bind.push(history_binds);
}

self
}
pub fn init_histories(&mut self) {
if let Some(histfile) = &self.history_file {
self.query_history.extend(read_file_lines(histfile).unwrap_or_default());
}

if let Some(cmd_histfile) = &self.cmd_history_file {
self.cmd_history
.extend(read_file_lines(cmd_histfile).unwrap_or_default());
}
}
}
10 changes: 5 additions & 5 deletions skim/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,14 @@ impl Query {

self.replstr = options.replstr.clone();

if let Some(history_file) = &options.history {
if let Some(file) = &options.history_file {
self.fz_query_history_before =
read_file_lines(history_file).expect(&format!("Failed to open history file {}", history_file));
read_file_lines(file).unwrap_or_else(|_| panic!("Failed to open history file {}", file));
}

if let Some(cmd_history_file) = &options.cmd_history {
self.cmd_history_before = read_file_lines(cmd_history_file)
.expect(&format!("Failed to open command history file {}", cmd_history_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));
}
}

Expand Down
12 changes: 1 addition & 11 deletions skim/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//! After reading in a line, reader will save an item into the pool(items)
use crate::global::mark_new_run;
use crate::options::SkimOptions;
use crate::prelude::*;
use crate::spinlock::SpinLock;
use crate::{SkimItem, SkimItemReceiver};
use crossbeam::channel::{bounded, select, Sender};
Expand Down Expand Up @@ -65,17 +64,8 @@ pub struct Reader {

impl Reader {
pub fn with_options(options: &SkimOptions) -> Self {
let item_reader_option = SkimItemReaderOption::default()
.ansi(options.ansi)
.delimiter(&options.delimiter)
.with_nth(options.with_nth.iter().map(|s| s.as_str()))
.nth(options.nth.iter().map(|s| s.as_str()))
.read0(options.read0)
.show_error(options.show_cmd_error)
.build();
let cmd_collector = Rc::new(RefCell::new(SkimItemReader::new(item_reader_option)));
Self {
cmd_collector,
cmd_collector: options.cmd_collector.clone(),
rx_item: None,
}
}
Expand Down
28 changes: 18 additions & 10 deletions skim/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,26 @@ impl Selection {
|| !options.pre_select_pat.is_empty()
|| !pre_select_items.is_empty()
|| options.pre_select_file.is_some()
|| options.selector.is_some()
{
let mut preset_file_items: Vec<String> = vec![];
if let Some(pre_select_file) = options.pre_select_file.clone() {
preset_file_items = read_file_lines(&pre_select_file).unwrap();
}
match options.selector.clone() {
None => {
let mut preset_file_items: Vec<String> = vec![];
if let Some(pre_select_file) = options.pre_select_file.clone() {
preset_file_items = read_file_lines(&pre_select_file).unwrap();
}

let selector = DefaultSkimSelector::default()
.first_n(options.pre_select_n)
.regex(&options.pre_select_pat)
.preset(pre_select_items)
.preset(preset_file_items);
self.selector = Some(Rc::new(selector));
let selector = DefaultSkimSelector::default()
.first_n(options.pre_select_n)
.regex(&options.pre_select_pat)
.preset(pre_select_items)
.preset(preset_file_items);
self.selector = Some(Rc::new(selector));
}
Some(s) => {
self.selector = Some(s);
}
}
}
}

Expand Down

0 comments on commit 33ca402

Please sign in to comment.