@fnndsc/brasa 0.31.4 → 0.32.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.
Files changed (68) hide show
  1. package/dist/buildinfo.json +1 -1
  2. package/dist/builtins/fs/pull.js +16 -0
  3. package/dist/builtins/fs/pull.js.map +1 -1
  4. package/dist/builtins/games/bytes.d.ts +21 -0
  5. package/dist/builtins/games/bytes.js +224 -0
  6. package/dist/builtins/games/bytes.js.map +1 -0
  7. package/dist/builtins/games/chimes.d.ts +64 -0
  8. package/dist/builtins/games/chimes.js +223 -0
  9. package/dist/builtins/games/chimes.js.map +1 -0
  10. package/dist/builtins/games/cowsay.d.ts +36 -0
  11. package/dist/builtins/games/cowsay.js +127 -0
  12. package/dist/builtins/games/cowsay.js.map +1 -0
  13. package/dist/builtins/games/figlet.d.ts +25 -0
  14. package/dist/builtins/games/figlet.js +109 -0
  15. package/dist/builtins/games/figlet.js.map +1 -0
  16. package/dist/builtins/games/lab.d.ts +51 -0
  17. package/dist/builtins/games/lab.js +161 -0
  18. package/dist/builtins/games/lab.js.map +1 -0
  19. package/dist/builtins/games/lolcat.d.ts +26 -0
  20. package/dist/builtins/games/lolcat.js +71 -0
  21. package/dist/builtins/games/lolcat.js.map +1 -0
  22. package/dist/builtins/games/morse.d.ts +18 -0
  23. package/dist/builtins/games/morse.js +46 -0
  24. package/dist/builtins/games/morse.js.map +1 -0
  25. package/dist/builtins/games/numbers.d.ts +55 -0
  26. package/dist/builtins/games/numbers.js +270 -0
  27. package/dist/builtins/games/numbers.js.map +1 -0
  28. package/dist/builtins/games/play.d.ts +53 -0
  29. package/dist/builtins/games/play.js +228 -0
  30. package/dist/builtins/games/play.js.map +1 -0
  31. package/dist/builtins/games/qr.d.ts +40 -0
  32. package/dist/builtins/games/qr.js +336 -0
  33. package/dist/builtins/games/qr.js.map +1 -0
  34. package/dist/builtins/games/shelf.d.ts +27 -0
  35. package/dist/builtins/games/shelf.js +71 -0
  36. package/dist/builtins/games/shelf.js.map +1 -0
  37. package/dist/builtins/games/show.d.ts +32 -0
  38. package/dist/builtins/games/show.js +68 -0
  39. package/dist/builtins/games/show.js.map +1 -0
  40. package/dist/builtins/games/sky.d.ts +69 -0
  41. package/dist/builtins/games/sky.js +190 -0
  42. package/dist/builtins/games/sky.js.map +1 -0
  43. package/dist/builtins/games/stdin.d.ts +34 -0
  44. package/dist/builtins/games/stdin.js +48 -0
  45. package/dist/builtins/games/stdin.js.map +1 -0
  46. package/dist/builtins/games/text.d.ts +46 -0
  47. package/dist/builtins/games/text.js +133 -0
  48. package/dist/builtins/games/text.js.map +1 -0
  49. package/dist/builtins/games/wtf.d.ts +13 -0
  50. package/dist/builtins/games/wtf.data.d.ts +12 -0
  51. package/dist/builtins/games/wtf.data.js +70 -0
  52. package/dist/builtins/games/wtf.data.js.map +1 -0
  53. package/dist/builtins/games/wtf.js +45 -0
  54. package/dist/builtins/games/wtf.js.map +1 -0
  55. package/dist/builtins/help.d.ts +8 -0
  56. package/dist/builtins/help.js +296 -0
  57. package/dist/builtins/help.js.map +1 -1
  58. package/dist/core/dispatch.js +125 -9
  59. package/dist/core/dispatch.js.map +1 -1
  60. package/dist/core/engine.js +1 -0
  61. package/dist/core/engine.js.map +1 -1
  62. package/dist/core/surface.d.ts +14 -0
  63. package/dist/core/surface.js.map +1 -1
  64. package/dist/lib/vfs/providers/static.js +15 -1
  65. package/dist/lib/vfs/providers/static.js.map +1 -1
  66. package/dist/lib/vfs/providers/static_content.js +2 -2
  67. package/dist/lib/vfs/providers/static_content.js.map +1 -1
  68. package/package.json +4 -4
