feat(tui): Add input for entry rename and related handle events
This commit is contained in:
parent
a135e2417f
commit
4ea4644b90
12
src/main.rs
12
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<PathBuf> for Project {
|
||||
fn from(value: PathBuf) -> Self {
|
||||
Self(value)
|
||||
fn from(path: PathBuf) -> Self {
|
||||
Self { path }
|
||||
}
|
||||
}
|
||||
|
||||
|
51
src/tui.rs
51
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<Message>, 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<Message>) -> 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)
|
||||
|
Loading…
Reference in New Issue
Block a user