diff --git a/src/main.rs b/src/main.rs index ada8010..c163999 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,6 +38,9 @@ pub struct App<'a> { /// The line the user inputs cmdline: String, + /// The position of the cursor + cmdline_position: u16, + /// Original text text_orig: Arc, @@ -46,9 +49,6 @@ pub struct App<'a> { /// Should every keystroke transform the original text? autorun: bool, - - /// Should this command be run when the program starts - run_initial: bool, } impl App<'_> { @@ -57,43 +57,62 @@ impl App<'_> { let text_orig = Arc::new(input); let command_result = CommandResult::default(); let hidden_command = template.command(); + let cmdline_position = 0; match template { Template::Generic(_) => Self { cmdline: String::new(), + cmdline_position, text_orig, command_result: CommandResult::default(), autorun: true, hidden_command, hidden_options: vec![], - run_initial: true, }, Template::Jq => Self { - cmdline: String::from("."), + cmdline: String::from("'.'"), + cmdline_position: 2, text_orig, command_result, autorun: true, hidden_command, hidden_options: vec!["-C"], - run_initial: true, }, Template::Grep | Template::Rg => Self { - cmdline: String::new(), + cmdline: String::from("'^'"), + cmdline_position: 2, text_orig, command_result: CommandResult::default(), autorun: true, hidden_command, hidden_options: vec!["--color=always"], - run_initial: false, }, - Template::Sed | Template::Awk => Self { - cmdline: String::new(), + Template::Sed => Self { + cmdline: String::from("'s///g'"), + cmdline_position: 3_u16, text_orig, command_result: CommandResult::default(), autorun: true, hidden_command, hidden_options: vec![], - run_initial: false, + }, + Template::Awk => Self { + cmdline: String::new(), + cmdline_position, + text_orig, + command_result: CommandResult::default(), + autorun: true, + hidden_command, + hidden_options: vec![], + }, + Template::Perl => Self { + cmdline: String::from("'s/./_/'"), + cmdline_position: 3_u16, + text_orig, + command_result: CommandResult::default(), + autorun: true, + hidden_command, + hidden_options: vec!["-p", "-e"], }, } } @@ -106,6 +125,7 @@ pub enum Template { Rg, Sed, Awk, + Perl, } impl Template { @@ -115,6 +135,8 @@ impl Template { "grep" => Self::Grep, "rg" => Self::Rg, "sed" => Self::Sed, + "awk" => Self::Awk, + "perl" => Self::Perl, c => Self::Generic(c.to_string()), } } @@ -127,6 +149,7 @@ impl Template { Template::Rg => String::from("rg"), Template::Sed => String::from("sed"), Template::Awk => String::from("awk"), + Template::Perl => String::from("perl"), } } } @@ -170,10 +193,14 @@ fn main() -> Result<()> { } fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result> { - if app.run_initial { + if !app.cmdline.is_empty() { command::run(&mut app); } + if app.cmdline_position == 0 { + app.cmdline_position = app.cmdline.len() as u16; + } + loop { terminal.draw(|f| ui(f, &app))?; @@ -183,20 +210,49 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result { - app.cmdline.push(c); + app.cmdline.insert(app.cmdline_position as usize, c); + app.cmdline_position = app.cmdline_position.saturating_add(1); if app.autorun { command::run(&mut app); } } KeyCode::Backspace => { - app.cmdline.pop(); + if app.cmdline_position > 0 { + app.cmdline_position = app.cmdline_position.saturating_sub(1); + app.cmdline.remove(app.cmdline_position as usize); + } + if app.autorun { command::run(&mut app); } } + KeyCode::Delete => { + if (app.cmdline_position as usize) < app.cmdline.len() { + app.cmdline.remove(app.cmdline_position as usize); + } + + if app.autorun { + command::run(&mut app); + } + } + KeyCode::End => { + app.cmdline_position = app.cmdline.len() as u16; + } + KeyCode::Home => { + app.cmdline_position = 0_u16; + } KeyCode::Enter => { return Ok(Some(app.cmdline.clone())); } + KeyCode::Left => { + app.cmdline_position = app.cmdline_position.saturating_sub(1); + } + KeyCode::Right => { + app.cmdline_position = std::cmp::min( + app.cmdline.len() as u16, + app.cmdline_position.saturating_add(1), + ); + } _ => {} } } @@ -214,9 +270,8 @@ fn ui(f: &mut Frame, app: &App) { .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) .split(vertical_chunks[0]); - // TODO: Get rid of this allocation f.render_widget( - Paragraph::new(app.text_orig.to_string()) + Paragraph::new(app.text_orig.as_str()) .block(Block::default().title("Orig").borders(Borders::ALL)), chunks[0], ); @@ -230,7 +285,7 @@ fn ui(f: &mut Frame, app: &App) { ui_output(f, chunks[1], app); f.set_cursor( - vertical_chunks[1].x + app.cmdline.len() as u16 + 1, + vertical_chunks[1].x + app.cmdline_position + 1, vertical_chunks[1].y + 1, ); }