@loomcli/core 0.6.0 → 0.8.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/NOTICE +34 -0
- package/dist/application.d.ts +11 -6
- package/dist/application.js +57 -19
- package/dist/capture.d.ts +65 -0
- package/dist/capture.js +99 -0
- package/dist/chain.d.ts +28 -17
- package/dist/chain.js +11 -10
- package/dist/command-rules.d.ts +1 -1
- package/dist/command-rules.js +2 -2
- package/dist/command.d.ts +31 -47
- package/dist/command.js +204 -209
- package/dist/errors.d.ts +22 -21
- package/dist/errors.js +38 -18
- package/dist/facts.d.ts +5 -0
- package/dist/facts.js +8 -1
- package/dist/globals.d.ts +48 -22
- package/dist/globals.js +72 -29
- package/dist/glyphs.generated.js +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -1
- package/dist/input-rules.d.ts +20 -2
- package/dist/input-rules.js +47 -5
- package/dist/inspect.d.ts +33 -17
- package/dist/inspect.js +74 -87
- package/dist/locate.js +52 -60
- package/dist/options.d.ts +101 -83
- package/dist/options.js +311 -267
- package/dist/parse.d.ts +162 -0
- package/dist/parse.js +601 -0
- package/dist/plain.d.ts +52 -2
- package/dist/plain.js +228 -2
- package/dist/plugin-rules.d.ts +8 -4
- package/dist/plugin-rules.js +13 -9
- package/dist/plugin-settings.d.ts +18 -0
- package/dist/plugin-settings.js +38 -0
- package/dist/plugin.d.ts +32 -27
- package/dist/plugin.js +107 -89
- package/dist/sources.d.ts +18 -9
- package/dist/sources.js +50 -20
- package/dist/style-layout.js +2 -2
- package/dist/style-width.d.ts +13 -0
- package/dist/style-width.js +170 -0
- package/dist/types.d.ts +70 -30
- package/dist/unicode.generated.d.ts +27 -0
- package/dist/unicode.generated.js +1036 -0
- package/dist/validation.d.ts +108 -34
- package/dist/validation.js +282 -125
- package/dist/view.d.ts +16 -11
- package/dist/view.js +13 -4
- package/licenses/unicode-LICENSE.txt +41 -0
- package/licenses/uucode-LICENSE.md +35 -0
- package/package.json +9 -5
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
Ported from the grapheme width iterator of @rockorager/uucode 2.2.1, src/width.ts.
|
|
3
|
+
Copyright (c) 2026 Tim Culverhouse. Licensed under the MIT License,
|
|
4
|
+
in licenses/uucode-LICENSE.md of @loomcli/core.
|
|
5
|
+
*/
|
|
6
|
+
import { graphemeTable, widthTable } from './unicode.generated.js';
|
|
7
|
+
/** The break state after a regional indicator, which pairs with the next one into a flag. */
|
|
8
|
+
const regionalIndicatorState = 1;
|
|
9
|
+
/** The break state inside an extended pictographic sequence, which a ZWJ continues. */
|
|
10
|
+
const pictographicState = 2;
|
|
11
|
+
// The table members, read once, so each lookup indexes the arrays directly.
|
|
12
|
+
const { stage1, stage1Shift, stage2, stage2Mask, stage3, widthMask, zeroWidthFlag, emojiVSFlag } = widthTable;
|
|
13
|
+
const { breakTable, graphemeBreakPropertyCount } = graphemeTable;
|
|
14
|
+
/** A code point's packed row: its grapheme break property, width, and emoji flags. */
|
|
15
|
+
function lookup(codePoint) {
|
|
16
|
+
const offset = stage1[codePoint >> stage1Shift] ?? 0;
|
|
17
|
+
return stage3[stage2[offset + (codePoint & stage2Mask)] ?? 0] ?? 0;
|
|
18
|
+
}
|
|
19
|
+
/** The row an empty string starts from: the Other break property at width one. */
|
|
20
|
+
const defaultRow = 1 << 5;
|
|
21
|
+
const graphemeBreak = (row) => row & 0x1f;
|
|
22
|
+
const rowWidth = (row) => (row >> 5) & widthMask;
|
|
23
|
+
const zeroInGrapheme = (row) => ((row >> 5) & zeroWidthFlag) !== 0;
|
|
24
|
+
const emojiSelectorBase = (row) => ((row >> 8) & emojiVSFlag) !== 0;
|
|
25
|
+
/** The next break state shifted left once, with whether a cluster boundary falls between. */
|
|
26
|
+
function transition(before, after, state) {
|
|
27
|
+
const count = graphemeBreakPropertyCount;
|
|
28
|
+
return breakTable[(state * count + before) * count + after] ?? 0;
|
|
29
|
+
}
|
|
30
|
+
/** A cursor at the start of a run, with the run's first code point read ahead. */
|
|
31
|
+
function cursor(text, start) {
|
|
32
|
+
const hasNext = start < text.length;
|
|
33
|
+
const codePoint = hasNext ? (text.codePointAt(start) ?? 0) : 0;
|
|
34
|
+
return {
|
|
35
|
+
codePoint: 0,
|
|
36
|
+
hasNext,
|
|
37
|
+
index: start,
|
|
38
|
+
isBreak: false,
|
|
39
|
+
nextCodePoint: codePoint,
|
|
40
|
+
nextIndex: hasNext ? start + (codePoint > 0xff_ff ? 2 : 1) : start,
|
|
41
|
+
nextRow: hasNext ? lookup(codePoint) : defaultRow,
|
|
42
|
+
row: defaultRow,
|
|
43
|
+
state: 0,
|
|
44
|
+
text,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Moves to the next code point and reads whether a cluster boundary follows it. */
|
|
48
|
+
function advance(at) {
|
|
49
|
+
if (!at.hasNext) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
at.codePoint = at.nextCodePoint;
|
|
53
|
+
at.row = at.nextRow;
|
|
54
|
+
const index = at.nextIndex;
|
|
55
|
+
at.index = index;
|
|
56
|
+
if (index >= at.text.length) {
|
|
57
|
+
at.hasNext = false;
|
|
58
|
+
at.isBreak = true;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
const first = at.text.charCodeAt(index);
|
|
62
|
+
let codePoint = first;
|
|
63
|
+
let nextIndex = index + 1;
|
|
64
|
+
if (first >= 0xd8_00 && first <= 0xdb_ff && nextIndex < at.text.length) {
|
|
65
|
+
const second = at.text.charCodeAt(nextIndex);
|
|
66
|
+
if (second >= 0xdc_00 && second <= 0xdf_ff) {
|
|
67
|
+
codePoint = ((first - 0xd8_00) << 10) + second - 0xdc_00 + 0x1_00_00;
|
|
68
|
+
nextIndex += 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const row = lookup(codePoint);
|
|
72
|
+
const packed = transition(graphemeBreak(at.row), graphemeBreak(row), at.state);
|
|
73
|
+
at.state = packed >> 1;
|
|
74
|
+
at.nextCodePoint = codePoint;
|
|
75
|
+
at.nextIndex = nextIndex;
|
|
76
|
+
at.nextRow = row;
|
|
77
|
+
at.isBreak = (packed & 1) !== 0;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
/** The width of the next grapheme cluster, leaving the cursor at its end. */
|
|
81
|
+
function clusterWidth(at) {
|
|
82
|
+
if (!advance(at)) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
const standalone = rowWidth(at.row);
|
|
86
|
+
if (at.isBreak) {
|
|
87
|
+
return standalone;
|
|
88
|
+
}
|
|
89
|
+
let width = zeroInGrapheme(at.row) ? 0 : standalone;
|
|
90
|
+
let previousRow = at.row;
|
|
91
|
+
let previousState = at.state;
|
|
92
|
+
for (;;) {
|
|
93
|
+
if (!advance(at)) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
switch (at.codePoint) {
|
|
97
|
+
case 0xfe_0f: {
|
|
98
|
+
if (emojiSelectorBase(previousRow)) {
|
|
99
|
+
width = 2;
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case 0xfe_0e: {
|
|
104
|
+
if (emojiSelectorBase(previousRow)) {
|
|
105
|
+
width = 1;
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 0x20_0d: {
|
|
110
|
+
if (previousState === pictographicState && !at.isBreak) {
|
|
111
|
+
if (!advance(at) || at.isBreak) {
|
|
112
|
+
return width;
|
|
113
|
+
}
|
|
114
|
+
previousRow = at.row;
|
|
115
|
+
previousState = at.state;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 0x1_f3_fb:
|
|
121
|
+
case 0x1_f3_fc:
|
|
122
|
+
case 0x1_f3_fd:
|
|
123
|
+
case 0x1_f3_fe:
|
|
124
|
+
case 0x1_f3_ff: {
|
|
125
|
+
width = 2;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
default: {
|
|
129
|
+
if (previousState === regionalIndicatorState) {
|
|
130
|
+
width = 2;
|
|
131
|
+
}
|
|
132
|
+
else if (!zeroInGrapheme(at.row)) {
|
|
133
|
+
width += rowWidth(at.row);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (at.isBreak) {
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
previousRow = at.row;
|
|
141
|
+
previousState = at.state;
|
|
142
|
+
}
|
|
143
|
+
return width;
|
|
144
|
+
}
|
|
145
|
+
/** Whether the character at an index is printable ASCII that no non-ASCII character follows. */
|
|
146
|
+
function asciiAlone(text, index) {
|
|
147
|
+
const code = text.charCodeAt(index);
|
|
148
|
+
return (code >= 0x20 && code < 0x7f && (index + 1 >= text.length || text.charCodeAt(index + 1) < 0x80));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Each grapheme cluster of a string with the terminal columns it occupies. Printable ASCII that no
|
|
152
|
+
* non-ASCII character follows is its own one-column cluster. Any other run of clusters is read by
|
|
153
|
+
* one cursor, which starts at the run and carries the break state from cluster to cluster.
|
|
154
|
+
*/
|
|
155
|
+
export function* graphemeWidths(text) {
|
|
156
|
+
let start = 0;
|
|
157
|
+
while (start < text.length) {
|
|
158
|
+
if (asciiAlone(text, start)) {
|
|
159
|
+
yield { end: start + 1, start, width: 1 };
|
|
160
|
+
start += 1;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const at = cursor(text, start);
|
|
164
|
+
do {
|
|
165
|
+
const width = clusterWidth(at);
|
|
166
|
+
yield { end: at.index, start, width };
|
|
167
|
+
start = at.index;
|
|
168
|
+
} while (start < text.length && !asciiAlone(text, start));
|
|
169
|
+
}
|
|
170
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,12 +8,18 @@ import type { RenderingPolicy } from './rendering.js';
|
|
|
8
8
|
import type { ContextualStyle } from './style.js';
|
|
9
9
|
type LowercaseLetter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
|
|
10
10
|
type ShortAlias = LowercaseLetter | Uppercase<LowercaseLetter>;
|
|
11
|
+
/**
|
|
12
|
+
* The spellings an option declares beyond its long form. `aliases` adds a long spelling for each
|
|
13
|
+
* name, so `shortOnly`, which removes every long spelling, never declares one.
|
|
14
|
+
*/
|
|
11
15
|
type OptionSpelling = {
|
|
12
16
|
short?: ShortAlias;
|
|
13
17
|
shortOnly?: false;
|
|
18
|
+
aliases?: readonly string[];
|
|
14
19
|
} | {
|
|
15
20
|
short: ShortAlias;
|
|
16
21
|
shortOnly: true;
|
|
22
|
+
aliases?: never;
|
|
17
23
|
};
|
|
18
24
|
type Presence = {
|
|
19
25
|
required: true;
|
|
@@ -48,6 +54,24 @@ type Omission = {
|
|
|
48
54
|
} | {
|
|
49
55
|
validateOmitted?: false;
|
|
50
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* The presence rules a global option never declares, because its validation runs on every Command.
|
|
59
|
+
* `GlobalOptionConfig` and `GlobalOmissionConstraint` both read the rule from here.
|
|
60
|
+
*/
|
|
61
|
+
type PresenceRuleKey = 'required' | 'validateOmitted';
|
|
62
|
+
/** The fault each presence rule names when a global option declares it. */
|
|
63
|
+
interface PresenceRuleFaults {
|
|
64
|
+
required: {
|
|
65
|
+
'A global option declares no required; the Commands that read it check for it': never;
|
|
66
|
+
};
|
|
67
|
+
validateOmitted: {
|
|
68
|
+
'A global option declares no validateOmitted; its omission is plain absence': never;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** The first presence rule a config declares, in the order the faults name them. */
|
|
72
|
+
type DeclaredPresenceRule<Config> = {
|
|
73
|
+
[Key in PresenceRuleKey]: [Extract<Config, Record<Key, unknown>>] extends [never] ? never : Key;
|
|
74
|
+
}[PresenceRuleKey];
|
|
51
75
|
/**
|
|
52
76
|
* The one-line summary every projection reads. It is a core fact: optional, and a string that holds
|
|
53
77
|
* a character other than whitespace and no line terminator.
|
|
@@ -156,8 +180,11 @@ export interface InputIdentity {
|
|
|
156
180
|
export interface SuppliedInputs {
|
|
157
181
|
/** Raw positional values of the routed Command: one string, or the tokens of a variadic. */
|
|
158
182
|
args: Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
159
|
-
/**
|
|
160
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Raw option values, globals and locals: a string, every occurrence, a Boolean presence, or the
|
|
185
|
+
* number of times a counted option was supplied.
|
|
186
|
+
*/
|
|
187
|
+
options: Readonly<Record<string, string | readonly string[] | boolean | number | undefined>>;
|
|
161
188
|
}
|
|
162
189
|
/**
|
|
163
190
|
* What core knows when it calls one schema. A default validates before any token is read, so its
|
|
@@ -185,7 +212,7 @@ export interface ViewContext {
|
|
|
185
212
|
export interface View<Data> {
|
|
186
213
|
render: (data: Readonly<Data>, context: ViewContext) => string;
|
|
187
214
|
/** A view has one shape; the row view of Results is the other. */
|
|
188
|
-
row?:
|
|
215
|
+
row?: undefined;
|
|
189
216
|
}
|
|
190
217
|
/**
|
|
191
218
|
* A row view renders a sequence one row at a time.
|
|
@@ -197,7 +224,7 @@ export interface RowView<Row> {
|
|
|
197
224
|
head?: (context: ViewContext) => string;
|
|
198
225
|
tail?: (count: number, context: ViewContext) => string;
|
|
199
226
|
/** A row view has one shape; the whole view of Rendered output is the other. */
|
|
200
|
-
render?:
|
|
227
|
+
render?: undefined;
|
|
201
228
|
}
|
|
202
229
|
/** The views record of a value result: every entry renders the whole value. */
|
|
203
230
|
export type ResultViews<Value> = Readonly<Record<string, View<Value>>>;
|
|
@@ -317,7 +344,7 @@ export interface ResultBinding {
|
|
|
317
344
|
/**
|
|
318
345
|
* The routed Command's invocation after parsing and validation, which every middleware reads. The
|
|
319
346
|
* values are what the action receives, the output of each declaration's schema, for that Command's
|
|
320
|
-
* own arguments and local options; global
|
|
347
|
+
* own arguments and local options; global option values are not here. The records are
|
|
321
348
|
* untyped and frozen, because a middleware runs ahead of every action and the graph carries no
|
|
322
349
|
* type for a value.
|
|
323
350
|
*/
|
|
@@ -341,6 +368,8 @@ export type StringOption = OptionSpelling & Presence & Multiplicity & Omission &
|
|
|
341
368
|
type: 'string';
|
|
342
369
|
polarity?: never;
|
|
343
370
|
validate?: StandardSchemaV1;
|
|
371
|
+
/** The value a bare spelling supplies, so an explicit value is attached to the spelling. */
|
|
372
|
+
implied?: string;
|
|
344
373
|
};
|
|
345
374
|
/** A variadic argument collects the remaining tokens, so it follows the multiple option rules. */
|
|
346
375
|
export type VariadicArgument = Presence & Described & ArgumentExtensions & {
|
|
@@ -357,6 +386,19 @@ export type ValidatedValue<Config, Raw> = Config extends unknown ? 'validate' ex
|
|
|
357
386
|
export type DefaultConstraint<Config> = Config extends unknown ? Config & {
|
|
358
387
|
default?: 'validate' extends keyof Config ? PerValue<Config, SchemaInput<Config['validate']>> : RawValue<Config>;
|
|
359
388
|
} : never;
|
|
389
|
+
/**
|
|
390
|
+
* An implied value is the string an operator would otherwise attach, so it must be a string the
|
|
391
|
+
* validator's input type accepts, as a default must be. A multiple option's validator reads one
|
|
392
|
+
* value, so the implied value meets that one value's input type. A validator that declares no types
|
|
393
|
+
* infers `never`, so it states nothing to check against. The key names the fault, the way the
|
|
394
|
+
* other declaration constraints do, because an intersection with the literal would reduce the whole
|
|
395
|
+
* config to `never` and report every key.
|
|
396
|
+
*/
|
|
397
|
+
export type ImpliedConstraint<Config> = Config extends {
|
|
398
|
+
implied: infer Implied;
|
|
399
|
+
} ? 'validate' extends keyof Config ? [SchemaInput<Config['validate']>] extends [never] ? unknown : Implied extends SchemaInput<Config['validate']> ? unknown : {
|
|
400
|
+
'An implied value must be in the validator input type': Config['validate'];
|
|
401
|
+
} : unknown : unknown;
|
|
360
402
|
/**
|
|
361
403
|
* A multiple option or a variadic argument passes each value to its validator alone, so the
|
|
362
404
|
* declared validator must accept one `string`. The key names the fault, the way the other
|
|
@@ -404,19 +446,9 @@ export type ValidateOmittedConstraint<Config> = Config extends {
|
|
|
404
446
|
/**
|
|
405
447
|
* A global option declares no presence rule, so its omission is always plain absence. A union
|
|
406
448
|
* config fails when any member declares the key, and a wide `OptionConfig` passes, because its
|
|
407
|
-
* members only allow the key.
|
|
449
|
+
* members only allow the key. `required` is named first when a config declares both.
|
|
408
450
|
*/
|
|
409
|
-
export type GlobalOmissionConstraint<Config> = [
|
|
410
|
-
required: unknown;
|
|
411
|
-
}>] extends [
|
|
412
|
-
never
|
|
413
|
-
] ? [Extract<Config, {
|
|
414
|
-
validateOmitted: unknown;
|
|
415
|
-
}>] extends [never] ? unknown : {
|
|
416
|
-
'A global option declares no validateOmitted; its omission is plain absence': never;
|
|
417
|
-
} : {
|
|
418
|
-
'A global option declares no required; the Commands that read it check for it': never;
|
|
419
|
-
};
|
|
451
|
+
export type GlobalOmissionConstraint<Config> = [DeclaredPresenceRule<Config>] extends [never] ? unknown : PresenceRuleFaults['required' extends DeclaredPresenceRule<Config> ? 'required' : 'validateOmitted'];
|
|
420
452
|
export type ArgumentValue<Config extends ArgumentConfig> = Config extends {
|
|
421
453
|
variadic: true;
|
|
422
454
|
} ? ValidatedValue<Config, string[]> : ValidatedValue<Config, string> | (Config extends {
|
|
@@ -433,6 +465,7 @@ export type BooleanOption = (OptionSpelling & Described & Listed & EnvBinding &
|
|
|
433
465
|
multiple?: never;
|
|
434
466
|
required?: never;
|
|
435
467
|
validateOmitted?: never;
|
|
468
|
+
implied?: never;
|
|
436
469
|
polarity?: 'positive' | 'negative';
|
|
437
470
|
}) | (Described & Listed & EnvBinding & OptionExtensions & {
|
|
438
471
|
type: 'boolean';
|
|
@@ -441,27 +474,34 @@ export type BooleanOption = (OptionSpelling & Described & Listed & EnvBinding &
|
|
|
441
474
|
multiple?: never;
|
|
442
475
|
required?: never;
|
|
443
476
|
validateOmitted?: never;
|
|
477
|
+
implied?: never;
|
|
444
478
|
polarity: 'both';
|
|
445
479
|
short?: ShortAlias;
|
|
446
480
|
shortOnly?: false;
|
|
481
|
+
aliases?: readonly string[];
|
|
447
482
|
});
|
|
448
|
-
export type OptionConfig = StringOption | BooleanOption;
|
|
449
483
|
/**
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* where the validation context every schema is promised cannot exist. Its middleware interprets
|
|
453
|
-
* the value.
|
|
454
|
-
* A Boolean plugin option is an ordinary `BooleanOption`, which already declares none of them.
|
|
484
|
+
* A counted option takes no value and reads how many times it was supplied, across every spelling,
|
|
485
|
+
* so it declares no validator, default, presence rule, collection, polarity, or implied value.
|
|
455
486
|
*/
|
|
456
|
-
export type
|
|
457
|
-
type: '
|
|
458
|
-
default?: string | string[];
|
|
459
|
-
polarity?: never;
|
|
460
|
-
required?: never;
|
|
487
|
+
export type CountOption = OptionSpelling & Described & Listed & EnvBinding & OptionExtensions & {
|
|
488
|
+
type: 'count';
|
|
461
489
|
validate?: never;
|
|
490
|
+
default?: never;
|
|
491
|
+
multiple?: never;
|
|
492
|
+
required?: never;
|
|
462
493
|
validateOmitted?: never;
|
|
494
|
+
polarity?: never;
|
|
495
|
+
implied?: never;
|
|
463
496
|
};
|
|
464
|
-
export type
|
|
497
|
+
export type OptionConfig = StringOption | BooleanOption | CountOption;
|
|
498
|
+
/**
|
|
499
|
+
* The configuration of a global option a plugin declares: everything `option()` takes except the
|
|
500
|
+
* presence rules, which a global option never declares, because its validation runs on every
|
|
501
|
+
* Command. `globalOption()` states the same rule through `GlobalOmissionConstraint`, which also
|
|
502
|
+
* accepts a config typed as the wide `OptionConfig`.
|
|
503
|
+
*/
|
|
504
|
+
export type GlobalOptionConfig = OptionConfig & Readonly<Partial<Record<PresenceRuleKey, never>>>;
|
|
465
505
|
export type OptionValue<Config extends OptionConfig> = Config extends StringOption ? Config extends {
|
|
466
506
|
multiple: true;
|
|
467
507
|
} ? ValidatedValue<Config, string[]> : ValidatedValue<Config, string> | (Config extends {
|
|
@@ -470,7 +510,7 @@ export type OptionValue<Config extends OptionConfig> = Config extends StringOpti
|
|
|
470
510
|
default: unknown;
|
|
471
511
|
} | {
|
|
472
512
|
validateOmitted: true;
|
|
473
|
-
} ? never : undefined) : boolean;
|
|
513
|
+
} ? never : undefined) : Config extends CountOption ? number : boolean;
|
|
474
514
|
/**
|
|
475
515
|
* What an action receives. `graph` is the frozen graph `inspect()` returns for this run, and
|
|
476
516
|
* `command` is the routed node inside it: the same two values the run's middleware receive.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
The tables derive from the Unicode Character Database.
|
|
3
|
+
Copyright © 1991-2025 Unicode, Inc. Licensed under the Unicode License v3,
|
|
4
|
+
in licenses/unicode-LICENSE.txt of @loomcli/core.
|
|
5
|
+
|
|
6
|
+
They are generated from the tables of @rockorager/uucode.
|
|
7
|
+
Copyright (c) 2026 Tim Culverhouse. Licensed under the MIT License,
|
|
8
|
+
in licenses/uucode-LICENSE.md of @loomcli/core.
|
|
9
|
+
*/
|
|
10
|
+
/** The grapheme break state machine, indexed by state and two break properties. */
|
|
11
|
+
export declare const graphemeTable: {
|
|
12
|
+
breakStateCount: number;
|
|
13
|
+
breakTable: Uint8Array<ArrayBuffer>;
|
|
14
|
+
graphemeBreakPropertyCount: number;
|
|
15
|
+
};
|
|
16
|
+
/** Each code point's width and grapheme break property, in a three-stage lookup. */
|
|
17
|
+
export declare const widthTable: {
|
|
18
|
+
emojiVSFlag: number;
|
|
19
|
+
maxCodePoint: number;
|
|
20
|
+
stage1: Uint16Array<ArrayBuffer>;
|
|
21
|
+
stage1Shift: number;
|
|
22
|
+
stage2: Uint8Array<ArrayBuffer>;
|
|
23
|
+
stage2Mask: number;
|
|
24
|
+
stage3: Uint16Array<ArrayBuffer>;
|
|
25
|
+
widthMask: number;
|
|
26
|
+
zeroWidthFlag: number;
|
|
27
|
+
};
|