diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 30ef12b886..1cf156a72f 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -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); pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec>) { path_openers.push(Box::new(items::BufferOpener)); @@ -139,7 +140,11 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec) -> Option>> { + fn confirm_completion( + &mut self, + completion_ix: Option, + cx: &mut ViewContext, + ) -> Option>> { 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 { + 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::( + 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), " diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index d097e1b003..339cabbbf3 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -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, } diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 2475dd9531..150561e3c6 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -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] diff --git a/crates/zed/assets/themes/black.toml b/crates/zed/assets/themes/black.toml index a197673f67..bc9f6c75d6 100644 --- a/crates/zed/assets/themes/black.toml +++ b/crates/zed/assets/themes/black.toml @@ -40,6 +40,7 @@ bad = "#b7372e" active_line = "#161313" highlighted_line = "#faca5033" hover = "#00000033" +selected = "#00000088" [editor.syntax] keyword = { color = "#0086c0", weight = "bold" } diff --git a/crates/zed/assets/themes/dark.toml b/crates/zed/assets/themes/dark.toml index 9450d22641..acfbf083c0 100644 --- a/crates/zed/assets/themes/dark.toml +++ b/crates/zed/assets/themes/dark.toml @@ -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" } diff --git a/crates/zed/assets/themes/light.toml b/crates/zed/assets/themes/light.toml index 3113a69110..cf8ebe34e6 100644 --- a/crates/zed/assets/themes/light.toml +++ b/crates/zed/assets/themes/light.toml @@ -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" }