Add support for insert_text_mode
of a completion (#28171)
I wanted this for CONL (https://conl.dev )'s nascent langauge server, and it seems like most of the support was already wired up on the LSP side, so this surfaces it into the editor. Release Notes: - Added support for the `insert_text_mode` field of completions from the language server protocol.
This commit is contained in:
parent
5a7222edc5
commit
a577a72f69
10 changed files with 91 additions and 4 deletions
|
@ -112,6 +112,7 @@ impl ContextPickerCompletionProvider {
|
|||
icon_path: Some(mode.icon().path().into()),
|
||||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
insert_text_mode: None,
|
||||
// This ensures that when a user accepts this completion, the
|
||||
// completion menu will still be shown after "@category " is
|
||||
// inserted
|
||||
|
@ -163,6 +164,7 @@ impl ContextPickerCompletionProvider {
|
|||
new_text,
|
||||
label: CodeLabel::plain(thread_entry.summary.to_string(), None),
|
||||
documentation: None,
|
||||
insert_text_mode: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
icon_path: Some(icon_for_completion.path().into()),
|
||||
confirm: Some(confirm_completion_callback(
|
||||
|
@ -209,6 +211,7 @@ impl ContextPickerCompletionProvider {
|
|||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
icon_path: Some(IconName::Globe.path().into()),
|
||||
insert_text_mode: None,
|
||||
confirm: Some(confirm_completion_callback(
|
||||
IconName::Globe.path().into(),
|
||||
url_to_fetch.clone(),
|
||||
|
@ -290,6 +293,7 @@ impl ContextPickerCompletionProvider {
|
|||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
icon_path: Some(completion_icon_path),
|
||||
insert_text_mode: None,
|
||||
confirm: Some(confirm_completion_callback(
|
||||
crease_icon_path,
|
||||
file_name,
|
||||
|
@ -352,6 +356,7 @@ impl ContextPickerCompletionProvider {
|
|||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
icon_path: Some(IconName::Code.path().into()),
|
||||
insert_text_mode: None,
|
||||
confirm: Some(confirm_completion_callback(
|
||||
IconName::Code.path().into(),
|
||||
symbol.name.clone().into(),
|
||||
|
|
|
@ -127,6 +127,7 @@ impl SlashCommandCompletionProvider {
|
|||
new_text,
|
||||
label: command.label(cx),
|
||||
icon_path: None,
|
||||
insert_text_mode: None,
|
||||
confirm,
|
||||
source: CompletionSource::Custom,
|
||||
})
|
||||
|
@ -228,6 +229,7 @@ impl SlashCommandCompletionProvider {
|
|||
new_text,
|
||||
documentation: None,
|
||||
confirm,
|
||||
insert_text_mode: None,
|
||||
source: CompletionSource::Custom,
|
||||
}
|
||||
})
|
||||
|
|
|
@ -315,6 +315,7 @@ impl MessageEditor {
|
|||
icon_path: None,
|
||||
confirm: None,
|
||||
documentation: None,
|
||||
insert_text_mode: None,
|
||||
source: CompletionSource::Custom,
|
||||
}
|
||||
})
|
||||
|
|
|
@ -367,6 +367,7 @@ impl ConsoleQueryBarCompletionProvider {
|
|||
documentation: None,
|
||||
confirm: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
insert_text_mode: None,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
|
@ -409,6 +410,7 @@ impl ConsoleQueryBarCompletionProvider {
|
|||
documentation: None,
|
||||
confirm: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
insert_text_mode: None,
|
||||
})
|
||||
.collect(),
|
||||
))
|
||||
|
|
|
@ -240,6 +240,7 @@ impl CompletionsMenu {
|
|||
icon_path: None,
|
||||
documentation: None,
|
||||
confirm: None,
|
||||
insert_text_mode: None,
|
||||
source: CompletionSource::Custom,
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -136,7 +136,7 @@ use task::{ResolvedTask, TaskTemplate, TaskVariables};
|
|||
pub use lsp::CompletionContext;
|
||||
use lsp::{
|
||||
CodeActionKind, CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity,
|
||||
InsertTextFormat, LanguageServerId, LanguageServerName,
|
||||
InsertTextFormat, InsertTextMode, LanguageServerId, LanguageServerName,
|
||||
};
|
||||
|
||||
use language::BufferSnapshot;
|
||||
|
@ -4442,6 +4442,7 @@ impl Editor {
|
|||
word_range,
|
||||
resolved: false,
|
||||
},
|
||||
insert_text_mode: Some(InsertTextMode::AS_IS),
|
||||
confirm: None,
|
||||
}));
|
||||
|
||||
|
@ -4687,7 +4688,13 @@ impl Editor {
|
|||
} else {
|
||||
this.buffer.update(cx, |buffer, cx| {
|
||||
let edits = ranges.iter().map(|range| (range.clone(), text));
|
||||
buffer.edit(edits, this.autoindent_mode.clone(), cx);
|
||||
let auto_indent = if completion.insert_text_mode == Some(InsertTextMode::AS_IS)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
this.autoindent_mode.clone()
|
||||
};
|
||||
buffer.edit(edits, auto_indent, cx);
|
||||
});
|
||||
}
|
||||
for (buffer, edits) in linked_edits {
|
||||
|
@ -18637,6 +18644,7 @@ fn snippet_completions(
|
|||
.description
|
||||
.clone()
|
||||
.map(|description| CompletionDocumentation::SingleLine(description.into())),
|
||||
insert_text_mode: None,
|
||||
confirm: None,
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10235,6 +10235,62 @@ async fn test_completion_sort(cx: &mut TestAppContext) {
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_as_is_completions(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
completion_provider: Some(lsp::CompletionOptions {
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
cx.lsp
|
||||
.set_request_handler::<lsp::request::Completion, _, _>(move |_, _| async move {
|
||||
Ok(Some(lsp::CompletionResponse::Array(vec![
|
||||
lsp::CompletionItem {
|
||||
label: "unsafe".into(),
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range {
|
||||
start: lsp::Position {
|
||||
line: 1,
|
||||
character: 2,
|
||||
},
|
||||
end: lsp::Position {
|
||||
line: 1,
|
||||
character: 3,
|
||||
},
|
||||
},
|
||||
new_text: "unsafe".to_string(),
|
||||
})),
|
||||
insert_text_mode: Some(lsp::InsertTextMode::AS_IS),
|
||||
..Default::default()
|
||||
},
|
||||
])))
|
||||
});
|
||||
cx.set_state("fn a() {}\n nˇ");
|
||||
cx.executor().run_until_parked();
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.show_completions(
|
||||
&ShowCompletions {
|
||||
trigger: Some("\n".into()),
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.confirm_completion(&Default::default(), window, cx)
|
||||
});
|
||||
cx.executor().run_until_parked();
|
||||
cx.assert_editor_state("fn a() {}\n unsafeˇ");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_no_duplicated_completion_requests(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
|
|
@ -704,8 +704,15 @@ impl LanguageServer {
|
|||
}),
|
||||
insert_replace_support: Some(true),
|
||||
label_details_support: Some(true),
|
||||
insert_text_mode_support: Some(InsertTextModeSupport {
|
||||
value_set: vec![
|
||||
InsertTextMode::AS_IS,
|
||||
InsertTextMode::ADJUST_INDENTATION,
|
||||
],
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION),
|
||||
completion_list: Some(CompletionListCapability {
|
||||
item_defaults: Some(vec![
|
||||
"commitCharacters".to_owned(),
|
||||
|
|
|
@ -8053,6 +8053,7 @@ impl LspStore {
|
|||
runs: Default::default(),
|
||||
filter_range: Default::default(),
|
||||
},
|
||||
insert_text_mode: None,
|
||||
icon_path: None,
|
||||
confirm: None,
|
||||
}]))),
|
||||
|
@ -9342,6 +9343,7 @@ async fn populate_labels_for_completions(
|
|||
documentation,
|
||||
old_range: completion.old_range,
|
||||
new_text: completion.new_text,
|
||||
insert_text_mode: lsp_completion.insert_text_mode,
|
||||
source: completion.source,
|
||||
icon_path: None,
|
||||
confirm: None,
|
||||
|
@ -9356,6 +9358,7 @@ async fn populate_labels_for_completions(
|
|||
old_range: completion.old_range,
|
||||
new_text: completion.new_text,
|
||||
source: completion.source,
|
||||
insert_text_mode: None,
|
||||
icon_path: None,
|
||||
confirm: None,
|
||||
});
|
||||
|
|
|
@ -68,8 +68,8 @@ use language::{
|
|||
language_settings::InlayHintKind, proto::split_operations,
|
||||
};
|
||||
use lsp::{
|
||||
CodeActionKind, CompletionContext, CompletionItemKind, DocumentHighlightKind, LanguageServerId,
|
||||
LanguageServerName, MessageActionItem,
|
||||
CodeActionKind, CompletionContext, CompletionItemKind, DocumentHighlightKind, InsertTextMode,
|
||||
LanguageServerId, LanguageServerName, MessageActionItem,
|
||||
};
|
||||
use lsp_command::*;
|
||||
use lsp_store::{CompletionDocumentation, LspFormatTarget, OpenLspBufferHandle};
|
||||
|
@ -392,6 +392,8 @@ pub struct Completion {
|
|||
pub source: CompletionSource,
|
||||
/// A path to an icon for this completion that is shown in the menu.
|
||||
pub icon_path: Option<SharedString>,
|
||||
/// Whether to adjust indentation (the default) or not.
|
||||
pub insert_text_mode: Option<InsertTextMode>,
|
||||
/// An optional callback to invoke when this completion is confirmed.
|
||||
/// Returns, whether new completions should be retriggered after the current one.
|
||||
/// If `true` is returned, the editor will show a new completion menu after this completion is confirmed.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue