Skip to content

Commit

Permalink
Add change mode(c) support to vim normal mode (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
panarch authored Nov 3, 2024
1 parent 1da7abb commit 51f5f90
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 35 deletions.
1 change: 1 addition & 0 deletions core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub enum NotebookEvent {
pub enum KeyEvent {
A,
B,
C,
D,
E,
G,
Expand Down
22 changes: 20 additions & 2 deletions core/src/state/notebook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ impl NotebookState {

format!("Note '{name}' normal mode - delete inside {n}di")
}
EditingNormalMode(VimNormalState::Change(n)) => {
let name = &self.get_selected_note()?.name;

let n = if *n >= 2 {
format!("{n}")
} else {
"".to_owned()
};
format!("Note '{name}' normal mode - change '{n}c'")
}
EditingVisualMode(VimVisualState::Idle) => {
let name = &self.get_selected_note()?.name;

Expand Down Expand Up @@ -227,9 +237,10 @@ impl NotebookState {
a, A, I, G, g, s, S, x, ^, y, d, u, Ctrl+r
*/
vec![
"[i] Insert mode".to_owned(),
"[v] Visual mode".to_owned(),
"[n] Browse notes".to_owned(),
"[i] Insert".to_owned(),
"[v] Visual".to_owned(),
"[c] Change".to_owned(),
"[t] Toggle line number".to_owned(),
"[Ctrl+h] Show Vim keymap".to_owned(),
"[Esc] Quit".to_owned(),
Expand Down Expand Up @@ -298,6 +309,13 @@ impl NotebookState {
"[Esc] Cancel".to_owned(),
]
}
EditingNormalMode(VimNormalState::Change(n)) => {
vec![
format!("[c] Delete {n} lines and insert mode"),
"[Ctrl+h] Show Vim keymap".to_owned(),
"[Esc] Cancel".to_owned(),
]
}
EditingVisualMode(VimVisualState::Idle) => {
// more in the keymap
vec![
Expand Down
63 changes: 59 additions & 4 deletions core/src/state/notebook/inner_state/editing_normal_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum VimNormalState {
Delete(usize),
Delete2(usize, usize),
DeleteInside(usize),
Change(usize),
}

pub async fn consume(
Expand All @@ -37,6 +38,7 @@ pub async fn consume(
VimNormalState::Delete(n) => consume_delete(db, state, n, event).await,
VimNormalState::Delete2(n1, n2) => consume_delete2(db, state, n1, n2, event).await,
VimNormalState::DeleteInside(n) => consume_delete_inside(db, state, n, event).await,
VimNormalState::Change(n) => consume_change(db, state, n, event).await,
}
}

Expand Down Expand Up @@ -124,16 +126,21 @@ async fn consume_idle(

DeleteMode.into()
}
Key(KeyEvent::C) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Change(1));

ChangeMode.into()
}
Key(KeyEvent::X) => DeleteChars(1).into(),
Key(KeyEvent::S) => {
state.inner_state = InnerState::EditingInsertMode;

DeleteCharsAndInsertMode(1).into()
DeleteChars(1).into()
}
Key(KeyEvent::CapS) => {
state.inner_state = InnerState::EditingInsertMode;

DeleteLineAndInsertMode(1).into()
DeleteLines(1).into()
}
Key(KeyEvent::Num(n)) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Numbering(n.into()));
Expand Down Expand Up @@ -210,12 +217,12 @@ async fn consume_numbering(
Key(KeyEvent::S) => {
state.inner_state = InnerState::EditingInsertMode;

DeleteCharsAndInsertMode(n).into()
DeleteChars(n).into()
}
Key(KeyEvent::CapS) => {
state.inner_state = InnerState::EditingInsertMode;

DeleteLineAndInsertMode(n).into()
DeleteLines(n).into()
}
Key(KeyEvent::Y) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Yank(n));
Expand All @@ -227,6 +234,11 @@ async fn consume_numbering(

DeleteMode.into()
}
Key(KeyEvent::C) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Change(n));

ChangeMode.into()
}
Key(KeyEvent::Esc) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

Expand Down Expand Up @@ -448,6 +460,49 @@ async fn consume_delete_inside(
}
}

async fn consume_change(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
) -> Result<NotebookTransition> {
use Event::*;
use NormalModeTransition::*;

match event {
Key(KeyEvent::Num(NumKey::Zero)) => {
state.inner_state = InnerState::EditingInsertMode;

DeleteLineStart.into()
}
Key(KeyEvent::C) => {
state.inner_state = InnerState::EditingInsertMode;
DeleteLinesAndInsert(n).into()
}
Key(KeyEvent::E | KeyEvent::W) => {
state.inner_state = InnerState::EditingInsertMode;
DeleteWordEnd(n).into()
}
Key(KeyEvent::B) => {
state.inner_state = InnerState::EditingInsertMode;
DeleteWordBack(n).into()
}
Key(KeyEvent::DollarSign) => {
state.inner_state = InnerState::EditingInsertMode;
DeleteLineEnd(n).into()
}
Key(KeyEvent::CtrlH) => Ok(NotebookTransition::ShowVimKeymap(
VimKeymapKind::NormalChange,
)),
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

impl From<NormalModeTransition> for Result<NotebookTransition> {
fn from(transition: NormalModeTransition) -> Self {
Ok(NotebookTransition::EditingNormalMode(transition))
Expand Down
11 changes: 8 additions & 3 deletions core/src/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub enum NotebookTransition {
pub enum VimKeymapKind {
NormalIdle,
NormalNumbering,
NormalChange,
VisualIdle,
VisualNumbering,
}
Expand All @@ -98,6 +99,7 @@ pub enum NormalModeTransition {
YankMode,
DeleteMode,
DeleteInsideMode,
ChangeMode,
MoveCursorDown(usize),
MoveCursorUp(usize),
MoveCursorBack(usize),
Expand All @@ -118,13 +120,16 @@ pub enum NormalModeTransition {
InsertNewLineBelow,
InsertNewLineAbove,
DeleteChars(usize),
DeleteCharsAndInsertMode(usize),
DeleteLineAndInsertMode(usize),
DeleteLines(usize),
DeleteLinesAndInsert(usize),
DeleteWordEnd(usize),
DeleteWordBack(usize),
DeleteLineStart,
DeleteLineEnd(usize),
Paste,
Undo,
Redo,
YankLines(usize),
DeleteLines(usize),
DeleteInsideWord(usize),
}

Expand Down
1 change: 1 addition & 0 deletions tui/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ fn to_event(input: Input) -> Option<KeyEvent> {
KeyCode::Char('r') if ctrl => KeyEvent::CtrlR,
KeyCode::Char('a') => KeyEvent::A,
KeyCode::Char('b') => KeyEvent::B,
KeyCode::Char('c') => KeyEvent::C,
KeyCode::Char('d') => KeyEvent::D,
KeyCode::Char('e') => KeyEvent::E,
KeyCode::Char('g') => KeyEvent::G,
Expand Down
78 changes: 54 additions & 24 deletions tui/src/transitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ impl App {
IdleMode => {
self.context.notebook.editor.cancel_selection();
}
NumberingMode | GatewayMode | YankMode | DeleteMode | DeleteInsideMode => {}
NumberingMode | GatewayMode | YankMode | DeleteMode | DeleteInsideMode | ChangeMode => {
}
MoveCursorDown(n) => {
let editor = &mut self.context.notebook.editor;
let cursor_move = cursor_move_down(editor, n);
Expand Down Expand Up @@ -214,12 +215,7 @@ impl App {
move_cursor_word_end(&mut self.context.notebook.editor, n);
}
MoveCursorWordBack(n) => {
for _ in 0..n {
self.context
.notebook
.editor
.move_cursor(CursorMove::WordBack);
}
move_cursor_word_back(&mut self.context.notebook.editor, n);
}
MoveCursorLineStart => {
self.context.notebook.editor.move_cursor(CursorMove::Head);
Expand Down Expand Up @@ -276,23 +272,6 @@ impl App {
editor.move_cursor(cursor_move);
editor.cut();
}
NormalModeTransition::DeleteCharsAndInsertMode(n) => {
let editor = &mut self.context.notebook.editor;
editor.start_selection();
let cursor_move = cursor_move_forward(editor, n);

editor.move_cursor(cursor_move);
editor.cut();
}
NormalModeTransition::DeleteLineAndInsertMode(n) => {
let editor = &mut self.context.notebook.editor;
editor.move_cursor(CursorMove::Head);
editor.start_selection();
let cursor_move = cursor_move_down(editor, n - 1);
editor.move_cursor(cursor_move);
editor.move_cursor(CursorMove::End);
editor.cut();
}
Paste => {
let editor = &mut self.context.notebook.editor;
if self.context.notebook.line_yanked {
Expand Down Expand Up @@ -346,6 +325,16 @@ impl App {
move_cursor_to_line_non_empty_start(editor);
self.context.notebook.line_yanked = true;
}
DeleteLinesAndInsert(n) => {
let editor = &mut self.context.notebook.editor;
editor.move_cursor(CursorMove::Head);
editor.start_selection();
let cursor_move = cursor_move_down(editor, n - 1);
editor.move_cursor(cursor_move);
editor.move_cursor(CursorMove::End);
editor.cut();
self.context.notebook.line_yanked = true;
}
DeleteInsideWord(n) => {
let editor = &mut self.context.notebook.editor;
let cursor = editor.cursor();
Expand All @@ -363,6 +352,41 @@ impl App {
editor.move_cursor(CursorMove::Forward);
editor.cut();

self.context.notebook.line_yanked = false;
}
DeleteWordEnd(n) => {
let editor = &mut self.context.notebook.editor;
editor.start_selection();
move_cursor_word_end(editor, n);
editor.move_cursor(CursorMove::Forward);
editor.cut();

self.context.notebook.line_yanked = false;
}
DeleteWordBack(n) => {
let editor = &mut self.context.notebook.editor;
editor.start_selection();
move_cursor_word_back(editor, n);
editor.cut();

self.context.notebook.line_yanked = false;
}
DeleteLineStart => {
let editor = &mut self.context.notebook.editor;
editor.start_selection();
editor.move_cursor(CursorMove::Head);
editor.cut();

self.context.notebook.line_yanked = false;
}
DeleteLineEnd(n) => {
let editor = &mut self.context.notebook.editor;
editor.start_selection();
let cursor_move = cursor_move_down(editor, n - 1);
editor.move_cursor(cursor_move);
editor.move_cursor(CursorMove::End);
editor.cut();

self.context.notebook.line_yanked = false;
}
};
Expand Down Expand Up @@ -530,6 +554,12 @@ fn move_cursor_word_end(editor: &mut TextArea, n: usize) {
}
}

fn move_cursor_word_back(editor: &mut TextArea, n: usize) {
for _ in 0..n {
editor.move_cursor(CursorMove::WordBack);
}
}

fn reselect_for_yank(editor: &mut TextArea) {
let (begin, end) = match editor.selection_range() {
None => return,
Expand Down
18 changes: 16 additions & 2 deletions tui/src/views/dialog/vim_keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn draw(frame: &mut Frame, keymap_kind: VimKeymapKind) {
let (title, height, message) = match keymap_kind {
VimKeymapKind::NormalIdle => (
"VIM NORMAL MODE KEYMAP",
41,
42,
vec![
Line::from("TO INSERT MODE".white().on_dark_gray()),
Line::raw("[i] Go to insert mode"),
Expand All @@ -26,6 +26,7 @@ pub fn draw(frame: &mut Frame, keymap_kind: VimKeymapKind) {
Line::raw("[S] Delete line and go to insert mode"),
Line::raw(""),
Line::from("TO OTHER MODES".white().on_dark_gray()),
Line::raw("[c] Go to change mode (prepare to edit text)"),
Line::raw("[v] Go to visual mode (select text to edit or copy)"),
Line::raw("[g] Go to gateway mode (access extended commands)"),
Line::raw("[y] Go to yank mode (prepare to copy text)"),
Expand All @@ -51,7 +52,7 @@ pub fn draw(frame: &mut Frame, keymap_kind: VimKeymapKind) {
Line::raw("[Ctrl+r] Redo the last undone change"),
],
),
VimKeymapKind::NormalNumbering => ("VIM NORMAL MODE KEYMAP - NUMBERING", 30, vec![
VimKeymapKind::NormalNumbering => ("VIM NORMAL MODE KEYMAP - NUMBERING", 31, vec![
Line::from("EXTENDING NUMBERING MODE".white().on_dark_gray()),
Line::raw("[0-9] Append additional digits to extend the current command"),
Line::raw(""),
Expand All @@ -60,6 +61,7 @@ pub fn draw(frame: &mut Frame, keymap_kind: VimKeymapKind) {
Line::raw("[S] Delete the entire line and go to insert mode"),
Line::raw(""),
Line::from("TO OTHER MODES".white().on_dark_gray()),
Line::raw("[c] Go to change mode with repeat count (prepare to edit text)"),
Line::raw("[y] Go to yank mode with repeat count (prepare to copy text)"),
Line::raw("[d] Go to delete mode with repeat count (prepare to delete text)"),
Line::raw(""),
Expand All @@ -77,6 +79,18 @@ pub fn draw(frame: &mut Frame, keymap_kind: VimKeymapKind) {
Line::raw("[x] Delete specified number of characters and return to normal mode"),
Line::raw(""),
]),
VimKeymapKind::NormalChange => ("VIM NORMAL MODE KEYMAP - CHANGE", 15, vec![
Line::from("CHANGE TEXT AND GO TO INSERT MODE".white().on_dark_gray()),
Line::raw("[c] Delete the specified number of lines"),
Line::from(vec![
"[e] ".into(),
"or ".dark_gray(),
"[w] Delete to the end of the word by the specified number of times".into(),
]),
Line::raw("[b] Delete to the start of the previous word, repeated by the specified number"),
Line::raw("[0] Delete to the beginning of the line"),
Line::raw("[$] Delete to the end of the line, repeated by the specified number"),
]),
VimKeymapKind::VisualIdle => ("VIM VISUAL MODE KEYMAP", 30, vec![
Line::from("MOVE CURSOR".white().on_dark_gray()),
Line::raw("[h] Move cursor left"),
Expand Down

0 comments on commit 51f5f90

Please sign in to comment.