261026.46 · 864eceebfe26de4778a05da0701b069d152085a3
Check the usage text with docopt-ng
The help text claimed docopt notation, but nothing parsed it. docopt rejected the usage outright: two description lines began with a dash and read as option definitions. It also rejected www --debug, since --debug, --no-bug, --cache and --disk appeared in no usage line.
The usage lines now name those options where they take effect, and [--] before DIR, which may start with a dash. TestUsageIsDocopt runs every command line TestParseArgs accepts through docopt-ng, fetched by uv run --script from the checker's inline metadata. It skips where uv is missing or cannot fetch.
reading declarations
Changes to testdata/. All files
@@ -0,0 +1,40 @@+# /// script+# requires-python = ">=3.9"+# dependencies = ["docopt-ng==0.9.0"]+# ///+"""Check command lines against a usage text with docopt-ng.++Usage:+ docopt-check.py USAGE < LINES++Reads USAGE, a file of docopt usage text, then one command line per line+on stdin, split as the shell would. Prints E22 for each line docopt+rejects and exits 22 if any was rejected or the usage text is malformed.+"""+import shlex+import sys++import docopt+++def main():+ if len(sys.argv) != 2:+ sys.stderr.write("E22: usage: docopt-check.py USAGE < LINES\n")+ return 22+ with open(sys.argv[1]) as f:+ usage = f.read()+ failed = False+ for line in sys.stdin:+ line = line.rstrip("\n")+ try:+ docopt.docopt(usage, shlex.split(line), default_help=False)+ except docopt.DocoptLanguageError as e:+ sys.stderr.write("E22: the usage text is not docopt: %s\n" % e)+ return 22+ except SystemExit:+ sys.stderr.write("E22: docopt rejects: %s\n" % line)+ failed = True+ return 22 if failed else 0+++sys.exit(main())