mirror of https://github.com/helix-editor/helix
Merge 1cf3d19722
into 362e97e927
commit
7ab7bfcf9e
|
@ -208,6 +208,7 @@
|
||||||
| `remove_primary_selection` | Remove primary selection | normal: `` <A-,> ``, select: `` <A-,> `` |
|
| `remove_primary_selection` | Remove primary selection | normal: `` <A-,> ``, select: `` <A-,> `` |
|
||||||
| `completion` | Invoke completion popup | insert: `` <C-x> `` |
|
| `completion` | Invoke completion popup | insert: `` <C-x> `` |
|
||||||
| `hover` | Show docs for item under cursor | normal: `` <space>k ``, select: `` <space>k `` |
|
| `hover` | Show docs for item under cursor | normal: `` <space>k ``, select: `` <space>k `` |
|
||||||
|
| `hover_dump` | Show docs for item under cursor in a new buffer | normal: `` <space>K ``, select: `` <space>K `` |
|
||||||
| `toggle_comments` | Comment/uncomment selections | normal: `` <C-c> ``, `` <space>c ``, select: `` <C-c> ``, `` <space>c `` |
|
| `toggle_comments` | Comment/uncomment selections | normal: `` <C-c> ``, `` <space>c ``, select: `` <C-c> ``, `` <space>c `` |
|
||||||
| `toggle_line_comments` | Line comment/uncomment selections | normal: `` <space><A-c> ``, select: `` <space><A-c> `` |
|
| `toggle_line_comments` | Line comment/uncomment selections | normal: `` <space><A-c> ``, select: `` <space><A-c> `` |
|
||||||
| `toggle_block_comments` | Block comment/uncomment selections | normal: `` <space>C ``, select: `` <space>C `` |
|
| `toggle_block_comments` | Block comment/uncomment selections | normal: `` <space>C ``, select: `` <space>C `` |
|
||||||
|
|
|
@ -291,6 +291,7 @@ This layer is a kludge of mappings, mostly pickers.
|
||||||
| `g` | Open changed file picker | `changed_file_picker` |
|
| `g` | Open changed file picker | `changed_file_picker` |
|
||||||
| `G` | Debug (experimental) | N/A |
|
| `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 [popup](#popup) (**LSP**) | `hover` |
|
||||||
|
| `K` | Go to documentation for item under cursor in a new buffer (**LSP**) | `goto_hover` |
|
||||||
| `s` | Open document symbol picker (**LSP**) | `symbol_picker` |
|
| `s` | Open document symbol picker (**LSP**) | `symbol_picker` |
|
||||||
| `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` |
|
| `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` |
|
||||||
| `d` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` |
|
| `d` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` |
|
||||||
|
|
|
@ -506,6 +506,7 @@ impl MappableCommand {
|
||||||
remove_primary_selection, "Remove primary selection",
|
remove_primary_selection, "Remove primary selection",
|
||||||
completion, "Invoke completion popup",
|
completion, "Invoke completion popup",
|
||||||
hover, "Show docs for item under cursor",
|
hover, "Show docs for item under cursor",
|
||||||
|
goto_hover, "Show docs for item under cursor in a new buffer",
|
||||||
toggle_comments, "Comment/uncomment selections",
|
toggle_comments, "Comment/uncomment selections",
|
||||||
toggle_line_comments, "Line comment/uncomment selections",
|
toggle_line_comments, "Line comment/uncomment selections",
|
||||||
toggle_block_comments, "Block comment/uncomment selections",
|
toggle_block_comments, "Block comment/uncomment selections",
|
||||||
|
|
|
@ -15,7 +15,7 @@ use super::{align_view, push_jump, Align, Context, Editor};
|
||||||
|
|
||||||
use helix_core::{
|
use helix_core::{
|
||||||
diagnostic::DiagnosticProvider, syntax::config::LanguageServerFeature,
|
diagnostic::DiagnosticProvider, syntax::config::LanguageServerFeature,
|
||||||
text_annotations::InlineAnnotation, Selection, Uri,
|
text_annotations::InlineAnnotation, Rope, Selection, Uri,
|
||||||
};
|
};
|
||||||
use helix_stdx::path;
|
use helix_stdx::path;
|
||||||
use helix_view::{
|
use helix_view::{
|
||||||
|
@ -32,7 +32,9 @@ use crate::{
|
||||||
ui::{self, overlay::overlaid, FileLocation, Picker, Popup, PromptEvent},
|
ui::{self, overlay::overlaid, FileLocation, Picker, Popup, PromptEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{cmp::Ordering, collections::HashSet, fmt::Display, future::Future, path::Path};
|
use std::{
|
||||||
|
cmp::Ordering, collections::HashSet, fmt::Display, future::Future, path::Path, sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
/// Gets the first language server that is attached to a document which supports a specific feature.
|
/// Gets the first language server that is attached to a document which supports a specific feature.
|
||||||
/// If there is no configured language server that supports the feature, this displays a status message.
|
/// If there is no configured language server that supports the feature, this displays a status message.
|
||||||
|
@ -1015,7 +1017,12 @@ pub fn signature_help(cx: &mut Context) {
|
||||||
.trigger_signature_help(SignatureHelpInvoked::Manual, cx.editor)
|
.trigger_signature_help(SignatureHelpInvoked::Manual, cx.editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover(cx: &mut Context) {
|
enum HoverDisplay {
|
||||||
|
Popup,
|
||||||
|
File,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hover_impl(cx: &mut Context, hover_action: HoverDisplay) {
|
||||||
use ui::lsp::hover::Hover;
|
use ui::lsp::hover::Hover;
|
||||||
|
|
||||||
let (view, doc) = current!(cx.editor);
|
let (view, doc) = current!(cx.editor);
|
||||||
|
@ -1062,15 +1069,42 @@ pub fn hover(cx: &mut Context) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new popup
|
let hover = Hover::new(hovers, editor.syn_loader.clone());
|
||||||
let contents = Hover::new(hovers, editor.syn_loader.clone());
|
|
||||||
let popup = Popup::new(Hover::ID, contents).auto_close(true);
|
match hover_action {
|
||||||
compositor.replace_or_push(Hover::ID, popup);
|
HoverDisplay::Popup => {
|
||||||
|
let popup = Popup::new(Hover::ID, hover).auto_close(true);
|
||||||
|
compositor.replace_or_push(Hover::ID, popup);
|
||||||
|
}
|
||||||
|
HoverDisplay::File => {
|
||||||
|
editor.new_file_from_document(
|
||||||
|
Action::Replace,
|
||||||
|
Document::from(
|
||||||
|
Rope::from(hover.content_string()),
|
||||||
|
None,
|
||||||
|
Arc::clone(&editor.config),
|
||||||
|
Arc::clone(&editor.syn_loader),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let hover_doc = doc_mut!(editor);
|
||||||
|
|
||||||
|
let _ = hover_doc
|
||||||
|
.set_language_by_language_id("markdown", &editor.syn_loader.load());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(Callback::EditorCompositor(Box::new(call)))
|
Ok(Callback::EditorCompositor(Box::new(call)))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hover(cx: &mut Context) {
|
||||||
|
hover_impl(cx, HoverDisplay::Popup)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn goto_hover(cx: &mut Context) {
|
||||||
|
hover_impl(cx, HoverDisplay::File)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rename_symbol(cx: &mut Context) {
|
pub fn rename_symbol(cx: &mut Context) {
|
||||||
fn get_prefill_from_word_boundary(editor: &Editor) -> String {
|
fn get_prefill_from_word_boundary(editor: &Editor) -> String {
|
||||||
let (view, doc) = current_ref!(editor);
|
let (view, doc) = current_ref!(editor);
|
||||||
|
|
|
@ -284,6 +284,7 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
|
||||||
"R" => replace_selections_with_clipboard,
|
"R" => replace_selections_with_clipboard,
|
||||||
"/" => global_search,
|
"/" => global_search,
|
||||||
"k" => hover,
|
"k" => hover,
|
||||||
|
"K" => goto_hover,
|
||||||
"r" => rename_symbol,
|
"r" => rename_symbol,
|
||||||
"h" => select_references_to_symbol_under_cursor,
|
"h" => select_references_to_symbol_under_cursor,
|
||||||
"c" => toggle_comments,
|
"c" => toggle_comments,
|
||||||
|
|
|
@ -30,16 +30,15 @@ impl Hover {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, (server_name, hover))| {
|
.map(|(idx, (server_name, hover))| {
|
||||||
let header = (n_hovers > 1).then(|| {
|
let header = (n_hovers > 1)
|
||||||
Markdown::new(
|
.then(|| format!("**[{}/{}] {}**\n", idx + 1, n_hovers, server_name))
|
||||||
format!("**[{}/{}] {}**", idx + 1, n_hovers, server_name),
|
.map(|h| Markdown::new(h, Arc::clone(&config_loader)));
|
||||||
config_loader.clone(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let body = Markdown::new(
|
let body = Markdown::new(
|
||||||
hover_contents_to_string(hover.contents),
|
hover_contents_to_string(hover.contents),
|
||||||
config_loader.clone(),
|
Arc::clone(&config_loader),
|
||||||
);
|
);
|
||||||
|
|
||||||
(header, body)
|
(header, body)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -54,10 +53,26 @@ impl Hover {
|
||||||
self.contents.len() > 1
|
self.contents.len() > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content(&self) -> &(Option<Markdown>, Markdown) {
|
fn content_markdown(&self) -> &(Option<Markdown>, Markdown) {
|
||||||
&self.contents[self.active_index]
|
&self.contents[self.active_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn content_string(&self) -> String {
|
||||||
|
self.contents
|
||||||
|
.iter()
|
||||||
|
.map(|(header, body)| {
|
||||||
|
let header: String = header
|
||||||
|
.iter()
|
||||||
|
.map(|header| header.contents.clone())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
format!("{}{}", header, body.contents)
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n\n---\n\n")
|
||||||
|
+ "\n"
|
||||||
|
}
|
||||||
|
|
||||||
fn set_index(&mut self, index: usize) {
|
fn set_index(&mut self, index: usize) {
|
||||||
assert!((0..self.contents.len()).contains(&index));
|
assert!((0..self.contents.len()).contains(&index));
|
||||||
self.active_index = index;
|
self.active_index = index;
|
||||||
|
@ -75,7 +90,7 @@ impl Component for Hover {
|
||||||
let margin = Margin::all(1);
|
let margin = Margin::all(1);
|
||||||
let area = area.inner(margin);
|
let area = area.inner(margin);
|
||||||
|
|
||||||
let (header, contents) = self.content();
|
let (header, contents) = self.content_markdown();
|
||||||
|
|
||||||
// show header and border only when more than one results
|
// show header and border only when more than one results
|
||||||
if let Some(header) = header {
|
if let Some(header) = header {
|
||||||
|
@ -110,7 +125,7 @@ impl Component for Hover {
|
||||||
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
||||||
let max_text_width = viewport.0.saturating_sub(PADDING_HORIZONTAL).clamp(10, 120);
|
let max_text_width = viewport.0.saturating_sub(PADDING_HORIZONTAL).clamp(10, 120);
|
||||||
|
|
||||||
let (header, contents) = self.content();
|
let (header, contents) = self.content_markdown();
|
||||||
|
|
||||||
let header_width = header
|
let header_width = header
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub fn highlighted_code_block<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Markdown {
|
pub struct Markdown {
|
||||||
contents: String,
|
pub contents: String,
|
||||||
|
|
||||||
config_loader: Arc<ArcSwap<syntax::Loader>>,
|
config_loader: Arc<ArcSwap<syntax::Loader>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1744,7 +1744,7 @@ impl Editor {
|
||||||
id
|
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);
|
let id = self.new_document(doc);
|
||||||
self.switch(id, action);
|
self.switch(id, action);
|
||||||
id
|
id
|
||||||
|
|
Loading…
Reference in New Issue