Why "directory completion (`cd **`)" and "cd key binding (`ALT-C`)" has different finding strategy?
- [x] I have read through the manual page (
man fzf) - [x] I have the latest version of fzf
- [x] I have searched through the existing issues
Info
- OS
- [x] Linux
- [ ] Mac OS X
- [ ] Windows
- [ ] Etc.
- Shell
- [ ] bash
- [ ] zsh
- [x] fish
Problem / Steps to reproduce
In completion.xsh, the default finding command is:
command find -L "$1" \
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \
-a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
In my opinion, Its purpose is to skip common version control directories.
On the other hand, the default finding command in key-bindings.xsh is:
command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type d -print 2> /dev/null | cut -b3-
In my opinion, Its purpose is to skip hidden directories and common virtual file systems directories.
I thought they are quite similar features, but their finding strategy is very different. What is the reason for this different behavior? Thanks!
Hmm, I don't have a good answer. It doesn't look like there's an inherent reason they should differ. They seemed to have gotten out of sync at some point. Probably an oversight.
This is an old PR that changed key-bindings, but not completion.
- https://github.com/junegunn/fzf/commit/53d5d9d1624d23175eca4c1e1bd93bbbb7b41b0c
Thanks for the quick reply and PR information. 😆
Do you think it is worth to sync these two commands? Maybe a new env variable FZF_FIND_DIR_COMMAND which has a placeholder $1 to accept a base search path (default value is '.')
For compatibility, it can use some expansion syntax like this: ${FZF_FIND_DIR_COMMAND:-${FZF_ALT_C_COMMAND:-"command find -L . ......"}}.
In this way, it can maintain consistence between these commands and provide users more flexibility to change default command in _fzf_compgen_dir()
Yes, it would be nice to update the command for directory completion. But a static command set via a configuration variable won't work as it can't handle the completion prefix (e.g. cd ~/**<tab> or cd /tmp/**<tab>, etc), and that's why we resort to _fzf_compgen_dir function with $1 being the base directory.
@kevin61416 Good point! I wrote a simple demo (#2721), which introduces a new _fzf_find_dir function to handle both completion with prefix and ALT-C Key Binding simply without breaking compatibility. This function should accept one (optional ?) argument as the base directory for finding, for example:
# .zshrc
function _fzf_find_dir()
{
local base=${1:-.}
command find -L $base -mindepth 1 \( -name .git -o -name .hg -o -name .svn \) -prune -o -type d -print 2> /dev/null | cut -b3-
}
@junegunn
For compatibility, this function (i.e., _fzf_find_dir) only works when users have provided it. At present, I have written ZSH version only. If you accept this proposal, I can help write other shells one.
Thanks 😀
Yes, it would be nice to update the command for directory completion. But a static command set via a configuration variable won't work as it can't handle the completion prefix (e.g.
cd ~/**<tab>orcd /tmp/**<tab>, etc), and that's why we resort to _fzf_compgen_dir function with$1being the base directory.
How about fzf doing cd first, and then invoke the user provided command?
Building upon @kevin61416's suggestion: CDPATH= cd "${1:-.}" && ${FZF_FIND_DIR_COMMAND:-${FZF_ALT_C_COMMAND:-"command find -L . ......"}}
Alternatively, we could use an unexpanded variable, like documented here: https://github.com/junegunn/fzf/#fish-shell