From 5d3b67cc755e1ffc2d9e986dd0a725160d09ae69 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 17 Mar 2023 11:29:16 +0200 Subject: Use rustyline --- src/main.rs | 50 +++++++++++++++++++++++++++++++------------------- src/parser.rs | 4 +--- 2 files changed, 32 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index bcbfe1c..e02be3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,8 @@ mod parser; use clap::Parser; use parser::*; -use std::{io, io::Write, ops::ControlFlow, process::Command}; +use rustyline::{error::ReadlineError, DefaultEditor}; +use std::{io, ops::ControlFlow, process::Command}; use thiserror::Error; /// Shackle Shell - A replacement for git-shell with repo management commands built in. @@ -15,18 +16,6 @@ struct Args { command: Option, } -fn prompt() -> Result<(), ShackleError> { - print!("> "); - io::stdout().flush()?; - Ok(()) -} - -fn read_stdin() -> Result { - let mut buffer = String::new(); - io::stdin().read_line(&mut buffer)?; - Ok(buffer) -} - fn main() -> Result<(), ShackleError> { let args = Args::parse(); match args.command { @@ -95,13 +84,34 @@ fn run_command(user_input: String) -> Result, ShackleError> } fn run_interactive_loop() -> Result<(), ShackleError> { + let mut rl = DefaultEditor::new()?; loop { - prompt()?; - let user_input = read_stdin()?; - // TODO: should this report errors differently? Most of the errors are from user actions. - let control_flow = run_command(user_input)?; - if control_flow.is_break() { - break; + let readline = rl.readline("> "); + match readline { + Ok(user_input) => { + rl.add_history_entry(user_input.as_str())?; + match run_command(user_input) { + Ok(control_flow) => { + if control_flow.is_break() { + break; + } + } + Err(e) => { + println!("{:?}", e); + } + } + } + Err(ReadlineError::Interrupted) => { + println!("Interrupted"); + break; + } + Err(ReadlineError::Eof) => { + break; + } + Err(err) => { + println!("Error: {:?}", err); + break; + } } } Ok(()) @@ -115,4 +125,6 @@ pub enum ShackleError { IoError(#[from] io::Error), #[error(transparent)] GitError(#[from] git2::Error), + #[error(transparent)] + ReadlineError(#[from] ReadlineError), } diff --git a/src/parser.rs b/src/parser.rs index 89e0d76..9938924 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -58,9 +58,7 @@ impl FromStr for ShackleCommand { fn from_str(s: &str) -> Result { let trimmed = s.trim(); - if s.len() == 0 { - Ok(ShackleCommand::Exit) - } else if trimmed.len() == 0 { + if trimmed.len() == 0 { Ok(ShackleCommand::Whitespace) } else { let lexed = shlex::split(trimmed); -- cgit v1.2.3