1
0
зеркало из https://github.com/glebtv/tui-textarea.git synced 2026-09-08 00:15:50 +03:00

update block and style only when mode changed in vim example

Этот коммит содержится в:
rhysd
2023-11-18 14:50:13 +09:00
родитель 0a5c190780
Коммит 306a976fc9

Просмотреть файл

@@ -22,22 +22,25 @@ enum Mode {
} }
impl Mode { impl Mode {
fn help_message(&self) -> &'static str { fn block<'a>(&self) -> Block<'a> {
match self { let help = match self {
Self::Normal => "type q to quit, type i to enter insert mode", Self::Normal => "type q to quit, type i to enter insert mode",
Self::Insert => "type Esc to back to normal mode", Self::Insert => "type Esc to back to normal mode",
Self::Visual => "type y to yank, type d to delete, type Esc to back to normal mode", Self::Visual => "type y to yank, type d to delete, type Esc to back to normal mode",
Self::Operator(_) => "move cursor to apply operator", Self::Operator(_) => "move cursor to apply operator",
} };
let title = format!("{} MODE ({})", self, help);
Block::default().borders(Borders::ALL).title(title)
} }
fn cursor_color(&self) -> Color { fn cursor_style(&self) -> Style {
match self { let color = match self {
Self::Normal => Color::Reset, Self::Normal => Color::Reset,
Self::Insert => Color::LightBlue, Self::Insert => Color::LightBlue,
Self::Visual => Color::LightYellow, Self::Visual => Color::LightYellow,
Self::Operator(_) => Color::LightGreen, Self::Operator(_) => Color::LightGreen,
} };
Style::default().fg(color).add_modifier(Modifier::REVERSED)
} }
} }
@@ -52,12 +55,6 @@ impl fmt::Display for Mode {
} }
} }
// State of Vim emulation
struct Vim {
mode: Mode,
pending: Input, // Pending input to handle a sequence with two keys like gg
}
// How the Vim emulation state transitions // How the Vim emulation state transitions
enum Transition { enum Transition {
Nop, Nop,
@@ -66,6 +63,12 @@ enum Transition {
Quit, Quit,
} }
// State of Vim emulation
struct Vim {
mode: Mode,
pending: Input, // Pending input to handle a sequence with two keys like gg
}
impl Vim { impl Vim {
fn new(mode: Mode) -> Self { fn new(mode: Mode) -> Self {
Self { Self {
@@ -81,7 +84,7 @@ impl Vim {
} }
} }
fn input(&self, input: Input, textarea: &mut TextArea<'_>) -> Transition { fn transition(&self, input: Input, textarea: &mut TextArea<'_>) -> Transition {
if input.key == Key::Null { if input.key == Key::Null {
return Transition::Nop; return Transition::Nop;
} }
@@ -396,23 +399,20 @@ fn main() -> io::Result<()> {
TextArea::default() TextArea::default()
}; };
textarea.set_block(Mode::Normal.block());
textarea.set_cursor_style(Mode::Normal.cursor_style());
let mut vim = Vim::new(Mode::Normal); let mut vim = Vim::new(Mode::Normal);
loop { loop {
// Show help message and current mode in title of the block
let title = format!("{} MODE ({})", vim.mode, vim.mode.help_message());
let block = Block::default().borders(Borders::ALL).title(title);
textarea.set_block(block);
// Change the cursor color looking at current mode
let color = vim.mode.cursor_color();
let style = Style::default().fg(color).add_modifier(Modifier::REVERSED);
textarea.set_cursor_style(style);
term.draw(|f| f.render_widget(textarea.widget(), f.size()))?; term.draw(|f| f.render_widget(textarea.widget(), f.size()))?;
vim = match vim.input(crossterm::event::read()?.into(), &mut textarea) { vim = match vim.transition(crossterm::event::read()?.into(), &mut textarea) {
Transition::Nop => vim, Transition::Mode(mode) if vim.mode != mode => {
Transition::Mode(mode) => Vim::new(mode), textarea.set_block(mode.block());
textarea.set_cursor_style(mode.cursor_style());
Vim::new(mode)
}
Transition::Nop | Transition::Mode(_) => vim,
Transition::Pending(input) => vim.with_pending(input), Transition::Pending(input) => vim.with_pending(input),
Transition::Quit => break, Transition::Quit => break,
} }