Support clicking on a completion to confirm it

This commit is contained in:
Antonio Scandurra 2022-02-03 11:39:19 +01:00
parent 7865c32727
commit efcbf2714c
6 changed files with 71 additions and 34 deletions

View File

@ -23,6 +23,7 @@ use gpui::{
fonts::{self, HighlightStyle, TextStyle},
geometry::vector::{vec2f, Vector2F},
keymap::Binding,
platform::CursorStyle,
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
MutableAppContext, RenderContext, Task, View, ViewContext, WeakModelHandle, WeakViewHandle,
};
@ -123,7 +124,7 @@ action!(FoldSelectedRanges);
action!(Scroll, Vector2F);
action!(Select, SelectPhase);
action!(ShowCompletions);
action!(ConfirmCompletion);
action!(ConfirmCompletion, Option<usize>);
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
path_openers.push(Box::new(items::BufferOpener));
@ -139,7 +140,11 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
Input("\n".into()),
Some("Editor && mode == auto_height"),
),
Binding::new("enter", ConfirmCompletion, Some("Editor && completing")),
Binding::new(
"enter",
ConfirmCompletion(None),
Some("Editor && completing"),
),
Binding::new("tab", Tab, Some("Editor")),
Binding::new("shift-tab", Outdent, Some("Editor")),
Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")),
@ -297,11 +302,13 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
cx.add_action(Editor::unfold);
cx.add_action(Editor::fold_selected_ranges);
cx.add_action(Editor::show_completions);
cx.add_action(|editor: &mut Editor, _: &ConfirmCompletion, cx| {
if let Some(task) = editor.confirm_completion(cx) {
task.detach_and_log_err(cx);
}
});
cx.add_action(
|editor: &mut Editor, &ConfirmCompletion(ix): &ConfirmCompletion, cx| {
if let Some(task) = editor.confirm_completion(ix, cx) {
task.detach_and_log_err(cx);
}
},
);
}
trait SelectionExt {
@ -1669,11 +1676,15 @@ impl Editor {
self.completion_state.take()
}
fn confirm_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
fn confirm_completion(
&mut self,
completion_ix: Option<usize>,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> {
let completion_state = self.hide_completions(cx)?;
let mat = completion_state
.matches
.get(completion_state.selected_item)?;
.get(completion_ix.unwrap_or(completion_state.selected_item))?;
let completion = completion_state.completions.get(mat.candidate_id)?;
if completion.is_snippet() {
@ -1702,6 +1713,8 @@ impl Editor {
}
pub fn render_completions(&self, cx: &AppContext) -> Option<ElementBox> {
enum CompletionTag {}
self.completion_state.as_ref().map(|state| {
let build_settings = self.build_settings.clone();
let settings = build_settings(cx);
@ -1715,30 +1728,48 @@ impl Editor {
let settings = build_settings(cx);
let start_ix = range.start;
for (ix, mat) in matches[range].iter().enumerate() {
let item_style = if start_ix + ix == selected_item {
settings.style.autocomplete.selected_item
} else {
settings.style.autocomplete.item
};
let completion = &completions[mat.candidate_id];
let item_ix = start_ix + ix;
items.push(
Text::new(completion.label.text.clone(), settings.style.text.clone())
.with_soft_wrap(false)
.with_highlights(combine_syntax_and_fuzzy_match_highlights(
&completion.label.text,
settings.style.text.color.into(),
completion.label.runs.iter().filter_map(
|(range, highlight_id)| {
highlight_id
.style(&settings.style.syntax)
.map(|style| (range.clone(), style))
},
),
&mat.positions,
))
.contained()
.with_style(item_style)
.boxed(),
MouseEventHandler::new::<CompletionTag, _, _, _>(
mat.candidate_id,
cx,
|state, _| {
let item_style = if item_ix == selected_item {
settings.style.autocomplete.selected_item
} else if state.hovered {
settings.style.autocomplete.hovered_item
} else {
settings.style.autocomplete.item
};
Text::new(
completion.label.text.clone(),
settings.style.text.clone(),
)
.with_soft_wrap(false)
.with_highlights(combine_syntax_and_fuzzy_match_highlights(
&completion.label.text,
settings.style.text.color.into(),
completion.label.runs.iter().filter_map(
|(range, highlight_id)| {
highlight_id
.style(&settings.style.syntax)
.map(|style| (range.clone(), style))
},
),
&mat.positions,
))
.contained()
.with_style(item_style)
.boxed()
},
)
.with_cursor_style(CursorStyle::PointingHand)
.on_mouse_down(move |cx| {
cx.dispatch_action(ConfirmCompletion(Some(item_ix)));
})
.boxed(),
);
}
},
@ -6952,7 +6983,7 @@ mod tests {
let apply_additional_edits = editor.update(&mut cx, |editor, cx| {
editor.move_down(&MoveDown, cx);
let apply_additional_edits = editor.confirm_completion(cx).unwrap();
let apply_additional_edits = editor.confirm_completion(None, cx).unwrap();
assert_eq!(
editor.text(cx),
"

View File

@ -328,6 +328,7 @@ pub struct AutocompleteStyle {
pub container: ContainerStyle,
pub item: ContainerStyle,
pub selected_item: ContainerStyle,
pub hovered_item: ContainerStyle,
pub match_highlight: HighlightStyle,
}

View File

@ -322,6 +322,10 @@ match_highlight = { color = "$editor.syntax.keyword.color", weight = "$editor.sy
[editor.autocomplete.selected_item]
extends = "$editor.autocomplete.item"
background = "$state.selected"
[editor.autocomplete.hovered_item]
extends = "$editor.autocomplete.item"
background = "$state.hover"
[project_diagnostics]

View File

@ -40,6 +40,7 @@ bad = "#b7372e"
active_line = "#161313"
highlighted_line = "#faca5033"
hover = "#00000033"
selected = "#00000088"
[editor.syntax]
keyword = { color = "#0086c0", weight = "bold" }

View File

@ -40,6 +40,7 @@ bad = "#b7372e"
active_line = "#00000022"
highlighted_line = "#faca5033"
hover = "#00000033"
selected = "#00000088"
[editor.syntax]
keyword = { color = "#0086c0", weight = "bold" }
@ -51,7 +52,6 @@ comment = "#6a9955"
property = "#4e94ce"
variant = "#4fc1ff"
constant = "#9cdcfe"
title = { color = "#9cdcfe", weight = "bold" }
emphasis = "#4ec9b0"
"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }

View File

@ -40,6 +40,7 @@ bad = "#b7372e"
active_line = "#00000008"
highlighted_line = "#faca5033"
hover = "#0000000D"
selected = "#0000001c"
[editor.syntax]
keyword = { color = "#0000fa", weight = "bold" }
@ -51,7 +52,6 @@ comment = "#6a9955"
property = "#4e94ce"
variant = "#4fc1ff"
constant = "#5a9ccc"
title = { color = "#5a9ccc", weight = "bold" }
emphasis = "#267f29"
"emphasis.strong" = { color = "#267f29", weight = "bold" }