Support clicking on a completion to confirm it
This commit is contained in:
parent
7865c32727
commit
efcbf2714c
6 changed files with 71 additions and 34 deletions
|
@ -23,6 +23,7 @@ use gpui::{
|
||||||
fonts::{self, HighlightStyle, TextStyle},
|
fonts::{self, HighlightStyle, TextStyle},
|
||||||
geometry::vector::{vec2f, Vector2F},
|
geometry::vector::{vec2f, Vector2F},
|
||||||
keymap::Binding,
|
keymap::Binding,
|
||||||
|
platform::CursorStyle,
|
||||||
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
||||||
MutableAppContext, RenderContext, Task, View, ViewContext, WeakModelHandle, WeakViewHandle,
|
MutableAppContext, RenderContext, Task, View, ViewContext, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
|
@ -123,7 +124,7 @@ action!(FoldSelectedRanges);
|
||||||
action!(Scroll, Vector2F);
|
action!(Scroll, Vector2F);
|
||||||
action!(Select, SelectPhase);
|
action!(Select, SelectPhase);
|
||||||
action!(ShowCompletions);
|
action!(ShowCompletions);
|
||||||
action!(ConfirmCompletion);
|
action!(ConfirmCompletion, Option<usize>);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
|
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
|
||||||
path_openers.push(Box::new(items::BufferOpener));
|
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()),
|
Input("\n".into()),
|
||||||
Some("Editor && mode == auto_height"),
|
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("tab", Tab, Some("Editor")),
|
||||||
Binding::new("shift-tab", Outdent, Some("Editor")),
|
Binding::new("shift-tab", Outdent, Some("Editor")),
|
||||||
Binding::new("ctrl-shift-K", DeleteLine, 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::unfold);
|
||||||
cx.add_action(Editor::fold_selected_ranges);
|
cx.add_action(Editor::fold_selected_ranges);
|
||||||
cx.add_action(Editor::show_completions);
|
cx.add_action(Editor::show_completions);
|
||||||
cx.add_action(|editor: &mut Editor, _: &ConfirmCompletion, cx| {
|
cx.add_action(
|
||||||
if let Some(task) = editor.confirm_completion(cx) {
|
|editor: &mut Editor, &ConfirmCompletion(ix): &ConfirmCompletion, cx| {
|
||||||
task.detach_and_log_err(cx);
|
if let Some(task) = editor.confirm_completion(ix, cx) {
|
||||||
}
|
task.detach_and_log_err(cx);
|
||||||
});
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SelectionExt {
|
trait SelectionExt {
|
||||||
|
@ -1669,11 +1676,15 @@ impl Editor {
|
||||||
self.completion_state.take()
|
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 completion_state = self.hide_completions(cx)?;
|
||||||
let mat = completion_state
|
let mat = completion_state
|
||||||
.matches
|
.matches
|
||||||
.get(completion_state.selected_item)?;
|
.get(completion_ix.unwrap_or(completion_state.selected_item))?;
|
||||||
let completion = completion_state.completions.get(mat.candidate_id)?;
|
let completion = completion_state.completions.get(mat.candidate_id)?;
|
||||||
|
|
||||||
if completion.is_snippet() {
|
if completion.is_snippet() {
|
||||||
|
@ -1702,6 +1713,8 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_completions(&self, cx: &AppContext) -> Option<ElementBox> {
|
pub fn render_completions(&self, cx: &AppContext) -> Option<ElementBox> {
|
||||||
|
enum CompletionTag {}
|
||||||
|
|
||||||
self.completion_state.as_ref().map(|state| {
|
self.completion_state.as_ref().map(|state| {
|
||||||
let build_settings = self.build_settings.clone();
|
let build_settings = self.build_settings.clone();
|
||||||
let settings = build_settings(cx);
|
let settings = build_settings(cx);
|
||||||
|
@ -1715,30 +1728,48 @@ impl Editor {
|
||||||
let settings = build_settings(cx);
|
let settings = build_settings(cx);
|
||||||
let start_ix = range.start;
|
let start_ix = range.start;
|
||||||
for (ix, mat) in matches[range].iter().enumerate() {
|
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 completion = &completions[mat.candidate_id];
|
||||||
|
let item_ix = start_ix + ix;
|
||||||
items.push(
|
items.push(
|
||||||
Text::new(completion.label.text.clone(), settings.style.text.clone())
|
MouseEventHandler::new::<CompletionTag, _, _, _>(
|
||||||
.with_soft_wrap(false)
|
mat.candidate_id,
|
||||||
.with_highlights(combine_syntax_and_fuzzy_match_highlights(
|
cx,
|
||||||
&completion.label.text,
|
|state, _| {
|
||||||
settings.style.text.color.into(),
|
let item_style = if item_ix == selected_item {
|
||||||
completion.label.runs.iter().filter_map(
|
settings.style.autocomplete.selected_item
|
||||||
|(range, highlight_id)| {
|
} else if state.hovered {
|
||||||
highlight_id
|
settings.style.autocomplete.hovered_item
|
||||||
.style(&settings.style.syntax)
|
} else {
|
||||||
.map(|style| (range.clone(), style))
|
settings.style.autocomplete.item
|
||||||
},
|
};
|
||||||
),
|
|
||||||
&mat.positions,
|
Text::new(
|
||||||
))
|
completion.label.text.clone(),
|
||||||
.contained()
|
settings.style.text.clone(),
|
||||||
.with_style(item_style)
|
)
|
||||||
.boxed(),
|
.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| {
|
let apply_additional_edits = editor.update(&mut cx, |editor, cx| {
|
||||||
editor.move_down(&MoveDown, 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!(
|
assert_eq!(
|
||||||
editor.text(cx),
|
editor.text(cx),
|
||||||
"
|
"
|
||||||
|
|
|
@ -328,6 +328,7 @@ pub struct AutocompleteStyle {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub item: ContainerStyle,
|
pub item: ContainerStyle,
|
||||||
pub selected_item: ContainerStyle,
|
pub selected_item: ContainerStyle,
|
||||||
|
pub hovered_item: ContainerStyle,
|
||||||
pub match_highlight: HighlightStyle,
|
pub match_highlight: HighlightStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,10 @@ match_highlight = { color = "$editor.syntax.keyword.color", weight = "$editor.sy
|
||||||
|
|
||||||
[editor.autocomplete.selected_item]
|
[editor.autocomplete.selected_item]
|
||||||
extends = "$editor.autocomplete.item"
|
extends = "$editor.autocomplete.item"
|
||||||
|
background = "$state.selected"
|
||||||
|
|
||||||
|
[editor.autocomplete.hovered_item]
|
||||||
|
extends = "$editor.autocomplete.item"
|
||||||
background = "$state.hover"
|
background = "$state.hover"
|
||||||
|
|
||||||
[project_diagnostics]
|
[project_diagnostics]
|
||||||
|
|
|
@ -40,6 +40,7 @@ bad = "#b7372e"
|
||||||
active_line = "#161313"
|
active_line = "#161313"
|
||||||
highlighted_line = "#faca5033"
|
highlighted_line = "#faca5033"
|
||||||
hover = "#00000033"
|
hover = "#00000033"
|
||||||
|
selected = "#00000088"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
keyword = { color = "#0086c0", weight = "bold" }
|
keyword = { color = "#0086c0", weight = "bold" }
|
||||||
|
|
|
@ -40,6 +40,7 @@ bad = "#b7372e"
|
||||||
active_line = "#00000022"
|
active_line = "#00000022"
|
||||||
highlighted_line = "#faca5033"
|
highlighted_line = "#faca5033"
|
||||||
hover = "#00000033"
|
hover = "#00000033"
|
||||||
|
selected = "#00000088"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
keyword = { color = "#0086c0", weight = "bold" }
|
keyword = { color = "#0086c0", weight = "bold" }
|
||||||
|
@ -51,7 +52,6 @@ comment = "#6a9955"
|
||||||
property = "#4e94ce"
|
property = "#4e94ce"
|
||||||
variant = "#4fc1ff"
|
variant = "#4fc1ff"
|
||||||
constant = "#9cdcfe"
|
constant = "#9cdcfe"
|
||||||
|
|
||||||
title = { color = "#9cdcfe", weight = "bold" }
|
title = { color = "#9cdcfe", weight = "bold" }
|
||||||
emphasis = "#4ec9b0"
|
emphasis = "#4ec9b0"
|
||||||
"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
|
"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
|
||||||
|
|
|
@ -40,6 +40,7 @@ bad = "#b7372e"
|
||||||
active_line = "#00000008"
|
active_line = "#00000008"
|
||||||
highlighted_line = "#faca5033"
|
highlighted_line = "#faca5033"
|
||||||
hover = "#0000000D"
|
hover = "#0000000D"
|
||||||
|
selected = "#0000001c"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
keyword = { color = "#0000fa", weight = "bold" }
|
keyword = { color = "#0000fa", weight = "bold" }
|
||||||
|
@ -51,7 +52,6 @@ comment = "#6a9955"
|
||||||
property = "#4e94ce"
|
property = "#4e94ce"
|
||||||
variant = "#4fc1ff"
|
variant = "#4fc1ff"
|
||||||
constant = "#5a9ccc"
|
constant = "#5a9ccc"
|
||||||
|
|
||||||
title = { color = "#5a9ccc", weight = "bold" }
|
title = { color = "#5a9ccc", weight = "bold" }
|
||||||
emphasis = "#267f29"
|
emphasis = "#267f29"
|
||||||
"emphasis.strong" = { color = "#267f29", weight = "bold" }
|
"emphasis.strong" = { color = "#267f29", weight = "bold" }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue