Compare commits
8 Commits
vim-syntax
...
zeta-synta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a8965ccc7 | ||
|
|
3364cd9889 | ||
|
|
b6ac26b1e2 | ||
|
|
9ab17f5b32 | ||
|
|
d5f5a615e8 | ||
|
|
f4f618c9cb | ||
|
|
71b4d98367 | ||
|
|
77328e8300 |
@@ -445,7 +445,10 @@ pub fn make_inlay_hints_style(cx: &WindowContext) -> HighlightStyle {
|
|||||||
type CompletionId = usize;
|
type CompletionId = usize;
|
||||||
|
|
||||||
enum InlineCompletion {
|
enum InlineCompletion {
|
||||||
Edit(Vec<(Range<Anchor>, String)>),
|
Edit {
|
||||||
|
edits: Vec<(Range<Anchor>, String)>,
|
||||||
|
applied_edits_buffer: Model<Buffer>,
|
||||||
|
},
|
||||||
Move(Anchor),
|
Move(Anchor),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4517,7 +4520,7 @@ impl Editor {
|
|||||||
selections.select_anchor_ranges([position..position]);
|
selections.select_anchor_ranges([position..position]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
InlineCompletion::Edit(edits) => {
|
InlineCompletion::Edit { edits, .. } => {
|
||||||
if let Some(provider) = self.inline_completion_provider() {
|
if let Some(provider) = self.inline_completion_provider() {
|
||||||
provider.accept(cx);
|
provider.accept(cx);
|
||||||
}
|
}
|
||||||
@@ -4564,7 +4567,7 @@ impl Editor {
|
|||||||
selections.select_anchor_ranges([position..position]);
|
selections.select_anchor_ranges([position..position]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
InlineCompletion::Edit(edits) => {
|
InlineCompletion::Edit { edits, .. } => {
|
||||||
if edits.len() == 1 && edits[0].0.start == edits[0].0.end {
|
if edits.len() == 1 && edits[0].0.start == edits[0].0.end {
|
||||||
let text = edits[0].1.as_str();
|
let text = edits[0].1.as_str();
|
||||||
let mut partial_completion = text
|
let mut partial_completion = text
|
||||||
@@ -4681,6 +4684,7 @@ impl Editor {
|
|||||||
let completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
|
let completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
|
||||||
let edits = completion
|
let edits = completion
|
||||||
.edits
|
.edits
|
||||||
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(range, new_text)| {
|
.map(|(range, new_text)| {
|
||||||
(
|
(
|
||||||
@@ -4714,13 +4718,13 @@ impl Editor {
|
|||||||
|
|
||||||
let mut inlay_ids = Vec::new();
|
let mut inlay_ids = Vec::new();
|
||||||
let invalidation_row_range;
|
let invalidation_row_range;
|
||||||
let completion;
|
let editor_completion;
|
||||||
if cursor_row < edit_start_row {
|
if cursor_row < edit_start_row {
|
||||||
invalidation_row_range = cursor_row..edit_end_row;
|
invalidation_row_range = cursor_row..edit_end_row;
|
||||||
completion = InlineCompletion::Move(first_edit_start);
|
editor_completion = InlineCompletion::Move(first_edit_start);
|
||||||
} else if cursor_row > edit_end_row {
|
} else if cursor_row > edit_end_row {
|
||||||
invalidation_row_range = edit_start_row..cursor_row;
|
invalidation_row_range = edit_start_row..cursor_row;
|
||||||
completion = InlineCompletion::Move(first_edit_start);
|
editor_completion = InlineCompletion::Move(first_edit_start);
|
||||||
} else {
|
} else {
|
||||||
if edits
|
if edits
|
||||||
.iter()
|
.iter()
|
||||||
@@ -4751,7 +4755,15 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
invalidation_row_range = edit_start_row..edit_end_row;
|
invalidation_row_range = edit_start_row..edit_end_row;
|
||||||
completion = InlineCompletion::Edit(edits);
|
|
||||||
|
let applied_edits_buffer = buffer.update(cx, |buffer, cx| buffer.branch(cx));
|
||||||
|
applied_edits_buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.edit(completion.edits, None, cx);
|
||||||
|
});
|
||||||
|
editor_completion = InlineCompletion::Edit {
|
||||||
|
edits,
|
||||||
|
applied_edits_buffer,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let invalidation_range = multibuffer
|
let invalidation_range = multibuffer
|
||||||
@@ -4763,7 +4775,7 @@ impl Editor {
|
|||||||
|
|
||||||
self.active_inline_completion = Some(InlineCompletionState {
|
self.active_inline_completion = Some(InlineCompletionState {
|
||||||
inlay_ids,
|
inlay_ids,
|
||||||
completion,
|
completion: editor_completion,
|
||||||
invalidation_range,
|
invalidation_range,
|
||||||
});
|
});
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ use gpui::{
|
|||||||
transparent_black, Action, AnchorCorner, AnyElement, AvailableSpace, Bounds, ClipboardItem,
|
transparent_black, Action, AnchorCorner, AnyElement, AvailableSpace, Bounds, ClipboardItem,
|
||||||
ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity,
|
ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity,
|
||||||
FontId, GlobalElementId, HighlightStyle, Hitbox, Hsla, InteractiveElement, IntoElement, Length,
|
FontId, GlobalElementId, HighlightStyle, Hitbox, Hsla, InteractiveElement, IntoElement, Length,
|
||||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad,
|
Model, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size,
|
PaintQuad, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString,
|
||||||
StatefulInteractiveElement, Style, Styled, TextRun, TextStyleRefinement, View, ViewContext,
|
Size, StatefulInteractiveElement, Style, Styled, TextRun, TextStyleRefinement, View,
|
||||||
WeakView, WindowContext,
|
ViewContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use gpui::{ClickEvent, Subscription};
|
use gpui::{ClickEvent, Subscription};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -45,7 +45,7 @@ use language::{
|
|||||||
IndentGuideBackgroundColoring, IndentGuideColoring, IndentGuideSettings,
|
IndentGuideBackgroundColoring, IndentGuideColoring, IndentGuideSettings,
|
||||||
ShowWhitespaceSetting,
|
ShowWhitespaceSetting,
|
||||||
},
|
},
|
||||||
ChunkRendererContext,
|
Buffer, ChunkRendererContext,
|
||||||
};
|
};
|
||||||
use lsp::DiagnosticSeverity;
|
use lsp::DiagnosticSeverity;
|
||||||
use multi_buffer::{
|
use multi_buffer::{
|
||||||
@@ -2818,7 +2818,10 @@ impl EditorElement {
|
|||||||
Some(element)
|
Some(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineCompletion::Edit(edits) => {
|
InlineCompletion::Edit {
|
||||||
|
edits,
|
||||||
|
applied_edits_buffer,
|
||||||
|
} => {
|
||||||
let edit_start = edits
|
let edit_start = edits
|
||||||
.first()
|
.first()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -2842,7 +2845,12 @@ impl EditorElement {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (text, highlights) = inline_completion_popover_text(editor_snapshot, edits, cx);
|
let (text, highlights) = inline_completion_popover_text(
|
||||||
|
editor_snapshot,
|
||||||
|
edits,
|
||||||
|
applied_edits_buffer.clone(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
let longest_row =
|
let longest_row =
|
||||||
editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
|
editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
|
||||||
@@ -4309,54 +4317,89 @@ impl EditorElement {
|
|||||||
fn inline_completion_popover_text(
|
fn inline_completion_popover_text(
|
||||||
editor_snapshot: &EditorSnapshot,
|
editor_snapshot: &EditorSnapshot,
|
||||||
edits: &Vec<(Range<Anchor>, String)>,
|
edits: &Vec<(Range<Anchor>, String)>,
|
||||||
|
applied_edits_buffer: Model<Buffer>,
|
||||||
cx: &WindowContext,
|
cx: &WindowContext,
|
||||||
) -> (String, Vec<(Range<usize>, HighlightStyle)>) {
|
) -> (String, Vec<(Range<usize>, HighlightStyle)>) {
|
||||||
let edit_start = edits
|
use text::{ToOffset as _, ToPoint as _};
|
||||||
|
|
||||||
|
let mut text = String::new();
|
||||||
|
let mut highlights = Vec::new();
|
||||||
|
let snapshot = applied_edits_buffer.read(cx).snapshot();
|
||||||
|
|
||||||
|
let mut start = edits
|
||||||
.first()
|
.first()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.start
|
.start
|
||||||
.to_display_point(editor_snapshot);
|
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||||
|
.text_anchor
|
||||||
let mut text = String::new();
|
.to_point(&snapshot);
|
||||||
let mut offset = DisplayPoint::new(edit_start.row(), 0).to_offset(editor_snapshot, Bias::Left);
|
start.column = 0;
|
||||||
let mut highlights = Vec::new();
|
let mut offset = text::ToOffset::to_offset(&start, &snapshot);
|
||||||
for (old_range, new_text) in edits {
|
for (old_range, new_text) in edits {
|
||||||
let old_offset_range = old_range.to_offset(&editor_snapshot.buffer_snapshot);
|
let edit_new_start = old_range
|
||||||
text.extend(
|
.start
|
||||||
editor_snapshot
|
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||||
.buffer_snapshot
|
.text_anchor
|
||||||
.chunks(offset..old_offset_range.start, false)
|
.to_offset(&snapshot);
|
||||||
.map(|chunk| chunk.text),
|
for chunk in snapshot.chunks(offset..edit_new_start, true) {
|
||||||
);
|
let start = text.len();
|
||||||
offset = old_offset_range.end;
|
text.push_str(chunk.text);
|
||||||
|
let end = text.len();
|
||||||
|
|
||||||
let start = text.len();
|
if let Some(highlight_style) = chunk
|
||||||
text.push_str(new_text);
|
.syntax_highlight_id
|
||||||
let end = text.len();
|
.and_then(|id| id.style(cx.theme().syntax()))
|
||||||
highlights.push((
|
{
|
||||||
start..end,
|
highlights.push((start..end, highlight_style));
|
||||||
HighlightStyle {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let end_offset = edit_new_start + new_text.len();
|
||||||
|
for chunk in snapshot.chunks(edit_new_start..end_offset, true) {
|
||||||
|
let start = text.len();
|
||||||
|
text.push_str(chunk.text);
|
||||||
|
let end = text.len();
|
||||||
|
|
||||||
|
let mut highlight_style = HighlightStyle {
|
||||||
background_color: Some(cx.theme().status().created_background),
|
background_color: Some(cx.theme().status().created_background),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
};
|
||||||
));
|
if let Some(syntax_highlight_style) = chunk
|
||||||
|
.syntax_highlight_id
|
||||||
|
.and_then(|id| id.style(cx.theme().syntax()))
|
||||||
|
{
|
||||||
|
highlight_style.highlight(syntax_highlight_style);
|
||||||
|
}
|
||||||
|
highlights.push((start..end, highlight_style));
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = end_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
let edit_end = edits
|
let mut end = edits
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.end
|
.end
|
||||||
.to_display_point(editor_snapshot);
|
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||||
let end_of_line = DisplayPoint::new(edit_end.row(), editor_snapshot.line_len(edit_end.row()))
|
.text_anchor
|
||||||
.to_offset(editor_snapshot, Bias::Right);
|
.to_point(&snapshot);
|
||||||
text.extend(
|
end.column = snapshot.line_len(end.row);
|
||||||
editor_snapshot
|
let end = text::ToOffset::to_offset(&end, &snapshot);
|
||||||
.buffer_snapshot
|
|
||||||
.chunks(offset..end_of_line, false)
|
for chunk in snapshot.chunks(offset..end, true) {
|
||||||
.map(|chunk| chunk.text),
|
let start = text.len();
|
||||||
);
|
text.push_str(chunk.text);
|
||||||
|
let end = text.len();
|
||||||
|
|
||||||
|
if let Some(highlight_style) = chunk
|
||||||
|
.syntax_highlight_id
|
||||||
|
.and_then(|id| id.style(cx.theme().syntax()))
|
||||||
|
{
|
||||||
|
highlights.push((start..end, highlight_style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(text, highlights)
|
(text, highlights)
|
||||||
}
|
}
|
||||||
@@ -6657,7 +6700,7 @@ mod tests {
|
|||||||
editor_tests::{init_test, update_test_language_settings},
|
editor_tests::{init_test, update_test_language_settings},
|
||||||
Editor, MultiBuffer,
|
Editor, MultiBuffer,
|
||||||
};
|
};
|
||||||
use gpui::{TestAppContext, VisualTestContext};
|
use gpui::{AppContext, TestAppContext, VisualTestContext};
|
||||||
use language::language_settings;
|
use language::language_settings;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
@@ -7127,7 +7170,12 @@ mod tests {
|
|||||||
..snapshot.buffer_snapshot.anchor_before(Point::new(0, 6));
|
..snapshot.buffer_snapshot.anchor_before(Point::new(0, 6));
|
||||||
let edits = vec![(edit_range, " beautiful".to_string())];
|
let edits = vec![(edit_range, " beautiful".to_string())];
|
||||||
|
|
||||||
let (text, highlights) = inline_completion_popover_text(&snapshot, &edits, cx);
|
let (text, highlights) = inline_completion_popover_text(
|
||||||
|
&snapshot,
|
||||||
|
&edits,
|
||||||
|
create_applied_edits_buffer(editor, edits.clone(), cx),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(text, "Hello, beautiful world!");
|
assert_eq!(text, "Hello, beautiful world!");
|
||||||
assert_eq!(highlights.len(), 1);
|
assert_eq!(highlights.len(), 1);
|
||||||
@@ -7157,7 +7205,12 @@ mod tests {
|
|||||||
"That".to_string(),
|
"That".to_string(),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let (text, highlights) = inline_completion_popover_text(&snapshot, &edits, cx);
|
let (text, highlights) = inline_completion_popover_text(
|
||||||
|
&snapshot,
|
||||||
|
&edits,
|
||||||
|
create_applied_edits_buffer(editor, edits.clone(), cx),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(text, "That is a test.");
|
assert_eq!(text, "That is a test.");
|
||||||
assert_eq!(highlights.len(), 1);
|
assert_eq!(highlights.len(), 1);
|
||||||
@@ -7194,7 +7247,12 @@ mod tests {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let (text, highlights) = inline_completion_popover_text(&snapshot, &edits, cx);
|
let (text, highlights) = inline_completion_popover_text(
|
||||||
|
&snapshot,
|
||||||
|
&edits,
|
||||||
|
create_applied_edits_buffer(editor, edits.clone(), cx),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(text, "Greetings, world and universe!");
|
assert_eq!(text, "Greetings, world and universe!");
|
||||||
assert_eq!(highlights.len(), 2);
|
assert_eq!(highlights.len(), 2);
|
||||||
@@ -7244,7 +7302,12 @@ mod tests {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let (text, highlights) = inline_completion_popover_text(&snapshot, &edits, cx);
|
let (text, highlights) = inline_completion_popover_text(
|
||||||
|
&snapshot,
|
||||||
|
&edits,
|
||||||
|
create_applied_edits_buffer(editor, edits.clone(), cx),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(text, "Second modified\nNew third line\nFourth updated line");
|
assert_eq!(text, "Second modified\nNew third line\nFourth updated line");
|
||||||
assert_eq!(highlights.len(), 3);
|
assert_eq!(highlights.len(), 3);
|
||||||
@@ -7263,6 +7326,29 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_applied_edits_buffer(
|
||||||
|
editor: &Editor,
|
||||||
|
edits: Vec<(Range<Anchor>, String)>,
|
||||||
|
cx: &mut AppContext,
|
||||||
|
) -> Model<Buffer> {
|
||||||
|
let buffer = editor
|
||||||
|
.buffer()
|
||||||
|
.read(cx)
|
||||||
|
.as_singleton()
|
||||||
|
.unwrap()
|
||||||
|
.update(cx, |buffer, cx| buffer.branch(cx));
|
||||||
|
buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.edit(
|
||||||
|
edits
|
||||||
|
.into_iter()
|
||||||
|
.map(|(range, text)| (range.start.text_anchor..range.end.text_anchor, text)),
|
||||||
|
None,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_invisibles_from_new_editor(
|
fn collect_invisibles_from_new_editor(
|
||||||
cx: &mut TestAppContext,
|
cx: &mut TestAppContext,
|
||||||
editor_mode: EditorMode,
|
editor_mode: EditorMode,
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ fn assert_editor_active_edit_completion(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("editor has no active completion");
|
.expect("editor has no active completion");
|
||||||
|
|
||||||
if let InlineCompletion::Edit(edits) = &completion_state.completion {
|
if let InlineCompletion::Edit { edits, .. } = &completion_state.completion {
|
||||||
assert(editor.buffer().read(cx).snapshot(cx), edits);
|
assert(editor.buffer().read(cx).snapshot(cx), edits);
|
||||||
} else {
|
} else {
|
||||||
panic!("expected edit completion");
|
panic!("expected edit completion");
|
||||||
|
|||||||
Reference in New Issue
Block a user