Only complete appropriate arguments for typed commands. (#5966)
This commit is contained in:
parent
d479adfdc6
commit
27aa919f1c
1 changed files with 154 additions and 84 deletions
|
@ -5,7 +5,7 @@ use crate::job::Job;
|
|||
|
||||
use super::*;
|
||||
|
||||
use helix_core::encoding;
|
||||
use helix_core::{encoding, shellwords::Shellwords};
|
||||
use helix_view::document::DEFAULT_LANGUAGE_NAME;
|
||||
use helix_view::editor::{Action, CloseError, ConfigEvent};
|
||||
use serde_json::Value;
|
||||
|
@ -18,7 +18,49 @@ pub struct TypableCommand {
|
|||
pub doc: &'static str,
|
||||
// params, flags, helper, completer
|
||||
pub fun: fn(&mut compositor::Context, &[Cow<str>], PromptEvent) -> anyhow::Result<()>,
|
||||
pub completer: Option<Completer>,
|
||||
/// What completion methods, if any, does this command have?
|
||||
pub signature: CommandSignature,
|
||||
}
|
||||
|
||||
impl TypableCommand {
|
||||
fn completer_for_argument_number(&self, n: usize) -> &Completer {
|
||||
match self.signature.positional_args.get(n) {
|
||||
Some(completer) => completer,
|
||||
_ => &self.signature.var_args,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CommandSignature {
|
||||
// Arguments with specific completion methods based on their position.
|
||||
positional_args: &'static [Completer],
|
||||
|
||||
// All remaining arguments will use this completion method, if set.
|
||||
var_args: Completer,
|
||||
}
|
||||
|
||||
impl CommandSignature {
|
||||
const fn none() -> Self {
|
||||
Self {
|
||||
positional_args: &[],
|
||||
var_args: completers::none,
|
||||
}
|
||||
}
|
||||
|
||||
const fn positional(completers: &'static [Completer]) -> Self {
|
||||
Self {
|
||||
positional_args: completers,
|
||||
var_args: completers::none,
|
||||
}
|
||||
}
|
||||
|
||||
const fn all(completer: Completer) -> Self {
|
||||
Self {
|
||||
positional_args: &[],
|
||||
var_args: completer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn quit(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
|
||||
|
@ -2113,112 +2155,114 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
|
|||
aliases: &["q"],
|
||||
doc: "Close the current view.",
|
||||
fun: quit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "quit!",
|
||||
aliases: &["q!"],
|
||||
doc: "Force close the current view, ignoring unsaved changes.",
|
||||
fun: force_quit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "open",
|
||||
aliases: &["o"],
|
||||
doc: "Open a file from disk into the current view.",
|
||||
fun: open,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::all(completers::filename),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close",
|
||||
aliases: &["bc", "bclose"],
|
||||
doc: "Close the current buffer.",
|
||||
fun: buffer_close,
|
||||
completer: Some(completers::buffer),
|
||||
signature: CommandSignature::all(completers::buffer),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close!",
|
||||
aliases: &["bc!", "bclose!"],
|
||||
doc: "Close the current buffer forcefully, ignoring unsaved changes.",
|
||||
fun: force_buffer_close,
|
||||
completer: Some(completers::buffer),
|
||||
signature: CommandSignature::all(completers::buffer)
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close-others",
|
||||
aliases: &["bco", "bcloseother"],
|
||||
doc: "Close all buffers but the currently focused one.",
|
||||
fun: buffer_close_others,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close-others!",
|
||||
aliases: &["bco!", "bcloseother!"],
|
||||
doc: "Force close all buffers but the currently focused one.",
|
||||
fun: force_buffer_close_others,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close-all",
|
||||
aliases: &["bca", "bcloseall"],
|
||||
doc: "Close all buffers without quitting.",
|
||||
fun: buffer_close_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-close-all!",
|
||||
aliases: &["bca!", "bcloseall!"],
|
||||
doc: "Force close all buffers ignoring unsaved changes without quitting.",
|
||||
fun: force_buffer_close_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-next",
|
||||
aliases: &["bn", "bnext"],
|
||||
doc: "Goto next buffer.",
|
||||
fun: buffer_next,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "buffer-previous",
|
||||
aliases: &["bp", "bprev"],
|
||||
doc: "Goto previous buffer.",
|
||||
fun: buffer_previous,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write",
|
||||
aliases: &["w"],
|
||||
doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
|
||||
fun: write,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::positional(&[completers::filename]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write!",
|
||||
aliases: &["w!"],
|
||||
doc: "Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt)",
|
||||
fun: force_write,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::positional(&[completers::filename]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "new",
|
||||
aliases: &["n"],
|
||||
doc: "Create a new scratch buffer.",
|
||||
fun: new_file,
|
||||
completer: Some(completers::filename),
|
||||
// TODO: This seems to complete with a filename, but doesn't use that filename to
|
||||
// set the path of the newly created buffer.
|
||||
signature: CommandSignature::positional(&[completers::filename]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "format",
|
||||
aliases: &["fmt"],
|
||||
doc: "Format the file using the LSP formatter.",
|
||||
fun: format,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "indent-style",
|
||||
aliases: &[],
|
||||
doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
|
||||
fun: set_indent_style,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "line-ending",
|
||||
|
@ -2228,231 +2272,231 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
|
|||
#[cfg(feature = "unicode-lines")]
|
||||
doc: "Set the document's default line ending. Options: crlf, lf, cr, ff, nel.",
|
||||
fun: set_line_ending,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "earlier",
|
||||
aliases: &["ear"],
|
||||
doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
|
||||
fun: earlier,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "later",
|
||||
aliases: &["lat"],
|
||||
doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
|
||||
fun: later,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write-quit",
|
||||
aliases: &["wq", "x"],
|
||||
doc: "Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)",
|
||||
fun: write_quit,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::positional(&[completers::filename]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write-quit!",
|
||||
aliases: &["wq!", "x!"],
|
||||
doc: "Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
|
||||
fun: force_write_quit,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::positional(&[completers::filename]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write-all",
|
||||
aliases: &["wa"],
|
||||
doc: "Write changes from all buffers to disk.",
|
||||
fun: write_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write-quit-all",
|
||||
aliases: &["wqa", "xa"],
|
||||
doc: "Write changes from all buffers to disk and close all views.",
|
||||
fun: write_all_quit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "write-quit-all!",
|
||||
aliases: &["wqa!", "xa!"],
|
||||
doc: "Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).",
|
||||
fun: force_write_all_quit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "quit-all",
|
||||
aliases: &["qa"],
|
||||
doc: "Close all views.",
|
||||
fun: quit_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "quit-all!",
|
||||
aliases: &["qa!"],
|
||||
doc: "Force close all views ignoring unsaved changes.",
|
||||
fun: force_quit_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "cquit",
|
||||
aliases: &["cq"],
|
||||
doc: "Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2).",
|
||||
fun: cquit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "cquit!",
|
||||
aliases: &["cq!"],
|
||||
doc: "Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2).",
|
||||
fun: force_cquit,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "theme",
|
||||
aliases: &[],
|
||||
doc: "Change the editor theme (show current theme if no name specified).",
|
||||
fun: theme,
|
||||
completer: Some(completers::theme),
|
||||
signature: CommandSignature::positional(&[completers::theme]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "clipboard-yank",
|
||||
aliases: &[],
|
||||
doc: "Yank main selection into system clipboard.",
|
||||
fun: yank_main_selection_to_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "clipboard-yank-join",
|
||||
aliases: &[],
|
||||
doc: "Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline.", // FIXME: current UI can't display long doc.
|
||||
fun: yank_joined_to_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "primary-clipboard-yank",
|
||||
aliases: &[],
|
||||
doc: "Yank main selection into system primary clipboard.",
|
||||
fun: yank_main_selection_to_primary_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "primary-clipboard-yank-join",
|
||||
aliases: &[],
|
||||
doc: "Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline.", // FIXME: current UI can't display long doc.
|
||||
fun: yank_joined_to_primary_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "clipboard-paste-after",
|
||||
aliases: &[],
|
||||
doc: "Paste system clipboard after selections.",
|
||||
fun: paste_clipboard_after,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "clipboard-paste-before",
|
||||
aliases: &[],
|
||||
doc: "Paste system clipboard before selections.",
|
||||
fun: paste_clipboard_before,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "clipboard-paste-replace",
|
||||
aliases: &[],
|
||||
doc: "Replace selections with content of system clipboard.",
|
||||
fun: replace_selections_with_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "primary-clipboard-paste-after",
|
||||
aliases: &[],
|
||||
doc: "Paste primary clipboard after selections.",
|
||||
fun: paste_primary_clipboard_after,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "primary-clipboard-paste-before",
|
||||
aliases: &[],
|
||||
doc: "Paste primary clipboard before selections.",
|
||||
fun: paste_primary_clipboard_before,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "primary-clipboard-paste-replace",
|
||||
aliases: &[],
|
||||
doc: "Replace selections with content of system primary clipboard.",
|
||||
fun: replace_selections_with_primary_clipboard,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "show-clipboard-provider",
|
||||
aliases: &[],
|
||||
doc: "Show clipboard provider name in status bar.",
|
||||
fun: show_clipboard_provider,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "change-current-directory",
|
||||
aliases: &["cd"],
|
||||
doc: "Change the current working directory.",
|
||||
fun: change_current_directory,
|
||||
completer: Some(completers::directory),
|
||||
signature: CommandSignature::positional(&[completers::directory]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "show-directory",
|
||||
aliases: &["pwd"],
|
||||
doc: "Show the current working directory.",
|
||||
fun: show_current_directory,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "encoding",
|
||||
aliases: &[],
|
||||
doc: "Set encoding. Based on `https://encoding.spec.whatwg.org`.",
|
||||
fun: set_encoding,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "character-info",
|
||||
aliases: &["char"],
|
||||
doc: "Get info about the character under the primary cursor.",
|
||||
fun: get_character_info,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "reload",
|
||||
aliases: &[],
|
||||
doc: "Discard changes and reload from the source file.",
|
||||
fun: reload,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "reload-all",
|
||||
aliases: &[],
|
||||
doc: "Discard changes and reload all documents from the source files.",
|
||||
fun: reload_all,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "update",
|
||||
aliases: &[],
|
||||
doc: "Write changes only if the file has been modified.",
|
||||
fun: update,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "lsp-workspace-command",
|
||||
aliases: &[],
|
||||
doc: "Open workspace command picker",
|
||||
fun: lsp_workspace_command,
|
||||
completer: Some(completers::lsp_workspace_command),
|
||||
signature: CommandSignature::positional(&[completers::lsp_workspace_command]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "lsp-restart",
|
||||
aliases: &[],
|
||||
doc: "Restarts the Language Server that is in use by the current doc",
|
||||
fun: lsp_restart,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "lsp-stop",
|
||||
|
@ -2466,182 +2510,183 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
|
|||
aliases: &[],
|
||||
doc: "Display tree sitter scopes, primarily for theming and development.",
|
||||
fun: tree_sitter_scopes,
|
||||
completer: None,
|
||||
},
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "debug-start",
|
||||
aliases: &["dbg"],
|
||||
doc: "Start a debug session from a given template with given parameters.",
|
||||
fun: debug_start,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "debug-remote",
|
||||
aliases: &["dbg-tcp"],
|
||||
doc: "Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.",
|
||||
fun: debug_remote,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "debug-eval",
|
||||
aliases: &[],
|
||||
doc: "Evaluate expression in current debug context.",
|
||||
fun: debug_eval,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "vsplit",
|
||||
aliases: &["vs"],
|
||||
doc: "Open the file in a vertical split.",
|
||||
fun: vsplit,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::all(completers::filename)
|
||||
},
|
||||
TypableCommand {
|
||||
name: "vsplit-new",
|
||||
aliases: &["vnew"],
|
||||
doc: "Open a scratch buffer in a vertical split.",
|
||||
fun: vsplit_new,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "hsplit",
|
||||
aliases: &["hs", "sp"],
|
||||
doc: "Open the file in a horizontal split.",
|
||||
fun: hsplit,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::all(completers::filename)
|
||||
},
|
||||
TypableCommand {
|
||||
name: "hsplit-new",
|
||||
aliases: &["hnew"],
|
||||
doc: "Open a scratch buffer in a horizontal split.",
|
||||
fun: hsplit_new,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "tutor",
|
||||
aliases: &[],
|
||||
doc: "Open the tutorial.",
|
||||
fun: tutor,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "goto",
|
||||
aliases: &["g"],
|
||||
doc: "Goto line number.",
|
||||
fun: goto_line_number,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "set-language",
|
||||
aliases: &["lang"],
|
||||
doc: "Set the language of current buffer (show current language if no value specified).",
|
||||
fun: language,
|
||||
completer: Some(completers::language),
|
||||
signature: CommandSignature::positional(&[completers::language]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "set-option",
|
||||
aliases: &["set"],
|
||||
doc: "Set a config option at runtime.\nFor example to disable smart case search, use `:set search.smart-case false`.",
|
||||
fun: set_option,
|
||||
completer: Some(completers::setting),
|
||||
// TODO: Add support for completion of the options value(s), when appropriate.
|
||||
signature: CommandSignature::positional(&[completers::setting]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "toggle-option",
|
||||
aliases: &["toggle"],
|
||||
doc: "Toggle a boolean config option at runtime.\nFor example to toggle smart case search, use `:toggle search.smart-case`.",
|
||||
fun: toggle_option,
|
||||
completer: Some(completers::setting),
|
||||
signature: CommandSignature::positional(&[completers::setting]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "get-option",
|
||||
aliases: &["get"],
|
||||
doc: "Get the current value of a config option.",
|
||||
fun: get_option,
|
||||
completer: Some(completers::setting),
|
||||
signature: CommandSignature::positional(&[completers::setting]),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "sort",
|
||||
aliases: &[],
|
||||
doc: "Sort ranges in selection.",
|
||||
fun: sort,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "rsort",
|
||||
aliases: &[],
|
||||
doc: "Sort ranges in selection in reverse order.",
|
||||
fun: sort_reverse,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "reflow",
|
||||
aliases: &[],
|
||||
doc: "Hard-wrap the current selection of lines to a given width.",
|
||||
fun: reflow,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "tree-sitter-subtree",
|
||||
aliases: &["ts-subtree"],
|
||||
doc: "Display tree sitter subtree under cursor, primarily for debugging queries.",
|
||||
fun: tree_sitter_subtree,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "config-reload",
|
||||
aliases: &[],
|
||||
doc: "Refresh user config.",
|
||||
fun: refresh_config,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "config-open",
|
||||
aliases: &[],
|
||||
doc: "Open the user config.toml file.",
|
||||
fun: open_config,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "log-open",
|
||||
aliases: &[],
|
||||
doc: "Open the helix log file.",
|
||||
fun: open_log,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "insert-output",
|
||||
aliases: &[],
|
||||
doc: "Run shell command, inserting output before each selection.",
|
||||
fun: insert_output,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "append-output",
|
||||
aliases: &[],
|
||||
doc: "Run shell command, appending output after each selection.",
|
||||
fun: append_output,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "pipe",
|
||||
aliases: &[],
|
||||
doc: "Pipe each selection to the shell command.",
|
||||
fun: pipe,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "pipe-to",
|
||||
aliases: &[],
|
||||
doc: "Pipe each selection to the shell command, ignoring output.",
|
||||
fun: pipe_to,
|
||||
completer: None,
|
||||
signature: CommandSignature::none(),
|
||||
},
|
||||
TypableCommand {
|
||||
name: "run-shell-command",
|
||||
aliases: &["sh"],
|
||||
doc: "Run a shell command",
|
||||
fun: run_shell_command,
|
||||
completer: Some(completers::filename),
|
||||
signature: CommandSignature::all(completers::filename)
|
||||
},
|
||||
TypableCommand {
|
||||
name: "reset-diff-change",
|
||||
|
@ -2665,8 +2710,6 @@ pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableComma
|
|||
|
||||
#[allow(clippy::unnecessary_unwrap)]
|
||||
pub(super) fn command_mode(cx: &mut Context) {
|
||||
use shellwords::Shellwords;
|
||||
|
||||
let mut prompt = Prompt::new(
|
||||
":".into(),
|
||||
Some(':'),
|
||||
|
@ -2705,10 +2748,11 @@ pub(super) fn command_mode(cx: &mut Context) {
|
|||
)
|
||||
};
|
||||
|
||||
if let Some(typed::TypableCommand {
|
||||
completer: Some(completer),
|
||||
..
|
||||
}) = typed::TYPABLE_COMMAND_MAP.get(&words[0] as &str)
|
||||
let argument_number = argument_number_of(&shellwords);
|
||||
|
||||
if let Some(completer) = TYPABLE_COMMAND_MAP
|
||||
.get(&words[0] as &str)
|
||||
.map(|tc| tc.completer_for_argument_number(argument_number))
|
||||
{
|
||||
completer(editor, part)
|
||||
.into_iter()
|
||||
|
@ -2773,3 +2817,29 @@ pub(super) fn command_mode(cx: &mut Context) {
|
|||
prompt.recalculate_completion(cx.editor);
|
||||
cx.push_layer(Box::new(prompt));
|
||||
}
|
||||
|
||||
fn argument_number_of(shellwords: &Shellwords) -> usize {
|
||||
if shellwords.ends_with_whitespace() {
|
||||
shellwords.words().len().saturating_sub(1)
|
||||
} else {
|
||||
shellwords.words().len().saturating_sub(2)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_argument_number_of() {
|
||||
let cases = vec![
|
||||
("set-option", 0),
|
||||
("set-option ", 0),
|
||||
("set-option a", 0),
|
||||
("set-option asdf", 0),
|
||||
("set-option asdf ", 1),
|
||||
("set-option asdf xyz", 1),
|
||||
("set-option asdf xyz abc", 2),
|
||||
("set-option asdf xyz abc ", 3),
|
||||
];
|
||||
|
||||
for case in cases {
|
||||
assert_eq!(case.1, argument_number_of(&Shellwords::from(case.0)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue