diff --git a/Cargo.lock b/Cargo.lock index 075a712032..45ab8ebe26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1566,6 +1566,7 @@ dependencies = [ "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sublime_fuzzy 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "surf 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2443,6 +2444,11 @@ name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sublime_fuzzy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "subprocess" version = "0.1.18" @@ -3247,6 +3253,7 @@ dependencies = [ "checksum stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4725650978235083241fab0fdc8e694c3de37821524e7534a1a9061d1068af" "checksum static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4f8de36da215253eb5f24020bfaa0646613b48bf7ebe36cdfa37c3b3b33b241" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum sublime_fuzzy 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97bd7ad698ea493a3a7f60c2ffa117c234f341e09f8cc2d39cef10cdde077acf" "checksum subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "28fc0f40f0c0da73339d347aa7d6d2b90341a95683a47722bc4eebed71ff3c00" "checksum surf 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "018eed64aede455beb88505d50c5c64882bebbe0996d4b660c272e3d8bb6f883" "checksum syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ee06ea4b620ab59a2267c6b48be16244a3389f8bfa0986bdd15c35b890b00af3" diff --git a/Cargo.toml b/Cargo.toml index cfe107e9be..e81bc0ee69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,7 @@ num-bigint = { version = "0.2.3", features = ["serde"] } bigdecimal = { version = "0.1.0", features = ["serde"] } natural = "0.3.0" serde_urlencoded = "0.6.1" +sublime_fuzzy = "0.5" neso = { version = "0.5.0", optional = true } crossterm = { version = "0.10.2", optional = true } diff --git a/src/cli.rs b/src/cli.rs index 8ed2b9bd55..af5a02a313 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -10,6 +10,7 @@ use crate::context::Context; use crate::data::Value; pub(crate) use crate::errors::ShellError; use crate::git::current_branch; +use crate::histsearch; use crate::parser::registry::Signature; use crate::parser::{hir, CallNode, Pipeline, PipelineElement, TokenNode}; use crate::prelude::*; @@ -333,6 +334,12 @@ pub async fn cli() -> Result<(), Box> { rl.set_edit_mode(edit_mode); + // Register Ctrl-r for history fuzzy search + // rustyline doesn't support custom commands, so we override Ctrl-D (EOF) + rl.bind_sequence(rustyline::KeyPress::Ctrl('R'), rustyline::Cmd::EndOfFile); + // Redefine Ctrl-D to same command as Ctrl-C + rl.bind_sequence(rustyline::KeyPress::Ctrl('D'), rustyline::Cmd::Interrupt); + let readline = rl.readline(&format!( "{}{}> ", cwd, @@ -347,6 +354,12 @@ pub async fn cli() -> Result<(), Box> { rl.add_history_entry(line.clone()); } + LineResult::SearchHist => { + let hist = std::fs::read_to_string("history.txt").expect("Cannot open history.txt"); + let lines = hist.lines().rev().collect(); + histsearch::select_from_list(&lines); + } + LineResult::CtrlC => { if ctrlcbreak { std::process::exit(0); @@ -390,6 +403,7 @@ pub async fn cli() -> Result<(), Box> { enum LineResult { Success(String), + SearchHist, Error(String, ShellError), CtrlC, Break, @@ -517,7 +531,7 @@ async fn process_line(readline: Result, ctx: &mut Context LineResult::Success(line.clone()) } Err(ReadlineError::Interrupted) => LineResult::CtrlC, - Err(ReadlineError::Eof) => LineResult::Break, + Err(ReadlineError::Eof) => LineResult::SearchHist, // Override LineResult::Break Err(err) => { println!("Error: {:?}", err); LineResult::Break diff --git a/src/histsearch.rs b/src/histsearch.rs index d5db186809..495b0d5a4e 100644 --- a/src/histsearch.rs +++ b/src/histsearch.rs @@ -3,7 +3,7 @@ use crossterm::{cursor, terminal, ClearType, InputEvent, KeyEvent, RawScreen}; use std::io::Write; use sublime_fuzzy::best_match; -fn select_from_list(lines: &Vec<&str>) { +pub fn select_from_list(lines: &Vec<&str>) { const MAX_RESULTS: usize = 5; #[derive(PartialEq)] enum State { @@ -163,9 +163,3 @@ fn paint_selection_list(lines: &Vec<&str>, selected: usize) { // Clear additional lines from previous selection terminal().clear(ClearType::FromCursorDown).unwrap(); } - -fn main() { - let hist = std::fs::read_to_string("history.txt").expect("Cannot open history.txt"); - let lines = hist.lines().rev().collect(); - select_from_list(&lines); -} diff --git a/src/lib.rs b/src/lib.rs index 1aedc2e11f..9802e2f686 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ mod errors; mod evaluate; mod format; mod git; +mod histsearch; mod parser; mod plugin; mod shell;