vim: Fix clipping when navigating over inlay hints (#22813)
This fixes the issue described in this comment: https://github.com/zed-industries/zed/pull/22439#issuecomment-2563896422 Essentially, we'd clip in the wrong direction when there were multi-line inlay hints. It also fixes inline completions for non-Zeta-providers showing up in normal mode. Release Notes: - N/A
This commit is contained in:
parent
dffdf99228
commit
f9ee28db5e
10 changed files with 76 additions and 13 deletions
|
@ -63,6 +63,10 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_completions_in_normal_mode() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled(
|
fn is_enabled(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
|
|
|
@ -42,7 +42,7 @@ use fold_map::{FoldMap, FoldSnapshot};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, Font, HighlightStyle, LineLayout, Model, ModelContext, Pixels, UnderlineStyle,
|
AnyElement, Font, HighlightStyle, LineLayout, Model, ModelContext, Pixels, UnderlineStyle,
|
||||||
};
|
};
|
||||||
pub(crate) use inlay_map::Inlay;
|
pub use inlay_map::Inlay;
|
||||||
use inlay_map::{InlayMap, InlaySnapshot};
|
use inlay_map::{InlayMap, InlaySnapshot};
|
||||||
pub use inlay_map::{InlayOffset, InlayPoint};
|
pub use inlay_map::{InlayOffset, InlayPoint};
|
||||||
use invisibles::{is_invisible, replacement};
|
use invisibles::{is_invisible, replacement};
|
||||||
|
|
|
@ -33,7 +33,7 @@ enum Transform {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Inlay {
|
pub struct Inlay {
|
||||||
pub(crate) id: InlayId,
|
pub(crate) id: InlayId,
|
||||||
pub position: Anchor,
|
pub position: Anchor,
|
||||||
pub text: text::Rope,
|
pub text: text::Rope,
|
||||||
|
|
|
@ -258,7 +258,7 @@ pub fn render_parsed_markdown(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub(crate) enum InlayId {
|
pub enum InlayId {
|
||||||
InlineCompletion(usize),
|
InlineCompletion(usize),
|
||||||
Hint(usize),
|
Hint(usize),
|
||||||
}
|
}
|
||||||
|
@ -3592,7 +3592,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn splice_inlays(
|
pub fn splice_inlays(
|
||||||
&self,
|
&self,
|
||||||
to_remove: Vec<InlayId>,
|
to_remove: Vec<InlayId>,
|
||||||
to_insert: Vec<Inlay>,
|
to_insert: Vec<Inlay>,
|
||||||
|
@ -4883,7 +4883,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inline_completion_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
|
pub fn inline_completion_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
|
||||||
Some(self.inline_completion_provider.as_ref()?.provider.clone())
|
Some(self.inline_completion_provider.as_ref()?.provider.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,10 @@ impl InlineCompletionProvider for FakeInlineCompletionProvider {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_completions_in_normal_mode() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled(
|
fn is_enabled(
|
||||||
&self,
|
&self,
|
||||||
_buffer: &gpui::Model<language::Buffer>,
|
_buffer: &gpui::Model<language::Buffer>,
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub trait InlineCompletionProvider: 'static + Sized {
|
||||||
fn name() -> &'static str;
|
fn name() -> &'static str;
|
||||||
fn display_name() -> &'static str;
|
fn display_name() -> &'static str;
|
||||||
fn show_completions_in_menu() -> bool;
|
fn show_completions_in_menu() -> bool;
|
||||||
|
fn show_completions_in_normal_mode() -> bool;
|
||||||
fn is_enabled(
|
fn is_enabled(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
|
@ -61,6 +62,7 @@ pub trait InlineCompletionProviderHandle {
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
fn show_completions_in_menu(&self) -> bool;
|
fn show_completions_in_menu(&self) -> bool;
|
||||||
|
fn show_completions_in_normal_mode(&self) -> bool;
|
||||||
fn refresh(
|
fn refresh(
|
||||||
&self,
|
&self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
|
@ -101,6 +103,10 @@ where
|
||||||
T::show_completions_in_menu()
|
T::show_completions_in_menu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_completions_in_normal_mode(&self) -> bool {
|
||||||
|
T::show_completions_in_normal_mode()
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled(
|
fn is_enabled(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
|
|
|
@ -106,6 +106,10 @@ impl InlineCompletionProvider for SupermavenCompletionProvider {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_completions_in_normal_mode() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled(&self, buffer: &Model<Buffer>, cursor_position: Anchor, cx: &AppContext) -> bool {
|
fn is_enabled(&self, buffer: &Model<Buffer>, cursor_position: Anchor, cx: &AppContext) -> bool {
|
||||||
if !self.supermaven.read(cx).is_enabled() {
|
if !self.supermaven.read(cx).is_enabled() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1206,6 +1206,7 @@ fn up_down_buffer_rows(
|
||||||
times: isize,
|
times: isize,
|
||||||
text_layout_details: &TextLayoutDetails,
|
text_layout_details: &TextLayoutDetails,
|
||||||
) -> (DisplayPoint, SelectionGoal) {
|
) -> (DisplayPoint, SelectionGoal) {
|
||||||
|
let bias = if times < 0 { Bias::Left } else { Bias::Right };
|
||||||
let start = map.display_point_to_fold_point(point, Bias::Left);
|
let start = map.display_point_to_fold_point(point, Bias::Left);
|
||||||
let begin_folded_line = map.fold_point_to_display_point(
|
let begin_folded_line = map.fold_point_to_display_point(
|
||||||
map.fold_snapshot
|
map.fold_snapshot
|
||||||
|
@ -1229,14 +1230,14 @@ fn up_down_buffer_rows(
|
||||||
|
|
||||||
let mut begin_folded_line = map.fold_point_to_display_point(
|
let mut begin_folded_line = map.fold_point_to_display_point(
|
||||||
map.fold_snapshot
|
map.fold_snapshot
|
||||||
.clip_point(FoldPoint::new(new_row, 0), Bias::Left),
|
.clip_point(FoldPoint::new(new_row, 0), bias),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < goal_wrap && begin_folded_line.row() < map.max_point().row() {
|
while i < goal_wrap && begin_folded_line.row() < map.max_point().row() {
|
||||||
let next_folded_line = DisplayPoint::new(begin_folded_line.row().next_row(), 0);
|
let next_folded_line = DisplayPoint::new(begin_folded_line.row().next_row(), 0);
|
||||||
if map
|
if map
|
||||||
.display_point_to_fold_point(next_folded_line, Bias::Right)
|
.display_point_to_fold_point(next_folded_line, bias)
|
||||||
.row()
|
.row()
|
||||||
== new_row
|
== new_row
|
||||||
{
|
{
|
||||||
|
@ -1254,10 +1255,7 @@ fn up_down_buffer_rows(
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
map.clip_point(
|
map.clip_point(DisplayPoint::new(begin_folded_line.row(), new_col), bias),
|
||||||
DisplayPoint::new(begin_folded_line.row(), new_col),
|
|
||||||
Bias::Left,
|
|
||||||
),
|
|
||||||
goal,
|
goal,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2484,7 +2482,11 @@ fn section_motion(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use crate::test::NeovimBackedTestContext;
|
use crate::{
|
||||||
|
state::Mode,
|
||||||
|
test::{NeovimBackedTestContext, VimTestContext},
|
||||||
|
};
|
||||||
|
use editor::display_map::Inlay;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -3146,4 +3148,35 @@ mod test {
|
||||||
}ˇ»
|
}ˇ»
|
||||||
"});
|
"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_clipping_with_inlay_hints(cx: &mut gpui::TestAppContext) {
|
||||||
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
|
|
||||||
|
cx.set_state(
|
||||||
|
indoc! {"
|
||||||
|
struct Foo {
|
||||||
|
ˇ
|
||||||
|
}
|
||||||
|
"},
|
||||||
|
Mode::Normal,
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.update_editor(|editor, cx| {
|
||||||
|
let range = editor.selections.newest_anchor().range();
|
||||||
|
let inlay_text = " field: int,\n field2: string\n field3: float";
|
||||||
|
let inlay = Inlay::inline_completion(1, range.start, inlay_text);
|
||||||
|
editor.splice_inlays(vec![], vec![inlay], cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.simulate_keystrokes("j");
|
||||||
|
cx.assert_state(
|
||||||
|
indoc! {"
|
||||||
|
struct Foo {
|
||||||
|
|
||||||
|
ˇ}
|
||||||
|
"},
|
||||||
|
Mode::Normal,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1196,7 +1196,15 @@ impl Vim {
|
||||||
editor.set_input_enabled(vim.editor_input_enabled());
|
editor.set_input_enabled(vim.editor_input_enabled());
|
||||||
editor.set_autoindent(vim.should_autoindent());
|
editor.set_autoindent(vim.should_autoindent());
|
||||||
editor.selections.line_mode = matches!(vim.mode, Mode::VisualLine);
|
editor.selections.line_mode = matches!(vim.mode, Mode::VisualLine);
|
||||||
editor.set_inline_completions_enabled(matches!(vim.mode, Mode::Insert | Mode::Replace));
|
|
||||||
|
let enable_inline_completions = match vim.mode {
|
||||||
|
Mode::Insert | Mode::Replace => true,
|
||||||
|
Mode::Normal => editor
|
||||||
|
.inline_completion_provider()
|
||||||
|
.map_or(false, |provider| provider.show_completions_in_normal_mode()),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
editor.set_inline_completions_enabled(enable_inline_completions);
|
||||||
});
|
});
|
||||||
cx.notify()
|
cx.notify()
|
||||||
}
|
}
|
||||||
|
|
|
@ -979,6 +979,10 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_completions_in_normal_mode() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn is_enabled(
|
fn is_enabled(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue