man(1) uses lowercase placeholders but we usually don't. Additionally,
the new synopsis autoformatting only recognizes placeholders if they
are uppercase. Use uppercase for all placeholders.
Recent synopsis changes move from literal code blocks to
[RST line blocks]. This does not translate well to HTML: it's not
rendered in monospace, so aligment is lost. Additionally, we don't
get syntax highlighting in HTML, which adds differences to our code
samples which are highlighted.
We hard-wrap synopsis lines (like code blocks). To align continuation
lines in manpages we need [backslashes in weird places]. Combined with
the **, *, and `` markup, it's a bit hard to get the alignment right.
Fix these by moving synopsis sources back to code blocks and compute
HTML syntax highlighting and manpage markup with a custom Sphinx
extension.
The new Pygments lexer can tokenize a synopsis and assign the various
highlighting roles, which closely matches fish's syntax highlighing:
- command/keyword (dark blue)
- parameter (light blue)
- operator like and/or/not/&&/|| (cyan)
- grammar metacharacter (black)
For manpage output, we don't project the fish syntax highlighting
but follow the markup convention in GNU's man(1):
bold text type exactly as shown.
italic text replace with appropriate argument.
To make it easy to separate these two automatically, formalize that
(italic) placeholders must be uppercase; while all lowercase text is
interpreted literally (so rendered bold).
This makes manpages more consistent, see string-join(1) and and(1).
Implementation notes:
Since we want manpage formatting but Sphinx's Pygments highlighing
plugin does not support manpage output, add our custom "synopsis"
directive. This directive parses differently when manpage output is
specified. This means that the HTML and manpage build processes must
not share a cache, because the parsed doctrees are cached. Work around
this by using separate cache locations for build targets "sphinx-docs"
(which creates HTML) and "sphinx-manpages". A better solution would
be to only override Sphinx's ManualPageBuilder but that would take a
bit more code (ideally we could override ManualPageWriter but Sphinx
4.3.2 doesn't really support that).
---
Alternative solution: stick with line blocks but use roles like
:command: or :option: (or custom ones). While this would make it
possible to produce HTML that is consistent with code blocks (by adding
a bit of CSS), the source would look uglier and is harder to maintain.
(Let's say we want to add custom formatting to the [|] metacharacters
in HTML. This is much easier with the proposed patch.)
---
[RST line blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#line-blocks
[backslashes in weird places]: https://github.com/fish-shell/fish-shell/pull/8626#discussion_r782837750
This corrects what looks like wrong alignment of some synopsis lines.
(I think the alignment is not a bad idea but it makes us do more
manual work, maybe we can automate that in future. We still need to
figure out how to translate it to HTML.)
"man -l build/user_doc/man/man1/history.1" before:
string match [-a | --all] [-e | --entire] [-i | --ignore-case]
[-r | --regex] [-n | --index] [-q | --quiet] [-v | --invert]
PATTERN [STRING…]
and after:
string match [-a | --all] [-e | --entire] [-i | --ignore-case]
[-r | --regex] [-n | --index] [-q | --quiet] [-v | --invert]
PATTERN [STRING…]
Also make the lines align the same way in the RST source by carefully
choosing the position of the backslash. I'm not sure why we used
two backslashes per line. Use only one; this gives us no choice
of where to put it so both source and man page output are aligned.
Change tabs to spaces to make the alignment in the source work.
The ellipsis is a grammar metacharacter, just like the []()|.
Write *FOO*… instead of *FOO…*, so the ellipsis is not underlined
in the man page. Not super sure about this one.
This matches the style in man(1) (except that we use the … ligature).
A previous iteration did the reverse (never use a space before the
ellipsis). That would be a smaller change.
We use plural "*OPTIONS*" more often than "*OPTION*...", so let's do
that everywhere.
In some other places where we do have an ellipsis, make sure to use
singular, since the ellipsis already means repetition. This change
is incomplete, and I'm not sure if this is worth it, since it's
subjective, so I might drop it.
Correct the grammar by moving the options after the command argument.
Also group the -c/--command and -p/--path pairs, to convey that the
short and long variants are equivalent.
While at it, consolidate the -C/--do-complete forms, like we usually
do.
One synopsis misrenders as
set [options] VARIABLE*[*INDICES]… VALUES…
Add a missing backslash to fix that. Also go back to uppercase
because I'm not sure why this was changed to lowercase.
Finally, remove the spurious ellipsis after VARIABLE[INDICES].
This element cannot be repeated. Multiple index values and ranges
can be specified but that's already implied by the plural INDICES.
For alteration we usually use "(a | b)", not "{a | b}".
While at it, instead of writing 4/6 subcommands in one line, write them
on separate lines, so it's very obvious that all these are separate
subcommands. We mainly use the (a | b) syntax for long/short options.
The -- is not special here and we don't mention it in other synopses.
It was originally added for a good reason in 98449fec5 (fix `math`
regression, 2017-07-14), along this addition to math.rst:
> You should always place a `--` flag separator before the expression. [...]
However, since 56d913453 (Cache math expressions, 2017-08-24) that
line was changed to
> You don't need to use `--` before the expression even if it begins with a minus sign [...]
Previously, when we got an unknown option with --ignore-unknown, we
would increment woptind but still try to read the same contents.
This means in e.g.
```
argparse -i h -- -ooo -h
```
The `-h` would also be skipped as an option, because after the first
`-o` getopt reads the other two `-o` and skips that many options.
This could be handled more extensively in wgetopt, but the simpler fix
is to just skip to the next argv entry once we have an unknown option
- there's nothing more we can do with it anyway!
Additionally, document this and clearly explain that we currently
don't transform the option.
Fixes#8637
Use the remaining_to_disclose count to determine if all completions
are shown (allows consistent behavior between short and long completion
lists).
Closes#8485