From 1c95bf05dc134aac493d1c7ce8a99de3d458561b Mon Sep 17 00:00:00 2001 From: Pirmin Kalberer Date: Wed, 18 Sep 2019 00:21:39 +0200 Subject: [PATCH] Process selected command --- src/cli.rs | 40 ++++++++++++++++++++++++++++++---------- src/histsearch.rs | 20 +++++++++++--------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index af5a02a313..5cfcb1475a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -340,26 +340,47 @@ pub async fn cli() -> Result<(), Box> { // Redefine Ctrl-D to same command as Ctrl-C rl.bind_sequence(rustyline::KeyPress::Ctrl('D'), rustyline::Cmd::Interrupt); - let readline = rl.readline(&format!( + let prompt = &format!( "{}{}> ", cwd, match current_branch() { Some(s) => format!("({})", s), None => "".to_string(), } - )); + ); + let mut initial_command = Some(String::new()); + let mut readline = Err(ReadlineError::Eof); + while let Some(ref cmd) = initial_command { + readline = rl.readline_with_initial(prompt, (&cmd, "")); + if let Err(ReadlineError::Eof) = &readline { + // Fuzzy search in history + let hist = std::fs::read_to_string("history.txt").expect("Cannot open history.txt"); + let lines = hist.lines().rev().collect(); + let selection = histsearch::select_from_list(&lines); // Clears last line with prompt + match selection { + histsearch::SelectionResult::Selected(line) => { + println!("{}{}", &prompt, &line); // TODO: colorize prompt + readline = Ok(line.clone()); + initial_command = None; + } + histsearch::SelectionResult::Edit(line) => { + initial_command = Some(line); + } + histsearch::SelectionResult::NoSelection => { + readline = Ok("".to_string()); + initial_command = None; + } + } + } else { + initial_command = None; + } + } match process_line(readline, &mut context).await { LineResult::Success(line) => { 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); @@ -403,7 +424,6 @@ pub async fn cli() -> Result<(), Box> { enum LineResult { Success(String), - SearchHist, Error(String, ShellError), CtrlC, Break, @@ -531,7 +551,7 @@ async fn process_line(readline: Result, ctx: &mut Context LineResult::Success(line.clone()) } Err(ReadlineError::Interrupted) => LineResult::CtrlC, - Err(ReadlineError::Eof) => LineResult::SearchHist, // Override LineResult::Break + Err(ReadlineError::Eof) => LineResult::Break, Err(err) => { println!("Error: {:?}", err); LineResult::Break diff --git a/src/histsearch.rs b/src/histsearch.rs index 495b0d5a4e..25e1fb7196 100644 --- a/src/histsearch.rs +++ b/src/histsearch.rs @@ -3,7 +3,13 @@ use crossterm::{cursor, terminal, ClearType, InputEvent, KeyEvent, RawScreen}; use std::io::Write; use sublime_fuzzy::best_match; -pub fn select_from_list(lines: &Vec<&str>) { +pub enum SelectionResult { + Selected(String), + Edit(String), + NoSelection, +} + +pub fn select_from_list(lines: &Vec<&str>) -> SelectionResult { const MAX_RESULTS: usize = 5; #[derive(PartialEq)] enum State { @@ -70,7 +76,7 @@ pub fn select_from_list(lines: &Vec<&str>) { cursor.move_up(selected_lines.len() as u16); } let (_x, y) = cursor.pos(); - let _ = cursor.goto(0, y); + let _ = cursor.goto(0, y - 1); let _ = cursor.show(); let _ = RawScreen::disable_raw_mode(); @@ -79,13 +85,9 @@ pub fn select_from_list(lines: &Vec<&str>) { terminal.clear(ClearType::FromCursorDown).unwrap(); match state { - State::Selected(idx) => { - print!("{}", lines[idx]); - } - State::Edit(idx) => { - print!("{}", lines[idx]); - } - _ => {} + State::Selected(idx) => SelectionResult::Selected(lines[idx].to_string()), + State::Edit(idx) => SelectionResult::Edit(lines[idx].to_string()), + _ => SelectionResult::NoSelection, } }