mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Support clicking on a completion to confirm it
This commit is contained in:
parent
7865c32727
commit
efcbf2714c
@ -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),
|
||||
"
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -40,6 +40,7 @@ bad = "#b7372e"
|
||||
active_line = "#161313"
|
||||
highlighted_line = "#faca5033"
|
||||
hover = "#00000033"
|
||||
selected = "#00000088"
|
||||
|
||||
[editor.syntax]
|
||||
keyword = { color = "#0086c0", weight = "bold" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
Loading…
Reference in New Issue
Block a user