@@ -5,7 +5,7 @@ use crate::job::Job;
6use super::*;
6use super::*;
8−use helix_core::encoding;
8+use helix_core::{encoding, shellwords::Shellwords};
9use helix_view::document::DEFAULT_LANGUAGE_NAME;
9use helix_view::document::DEFAULT_LANGUAGE_NAME;
10use helix_view::editor::{Action, CloseError, ConfigEvent};
10use helix_view::editor::{Action, CloseError, ConfigEvent};
11use serde_json::Value;
11use serde_json::Value;
@@ -18,7 +18,49 @@ pub struct TypableCommand {
18 pub doc: &'static str,
18 pub doc: &'static str,
19 // params, flags, helper, completer
19 // params, flags, helper, completer
20 pub fun: fn(&mut compositor::Context, &[Cow<str>], PromptEvent) -> anyhow::Result<()>,
20 pub fun: fn(&mut compositor::Context, &[Cow<str>], PromptEvent) -> anyhow::Result<()>,
21+ /// What completion methods, if any, does this command have?
22+ pub signature: CommandSignature,
26+ fn completer_for_argument_number(&self, n: usize) -> &Completer {
27+ match self.signature.positional_args.get(n) {
28+ Some(completer) => completer,
29+ _ => &self.signature.var_args,
35+pub struct CommandSignature {
36+ // Arguments with specific completion methods based on their position.
37+ positional_args: &'static [Completer],
39+ // All remaining arguments will use this completion method, if set.
43+impl CommandSignature {
44+ const fn none() -> Self {
46+ positional_args: &[],
47+ var_args: completers::none,
51+ const fn positional(completers: &'static [Completer]) -> Self {
53+ positional_args: completers,
54+ var_args: completers::none,
21− pub completer: Option<Completer>,
58+ const fn all(completer: Completer) -> Self {
60+ positional_args: &[],
24fn quit(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
66fn quit(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
@@ -2113,112 +2155,114 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
2113 aliases: &["q"],
2155 aliases: &["q"],
2114 doc: "Close the current view.",
2156 doc: "Close the current view.",
2115 fun: quit,
2157 fun: quit,
2116− completer: None,
2158+ signature: CommandSignature::none(),
2118 TypableCommand {
2160 TypableCommand {
2119 name: "quit!",
2161 name: "quit!",
2120 aliases: &["q!"],
2162 aliases: &["q!"],
2121 doc: "Force close the current view, ignoring unsaved changes.",
2163 doc: "Force close the current view, ignoring unsaved changes.",
2122 fun: force_quit,
2164 fun: force_quit,
2123− completer: None,
2165+ signature: CommandSignature::none(),
2125 TypableCommand {
2167 TypableCommand {
2126 name: "open",
2168 name: "open",
2127 aliases: &["o"],
2169 aliases: &["o"],
2128 doc: "Open a file from disk into the current view.",
2170 doc: "Open a file from disk into the current view.",
2129 fun: open,
2171 fun: open,
2130− completer: Some(completers::filename),
2172+ signature: CommandSignature::all(completers::filename),
2132 TypableCommand {
2174 TypableCommand {
2133 name: "buffer-close",
2175 name: "buffer-close",
2134 aliases: &["bc", "bclose"],
2176 aliases: &["bc", "bclose"],
2135 doc: "Close the current buffer.",
2177 doc: "Close the current buffer.",
2136 fun: buffer_close,
2178 fun: buffer_close,
2137− completer: Some(completers::buffer),
2179+ signature: CommandSignature::all(completers::buffer),
2139 TypableCommand {
2181 TypableCommand {
2140 name: "buffer-close!",
2182 name: "buffer-close!",
2141 aliases: &["bc!", "bclose!"],
2183 aliases: &["bc!", "bclose!"],
2142 doc: "Close the current buffer forcefully, ignoring unsaved changes.",
2184 doc: "Close the current buffer forcefully, ignoring unsaved changes.",
2143 fun: force_buffer_close,
2185 fun: force_buffer_close,
2144− completer: Some(completers::buffer),
2186+ signature: CommandSignature::all(completers::buffer)
2146 TypableCommand {
2188 TypableCommand {
2147 name: "buffer-close-others",
2189 name: "buffer-close-others",
2148 aliases: &["bco", "bcloseother"],
2190 aliases: &["bco", "bcloseother"],
2149 doc: "Close all buffers but the currently focused one.",
2191 doc: "Close all buffers but the currently focused one.",
2150 fun: buffer_close_others,
2192 fun: buffer_close_others,
2151− completer: None,
2193+ signature: CommandSignature::none(),
2153 TypableCommand {
2195 TypableCommand {
2154 name: "buffer-close-others!",
2196 name: "buffer-close-others!",
2155 aliases: &["bco!", "bcloseother!"],
2197 aliases: &["bco!", "bcloseother!"],
2156 doc: "Force close all buffers but the currently focused one.",
2198 doc: "Force close all buffers but the currently focused one.",
2157 fun: force_buffer_close_others,
2199 fun: force_buffer_close_others,
2158− completer: None,
2200+ signature: CommandSignature::none(),
2160 TypableCommand {
2202 TypableCommand {
2161 name: "buffer-close-all",
2203 name: "buffer-close-all",
2162 aliases: &["bca", "bcloseall"],
2204 aliases: &["bca", "bcloseall"],
2163 doc: "Close all buffers without quitting.",
2205 doc: "Close all buffers without quitting.",
2164 fun: buffer_close_all,
2206 fun: buffer_close_all,
2165− completer: None,
2207+ signature: CommandSignature::none(),
2167 TypableCommand {
2209 TypableCommand {
2168 name: "buffer-close-all!",
2210 name: "buffer-close-all!",
2169 aliases: &["bca!", "bcloseall!"],
2211 aliases: &["bca!", "bcloseall!"],
2170 doc: "Force close all buffers ignoring unsaved changes without quitting.",
2212 doc: "Force close all buffers ignoring unsaved changes without quitting.",
2171 fun: force_buffer_close_all,
2213 fun: force_buffer_close_all,
2172− completer: None,
2214+ signature: CommandSignature::none(),
2174 TypableCommand {
2216 TypableCommand {
2175 name: "buffer-next",
2217 name: "buffer-next",
2176 aliases: &["bn", "bnext"],
2218 aliases: &["bn", "bnext"],
2177 doc: "Goto next buffer.",
2219 doc: "Goto next buffer.",
2178 fun: buffer_next,
2220 fun: buffer_next,
2179− completer: None,
2221+ signature: CommandSignature::none(),
2181 TypableCommand {
2223 TypableCommand {
2182 name: "buffer-previous",
2224 name: "buffer-previous",
2183 aliases: &["bp", "bprev"],
2225 aliases: &["bp", "bprev"],
2184 doc: "Goto previous buffer.",
2226 doc: "Goto previous buffer.",
2185 fun: buffer_previous,
2227 fun: buffer_previous,
2186− completer: None,
2228+ signature: CommandSignature::none(),
2188 TypableCommand {
2230 TypableCommand {
2189 name: "write",
2231 name: "write",
2190 aliases: &["w"],
2232 aliases: &["w"],
2191 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
2233 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
2192 fun: write,
2234 fun: write,
2193− completer: Some(completers::filename),
2235+ signature: CommandSignature::positional(&[completers::filename]),
2195 TypableCommand {
2237 TypableCommand {
2196 name: "write!",
2238 name: "write!",
2197 aliases: &["w!"],
2239 aliases: &["w!"],
2198 doc: "Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt)",
2240 doc: "Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt)",
2199 fun: force_write,
2241 fun: force_write,
2200− completer: Some(completers::filename),
2242+ signature: CommandSignature::positional(&[completers::filename]),
2202 TypableCommand {
2244 TypableCommand {
2203 name: "new",
2245 name: "new",
2204 aliases: &["n"],
2246 aliases: &["n"],
2205 doc: "Create a new scratch buffer.",
2247 doc: "Create a new scratch buffer.",
2206 fun: new_file,
2248 fun: new_file,
2249+ // TODO: This seems to complete with a filename, but doesn't use that filename to
2250+ // set the path of the newly created buffer.
2207− completer: Some(completers::filename),
2251+ signature: CommandSignature::positional(&[completers::filename]),
2209 TypableCommand {
2253 TypableCommand {
2210 name: "format",
2254 name: "format",
2211 aliases: &["fmt"],
2255 aliases: &["fmt"],
2212 doc: "Format the file using the LSP formatter.",
2256 doc: "Format the file using the LSP formatter.",
2213 fun: format,
2257 fun: format,
2214− completer: None,
2258+ signature: CommandSignature::none(),
2216 TypableCommand {
2260 TypableCommand {
2217 name: "indent-style",
2261 name: "indent-style",
2218 aliases: &[],
2262 aliases: &[],
2219 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
2263 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
2220 fun: set_indent_style,
2264 fun: set_indent_style,
2221− completer: None,
2265+ signature: CommandSignature::none(),
2223 TypableCommand {
2267 TypableCommand {
2224 name: "line-ending",
2268 name: "line-ending",
@@ -2228,231 +2272,231 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
2228 #[cfg(feature = "unicode-lines")]
2272 #[cfg(feature = "unicode-lines")]
2229 doc: "Set the document's default line ending. Options: crlf, lf, cr, ff, nel.",
2273 doc: "Set the document's default line ending. Options: crlf, lf, cr, ff, nel.",
2230 fun: set_line_ending,
2274 fun: set_line_ending,
2231− completer: None,
2275+ signature: CommandSignature::none(),
2233 TypableCommand {
2277 TypableCommand {
2234 name: "earlier",
2278 name: "earlier",
2235 aliases: &["ear"],
2279 aliases: &["ear"],
2236 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
2280 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
2237 fun: earlier,
2281 fun: earlier,
2238− completer: None,
2282+ signature: CommandSignature::none(),
2240 TypableCommand {
2284 TypableCommand {
2241 name: "later",
2285 name: "later",
2242 aliases: &["lat"],
2286 aliases: &["lat"],
2243 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
2287 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
2244 fun: later,
2288 fun: later,
2245− completer: None,
2289+ signature: CommandSignature::none(),
2247 TypableCommand {
2291 TypableCommand {
2248 name: "write-quit",
2292 name: "write-quit",
2249 aliases: &["wq", "x"],
2293 aliases: &["wq", "x"],
2250 doc: "Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)",
2294 doc: "Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)",
2251 fun: write_quit,
2295 fun: write_quit,
2252− completer: Some(completers::filename),
2296+ signature: CommandSignature::positional(&[completers::filename]),
2254 TypableCommand {
2298 TypableCommand {
2255 name: "write-quit!",
2299 name: "write-quit!",
2256 aliases: &["wq!", "x!"],
2300 aliases: &["wq!", "x!"],
2257 doc: "Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
2301 doc: "Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
2258 fun: force_write_quit,
2302 fun: force_write_quit,
2259− completer: Some(completers::filename),
2303+ signature: CommandSignature::positional(&[completers::filename]),
2261 TypableCommand {
2305 TypableCommand {
2262 name: "write-all",
2306 name: "write-all",
2263 aliases: &["wa"],
2307 aliases: &["wa"],
2264 doc: "Write changes from all buffers to disk.",
2308 doc: "Write changes from all buffers to disk.",
2265 fun: write_all,
2309 fun: write_all,
2266− completer: None,
2310+ signature: CommandSignature::none(),
2268 TypableCommand {
2312 TypableCommand {
2269 name: "write-quit-all",
2313 name: "write-quit-all",
2270 aliases: &["wqa", "xa"],
2314 aliases: &["wqa", "xa"],
2271 doc: "Write changes from all buffers to disk and close all views.",
2315 doc: "Write changes from all buffers to disk and close all views.",
2272 fun: write_all_quit,
2316 fun: write_all_quit,
2273− completer: None,
2317+ signature: CommandSignature::none(),
2275 TypableCommand {
2319 TypableCommand {
2276 name: "write-quit-all!",
2320 name: "write-quit-all!",
2277 aliases: &["wqa!", "xa!"],
2321 aliases: &["wqa!", "xa!"],
2278 doc: "Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).",
2322 doc: "Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).",
2279 fun: force_write_all_quit,
2323 fun: force_write_all_quit,
2280− completer: None,
2324+ signature: CommandSignature::none(),
2282 TypableCommand {
2326 TypableCommand {
2283 name: "quit-all",
2327 name: "quit-all",
2284 aliases: &["qa"],
2328 aliases: &["qa"],
2285 doc: "Close all views.",
2329 doc: "Close all views.",
2286 fun: quit_all,
2330 fun: quit_all,
2287− completer: None,
2331+ signature: CommandSignature::none(),
2289 TypableCommand {
2333 TypableCommand {
2290 name: "quit-all!",
2334 name: "quit-all!",
2291 aliases: &["qa!"],
2335 aliases: &["qa!"],
2292 doc: "Force close all views ignoring unsaved changes.",
2336 doc: "Force close all views ignoring unsaved changes.",
2293 fun: force_quit_all,
2337 fun: force_quit_all,
2294− completer: None,
2338+ signature: CommandSignature::none(),
2296 TypableCommand {
2340 TypableCommand {
2297 name: "cquit",
2341 name: "cquit",
2298 aliases: &["cq"],
2342 aliases: &["cq"],
2299 doc: "Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2).",
2343 doc: "Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2).",
2300 fun: cquit,
2344 fun: cquit,
2301− completer: None,
2345+ signature: CommandSignature::none(),
2303 TypableCommand {
2347 TypableCommand {
2304 name: "cquit!",
2348 name: "cquit!",
2305 aliases: &["cq!"],
2349 aliases: &["cq!"],
2306 doc: "Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2).",
2350 doc: "Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2).",
2307 fun: force_cquit,
2351 fun: force_cquit,
2308− completer: None,
2352+ signature: CommandSignature::none(),
2310 TypableCommand {
2354 TypableCommand {
2311 name: "theme",
2355 name: "theme",
2312 aliases: &[],
2356 aliases: &[],
2313 doc: "Change the editor theme (show current theme if no name specified).",
2357 doc: "Change the editor theme (show current theme if no name specified).",
2314 fun: theme,
2358 fun: theme,
2315− completer: Some(completers::theme),
2359+ signature: CommandSignature::positional(&[completers::theme]),
2317 TypableCommand {
2361 TypableCommand {
2318 name: "clipboard-yank",
2362 name: "clipboard-yank",
2319 aliases: &[],
2363 aliases: &[],
2320 doc: "Yank main selection into system clipboard.",
2364 doc: "Yank main selection into system clipboard.",
2321 fun: yank_main_selection_to_clipboard,
2365 fun: yank_main_selection_to_clipboard,
2322− completer: None,
2366+ signature: CommandSignature::none(),
2324 TypableCommand {
2368 TypableCommand {
2325 name: "clipboard-yank-join",
2369 name: "clipboard-yank-join",
2326 aliases: &[],
2370 aliases: &[],
2327 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.
2371 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.
2328 fun: yank_joined_to_clipboard,
2372 fun: yank_joined_to_clipboard,
2329− completer: None,
2373+ signature: CommandSignature::none(),
2331 TypableCommand {
2375 TypableCommand {
2332 name: "primary-clipboard-yank",
2376 name: "primary-clipboard-yank",
2333 aliases: &[],
2377 aliases: &[],
2334 doc: "Yank main selection into system primary clipboard.",
2378 doc: "Yank main selection into system primary clipboard.",
2335 fun: yank_main_selection_to_primary_clipboard,
2379 fun: yank_main_selection_to_primary_clipboard,
2336− completer: None,
2380+ signature: CommandSignature::none(),
2338 TypableCommand {
2382 TypableCommand {
2339 name: "primary-clipboard-yank-join",
2383 name: "primary-clipboard-yank-join",
2340 aliases: &[],
2384 aliases: &[],
2341 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.
2385 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.
2342 fun: yank_joined_to_primary_clipboard,
2386 fun: yank_joined_to_primary_clipboard,
2343− completer: None,
2387+ signature: CommandSignature::none(),
2345 TypableCommand {
2389 TypableCommand {
2346 name: "clipboard-paste-after",
2390 name: "clipboard-paste-after",
2347 aliases: &[],
2391 aliases: &[],
2348 doc: "Paste system clipboard after selections.",
2392 doc: "Paste system clipboard after selections.",
2349 fun: paste_clipboard_after,
2393 fun: paste_clipboard_after,
2350− completer: None,
2394+ signature: CommandSignature::none(),
2352 TypableCommand {
2396 TypableCommand {
2353 name: "clipboard-paste-before",
2397 name: "clipboard-paste-before",
2354 aliases: &[],
2398 aliases: &[],
2355 doc: "Paste system clipboard before selections.",
2399 doc: "Paste system clipboard before selections.",
2356 fun: paste_clipboard_before,
2400 fun: paste_clipboard_before,
2357− completer: None,
2401+ signature: CommandSignature::none(),
2359 TypableCommand {
2403 TypableCommand {
2360 name: "clipboard-paste-replace",
2404 name: "clipboard-paste-replace",
2361 aliases: &[],
2405 aliases: &[],
2362 doc: "Replace selections with content of system clipboard.",
2406 doc: "Replace selections with content of system clipboard.",
2363 fun: replace_selections_with_clipboard,
2407 fun: replace_selections_with_clipboard,
2364− completer: None,
2408+ signature: CommandSignature::none(),
2366 TypableCommand {
2410 TypableCommand {
2367 name: "primary-clipboard-paste-after",
2411 name: "primary-clipboard-paste-after",
2368 aliases: &[],
2412 aliases: &[],
2369 doc: "Paste primary clipboard after selections.",
2413 doc: "Paste primary clipboard after selections.",
2370 fun: paste_primary_clipboard_after,
2414 fun: paste_primary_clipboard_after,
2371− completer: None,
2415+ signature: CommandSignature::none(),
2373 TypableCommand {
2417 TypableCommand {
2374 name: "primary-clipboard-paste-before",
2418 name: "primary-clipboard-paste-before",
2375 aliases: &[],
2419 aliases: &[],
2376 doc: "Paste primary clipboard before selections.",
2420 doc: "Paste primary clipboard before selections.",
2377 fun: paste_primary_clipboard_before,
2421 fun: paste_primary_clipboard_before,
2378− completer: None,
2422+ signature: CommandSignature::none(),
2380 TypableCommand {
2424 TypableCommand {
2381 name: "primary-clipboard-paste-replace",
2425 name: "primary-clipboard-paste-replace",
2382 aliases: &[],
2426 aliases: &[],
2383 doc: "Replace selections with content of system primary clipboard.",
2427 doc: "Replace selections with content of system primary clipboard.",
2384 fun: replace_selections_with_primary_clipboard,
2428 fun: replace_selections_with_primary_clipboard,
2385− completer: None,
2429+ signature: CommandSignature::none(),
2387 TypableCommand {
2431 TypableCommand {
2388 name: "show-clipboard-provider",
2432 name: "show-clipboard-provider",
2389 aliases: &[],
2433 aliases: &[],
2390 doc: "Show clipboard provider name in status bar.",
2434 doc: "Show clipboard provider name in status bar.",
2391 fun: show_clipboard_provider,
2435 fun: show_clipboard_provider,
2392− completer: None,
2436+ signature: CommandSignature::none(),
2394 TypableCommand {
2438 TypableCommand {
2395 name: "change-current-directory",
2439 name: "change-current-directory",
2396 aliases: &["cd"],
2440 aliases: &["cd"],
2397 doc: "Change the current working directory.",
2441 doc: "Change the current working directory.",
2398 fun: change_current_directory,
2442 fun: change_current_directory,
2399− completer: Some(completers::directory),
2443+ signature: CommandSignature::positional(&[completers::directory]),
2401 TypableCommand {
2445 TypableCommand {
2402 name: "show-directory",
2446 name: "show-directory",
2403 aliases: &["pwd"],
2447 aliases: &["pwd"],
2404 doc: "Show the current working directory.",
2448 doc: "Show the current working directory.",
2405 fun: show_current_directory,
2449 fun: show_current_directory,
2406− completer: None,
2450+ signature: CommandSignature::none(),
2408 TypableCommand {
2452 TypableCommand {
2409 name: "encoding",
2453 name: "encoding",
2410 aliases: &[],
2454 aliases: &[],
2411 doc: "Set encoding. Based on `https://encoding.spec.whatwg.org`.",
2455 doc: "Set encoding. Based on `https://encoding.spec.whatwg.org`.",
2412 fun: set_encoding,
2456 fun: set_encoding,
2413− completer: None,
2457+ signature: CommandSignature::none(),
2415 TypableCommand {
2459 TypableCommand {
2416 name: "character-info",
2460 name: "character-info",
2417 aliases: &["char"],
2461 aliases: &["char"],
2418 doc: "Get info about the character under the primary cursor.",
2462 doc: "Get info about the character under the primary cursor.",
2419 fun: get_character_info,
2463 fun: get_character_info,
2420− completer: None,
2464+ signature: CommandSignature::none(),
2422 TypableCommand {
2466 TypableCommand {
2423 name: "reload",
2467 name: "reload",
2424 aliases: &[],
2468 aliases: &[],
2425 doc: "Discard changes and reload from the source file.",
2469 doc: "Discard changes and reload from the source file.",
2426 fun: reload,
2470 fun: reload,
2427− completer: None,
2471+ signature: CommandSignature::none(),
2429 TypableCommand {
2473 TypableCommand {
2430 name: "reload-all",
2474 name: "reload-all",
2431 aliases: &[],
2475 aliases: &[],
2432 doc: "Discard changes and reload all documents from the source files.",
2476 doc: "Discard changes and reload all documents from the source files.",
2433 fun: reload_all,
2477 fun: reload_all,
2434− completer: None,
2478+ signature: CommandSignature::none(),
2436 TypableCommand {
2480 TypableCommand {
2437 name: "update",
2481 name: "update",
2438 aliases: &[],
2482 aliases: &[],
2439 doc: "Write changes only if the file has been modified.",
2483 doc: "Write changes only if the file has been modified.",
2440 fun: update,
2484 fun: update,
2441− completer: None,
2485+ signature: CommandSignature::none(),
2443 TypableCommand {
2487 TypableCommand {
2444 name: "lsp-workspace-command",
2488 name: "lsp-workspace-command",
2445 aliases: &[],
2489 aliases: &[],
2446 doc: "Open workspace command picker",
2490 doc: "Open workspace command picker",
2447 fun: lsp_workspace_command,
2491 fun: lsp_workspace_command,
2448− completer: Some(completers::lsp_workspace_command),
2492+ signature: CommandSignature::positional(&[completers::lsp_workspace_command]),
2450 TypableCommand {
2494 TypableCommand {
2451 name: "lsp-restart",
2495 name: "lsp-restart",
2452 aliases: &[],
2496 aliases: &[],
2453 doc: "Restarts the Language Server that is in use by the current doc",
2497 doc: "Restarts the Language Server that is in use by the current doc",
2454 fun: lsp_restart,
2498 fun: lsp_restart,
2455− completer: None,
2499+ signature: CommandSignature::none(),
2457 TypableCommand {
2501 TypableCommand {
2458 name: "lsp-stop",
2502 name: "lsp-stop",
@@ -2466,182 +2510,183 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
2466 aliases: &[],
2510 aliases: &[],
2467 doc: "Display tree sitter scopes, primarily for theming and development.",
2511 doc: "Display tree sitter scopes, primarily for theming and development.",
2468 fun: tree_sitter_scopes,
2512 fun: tree_sitter_scopes,
2469− completer: None,
2513+ signature: CommandSignature::none(),
2471 TypableCommand {
2515 TypableCommand {
2472 name: "debug-start",
2516 name: "debug-start",
2473 aliases: &["dbg"],
2517 aliases: &["dbg"],
2474 doc: "Start a debug session from a given template with given parameters.",
2518 doc: "Start a debug session from a given template with given parameters.",
2475 fun: debug_start,
2519 fun: debug_start,
2476− completer: None,
2520+ signature: CommandSignature::none(),
2478 TypableCommand {
2522 TypableCommand {
2479 name: "debug-remote",
2523 name: "debug-remote",
2480 aliases: &["dbg-tcp"],
2524 aliases: &["dbg-tcp"],
2481 doc: "Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.",
2525 doc: "Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.",
2482 fun: debug_remote,
2526 fun: debug_remote,
2483− completer: None,
2527+ signature: CommandSignature::none(),
2485 TypableCommand {
2529 TypableCommand {
2486 name: "debug-eval",
2530 name: "debug-eval",
2487 aliases: &[],
2531 aliases: &[],
2488 doc: "Evaluate expression in current debug context.",
2532 doc: "Evaluate expression in current debug context.",
2489 fun: debug_eval,
2533 fun: debug_eval,
2490− completer: None,
2534+ signature: CommandSignature::none(),
2492 TypableCommand {
2536 TypableCommand {
2493 name: "vsplit",
2537 name: "vsplit",
2494 aliases: &["vs"],
2538 aliases: &["vs"],
2495 doc: "Open the file in a vertical split.",
2539 doc: "Open the file in a vertical split.",
2496 fun: vsplit,
2540 fun: vsplit,
2497− completer: Some(completers::filename),
2541+ signature: CommandSignature::all(completers::filename)
2499 TypableCommand {
2543 TypableCommand {
2500 name: "vsplit-new",
2544 name: "vsplit-new",
2501 aliases: &["vnew"],
2545 aliases: &["vnew"],
2502 doc: "Open a scratch buffer in a vertical split.",
2546 doc: "Open a scratch buffer in a vertical split.",
2503 fun: vsplit_new,
2547 fun: vsplit_new,
2504− completer: None,
2548+ signature: CommandSignature::none(),
2506 TypableCommand {
2550 TypableCommand {
2507 name: "hsplit",
2551 name: "hsplit",
2508 aliases: &["hs", "sp"],
2552 aliases: &["hs", "sp"],
2509 doc: "Open the file in a horizontal split.",
2553 doc: "Open the file in a horizontal split.",
2510 fun: hsplit,
2554 fun: hsplit,
2511− completer: Some(completers::filename),
2555+ signature: CommandSignature::all(completers::filename)
2513 TypableCommand {
2557 TypableCommand {
2514 name: "hsplit-new",
2558 name: "hsplit-new",
2515 aliases: &["hnew"],
2559 aliases: &["hnew"],
2516 doc: "Open a scratch buffer in a horizontal split.",
2560 doc: "Open a scratch buffer in a horizontal split.",
2517 fun: hsplit_new,
2561 fun: hsplit_new,
2518− completer: None,
2562+ signature: CommandSignature::none(),
2520 TypableCommand {
2564 TypableCommand {
2521 name: "tutor",
2565 name: "tutor",
2522 aliases: &[],
2566 aliases: &[],
2523 doc: "Open the tutorial.",
2567 doc: "Open the tutorial.",
2524 fun: tutor,
2568 fun: tutor,
2525− completer: None,
2569+ signature: CommandSignature::none(),
2527 TypableCommand {
2571 TypableCommand {
2528 name: "goto",
2572 name: "goto",
2529 aliases: &["g"],
2573 aliases: &["g"],
2530 doc: "Goto line number.",
2574 doc: "Goto line number.",
2531 fun: goto_line_number,
2575 fun: goto_line_number,
2532− completer: None,
2576+ signature: CommandSignature::none(),
2534 TypableCommand {
2578 TypableCommand {
2535 name: "set-language",
2579 name: "set-language",
2536 aliases: &["lang"],
2580 aliases: &["lang"],
2537 doc: "Set the language of current buffer (show current language if no value specified).",
2581 doc: "Set the language of current buffer (show current language if no value specified).",
2538 fun: language,
2582 fun: language,
2539− completer: Some(completers::language),
2583+ signature: CommandSignature::positional(&[completers::language]),
2541 TypableCommand {
2585 TypableCommand {
2542 name: "set-option",
2586 name: "set-option",
2543 aliases: &["set"],
2587 aliases: &["set"],
2544 doc: "Set a config option at runtime.\nFor example to disable smart case search, use `:set search.smart-case false`.",
2588 doc: "Set a config option at runtime.\nFor example to disable smart case search, use `:set search.smart-case false`.",
2545 fun: set_option,
2589 fun: set_option,
2590+ // TODO: Add support for completion of the options value(s), when appropriate.
2546− completer: Some(completers::setting),
2591+ signature: CommandSignature::positional(&[completers::setting]),
2548 TypableCommand {
2593 TypableCommand {
2549 name: "toggle-option",
2594 name: "toggle-option",
2550 aliases: &["toggle"],
2595 aliases: &["toggle"],
2551 doc: "Toggle a boolean config option at runtime.\nFor example to toggle smart case search, use `:toggle search.smart-case`.",
2596 doc: "Toggle a boolean config option at runtime.\nFor example to toggle smart case search, use `:toggle search.smart-case`.",
2552 fun: toggle_option,
2597 fun: toggle_option,
2553− completer: Some(completers::setting),
2598+ signature: CommandSignature::positional(&[completers::setting]),
2555 TypableCommand {
2600 TypableCommand {
2556 name: "get-option",
2601 name: "get-option",
2557 aliases: &["get"],
2602 aliases: &["get"],
2558 doc: "Get the current value of a config option.",
2603 doc: "Get the current value of a config option.",
2559 fun: get_option,
2604 fun: get_option,
2560− completer: Some(completers::setting),
2605+ signature: CommandSignature::positional(&[completers::setting]),
2562 TypableCommand {
2607 TypableCommand {
2563 name: "sort",
2608 name: "sort",
2564 aliases: &[],
2609 aliases: &[],
2565 doc: "Sort ranges in selection.",
2610 doc: "Sort ranges in selection.",
2566 fun: sort,
2611 fun: sort,
2567− completer: None,
2612+ signature: CommandSignature::none(),
2569 TypableCommand {
2614 TypableCommand {
2570 name: "rsort",
2615 name: "rsort",
2571 aliases: &[],
2616 aliases: &[],
2572 doc: "Sort ranges in selection in reverse order.",
2617 doc: "Sort ranges in selection in reverse order.",
2573 fun: sort_reverse,
2618 fun: sort_reverse,
2574− completer: None,
2619+ signature: CommandSignature::none(),
2576 TypableCommand {
2621 TypableCommand {
2577 name: "reflow",
2622 name: "reflow",
2578 aliases: &[],
2623 aliases: &[],
2579 doc: "Hard-wrap the current selection of lines to a given width.",
2624 doc: "Hard-wrap the current selection of lines to a given width.",
2580 fun: reflow,
2625 fun: reflow,
2581− completer: None,
2626+ signature: CommandSignature::none(),
2583 TypableCommand {
2628 TypableCommand {
2584 name: "tree-sitter-subtree",
2629 name: "tree-sitter-subtree",
2585 aliases: &["ts-subtree"],
2630 aliases: &["ts-subtree"],
2586 doc: "Display tree sitter subtree under cursor, primarily for debugging queries.",
2631 doc: "Display tree sitter subtree under cursor, primarily for debugging queries.",
2587 fun: tree_sitter_subtree,
2632 fun: tree_sitter_subtree,
2588− completer: None,
2633+ signature: CommandSignature::none(),
2590 TypableCommand {
2635 TypableCommand {
2591 name: "config-reload",
2636 name: "config-reload",
2592 aliases: &[],
2637 aliases: &[],
2593 doc: "Refresh user config.",
2638 doc: "Refresh user config.",
2594 fun: refresh_config,
2639 fun: refresh_config,
2595− completer: None,
2640+ signature: CommandSignature::none(),
2597 TypableCommand {
2642 TypableCommand {
2598 name: "config-open",
2643 name: "config-open",
2599 aliases: &[],
2644 aliases: &[],
2600 doc: "Open the user config.toml file.",
2645 doc: "Open the user config.toml file.",
2601 fun: open_config,
2646 fun: open_config,
2602− completer: None,
2647+ signature: CommandSignature::none(),
2604 TypableCommand {
2649 TypableCommand {
2605 name: "log-open",
2650 name: "log-open",
2606 aliases: &[],
2651 aliases: &[],
2607 doc: "Open the helix log file.",
2652 doc: "Open the helix log file.",
2608 fun: open_log,
2653 fun: open_log,
2609− completer: None,
2654+ signature: CommandSignature::none(),
2611 TypableCommand {
2656 TypableCommand {
2612 name: "insert-output",
2657 name: "insert-output",
2613 aliases: &[],
2658 aliases: &[],
2614 doc: "Run shell command, inserting output before each selection.",
2659 doc: "Run shell command, inserting output before each selection.",
2615 fun: insert_output,
2660 fun: insert_output,
2616− completer: None,
2661+ signature: CommandSignature::none(),
2618 TypableCommand {
2663 TypableCommand {
2619 name: "append-output",
2664 name: "append-output",
2620 aliases: &[],
2665 aliases: &[],
2621 doc: "Run shell command, appending output after each selection.",
2666 doc: "Run shell command, appending output after each selection.",
2622 fun: append_output,
2667 fun: append_output,
2623− completer: None,
2668+ signature: CommandSignature::none(),
2625 TypableCommand {
2670 TypableCommand {
2626 name: "pipe",
2671 name: "pipe",
2627 aliases: &[],
2672 aliases: &[],
2628 doc: "Pipe each selection to the shell command.",
2673 doc: "Pipe each selection to the shell command.",
2629 fun: pipe,
2674 fun: pipe,
2630− completer: None,
2675+ signature: CommandSignature::none(),
2632 TypableCommand {
2677 TypableCommand {
2633 name: "pipe-to",
2678 name: "pipe-to",
2634 aliases: &[],
2679 aliases: &[],
2635 doc: "Pipe each selection to the shell command, ignoring output.",
2680 doc: "Pipe each selection to the shell command, ignoring output.",
2636 fun: pipe_to,
2681 fun: pipe_to,
2637− completer: None,
2682+ signature: CommandSignature::none(),
2639 TypableCommand {
2684 TypableCommand {
2640 name: "run-shell-command",
2685 name: "run-shell-command",
2641 aliases: &["sh"],
2686 aliases: &["sh"],
2642 doc: "Run a shell command",
2687 doc: "Run a shell command",
2643 fun: run_shell_command,
2688 fun: run_shell_command,
2644− completer: Some(completers::filename),
2689+ signature: CommandSignature::all(completers::filename)
2646 TypableCommand {
2691 TypableCommand {
2647 name: "reset-diff-change",
2692 name: "reset-diff-change",
@@ -2665,8 +2710,6 @@ pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableComma
2666#[allow(clippy::unnecessary_unwrap)]
2711#[allow(clippy::unnecessary_unwrap)]
2667pub(super) fn command_mode(cx: &mut Context) {
2712pub(super) fn command_mode(cx: &mut Context) {
2668− use shellwords::Shellwords;
2670 let mut prompt = Prompt::new(
2713 let mut prompt = Prompt::new(
2671 ":".into(),
2714 ":".into(),
2672 Some(':'),
2715 Some(':'),
@@ -2705,10 +2748,11 @@ pub(super) fn command_mode(cx: &mut Context) {
2708− if let Some(typed::TypableCommand {
2751+ let argument_number = argument_number_of(&shellwords);
2709− completer: Some(completer),
2752+
2710− ..
2753+ if let Some(completer) = TYPABLE_COMMAND_MAP
2711− }) = typed::TYPABLE_COMMAND_MAP.get(&words[0] as &str)
2754+ .get(&words[0] as &str)
2755+ .map(|tc| tc.completer_for_argument_number(argument_number))
2713 completer(editor, part)
2757 completer(editor, part)
2714 .into_iter()
2758 .into_iter()
@@ -2773,3 +2817,29 @@ pub(super) fn command_mode(cx: &mut Context) {
2773 prompt.recalculate_completion(cx.editor);
2817 prompt.recalculate_completion(cx.editor);
2774 cx.push_layer(Box::new(prompt));
2818 cx.push_layer(Box::new(prompt));
2821+fn argument_number_of(shellwords: &Shellwords) -> usize {
2822+ if shellwords.ends_with_whitespace() {
2823+ shellwords.words().len().saturating_sub(1)
2825+ shellwords.words().len().saturating_sub(2)
2830+fn test_argument_number_of() {
2833+ ("set-option ", 0),
2834+ ("set-option a", 0),
2835+ ("set-option asdf", 0),
2836+ ("set-option asdf ", 1),
2837+ ("set-option asdf xyz", 1),
2838+ ("set-option asdf xyz abc", 2),
2839+ ("set-option asdf xyz abc ", 3),
2842+ for case in cases {
2843+ assert_eq!(case.1, argument_number_of(&Shellwords::from(case.0)));