in progress
This commit is contained in:
parent
048da9ddce
commit
14eec66e38
6 changed files with 102 additions and 25 deletions
|
@ -209,6 +209,10 @@
|
||||||
"ctrl-e": [
|
"ctrl-e": [
|
||||||
"vim::Scroll",
|
"vim::Scroll",
|
||||||
"LineDown"
|
"LineDown"
|
||||||
|
],
|
||||||
|
"r": [
|
||||||
|
"vim::PushOperator",
|
||||||
|
"Replace"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -294,7 +298,11 @@
|
||||||
"d": "vim::VisualDelete",
|
"d": "vim::VisualDelete",
|
||||||
"x": "vim::VisualDelete",
|
"x": "vim::VisualDelete",
|
||||||
"y": "vim::VisualYank",
|
"y": "vim::VisualYank",
|
||||||
"p": "vim::VisualPaste"
|
"p": "vim::VisualPaste",
|
||||||
|
"r": [
|
||||||
|
"vim::PushOperator",
|
||||||
|
"Replace"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@ use editor::{
|
||||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||||
movement, Bias, CharKind, DisplayPoint,
|
movement, Bias, CharKind, DisplayPoint,
|
||||||
};
|
};
|
||||||
use gpui::{actions, impl_actions, keymap_matcher::KeyPressed, MutableAppContext};
|
use gpui::{actions, impl_actions, MutableAppContext};
|
||||||
use language::{Point, Selection, SelectionGoal};
|
use language::{Point, Selection, SelectionGoal};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
@ -109,27 +109,6 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
&PreviousWordStart { ignore_punctuation }: &PreviousWordStart,
|
&PreviousWordStart { ignore_punctuation }: &PreviousWordStart,
|
||||||
cx: _| { motion(Motion::PreviousWordStart { ignore_punctuation }, cx) },
|
cx: _| { motion(Motion::PreviousWordStart { ignore_punctuation }, cx) },
|
||||||
);
|
);
|
||||||
cx.add_action(
|
|
||||||
|_: &mut Workspace, KeyPressed { keystroke }: &KeyPressed, cx| match Vim::read(cx)
|
|
||||||
.active_operator()
|
|
||||||
{
|
|
||||||
Some(Operator::FindForward { before }) => motion(
|
|
||||||
Motion::FindForward {
|
|
||||||
before,
|
|
||||||
character: keystroke.key.chars().next().unwrap(),
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
Some(Operator::FindBackward { after }) => motion(
|
|
||||||
Motion::FindBackward {
|
|
||||||
after,
|
|
||||||
character: keystroke.key.chars().next().unwrap(),
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
_ => cx.propagate_action(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn motion(motion: Motion, cx: &mut MutableAppContext) {
|
pub(crate) fn motion(motion: Motion, cx: &mut MutableAppContext) {
|
||||||
|
|
|
@ -424,6 +424,25 @@ fn scroll(editor: &mut Editor, amount: &ScrollAmount, cx: &mut ViewContext<Edito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn normal_replace(text: &str, cx: &mut MutableAppContext) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.transact(cx, |editor, cx| {
|
||||||
|
editor.set_clip_at_line_ends(false, cx);
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.move_with(|map, selection| {
|
||||||
|
*selection.end.column_mut() += 1;
|
||||||
|
selection.end = map.clip_point(selection.end, Bias::Right);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
editor.insert(text, cx);
|
||||||
|
editor.set_clip_at_line_ends(true, cx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
vim.pop_operator(cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub enum Operator {
|
||||||
Change,
|
Change,
|
||||||
Delete,
|
Delete,
|
||||||
Yank,
|
Yank,
|
||||||
|
Replace,
|
||||||
Object { around: bool },
|
Object { around: bool },
|
||||||
FindForward { before: bool },
|
FindForward { before: bool },
|
||||||
FindBackward { after: bool },
|
FindBackward { after: bool },
|
||||||
|
@ -117,6 +118,7 @@ impl Operator {
|
||||||
Operator::Change => "c",
|
Operator::Change => "c",
|
||||||
Operator::Delete => "d",
|
Operator::Delete => "d",
|
||||||
Operator::Yank => "y",
|
Operator::Yank => "y",
|
||||||
|
Operator::Replace => "r",
|
||||||
Operator::FindForward { before: false } => "f",
|
Operator::FindForward { before: false } => "f",
|
||||||
Operator::FindForward { before: true } => "t",
|
Operator::FindForward { before: true } => "t",
|
||||||
Operator::FindBackward { after: false } => "F",
|
Operator::FindBackward { after: false } => "F",
|
||||||
|
@ -127,7 +129,9 @@ impl Operator {
|
||||||
pub fn context_flags(&self) -> &'static [&'static str] {
|
pub fn context_flags(&self) -> &'static [&'static str] {
|
||||||
match self {
|
match self {
|
||||||
Operator::Object { .. } => &["VimObject"],
|
Operator::Object { .. } => &["VimObject"],
|
||||||
Operator::FindForward { .. } | Operator::FindBackward { .. } => &["VimWaiting"],
|
Operator::FindForward { .. } | Operator::FindBackward { .. } | Operator::Replace => {
|
||||||
|
&["VimWaiting"]
|
||||||
|
}
|
||||||
_ => &[],
|
_ => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,18 @@ mod visual;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use command_palette::CommandPaletteFilter;
|
use command_palette::CommandPaletteFilter;
|
||||||
use editor::{Bias, Cancel, Editor};
|
use editor::{Bias, Cancel, Editor};
|
||||||
use gpui::{impl_actions, MutableAppContext, Subscription, ViewContext, WeakViewHandle};
|
use gpui::{
|
||||||
|
impl_actions,
|
||||||
|
keymap_matcher::{KeyPressed, Keystroke},
|
||||||
|
MutableAppContext, Subscription, ViewContext, WeakViewHandle,
|
||||||
|
};
|
||||||
use language::CursorShape;
|
use language::CursorShape;
|
||||||
|
use motion::Motion;
|
||||||
|
use normal::normal_replace;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use state::{Mode, Operator, VimState};
|
use state::{Mode, Operator, VimState};
|
||||||
|
use visual::visual_replace;
|
||||||
use workspace::{self, Workspace};
|
use workspace::{self, Workspace};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
|
@ -51,6 +58,11 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, n: &Number, cx: _| {
|
cx.add_action(|_: &mut Workspace, n: &Number, cx: _| {
|
||||||
Vim::update(cx, |vim, cx| vim.push_number(n, cx));
|
Vim::update(cx, |vim, cx| vim.push_number(n, cx));
|
||||||
});
|
});
|
||||||
|
cx.add_action(
|
||||||
|
|_: &mut Workspace, KeyPressed { keystroke }: &KeyPressed, cx| {
|
||||||
|
Vim::key_pressed(keystroke, cx);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Editor Actions
|
// Editor Actions
|
||||||
cx.add_action(|_: &mut Editor, _: &Cancel, cx| {
|
cx.add_action(|_: &mut Editor, _: &Cancel, cx| {
|
||||||
|
@ -208,6 +220,27 @@ impl Vim {
|
||||||
self.state.operator_stack.last().copied()
|
self.state.operator_stack.last().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn key_pressed(keystroke: &Keystroke, cx: &mut ViewContext<Workspace>) {
|
||||||
|
match Vim::read(cx).active_operator() {
|
||||||
|
Some(Operator::FindForward { before }) => {
|
||||||
|
if let Some(character) = keystroke.key.chars().next() {
|
||||||
|
motion::motion(Motion::FindForward { before, character }, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Operator::FindBackward { after }) => {
|
||||||
|
if let Some(character) = keystroke.key.chars().next() {
|
||||||
|
motion::motion(Motion::FindBackward { after, character }, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Operator::Replace) => match Vim::read(cx).state.mode {
|
||||||
|
Mode::Normal => normal_replace(&keystroke.key, cx),
|
||||||
|
Mode::Visual { line } => visual_replace(&keystroke.key, line, cx),
|
||||||
|
_ => Vim::update(cx, |vim, cx| vim.clear_operator(cx)),
|
||||||
|
},
|
||||||
|
_ => cx.propagate_action(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_enabled(&mut self, enabled: bool, cx: &mut MutableAppContext) {
|
fn set_enabled(&mut self, enabled: bool, cx: &mut MutableAppContext) {
|
||||||
if self.enabled != enabled {
|
if self.enabled != enabled {
|
||||||
self.enabled = enabled;
|
self.enabled = enabled;
|
||||||
|
|
|
@ -313,6 +313,40 @@ pub fn paste(_: &mut Workspace, _: &VisualPaste, cx: &mut ViewContext<Workspace>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn visual_replace(text: &str, line: bool, cx: &mut MutableAppContext) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.transact(cx, |editor, cx| {
|
||||||
|
let (display_map, selections) = editor.selections.all_adjusted_display(cx);
|
||||||
|
let mut new_selections = Vec::new();
|
||||||
|
editor.buffer().update(cx, |buffer, cx| {
|
||||||
|
let mut edits = Vec::new();
|
||||||
|
for selection in selections.iter() {
|
||||||
|
let mut selection = selection.clone();
|
||||||
|
if !line && !selection.reversed {
|
||||||
|
// Head is at the end of the selection. Adjust the end position to
|
||||||
|
// to include the character under the cursor.
|
||||||
|
*selection.end.column_mut() = selection.end.column() + 1;
|
||||||
|
selection.end = display_map.clip_point(selection.end, Bias::Right);
|
||||||
|
}
|
||||||
|
|
||||||
|
let range = selection
|
||||||
|
.map(|p| p.to_offset(&display_map, Bias::Right))
|
||||||
|
.range();
|
||||||
|
new_selections.push(range.start..range.start);
|
||||||
|
let text = text.repeat(range.len());
|
||||||
|
edits.push((range, text));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.edit(edits, None, cx);
|
||||||
|
});
|
||||||
|
editor.change_selections(None, cx, |s| s.select_ranges(new_selections));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
vim.pop_operator(cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue