Detailed changes
@@ -342,8 +342,8 @@
"r": ["vim::PushOperator", "Replace"],
"s": "vim::Substitute",
"shift-s": "vim::SubstituteLine",
- "> >": "editor::Indent",
- "< <": "editor::Outdent",
+ "> >": "vim::Indent",
+ "< <": "vim::Outdent",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem"
}
@@ -460,8 +460,8 @@
"ctrl-c": ["vim::SwitchMode", "Normal"],
"escape": ["vim::SwitchMode", "Normal"],
"ctrl-[": ["vim::SwitchMode", "Normal"],
- ">": "editor::Indent",
- "<": "editor::Outdent",
+ ">": "vim::Indent",
+ "<": "vim::Outdent",
"i": [
"vim::PushOperator",
{
@@ -492,7 +492,9 @@
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
"ctrl-x ctrl-z": "editor::Cancel",
"ctrl-w": "editor::DeleteToPreviousWordStart",
- "ctrl-u": "editor::DeleteToBeginningOfLine"
+ "ctrl-u": "editor::DeleteToBeginningOfLine",
+ "ctrl-t": "vim::Indent",
+ "ctrl-d": "vim::Outdent"
}
},
{
@@ -4474,6 +4474,9 @@ impl Editor {
}
pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
+ if self.read_only(cx) {
+ return;
+ }
let mut selections = self.selections.all::<Point>(cx);
let mut prev_edited_row = 0;
let mut row_delta = 0;
@@ -4516,7 +4519,7 @@ impl Editor {
// If a selection ends at the beginning of a line, don't indent
// that last line.
- if selection.end.column == 0 {
+ if selection.end.column == 0 && selection.end.row > selection.start.row {
end_row -= 1;
}
@@ -4567,6 +4570,9 @@ impl Editor {
}
pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
+ if self.read_only(cx) {
+ return;
+ }
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all::<Point>(cx);
let mut deletion_ranges = Vec::new();
@@ -4707,6 +4713,9 @@ impl Editor {
}
pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
+ if self.read_only(cx) {
+ return;
+ }
let mut row_ranges = Vec::<Range<u32>>::new();
for selection in self.selections.all::<Point>(cx) {
let start = selection.start.row;
@@ -51,6 +51,8 @@ actions!(
ConvertToUpperCase,
ConvertToLowerCase,
JoinLines,
+ Indent,
+ Outdent,
]
);
@@ -125,7 +127,34 @@ pub(crate) fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace
editor.join_lines(&Default::default(), cx)
}
})
- })
+ });
+ if vim.state().mode.is_visual() {
+ vim.switch_mode(Mode::Normal, false, cx)
+ }
+ });
+ });
+
+ workspace.register_action(|_: &mut Workspace, _: &Indent, cx| {
+ Vim::update(cx, |vim, cx| {
+ vim.record_current_action(cx);
+ vim.update_active_editor(cx, |_, editor, cx| {
+ editor.transact(cx, |editor, cx| editor.indent(&Default::default(), cx))
+ });
+ if vim.state().mode.is_visual() {
+ vim.switch_mode(Mode::Normal, false, cx)
+ }
+ });
+ });
+
+ workspace.register_action(|_: &mut Workspace, _: &Outdent, cx| {
+ Vim::update(cx, |vim, cx| {
+ vim.record_current_action(cx);
+ vim.update_active_editor(cx, |_, editor, cx| {
+ editor.transact(cx, |editor, cx| editor.outdent(&Default::default(), cx))
+ });
+ if vim.state().mode.is_visual() {
+ vim.switch_mode(Mode::Normal, false, cx)
+ }
});
});
@@ -163,9 +163,9 @@ async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
cx.simulate_keystrokes(["<", "<"]);
cx.assert_editor_state("aa\nbหb\ncc");
- // works in visuial mode
+ // works in visual mode
cx.simulate_keystrokes(["shift-v", "down", ">"]);
- cx.assert_editor_state("aa\n bยซb\n ccหยป");
+ cx.assert_editor_state("aa\n bb\n cหc");
}
#[gpui::test]
@@ -67,7 +67,6 @@ impl VimTestContext {
// Setup search toolbars and keypress hook
cx.update_workspace(|workspace, cx| {
- observe_keystrokes(cx);
workspace.active_pane().update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
let buffer_search_bar = cx.new_view(BufferSearchBar::new);
@@ -22,8 +22,8 @@ use editor::{
Editor, EditorEvent, EditorMode,
};
use gpui::{
- actions, impl_actions, Action, AppContext, EntityId, Global, Subscription, View, ViewContext,
- WeakView, WindowContext,
+ actions, impl_actions, Action, AppContext, EntityId, Global, KeystrokeEvent, Subscription,
+ View, ViewContext, WeakView, WindowContext,
};
use language::{CursorShape, Point, Selection, SelectionGoal};
pub use mode_indicator::ModeIndicator;
@@ -76,6 +76,7 @@ pub fn init(cx: &mut AppContext) {
VimModeSetting::register(cx);
VimSettings::register(cx);
+ cx.observe_keystrokes(observe_keystrokes).detach();
editor_events::init(cx);
cx.observe_new_views(|workspace: &mut Workspace, cx| register(workspace, cx))
@@ -135,46 +136,42 @@ fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
visual::register(workspace, cx);
}
-/// Registers a keystroke observer to observe keystrokes for the Vim integration.
-pub fn observe_keystrokes(cx: &mut WindowContext) {
- cx.observe_keystrokes(|keystroke_event, cx| {
- if let Some(action) = keystroke_event
- .action
- .as_ref()
- .map(|action| action.boxed_clone())
- {
- Vim::update(cx, |vim, _| {
- if vim.workspace_state.recording {
- vim.workspace_state
- .recorded_actions
- .push(ReplayableAction::Action(action.boxed_clone()));
-
- if vim.workspace_state.stop_recording_after_next_action {
- vim.workspace_state.recording = false;
- vim.workspace_state.stop_recording_after_next_action = false;
- }
- }
- });
+/// Called whenever an keystroke is typed so vim can observe all actions
+/// and keystrokes accordingly.
+fn observe_keystrokes(keystroke_event: &KeystrokeEvent, cx: &mut WindowContext) {
+ if let Some(action) = keystroke_event
+ .action
+ .as_ref()
+ .map(|action| action.boxed_clone())
+ {
+ Vim::update(cx, |vim, _| {
+ if vim.workspace_state.recording {
+ vim.workspace_state
+ .recorded_actions
+ .push(ReplayableAction::Action(action.boxed_clone()));
- // Keystroke is handled by the vim system, so continue forward
- if action.name().starts_with("vim::") {
- return;
+ if vim.workspace_state.stop_recording_after_next_action {
+ vim.workspace_state.recording = false;
+ vim.workspace_state.stop_recording_after_next_action = false;
+ }
}
- } else if cx.has_pending_keystrokes() {
+ });
+
+ // Keystroke is handled by the vim system, so continue forward
+ if action.name().starts_with("vim::") {
return;
}
+ } else if cx.has_pending_keystrokes() {
+ return;
+ }
- Vim::update(cx, |vim, cx| match vim.active_operator() {
- Some(
- Operator::FindForward { .. } | Operator::FindBackward { .. } | Operator::Replace,
- ) => {}
- Some(_) => {
- vim.clear_operator(cx);
- }
- _ => {}
- });
- })
- .detach()
+ Vim::update(cx, |vim, cx| match vim.active_operator() {
+ Some(Operator::FindForward { .. } | Operator::FindBackward { .. } | Operator::Replace) => {}
+ Some(_) => {
+ vim.clear_operator(cx);
+ }
+ _ => {}
+ });
}
/// The state pertaining to Vim mode.
@@ -142,8 +142,6 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
auto_update::notify_of_any_new_update(cx);
- vim::observe_keystrokes(cx);
-
let handle = cx.view().downgrade();
cx.on_window_should_close(move |cx| {
handle