Run slash commands both on enter and on argument completion that requires it (#16283)

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2024-08-15 19:36:30 +03:00 committed by GitHub
parent 5a30e29848
commit c45adce2e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 61 additions and 34 deletions

View file

@ -2081,7 +2081,7 @@ impl ContextEditor {
}
editor.insert(&format!("/{name}"), cx);
if command.requires_argument() {
if command.accepts_arguments() {
editor.insert(" ", cx);
editor.show_completions(&ShowCompletions::default(), cx);
}
@ -2094,6 +2094,10 @@ impl ContextEditor {
}
pub fn confirm_command(&mut self, _: &ConfirmCommand, cx: &mut ViewContext<Self>) {
if self.editor.read(cx).has_active_completions_menu() {
return;
}
let selections = self.editor.read(cx).selections.disjoint_anchors();
let mut commands_by_range = HashMap::default();
let workspace = self.workspace.clone();

View file

@ -97,20 +97,25 @@ impl SlashCommandCompletionProvider {
let command = commands.command(&mat.string)?;
let mut new_text = mat.string.clone();
let requires_argument = command.requires_argument();
if requires_argument {
let accepts_arguments = command.accepts_arguments();
if requires_argument || accepts_arguments {
new_text.push(' ');
}
let confirm = editor.clone().zip(workspace.clone()).and_then(
|(editor, workspace)| {
(!requires_argument).then(|| {
let confirm =
editor
.clone()
.zip(workspace.clone())
.map(|(editor, workspace)| {
let command_name = mat.string.clone();
let command_range = command_range.clone();
let editor = editor.clone();
let workspace = workspace.clone();
Arc::new(
move |intent: CompletionIntent, cx: &mut WindowContext| {
if intent.is_complete() {
if !requires_argument
&& (!accepts_arguments || intent.is_complete())
{
editor
.update(cx, |editor, cx| {
editor.run_command(
@ -123,12 +128,13 @@ impl SlashCommandCompletionProvider {
);
})
.ok();
false
} else {
requires_argument || accepts_arguments
}
},
) as Arc<_>
})
},
);
});
Some(project::Completion {
old_range: name_range.clone(),
documentation: Some(Documentation::SingleLine(command.description())),
@ -136,7 +142,6 @@ impl SlashCommandCompletionProvider {
label: command.label(cx),
server_id: LanguageServerId(0),
lsp_completion: Default::default(),
show_new_completions_on_confirm: requires_argument,
confirm,
})
})
@ -175,7 +180,7 @@ impl SlashCommandCompletionProvider {
.await?
.into_iter()
.map(|new_argument| {
let confirm = if new_argument.run_command {
let confirm =
editor
.clone()
.zip(workspace.clone())
@ -192,7 +197,7 @@ impl SlashCommandCompletionProvider {
let command_range = command_range.clone();
let command_name = command_name.clone();
move |intent: CompletionIntent, cx: &mut WindowContext| {
if intent.is_complete() {
if new_argument.run_command || intent.is_complete() {
editor
.update(cx, |editor, cx| {
editor.run_command(
@ -205,13 +210,13 @@ impl SlashCommandCompletionProvider {
);
})
.ok();
false
} else {
!new_argument.run_command
}
}
}) as Arc<_>
})
} else {
None
};
});
let mut new_text = new_argument.new_text.clone();
if !new_argument.run_command {
@ -229,7 +234,6 @@ impl SlashCommandCompletionProvider {
documentation: None,
server_id: LanguageServerId(0),
lsp_completion: Default::default(),
show_new_completions_on_confirm: !new_argument.run_command,
confirm,
}
})

View file

@ -103,6 +103,10 @@ impl SlashCommand for DiagnosticsSlashCommand {
false
}
fn accepts_arguments(&self) -> bool {
true
}
fn complete_argument(
self: Arc<Self>,
arguments: &[String],

View file

@ -39,6 +39,10 @@ impl SlashCommand for TabSlashCommand {
false
}
fn accepts_arguments(&self) -> bool {
true
}
fn complete_argument(
self: Arc<Self>,
arguments: &[String],
@ -94,15 +98,16 @@ impl SlashCommand for TabSlashCommand {
})
});
let active_item_completion = active_item_path.as_deref().map(|active_item_path| {
let path_string = active_item_path.to_string_lossy().to_string();
ArgumentCompletion {
let active_item_completion = active_item_path
.as_deref()
.map(|active_item_path| active_item_path.to_string_lossy().to_string())
.filter(|path_string| !argument_set.contains(path_string))
.map(|path_string| ArgumentCompletion {
label: path_string.clone().into(),
new_text: path_string,
replace_previous_arguments: false,
run_command,
}
});
});
Ok(active_item_completion
.into_iter()

View file

@ -40,6 +40,10 @@ impl SlashCommand for TerminalSlashCommand {
false
}
fn accepts_arguments(&self) -> bool {
true
}
fn complete_argument(
self: Arc<Self>,
_arguments: &[String],

View file

@ -42,6 +42,9 @@ pub trait SlashCommand: 'static + Send + Sync {
cx: &mut WindowContext,
) -> Task<Result<Vec<ArgumentCompletion>>>;
fn requires_argument(&self) -> bool;
fn accepts_arguments(&self) -> bool {
self.requires_argument()
}
fn run(
self: Arc<Self>,
arguments: &[String],

View file

@ -314,7 +314,6 @@ impl MessageEditor {
server_id: LanguageServerId(0), // TODO: Make this optional or something?
lsp_completion: Default::default(), // TODO: Make this optional or something?
confirm: None,
show_new_completions_on_confirm: false,
}
})
.collect()

View file

@ -4379,11 +4379,11 @@ impl Editor {
this.refresh_inline_completion(true, cx);
});
if let Some(confirm) = completion.confirm.as_ref() {
(confirm)(intent, cx);
}
if completion.show_new_completions_on_confirm {
let show_new_completions_on_confirm = completion
.confirm
.as_ref()
.map_or(false, |confirm| confirm(intent, cx));
if show_new_completions_on_confirm {
self.show_completions(&ShowCompletions { trigger: None }, cx);
}
@ -11926,6 +11926,12 @@ impl Editor {
let bounds = self.last_bounds?;
Some(element::gutter_bounds(bounds, self.gutter_dimensions))
}
pub fn has_active_completions_menu(&self) -> bool {
self.context_menu.read().as_ref().map_or(false, |menu| {
menu.visible() && matches!(menu, ContextMenu::Completions(_))
})
}
}
fn hunks_for_selections(
@ -12141,7 +12147,6 @@ fn snippet_completions(
..Default::default()
},
confirm: None,
show_new_completions_on_confirm: false,
})
})
.collect()

View file

@ -450,9 +450,10 @@ pub struct Completion {
/// The raw completion provided by the language server.
pub lsp_completion: lsp::CompletionItem,
/// An optional callback to invoke when this completion is confirmed.
pub confirm: Option<Arc<dyn Send + Sync + Fn(CompletionIntent, &mut WindowContext)>>,
/// If true, the editor will show a new completion menu after this completion is confirmed.
pub show_new_completions_on_confirm: bool,
/// 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.
/// if no confirmation is provided or `false` is returned, the completion will be committed.
pub confirm: Option<Arc<dyn Send + Sync + Fn(CompletionIntent, &mut WindowContext) -> bool>>,
}
impl std::fmt::Debug for Completion {
@ -9128,7 +9129,6 @@ impl Project {
filter_range: Default::default(),
},
confirm: None,
show_new_completions_on_confirm: false,
},
false,
cx,
@ -10765,7 +10765,6 @@ async fn populate_labels_for_completions(
documentation,
lsp_completion,
confirm: None,
show_new_completions_on_confirm: false,
})
}
}