Binding to move search root to parent?
Checklist
- [x] I have read through the manual page (
man fzf) - [x] I have searched through the existing issues
- [x] For bug reports, I have checked if the bug is reproducible in the latest version of fzf
Output of fzf --version
0.57.0 (0476a65)
OS
- [x] Linux
- [ ] macOS
- [ ] Windows
- [ ] Etc.
Shell
- [ ] bash
- [x] zsh
- [ ] fish
Problem / Steps to reproduce
Feature request: a binding to change the search root to the parent folder.
Use case: sometimes I enter fzf with alt-c or ctrl-t, and I then realize that the folder that I'm looking for is an ancestor or cousin. I then have to ctrl-c, cd ../.., and try again. It would be cool if there was a binding to restart fzf with .. as the new search root to make this quicker. My suggestion is alt-left because that's the binding for back in most browsers.
I think this can be hacked together using the existing very powerful binding features, but I wanted to suggest making this a default binding since it would be really useful in a common use case.
~~You can add a bind in FZF_ALT_C_OPTS to allow moving to a fix directory like this:~~
export FZF_ALT_C_OPTS="
--bind "ctrl-u:reload(find .. -type d)"
"
~~However it only allows to a fix location because the fzf process will preserve the cwd and you can only move relative from the start. Maybe if fzf allows to change the cwd in a action that would be enough to keep moving up.~~
Never mind, I just realize that although that works to show other directories, it won't cd into them because it expects the same path from where it started. So yeah, it needs to be updated from the script that sets alt-c.
NOTE: Updated snipped. It should work as long as find return a relative path e.g. ../dir or an absolute path /home/user/foo
find .. -type d
Since version 0.47.0[^1], fzf has started using a custom walker, and in subsequent iterations,
it has added some flags to it; it should be faster than find.
Reloading with a walker like this works, but there is an issue for adding a potential flag: #4062.
source <(fzf --zsh)
export FZF_ALT_C_OPTS="--bind 'ctrl-u:reload:</dev/tty FZF_DEFAULT_COMMAND= fzf --filter= --walker dir --walker-root ..'"
but I wanted to suggest making this a default binding since it would be really useful in a common use case
The maintainer makes the call, but in the past, the saying went that the provided shell integration are an offer to the user to use it and alter them to fit their needs.
[^1]: fzf/CHANGELOG.md 0.47.0
Here's my take.
read -d '' FZF_ALT_C_OPTS << 'EOF'
--bind 'ctrl-h:transform:
dir="${FZF_PROMPT%%> }"
dir="${dir:-.}"
dir="$(realpath "$dir/..")"
printf "top+change-prompt(%s> )" "$dir"
printf "+reload:</dev/tty fzf --filter %q --walker dir --walker-root %s" "" "$dir"
'
--bind 'ctrl-l:transform:
dir="${FZF_PROMPT%%> }"
if [[ -n $dir ]]; then
dir="$(realpath {})"
else
dir={}
fi
printf "top+change-prompt(%s> )" "$dir"
printf "+reload:</dev/tty fzf --filter %q --walker dir --walker-root %s" "" "$dir"
'
EOF
- CTRL-H to go up to the parent, CTRL-L to go inside the directory
- It uses the prompt as the placeholder for the current location
Since https://github.com/junegunn/fzf/commit/80da0776f85612d527e380226734f9372e7a0719, this can be simplified as
read -d '' FZF_ALT_C_OPTS << 'EOF'
--bind 'ctrl-h,ctrl-l:transform:
dir="${FZF_PROMPT%%> }"
if [[ $FZF_KEY = ctrl-h ]]; then
dir="${dir:-.}"
dir="$(realpath "$dir/..")"
elif [[ -n $dir ]]; then
dir="$(realpath {})"
else
dir={}
fi
printf "top+change-prompt(%s> )" "$dir"
printf "+reload:</dev/tty fzf --filter %q --walker dir --walker-root %s" "" "$dir"
'
EOF
While I like this, it's not easy to make it the default because we can't guarantee that it is compatible with the user's $FZF_ALT_C_OPTS and $FZF_ALT_C_COMMAND. Also, there's no universal consensus on which keys should be used.