Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: support escaping of printed elements #3494

Open
3 tasks done
calestyo opened this issue Oct 26, 2023 · 1 comment
Open
3 tasks done

feature request: support escaping of printed elements #3494

calestyo opened this issue Oct 26, 2023 · 1 comment

Comments

@calestyo
Copy link
Contributor

  • I have read through the manual page (man fzf)
  • I have the latest version of fzf
  • 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
Copy link
Contributor Author

Oh and just for the records:

If I'm not mistaken, e.g. bash's implementation of %q in its printf builtin can be found at:
https://github.com/bminor/bash/blob/ec8113b9861375e4e17b3307372569d429dec814/builtins/printf.def#L595-L644

with the actual work horses being:
https://github.com/bminor/bash/blob/ec8113b9861375e4e17b3307372569d429dec814/lib/sh/strtrans.c#L230-L317

or:

https://github.com/bminor/bash/blob/ec8113b9861375e4e17b3307372569d429dec814/lib/sh/shquote.c#L261-L312

(notice that these are unofficial git mirrors)

Maybe ls does it a bit different.

Also note, that for such functionality to be useful in the way I propose, it would be crucial that the escaping is done right, so that and arbitrary input string is quoted in a manner so that it can really be safely re-used as input (e.g. in eval) without any expansions/substitutions/etc. happening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant