aontu 0.53.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aontu.d.ts +3 -2
- package/dist/aontu.js +36 -7
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +500 -8
- package/dist/cli.js.map +1 -1
- package/dist/ctx.d.ts +5 -0
- package/dist/ctx.js +1 -0
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js.map +1 -1
- package/dist/err.js +7 -1
- package/dist/err.js.map +1 -1
- package/dist/graph.d.ts +2 -5
- package/dist/graph.js +83 -46
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +9 -10
- package/dist/hcanon.js.map +1 -1
- package/dist/hints.js +94 -26
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +34 -0
- package/dist/jsonschema.js.map +1 -1
- package/dist/lang.js +593 -191
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +86 -6
- package/dist/lsp.js.map +1 -1
- package/dist/mcp.js +153 -6
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +42 -8
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.d.ts +4 -0
- package/dist/mod.js +97 -2
- package/dist/mod.js.map +1 -1
- package/dist/patch.d.ts +5 -0
- package/dist/patch.js +25 -25
- package/dist/patch.js.map +1 -1
- package/dist/provenance.d.ts +1 -0
- package/dist/provenance.js +2 -1
- package/dist/provenance.js.map +1 -1
- package/dist/query.js.map +1 -1
- package/dist/reach.d.ts +1 -0
- package/dist/reach.js +49 -21
- package/dist/reach.js.map +1 -1
- package/dist/relation.d.ts +4 -0
- package/dist/relation.js +125 -200
- package/dist/relation.js.map +1 -1
- package/dist/sig.d.ts +25 -0
- package/dist/sig.js +277 -0
- package/dist/sig.js.map +1 -0
- package/dist/sigdecl.d.ts +2 -0
- package/dist/sigdecl.js +11 -0
- package/dist/sigdecl.js.map +1 -0
- package/dist/siggate.d.ts +4 -0
- package/dist/siggate.js +90 -0
- package/dist/siggate.js.map +1 -0
- package/dist/std.js +75 -16
- package/dist/std.js.map +1 -1
- package/dist/subsume.js +57 -10
- package/dist/subsume.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/unify.d.ts +2 -2
- package/dist/unify.js +93 -114
- package/dist/unify.js.map +1 -1
- package/dist/utility.d.ts +1 -2
- package/dist/utility.js +7 -61
- package/dist/utility.js.map +1 -1
- package/dist/val/AggFuncVal.d.ts +12 -1
- package/dist/val/AggFuncVal.js +165 -3
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/BagVal.d.ts +2 -0
- package/dist/val/BagVal.js +56 -8
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +33 -5
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.d.ts +35 -0
- package/dist/val/ContainerKindVal.js +99 -0
- package/dist/val/ContainerKindVal.js.map +1 -0
- package/dist/val/CopyFuncVal.js +0 -7
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.d.ts +1 -2
- package/dist/val/DisjunctVal.js +146 -39
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/ExpectVal.js +37 -2
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +19 -8
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.d.ts +39 -0
- package/dist/val/GraphAtomVal.js +184 -0
- package/dist/val/GraphAtomVal.js.map +1 -0
- package/dist/val/JunctionVal.js +22 -5
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/ListVal.js +27 -34
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/MapVal.d.ts +1 -0
- package/dist/val/MapVal.js +82 -35
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/PathFuncVal.d.ts +2 -2
- package/dist/val/PathFuncVal.js +75 -16
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.d.ts +25 -0
- package/dist/val/PathVal.js +150 -0
- package/dist/val/PathVal.js.map +1 -0
- package/dist/val/PlusOpVal.d.ts +2 -1
- package/dist/val/PlusOpVal.js +50 -35
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefVal.d.ts +2 -0
- package/dist/val/PrefVal.js +159 -32
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.d.ts +19 -0
- package/dist/val/RecurseVal.js +217 -0
- package/dist/val/RecurseVal.js.map +1 -0
- package/dist/val/RefVal.d.ts +2 -1
- package/dist/val/RefVal.js +105 -72
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.d.ts +30 -7
- package/dist/val/ReferFuncVal.js +395 -94
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.d.ts +4 -2
- package/dist/val/ScalarKindVal.js +12 -1
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/SuperFuncVal.d.ts +4 -2
- package/dist/val/SuperFuncVal.js +118 -14
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.d.ts +1 -1
- package/dist/val/Val.d.ts +2 -3
- package/dist/val/Val.js +39 -20
- package/dist/val/Val.js.map +1 -1
- package/dist/val/arith.js +4 -1
- package/dist/val/arith.js.map +1 -1
- package/dist/vet.d.ts +1 -0
- package/dist/vet.js +32 -1
- package/dist/vet.js.map +1 -1
- package/dist/view.d.ts +90 -0
- package/dist/view.js +2168 -0
- package/dist/view.js.map +1 -0
- package/grammar/aontu.gbnf +18 -10
- package/grammar/aontu.lark +15 -10
- package/grammar/aontu.tmLanguage.json +184 -0
- package/package.json +10 -3
- package/skill/grammar-card.md +1 -2
- package/src/aontu.ts +37 -7
- package/src/cli.ts +553 -8
- package/src/ctx.ts +20 -0
- package/src/diff.ts +4 -2
- package/src/err.ts +8 -1
- package/src/graph.ts +125 -75
- package/src/hcanon.ts +9 -11
- package/src/hints.ts +112 -29
- package/src/jsonschema.ts +41 -0
- package/src/lang.ts +642 -203
- package/src/lsp.ts +75 -6
- package/src/mcp.ts +164 -6
- package/src/mod-tool.ts +48 -9
- package/src/mod.ts +110 -1
- package/src/patch.ts +31 -27
- package/src/provenance.ts +8 -1
- package/src/query.ts +4 -2
- package/src/reach.ts +52 -23
- package/src/relation.ts +139 -236
- package/src/sig.ts +345 -0
- package/src/sigdecl.ts +11 -0
- package/src/siggate.ts +144 -0
- package/src/std.ts +77 -16
- package/src/subsume.ts +59 -10
- package/src/unify.ts +102 -125
- package/src/utility.ts +7 -67
- package/src/val/AggFuncVal.ts +231 -4
- package/src/val/BagVal.ts +58 -9
- package/src/val/ConstraintVal.ts +34 -5
- package/src/val/ContainerKindVal.ts +158 -0
- package/src/val/CopyFuncVal.ts +0 -7
- package/src/val/DisjunctVal.ts +152 -40
- package/src/val/ExpectVal.ts +39 -4
- package/src/val/FuncBaseVal.ts +21 -8
- package/src/val/GraphAtomVal.ts +264 -0
- package/src/val/JunctionVal.ts +23 -6
- package/src/val/ListVal.ts +30 -37
- package/src/val/MapVal.ts +87 -39
- package/src/val/PathFuncVal.ts +107 -19
- package/src/val/PathVal.ts +221 -0
- package/src/val/PlusOpVal.ts +56 -37
- package/src/val/PrefVal.ts +186 -38
- package/src/val/RecurseVal.ts +285 -0
- package/src/val/RefVal.ts +105 -83
- package/src/val/ReferFuncVal.ts +445 -100
- package/src/val/ScalarKindVal.ts +12 -0
- package/src/val/SuperFuncVal.ts +137 -13
- package/src/val/TopVal.ts +1 -1
- package/src/val/Val.ts +44 -35
- package/src/val/arith.ts +4 -1
- package/src/vet.ts +41 -4
- package/src/view.ts +2882 -0
- package/dist/val/IdFuncVal.d.ts +0 -13
- package/dist/val/IdFuncVal.js +0 -54
- package/dist/val/IdFuncVal.js.map +0 -1
- package/src/val/IdFuncVal.ts +0 -91
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ exports.runBreaking = runBreaking;
|
|
|
11
11
|
exports.runTrim = runTrim;
|
|
12
12
|
exports.runRelations = runRelations;
|
|
13
13
|
exports.runReaches = runReaches;
|
|
14
|
+
exports.runView = runView;
|
|
14
15
|
exports.runJsonSchema = runJsonSchema;
|
|
15
16
|
exports.runMod = runMod;
|
|
16
17
|
exports.runHash = runHash;
|
|
@@ -43,6 +44,7 @@ const mod_tool_1 = require("./mod-tool");
|
|
|
43
44
|
const mod_1 = require("./mod");
|
|
44
45
|
const vet_1 = require("./vet");
|
|
45
46
|
const reach_1 = require("./reach");
|
|
47
|
+
const view_1 = require("./view");
|
|
46
48
|
const agentsmd_1 = require("./agentsmd");
|
|
47
49
|
const HELP = `Usage: aontu [options] [file]
|
|
48
50
|
aontu vet [options] <schema> <data> [more-data...]
|
|
@@ -51,6 +53,8 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
51
53
|
aontu trim --check [options] <file>
|
|
52
54
|
aontu relations [options] <file>
|
|
53
55
|
aontu reaches <from> <to> [--relation <name>] [options] <file>
|
|
56
|
+
aontu view <kind> [options] <file>...
|
|
57
|
+
aontu view --views <path> [--check] [options] <file>
|
|
54
58
|
aontu jsonschema [--at <path>] [--strict] [options] <file>
|
|
55
59
|
aontu hash [options] <file>
|
|
56
60
|
aontu mod tidy|verify|vendor|manifest [options] [dir]
|
|
@@ -171,6 +175,72 @@ Why options:
|
|
|
171
175
|
Why exit codes mirror get's: 0 explained, 1 the path names nothing,
|
|
172
176
|
2 usage, 4 the document does not stand up on its own.
|
|
173
177
|
|
|
178
|
+
View kinds: tree, matrix, graph, layer, sets, layers, ladder, poset
|
|
179
|
+
(the poset takes several files). The figure goes to stdout, the loss
|
|
180
|
+
report to stderr. With --views it draws every figure a document
|
|
181
|
+
declares as data, from one evaluation: each declaration names its own
|
|
182
|
+
kind and out file, nothing is written unless every figure rendered,
|
|
183
|
+
and --check gates the committed set.
|
|
184
|
+
|
|
185
|
+
View options:
|
|
186
|
+
--as <profile> text | mermaid | dot | er | svg, per kind: doc,
|
|
187
|
+
tree, matrix, sets and layers draw text (default)
|
|
188
|
+
or svg; graph draws mermaid (default), dot or er;
|
|
189
|
+
layer draws text (default), mermaid or svg; ladder
|
|
190
|
+
and poset draw mermaid (default) or dot
|
|
191
|
+
--at <path> Restrict the figure to nodes under this path; the
|
|
192
|
+
subtree doc draws; the path the ladder draws;
|
|
193
|
+
where the poset compares
|
|
194
|
+
--views <path> Draw every figure the document declares at this
|
|
195
|
+
path, one evaluation, all or nothing; each
|
|
196
|
+
declaration names its own kind and out file
|
|
197
|
+
-o, --out <file> Write the figure here instead of stdout
|
|
198
|
+
--check Exit 1 if --out differs from what would be drawn;
|
|
199
|
+
nothing is written
|
|
200
|
+
--strict Exit 1 when the loss report holds anything beyond
|
|
201
|
+
edges_deduped, inverse_suppressed and crossings
|
|
202
|
+
--depth <n> doc: how many levels of key to draw (default 3)
|
|
203
|
+
--max-rows <n> Refuse a figure above this many rows (default 60)
|
|
204
|
+
--style <s> auto (default), none, ansi or css. A figure's
|
|
205
|
+
marks carry their meaning -- a direct cell, a
|
|
206
|
+
closure cell, an upward edge -- and each profile
|
|
207
|
+
has one way to show it: SGR escapes for text, CSS
|
|
208
|
+
classes for svg. auto picks that mechanism where
|
|
209
|
+
the destination can carry it: escapes only on a
|
|
210
|
+
terminal (NO_COLOR is honoured), and an svg keeps
|
|
211
|
+
the stylesheet that makes it standalone. none
|
|
212
|
+
drops both; on svg the classes stay and only the
|
|
213
|
+
stylesheet goes, for a host page that has already
|
|
214
|
+
bound --av-ink and its kin. Escapes are never
|
|
215
|
+
written to a file
|
|
216
|
+
--format <f> text (default) or json, the whole report
|
|
217
|
+
--relation <n> tree, matrix, layer: draw over this relation only;
|
|
218
|
+
graph: keep this predicate (repeatable)
|
|
219
|
+
--root <path> tree: draw only the subtree under this node;
|
|
220
|
+
repeatable
|
|
221
|
+
--order <o> matrix: canon (default) or partition
|
|
222
|
+
--closure matrix: mark transitively reachable cells +
|
|
223
|
+
--group-by <k> graph: one subgraph per distinct value of field k;
|
|
224
|
+
layer: one band per value (required)
|
|
225
|
+
--layers <a,b> layer: the bands in this order, top first; without
|
|
226
|
+
it the order is derived from the relation
|
|
227
|
+
--edges <e> layer: which of the relation's edges to draw over
|
|
228
|
+
the bands -- upward (the violations, the default
|
|
229
|
+
for text and svg), all (mermaid's default) or none
|
|
230
|
+
--label <k> graph: label each node with field k
|
|
231
|
+
--sets <path> sets: the map whose keys are the sets
|
|
232
|
+
--member <k> sets: the field holding each set's members
|
|
233
|
+
--universe <p> sets: the full element domain, so the empty
|
|
234
|
+
column exists
|
|
235
|
+
--min-degree <n> sets: drop intersections below this degree
|
|
236
|
+
--min-size <n> layers: drop intersections below this many paths
|
|
237
|
+
--max-cols <n> sets, layers: elide columns beyond this many
|
|
238
|
+
--profile <p> poset: values | defaults (default) | gen
|
|
239
|
+
|
|
240
|
+
View exit codes: 0 rendered, 1 --check mismatch or lossy under
|
|
241
|
+
--strict, 2 usage or --max-rows exceeded, 4 the document does not stand
|
|
242
|
+
up on its own, or a relation, root or path that names nothing.
|
|
243
|
+
|
|
174
244
|
Set options:
|
|
175
245
|
--entry <file> The document the change is checked against
|
|
176
246
|
--overlay <file> The file the change is appended to (created if
|
|
@@ -1419,6 +1489,57 @@ const REACHES_EXIT = {
|
|
|
1419
1489
|
unreachable: 1,
|
|
1420
1490
|
error: 4,
|
|
1421
1491
|
};
|
|
1492
|
+
const VIEW_HELP = 'aontu view <kind> [options] <file>... (try --help)';
|
|
1493
|
+
const VIEW_KINDS = ['doc', 'tree', 'matrix', 'graph', 'layer', 'sets', 'layers', 'ladder',
|
|
1494
|
+
'poset'];
|
|
1495
|
+
const VIEW_PROFILES = ['text', 'mermaid', 'dot', 'er', 'svg'];
|
|
1496
|
+
const VIEW_EDGES = ['upward', 'all', 'none'];
|
|
1497
|
+
// The styles the CLI accepts (VIEWS.0.md, "7. Styling"). `auto` is
|
|
1498
|
+
// here and NOT in ViewStyle: resolving it means knowing whether stdout
|
|
1499
|
+
// is a terminal, which is the CLI's to know and the library's never --
|
|
1500
|
+
// the same division err.ts already draws for the error frames.
|
|
1501
|
+
const VIEW_STYLES = ['auto', 'none', 'ansi', 'css'];
|
|
1502
|
+
// `--style auto` resolved, which only the CLI can do. The mechanism is
|
|
1503
|
+
// the PROFILE's and the library knows it -- an SVG carries its
|
|
1504
|
+
// stylesheet unless told not to, which is what makes a figure stand
|
|
1505
|
+
// alone. What the library cannot know is whether the DESTINATION is a
|
|
1506
|
+
// terminal, so that is the only thing decided here: escapes on the
|
|
1507
|
+
// text profile when stdout is a terminal and NO_COLOR is unset, the
|
|
1508
|
+
// same two conditions the error frames use. `undefined` leaves the
|
|
1509
|
+
// profile's own default in place.
|
|
1510
|
+
function viewStyleOf(asked, as) {
|
|
1511
|
+
if (undefined !== asked && 'auto' !== asked) {
|
|
1512
|
+
return asked;
|
|
1513
|
+
}
|
|
1514
|
+
// STDOUT'S OWN TERMINAL-NESS, and NO_COLOR read here rather than
|
|
1515
|
+
// through colorActive(). The figure goes to STDOUT and the error
|
|
1516
|
+
// frames go to STDERR, and they are not the same destination: main()
|
|
1517
|
+
// has already called setColor for stderr, so asking colorActive()
|
|
1518
|
+
// would answer the wrong question twice --- no escapes for
|
|
1519
|
+
// `aontu view tree m.aon 2>/dev/null` at a terminal, and escapes
|
|
1520
|
+
// into the pipe for `aontu view tree m.aon | less`. The NO_COLOR
|
|
1521
|
+
// rule is the one no-color.org states and err.ts implements:
|
|
1522
|
+
// set, to anything but empty, means no colour.
|
|
1523
|
+
const no = process.env.NO_COLOR;
|
|
1524
|
+
return 'text' === as && true === process.stdout.isTTY
|
|
1525
|
+
&& (null == no || '' === no) ? 'ansi' : undefined;
|
|
1526
|
+
}
|
|
1527
|
+
// The figure was drawn (0, `lossy` included: the loss report says
|
|
1528
|
+
// what it could not draw, and --strict is the gate on that), or the
|
|
1529
|
+
// document could not be drawn (4). An EMPTY figure is a drawing, not
|
|
1530
|
+
// a failure: a model with no links has nothing to draw, honestly.
|
|
1531
|
+
const VIEW_EXIT = {
|
|
1532
|
+
rendered: 0,
|
|
1533
|
+
lossy: 0,
|
|
1534
|
+
error: 4,
|
|
1535
|
+
};
|
|
1536
|
+
// The refusals that are USAGE, not the document's fault: exit 2, as
|
|
1537
|
+
// every other verb's usage errors do.
|
|
1538
|
+
const VIEW_USAGE_CODES = [
|
|
1539
|
+
'view_kind_unknown', 'view_profile_unknown', 'view_rows_exceeded',
|
|
1540
|
+
'view_at_required', 'view_sets_required', 'view_group_required',
|
|
1541
|
+
'view_document_shape', 'view_style_profile', 'view_style_unknown',
|
|
1542
|
+
];
|
|
1422
1543
|
const MOD_HELP = 'aontu mod tidy|verify|vendor|manifest [dir] (try --help)';
|
|
1423
1544
|
// The module tooling (G6 phase 3, ts/src/mod-tool.ts). All LOCAL:
|
|
1424
1545
|
// `tidy` resolves the closure from what is in the stores and rewrites
|
|
@@ -1476,7 +1597,8 @@ function runMod(argv) {
|
|
|
1476
1597
|
const dir = rest[1] ?? '.';
|
|
1477
1598
|
if ('get' === sub || 'publish' === sub) {
|
|
1478
1599
|
process.stderr.write('aontu: mod ' + sub + ' needs a registry client, which this build ' +
|
|
1479
|
-
'does not ship
|
|
1600
|
+
'does not ship; vendor the module by hand and run ' +
|
|
1601
|
+
"'aontu mod tidy'\n");
|
|
1480
1602
|
return 2;
|
|
1481
1603
|
}
|
|
1482
1604
|
if (!MOD_SUBS.includes(sub) || 2 < rest.length) {
|
|
@@ -1690,7 +1812,7 @@ function runReaches(argv) {
|
|
|
1690
1812
|
}
|
|
1691
1813
|
}
|
|
1692
1814
|
if (3 !== rest.length) {
|
|
1693
|
-
process.stderr.write(`aontu: reaches needs two
|
|
1815
|
+
process.stderr.write(`aontu: reaches needs two node paths and one file\n${REACHES_HELP}\n`);
|
|
1694
1816
|
return 2;
|
|
1695
1817
|
}
|
|
1696
1818
|
let src;
|
|
@@ -1732,6 +1854,376 @@ function renderReachesJson(report) {
|
|
|
1732
1854
|
...(null == report.errors ? {} : { errors: report.errors }),
|
|
1733
1855
|
}, 2);
|
|
1734
1856
|
}
|
|
1857
|
+
// ---------------------------------------------------------------------
|
|
1858
|
+
// The tree view (docs/design/VIEWS.0.md, ts/src/view.ts): the drawn
|
|
1859
|
+
// edge set, as text a golden diff can check.
|
|
1860
|
+
function runView(argv) {
|
|
1861
|
+
const trusted = takeTrust(argv);
|
|
1862
|
+
if (null == trusted) {
|
|
1863
|
+
return 2;
|
|
1864
|
+
}
|
|
1865
|
+
argv = trusted.argv;
|
|
1866
|
+
const trust = trusted.trust;
|
|
1867
|
+
const rest = [];
|
|
1868
|
+
let format = 'text';
|
|
1869
|
+
let out = undefined;
|
|
1870
|
+
let check = false;
|
|
1871
|
+
let strict = false;
|
|
1872
|
+
const relations = [];
|
|
1873
|
+
const roots = [];
|
|
1874
|
+
const opts = {};
|
|
1875
|
+
// The style ASKED FOR, which may be `auto` -- a word ViewStyle does
|
|
1876
|
+
// not have, because resolving it is the CLI's job.
|
|
1877
|
+
let style = undefined;
|
|
1878
|
+
// A flag that takes a value, read into `opts` by name.
|
|
1879
|
+
const valued = {
|
|
1880
|
+
'--as': 'as', '--at': 'at', '--order': 'order', '--group-by': 'groupBy',
|
|
1881
|
+
'--label': 'label', '--sets': 'sets', '--member': 'member',
|
|
1882
|
+
'--universe': 'universe', '--profile': 'profile', '--views': 'views',
|
|
1883
|
+
'--edges': 'edges',
|
|
1884
|
+
};
|
|
1885
|
+
const counted = {
|
|
1886
|
+
'--max-rows': 'maxRows', '--max-cols': 'maxCols',
|
|
1887
|
+
'--min-degree': 'minDegree', '--min-size': 'minSize',
|
|
1888
|
+
'--depth': 'depth',
|
|
1889
|
+
};
|
|
1890
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1891
|
+
const arg = argv[i];
|
|
1892
|
+
if ('-h' === arg || '--help' === arg) {
|
|
1893
|
+
process.stdout.write(HELP);
|
|
1894
|
+
return 0;
|
|
1895
|
+
}
|
|
1896
|
+
if ('--format' === arg) {
|
|
1897
|
+
const f = argv[++i];
|
|
1898
|
+
if ('text' !== f && 'json' !== f) {
|
|
1899
|
+
process.stderr.write('aontu: --format needs text or json\n');
|
|
1900
|
+
return 2;
|
|
1901
|
+
}
|
|
1902
|
+
format = f;
|
|
1903
|
+
}
|
|
1904
|
+
else if ('--relation' === arg) {
|
|
1905
|
+
const relation = argv[++i];
|
|
1906
|
+
if (null == relation || '' === relation) {
|
|
1907
|
+
process.stderr.write('aontu: --relation needs a name\n');
|
|
1908
|
+
return 2;
|
|
1909
|
+
}
|
|
1910
|
+
relations.push(relation);
|
|
1911
|
+
}
|
|
1912
|
+
else if ('--root' === arg) {
|
|
1913
|
+
const root = argv[++i];
|
|
1914
|
+
if (null == root) {
|
|
1915
|
+
process.stderr.write('aontu: --root needs a node path\n');
|
|
1916
|
+
return 2;
|
|
1917
|
+
}
|
|
1918
|
+
roots.push(root);
|
|
1919
|
+
}
|
|
1920
|
+
else if ('-o' === arg || '--out' === arg) {
|
|
1921
|
+
out = argv[++i];
|
|
1922
|
+
if (null == out) {
|
|
1923
|
+
process.stderr.write('aontu: --out needs a file\n');
|
|
1924
|
+
return 2;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
else if ('--style' === arg) {
|
|
1928
|
+
style = argv[++i];
|
|
1929
|
+
if (null == style || !VIEW_STYLES.includes(style)) {
|
|
1930
|
+
process.stderr.write(`aontu: --style needs one of ${VIEW_STYLES.join(', ')}\n`);
|
|
1931
|
+
return 2;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
else if ('--check' === arg) {
|
|
1935
|
+
check = true;
|
|
1936
|
+
}
|
|
1937
|
+
else if ('--strict' === arg) {
|
|
1938
|
+
strict = true;
|
|
1939
|
+
}
|
|
1940
|
+
else if ('--closure' === arg) {
|
|
1941
|
+
opts.closure = true;
|
|
1942
|
+
}
|
|
1943
|
+
else if ('--layers' === arg) {
|
|
1944
|
+
const v = argv[++i];
|
|
1945
|
+
if (null == v || '' === v) {
|
|
1946
|
+
process.stderr.write('aontu: --layers needs a comma-separated list\n');
|
|
1947
|
+
return 2;
|
|
1948
|
+
}
|
|
1949
|
+
opts.layers = v.split(',');
|
|
1950
|
+
}
|
|
1951
|
+
else if (undefined !== valued[arg]) {
|
|
1952
|
+
const v = argv[++i];
|
|
1953
|
+
if (null == v || '' === v) {
|
|
1954
|
+
process.stderr.write(`aontu: ${arg} needs a value\n`);
|
|
1955
|
+
return 2;
|
|
1956
|
+
}
|
|
1957
|
+
opts[valued[arg]] = v;
|
|
1958
|
+
}
|
|
1959
|
+
else if (undefined !== counted[arg]) {
|
|
1960
|
+
const v = argv[++i];
|
|
1961
|
+
if (null == v || !/^[0-9]+$/.test(v)) {
|
|
1962
|
+
process.stderr.write(`aontu: ${arg} needs a count\n`);
|
|
1963
|
+
return 2;
|
|
1964
|
+
}
|
|
1965
|
+
opts[counted[arg]] = parseInt(v, 10);
|
|
1966
|
+
}
|
|
1967
|
+
else if (arg.startsWith('-')) {
|
|
1968
|
+
process.stderr.write(`aontu: unknown view option ${arg} (try --help)\n`);
|
|
1969
|
+
return 2;
|
|
1970
|
+
}
|
|
1971
|
+
else {
|
|
1972
|
+
rest.push(arg);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
// ESCAPES NEVER GO INTO A FILE. A pinned golden holding terminal
|
|
1976
|
+
// control codes is not a golden anybody can read, and a byte
|
|
1977
|
+
// comparison against one would fail on the reader's terminal
|
|
1978
|
+
// settings. `auto` resolves to `none` there on its own; asking for
|
|
1979
|
+
// `ansi` explicitly is a usage error rather than a silent downgrade,
|
|
1980
|
+
// so a script that wanted colour is told where it went.
|
|
1981
|
+
if ('ansi' === style && (undefined !== out || undefined !== opts.views)) {
|
|
1982
|
+
process.stderr.write('aontu: --style ansi writes to a terminal, not to a file\n');
|
|
1983
|
+
return 2;
|
|
1984
|
+
}
|
|
1985
|
+
// THE VIEW DOCUMENT draws every figure a document declares, so it
|
|
1986
|
+
// names no kind: the declarations do, one each.
|
|
1987
|
+
if (undefined !== opts.views) {
|
|
1988
|
+
// A declaration names its own profile, so the style is left to
|
|
1989
|
+
// each figure's own default; `--style none` still reaches every
|
|
1990
|
+
// one of them, which is how a host page that binds the CSS
|
|
1991
|
+
// variables asks for eight figures without eight stylesheets.
|
|
1992
|
+
opts.style = viewStyleOf(style, undefined);
|
|
1993
|
+
return runViewSet(rest, opts, trust, { format, check, strict, out });
|
|
1994
|
+
}
|
|
1995
|
+
if (2 > rest.length) {
|
|
1996
|
+
process.stderr.write(`aontu: view needs a kind and a file\n${VIEW_HELP}\n`);
|
|
1997
|
+
return 2;
|
|
1998
|
+
}
|
|
1999
|
+
const kind = rest[0];
|
|
2000
|
+
if (!VIEW_KINDS.includes(kind)) {
|
|
2001
|
+
process.stderr.write(`aontu: unknown view kind ${kind} (the kinds are: ${VIEW_KINDS.join(', ')})\n`);
|
|
2002
|
+
return 2;
|
|
2003
|
+
}
|
|
2004
|
+
if (undefined !== opts.as && !VIEW_PROFILES.includes(opts.as)) {
|
|
2005
|
+
process.stderr.write(`aontu: --as needs one of ${VIEW_PROFILES.join(', ')}\n`);
|
|
2006
|
+
return 2;
|
|
2007
|
+
}
|
|
2008
|
+
if (undefined !== opts.order && 'canon' !== opts.order && 'partition' !== opts.order) {
|
|
2009
|
+
process.stderr.write('aontu: --order needs canon or partition\n');
|
|
2010
|
+
return 2;
|
|
2011
|
+
}
|
|
2012
|
+
if (undefined !== opts.edges && !VIEW_EDGES.includes(opts.edges)) {
|
|
2013
|
+
process.stderr.write(`aontu: --edges needs one of ${VIEW_EDGES.join(', ')}\n`);
|
|
2014
|
+
return 2;
|
|
2015
|
+
}
|
|
2016
|
+
if (undefined !== opts.profile && !['values', 'defaults', 'gen'].includes(opts.profile)) {
|
|
2017
|
+
process.stderr.write('aontu: --profile needs values, defaults or gen\n');
|
|
2018
|
+
return 2;
|
|
2019
|
+
}
|
|
2020
|
+
if ('poset' !== kind && 2 !== rest.length) {
|
|
2021
|
+
process.stderr.write(`aontu: view ${kind} takes one file\n`);
|
|
2022
|
+
return 2;
|
|
2023
|
+
}
|
|
2024
|
+
if ('graph' === kind) {
|
|
2025
|
+
opts.relations = relations;
|
|
2026
|
+
}
|
|
2027
|
+
else if (1 < relations.length) {
|
|
2028
|
+
process.stderr.write(`aontu: view ${kind} takes one --relation\n`);
|
|
2029
|
+
return 2;
|
|
2030
|
+
}
|
|
2031
|
+
else {
|
|
2032
|
+
opts.relation = relations[0];
|
|
2033
|
+
}
|
|
2034
|
+
if (check && undefined === out) {
|
|
2035
|
+
process.stderr.write('aontu: --check needs --out\n');
|
|
2036
|
+
return 2;
|
|
2037
|
+
}
|
|
2038
|
+
const files = rest.slice(1);
|
|
2039
|
+
const srcs = [];
|
|
2040
|
+
for (const file of files) {
|
|
2041
|
+
try {
|
|
2042
|
+
srcs.push((0, node_fs_1.readFileSync)(file, 'utf8'));
|
|
2043
|
+
}
|
|
2044
|
+
catch (err) {
|
|
2045
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2046
|
+
return 2;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
const report = (0, view_1.view)(srcs[0], {
|
|
2050
|
+
...opts,
|
|
2051
|
+
style: viewStyleOf(style, opts.as ?? (0, view_1.viewDefaultProfile)(kind)),
|
|
2052
|
+
kind,
|
|
2053
|
+
path: files[0],
|
|
2054
|
+
roots,
|
|
2055
|
+
trust: verbTrust(trust, entryRootOf(files[0])),
|
|
2056
|
+
docs: files.slice(1).map((path, i) => ({ src: srcs[i + 1], path })),
|
|
2057
|
+
});
|
|
2058
|
+
if ('json' === format) {
|
|
2059
|
+
process.stdout.write(renderViewJson(report) + '\n');
|
|
2060
|
+
}
|
|
2061
|
+
else if ('error' === report.verdict) {
|
|
2062
|
+
process.stderr.write(report.errors.map(renderFinding).join('\n') + '\n');
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
// THE FIGURE AND NOTHING ELSE on stdout (or in the file): stdout is
|
|
2066
|
+
// what a golden diff reads, and a verdict line would be part of
|
|
2067
|
+
// every drawing. The loss report goes to stderr, so a figure
|
|
2068
|
+
// written to a file still tells the reader what it could not draw.
|
|
2069
|
+
const text = report.text + '\n';
|
|
2070
|
+
if (undefined === out) {
|
|
2071
|
+
process.stdout.write(text);
|
|
2072
|
+
}
|
|
2073
|
+
else if (check) {
|
|
2074
|
+
let have = undefined;
|
|
2075
|
+
try {
|
|
2076
|
+
have = (0, node_fs_1.readFileSync)(out, 'utf8');
|
|
2077
|
+
}
|
|
2078
|
+
catch (_err) {
|
|
2079
|
+
// Absent is a mismatch.
|
|
2080
|
+
}
|
|
2081
|
+
if (have !== text) {
|
|
2082
|
+
process.stderr.write(`aontu: ${out} differs from the ${kind} figure\n`);
|
|
2083
|
+
return 1;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
else {
|
|
2087
|
+
(0, node_fs_1.writeFileSync)(out, text, 'utf8');
|
|
2088
|
+
}
|
|
2089
|
+
if (0 < report.loss.length) {
|
|
2090
|
+
process.stderr.write(renderViewLoss(report.loss) + '\n');
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
if ('error' === report.verdict) {
|
|
2094
|
+
const code = report.errors[0]?.code;
|
|
2095
|
+
return VIEW_USAGE_CODES.includes(code) ? 2 : VIEW_EXIT.error;
|
|
2096
|
+
}
|
|
2097
|
+
return strict && 'lossy' === report.verdict ? 1 : VIEW_EXIT[report.verdict];
|
|
2098
|
+
}
|
|
2099
|
+
// `aontu view --views <path> <file>`: every figure the document
|
|
2100
|
+
// declares, from one evaluation, all or nothing.
|
|
2101
|
+
//
|
|
2102
|
+
// A declared `out` is resolved against the DOCUMENT's own directory,
|
|
2103
|
+
// not the caller's: a view document is committed beside the figures it
|
|
2104
|
+
// gates, and a gate that only passes from one working directory is not
|
|
2105
|
+
// a gate.
|
|
2106
|
+
function runViewSet(rest, opts, trust, how) {
|
|
2107
|
+
if (1 !== rest.length) {
|
|
2108
|
+
process.stderr.write('aontu: view --views takes one file\n');
|
|
2109
|
+
return 2;
|
|
2110
|
+
}
|
|
2111
|
+
if (undefined !== how.out) {
|
|
2112
|
+
process.stderr.write('aontu: --out is per figure in a view document; each declares its own\n');
|
|
2113
|
+
return 2;
|
|
2114
|
+
}
|
|
2115
|
+
const file = rest[0];
|
|
2116
|
+
let src;
|
|
2117
|
+
try {
|
|
2118
|
+
src = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
2119
|
+
}
|
|
2120
|
+
catch (err) {
|
|
2121
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2122
|
+
return 2;
|
|
2123
|
+
}
|
|
2124
|
+
const report = (0, view_1.viewSet)(src, {
|
|
2125
|
+
...opts, path: file, trust: verbTrust(trust, entryRootOf(file)),
|
|
2126
|
+
});
|
|
2127
|
+
if ('json' === how.format) {
|
|
2128
|
+
process.stdout.write(renderViewSetJson(report) + '\n');
|
|
2129
|
+
}
|
|
2130
|
+
else if (undefined !== report.errors) {
|
|
2131
|
+
process.stderr.write(report.errors.map(renderFinding).join('\n') + '\n');
|
|
2132
|
+
}
|
|
2133
|
+
else {
|
|
2134
|
+
for (const fig of report.views) {
|
|
2135
|
+
if (undefined !== fig.errors) {
|
|
2136
|
+
process.stderr.write(`${fig.name} (${fig.kind}):\n` +
|
|
2137
|
+
fig.errors.map(renderFinding).join('\n') + '\n');
|
|
2138
|
+
}
|
|
2139
|
+
else if (0 < fig.loss.length) {
|
|
2140
|
+
process.stderr.write(renderViewLoss(fig.loss)
|
|
2141
|
+
.split('\n').map((l) => `${fig.name} ${l}`).join('\n') + '\n');
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
if ('error' === report.verdict) {
|
|
2146
|
+
return setExit(report);
|
|
2147
|
+
}
|
|
2148
|
+
// EVERY FIGURE RENDERED, so the whole set is written -- or, under
|
|
2149
|
+
// --check, the whole set is compared and every difference named.
|
|
2150
|
+
const dir = (0, node_path_1.dirname)((0, node_path_1.resolve)(file));
|
|
2151
|
+
let differ = 0;
|
|
2152
|
+
for (const fig of report.views) {
|
|
2153
|
+
const path = (0, node_path_1.resolve)(dir, fig.out);
|
|
2154
|
+
const text = fig.text + '\n';
|
|
2155
|
+
if (how.check) {
|
|
2156
|
+
let have = undefined;
|
|
2157
|
+
try {
|
|
2158
|
+
have = (0, node_fs_1.readFileSync)(path, 'utf8');
|
|
2159
|
+
}
|
|
2160
|
+
catch (_err) {
|
|
2161
|
+
// Absent is a mismatch.
|
|
2162
|
+
}
|
|
2163
|
+
if (have !== text) {
|
|
2164
|
+
differ++;
|
|
2165
|
+
process.stderr.write(`aontu: ${fig.out} differs from the ${fig.name} figure\n`);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
else {
|
|
2169
|
+
try {
|
|
2170
|
+
(0, node_fs_1.writeFileSync)(path, text, 'utf8');
|
|
2171
|
+
}
|
|
2172
|
+
catch (err) {
|
|
2173
|
+
process.stderr.write(`aontu: cannot write ${err.path}: ${err.message}\n`);
|
|
2174
|
+
return 2;
|
|
2175
|
+
}
|
|
2176
|
+
if ('json' !== how.format) {
|
|
2177
|
+
process.stderr.write(`wrote ${fig.out} ${fig.name} (${fig.kind})\n`);
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
if (0 < differ) {
|
|
2182
|
+
return 1;
|
|
2183
|
+
}
|
|
2184
|
+
return how.strict && 'lossy' === report.verdict ? 1 : VIEW_EXIT[report.verdict];
|
|
2185
|
+
}
|
|
2186
|
+
// A set's exit code is the worst of its figures': a usage refusal
|
|
2187
|
+
// anywhere is usage, and any other refusal is the document's fault.
|
|
2188
|
+
function setExit(report) {
|
|
2189
|
+
const codes = [
|
|
2190
|
+
...(report.errors ?? []),
|
|
2191
|
+
...report.views.flatMap((v) => v.errors ?? []),
|
|
2192
|
+
].map((e) => e.code);
|
|
2193
|
+
return codes.some((c) => VIEW_USAGE_CODES.includes(c))
|
|
2194
|
+
? 2 : VIEW_EXIT.error;
|
|
2195
|
+
}
|
|
2196
|
+
function renderViewSetJson(report) {
|
|
2197
|
+
return (0, aontu_1.exactJSON)({
|
|
2198
|
+
aontu: { version: version(), verb: 'view' },
|
|
2199
|
+
verdict: report.verdict,
|
|
2200
|
+
views: report.views.map((v) => ({
|
|
2201
|
+
name: v.name,
|
|
2202
|
+
kind: v.kind,
|
|
2203
|
+
out: v.out,
|
|
2204
|
+
verdict: v.verdict,
|
|
2205
|
+
...(null == v.text ? {} : { text: v.text }),
|
|
2206
|
+
loss: v.loss,
|
|
2207
|
+
...(null == v.errors ? {} : { errors: v.errors }),
|
|
2208
|
+
})),
|
|
2209
|
+
...(null == report.errors ? {} : { errors: report.errors }),
|
|
2210
|
+
}, 2);
|
|
2211
|
+
}
|
|
2212
|
+
// One line per code: the code, the count, and the detail if any.
|
|
2213
|
+
function renderViewLoss(loss) {
|
|
2214
|
+
return loss.map((l) => `${l.code} ${l.count}` +
|
|
2215
|
+
(undefined === l.detail ? '' : ' ' + l.detail.join(' '))).join('\n');
|
|
2216
|
+
}
|
|
2217
|
+
function renderViewJson(report) {
|
|
2218
|
+
return (0, aontu_1.exactJSON)({
|
|
2219
|
+
aontu: { version: version(), verb: 'view' },
|
|
2220
|
+
kind: report.kind,
|
|
2221
|
+
verdict: report.verdict,
|
|
2222
|
+
...(null == report.text ? {} : { text: report.text }),
|
|
2223
|
+
loss: report.loss,
|
|
2224
|
+
...(null == report.errors ? {} : { errors: report.errors }),
|
|
2225
|
+
}, 2);
|
|
2226
|
+
}
|
|
1735
2227
|
function renderRelationsText(report) {
|
|
1736
2228
|
const head = `verdict: ${report.verdict}`;
|
|
1737
2229
|
// WHY, when the document could not be evaluated at all: rendered as
|
|
@@ -1745,11 +2237,8 @@ function renderRelationsText(report) {
|
|
|
1745
2237
|
}
|
|
1746
2238
|
const lines = report.findings.map((f) => 'relation_cycle' === f.code
|
|
1747
2239
|
? `${f.at} ${f.relation}: cycle ${f.detail.join(' -> ')}`
|
|
1748
|
-
:
|
|
1749
|
-
|
|
1750
|
-
`${f.relation} targets (${f.detail[2]})`
|
|
1751
|
-
: `${f.at} ${f.relation}: ${f.detail[1]} does not list ` +
|
|
1752
|
-
`${f.detail[0]} under ${f.detail[2]}`);
|
|
2240
|
+
: `${f.at} ${f.relation}: ${f.detail[1]} does not list ` +
|
|
2241
|
+
`${f.detail[0]} under ${f.detail[2]}`);
|
|
1753
2242
|
return [head, ''].concat(lines).join('\n');
|
|
1754
2243
|
}
|
|
1755
2244
|
function renderRelationsJson(report) {
|
|
@@ -2468,6 +2957,9 @@ function main(argv) {
|
|
|
2468
2957
|
if ('reaches' === argv[2]) {
|
|
2469
2958
|
return finish(runReaches(argv.slice(3)));
|
|
2470
2959
|
}
|
|
2960
|
+
if ('view' === argv[2]) {
|
|
2961
|
+
return finish(runView(argv.slice(3)));
|
|
2962
|
+
}
|
|
2471
2963
|
if ('trim' === argv[2]) {
|
|
2472
2964
|
return finish(runTrim(argv.slice(3)));
|
|
2473
2965
|
}
|
|
@@ -2546,5 +3038,5 @@ function main(argv) {
|
|
|
2546
3038
|
else {
|
|
2547
3039
|
runStdin(mode, trust).then((code) => finish(code));
|
|
2548
3040
|
}
|
|
2549
|
-
} /* node:coverage ignore next
|
|
3041
|
+
} /* node:coverage ignore next 16 */
|
|
2550
3042
|
//# sourceMappingURL=cli.js.map
|