mirror of
https://codeberg.org/unspeaker/perch.git
synced 2025-12-06 09:36:42 +01:00
add edit modes
This commit is contained in:
parent
06b4efd70e
commit
870bf249d8
4 changed files with 53 additions and 30 deletions
47
src/keys.rs
47
src/keys.rs
|
|
@ -25,7 +25,16 @@ impl Handle<TuiIn> for Taggart {
|
|||
let x_min = self.offset;
|
||||
let x_max = self.offset + self.display.h().saturating_sub(1);
|
||||
let event = &*input.event();
|
||||
match &self.editing {
|
||||
match &self.mode {
|
||||
Some(Mode::Edit { .. }) => match event {
|
||||
press!(Char(c)) => self.edit_insert(*c),
|
||||
press!(Shift-Char(c)) => self.edit_insert(c.to_uppercase().next().unwrap()),
|
||||
press!(Backspace) => self.edit_backspace(),
|
||||
press!(Delete) => self.edit_delete(),
|
||||
press!(Enter) => self.edit_confirm(),
|
||||
press!(Esc) => self.edit_cancel(),
|
||||
_ => {}
|
||||
},
|
||||
None => match event {
|
||||
press!(Char('q')) => { input.done() },
|
||||
press!(Up) => { self.cursor = self.cursor.saturating_sub(1); },
|
||||
|
|
@ -40,16 +49,8 @@ impl Handle<TuiIn> for Taggart {
|
|||
press!(Char('[')) => { self.columns.0[self.column].width =
|
||||
self.columns.0[self.column].width.saturating_sub(1).max(5); }
|
||||
_ => {}
|
||||
},
|
||||
Some(_value) => match event {
|
||||
press!(Char(c)) => self.edit_insert(*c),
|
||||
press!(Shift-Char(c)) => self.edit_insert(c.to_uppercase().next().unwrap()),
|
||||
press!(Backspace) => self.edit_backspace(),
|
||||
press!(Delete) => self.edit_delete(),
|
||||
press!(Enter) => self.edit_confirm(),
|
||||
press!(Esc) => self.edit_cancel(),
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
_ => todo!("{:?}", self.mode)
|
||||
}
|
||||
if self.cursor < x_min {
|
||||
self.offset = self.cursor;
|
||||
|
|
@ -77,32 +78,38 @@ impl Taggart {
|
|||
{
|
||||
let value = (column.getter)(&self.entries[self.cursor]);
|
||||
let value = format!("{}", value.unwrap_or_default());
|
||||
self.editing = Some((value.len(), value));
|
||||
self.mode = Some(Mode::Edit { index: value.len(), value });
|
||||
}
|
||||
}
|
||||
pub fn edit_cancel (&mut self) {
|
||||
self.editing = None;
|
||||
self.mode = None;
|
||||
}
|
||||
pub fn edit_confirm (&mut self) {
|
||||
if let Some((_edit_index, value)) = &self.editing
|
||||
if let Some(Mode::Edit { value, .. }) = &self.mode
|
||||
&& let Some(column) = self.columns.0.get(self.column)
|
||||
&& let Some(setter) = &column.setter
|
||||
&& self.entries.get_mut(self.cursor).is_some()
|
||||
{
|
||||
setter(self.entries.as_mut_slice(), self.cursor, value)
|
||||
setter(self.entries.as_mut_slice(), self.cursor, value);
|
||||
self.mode = None;
|
||||
}
|
||||
self.editing = None;
|
||||
}
|
||||
pub fn edit_insert (&mut self, c: char) {
|
||||
if let Some((edit_index, value)) = &mut self.editing {
|
||||
self.editing = Some((*edit_index + 1, format!("{value}{c}")));
|
||||
if let Some(Mode::Edit { value, index }) = &self.mode {
|
||||
self.mode = Some(Mode::Edit {
|
||||
index: *index + 1,
|
||||
value: format!("{value}{c}")
|
||||
});
|
||||
}
|
||||
}
|
||||
pub fn edit_backspace (&mut self) {
|
||||
if let Some((edit_index, value)) = &mut self.editing {
|
||||
if let Some(Mode::Edit { value, index }) = &self.mode {
|
||||
let mut chars = value.chars();
|
||||
chars.next_back();
|
||||
self.editing = Some((edit_index.saturating_sub(1), chars.as_str().into()));
|
||||
self.mode = Some(Mode::Edit {
|
||||
index: index.saturating_sub(1),
|
||||
value: chars.as_str().into()
|
||||
});
|
||||
}
|
||||
}
|
||||
pub fn edit_delete (&mut self) {
|
||||
|
|
|
|||
19
src/model.rs
19
src/model.rs
|
|
@ -14,8 +14,23 @@ pub struct Taggart {
|
|||
pub column: usize,
|
||||
pub columns: Columns<Entry, fn(&Entry)->Option<Arc<str>>, fn(&mut [Entry], usize, &str)>,
|
||||
pub display: Measure<TuiOut>,
|
||||
pub editing: Option<(usize, String)>,
|
||||
pub tasks: Vec<Task>,
|
||||
pub mode: Option<Mode>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Mode {
|
||||
Help,
|
||||
Edit {
|
||||
value: String,
|
||||
index: usize,
|
||||
},
|
||||
Apply {
|
||||
value: bool,
|
||||
},
|
||||
Unsaved {
|
||||
value: u8
|
||||
},
|
||||
}
|
||||
|
||||
impl Taggart {
|
||||
|
|
@ -26,7 +41,7 @@ impl Taggart {
|
|||
offset: 0,
|
||||
column: 2,
|
||||
display: Measure::new(),
|
||||
editing: None,
|
||||
mode: None,
|
||||
columns: Columns::default(),
|
||||
tasks: vec![],
|
||||
entries,
|
||||
|
|
|
|||
|
|
@ -34,13 +34,14 @@ impl Content<TuiOut> for Taggart {
|
|||
Color::Rgb(0, 0, 0),
|
||||
Color::Rgb(192, 192, 192),
|
||||
Fill::x(Bsp::a(
|
||||
Fill::x(Align::w(Tui::bold(true, if self.editing.is_some() {
|
||||
Fill::x(Align::w(Tui::bold(true, match self.mode {
|
||||
Some(Mode::Edit { .. }) => {
|
||||
Bsp::e(
|
||||
Tui::bg(Self::BG_EDIT, Tui::fg(Self::FG_EDIT, " EDIT ")),
|
||||
" Esc: cancel, Enter: set value"
|
||||
)
|
||||
} else {
|
||||
Bsp::e(
|
||||
},
|
||||
_ => Bsp::e(
|
||||
Tui::bg(Self::BG_BROWSE, Tui::fg(Self::FG_BROWSE, " BROWSE ")),
|
||||
" Q: exit, Arrows: select, Space: open, Enter: edit"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl<'a> TreeTable<'a> {
|
|||
..
|
||||
}) in self.0.columns.0.iter().enumerate() {
|
||||
to.area[0] = *x;
|
||||
if let Some((edit_index, value)) = self.0.editing.as_ref()
|
||||
if let Some(Mode::Edit { index: edit_index, value }) = self.0.mode.as_ref()
|
||||
&& self.0.column == column_index
|
||||
&& self.0.cursor == cursor
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue