diff --git a/src/the_way/cli.rs b/src/the_way/cli.rs index be62a10..6f65c43 100644 --- a/src/the_way/cli.rs +++ b/src/the_way/cli.rs @@ -32,16 +32,19 @@ pub enum TheWaySubcommand { /// shell snippet code code: Option, }, - /// Fuzzy search to find a snippet and copy, edit or delete it + /// Search to find a snippet and copy, edit or delete it Search { #[clap(flatten)] filters: Filters, + /// Use exact search instead of fuzzy + #[clap(long, short)] + exact: bool, /// Print to stdout instead of copying (with Enter) #[clap(long, short)] stdout: bool, - /// Use exact search instead of fuzzy + /// Don't ask for confirmation when deleting #[clap(long, short)] - exact: bool, + force: bool, }, /// Sync snippets to a Gist /// @@ -116,14 +119,24 @@ pub enum TheWaySubcommand { }, /// Change snippet Edit { - /// Index of snippet to change - index: usize, + /// Index of snippet to change, opens a search window if not given + index: Option, + #[clap(flatten)] + filters: Filters, + /// Use exact search instead of fuzzy + #[clap(long, short)] + exact: bool, }, /// Delete snippet #[clap(alias = "delete")] Del { - /// Index of snippet to delete - index: usize, + /// Index of snippet to delete, opens a search window if not given + index: Option, + #[clap(flatten)] + filters: Filters, + /// Use exact search instead of fuzzy + #[clap(long, short)] + exact: bool, /// Don't ask for confirmation #[clap(long, short)] force: bool, @@ -131,16 +144,26 @@ pub enum TheWaySubcommand { /// Copy snippet to clipboard #[clap(alias = "copy")] Cp { - /// Index of snippet to copy - index: usize, + /// Index of snippet to copy, opens a search window if not given + index: Option, + #[clap(flatten)] + filters: Filters, + /// Use exact search instead of fuzzy + #[clap(long, short)] + exact: bool, /// Print to stdout instead of copying #[clap(long, short)] stdout: bool, }, /// View snippet View { - /// Index of snippet to show - index: usize, + /// Index of snippet to show, opens a search window if not given + index: Option, + #[clap(flatten)] + filters: Filters, + /// Use exact search instead of fuzzy + #[clap(long, short)] + exact: bool, }, /// Lists (optionally filtered) tags Tags { diff --git a/src/the_way/mod.rs b/src/the_way/mod.rs index 98db484..df6468d 100644 --- a/src/the_way/mod.rs +++ b/src/the_way/mod.rs @@ -88,13 +88,44 @@ impl TheWay { TheWaySubcommand::Cmd { code } => self.the_way_cmd(code), TheWaySubcommand::Search { filters, + exact, stdout, + force, + } => self.search(&filters, stdout, search::SkimCommand::All, exact, force), + TheWaySubcommand::Cp { + index, + filters, + exact, + stdout, + } => match index { + Some(index) => self.copy(index, stdout), + None => self.search(&filters, stdout, search::SkimCommand::Copy, exact, false), + }, + TheWaySubcommand::Edit { + index, + filters, + exact, + } => match index { + Some(index) => self.edit(index), + None => self.search(&filters, exact, search::SkimCommand::Edit, false, false), + }, + TheWaySubcommand::Del { + index, + filters, exact, - } => self.search(&filters, stdout, exact), - TheWaySubcommand::Cp { index, stdout } => self.copy(index, stdout), - TheWaySubcommand::Edit { index } => self.edit(index), - TheWaySubcommand::Del { index, force } => self.delete(index, force), - TheWaySubcommand::View { index } => self.view(index), + force, + } => match index { + Some(index) => self.delete(index, force), + None => self.search(&filters, exact, search::SkimCommand::Delete, false, force), + }, + TheWaySubcommand::View { + index, + filters, + exact, + } => match index { + Some(index) => self.view(index), + None => self.search(&filters, exact, search::SkimCommand::View, false, false), + }, TheWaySubcommand::List { filters } => self.list(&filters, ListType::Snippet), TheWaySubcommand::Import { file, @@ -358,15 +389,24 @@ impl TheWay { /// Displays all snippet descriptions in a skim fuzzy search window /// A preview window on the right shows the indices of snippets matching the query - fn search(&mut self, filters: &Filters, stdout: bool, exact: bool) -> color_eyre::Result<()> { + fn search( + &mut self, + filters: &Filters, + exact: bool, + command: search::SkimCommand, + stdout: bool, + force: bool, + ) -> color_eyre::Result<()> { let mut snippets = self.filter_snippets(filters)?; snippets.sort_by(|a, b| a.index.cmp(&b.index)); self.make_search( snippets, self.highlighter.skim_theme.clone(), self.highlighter.selection_style, - stdout, exact, + command, + stdout, + force, )?; Ok(()) } diff --git a/src/the_way/search.rs b/src/the_way/search.rs index bf41522..6a90335 100644 --- a/src/the_way/search.rs +++ b/src/the_way/search.rs @@ -125,6 +125,36 @@ impl SkimItem for SearchSnippet { } } +#[derive(Debug, Clone, Copy)] +pub(crate) enum SkimCommand { + Copy, + Delete, + Edit, + View, + All, +} + +impl SkimCommand { + pub fn keys(&self) -> Vec<&'static str> { + match self { + SkimCommand::Copy | SkimCommand::Delete | SkimCommand::Edit | SkimCommand::View => { + vec!["Enter"] + } + SkimCommand::All => vec!["Enter", "shift-left", "shift-right"], + } + } + + pub fn names(&self) -> Vec<&'static str> { + match self { + SkimCommand::Copy => vec!["copy"], + SkimCommand::Delete => vec!["delete"], + SkimCommand::Edit => vec!["edit"], + SkimCommand::View => vec!["view"], + SkimCommand::All => vec!["copy", "delete", "edit"], + } + } +} + impl TheWay { /// Converts a list of snippets into searchable objects and opens a fuzzy search window with the /// bottom panel listing each snippet's index, description, language and tags @@ -134,8 +164,10 @@ impl TheWay { snippets: Vec, skim_theme: String, selection_style: Style, - stdout: bool, exact: bool, + command: SkimCommand, + stdout: bool, + force: bool, ) -> color_eyre::Result<()> { let default_language = Language::default(); @@ -163,18 +195,28 @@ impl TheWay { index: snippet.index, }); } + let bind = command + .keys() + .into_iter() + .map(|s| format!("{s}:accept")) + .collect::>(); + let header = format!( + "Press {}", + command + .keys() + .into_iter() + .zip(command.names().into_iter()) + .map(|(key, name)| format!("{key} to {name}")) + .collect::>() + .join(", "), + ); + let options = SkimOptionsBuilder::default() .height(Some("100%")) .preview(Some("")) .preview_window(Some("up:70%:wrap")) - .bind(vec![ - "shift-left:accept", - "shift-right:accept", - "Enter:accept", - ]) - .header(Some( - "Press Enter to copy, Shift-left to delete, Shift-right to edit", - )) + .bind(bind.iter().map(|s| s.as_ref()).collect()) + .header(Some(&header)) .exact(exact) .multi(true) .reverse(true) @@ -195,14 +237,27 @@ impl TheWay { .as_any() .downcast_ref::() .ok_or(LostTheWay::SearchError)?; - match key { - Key::Enter => { + + match (command, key) { + (SkimCommand::Copy, Key::Enter) => { + self.copy(snippet.index, stdout)?; + } + (SkimCommand::Delete, Key::Enter) => { + self.delete(snippet.index, force)?; + } + (SkimCommand::Edit, Key::Enter) => { + self.edit(snippet.index)?; + } + (SkimCommand::View, Key::Enter) => { + self.view(snippet.index)?; + } + (SkimCommand::All, Key::Enter) => { self.copy(snippet.index, stdout)?; } - Key::ShiftLeft => { - self.delete(snippet.index, false)?; + (SkimCommand::All, Key::ShiftLeft) => { + self.delete(snippet.index, force)?; } - Key::ShiftRight => { + (SkimCommand::All, Key::ShiftRight) => { self.edit(snippet.index)?; } _ => (),