Compare commits
8 Commits
scan-code
...
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;
|
||||
|
||||
enum InlineCompletion {
|
||||
Edit(Vec<(Range<Anchor>, String)>),
|
||||
Edit {
|
||||
edits: Vec<(Range<Anchor>, String)>,
|
||||
applied_edits_buffer: Model<Buffer>,
|
||||
},
|
||||
Move(Anchor),
|
||||
}
|
||||
|
||||
@@ -4517,7 +4520,7 @@ impl Editor {
|
||||
selections.select_anchor_ranges([position..position]);
|
||||
});
|
||||
}
|
||||
InlineCompletion::Edit(edits) => {
|
||||
InlineCompletion::Edit { edits, .. } => {
|
||||
if let Some(provider) = self.inline_completion_provider() {
|
||||
provider.accept(cx);
|
||||
}
|
||||
@@ -4564,7 +4567,7 @@ impl Editor {
|
||||
selections.select_anchor_ranges([position..position]);
|
||||
});
|
||||
}
|
||||
InlineCompletion::Edit(edits) => {
|
||||
InlineCompletion::Edit { edits, .. } => {
|
||||
if edits.len() == 1 && edits[0].0.start == edits[0].0.end {
|
||||
let text = edits[0].1.as_str();
|
||||
let mut partial_completion = text
|
||||
@@ -4681,6 +4684,7 @@ impl Editor {
|
||||
let completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
|
||||
let edits = completion
|
||||
.edits
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(range, new_text)| {
|
||||
(
|
||||
@@ -4714,13 +4718,13 @@ impl Editor {
|
||||
|
||||
let mut inlay_ids = Vec::new();
|
||||
let invalidation_row_range;
|
||||
let completion;
|
||||
let editor_completion;
|
||||
if cursor_row < edit_start_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 {
|
||||
invalidation_row_range = edit_start_row..cursor_row;
|
||||
completion = InlineCompletion::Move(first_edit_start);
|
||||
editor_completion = InlineCompletion::Move(first_edit_start);
|
||||
} else {
|
||||
if edits
|
||||
.iter()
|
||||
@@ -4751,7 +4755,15 @@ impl Editor {
|
||||
}
|
||||
|
||||
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
|
||||
@@ -4763,7 +4775,7 @@ impl Editor {
|
||||
|
||||
self.active_inline_completion = Some(InlineCompletionState {
|
||||
inlay_ids,
|
||||
completion,
|
||||
completion: editor_completion,
|
||||
invalidation_range,
|
||||
});
|
||||
cx.notify();
|
||||
|
||||
@@ -33,10 +33,10 @@ use gpui::{
|
||||
transparent_black, Action, AnchorCorner, AnyElement, AvailableSpace, Bounds, ClipboardItem,
|
||||
ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity,
|
||||
FontId, GlobalElementId, HighlightStyle, Hitbox, Hsla, InteractiveElement, IntoElement, Length,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad,
|
||||
ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size,
|
||||
StatefulInteractiveElement, Style, Styled, TextRun, TextStyleRefinement, View, ViewContext,
|
||||
WeakView, WindowContext,
|
||||
Model, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||
PaintQuad, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString,
|
||||
Size, StatefulInteractiveElement, Style, Styled, TextRun, TextStyleRefinement, View,
|
||||
ViewContext, WeakView, WindowContext,
|
||||
};
|
||||
use gpui::{ClickEvent, Subscription};
|
||||
use itertools::Itertools;
|
||||
@@ -45,7 +45,7 @@ use language::{
|
||||
IndentGuideBackgroundColoring, IndentGuideColoring, IndentGuideSettings,
|
||||
ShowWhitespaceSetting,
|
||||
},
|
||||
ChunkRendererContext,
|
||||
Buffer, ChunkRendererContext,
|
||||
};
|
||||
use lsp::DiagnosticSeverity;
|
||||
use multi_buffer::{
|
||||
@@ -2818,7 +2818,10 @@ impl EditorElement {
|
||||
Some(element)
|
||||
}
|
||||
}
|
||||
InlineCompletion::Edit(edits) => {
|
||||
InlineCompletion::Edit {
|
||||
edits,
|
||||
applied_edits_buffer,
|
||||
} => {
|
||||
let edit_start = edits
|
||||
.first()
|
||||
.unwrap()
|
||||
@@ -2842,7 +2845,12 @@ impl EditorElement {
|
||||
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 =
|
||||
editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
|
||||
@@ -4309,54 +4317,89 @@ impl EditorElement {
|
||||
fn inline_completion_popover_text(
|
||||
editor_snapshot: &EditorSnapshot,
|
||||
edits: &Vec<(Range<Anchor>, String)>,
|
||||
applied_edits_buffer: Model<Buffer>,
|
||||
cx: &WindowContext,
|
||||
) -> (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()
|
||||
.unwrap()
|
||||
.0
|
||||
.start
|
||||
.to_display_point(editor_snapshot);
|
||||
|
||||
let mut text = String::new();
|
||||
let mut offset = DisplayPoint::new(edit_start.row(), 0).to_offset(editor_snapshot, Bias::Left);
|
||||
let mut highlights = Vec::new();
|
||||
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||
.text_anchor
|
||||
.to_point(&snapshot);
|
||||
start.column = 0;
|
||||
let mut offset = text::ToOffset::to_offset(&start, &snapshot);
|
||||
for (old_range, new_text) in edits {
|
||||
let old_offset_range = old_range.to_offset(&editor_snapshot.buffer_snapshot);
|
||||
text.extend(
|
||||
editor_snapshot
|
||||
.buffer_snapshot
|
||||
.chunks(offset..old_offset_range.start, false)
|
||||
.map(|chunk| chunk.text),
|
||||
);
|
||||
offset = old_offset_range.end;
|
||||
let edit_new_start = old_range
|
||||
.start
|
||||
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||
.text_anchor
|
||||
.to_offset(&snapshot);
|
||||
for chunk in snapshot.chunks(offset..edit_new_start, true) {
|
||||
let start = text.len();
|
||||
text.push_str(chunk.text);
|
||||
let end = text.len();
|
||||
|
||||
let start = text.len();
|
||||
text.push_str(new_text);
|
||||
let end = text.len();
|
||||
highlights.push((
|
||||
start..end,
|
||||
HighlightStyle {
|
||||
if let Some(highlight_style) = chunk
|
||||
.syntax_highlight_id
|
||||
.and_then(|id| id.style(cx.theme().syntax()))
|
||||
{
|
||||
highlights.push((start..end, highlight_style));
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
..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()
|
||||
.unwrap()
|
||||
.0
|
||||
.end
|
||||
.to_display_point(editor_snapshot);
|
||||
let end_of_line = DisplayPoint::new(edit_end.row(), editor_snapshot.line_len(edit_end.row()))
|
||||
.to_offset(editor_snapshot, Bias::Right);
|
||||
text.extend(
|
||||
editor_snapshot
|
||||
.buffer_snapshot
|
||||
.chunks(offset..end_of_line, false)
|
||||
.map(|chunk| chunk.text),
|
||||
);
|
||||
.bias_left(&editor_snapshot.buffer_snapshot)
|
||||
.text_anchor
|
||||
.to_point(&snapshot);
|
||||
end.column = snapshot.line_len(end.row);
|
||||
let end = text::ToOffset::to_offset(&end, &snapshot);
|
||||
|
||||
for chunk in snapshot.chunks(offset..end, true) {
|
||||
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)
|
||||
}
|
||||
@@ -6657,7 +6700,7 @@ mod tests {
|
||||
editor_tests::{init_test, update_test_language_settings},
|
||||
Editor, MultiBuffer,
|
||||
};
|
||||
use gpui::{TestAppContext, VisualTestContext};
|
||||
use gpui::{AppContext, TestAppContext, VisualTestContext};
|
||||
use language::language_settings;
|
||||
use log::info;
|
||||
use std::num::NonZeroU32;
|
||||
@@ -7127,7 +7170,12 @@ mod tests {
|
||||
..snapshot.buffer_snapshot.anchor_before(Point::new(0, 6));
|
||||
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!(highlights.len(), 1);
|
||||
@@ -7157,7 +7205,12 @@ mod tests {
|
||||
"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!(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!(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!(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(
|
||||
cx: &mut TestAppContext,
|
||||
editor_mode: EditorMode,
|
||||
|
||||
@@ -237,7 +237,7 @@ fn assert_editor_active_edit_completion(
|
||||
.as_ref()
|
||||
.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);
|
||||
} else {
|
||||
panic!("expected edit completion");
|
||||
|
||||
Reference in New Issue
Block a user