зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-07 16:05:50 +03:00
update block and style only when mode changed in vim example
Этот коммит содержится в:
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user