fzf icon indicating copy to clipboard operation
fzf copied to clipboard

CTRL-T binding not using last token with custom FZF_CTRL_T_COMMAND

Open ZacDanMon opened this issue 4 months ago • 8 comments

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.65.1 (Fedora)

OS

  • [x] Linux
  • [ ] macOS
  • [ ] Windows
  • [ ] Etc.

Shell

  • [ ] bash
  • [ ] zsh
  • [x] fish

Problem / Steps to reproduce

fzf version: 0.65.1 fish version: 4.0.2

I've been exploring the shell integration features of fzf with fish shell, and I came across the CTRL-T binding and ways to customize it. From what I can see in the readme, referencing $dir in FZF_CTRL_T_COMMAND should allow me to use the current last token on the command line as the root directory. I've tried many different ways to format the command, with both find and fd, but I'm finding that any value in that variable causes the root directory to be the cwd, and not the last token.

The correct behavior is working if FZF_CTRL_T_COMMAND is unset. Following the example in the readme, hitting CTRL-T with the following text in the command line:

ls /var/

Does list files and directories relative to /var/

The problem occurs if you set FZF_CTRL_T_COMMAND to either:

  • As suggested in the readme with find:
    • set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'"
  • As suggested in #4251 with fd:
    • set -g FZF_CTRL_T_COMMAND "command fd -L --type f --hidden --follow --exclude .git . \$dir"

And then try to use the CTRL-T binding from the same starting text as above, it will incorrectly list files relative to your current working directory.

I've tried this with my own fish config, and from a blank config started with fish -N and the behavior is the same. I haven't been able to find any value for FZF_CTRL_T_COMMAND that shows the list relative to the directory.

Based on previous issues I've found, like the one referenced above this seems to have been working before. I know there's been some bigger fish version changes lately, so it's possible the current way of setting that token isn't working with the newest version of fish.

ZacDanMon avatar Aug 20 '25 16:08 ZacDanMon

After further testing, this issue might be specific to the fedora packaged version of fzf. I tried it on my home pc running Arch Linux, with the same fish and fzf versions, and the CTRL-T bindings work fine there with a custom FZF_CTRL_T_COMMAND.

ZacDanMon avatar Aug 22 '25 12:08 ZacDanMon

What is the output of functions fzf-file-widget in Fedora?

bitraid avatar Aug 22 '25 13:08 bitraid

# Defined via `source`
function fzf-file-widget --description 'List files and folders'
    set -l commandline (__fzf_parse_commandline)
    set -lx dir $commandline[1]
    set -l fzf_query $commandline[2]
    set -l prefix $commandline[3]

    set -lx FZF_DEFAULT_OPTS (__fzf_defaults \
      "--reverse --walker=file,dir,follow,hidden --scheme=path" \
      "$FZF_CTRL_T_OPTS --multi --print0")

    set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
    set -lx FZF_DEFAULT_OPTS_FILE

    set -l result (eval (__fzfcmd) --walker-root=$dir --query=$fzf_query | string split0)
    and commandline -rt -- (string join -- ' ' $prefix(string escape -- $result))' '

    commandline -f repaint
  
end

This is the output on Fedora. When I get home later, I can compare this with what it shows on Arch, if this looks wrong.

ZacDanMon avatar Aug 22 '25 14:08 ZacDanMon

It seems OK. If you set FZF_CTRL_T_COMMAND to echo \$dir, and then press ctrl-t after ls /var/, what gets displayed in fzf list?

bitraid avatar Aug 22 '25 15:08 bitraid

There's only one blank entry that shows in the list. If I select it, an empty string, '' gets entered.

ZacDanMon avatar Aug 22 '25 16:08 ZacDanMon

I loaded Fedora 42 on a VM, but I can't reproduce. Try this:

set -g FZF_CTRL_T_COMMAND echo \$dir
fzf --fish | string replace 'set -lx dir $commandline[1]' 'set -lx dir $commandline[1]; set --show dir > /tmp/fzf_dir' | source
ls /var/ #press CTRL-T and them exit fzf
cat /tmp/fzf_dir

What is the output of the last command?

bitraid avatar Aug 22 '25 17:08 bitraid

$dir: set in local scope, exported, with 1 elements
$dir[1]: |/var|

Still showed only the 1 blank entry, but at the point that it's logged $dir is set to what it should be.

ZacDanMon avatar Aug 22 '25 19:08 ZacDanMon

This is strange (especially since it also happens with fish -N). You can try a few more things:

  • What is the output of type fzf?
  • Set FZF_CTRL_T_COMMAND to set -S dir and press ctrl-t after /var/. Does it display anything in fzf list?
  • Type this in fish prompt:
begin
    set -lx dir /var
    fish -c 'set -S dir'
end

Does it display anything?

  • Does this display anything in fzf list?
set -g FZF_CTRL_T_COMMAND set -S dir_uniq123
fzf --fish | string replace 'set -lx dir $commandline[1]' 'set -lx dir_uniq123 $commandline[1]' | source
ls /var/ # press CTRL-T

bitraid avatar Aug 22 '25 20:08 bitraid