Welcome to Vifm Q&A, where you can ask questions about using Vifm. Registration is optional, anonymous posts are moderated. E-mail and GitHub logins are enabled.
0 votes
in vifm by

The following function call

term("source $VIFM/scripts/fzf_vifm_integration.bash && echo $(__fzf_cd__ 2>/dev/tty | sed 's/\s*builtin cd --\s*//')")

writes errors to the terminal '... broken pipe blah blah blah' when fzf is still gathering directories but the user already made his choice. The same code running within an interactive shell works as expected, no errors:

source <path-to-script>/scripts/fzf_vifm_integration.bash && echo $(__fzf_cd__ 2>/dev/tty | sed 's/\s*builtin cd --\s*//')

My guess is term() function finishes its execution while some shell processes inside it are still running and connected to some pipelines.

The question is how to fix this edge case?

1 Answer

0 votes
by
edited by

Would be nice to know what prints the error, the shell?

I tried

:echo term("echo a && echo $(fzf 2>/dev/tty | sed 's/\s*builtin cd --\s*//')")

and didn't get any errors. Does this command error for you?

by

Your piece of code works fine. But this one doesn't:

term("source $VIFM/scripts/fzf_vifm_integration.bash && echo $(__fzf_cd__ 2>/dev/tty | sed 's/\s*builtin cd --\s*//')")

When interrupting (by escape, for instance) long running fzf loading process one gets the error: sed: couldn't write 64 items to stdout: Broken pipe

$VIFM/scripts/fzf_vifm_integration.bash (copied from fzf's key-bindings.bash):

__fzfcmd() {
  [[ -n "${TMUX_PANE-}" ]] && { [[ "${FZF_TMUX:-0}" != 0 ]] || [[ -n "${FZF_TMUX_OPTS-}" ]]; } &&
    echo "fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- " || echo "fzf"
}

__fzf_cd__() {
  local cmd opts dir
  cmd="${FZF_ALT_C_COMMAND:-"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 | command cut -b3-"}"
  opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-} +m"
  dir=$(set +o pipefail; eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd)) && printf 'builtin cd -- %q' "$dir"
}

There is set +o pipefail, but for some reason calling __fzf_cd__ directly from the shell and interrupting it by escape doesn't produce any errors.

I'm trying to reuse my FZF_ALT_C_COMMAND and FZF_ALT_C_OPTS defined in .bashrc and call fzf intrinsics (__fzf_cd__) to make fzf use my already defined fzf options for searching directories and get identical experience in vifm and bash.

by

I only get cut: write error: Broken pipe which seems to come from default value of $FZF_ALT_C_COMMAND.

Vifm doesn't wait for process to finish, it waits for pipe to reach end-of-file state, which happens after all writing processes have closed their end of the pipe.

Maybe your values of FZF_ALT_C_COMMAND and FZF_ALT_C_OPTS play a role. If you have another sed invocation there, it would explain the error.

I can also push a branch that does wait for child process to finish before closing the pipe if you're willing to test it.

by

If you have another sed invocation there, it would explain the error.

I have another piece of code for searching files without sed invocation, it gives same errors:

let $FZF_PICK = term("source $VIFM/scripts/fzf_vifm_integration.bash && echo $(__fzf_select__ 2>/dev/tty)")

Maybe your values of FZF_ALT_C_COMMAND and FZF_ALT_C_OPTS play a role. If you have another sed invocation there, it would explain the error.

My FZF_ALT_C_COMMAND:

export FZF_ALT_C_COMMAND="find -L . -type d \( -name .git -o -name .svn -o -name .hg -o -name node_modules -o -name .npm -o -name .cache -o -name .asdf -o -name .gnupg -o -name .mozilla -o -name .thunderbird -o -name .vscode -o -name .var -o -name .pki -o -name .dotnet -o -name .thumbnails -o -name .cargo \) -prune -o -type d -not -name '.' -print 2>/dev/null | sed s@^\./@@"

But if I use the following default fzf cmd and opts

export FZF_ALT_C_COMMAND="find . -iname '*'"
export FZF_ALT_C_OPTS=""

and interrupt fzf before it produces a full set of results I still get the error:
find: standard output’: Broken pipe find: write error

I can also push a branch that does wait for child process to finish before closing the pipe if you're willing to test it.

It's not necessary. I just wanted to make sure that there are no fuckups on my end and get the quick solution if possible. fzf search works anyway and situations when I have to wait for fzf results are rare.

Thanks for your help.

If you would like to make a bug report or feature request consider using GitHub, SourceForge or e-mail. Posting such things here is acceptable, but this is not a perfect place for them.
...