fzf icon indicating copy to clipboard operation
fzf copied to clipboard

feature request: support escaping of printed elements

Open calestyo opened this issue 8 months ago • 1 comments

  • [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

Feature Request

This is a companion to #3493, with the difference that here it's about a quoting style for the (selected) output of fzf.

I would say that fzf is quite often used from shells. But there, any meta-characters or other "strange" can easily cause problems.
Further, I'd say that often, the elements are pathnames (which may contain everything except for NUL).

A typical use-case seems to be e.g.:

$ do_something_with "$(find … | fzf)"

or:

$ file="$(find … | fzf)"

The NUL-delimited versions of these would be:

$ do_something_with "$(find … -print0 | fzf --read0 --print0)"

or:

$ file="$(find … -print0 | fzf --read0 --print0)"

There are three problems here:

  1. trailing newlines are lost
  2. POSIX declares the results unspecified when NUL is on the stdout within a command substitution. So either it might be ignored, or it might terminate the string or... whatever. Not using --print0 causes an undesired newline to be added in fzf’s output, which is however anyway stripped because of (1).
  3. this doesn't work anymore, when -m multiple elements are selected, either because of (2) or, if --print0 is not used, because the separator would again be newline, which would be indistinguishable from newlines in the elements.

One workaround in bash (only) is something like:

printf_from_stdin()
{
	local stdin
	IFS='' read -r -d '' -u 0 stdin
	printf '%q' "${stdin}"
}

together with:

eval "var=$(find . -mindepth 1 -maxdepth 1 -type d -print0 | fzf --read0 --print0 | printf_from_stdin)"

after which var may hold e.g. 'k'$'\n\n'
respectively (for the fzf -m case):

i=0
find . -mindepth 1 -maxdepth 1 -type d -print0 | fzf -m --read0 --print0 | \
while true; do
	eval "var=$(printf_from_stdin)"
	if [ -z "${var}" ]; then
		break
	fi
	
	printf ':%s:%s::\n' "${i}" "${var}"
	i=$(($i+1))
done

(with some sugar for display purposes)

Main problems with that: a. Works only in bash (POSIX’ read doesn't have the -d and -u options) b. Using that is rather ugly ^^

So the idea of this feature request would be that fzf gets a function similar to ls--quoting-style=-option, but specifically for output, so that one could e.g. do something like.

$ ls -al $(find . -mindepth 1 -maxdepth 1 -type d -print0 | fzf -m --read0 --print0 --output-quoting-style=shell-escape)

Assuming that shell-escape is a schema that escapes in such a way that it's re-usable as input to the shell.

Of course one could have various quoting styles, e.g. for other shells that are not POSIX compatible. Also, current POSIX doesn't support $'…'-style quoting (but the next upcoming issue of POSIX will), so it might make sense to add a style for old POSIX,... or perhaps one for fish (if that's special in that regard - I don't know).

Cheers, Chris.

calestyo avatar Oct 26 '23 23:10 calestyo