@@ -0,0 +1,223 @@
1
+ /**
2
+ * @file Chimes: `timer`, `leave` and `stopwatch`.
3
+ *
4
+ * A chime is a word said later. The kernel keeps it on a clock and, when
5
+ * the time comes, publishes it on the ambient channel as an envelope of
6
+ * its own — the same road a refreshed listing takes — so every surface on
7
+ * the session hears it: ARGUS notes it in the console and speaks it, a
8
+ * remote chell prints it. Nothing holds the lane while it waits. A chime
9
+ * lives as long as the process: a session's chimes end with it.
10
+ *
11
+ * @module
12
+ */
13
+ import { envelope_ok, envelope_error } from '@fnndsc/cumin';
14
+ import chalk from 'chalk';
15
+ import { ambient_publish } from '../../core/ambient.js';
16
+ /** The longest a chime may wait. */
17
+ export const CHIME_MAX_MS = 24 * 3600 * 1000;
18
+ const pending = new Map();
19
+ let nextId = 1;
20
+ const chime_sound = (chime) => {
21
+ ambient_publish({
22
+ kind: 'envelope',
23
+ envelope: envelope_ok(`${chalk.yellow('🔔')} ${chime.text}\n`, { kind: 'games.chime', data: { id: chime.id, text: chime.text, source: chime.source, at: new Date(chime.at).toISOString() } }),
24
+ });
25
+ };
26
+ /**
27
+ * Sets a chime.
28
+ *
29
+ * @param delayMs - How long from now.
30
+ * @param text - What it says.
31
+ * @param source - What set it.
32
+ * @param sound - How it sounds (the ambient channel by default).
33
+ * @returns The chime.
34
+ */
35
+ export function chime_set(delayMs, text, source, sound = chime_sound) {
36
+ const chime = { id: nextId++, at: Date.now() + delayMs, text, source };
37
+ const handle = setTimeout(() => {
38
+ pending.delete(chime.id);
39
+ sound(chime);
40
+ }, delayMs);
41
+ // A waiting chime must not hold the process open on its own.
42
+ handle.unref();
43
+ pending.set(chime.id, { chime, handle });
44
+ return chime;
45
+ }
46
+ /** The chimes still waiting, soonest first. */
47
+ export function chimes_list() {
48
+ return [...pending.values()].map((p) => p.chime).sort((a, b) => a.at - b.at);
49
+ }
50
+ /**
51
+ * Cancels one chime, or every chime of a source, or all of them.
52
+ *
53
+ * @returns How many were cancelled.
54
+ */
55
+ export function chimes_cancel(which) {
56
+ let count = 0;
57
+ for (const [id, entry] of pending) {
58
+ if (which === 'all' || which === id || which === entry.chime.source) {
59
+ clearTimeout(entry.handle);
60
+ pending.delete(id);
61
+ count++;
62
+ }
63
+ }
64
+ return count;
65
+ }
66
+ /**
67
+ * Reads a duration: `90s`, `5m`, `1h30m`, `2:30` (m:ss), `1:00:00`, or a bare number of minutes.
68
+ *
69
+ * @returns Milliseconds, or null when the words are not a duration.
70
+ */
71
+ export function duration_parse(text) {
72
+ const t = text.trim().toLowerCase();
73
+ if (/^\d+$/.test(t))
74
+ return Number(t) * 60_000;
75
+ const clock = /^(\d+):(\d{1,2})(?::(\d{1,2}))?$/.exec(t);
76
+ if (clock !== null) {
77
+ const parts = [clock[1], clock[2], clock[3]].filter((p) => p !== undefined).map(Number);
78
+ const seconds = parts.length === 3 ? parts[0] * 3600 + parts[1] * 60 + parts[2] : parts[0] * 60 + parts[1];
79
+ return seconds * 1000;
80
+ }
81
+ const units = /^(?:(\d+(?:\.\d+)?)h)?(?:(\d+(?:\.\d+)?)m)?(?:(\d+(?:\.\d+)?)s)?$/.exec(t);
82
+ if (units === null || units[0] === '')
83
+ return null;
84
+ const [, h, m, s] = units;
85
+ return Math.round(((Number(h ?? 0)) * 3600 + Number(m ?? 0) * 60 + Number(s ?? 0)) * 1000);
86
+ }
87
+ /** A span in words: `1h 05m`, `4m 30s`, `12s`. */
88
+ export function span_words(ms) {
89
+ const total = Math.max(0, Math.round(ms / 1000));
90
+ const h = Math.floor(total / 3600);
91
+ const m = Math.floor((total % 3600) / 60);
92
+ const s = total % 60;
93
+ if (h > 0)
94
+ return `${h}h ${String(m).padStart(2, '0')}m`;
95
+ if (m > 0)
96
+ return `${m}m ${String(s).padStart(2, '0')}s`;
97
+ return `${s}s`;
98
+ }
99
+ function chimes_render() {
100
+ const list = chimes_list();
101
+ if (list.length === 0)
102
+ return `${chalk.gray('no chimes waiting')}\n`;
103
+ return list.map((c) => `${String(c.id).padStart(3)} ${c.source.padEnd(5)} in ${span_words(c.at - Date.now()).padEnd(8)} ${c.text}`).join('\n') + '\n';
104
+ }
105
+ /** `timer <duration> [words] | timer | timer cancel [id|all]` */
106
+ export async function builtin_timer(args) {
107
+ if (args.length === 0)
108
+ return envelope_ok(chimes_render(), { kind: 'games.chimes', data: { chimes: chimes_list() } });
109
+ if (args[0] === 'cancel') {
110
+ const which = args[1] === undefined ? 'timer' : args[1] === 'all' ? 'all' : Number(args[1]);
111
+ if (typeof which === 'number' && !Number.isInteger(which))
112
+ return envelope_error('', undefined, 'timer: cancel wants a chime id, or all\n');
113
+ const n = chimes_cancel(which);
114
+ return envelope_ok(`${n} chime${n === 1 ? '' : 's'} cancelled\n`, { kind: 'games.chimes', data: { cancelled: n } });
115
+ }
116
+ const ms = duration_parse(args[0]);
117
+ if (ms === null || ms <= 0)
118
+ return envelope_error('', undefined, `timer: '${args[0]}' is not a duration (try 90s, 5m, 1h30m, 2:30)\n`);
119
+ if (ms > CHIME_MAX_MS)
120
+ return envelope_error('', undefined, 'timer: a day is the most a timer waits\n');
121
+ const words = args.slice(1).join(' ') || `timer: ${span_words(ms)} is up`;
122
+ const chime = chime_set(ms, words, 'timer');
123
+ return envelope_ok(`timer ${chime.id} set: ${span_words(ms)} from now (${new Date(chime.at).toTimeString().slice(0, 8)}) — ${words}\n`, { kind: 'games.chimes', data: { set: chime } });
124
+ }
125
+ /** Reads `+hhmm` (from now) or `hhmm` (a clock time, today or tomorrow) as a delay. */
126
+ export function leave_delay(text, now = new Date()) {
127
+ const m = /^(\+)?(\d{1,2}):?(\d{2})$/.exec(text.trim());
128
+ if (m === null)
129
+ return null;
130
+ const hours = Number(m[2]);
131
+ const minutes = Number(m[3]);
132
+ if (minutes > 59 || hours > 23 && m[1] === undefined)
133
+ return null;
134
+ if (m[1] === '+')
135
+ return (hours * 60 + minutes) * 60_000;
136
+ const at = new Date(now);
137
+ at.setHours(hours, minutes, 0, 0);
138
+ if (at.getTime() <= now.getTime())
139
+ at.setDate(at.getDate() + 1);
140
+ return at.getTime() - now.getTime();
141
+ }
142
+ /** `leave [+hhmm | hhmm] | leave cancel` — BSD's leave: a word five minutes before, one at the time, and one after. */
143
+ export async function builtin_leave(args) {
144
+ if (args.length === 0) {
145
+ const mine = chimes_list().filter((c) => c.source === 'leave');
146
+ if (mine.length === 0)
147
+ return envelope_ok(`${chalk.gray('no leave set (leave +0030, or leave 1730)')}\n`, { kind: 'games.chimes', data: { chimes: [] } });
148
+ const last = mine[mine.length - 1];
149
+ return envelope_ok(`leaving at ${new Date(last.at - 60_000).toTimeString().slice(0, 5)} — in ${span_words(last.at - 60_000 - Date.now())}\n`, { kind: 'games.chimes', data: { chimes: mine } });
150
+ }
151
+ if (args[0] === 'cancel') {
152
+ const n = chimes_cancel('leave');
153
+ return envelope_ok(`${n === 0 ? 'no leave was set' : 'leave cancelled'}\n`, { kind: 'games.chimes', data: { cancelled: n } });
154
+ }
155
+ const delay = leave_delay(args[0]);
156
+ if (delay === null)
157
+ return envelope_error('', undefined, `leave: '${args[0]}' is not a time (leave +hhmm from now, or leave hhmm)\n`);
158
+ chimes_cancel('leave');
159
+ const at = new Date(Date.now() + delay);
160
+ if (delay > 5 * 60_000)
161
+ chime_set(delay - 5 * 60_000, 'You have to leave in 5 minutes.', 'leave');
162
+ if (delay > 60_000)
163
+ chime_set(delay - 60_000, 'Just one more minute!', 'leave');
164
+ chime_set(delay, 'Time to leave!', 'leave');
165
+ chime_set(delay + 60_000, "You're going to be late!", 'leave');
166
+ return envelope_ok(`Alarm set for ${at.toTimeString().slice(0, 5)} (in ${span_words(delay)}).\n`, { kind: 'games.chimes', data: { at: at.toISOString() } });
167
+ }
168
+ const watch = { startedAt: null, accumulated: 0, laps: [] };
169
+ /** The stopwatch's elapsed time now. */
170
+ export function stopwatch_elapsed(now = Date.now()) {
171
+ return watch.accumulated + (watch.startedAt === null ? 0 : now - watch.startedAt);
172
+ }
173
+ /** Resets the stopwatch (a test's seam, and `stopwatch reset`). */
174
+ export function stopwatch_reset() {
175
+ watch.startedAt = null;
176
+ watch.accumulated = 0;
177
+ watch.laps = [];
178
+ }
179
+ const clock_words = (ms) => {
180
+ const total = Math.floor(ms / 1000);
181
+ const h = Math.floor(total / 3600);
182
+ const m = Math.floor((total % 3600) / 60);
183
+ const s = total % 60;
184
+ const tenths = Math.floor((ms % 1000) / 100);
185
+ return `${h > 0 ? `${h}:` : ''}${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}.${tenths}`;
186
+ };
187
+ /** `stopwatch [start|stop|lap|reset]` — bare, it shows the time. */
188
+ export async function builtin_stopwatch(args) {
189
+ const verb = args[0] ?? 'show';
190
+ const now = Date.now();
191
+ const running = watch.startedAt !== null;
192
+ if (verb === 'start') {
193
+ if (running)
194
+ return envelope_ok(`already running: ${clock_words(stopwatch_elapsed(now))}\n`, { kind: 'games.stopwatch', data: { elapsedMs: stopwatch_elapsed(now), running } });
195
+ watch.startedAt = now;
196
+ return envelope_ok(`stopwatch started${watch.accumulated > 0 ? ` (resuming at ${clock_words(watch.accumulated)})` : ''}\n`, { kind: 'games.stopwatch', data: { elapsedMs: watch.accumulated, running: true } });
197
+ }
198
+ if (verb === 'stop') {
199
+ if (!running)
200
+ return envelope_ok(`stopped at ${clock_words(watch.accumulated)}\n`, { kind: 'games.stopwatch', data: { elapsedMs: watch.accumulated, running: false } });
201
+ watch.accumulated += now - watch.startedAt;
202
+ watch.startedAt = null;
203
+ return envelope_ok(`stopped at ${clock_words(watch.accumulated)}\n`, { kind: 'games.stopwatch', data: { elapsedMs: watch.accumulated, running: false } });
204
+ }
205
+ if (verb === 'lap') {
206
+ if (!running)
207
+ return envelope_error('', undefined, 'stopwatch: not running (stopwatch start)\n');
208
+ const elapsed = stopwatch_elapsed(now);
209
+ watch.laps.push(elapsed);
210
+ const previous = watch.laps.length > 1 ? watch.laps[watch.laps.length - 2] : 0;
211
+ return envelope_ok(`lap ${watch.laps.length}: ${clock_words(elapsed - previous)} (${clock_words(elapsed)} total)\n`, { kind: 'games.stopwatch', data: { elapsedMs: elapsed, laps: watch.laps, running } });
212
+ }
213
+ if (verb === 'reset') {
214
+ stopwatch_reset();
215
+ return envelope_ok('stopwatch reset\n', { kind: 'games.stopwatch', data: { elapsedMs: 0, running: false } });
216
+ }
217
+ if (verb !== 'show')
218
+ return envelope_error('', undefined, `stopwatch: unknown word '${verb}' (start, stop, lap, reset)\n`);
219
+ const elapsed = stopwatch_elapsed(now);
220
+ const laps = watch.laps.map((l, i) => ` lap ${i + 1} ${clock_words(l - (watch.laps[i - 1] ?? 0))}`).join('\n');
221
+ return envelope_ok(`${clock_words(elapsed)}${running ? ' (running)' : watch.accumulated > 0 ? ' (stopped)' : ''}\n${laps ? `${laps}\n` : ''}`, { kind: 'games.stopwatch', data: { elapsedMs: elapsed, laps: watch.laps, running } });
222
+ }
223
+ //# sourceMappingURL=chimes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chimes.js","sourceRoot":"","sources":["../../../src/builtins/games/chimes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @file `cowsay`, with the ChRIS brain for a cow.
3
+ *
4
+ * The classic: a speech bubble over a creature. Ours thinks rather than
5
+ * lows — the brain is the mascot, and `fortune | cowsay` is what the shelf
6
+ * is for. `-W N` wraps at N columns; `cowthink` is the same with a thought
7
+ * bubble.
8
+ *
9
+ * @module
10
+ */
11
+ import { CommandEnvelope } from '@fnndsc/cumin';
12
+ /** The brain, as ASCII has long drawn it. */
13
+ export declare const BRAIN: ReadonlyArray<string>;
14
+ /** Default wrap width, as cowsay's. */
15
+ export declare const COWSAY_WIDTH: number;
16
+ /** Wraps text at a width, keeping the lines it already had. */
17
+ export declare function text_wrap(text: string, width: number): string[];
18
+ /**
19
+ * Draws the bubble: said (speech) or thought.
20
+ *
21
+ * @param lines - The wrapped lines.
22
+ * @param thought - True for a thought bubble (round sides, `o` trail).
23
+ */
24
+ export declare function bubble_draw(lines: string[], thought: boolean): string[];
25
+ /**
26
+ * The whole picture: the bubble, its trail, the brain.
27
+ *
28
+ * @param text - What the brain says.
29
+ * @param thought - Thought bubble rather than speech.
30
+ * @param width - Wrap width.
31
+ */
32
+ export declare function cowsay_render(text: string, thought?: boolean, width?: number): string;
33
+ /** `cowsay [-W N] [text]` */
34
+ export declare function builtin_cowsay(args: string[]): Promise<CommandEnvelope>;
35
+ /** `cowthink [-W N] [text]` */
36
+ export declare function builtin_cowthink(args: string[]): Promise<CommandEnvelope>;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @file `cowsay`, with the ChRIS brain for a cow.
3
+ *
4
+ * The classic: a speech bubble over a creature. Ours thinks rather than
5
+ * lows — the brain is the mascot, and `fortune | cowsay` is what the shelf
6
+ * is for. `-W N` wraps at N columns; `cowthink` is the same with a thought
7
+ * bubble.
8
+ *
9
+ * @module
10
+ */
11
+ import { envelope_ok, envelope_error } from '@fnndsc/cumin';
12
+ import { text_input } from './stdin.js';
13
+ /** The brain, as ASCII has long drawn it. */
14
+ export const BRAIN = [
15
+ ' _---~~(~~-_.',
16
+ ' _{ ) )',
17
+ ' , ) -~~- ( ,-\' )_',
18
+ ' ( `-,_..`., )-- \'_,)',
19
+ ' ( ` _) ( -~( -_ `, }',
20
+ ' (_- _ ~_-~~~~`, ,\' )',
21
+ ' `~ -^( __;-,((()))',
22
+ ' ~~~~ {_ -_(())',
23
+ ' `\\ }',
24
+ ' { }',
25
+ ];
26
+ /** Default wrap width, as cowsay's. */
27
+ export const COWSAY_WIDTH = 40;
28
+ /** Wraps text at a width, keeping the lines it already had. */
29
+ export function text_wrap(text, width) {
30
+ const out = [];
31
+ for (const paragraph of text.split('\n')) {
32
+ const words = paragraph.split(/\s+/).filter((w) => w.length > 0);
33
+ if (words.length === 0) {
34
+ out.push('');
35
+ continue;
36
+ }
37
+ let line = '';
38
+ for (const word of words) {
39
+ if (line.length === 0)
40
+ line = word;
41
+ else if (line.length + 1 + word.length <= width)
42
+ line += ` ${word}`;
43
+ else {
44
+ out.push(line);
45
+ line = word;
46
+ }
47
+ }
48
+ out.push(line);
49
+ }
50
+ return out;
51
+ }
52
+ /**
53
+ * Draws the bubble: said (speech) or thought.
54
+ *
55
+ * @param lines - The wrapped lines.
56
+ * @param thought - True for a thought bubble (round sides, `o` trail).
57
+ */
58
+ export function bubble_draw(lines, thought) {
59
+ const width = Math.max(1, ...lines.map((l) => l.length));
60
+ const pad = (l) => l.padEnd(width, ' ');
61
+ const top = ` ${'_'.repeat(width + 2)}`;
62
+ const bottom = ` ${'-'.repeat(width + 2)}`;
63
+ if (thought)
64
+ return [top, ...lines.map((l) => `( ${pad(l)} )`), bottom];
65
+ if (lines.length === 1)
66
+ return [top, `< ${pad(lines[0])} >`, bottom];
67
+ return [
68
+ top,
69
+ ...lines.map((l, i) => {
70
+ const [left, right] = i === 0 ? ['/', '\\'] : i === lines.length - 1 ? ['\\', '/'] : ['|', '|'];
71
+ return `${left} ${pad(l)} ${right}`;
72
+ }),
73
+ bottom,
74
+ ];
75
+ }
76
+ /**
77
+ * The whole picture: the bubble, its trail, the brain.
78
+ *
79
+ * @param text - What the brain says.
80
+ * @param thought - Thought bubble rather than speech.
81
+ * @param width - Wrap width.
82
+ */
83
+ export function cowsay_render(text, thought = false, width = COWSAY_WIDTH) {
84
+ const lines = text_wrap(text, Math.max(8, width));
85
+ const trail = thought ? [' o', ' o'] : [' \\', ' \\'];
86
+ return [...bubble_draw(lines, thought), ...trail, ...BRAIN].join('\n') + '\n';
87
+ }
88
+ /** Parses `-W N` out of the arguments; the rest is the text. */
89
+ function cowsayArgs_parse(args) {
90
+ let width = COWSAY_WIDTH;
91
+ const words = [];
92
+ for (let i = 0; i < args.length; i++) {
93
+ if (args[i] === '-W') {
94
+ const n = Number(args[i + 1]);
95
+ if (!Number.isInteger(n) || n < 8)
96
+ return { refusal: 'cowsay: -W wants a width of 8 or more' };
97
+ width = n;
98
+ i++;
99
+ }
100
+ else if (args[i]?.startsWith('-') && (args[i]?.length ?? 0) > 1) {
101
+ return { refusal: `cowsay: unknown flag '${args[i]}' (only -W N)` };
102
+ }
103
+ else {
104
+ words.push(args[i]);
105
+ }
106
+ }
107
+ return { width, words };
108
+ }
109
+ async function cow_run(args, thought, name) {
110
+ const parsed = cowsayArgs_parse(args);
111
+ if ('refusal' in parsed)
112
+ return envelope_error('', undefined, `${parsed.refusal}\n`);
113
+ const text = text_input(parsed.words);
114
+ if (text === null)
115
+ return envelope_error('', undefined, `${name}: nothing to say (pipe text in, or give it: fortune | ${name})\n`);
116
+ const said = text.replace(/\n$/, '');
117
+ return envelope_ok(cowsay_render(said, thought, parsed.width), { kind: 'games.cowsay', data: { text: said, thought } });
118
+ }
119
+ /** `cowsay [-W N] [text]` */
120
+ export async function builtin_cowsay(args) {
121
+ return cow_run(args, false, 'cowsay');
122
+ }
123
+ /** `cowthink [-W N] [text]` */
124
+ export async function builtin_cowthink(args) {
125
+ return cow_run(args, true, 'cowthink');
126
+ }
127
+ //# sourceMappingURL=cowsay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cowsay.js","sourceRoot":"","sources":["../../../src/builtins/games/cowsay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @file `figlet` and `banner`: big letters.
3
+ *
4
+ * One bundled face, five rows tall, drawn in `#` the way `banner` always
5
+ * was; `figlet` fills with `█` for a solid look. Letters, digits and the
6
+ * punctuation a title needs. A glyph is five strings of equal width; the
7
+ * row of a word is its glyphs' rows side by side with one column between.
8
+ *
9
+ * @module
10
+ */
11
+ import { CommandEnvelope } from '@fnndsc/cumin';
12
+ /** The rows of the face, five. */
13
+ export declare const FACE_ROWS: number;
14
+ /**
15
+ * Sets a text in the face.
16
+ *
17
+ * @param text - The words; lowercase is set as capitals, an unknown character as `?`.
18
+ * @param ink - The character to draw with.
19
+ * @returns The five rows (more for several lines).
20
+ */
21
+ export declare function figlet_render(text: string, ink?: string): string[];
22
+ /** `figlet [text]`: big letters, solid. */
23
+ export declare function builtin_figlet(args: string[]): Promise<CommandEnvelope>;
24
+ /** `banner [text]`: big letters in `#`, as banner always drew them. */
25
+ export declare function builtin_banner(args: string[]): Promise<CommandEnvelope>;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @file `figlet` and `banner`: big letters.
3
+ *
4
+ * One bundled face, five rows tall, drawn in `#` the way `banner` always
5
+ * was; `figlet` fills with `█` for a solid look. Letters, digits and the
6
+ * punctuation a title needs. A glyph is five strings of equal width; the
7
+ * row of a word is its glyphs' rows side by side with one column between.
8
+ *
9
+ * @module
10
+ */
11
+ import { envelope_ok, envelope_error } from '@fnndsc/cumin';
12
+ import { text_input } from './stdin.js';
13
+ /** The face: each glyph five rows, `#` for ink. */
14
+ const FACE = {
15
+ A: [' ### ', '# #', '#####', '# #', '# #'],
16
+ B: ['#### ', '# #', '#### ', '# #', '#### '],
17
+ C: [' ####', '# ', '# ', '# ', ' ####'],
18
+ D: ['#### ', '# #', '# #', '# #', '#### '],
19
+ E: ['#####', '# ', '#### ', '# ', '#####'],
20
+ F: ['#####', '# ', '#### ', '# ', '# '],
21
+ G: [' ####', '# ', '# ##', '# #', ' ####'],
22
+ H: ['# #', '# #', '#####', '# #', '# #'],
23
+ I: ['#####', ' # ', ' # ', ' # ', '#####'],
24
+ J: [' #', ' #', ' #', '# #', ' ### '],
25
+ K: ['# #', '# # ', '### ', '# # ', '# #'],
26
+ L: ['# ', '# ', '# ', '# ', '#####'],
27
+ M: ['# #', '## ##', '# # #', '# #', '# #'],
28
+ N: ['# #', '## #', '# # #', '# ##', '# #'],
29
+ O: [' ### ', '# #', '# #', '# #', ' ### '],
30
+ P: ['#### ', '# #', '#### ', '# ', '# '],
31
+ Q: [' ### ', '# #', '# # #', '# # ', ' ## #'],
32
+ R: ['#### ', '# #', '#### ', '# # ', '# #'],
33
+ S: [' ####', '# ', ' ### ', ' #', '#### '],
34
+ T: ['#####', ' # ', ' # ', ' # ', ' # '],
35
+ U: ['# #', '# #', '# #', '# #', ' ### '],
36
+ V: ['# #', '# #', '# #', ' # # ', ' # '],
37
+ W: ['# #', '# #', '# # #', '## ##', '# #'],
38
+ X: ['# #', ' # # ', ' # ', ' # # ', '# #'],
39
+ Y: ['# #', ' # # ', ' # ', ' # ', ' # '],
40
+ Z: ['#####', ' # ', ' # ', ' # ', '#####'],
41
+ '0': [' ### ', '# ##', '# # #', '## #', ' ### '],
42
+ '1': [' # ', ' ## ', ' # ', ' # ', '#####'],
43
+ '2': [' ### ', '# #', ' ## ', ' # ', '#####'],
44
+ '3': ['#### ', ' #', ' ### ', ' #', '#### '],
45
+ '4': ['# # ', '# # ', '#####', ' # ', ' # '],
46
+ '5': ['#####', '# ', '#### ', ' #', '#### '],
47
+ '6': [' ### ', '# ', '#### ', '# #', ' ### '],
48
+ '7': ['#####', ' #', ' # ', ' # ', ' # '],
49
+ '8': [' ### ', '# #', ' ### ', '# #', ' ### '],
50
+ '9': [' ### ', '# #', ' ####', ' #', ' ### '],
51
+ ' ': [' ', ' ', ' ', ' ', ' '],
52
+ '.': [' ', ' ', ' ', ' ', '#'],
53
+ ',': [' ', ' ', ' ', '#', '#'],
54
+ '!': ['#', '#', '#', ' ', '#'],
55
+ '?': [' ### ', '# #', ' # ', ' ', ' # '],
56
+ '-': [' ', ' ', '#####', ' ', ' '],
57
+ '_': [' ', ' ', ' ', ' ', '#####'],
58
+ ':': [' ', '#', ' ', '#', ' '],
59
+ '/': [' #', ' # ', ' # ', ' # ', '# '],
60
+ '+': [' ', ' # ', '#####', ' # ', ' '],
61
+ '=': [' ', '#####', ' ', '#####', ' '],
62
+ '*': [' ', '# # #', ' ### ', '# # #', ' '],
63
+ '#': [' # # ', '#####', ' # # ', '#####', ' # # '],
64
+ '(': [' #', '# ', '# ', '# ', ' #'],
65
+ ')': ['# ', ' #', ' #', ' #', '# '],
66
+ '\'': ['#', '#', ' ', ' ', ' '],
67
+ '"': ['# #', '# #', ' ', ' ', ' '],
68
+ '&': [' ## ', '# #', ' ## ', '# # ', ' # #'],
69
+ '@': [' ### ', '# ##', '# # #', '# # ', ' ### '],
70
+ '%': ['# #', ' # ', ' # ', ' # ', '# #'],
71
+ };
72
+ /** The rows of the face, five. */
73
+ export const FACE_ROWS = 5;
74
+ /**
75
+ * Sets a text in the face.
76
+ *
77
+ * @param text - The words; lowercase is set as capitals, an unknown character as `?`.
78
+ * @param ink - The character to draw with.
79
+ * @returns The five rows (more for several lines).
80
+ */
81
+ export function figlet_render(text, ink = '#') {
82
+ const rows = [];
83
+ for (const line of text.split('\n')) {
84
+ const glyphs = [...line.toUpperCase()].map((c) => FACE[c] ?? FACE['?']);
85
+ for (let r = 0; r < FACE_ROWS; r++) {
86
+ const row = glyphs.map((g) => g[r] ?? '').join(' ').replace(/#/g, ink).trimEnd();
87
+ rows.push(row);
88
+ }
89
+ rows.push('');
90
+ }
91
+ rows.pop();
92
+ return rows;
93
+ }
94
+ async function big_run(args, ink, name) {
95
+ const text = text_input(args);
96
+ if (text === null)
97
+ return envelope_error('', undefined, `${name}: nothing to set (give words, or pipe them in)\n`);
98
+ const said = text.replace(/\n$/, '');
99
+ return envelope_ok(`${figlet_render(said, ink).join('\n')}\n`, { kind: 'games.figlet', data: { text: said, ink } });
100
+ }
101
+ /** `figlet [text]`: big letters, solid. */
102
+ export async function builtin_figlet(args) {
103
+ return big_run(args, '█', 'figlet');
104
+ }
105
+ /** `banner [text]`: big letters in `#`, as banner always drew them. */
106
+ export async function builtin_banner(args) {
107
+ return big_run(args, '#', 'banner');
108
+ }
109
+ //# sourceMappingURL=figlet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figlet.js","sourceRoot":"","sources":["../../../src/builtins/games/figlet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAmB,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,mDAAmD;AACnD,MAAM,IAAI,GAAoD;IAC5D,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAChD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAC9B,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAC9B,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,E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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @file The lab's own toys: `who`, `uptime`, `ping`, `chrisfetch`, `say`.
3
+ *
4
+ * Small tools that happen to be fun. `who` names the surfaces on this
5
+ * session, `uptime` how long the process has been up, `ping` the round
6
+ * trip to CUBE, `chrisfetch` the brain beside the session's facts, and
7
+ * `say` hands words to a surface with a voice (the console prints them).
8
+ *
9
+ * @module
10
+ */
11
+ import { CommandEnvelope } from '@fnndsc/cumin';
12
+ /** Round trips `ping` makes when not told. */
13
+ export declare const PING_COUNT: number;
14
+ /** The most round trips `ping` makes however asked. */
15
+ export declare const PING_MAX: number;
16
+ /** A span of seconds in words: `2d 3h 04m`, `17m 05s`. */
17
+ export declare function uptime_words(seconds: number): string;
18
+ /** `who`: the surfaces attached to this session. */
19
+ export declare function builtin_who(_args: string[]): Promise<CommandEnvelope>;
20
+ /** `uptime`: how long this process has been up, and who is here. */
21
+ export declare function builtin_uptime(_args: string[]): Promise<CommandEnvelope>;
22
+ /** One round trip's outcome. */
23
+ export interface PingSample {
24
+ seq: number;
25
+ ms: number | null;
26
+ status: number | null;
27
+ }
28
+ /** What `ping` uses to reach CUBE; a test hands in its own. */
29
+ export type PingFetch = (url: string, init: {
30
+ method: string;
31
+ signal: AbortSignal;
32
+ }) => Promise<{
33
+ status: number;
34
+ }>;
35
+ /**
36
+ * Round-trips to a URL `count` times.
37
+ *
38
+ * @param url - Where.
39
+ * @param count - How many.
40
+ * @param fetchFn - The fetch to use.
41
+ * @param onSample - Told each sample as it lands, for a surface that streams.
42
+ */
43
+ export declare function ping_run(url: string, count: number, fetchFn: PingFetch, onSample?: (s: PingSample) => void): Promise<PingSample[]>;
44
+ /** The summary line, as ping prints it. */
45
+ export declare function ping_summary(samples: PingSample[]): string;
46
+ /** `ping [-c N]`: round trips to CUBE. */
47
+ export declare function builtin_ping(args: string[], fetchFn?: PingFetch): Promise<CommandEnvelope>;
48
+ /** `chrisfetch`: the brain beside the session's facts, neofetch style. */
49
+ export declare function builtin_chrisfetch(_args: string[]): Promise<CommandEnvelope>;
50
+ /** `say [text]`: a surface with a voice speaks it; the console prints it. */
51
+ export declare function builtin_say(args: string[]): Promise<CommandEnvelope>;