valkey-io / valkey-io.github.io

BSD 3-Clause "New" or "Revised" License
33 stars 34 forks source link

Command syntax: Avoid repetition for shorter rendering (simplifications) #118

Open zuiderkwast opened 2 months ago

zuiderkwast commented 2 months ago

Some command syntaxes are extremely long on the website, for example CLIENT KILL:

CLIENT KILL 〈 old-format | 〈 [ ID client-id ] | [ TYPE normal | master | primary | slave | replica | pubsub ] | [ USER username ] | [ ADDR addr ] | [ LADDR laddr ] | [ SKIPME yes | no ] | [ MAXAGE maxage ] 〉 [ 〈 [ ID client-id ] | [ TYPE normal | master | primary | slave | replica | pubsub ] | [ USER username ] | [ ADDR addr ] | [ LADDR laddr ] | [ SKIPME yes | no ] | [ MAXAGE maxage ] 〉 ... ] 〉

It's a bit hard to read it.

Describe the solution you'd like

In the man pages, there is another rendering, equivalent but shorter:

CLIENT KILL ip:port\ CLIENT KILL [<ID client-id | TYPE <NORMAL | MASTER | PRIMARY | SLAVE | REPLICA | PUBSUB> | USER username | ADDR ip:port | LADDR ip:port | SKIPME <YES | NO> | MAXAGE maxage>...]

Differences:

  1. When everything after the command and subcommand name is a single "oneof" argument, the syntax can be split into multiple lines, so COMMAND SUBCOMMAND <old-format | new-format> becomes COMMAND SUBCOMMAND old-format and on a separate line COMMAND SUBCOMMAND new-format. This multiline display is often used on man pages and --help output of commands, for example this one:

    SYNOPSIS
          git diff [<options>] [<commit>] [--] [<path>...]
          git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]
          git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...]
          git diff [<options>] <commit>...<commit> [--] [<path>...]
          git diff [<options>] <blob> <blob>
          git diff [<options>] --no-index [--] <path> <path>
  2. ip:port instead of old-format. Just use the "display" field in the JSON defintion, if it's available. This argument has a JSON definition like this:

                {
                    "name": "old-format",
                    "display": "ip:port",
                    "type": "string",
                    "deprecated_since": "2.8.12"
                },
  3. Rewrite to simplify. When an argument has "type": "oneof" and not optional, but all of its arguments have "optional": true, then we can move the optional property to the outer "oneof" argument.

    < [a] | [b] | [c] > ...

    becomes

    [ <a | b | c> ... ]

    In the CLIENT KILL example, the argument that starts with 〈 [ ID client-id ] | ... 〉 can benefit from this rewrite.

  4. When a "oneof" that is not optional, it is rendered as <a | b>. If this thing also has the "multiple": true propery, then it's currently rendered as <a | b> [ <a | b> ... ], i.e. the whole oneof thing is repeated. This combination often becomes too long to be readable.

    When I experimented with combinations of "oneof", "multiple", "optional" and "block", I realized that it's good to consider combinations of these and define a syntax for each combinatio. I ended up with the following style, which is what's applied in the suggestion above.

    simple                       foo
    optional                     [foo]
    multiple                     foo [foo...]
    multiple + optional          [foo...]
    
    oneof                        <foo | bar>
    oneof + optional             [foo | bar]
    oneof + multiple             <foo | bar> [<foo | bar>...]
    oneof + multiple + optional  [<foo | bar>...]
    
    block                        foo bar
    block + optional             [foo bar]
    block + multiple             foo bar [foo bar ...]
    block + multiple + optional  [foo bar [foo bar ...]]

Additional context

  CLIENT KILL <ip:port | <[ID client-id] | [TYPE <NORMAL | MASTER |
  SLAVE | REPLICA | PUBSUB>] | [USER username] | [ADDR ip:port] |
  [LADDR ip:port] | [SKIPME <YES | NO>] | [MAXAGE maxage]
  [[ID client-id] | [TYPE <NORMAL | MASTER | SLAVE | REPLICA |
  PUBSUB>] | [USER username] | [ADDR ip:port] | [LADDR ip:port] |
  [SKIPME <YES | NO>] | [MAXAGE maxage] ...]>>`.
stockholmux commented 1 month ago

The multiple line version is definitely clearer.