From 4ea4644b90d95724d0fc0c6d37294f3dc8b331b9 Mon Sep 17 00:00:00 2001 From: Patrick Auernig Date: Mon, 6 Jan 2025 18:52:03 +0100 Subject: [PATCH] feat(tui): Add input for entry rename and related handle events --- src/main.rs | 12 +++++++----- src/tui.rs | 51 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index c6284de..8c68847 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,22 +26,24 @@ struct Projects { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -struct Project(PathBuf); +struct Project { + path: PathBuf, +} impl Project { pub fn path(&self) -> &PathBuf { - &self.0 + &self.path } pub fn name(&self) -> String { - let name = self.0.file_name().unwrap(); + let name = self.path.file_name().unwrap(); name.to_string_lossy().to_string() } } impl From for Project { - fn from(value: PathBuf) -> Self { - Self(value) + fn from(path: PathBuf) -> Self { + Self { path } } } diff --git a/src/tui.rs b/src/tui.rs index 28b4b61..17ba011 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -23,6 +23,7 @@ enum Message { SelectNext, Confirm, SearchUpdate, + RenameEntry, } @@ -37,6 +38,7 @@ enum Mode { struct State { projects: Projects, search: Input, + rename: Input, mode: Mode, should_exit: bool, project_table: TableState, @@ -51,6 +53,7 @@ impl State { Self { projects, search: Input::default(), + rename: Input::default(), mode: Mode::default(), should_exit: false, project_table, @@ -117,6 +120,19 @@ fn handle_key_event(state: &mut State, tx: &mut mpsc::Sender, event: Ke state.search.handle(InputRequest::DeletePrevChar); Message::SearchUpdate } + (Mode::Search, KeyModifiers::CONTROL, KeyCode::Char('r')) => { + state.mode = Mode::Rename; + Message::Noop + } + (Mode::Rename, KeyModifiers::NONE, KeyCode::Esc) => { + state.mode = Mode::Search; + Message::Noop + } + (Mode::Rename, KeyModifiers::NONE, KeyCode::Char(c)) => { + state.rename.handle(InputRequest::InsertChar(c)); + Message::Noop + } + (Mode::Rename, KeyModifiers::NONE, KeyCode::Enter) => Message::RenameEntry, (_, _, KeyCode::Enter) => Message::Confirm, _ => Message::Noop, @@ -160,6 +176,7 @@ fn handle_messages(state: &mut State, rx: &mut mpsc::Receiver) -> Resul Message::SearchUpdate => { state.project_table.select_first(); } + Message::RenameEntry => {} _ => (), } @@ -171,37 +188,29 @@ fn draw(state: &mut State, frame: &mut Frame) { let block = Block::default().borders(Borders::ALL); frame.render_widget(&block, frame.area()); - match state.mode { - Mode::Search => { - let layout = Layout::vertical([Constraint::Fill(1), Constraint::Max(2)]); - let inner_area = block.inner(frame.area()); - let layout_rects = layout.split(inner_area); - draw_list(state, frame, layout_rects[0]); - draw_search(state, frame, layout_rects[1]); - } - Mode::Rename => { - let layout = Layout::vertical([Constraint::Fill(1)]); - let inner_area = block.inner(frame.area()); - let layout_rects = layout.split(inner_area); - draw_list(state, frame, layout_rects[0]); - } - } + let layout = Layout::vertical([Constraint::Fill(1), Constraint::Max(2)]); + let inner_area = block.inner(frame.area()); + let layout_rects = layout.split(inner_area); + draw_list(state, frame, layout_rects[0]); + draw_status(state, frame, layout_rects[1]); } -fn draw_search(state: &mut State, frame: &mut Frame, area: Rect) { - const PROMPT_PREFIX: &str = "Search: "; +fn draw_status(state: &mut State, frame: &mut Frame, area: Rect) { + let (prefix, input) = match &state.mode { + Mode::Search => ("Search: ", &state.search), + Mode::Rename => ("Rename: ", &state.rename), + }; - let search_input = &state.search; + let scroll_offset = (0, input.visual_scroll(area.width as usize) as u16); - let scroll_offset = (0, search_input.visual_scroll(area.width as usize) as u16); + let prompt = format!("{prefix}{}", input.value()); - let prompt = format!("{PROMPT_PREFIX}{}", search_input.value()); let search = Paragraph::new(prompt).scroll(scroll_offset); frame.render_widget(search, area); let cursor_pos = ( - area.x + (search_input.visual_cursor() + PROMPT_PREFIX.len()) as u16, + area.x + (input.visual_cursor() + prefix.len()) as u16, area.y, ); frame.set_cursor_position(cursor_pos)