aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui/completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/ui/completion.rs')
-rw-r--r--helix-term/src/ui/completion.rs55
1 files changed, 47 insertions, 8 deletions
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index dd782d29..35afe81e 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -154,8 +154,19 @@ impl Completion {
);
doc.apply(&transaction, view.id);
- if let Some(additional_edits) = &item.additional_text_edits {
- // gopls uses this to add extra imports
+ // apply additional edits, mostly used to auto import unqualified types
+ let resolved_additional_text_edits = if item.additional_text_edits.is_some() {
+ None
+ } else {
+ Self::resolve_completion_item(doc, item.clone())
+ .and_then(|item| item.additional_text_edits)
+ };
+
+ if let Some(additional_edits) = item
+ .additional_text_edits
+ .as_ref()
+ .or_else(|| resolved_additional_text_edits.as_ref())
+ {
if !additional_edits.is_empty() {
let transaction = util::generate_transaction_from_edits(
doc.text(),
@@ -168,7 +179,7 @@ impl Completion {
}
};
});
- let popup = Popup::new(menu);
+ let popup = Popup::new("completion", menu);
let mut completion = Self {
popup,
start_offset,
@@ -181,6 +192,31 @@ impl Completion {
completion
}
+ fn resolve_completion_item(
+ doc: &Document,
+ completion_item: lsp::CompletionItem,
+ ) -> Option<CompletionItem> {
+ let language_server = doc.language_server()?;
+ let completion_resolve_provider = language_server
+ .capabilities()
+ .completion_provider
+ .as_ref()?
+ .resolve_provider;
+ if completion_resolve_provider != Some(true) {
+ return None;
+ }
+
+ let future = language_server.resolve_completion_item(completion_item);
+ let response = helix_lsp::block_on(future);
+ match response {
+ Ok(completion_item) => Some(completion_item),
+ Err(err) => {
+ log::error!("execute LSP command: {}", err);
+ None
+ }
+ }
+ }
+
pub fn recompute_filter(&mut self, editor: &Editor) {
// recompute menu based on matches
let menu = self.popup.contents_mut();
@@ -268,6 +304,9 @@ impl Component for Completion {
let cursor_pos = doc.selection(view.id).primary().cursor(text);
let coords = helix_core::visual_coords_at_pos(text, cursor_pos, doc.tab_width());
let cursor_pos = (coords.row - view.offset.row) as u16;
+
+ let markdown_ui =
+ |content, syn_loader| Markdown::new(content, syn_loader).style_group("completion");
let mut markdown_doc = match &option.documentation {
Some(lsp::Documentation::String(contents))
| Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
@@ -275,7 +314,7 @@ impl Component for Completion {
value: contents,
})) => {
// TODO: convert to wrapped text
- Markdown::new(
+ markdown_ui(
format!(
"```{}\n{}\n```\n{}",
language,
@@ -290,7 +329,7 @@ impl Component for Completion {
value: contents,
})) => {
// TODO: set language based on doc scope
- Markdown::new(
+ markdown_ui(
format!(
"```{}\n{}\n```\n{}",
language,
@@ -304,7 +343,7 @@ impl Component for Completion {
// TODO: copied from above
// TODO: set language based on doc scope
- Markdown::new(
+ markdown_ui(
format!(
"```{}\n{}\n```",
language,
@@ -328,8 +367,8 @@ impl Component for Completion {
let y = popup_y;
if let Some((rel_width, rel_height)) = markdown_doc.required_size((width, height)) {
- width = rel_width;
- height = rel_height;
+ width = rel_width.min(width);
+ height = rel_height.min(height);
}
Rect::new(x, y, width, height)
} else {