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_min = self.offset;
|
||||||
let x_max = self.offset + self.display.h().saturating_sub(1);
|
let x_max = self.offset + self.display.h().saturating_sub(1);
|
||||||
let event = &*input.event();
|
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 {
|
None => match event {
|
||||||
press!(Char('q')) => { input.done() },
|
press!(Char('q')) => { input.done() },
|
||||||
press!(Up) => { self.cursor = self.cursor.saturating_sub(1); },
|
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 =
|
press!(Char('[')) => { self.columns.0[self.column].width =
|
||||||
self.columns.0[self.column].width.saturating_sub(1).max(5); }
|
self.columns.0[self.column].width.saturating_sub(1).max(5); }
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
}
|
||||||
Some(_value) => match event {
|
_ => todo!("{:?}", self.mode)
|
||||||
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(),
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if self.cursor < x_min {
|
if self.cursor < x_min {
|
||||||
self.offset = self.cursor;
|
self.offset = self.cursor;
|
||||||
|
|
@ -77,32 +78,38 @@ impl Taggart {
|
||||||
{
|
{
|
||||||
let value = (column.getter)(&self.entries[self.cursor]);
|
let value = (column.getter)(&self.entries[self.cursor]);
|
||||||
let value = format!("{}", value.unwrap_or_default());
|
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) {
|
pub fn edit_cancel (&mut self) {
|
||||||
self.editing = None;
|
self.mode = None;
|
||||||
}
|
}
|
||||||
pub fn edit_confirm (&mut self) {
|
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(column) = self.columns.0.get(self.column)
|
||||||
&& let Some(setter) = &column.setter
|
&& let Some(setter) = &column.setter
|
||||||
&& self.entries.get_mut(self.cursor).is_some()
|
&& 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) {
|
pub fn edit_insert (&mut self, c: char) {
|
||||||
if let Some((edit_index, value)) = &mut self.editing {
|
if let Some(Mode::Edit { value, index }) = &self.mode {
|
||||||
self.editing = Some((*edit_index + 1, format!("{value}{c}")));
|
self.mode = Some(Mode::Edit {
|
||||||
|
index: *index + 1,
|
||||||
|
value: format!("{value}{c}")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn edit_backspace (&mut self) {
|
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();
|
let mut chars = value.chars();
|
||||||
chars.next_back();
|
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) {
|
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 column: usize,
|
||||||
pub columns: Columns<Entry, fn(&Entry)->Option<Arc<str>>, fn(&mut [Entry], usize, &str)>,
|
pub columns: Columns<Entry, fn(&Entry)->Option<Arc<str>>, fn(&mut [Entry], usize, &str)>,
|
||||||
pub display: Measure<TuiOut>,
|
pub display: Measure<TuiOut>,
|
||||||
pub editing: Option<(usize, String)>,
|
|
||||||
pub tasks: Vec<Task>,
|
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 {
|
impl Taggart {
|
||||||
|
|
@ -26,7 +41,7 @@ impl Taggart {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
column: 2,
|
column: 2,
|
||||||
display: Measure::new(),
|
display: Measure::new(),
|
||||||
editing: None,
|
mode: None,
|
||||||
columns: Columns::default(),
|
columns: Columns::default(),
|
||||||
tasks: vec![],
|
tasks: vec![],
|
||||||
entries,
|
entries,
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,14 @@ impl Content<TuiOut> for Taggart {
|
||||||
Color::Rgb(0, 0, 0),
|
Color::Rgb(0, 0, 0),
|
||||||
Color::Rgb(192, 192, 192),
|
Color::Rgb(192, 192, 192),
|
||||||
Fill::x(Bsp::a(
|
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(
|
Bsp::e(
|
||||||
Tui::bg(Self::BG_EDIT, Tui::fg(Self::FG_EDIT, " EDIT ")),
|
Tui::bg(Self::BG_EDIT, Tui::fg(Self::FG_EDIT, " EDIT ")),
|
||||||
" Esc: cancel, Enter: set value"
|
" Esc: cancel, Enter: set value"
|
||||||
)
|
)
|
||||||
} else {
|
},
|
||||||
Bsp::e(
|
_ => Bsp::e(
|
||||||
Tui::bg(Self::BG_BROWSE, Tui::fg(Self::FG_BROWSE, " BROWSE ")),
|
Tui::bg(Self::BG_BROWSE, Tui::fg(Self::FG_BROWSE, " BROWSE ")),
|
||||||
" Q: exit, Arrows: select, Space: open, Enter: edit"
|
" Q: exit, Arrows: select, Space: open, Enter: edit"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ impl<'a> TreeTable<'a> {
|
||||||
..
|
..
|
||||||
}) in self.0.columns.0.iter().enumerate() {
|
}) in self.0.columns.0.iter().enumerate() {
|
||||||
to.area[0] = *x;
|
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.column == column_index
|
||||||
&& self.0.cursor == cursor
|
&& self.0.cursor == cursor
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue