Skip to content

Conversation

@oxysoft
Copy link

@oxysoft oxysoft commented Dec 30, 2025

Summary

  • Adds with_auto_complete_menu(enable: bool) builder method to Reedline
  • When enabled, completion menu appears automatically as you type (like fish/IDEs)
  • Menu activates after 1+ character typed for any argument
  • Menu deactivates on space (waiting for next word)
  • First word (commands) never auto-completes
  • Bonus: adds CompletionHinter for inline gray-text suggestions

Motivation

Many users coming from fish shell expect completions to appear automatically without pressing Tab. This provides an opt-in way to enable that behavior.

Test plan

  • Build with cargo build
  • Tested in nushell with $env.config.completions.auto_menu = true
  • Verified menu appears for flags (ls -) and files (ls d)
  • Verified menu deactivates on space (ls --all )
  • Verified no scroll jank (menu only activates once per word)

Adds a new `with_auto_complete_menu(enable: bool)` builder method that
enables automatic completion menu display as you type, similar to
fish shell and modern IDEs.

When enabled:
- Completion menu appears after typing 1+ character for any argument
- Menu deactivates when typing just a space (waiting for next word)
- First word (commands) never auto-completes
- Prevents scroll jank by only activating menu once

Also adds CompletionHinter for inline gray-text suggestions from the
completer (fish-style), though this is separate from the menu feature.
oxysoft added a commit to oxysoft/nushell that referenced this pull request Dec 30, 2025
Adds `$env.config.completions.auto_menu` option (default: false) that
enables automatic completion menu display as you type.

When enabled:
- Completion menu appears after typing 1+ character for any argument
- Menu deactivates when typing just a space (waiting for next word)
- First word (commands) never auto-completes

Also switches hint provider from CwdAwareHinter to CompletionHinter
for fish-style inline suggestions based on completions rather than history.

Requires: nushell/reedline#993
@blindFS
Copy link
Contributor

blindFS commented Dec 30, 2025

A potentially stupid question: I don't see any ide_menu specific change, does this feature work for columnar completion menu?

Or, by IDE-style, you mean something unrelated to ide_menu?

Copy link
Member

@ysthakur ysthakur left a comment

Choose a reason for hiding this comment

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

Thanks for working on this!

I like the idea of a CompletionHinter, but it seems unrelated to the auto_complete_menu change and should be split into a separate PR

false
};

if let Some(menu) = self.menus.iter_mut().find(|m| m.name() == "completion_menu") {
Copy link
Member

Choose a reason for hiding this comment

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

Not a fan of the menu name being hardcoded here. I'd rather auto_complete_menu be an Option<String> holding the name of the menu to activate automatically. That way, users can choose which menu they want to always be active.

hide_hints: bool,

// Auto-show completion menu as you type (IDE/fish style)
auto_complete_menu: bool,
Copy link
Member

Choose a reason for hiding this comment

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

I think this name can confuse people. auto_complete_menu sounds like it's a menu for autocompletion, which all the menus are for. I'd prefer always_on_menu or something like that

hinter: Option<Box<dyn Hinter>>,
hide_hints: bool,

// Auto-show completion menu as you type (IDE/fish style)
Copy link
Member

Choose a reason for hiding this comment

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

You say "IDE" here, but looking at your code, it won't necessarily pick the IdeMenu, it'll pick whichever menu is named completion_menu. I think you just happened to see the IDE menu because that's what you have set in your Nushell config.

But also, let's not restrict this feature to the IDE menu. I prefer the columnar menu myself and would like to use that. So you can just remove the "(IDE/fish style)" bit from this comment

Choose a reason for hiding this comment

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

I think this comment just explain what the author means by "as you type", since in IDE like vscode completion is shown as you type.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this comment just explain what the author means by "as you type", since in IDE like vscode completion is shown as you type.

The thing is that "IDE" in reedline context has sort of special meaning.

Choose a reason for hiding this comment

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

Surely, but given that it appears next to fish I don't think it relates to this internal meaning. Nevermind it's just a comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Surely, but given that it appears next to fish I don't think it relates to this internal meaning. Nevermind it's just a comment.

I'd prefer precise comments.

// - Files/args: show after 1+ chars typed (not just space)
// - Commands (first word): don't auto-complete
let buffer = self.editor.line_buffer().get_buffer();
let should_show = if let Some(last_word_start) = buffer.rfind(' ') {
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer to make it so that the menu is always active, even if it's after a space. Let's leave it up to the menu and completer to decide whether to show anything.

I know this means users will see "NO RECORDS" all the time, but I'm sure we can work around that (or just let it be).

@blindFS thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit tricky.

On one side, there should be a configurable min-triggering-characters to lower the frequency.

However spaces are sometimes meaningful characters for fuzzy/substring matcher.

Seems to me a pure reedline solution won't be "smart" enough in that sense.

Copy link
Member

Choose a reason for hiding this comment

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

It's not just for the fuzzy/substring matchers, I'm thinking about a scenario where someone has a command foo that can only take one fruit as an argument: apple or banana. So if I type foo <TAB>, I want to see the options apple and banana, even if I haven't typed anything yet

And yeah, it's out of scope for Reedline to guess how a completer works. The only time that disabling the menu is probably safe is when the user hasn't typed anything at all yet (empty buffer)

Comment on lines +1263 to +1279
if !menu.is_active() {
// Only activate if not already active
menu.menu_event(MenuEvent::Activate(self.quick_completions));
menu.update_values(
&mut self.editor,
self.completer.as_mut(),
self.history.as_ref(),
);
} else {
// Menu already active, just send edit event to update
menu.menu_event(MenuEvent::Edit(self.quick_completions));
menu.update_values(
&mut self.editor,
self.completer.as_mut(),
self.history.as_ref(),
);
}
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick (pardon the indentation)

Suggested change
if !menu.is_active() {
// Only activate if not already active
menu.menu_event(MenuEvent::Activate(self.quick_completions));
menu.update_values(
&mut self.editor,
self.completer.as_mut(),
self.history.as_ref(),
);
} else {
// Menu already active, just send edit event to update
menu.menu_event(MenuEvent::Edit(self.quick_completions));
menu.update_values(
&mut self.editor,
self.completer.as_mut(),
self.history.as_ref(),
);
}
if !menu.is_active() {
// Only activate if not already active
menu.menu_event(MenuEvent::Activate(self.quick_completions));
} else {
menu.menu_event(MenuEvent::Edit(self.quick_completions));
}
menu.update_values(
&mut self.editor,
self.completer.as_mut(),
self.history.as_ref(),
);

@tobiasBora
Copy link

Thanks a lot for this feature that I've been waiting for to start adopting nushell given how much I like zfs_autocomplete in powerlevel10k. That being said, I'm a bit worried by this:

Menu activates after 1+ character typed for any argument
Menu deactivates on space (waiting for next word)

since I often really like seeing in zfs suggestions right after typing space. For instance just typing cd <space> proposes me all folders I can cd to, this way I don't need to remember the name of the folder to type.

Similarly for

First word (commands) never auto-completes

In zfs it also proposes autocompletion of the command as I type and it is really practical.

Would you consider putting these behind options to allow people like me to enable these options?

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.

4 participants