Files
MeshTerm/meshterm/core/exitcodes.py
T
Jean-Pierre MartineauandClaude Opus 5 da05dd402f Give the CLI its own voice, meant for a pipe rather than an eye
The CLI had grown the menu's manners -- colour, boxes, section headings,
glyph columns, a closing check mark -- and every one of them is in the way
of the thing it is actually for. It now prints like a standard Unix
utility: plain text, no escape sequences at all, no frames, one record per
line, and nothing wrapped, so a long line runs off the right instead of
folding its fields onto a second one.

meshterm/ui/script.py is the whole vocabulary. Listings are an uppercase
header and space-aligned records; key/value blocks are sysctl's shape, and
a `get` prints the bare value alone. Names are quoted wherever they share a
line, because a name can hold a space or a comma and a bare one is not a
field. A route reads "Origin" (3d),"Relay" (f2),"Us" (a1) -- the hash
outside the quotes, our own node a hop like any other rather than a star,
since the hash is what carries the identity that colour carries on screen.
Times are absolute local ISO-8601 and "-" is the one token for absent.

The return value is now half the report: 0 ok, 1 failure, 2 usage, 3 no
device, 4 the device was reached and the operation failed, 5 nothing to
report. That last one is the point -- a command that ran fine and found
nothing prints nothing and says so in $?, so a script never has to count
output lines to tell an empty mesh from a full one. Errors and progress
moved to stderr, and an expected failure no longer arrives as a traceback.

Two things lose their scripted face rather than get a degraded one. The map
is a picture whose nodes are told apart by colour: monochrome it would be
unreadable, coloured it could not be piped anywhere useful, and the nodes
themselves are still in `contacts`. The QR codes are a second rendering of
a link the output already prints.

ui.ack joins ui.note to draw the line the change needed: a note is output,
an acknowledgement is reassurance a person wants and a script must filter
out, so the menu prints it and the CLI drops it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:52:48 -04:00

74 lines
3.8 KiB
Python

"""The exit statuses ``meshterm`` returns, and what each one means.
A scripted run's *return value is its report*: the CLI says what happened in plain
text on stdout and says whether it worked in ``$?``. The codes are classified rather
than a bare 0/1 so a caller can tell the failures apart without reading prose — a
timeout is worth retrying, a bad key never is.
The set is small and closed. Anything that does not map onto one of the specific
causes below is :data:`FAILURE`; nothing invents a code of its own.
+------+--------------+--------------------------------------------------------+
| Code | Name | Meaning |
+======+==============+========================================================+
| 0 | ``OK`` | The command did what it was asked. |
+------+--------------+--------------------------------------------------------+
| 1 | ``FAILURE`` | It failed for a reason with no more specific code — |
| | | a bad configuration or preference value, an |
| | | unreadable file, an unhandled fault. |
+------+--------------+--------------------------------------------------------+
| 2 | ``USAGE`` | The command line itself was wrong: an unknown flag, a |
| | | missing argument, a value the parser rejected. Click |
| | | returns this on its own; it is named here so the |
| | | table is complete. |
+------+--------------+--------------------------------------------------------+
| 3 | ``NO_DEVICE``| No companion could be selected: none attached, none |
| | | matching ``--port``/``--ble``/``--tcp``, or the |
| | | choice was ambiguous. Nothing was transmitted. |
+------+--------------+--------------------------------------------------------+
| 4 | ``DEVICE`` | A device was reached but the operation failed: a |
| | | command error, a timeout, a link lost mid-run. |
| | | Retrying is reasonable. |
+------+--------------+--------------------------------------------------------+
| 5 | ``NO_RESULT``| The command ran and completed, and there was nothing |
| | | to report: an empty list, a target that never |
| | | answered, a conversation with no messages. stdout is |
| | | empty; this is not an error. |
+------+--------------+--------------------------------------------------------+
:data:`NO_RESULT` is the one that needs saying out loud, because it is the one a
script most wants and no other tool offers: ``grep`` conflates "found nothing" with
"worked", and a caller that has to count output lines to tell an empty mesh from a
full one is parsing when it could be branching.
"""
from __future__ import annotations
#: The command did what it was asked.
OK = 0
#: A failure with no more specific code — a bad value, an unreadable file, a fault.
FAILURE = 1
#: The command line was wrong. Click returns this itself; named here for completeness.
USAGE = 2
#: No companion device could be selected. Nothing was transmitted.
NO_DEVICE = 3
#: A device was reached but the operation failed. Retrying is reasonable.
DEVICE = 4
#: The command completed with nothing to report. Not an error; stdout is empty.
NO_RESULT = 5
#: Every code, by name, for the ``--help`` epilog and the documentation.
MEANINGS: dict[int, str] = {
OK: "success",
FAILURE: "failure",
USAGE: "usage error",
NO_DEVICE: "no device found, or the selection was ambiguous",
DEVICE: "the device was reached but the operation failed",
NO_RESULT: "nothing to report (empty result)",
}