Skip to content

Add commandline complete to invoke nushell completions#17941

Draft
ian-h-chamberlain wants to merge 2 commits intonushell:mainfrom
ian-h-chamberlain:feature/commandline-complete
Draft

Add commandline complete to invoke nushell completions#17941
ian-h-chamberlain wants to merge 2 commits intonushell:mainfrom
ian-h-chamberlain:feature/commandline-complete

Conversation

@ian-h-chamberlain
Copy link
Copy Markdown
Contributor

Closes #16951

I'm keeping this as a draft for now, because there are a couple of things incomplete. It could be merged without them to keep this PR smaller, but would be nice to have at some point:

  • This line should probably not clone the world just to run this command:

    let completer = NuCompleter::new(Arc::new(engine_state.clone()), Arc::new(stack.clone()));

    It definitely is possible to make a NuCompleterRef<'_> type or something to avoid this, but it would be a bigger refactor and this PR already feels big, so maybe I should add that first?

  • Color conversion back from Style -> NuStyle is incomplete; the default LS_COLORS are Fixed(_) so they don't convert cleanly back to strings yet. This means file completions won't roundtrip properly when passed into a completer, yet.

Questions:

  • Am I using spans appropriately here? Particularly converting between reedline span + nushell span, I'm not sure what the "source" for these completions really should be (or if it needs to be offset according to the cursor position).

  • adding impl TryIntoValue for SuggestionKind could be a breaking change, and I'm not sure it's the right semantics either... should I mvoe this into a custom wrapper in the command itself or nu-cli instead?

  • bikeshed on the name for --detailed(-d) (mirroring describe)? This felt more descriptive than --long (from ps, ls) to me, not sure if there are other builtins with similar flags for examples

Release notes summary - What our users need to know

TODO

Tasks after submitting

#[test]
fn commandline_test_complete_flags() -> TestResult {
run_test(
"def cmd [ --flag: string, --switch(-s) ] {}\n\
Copy link
Copy Markdown
Contributor Author

@ian-h-chamberlain ian-h-chamberlain Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nice to have some tests that demonstrate usage as a custom completer, or arg: path, arg: glob examples, but maybe that kind of test is better suited to crates/nu-cli/tests/completions/mod.rs.

This feature probably could use a spot in the custom_completers cookbook if+when it's merged too

Signature::build("commandline complete")
.input_output_types(vec![
(Type::Nothing, Type::List(Box::new(Type::String))),
(Type::String, Type::List(Box::new(Type::String))),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, I need to add the record type as a possible output since I added that with -d

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Mar 31, 2026

This sounds very cool!
/cc @ysthakur

@Juhan280
Copy link
Copy Markdown
Contributor

There should be dedicated flags for the default completions like commandline complete --directory or --path or something similar

"detailed",
"Output completions as records, in the format expected from custom completers.",
Some('d'),
)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧵 Adding comment here for thread discussion

@Juhan280 said:

There should be dedicated flags for the default completions like commandline complete --directory or --path or something similar

That sounds like a nice API... I'm not sure exactly how it would work, since ultimately this command just takes a plain string and passes that along to the REPL completer, which ultimately does a bunch of parsing + delegation to get the actual completion values based on the cursor position.

I'd like to avoid duplicating all the implementation between the main completer and this command, so that any future enhancements to completions come "for free" in this command... what if we had something like this where any valid type annotation was allowed?

let s = "..."

# full REPL-style completion
$s | commandline complete

# same thing, but using current commandline contents
commandline complete

let type = 'directory' # or e.g. 'cell-path', 'glob', etc.

commandline complete --type=$type # still based on current commandline contents?

'./' | commandline complete --type=$type

# maybe this can be used to get all completions of $type, ignoring current commandline:
'' | commandline complete --type=$type

This would basically be sugar around the completion example like

def paths [p:path] {}
'paths ' | commandline complete # for empty input
# or 
$'paths ($in)' | commandline complete

Although I'll have to see if there's a nice way to set this up that isn't too hacky...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, experimenting with this a bit more, it seems directory, path, glob are really the main useful type annotations that could be accepted here, so maybe it's simpler to just manually add flags for a few common cases.

For more advanced uses (like external commands, partial cell paths, variables, flags), it's still possible to construct a string to get the desired output, so I guess any convenience flags like this probably don't need to be comprehensive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable directly invoking the default path completions

3 participants