implemented quote/delimiter text objects
This commit is contained in:
@@ -6,7 +6,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::keys::{KeyCode as K, KeyEvent as E, ModKeys as M};
|
||||
use super::linebuf::CharClass;
|
||||
use super::vicmd::{Anchor, Bound, Dest, Direction, Motion, MotionCmd, RegisterName, TextObj, To, Verb, VerbCmd, ViCmd, Word};
|
||||
use super::vicmd::{Anchor, Bound, CmdFlags, Dest, Direction, Motion, MotionCmd, RegisterName, TextObj, To, Verb, VerbCmd, ViCmd, Word};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -82,7 +82,8 @@ impl ViInsert {
|
||||
self
|
||||
}
|
||||
pub fn register_and_return(&mut self) -> Option<ViCmd> {
|
||||
let cmd = self.take_cmd();
|
||||
let mut cmd = self.take_cmd();
|
||||
cmd.normalize_counts();
|
||||
self.register_cmd(&cmd);
|
||||
Some(cmd)
|
||||
}
|
||||
@@ -188,19 +189,11 @@ impl ViReplace {
|
||||
self
|
||||
}
|
||||
pub fn register_and_return(&mut self) -> Option<ViCmd> {
|
||||
let cmd = self.take_cmd();
|
||||
let mut cmd = self.take_cmd();
|
||||
cmd.normalize_counts();
|
||||
self.register_cmd(&cmd);
|
||||
Some(cmd)
|
||||
}
|
||||
pub fn ctrl_w_is_undo(&self) -> bool {
|
||||
let insert_count = self.cmds.iter().filter(|cmd| {
|
||||
matches!(cmd.verb(),Some(VerbCmd(1, Verb::ReplaceChar(_))))
|
||||
}).count();
|
||||
let backspace_count = self.cmds.iter().filter(|cmd| {
|
||||
matches!(cmd.verb(),Some(VerbCmd(1, Verb::Delete)))
|
||||
}).count();
|
||||
insert_count > backspace_count
|
||||
}
|
||||
pub fn register_cmd(&mut self, cmd: &ViCmd) {
|
||||
self.cmds.push(cmd.clone())
|
||||
}
|
||||
@@ -218,14 +211,9 @@ impl ViMode for ViReplace {
|
||||
self.register_and_return()
|
||||
}
|
||||
E(K::Char('W'), M::CTRL) => {
|
||||
if self.ctrl_w_is_undo() {
|
||||
self.pending_cmd.set_verb(VerbCmd(1,Verb::Undo));
|
||||
self.cmds.clear();
|
||||
Some(self.take_cmd())
|
||||
} else {
|
||||
self.pending_cmd.set_motion(MotionCmd(1, Motion::WordMotion(To::Start, Word::Normal, Direction::Backward)));
|
||||
self.register_and_return()
|
||||
}
|
||||
self.pending_cmd.set_verb(VerbCmd(1, Verb::Delete));
|
||||
self.pending_cmd.set_motion(MotionCmd(1, Motion::WordMotion(To::Start, Word::Normal, Direction::Backward)));
|
||||
self.register_and_return()
|
||||
}
|
||||
E(K::Char('H'), M::CTRL) |
|
||||
E(K::Backspace, M::NONE) => {
|
||||
@@ -280,6 +268,7 @@ impl ViMode for ViReplace {
|
||||
#[derive(Default,Debug)]
|
||||
pub struct ViNormal {
|
||||
pending_seq: String,
|
||||
pending_flags: CmdFlags,
|
||||
}
|
||||
|
||||
impl ViNormal {
|
||||
@@ -292,6 +281,9 @@ impl ViNormal {
|
||||
pub fn take_cmd(&mut self) -> String {
|
||||
std::mem::take(&mut self.pending_seq)
|
||||
}
|
||||
pub fn flags(&self) -> CmdFlags {
|
||||
self.pending_flags
|
||||
}
|
||||
#[allow(clippy::unnecessary_unwrap)]
|
||||
fn validate_combination(&self, verb: Option<&Verb>, motion: Option<&Motion>) -> CmdState {
|
||||
if verb.is_none() {
|
||||
@@ -337,6 +329,12 @@ impl ViNormal {
|
||||
self.pending_seq.push(ch);
|
||||
let mut chars = self.pending_seq.chars().peekable();
|
||||
|
||||
/*
|
||||
* Parse the register
|
||||
*
|
||||
* Registers can be any letter a-z or A-Z.
|
||||
* While uncommon, it is possible to give a count to a register name.
|
||||
*/
|
||||
let register = 'reg_parse: {
|
||||
let mut chars_clone = chars.clone();
|
||||
let count = self.parse_count(&mut chars_clone);
|
||||
@@ -345,7 +343,7 @@ impl ViNormal {
|
||||
break 'reg_parse RegisterName::default()
|
||||
};
|
||||
|
||||
let Some(reg_name) = chars_clone.next() else {
|
||||
let Some(reg_name) = chars_clone.next() else {
|
||||
return None // Pending register name
|
||||
};
|
||||
match reg_name {
|
||||
@@ -358,6 +356,17 @@ impl ViNormal {
|
||||
RegisterName::new(Some(reg_name), count)
|
||||
};
|
||||
|
||||
/*
|
||||
* We will now parse the verb
|
||||
* If we hit an invalid sequence, we will call 'return self.quit_parse()'
|
||||
* self.quit_parse() will clear the pending command and return None
|
||||
*
|
||||
* If we hit an incomplete sequence, we will simply return None.
|
||||
* returning None leaves the pending sequence where it is
|
||||
*
|
||||
* Note that we do use a label here for the block and 'return' values from this scope
|
||||
* using "break 'verb_parse <value>"
|
||||
*/
|
||||
let verb = 'verb_parse: {
|
||||
let mut chars_clone = chars.clone();
|
||||
let count = self.parse_count(&mut chars_clone).unwrap_or(1);
|
||||
@@ -375,7 +384,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::VisualModeSelectLast)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags(),
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -412,6 +422,7 @@ impl ViNormal {
|
||||
verb: Some(VerbCmd(count, Verb::RepeatLast)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -421,7 +432,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Delete)),
|
||||
motion: Some(MotionCmd(1, Motion::ForwardChar)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -431,7 +443,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Delete)),
|
||||
motion: Some(MotionCmd(1, Motion::BackwardChar)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -441,8 +454,9 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Change)),
|
||||
motion: Some(MotionCmd(1, Motion::ForwardChar)),
|
||||
raw_seq: self.take_cmd()
|
||||
}
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
},
|
||||
)
|
||||
}
|
||||
'S' => {
|
||||
@@ -451,7 +465,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Change)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -476,9 +491,10 @@ impl ViNormal {
|
||||
return Some(
|
||||
ViCmd {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::ReplaceChar(ch))),
|
||||
verb: Some(VerbCmd(1, Verb::ReplaceCharInplace(ch,count as u16))),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -488,7 +504,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::ReplaceMode)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -496,9 +513,10 @@ impl ViNormal {
|
||||
return Some(
|
||||
ViCmd {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::ToggleCaseSingle)),
|
||||
verb: Some(VerbCmd(1, Verb::ToggleCaseInplace(count as u16))),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -508,7 +526,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Undo)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -518,7 +537,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::VisualMode)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -528,7 +548,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::VisualModeLine)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -538,7 +559,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertModeLineBreak(Anchor::After))),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -548,7 +570,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertModeLineBreak(Anchor::Before))),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -558,7 +581,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: Some(MotionCmd(1, Motion::ForwardChar)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -568,7 +592,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: Some(MotionCmd(1, Motion::EndOfLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -578,7 +603,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -588,7 +614,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: Some(MotionCmd(1, Motion::BeginningOfFirstWord)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -598,7 +625,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::JoinLines)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -620,7 +648,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Yank)),
|
||||
motion: Some(MotionCmd(1, Motion::EndOfLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -630,7 +659,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Delete)),
|
||||
motion: Some(MotionCmd(1, Motion::EndOfLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -640,7 +670,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::Change)),
|
||||
motion: Some(MotionCmd(1, Motion::EndOfLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -672,15 +703,6 @@ impl ViNormal {
|
||||
('~', Some(VerbCmd(_,Verb::ToggleCaseRange))) |
|
||||
('>', Some(VerbCmd(_,Verb::Indent))) |
|
||||
('<', Some(VerbCmd(_,Verb::Dedent))) => break 'motion_parse Some(MotionCmd(count, Motion::WholeLine)),
|
||||
|
||||
// Exception cases
|
||||
('w', Some(VerbCmd(_, Verb::Change))) => {
|
||||
// 'w' usually means 'to the start of the next word'
|
||||
// e.g. 'dw' deleted to the start of the next word
|
||||
// however, 'cw' only changes to the end of the current word
|
||||
// 'caw' is used to change to the start of the next word
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Normal, Direction::Forward)));
|
||||
}
|
||||
('W', Some(VerbCmd(_, Verb::Change))) => {
|
||||
// Same with 'W'
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Big, Direction::Forward)));
|
||||
@@ -689,47 +711,69 @@ impl ViNormal {
|
||||
}
|
||||
match ch {
|
||||
'g' => {
|
||||
if let Some(ch) = chars_clone.peek() {
|
||||
match ch {
|
||||
'g' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfBuffer))
|
||||
}
|
||||
'e' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Normal, Direction::Backward)));
|
||||
}
|
||||
'E' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Big, Direction::Backward)));
|
||||
}
|
||||
'k' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineUp));
|
||||
}
|
||||
'j' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineDown));
|
||||
}
|
||||
'_' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::EndOfLastWord));
|
||||
}
|
||||
'0' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfScreenLine));
|
||||
}
|
||||
'^' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::FirstGraphicalOnScreenLine));
|
||||
}
|
||||
_ => return self.quit_parse()
|
||||
}
|
||||
} else {
|
||||
let Some(ch) = chars_clone.peek() else {
|
||||
break 'motion_parse None
|
||||
};
|
||||
match ch {
|
||||
'g' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfBuffer))
|
||||
}
|
||||
'e' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Normal, Direction::Backward)));
|
||||
}
|
||||
'E' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Big, Direction::Backward)));
|
||||
}
|
||||
'k' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineUp));
|
||||
}
|
||||
'j' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineDown));
|
||||
}
|
||||
'_' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::EndOfLastWord));
|
||||
}
|
||||
'0' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfScreenLine));
|
||||
}
|
||||
'^' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::FirstGraphicalOnScreenLine));
|
||||
}
|
||||
_ => return self.quit_parse()
|
||||
}
|
||||
}
|
||||
'v' => {
|
||||
// We got 'v' after a verb
|
||||
// Instead of normal operations, we will calculate the span based on how visual mode would see it
|
||||
if self.flags().intersects(CmdFlags::VISUAL | CmdFlags::VISUAL_LINE | CmdFlags::VISUAL_BLOCK) {
|
||||
// We can't have more than one of these
|
||||
return self.quit_parse();
|
||||
}
|
||||
self.pending_flags |= CmdFlags::VISUAL;
|
||||
break 'motion_parse None
|
||||
}
|
||||
'V' => {
|
||||
// We got 'V' after a verb
|
||||
// Instead of normal operations, we will calculate the span based on how visual line mode would see it
|
||||
if self.flags().intersects(CmdFlags::VISUAL | CmdFlags::VISUAL_LINE | CmdFlags::VISUAL_BLOCK) {
|
||||
// We can't have more than one of these
|
||||
// I know vim can technically do this, but it doesn't really make sense to allow it
|
||||
// since even in vim only the first one given is used
|
||||
return self.quit_parse();
|
||||
}
|
||||
self.pending_flags |= CmdFlags::VISUAL;
|
||||
break 'motion_parse None
|
||||
}
|
||||
// TODO: figure out how to include 'Ctrl+V' here, might need a refactor
|
||||
'G' => {
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::EndOfBuffer));
|
||||
@@ -840,6 +884,7 @@ impl ViNormal {
|
||||
'W' => TextObj::Word(Word::Big),
|
||||
'"' => TextObj::DoubleQuote,
|
||||
'\'' => TextObj::SingleQuote,
|
||||
'`' => TextObj::BacktickQuote,
|
||||
'(' | ')' | 'b' => TextObj::Paren,
|
||||
'{' | '}' | 'B' => TextObj::Brace,
|
||||
'[' | ']' => TextObj::Bracket,
|
||||
@@ -868,7 +913,8 @@ impl ViNormal {
|
||||
register,
|
||||
verb,
|
||||
motion,
|
||||
raw_seq: std::mem::take(&mut self.pending_seq)
|
||||
raw_seq: std::mem::take(&mut self.pending_seq),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -885,7 +931,7 @@ impl ViNormal {
|
||||
|
||||
impl ViMode for ViNormal {
|
||||
fn handle_key(&mut self, key: E) -> Option<ViCmd> {
|
||||
match key {
|
||||
let mut cmd = match key {
|
||||
E(K::Char(ch), M::NONE) => self.try_parse(ch),
|
||||
E(K::Backspace, M::NONE) => {
|
||||
Some(ViCmd {
|
||||
@@ -893,6 +939,7 @@ impl ViMode for ViNormal {
|
||||
verb: None,
|
||||
motion: Some(MotionCmd(1, Motion::BackwardChar)),
|
||||
raw_seq: "".into(),
|
||||
flags: self.flags()
|
||||
})
|
||||
}
|
||||
E(K::Char('R'), M::CTRL) => {
|
||||
@@ -903,7 +950,8 @@ impl ViMode for ViNormal {
|
||||
register: RegisterName::default(),
|
||||
verb: Some(VerbCmd(count,Verb::Redo)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: self.flags()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -919,7 +967,12 @@ impl ViMode for ViNormal {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(cmd) = cmd.as_mut() {
|
||||
cmd.normalize_counts();
|
||||
};
|
||||
cmd
|
||||
}
|
||||
|
||||
fn is_repeatable(&self) -> bool {
|
||||
@@ -1051,7 +1104,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::VisualModeSelectLast)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1061,7 +1115,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::Rot13)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1078,6 +1133,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(count, Verb::RepeatLast)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1092,6 +1148,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(1, Verb::Delete)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1101,7 +1158,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::Yank)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1111,7 +1169,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::Delete)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1123,6 +1182,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(1, Verb::Change)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1133,6 +1193,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(1, Verb::Indent)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1143,6 +1204,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(1, Verb::Dedent)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1153,6 +1215,7 @@ impl ViVisual {
|
||||
verb: Some(VerbCmd(1, Verb::Equalize)),
|
||||
motion: Some(MotionCmd(1, Motion::WholeLine)),
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1168,7 +1231,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::ReplaceChar(ch))),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1178,7 +1242,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(1, Verb::ToggleCaseRange)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1188,7 +1253,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::ToLower)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1198,7 +1264,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::ToUpper)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1209,7 +1276,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::SwapVisualAnchor)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1219,7 +1287,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: Some(MotionCmd(1, Motion::ForwardChar)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1229,7 +1298,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::InsertMode)),
|
||||
motion: Some(MotionCmd(1, Motion::BeginningOfLine)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1239,7 +1309,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(VerbCmd(count, Verb::JoinLines)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1264,7 +1335,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb: Some(verb),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1294,18 +1366,22 @@ impl ViVisual {
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfBuffer))
|
||||
}
|
||||
'e' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Normal, Direction::Backward)));
|
||||
}
|
||||
'E' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::WordMotion(To::End, Word::Big, Direction::Backward)));
|
||||
}
|
||||
'k' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineUp));
|
||||
}
|
||||
'j' => {
|
||||
chars_clone.next();
|
||||
chars = chars_clone;
|
||||
break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineDown));
|
||||
}
|
||||
@@ -1417,6 +1493,7 @@ impl ViVisual {
|
||||
'W' => TextObj::Word(Word::Big),
|
||||
'"' => TextObj::DoubleQuote,
|
||||
'\'' => TextObj::SingleQuote,
|
||||
'`' => TextObj::BacktickQuote,
|
||||
'(' | ')' | 'b' => TextObj::Paren,
|
||||
'{' | '}' | 'B' => TextObj::Brace,
|
||||
'[' | ']' => TextObj::Bracket,
|
||||
@@ -1445,7 +1522,8 @@ impl ViVisual {
|
||||
register,
|
||||
verb,
|
||||
motion,
|
||||
raw_seq: std::mem::take(&mut self.pending_seq)
|
||||
raw_seq: std::mem::take(&mut self.pending_seq),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1462,7 +1540,7 @@ impl ViVisual {
|
||||
|
||||
impl ViMode for ViVisual {
|
||||
fn handle_key(&mut self, key: E) -> Option<ViCmd> {
|
||||
match key {
|
||||
let mut cmd = match key {
|
||||
E(K::Char(ch), M::NONE) => self.try_parse(ch),
|
||||
E(K::Backspace, M::NONE) => {
|
||||
Some(ViCmd {
|
||||
@@ -1470,6 +1548,7 @@ impl ViMode for ViVisual {
|
||||
verb: None,
|
||||
motion: Some(MotionCmd(1, Motion::BackwardChar)),
|
||||
raw_seq: "".into(),
|
||||
flags: CmdFlags::empty()
|
||||
})
|
||||
}
|
||||
E(K::Char('R'), M::CTRL) => {
|
||||
@@ -1480,7 +1559,8 @@ impl ViMode for ViVisual {
|
||||
register: RegisterName::default(),
|
||||
verb: Some(VerbCmd(count,Verb::Redo)),
|
||||
motion: None,
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1490,7 +1570,8 @@ impl ViMode for ViVisual {
|
||||
register: Default::default(),
|
||||
verb: Some(VerbCmd(1, Verb::NormalMode)),
|
||||
motion: Some(MotionCmd(1, Motion::Null)),
|
||||
raw_seq: self.take_cmd()
|
||||
raw_seq: self.take_cmd(),
|
||||
flags: CmdFlags::empty()
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
@@ -1501,7 +1582,12 @@ impl ViMode for ViVisual {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(cmd) = cmd.as_mut() {
|
||||
cmd.normalize_counts();
|
||||
};
|
||||
cmd
|
||||
}
|
||||
|
||||
fn is_repeatable(&self) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user