From 0113661c81a0584028637ec4c7d5e583a8c18085 Mon Sep 17 00:00:00 2001 From: Chris Gillespie <6572184+gillespiecd@users.noreply.github.com> Date: Mon, 9 Nov 2020 08:23:41 -0800 Subject: [PATCH] Flag to clear history file (#2720) --- crates/nu-cli/src/cli.rs | 7 +++ crates/nu-cli/src/commands/history.rs | 61 ++++++++++++++++++--------- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 8da97bc1ce..6c05df65ce 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -323,6 +323,7 @@ pub async fn run_vec_of_pipelines( #[cfg(feature = "rustyline-support")] fn convert_rustyline_result_to_string(input: Result) -> LineResult { match input { + Ok(s) if s == "history -c" || s == "history --clear" => LineResult::ClearHistory, Ok(s) => LineResult::Success(s), Err(ReadlineError::Interrupted) => LineResult::CtrlC, Err(ReadlineError::Eof) => LineResult::CtrlD, @@ -499,6 +500,11 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box> { context.maybe_print_errors(Text::from(line)); } + LineResult::ClearHistory => { + rl.clear_history(); + let _ = rl.save_history(&history_path); + } + LineResult::Error(line, err) => { rl.add_history_entry(&line); let _ = rl.save_history(&history_path); @@ -848,6 +854,7 @@ pub enum LineResult { Break, CtrlC, CtrlD, + ClearHistory, } pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result { diff --git a/crates/nu-cli/src/commands/history.rs b/crates/nu-cli/src/commands/history.rs index 5b5b963e1f..586efee6b1 100644 --- a/crates/nu-cli/src/commands/history.rs +++ b/crates/nu-cli/src/commands/history.rs @@ -27,6 +27,11 @@ pub fn history_path(config: &dyn Conf) -> PathBuf { }) } +#[derive(Deserialize)] +struct Arguments { + clear: Option, +} + pub struct History; #[async_trait] @@ -36,7 +41,7 @@ impl WholeStreamCommand for History { } fn signature(&self) -> Signature { - Signature::build("history") + Signature::build("history").switch("clear", "Clears out the history entries", Some('c')) } fn usage(&self) -> &str { @@ -48,31 +53,45 @@ impl WholeStreamCommand for History { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - history(args, registry) + history(args, registry).await } } -fn history(args: CommandArgs, _registry: &CommandRegistry) -> Result { +async fn history( + args: CommandArgs, + _registry: &CommandRegistry, +) -> Result { let config: Box = Box::new(NuConfig::new()); - let tag = args.call_info.name_tag; - let path = history_path(&config); - let file = File::open(path); - if let Ok(file) = file { - let reader = BufReader::new(file); - let output = reader.lines().filter_map(move |line| match line { - Ok(line) => Some(ReturnSuccess::value( - UntaggedValue::string(line).into_value(tag.clone()), - )), - Err(_) => None, - }); + let tag = args.call_info.name_tag.clone(); + let (Arguments { clear }, _) = args.process(&_registry).await?; - Ok(futures::stream::iter(output).to_output_stream()) - } else { - Err(ShellError::labeled_error( - "Could not open history", - "history file could not be opened", - tag, - )) + let path = history_path(&config); + + match clear { + Some(_) => { + // This is a NOOP, the logic to clear is handled in cli.rs + Ok(OutputStream::empty()) + } + None => { + if let Ok(file) = File::open(path) { + let reader = BufReader::new(file); + // Skips the first line, which is a Rustyline internal + let output = reader.lines().skip(1).filter_map(move |line| match line { + Ok(line) => Some(ReturnSuccess::value( + UntaggedValue::string(line).into_value(tag.clone()), + )), + Err(_) => None, + }); + + Ok(futures::stream::iter(output).to_output_stream()) + } else { + Err(ShellError::labeled_error( + "Could not open history", + "history file could not be opened", + tag, + )) + } + } } }