Support `--quoting-style` like `ls` (and quote filenames with spaces by default)
When a filename ends in a space, there is no indication. Compare this with GNU ls, which encloses filenames with spaces in quotes.
$ touch hello
$ ls
hello
$ exa
hello
$ touch 'hello '
$ ls
hello 'hello '
$ exa
hello hello
As an aside on the example above, GNU ls sorts 'hello ' after 'hello' while exa sorts them the other way round.
This is a special case of #211 in a way.
#211 looks more complex to implement, maybe that's the reason it's 3+ years old?
Simply wrapping in quotes the file names when they contain a space would be a lot easier to implement and REALLY useful.
exa -l
lrwxrwxrwx 10 dd 29 Oct 11:59 foo -> bar -> baz -> foo -> bar
which is the link and which is the target?
ls -l
lrwxrwxrwx 1 dd dd 10 Oct 29 11:59 'foo -> bar -> baz' -> 'foo -> bar'
That looks quite fundamental to me.
This is something I still want to have!
What does ls do?
There are more details about the feature in info ls, section 10.1.7. Reproducing here the content (as of coreutils 8.32):
Documentation about --quoting-style
These options change how file names themselves are printed.
‘-b’
‘--escape’
‘--quoting-style=escape’
Quote nongraphic characters in file names using alphabetic and
octal backslash sequences like those used in C.
‘-N’
‘--literal’
‘--quoting-style=literal’
Do not quote file names. However, with ‘ls’ nongraphic characters
are still printed as question marks if the output is a terminal and
you do not specify the ‘--show-control-chars’ option.
‘-q’
‘--hide-control-chars’
Print question marks instead of nongraphic characters in file
names. This is the default if the output is a terminal and the
program is ‘ls’.
‘-Q’
‘--quote-name’
‘--quoting-style=c’
Enclose file names in double quotes and quote nongraphic characters
as in C.
‘--quoting-style=WORD’
Use style WORD to quote file names and other strings that may
contain arbitrary characters. The WORD should be one of the
following:
‘literal’
Output strings as-is; this is the same as the ‘-N’ or
‘--literal’ option.
‘shell’
Quote strings for the shell if they contain shell
metacharacters or would cause ambiguous output. The quoting
is suitable for POSIX-compatible shells like ‘bash’, but it
does not always work for incompatible shells like ‘csh’.
‘shell-always’
Quote strings for the shell, even if they would normally not
require quoting.
‘shell-escape’
Like ‘shell’, but also quoting non-printable characters using
the POSIX proposed ‘$''’ syntax suitable for most shells.
‘shell-escape-always’
Like ‘shell-escape’, but quote strings even if they would
normally not require quoting.
‘c’
Quote strings as for C character string literals, including
the surrounding double-quote characters; this is the same as
the ‘-Q’ or ‘--quote-name’ option.
‘escape’
Quote strings as for C character string literals, except omit
the surrounding double-quote characters; this is the same as
the ‘-b’ or ‘--escape’ option.
‘clocale’
Quote strings as for C character string literals, except use
surrounding quotation marks appropriate for the locale.
‘locale’
Quote strings as for C character string literals, except use
surrounding quotation marks appropriate for the locale, and
quote 'like this' instead of "like this" in the default C
locale. This looks nicer on many displays.
You can specify the default value of the ‘--quoting-style’ option
with the environment variable ‘QUOTING_STYLE’. If that environment
variable is not set, the default value is ‘shell-escape’ when the
output is a terminal, and ‘literal’ otherwise.
A few notes:
-
literal,shellandshell-always: display some characters it can’t display, like new line (\n), as? -
shell-escapeandshell-escape-always: “POSIX proposed$''syntax” is hard to read IMHO (the C/Rust string"first\nsecond"is printed as'first'$'\n''second'by ls — butfirst$'\n'secondis totally valid) and doesn’t work with fish. -
candescape: May be easy to implement, a Rust mode might be relevant too. -
clocaleandlocale: I doesn’t seem very useful, and it needs support for knowing which quotes are used for which language.
What does exa do now?
- When exa displays a character by its escape code it uses a different color (it’s good!), but different filenames can be represented by the same string, only with different colors (e.g. in
test\n,\ncan represent a new line character or the two characters\andn). - Some escapes used are not valid in terminals, e.g. what ls prints as
'test'$'\b'is printed astest\u{8}in exa.
What do we want exa to do?
Several possible goals:
- Default output should be unambiguous (be able to differentiate between
test\\nandtest\neven without color) - Be able to copy-paste the result and reuse it in a POSIX shell
- Support an output style for fish (see fish quotes and escaping characters, function to escape strings in fish code)
What details should be taken care of
GNU Coreutils have a page about the feature. It’s interesting because it tells about a few bugs they had to fix, especially regarding alignment.
Here’s the code used by GNU ls to do it:
https://github.com/coreutils/gnulib/blob/master/lib/quotearg.c
But really it sounds like a nightmare to implement all these quoting styles, and I don’t think it’s really useful. We could probably agree on three or four quoting styles.
Also, I’d argue it could be good to at least quote the filename if there’s a space in it as a first step for better handling of filenames, since I believe it’s the more common use case.