mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
vim: Add Smart Relative Line Number (#16567)
Closes #16514 Release Notes: - Added Vim: absolute numbering in any mode except `insert` mode --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
26d943287b
commit
9662829810
@ -946,6 +946,7 @@
|
|||||||
},
|
},
|
||||||
// Vim settings
|
// Vim settings
|
||||||
"vim": {
|
"vim": {
|
||||||
|
"toggle_relative_line_numbers": false,
|
||||||
"use_system_clipboard": "always",
|
"use_system_clipboard": "always",
|
||||||
"use_multiline_find": false,
|
"use_multiline_find": false,
|
||||||
"use_smartcase_find": false,
|
"use_smartcase_find": false,
|
||||||
|
@ -318,6 +318,7 @@ gpui::actions!(
|
|||||||
ToggleHunkDiff,
|
ToggleHunkDiff,
|
||||||
ToggleInlayHints,
|
ToggleInlayHints,
|
||||||
ToggleLineNumbers,
|
ToggleLineNumbers,
|
||||||
|
ToggleRelativeLineNumbers,
|
||||||
ToggleIndentGuides,
|
ToggleIndentGuides,
|
||||||
ToggleSoftWrap,
|
ToggleSoftWrap,
|
||||||
ToggleTabBar,
|
ToggleTabBar,
|
||||||
|
@ -512,6 +512,7 @@ pub struct Editor {
|
|||||||
show_breadcrumbs: bool,
|
show_breadcrumbs: bool,
|
||||||
show_gutter: bool,
|
show_gutter: bool,
|
||||||
show_line_numbers: Option<bool>,
|
show_line_numbers: Option<bool>,
|
||||||
|
use_relative_line_numbers: Option<bool>,
|
||||||
show_git_diff_gutter: Option<bool>,
|
show_git_diff_gutter: Option<bool>,
|
||||||
show_code_actions: Option<bool>,
|
show_code_actions: Option<bool>,
|
||||||
show_runnables: Option<bool>,
|
show_runnables: Option<bool>,
|
||||||
@ -1853,6 +1854,7 @@ impl Editor {
|
|||||||
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
||||||
show_gutter: mode == EditorMode::Full,
|
show_gutter: mode == EditorMode::Full,
|
||||||
show_line_numbers: None,
|
show_line_numbers: None,
|
||||||
|
use_relative_line_numbers: None,
|
||||||
show_git_diff_gutter: None,
|
show_git_diff_gutter: None,
|
||||||
show_code_actions: None,
|
show_code_actions: None,
|
||||||
show_runnables: None,
|
show_runnables: None,
|
||||||
@ -10610,6 +10612,29 @@ impl Editor {
|
|||||||
EditorSettings::override_global(editor_settings, cx);
|
EditorSettings::override_global(editor_settings, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn should_use_relative_line_numbers(&self, cx: &WindowContext) -> bool {
|
||||||
|
self.use_relative_line_numbers
|
||||||
|
.unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle_relative_line_numbers(
|
||||||
|
&mut self,
|
||||||
|
_: &ToggleRelativeLineNumbers,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
let is_relative = self.should_use_relative_line_numbers(cx);
|
||||||
|
self.set_relative_line_number(Some(!is_relative), cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_relative_line_number(
|
||||||
|
&mut self,
|
||||||
|
is_relative: Option<bool>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
self.use_relative_line_numbers = is_relative;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
|
pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
|
||||||
self.show_gutter = show_gutter;
|
self.show_gutter = show_gutter;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -344,6 +344,7 @@ impl EditorElement {
|
|||||||
register_action(view, cx, Editor::toggle_soft_wrap);
|
register_action(view, cx, Editor::toggle_soft_wrap);
|
||||||
register_action(view, cx, Editor::toggle_tab_bar);
|
register_action(view, cx, Editor::toggle_tab_bar);
|
||||||
register_action(view, cx, Editor::toggle_line_numbers);
|
register_action(view, cx, Editor::toggle_line_numbers);
|
||||||
|
register_action(view, cx, Editor::toggle_relative_line_numbers);
|
||||||
register_action(view, cx, Editor::toggle_indent_guides);
|
register_action(view, cx, Editor::toggle_indent_guides);
|
||||||
register_action(view, cx, Editor::toggle_inlay_hints);
|
register_action(view, cx, Editor::toggle_inlay_hints);
|
||||||
register_action(view, cx, hover_popover::hover);
|
register_action(view, cx, hover_popover::hover);
|
||||||
@ -1770,7 +1771,7 @@ impl EditorElement {
|
|||||||
});
|
});
|
||||||
let font_size = self.style.text.font_size.to_pixels(cx.rem_size());
|
let font_size = self.style.text.font_size.to_pixels(cx.rem_size());
|
||||||
|
|
||||||
let is_relative = EditorSettings::get_global(cx).relative_line_numbers;
|
let is_relative = editor.should_use_relative_line_numbers(cx);
|
||||||
let relative_to = if is_relative {
|
let relative_to = if is_relative {
|
||||||
Some(newest_selection_head.row())
|
Some(newest_selection_head.row())
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,9 @@ use crate::{UseSystemClipboard, Vim, VimSettings};
|
|||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
|
use command_palette_hooks::{CommandPaletteFilter, CommandPaletteInterceptor};
|
||||||
use editor::{Anchor, ClipboardSelection, Editor};
|
use editor::{Anchor, ClipboardSelection, Editor};
|
||||||
use gpui::{Action, AppContext, BorrowAppContext, ClipboardEntry, ClipboardItem, Global};
|
use gpui::{
|
||||||
|
Action, AppContext, BorrowAppContext, ClipboardEntry, ClipboardItem, Global, View, WeakView,
|
||||||
|
};
|
||||||
use language::Point;
|
use language::Point;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
@ -160,6 +162,8 @@ pub struct VimGlobals {
|
|||||||
pub last_yank: Option<SharedString>,
|
pub last_yank: Option<SharedString>,
|
||||||
pub registers: HashMap<char, Register>,
|
pub registers: HashMap<char, Register>,
|
||||||
pub recordings: HashMap<char, Vec<ReplayableAction>>,
|
pub recordings: HashMap<char, Vec<ReplayableAction>>,
|
||||||
|
|
||||||
|
pub focused_vim: Option<WeakView<Vim>>,
|
||||||
}
|
}
|
||||||
impl Global for VimGlobals {}
|
impl Global for VimGlobals {}
|
||||||
|
|
||||||
@ -373,6 +377,10 @@ impl VimGlobals {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn focused_vim(&self) -> Option<View<Vim>> {
|
||||||
|
self.focused_vim.as_ref().and_then(|vim| vim.upgrade())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vim {
|
impl Vim {
|
||||||
|
@ -23,8 +23,8 @@ use editor::{
|
|||||||
Anchor, Bias, Editor, EditorEvent, EditorMode, ToPoint,
|
Anchor, Bias, Editor, EditorEvent, EditorMode, ToPoint,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, impl_actions, Action, AppContext, EventEmitter, KeyContext, KeystrokeEvent, Render,
|
actions, impl_actions, Action, AppContext, Entity, EventEmitter, KeyContext, KeystrokeEvent,
|
||||||
View, ViewContext, WeakView,
|
Render, View, ViewContext, WeakView,
|
||||||
};
|
};
|
||||||
use insert::NormalBefore;
|
use insert::NormalBefore;
|
||||||
use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
|
use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
|
||||||
@ -228,8 +228,21 @@ impl Vim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut was_enabled = Vim::enabled(cx);
|
let mut was_enabled = Vim::enabled(cx);
|
||||||
|
let mut was_toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
|
||||||
cx.observe_global::<SettingsStore>(move |editor, cx| {
|
cx.observe_global::<SettingsStore>(move |editor, cx| {
|
||||||
let enabled = Vim::enabled(cx);
|
let enabled = Vim::enabled(cx);
|
||||||
|
let toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
|
||||||
|
if enabled && was_enabled && (toggle != was_toggle) {
|
||||||
|
if toggle {
|
||||||
|
let is_relative = editor
|
||||||
|
.addon::<VimAddon>()
|
||||||
|
.map(|vim| vim.view.read(cx).mode != Mode::Insert);
|
||||||
|
editor.set_relative_line_number(is_relative, cx)
|
||||||
|
} else {
|
||||||
|
editor.set_relative_line_number(None, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
was_toggle = VimSettings::get_global(cx).toggle_relative_line_numbers;
|
||||||
if was_enabled == enabled {
|
if was_enabled == enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -296,6 +309,7 @@ impl Vim {
|
|||||||
editor.set_autoindent(true);
|
editor.set_autoindent(true);
|
||||||
editor.selections.line_mode = false;
|
editor.selections.line_mode = false;
|
||||||
editor.unregister_addon::<VimAddon>();
|
editor.unregister_addon::<VimAddon>();
|
||||||
|
editor.set_relative_line_number(None, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register an action on the editor.
|
/// Register an action on the editor.
|
||||||
@ -424,6 +438,17 @@ impl Vim {
|
|||||||
// Sync editor settings like clip mode
|
// Sync editor settings like clip mode
|
||||||
self.sync_vim_settings(cx);
|
self.sync_vim_settings(cx);
|
||||||
|
|
||||||
|
if VimSettings::get_global(cx).toggle_relative_line_numbers {
|
||||||
|
if self.mode != self.last_mode {
|
||||||
|
if self.mode == Mode::Insert || self.last_mode == Mode::Insert {
|
||||||
|
self.update_editor(cx, |vim, editor, cx| {
|
||||||
|
let is_relative = vim.mode != Mode::Insert;
|
||||||
|
editor.set_relative_line_number(Some(is_relative), cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if leave_selections {
|
if leave_selections {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -616,6 +641,24 @@ impl Vim {
|
|||||||
|
|
||||||
cx.emit(VimEvent::Focused);
|
cx.emit(VimEvent::Focused);
|
||||||
self.sync_vim_settings(cx);
|
self.sync_vim_settings(cx);
|
||||||
|
|
||||||
|
if VimSettings::get_global(cx).toggle_relative_line_numbers {
|
||||||
|
if let Some(old_vim) = Vim::globals(cx).focused_vim() {
|
||||||
|
if old_vim.entity_id() != cx.view().entity_id() {
|
||||||
|
old_vim.update(cx, |vim, cx| {
|
||||||
|
vim.update_editor(cx, |_, editor, cx| {
|
||||||
|
editor.set_relative_line_number(None, cx)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
self.update_editor(cx, |vim, editor, cx| {
|
||||||
|
let is_relative = vim.mode != Mode::Insert;
|
||||||
|
editor.set_relative_line_number(Some(is_relative), cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vim::globals(cx).focused_vim = Some(cx.view().downgrade());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blurred(&mut self, cx: &mut ViewContext<Self>) {
|
fn blurred(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
@ -1039,6 +1082,7 @@ pub enum UseSystemClipboard {
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct VimSettings {
|
struct VimSettings {
|
||||||
|
pub toggle_relative_line_numbers: bool,
|
||||||
pub use_system_clipboard: UseSystemClipboard,
|
pub use_system_clipboard: UseSystemClipboard,
|
||||||
pub use_multiline_find: bool,
|
pub use_multiline_find: bool,
|
||||||
pub use_smartcase_find: bool,
|
pub use_smartcase_find: bool,
|
||||||
@ -1047,6 +1091,7 @@ struct VimSettings {
|
|||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
struct VimSettingsContent {
|
struct VimSettingsContent {
|
||||||
|
pub toggle_relative_line_numbers: Option<bool>,
|
||||||
pub use_system_clipboard: Option<UseSystemClipboard>,
|
pub use_system_clipboard: Option<UseSystemClipboard>,
|
||||||
pub use_multiline_find: Option<bool>,
|
pub use_multiline_find: Option<bool>,
|
||||||
pub use_smartcase_find: Option<bool>,
|
pub use_smartcase_find: Option<bool>,
|
||||||
|
@ -241,8 +241,17 @@ Some vim settings are available to modify the default vim behavior:
|
|||||||
// "never": don't use system clipboard unless "+ or "* is specified
|
// "never": don't use system clipboard unless "+ or "* is specified
|
||||||
// "on_yank": use system clipboard for yank operations when no register is specified
|
// "on_yank": use system clipboard for yank operations when no register is specified
|
||||||
"use_system_clipboard": "always",
|
"use_system_clipboard": "always",
|
||||||
// Lets `f` and `t` motions extend across multiple lines
|
// Let `f` and `t` motions extend across multiple lines
|
||||||
"use_multiline_find": true
|
"use_multiline_find": true,
|
||||||
|
// Let `f` and `t` motions match case insensitively if the target is lowercase
|
||||||
|
"use_smartcase_find": true,
|
||||||
|
// Use relative line numbers in normal mode, absolute in insert mode
|
||||||
|
// c.f. https://github.com/jeffkreeftmeijer/vim-numbertoggle
|
||||||
|
"toggle_relative_line_numbers": true,
|
||||||
|
// Add custom digraphs (e.g. ctrl-k f z will insert a zombie emoji)
|
||||||
|
"custom_digraphs": {
|
||||||
|
"fz": "🧟♀️"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user