diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 88ad4f6557..6713eb0e6d 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -86,6 +86,7 @@ "ctrl-[": ["vim::SwitchMode", "Normal"], "v": "vim::ToggleVisual", "shift-v": "vim::ToggleVisualLine", + "ctrl-g": "vim::ShowLocation", "ctrl-v": "vim::ToggleVisualBlock", "ctrl-q": "vim::ToggleVisualBlock", "shift-k": "editor::Hover", diff --git a/crates/vim/src/mode_indicator.rs b/crates/vim/src/mode_indicator.rs index 8b608fdfe3..253f5e1b5d 100644 --- a/crates/vim/src/mode_indicator.rs +++ b/crates/vim/src/mode_indicator.rs @@ -97,18 +97,24 @@ impl Render for ModeIndicator { }; let vim_readable = vim.read(cx); - let mode = if vim_readable.temp_mode { - format!("(insert) {}", vim_readable.mode) + let label = if let Some(label) = vim_readable.status_label.clone() { + label } else { - vim_readable.mode.to_string() + let mode = if vim_readable.temp_mode { + format!("(insert) {}", vim_readable.mode) + } else { + vim_readable.mode.to_string() + }; + + let current_operators_description = self.current_operators_description(vim.clone(), cx); + let pending = self + .pending_keys + .as_ref() + .unwrap_or(¤t_operators_description); + format!("{} -- {} --", pending, mode).into() }; - let current_operators_description = self.current_operators_description(vim.clone(), cx); - let pending = self - .pending_keys - .as_ref() - .unwrap_or(¤t_operators_description); - Label::new(format!("{} -- {} --", pending, mode)) + Label::new(label) .size(LabelSize::Small) .line_height_style(LineHeightStyle::UiLabel) .into_any_element() diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 34c183b20a..9a872e61f8 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -30,7 +30,7 @@ use editor::Bias; use editor::Editor; use editor::{display_map::ToDisplayPoint, movement}; use gpui::{actions, ViewContext}; -use language::{Point, SelectionGoal}; +use language::{Point, SelectionGoal, ToPoint}; use log::error; use multi_buffer::MultiBufferRow; @@ -56,6 +56,7 @@ actions!( ConvertToUpperCase, ConvertToLowerCase, ToggleComments, + ShowLocation, Undo, Redo, ] @@ -75,6 +76,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext) { Vim::action(editor, cx, Vim::yank_line); Vim::action(editor, cx, Vim::toggle_comments); Vim::action(editor, cx, Vim::paste); + Vim::action(editor, cx, Vim::show_location); Vim::action(editor, cx, |vim, _: &DeleteLeft, cx| { vim.record_current_action(cx); @@ -419,6 +421,45 @@ impl Vim { self.yank_motion(motion::Motion::CurrentLine, count, cx) } + fn show_location(&mut self, _: &ShowLocation, cx: &mut ViewContext) { + let count = Vim::take_count(cx); + self.update_editor(cx, |vim, editor, cx| { + let selection = editor.selections.newest_anchor(); + if let Some((_, buffer, _)) = editor.active_excerpt(cx) { + let filename = if let Some(file) = buffer.read(cx).file() { + if count.is_some() { + if let Some(local) = file.as_local() { + local.abs_path(cx).to_string_lossy().to_string() + } else { + file.full_path(cx).to_string_lossy().to_string() + } + } else { + file.path().to_string_lossy().to_string() + } + } else { + "[No Name]".into() + }; + let buffer = buffer.read(cx); + let snapshot = buffer.snapshot(); + let lines = buffer.max_point().row + 1; + let current_line = selection.head().text_anchor.to_point(&snapshot).row; + let percentage = current_line as f32 / lines as f32; + let modified = if buffer.is_dirty() { " [modified]" } else { "" }; + vim.status_label = Some( + format!( + "{}{} {} lines --{:.0}%--", + filename, + modified, + lines, + percentage * 100.0, + ) + .into(), + ); + cx.notify(); + } + }); + } + fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext) { self.record_current_action(cx); self.store_visual_marks(cx); diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index e40eadf955..251e5a9bcd 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -42,7 +42,7 @@ use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals}; use std::{mem, ops::Range, sync::Arc}; use surrounds::SurroundsType; use theme::ThemeSettings; -use ui::{px, IntoElement, VisualContext}; +use ui::{px, IntoElement, SharedString, VisualContext}; use vim_mode_setting::VimModeSetting; use workspace::{self, Pane, ResizeIntent, Workspace}; @@ -201,6 +201,7 @@ pub(crate) struct Vim { pub(crate) mode: Mode, pub last_mode: Mode, pub temp_mode: bool, + pub status_label: Option, pub exit_temporary_mode: bool, operator_stack: Vec, @@ -262,6 +263,7 @@ impl Vim { current_anchor: None, undo_modes: HashMap::default(), + status_label: None, selected_register: None, search: SearchState::default(), @@ -519,6 +521,7 @@ impl Vim { let last_mode = self.mode; let prior_mode = self.last_mode; let prior_tx = self.current_tx; + self.status_label.take(); self.last_mode = last_mode; self.mode = mode; self.operator_stack.clear();