diff --git a/book/src/generated/static-cmd.md b/book/src/generated/static-cmd.md index 4d838a10999d..7de7c436292e 100644 --- a/book/src/generated/static-cmd.md +++ b/book/src/generated/static-cmd.md @@ -200,6 +200,7 @@ | `remove_primary_selection` | Remove primary selection | normal: `` ``, select: `` `` | | `completion` | Invoke completion popup | insert: `` `` | | `hover` | Show docs for item under cursor | normal: `` k ``, select: `` k `` | +| `hover_dump` | Show docs for item under cursor in a new buffer | normal: `` K ``, select: `` K `` | | `toggle_comments` | Comment/uncomment selections | normal: `` ``, `` c ``, select: `` ``, `` c `` | | `toggle_line_comments` | Line comment/uncomment selections | normal: `` ``, select: `` `` | | `toggle_block_comments` | Block comment/uncomment selections | normal: `` C ``, select: `` C `` | diff --git a/book/src/keymap.md b/book/src/keymap.md index 2797eaee2908..5ece2afc6835 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -290,6 +290,7 @@ This layer is a kludge of mappings, mostly pickers. | `g` | Open changed file picker | `changed_file_picker` | | `G` | Debug (experimental) | N/A | | `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` | +| `K` | Show documentation for item under cursor in a new buffer (**LSP**) | `hover_dump` | | `s` | Open document symbol picker (**LSP**) | `symbol_picker` | | `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` | | `d` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index d08148362e25..2ebeb2416ab9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -476,6 +476,7 @@ impl MappableCommand { remove_primary_selection, "Remove primary selection", completion, "Invoke completion popup", hover, "Show docs for item under cursor", + hover_dump, "Show docs for item under cursor in a new buffer", toggle_comments, "Comment/uncomment selections", toggle_line_comments, "Line comment/uncomment selections", toggle_block_comments, "Block comment/uncomment selections", diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index fcc0333e8cd8..e7fa0825a160 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -14,7 +14,7 @@ use tui::{text::Span, widgets::Row}; use super::{align_view, push_jump, Align, Context, Editor}; use helix_core::{ - syntax::LanguageServerFeature, text_annotations::InlineAnnotation, Selection, Uri, + syntax::LanguageServerFeature, text_annotations::InlineAnnotation, Rope, Selection, Uri, }; use helix_stdx::path; use helix_view::{ @@ -1008,7 +1008,10 @@ pub fn signature_help(cx: &mut Context) { .trigger_signature_help(SignatureHelpInvoked::Manual, cx.editor) } -pub fn hover(cx: &mut Context) { +pub fn hover_impl(cx: &mut Context, callback: T) +where + T: FnOnce(String, &mut Editor, &mut Compositor) + std::marker::Send + 'static, +{ let (view, doc) = current!(cx.editor); // TODO support multiple language servers (merge UI somehow) @@ -1049,16 +1052,31 @@ pub fn hover(cx: &mut Context) { lsp::HoverContents::Markup(contents) => contents.value, }; - // skip if contents empty - - let contents = ui::Markdown::new(contents, editor.syn_loader.clone()); - let popup = Popup::new("hover", contents).auto_close(true); - compositor.replace_or_push("hover", popup); + callback(contents, editor, compositor); } }, ); } +pub fn hover_dump(cx: &mut Context) { + hover_impl(cx, |contents, editor, _compositor| { + editor.new_file_from_document( + Action::VerticalSplit, + Document::from(Rope::from(contents), None, editor.config.clone()), + ); + let hover_doc = doc_mut!(editor); + let _ = hover_doc.set_language_by_language_id("markdown", editor.syn_loader.clone()); + }) +} + +pub fn hover(cx: &mut Context) { + hover_impl(cx, |contents, editor, compositor| { + let contents = ui::Markdown::new(contents, editor.syn_loader.clone()); + let popup = Popup::new("hover", contents).auto_close(true); + compositor.replace_or_push("hover", popup); + }) +} + pub fn rename_symbol(cx: &mut Context) { fn get_prefill_from_word_boundary(editor: &Editor) -> String { let (view, doc) = current_ref!(editor); diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index c6cefd927574..b92ee862a92d 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -281,6 +281,7 @@ pub fn default() -> HashMap { "R" => replace_selections_with_clipboard, "/" => global_search, "k" => hover, + "K" => hover_dump, "r" => rename_symbol, "h" => select_references_to_symbol_under_cursor, "c" => toggle_comments, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index aa9a11533bbb..f492a5f8db30 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -1689,7 +1689,7 @@ impl Editor { id } - fn new_file_from_document(&mut self, action: Action, doc: Document) -> DocumentId { + pub fn new_file_from_document(&mut self, action: Action, doc: Document) -> DocumentId { let id = self.new_document(doc); self.switch(id, action); id