shell: nushell integration scripts#4630
Conversation
Fixes some path issues. There are still some other things to fix
Pass~[1] is a command line password storage utility. Possible queries are deduced from the file GPG hierarchy under ~/.password-store. [1]: https://www.passwordstore.org/
Not sure why it doesn't work in this context, but if those are not removed, the completion process doesn't substitute the selected value to '**'.
fix typo shell/key-bindinds.nu → shell/key-bindings.nu
There was a problem hiding this comment.
Pull request overview
Adds first-class Nushell integration to fzf, including keybindings, **<TAB> fuzzy completion via Nushell’s external completer mechanism, installation/uninstallation support, and CI/test coverage to prevent regressions.
Changes:
- Add
fzf --nushellflag that prints Nushell integration scripts (keybindings + completion) - Add Nushell install/uninstall handling (autoload
fzf.nu) and update docs - Add Nushell integration tests + Linux CI dependency install for nushell
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
main.go |
Embeds and prints Nushell integration scripts when --nushell is used |
src/options.go |
Adds --nushell option parsing and Options.Nushell flag |
shell/key-bindings.nu |
Implements CTRL-T / CTRL-R / ALT-C bindings for Nushell |
shell/completion.nu |
Implements ** completion via Nushell external completer + command-specific completers |
install |
Adds Nushell to supported shells and generates autoload fzf.nu |
uninstall |
Removes Nushell autoload file during uninstall |
README.md |
Documents Nushell integration setup and limitations |
test/lib/common.rb |
Adds Nushell shell harness + tmux prep behavior |
test/test_shell_integration.rb |
Adds Nushell-specific integration tests (bindings + completion smoke test) |
.github/workflows/linux.yml |
Installs nushell in CI to run Nushell tests |
typos.toml |
Adds Slq to allowed words (for pacman -Slq) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace the confusing 'run this in your regular shell' comment with a pure Nushell command using 'save -f'.
The note references fzf 0.48.0 which only introduced --bash, --zsh, and --fish. The --nushell flag will be available in a later release.
Use 'recent versions of fzf' instead of a specific version number as suggested by junegunn. Also add mkdir before save to handle the case where the autoload directory does not exist yet.
f154fa3 to
adbd8e7
Compare
|
Let me just randomly post issues I noticed in the comments. |
|
Fuzzy completion does not respect export FZF_DEFAULT_OPTS='--tmux 90%,70%' |
|
Multi-selection (tab) in fuzzy completion doesn't work properly. It works for |
Wrap the ls glob in a try/catch so that pass completion returns an empty list instead of a verbose error when ~/.password-store does not exist.
When multiple files are selected with Tab in fzf, join them with spaces so the completer returns a single result instead of separate candidates displayed with ::: separators.
Options from FZF_DEFAULT_OPTS are already parsed and passed as CLI arguments. Without clearing the env var, fzf reads it again, causing --height (CLI) to override --tmux (env) since CLI args take precedence over FZF_DEFAULT_OPTS.
Rewrite __fzf_defaults_nu to return a string (like bash's __fzf_defaults) instead of a list, and pass it via FZF_DEFAULT_OPTS with-env. This ensures --height has a lower index than --tmux from the user's FZF_DEFAULT_OPTS, so --tmux wins when both are present. Also fix a critical bug where the non-existent is-string command silently swallowed all options from FZF_DEFAULT_OPTS.
These tests were identical to the ones inherited from TestShell via include, so the redefinitions were unnecessary.
|
Thanks for testing! Here's a summary of the fixes:
|
Remove test_ctrl_r which was identical to the inherited TestShell version. Add comments explaining why the remaining overrides are necessary: - test_ctrl_t_unicode: uses ^echo (external) instead of echo - test_file_completion: single-selection only (completer replaces token) - test_ctrl_r_abort: skips quote characters that break Nushell
|
Coding agents can miss subtle issues that only surface in hands-on use, which matters a lot for an interactive tool like fzf. Could you share a list of what you manually tested, ideally with screenshots? |
Nushell passes ~/path to the external completer with the tilde unexpanded. Expand it with 'path expand' before passing it to fzf as --walker-root, and restore the tilde prefix in the result.
54c2615 to
b4e1992
Compare
…letion Cover multi-selection (Tab+Tab), single selection, and hidden files. Previously only single selection was tested, which let the multi-selection bug slip through unnoticed.
| - Custom completion extensibility (e.g. `_fzf_complete_COMMAND` in bash/zsh) | ||
| is not available. Custom completions are defined via a `match` statement | ||
| in `completion.nu`. |
There was a problem hiding this comment.
Would it be possible to implement this scheme? A hard-coded match statement feels quite limiting. It could easily turn into a "kitchen sink", with users continually requesting more commands to be added.
For what it's worth, I'm on macOS and don't use tools like pacman or pass, so having them in the default list feels a bit off. I imagine this concern will only grow as more items get added over time.
There was a problem hiding this comment.
You're right, the hard-coded match is not ideal. I investigated a dynamic dispatch approach that works within Nushell's constraints.
Users could define an $env.FZF_COMPLETERS record in their config.nu with closures keyed by command name. Each closure receives the prefix and returns a list of candidates, which are then fed to fzf:
# In config.nu
$env.FZF_COMPLETERS = {
git: {|prefix| ["branch-main", "branch-dev", "branch-feature"]}
pacman: {|prefix| ^pacman -Slq | lines}
}In completion.nu, we'd check $env.FZF_COMPLETERS before falling through to the built-in defaults:
let user_completers = ($env.FZF_COMPLETERS? | default {})
if ($cmd_word in $user_completers) {
# call _fzf_complete_nu with the user's closure
} else {
match $cmd_word {
"ssh" | ... => { ... }
"kill" => { ... }
...
}
}I tested this end-to-end: defining a completer in config.nu, triggering git **<TAB>, selecting from fzf, and confirming the result is inserted on the command line. It works.
With this in place, we could remove pacman, paru, and pass from the default match and keep only the universal ones (ssh, kill). The question is where to provide the removed implementations as examples for users -- perhaps in the README or in a separate example file. What do you think?
Limitation: The closures must be defined in config.nu, not in a separate autoload file, because Nushell doesn't propagate $env mutations from autoload files to later-loaded files. This is consistent with how users configure other Nushell settings.
There was a problem hiding this comment.
With this in place, we could remove
pacman,paru, andpassfrom the defaultmatchand keep only the universal ones (ssh,kill). The question is where to provide the removed implementations as examples for users -- perhaps in the README or in a separate example file. What do you think?
Sounds good to me. How about putting them under shell/completion-examples.nu (any better name suggestion?) and add a link to the file in the README file?








alt_c,ctrl_randctrl_t**completionCloses: #4122