diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 00201dbd3208fcdc44925931ed3f940045dac13d..0707f7156045254e3a0f7b71c79b4c92f60b3ef7 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -191,6 +191,7 @@ actions!( UnfoldLines, FoldSelectedRanges, ShowCompletions, + ShowHover, OpenExcerpts, RestartLanguageServer, ] @@ -413,6 +414,7 @@ pub struct Editor { next_completion_id: CompletionId, available_code_actions: Option<(ModelHandle, Arc<[CodeAction]>)>, code_actions_task: Option>, + hover_task: Option>, document_highlights_task: Option>, pending_rename: Option, searchable: bool, @@ -559,6 +561,7 @@ struct InvalidationStack(Vec); enum ContextMenu { Completions(CompletionsMenu), CodeActions(CodeActionsMenu), + Hover(HoverPopover), } impl ContextMenu { @@ -567,6 +570,7 @@ impl ContextMenu { match self { ContextMenu::Completions(menu) => menu.select_prev(cx), ContextMenu::CodeActions(menu) => menu.select_prev(cx), + _ => {} } true } else { @@ -579,6 +583,7 @@ impl ContextMenu { match self { ContextMenu::Completions(menu) => menu.select_next(cx), ContextMenu::CodeActions(menu) => menu.select_next(cx), + _ => {} } true } else { @@ -590,6 +595,7 @@ impl ContextMenu { match self { ContextMenu::Completions(menu) => menu.visible(), ContextMenu::CodeActions(menu) => menu.visible(), + ContextMenu::Hover(_) => true, } } @@ -602,6 +608,7 @@ impl ContextMenu { match self { ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)), ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx), + ContextMenu::Hover(popover) => (cursor_position, popover.render(style)), } } } @@ -846,6 +853,22 @@ impl CodeActionsMenu { } } +#[derive(Clone)] +struct HoverPopover { + pub text: String, + pub runs: Vec<(Range, HighlightStyle)>, +} + +impl HoverPopover { + fn render(&self, style: EditorStyle) -> ElementBox { + Text::new(self.text.clone(), style.text.clone()) + .with_soft_wrap(false) + .with_highlights(self.runs.clone()) + .contained() + .boxed() + } +} + #[derive(Debug)] struct ActiveDiagnosticGroup { primary_range: Range, @@ -2385,6 +2408,59 @@ impl Editor { })) } + fn show_hover(&mut self, _: &ShowHover, cx: &mut ViewContext) { + if self.pending_rename.is_some() { + return; + } + + let project = if let Some(project) = self.project.clone() { + project + } else { + return; + }; + + let position = self.selections.newest_anchor().head(); + let (buffer, buffer_position) = if let Some(output) = self + .buffer + .read(cx) + .text_anchor_for_position(position.clone(), cx) + { + output + } else { + return; + }; + + let hover = HoverPopover { + text: "Test hover information".to_string(), + runs: Vec::new(), + }; + + let id = post_inc(&mut self.next_completion_id); + let task = cx.spawn_weak(|this, mut cx| { + async move { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + if !matches!( + this.context_menu.as_ref(), + None | Some(ContextMenu::Hover(_)) + ) { + return; + } + + if this.focused { + this.show_context_menu(ContextMenu::Hover(hover), cx); + } + + cx.notify(); + }); + } + Ok::<_, anyhow::Error>(()) + } + .log_err() + }); + self.completion_tasks.push((id, task)); + } + async fn open_project_transaction( this: ViewHandle, workspace: ViewHandle, @@ -2628,7 +2704,7 @@ impl Editor { ) -> Option<(DisplayPoint, ElementBox)> { self.context_menu .as_ref() - .map(|menu| menu.render(cursor_position, style, cx)) + .map(|menu| menu.render(cursor_position, style)) } fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext) { @@ -5665,6 +5741,9 @@ impl View for Editor { Some(ContextMenu::CodeActions(_)) => { context.set.insert("showing_code_actions".into()); } + Some(ContextMenu::Hover(_)) => { + context.set.insert("showing_hover".into()); + } None => {} } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index daeb9b56948f65e5e230345d82248bbd83381403..5555a8fb11df4014f658cf763c08d5c43924ff3c 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1091,8 +1091,7 @@ impl Element for EditorElement { if (start_row..end_row).contains(&newest_selection_head.row()) { let style = view.style(cx); if view.context_menu_visible() { - context_menu = - view.render_context_menu(newest_selection_head, style.clone(), cx); + context_menu = view.render_context_menu(newest_selection_head, style.clone()); } code_actions_indicator = view