funcity-cli 0.5.0 → 0.6.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/README.md +2 -2
- package/dist/cli.d.ts +7 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/generated/packageMetadata.d.ts +3 -3
- package/dist/generated/packageMetadata.d.ts.map +1 -1
- package/dist/index.cjs +311 -44
- package/dist/index.cjs.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -61,8 +61,8 @@ const script = "Today is {{cond weather.sunny ‘nice’ 'bad'}} weather.";
|
|
|
61
61
|
|
|
62
62
|
// Run the interpreter
|
|
63
63
|
const variables = buildCandidateVariables();
|
|
64
|
-
const
|
|
65
|
-
const text = await
|
|
64
|
+
const logs: FunCityLogEntry[] = [];
|
|
65
|
+
const text = await runScriptOnceToText(script, variables, logs);
|
|
66
66
|
|
|
67
67
|
// Display the result text
|
|
68
68
|
console.log(text);
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FunCityLogEntry } from 'funcity';
|
|
2
2
|
export interface ReplEvaluationResult {
|
|
3
3
|
readonly output: string | undefined;
|
|
4
|
-
readonly
|
|
4
|
+
readonly logs: FunCityLogEntry[];
|
|
5
|
+
readonly shouldExit: boolean;
|
|
5
6
|
}
|
|
6
7
|
export interface ReplSession {
|
|
8
|
+
evaluateLine: (line: string, signal: AbortSignal) => Promise<ReplEvaluationResult>;
|
|
7
9
|
getPrompt: () => Promise<string>;
|
|
8
|
-
|
|
10
|
+
setVariable: (name: string, value: unknown) => void;
|
|
9
11
|
}
|
|
10
12
|
export declare const createReplSession: () => ReplSession;
|
|
11
|
-
export declare const runScriptToText: (script: string) => Promise<{
|
|
13
|
+
export declare const runScriptToText: (script: string, basePath?: string) => Promise<{
|
|
12
14
|
output: string | undefined;
|
|
13
|
-
|
|
15
|
+
logs: FunCityLogEntry[];
|
|
14
16
|
}>;
|
|
15
17
|
export declare const runMain: (argv?: string[]) => Promise<void>;
|
|
16
18
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,eAAe,EAIhB,MAAM,SAAS,CAAC;AAkNjB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,iBAAiB,QAAO,WA6EpC,CAAC;AAwJF,eAAO,MAAM,eAAe,GAAU,QAAQ,MAAM,EAAE,WAAW,MAAM;;;EAQtE,CAAC;AA8HF,eAAO,MAAM,OAAO,GAAU,OAAM,MAAM,EAAiB,KAAG,OAAO,CAAC,IAAI,CAsCzE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare const name = "funcity-cli";
|
|
2
|
-
export declare const version = "0.
|
|
2
|
+
export declare const version = "0.6.0";
|
|
3
3
|
export declare const description = "A functional language interpreter with text processing";
|
|
4
4
|
export declare const author = "Kouji Matsui (@kekyo@mi.kekyo.net)";
|
|
5
5
|
export declare const license = "MIT";
|
|
6
|
-
export declare const repository_url = "https://github.com/kekyo/funcity
|
|
7
|
-
export declare const git_commit_hash = "
|
|
6
|
+
export declare const repository_url = "https://github.com/kekyo/funcity";
|
|
7
|
+
export declare const git_commit_hash = "0ead9e15b1d6951acb7bf50d4850def586a23c47";
|
|
8
8
|
//# sourceMappingURL=packageMetadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageMetadata.d.ts","sourceRoot":"","sources":["../../src/generated/packageMetadata.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAClC,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,WAAW,2DAA2D,CAAC;AACpF,eAAO,MAAM,MAAM,uCAAuC,CAAC;AAC3D,eAAO,MAAM,OAAO,QAAQ,CAAC;AAC7B,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"packageMetadata.d.ts","sourceRoot":"","sources":["../../src/generated/packageMetadata.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAClC,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,WAAW,2DAA2D,CAAC;AACpF,eAAO,MAAM,MAAM,uCAAuC,CAAC;AAC3D,eAAO,MAAM,OAAO,QAAQ,CAAC;AAC7B,eAAO,MAAM,cAAc,qCAAqC,CAAC;AACjE,eAAO,MAAM,eAAe,6CAA6C,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,24 +1,102 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*!
|
|
3
3
|
* name: funcity-cli
|
|
4
|
-
* version: 0.
|
|
4
|
+
* version: 0.6.0
|
|
5
5
|
* description: A functional language interpreter with text processing
|
|
6
6
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
7
7
|
* license: MIT
|
|
8
|
-
* repository.url: https://github.com/kekyo/funcity
|
|
9
|
-
* git.commit.hash:
|
|
8
|
+
* repository.url: https://github.com/kekyo/funcity
|
|
9
|
+
* git.commit.hash: 0ead9e15b1d6951acb7bf50d4850def586a23c47
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
"use strict";
|
|
13
13
|
const promises = require("fs/promises");
|
|
14
|
+
const os = require("os");
|
|
15
|
+
const path = require("path");
|
|
14
16
|
const readline = require("readline");
|
|
15
17
|
const commander = require("commander");
|
|
16
18
|
const funcity = require("funcity");
|
|
19
|
+
const node = require("funcity/node");
|
|
20
|
+
function _interopNamespaceDefault(e) {
|
|
21
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
22
|
+
if (e) {
|
|
23
|
+
for (const k in e) {
|
|
24
|
+
if (k !== "default") {
|
|
25
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
26
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: () => e[k]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
n.default = e;
|
|
34
|
+
return Object.freeze(n);
|
|
35
|
+
}
|
|
36
|
+
const os__namespace = /* @__PURE__ */ _interopNamespaceDefault(os);
|
|
37
|
+
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
17
38
|
const name = "funcity-cli";
|
|
18
|
-
const version = "0.
|
|
39
|
+
const version = "0.6.0";
|
|
19
40
|
const description = "A functional language interpreter with text processing";
|
|
20
|
-
const
|
|
41
|
+
const repository_url = "https://github.com/kekyo/funcity";
|
|
42
|
+
const git_commit_hash = "0ead9e15b1d6951acb7bf50d4850def586a23c47";
|
|
21
43
|
const continuationPromptText = "? ";
|
|
44
|
+
let replReadlineInterface;
|
|
45
|
+
const createReplReadline = () => {
|
|
46
|
+
const fallbackReadline = node.nodeJsVariables.readline;
|
|
47
|
+
return async function(prompt) {
|
|
48
|
+
if (!replReadlineInterface) {
|
|
49
|
+
return await fallbackReadline.call(this, prompt);
|
|
50
|
+
}
|
|
51
|
+
const question = prompt === void 0 ? "" : this.convertToString(prompt);
|
|
52
|
+
const signal = this.abortSignal;
|
|
53
|
+
if (signal?.aborted) {
|
|
54
|
+
const abortError = new Error("Aborted");
|
|
55
|
+
abortError.name = "AbortError";
|
|
56
|
+
throw abortError;
|
|
57
|
+
}
|
|
58
|
+
return await new Promise((resolve, reject) => {
|
|
59
|
+
const rl = replReadlineInterface;
|
|
60
|
+
let settled = false;
|
|
61
|
+
const cleanup = () => {
|
|
62
|
+
if (signal) {
|
|
63
|
+
signal.removeEventListener("abort", onAbort);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const finishResolve = (value) => {
|
|
67
|
+
if (settled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
settled = true;
|
|
71
|
+
cleanup();
|
|
72
|
+
resolve(value);
|
|
73
|
+
};
|
|
74
|
+
const finishReject = (error) => {
|
|
75
|
+
if (settled) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
settled = true;
|
|
79
|
+
cleanup();
|
|
80
|
+
reject(error);
|
|
81
|
+
};
|
|
82
|
+
const onAbort = () => {
|
|
83
|
+
const abortError = new Error("Aborted");
|
|
84
|
+
abortError.name = "AbortError";
|
|
85
|
+
finishReject(abortError);
|
|
86
|
+
};
|
|
87
|
+
if (signal) {
|
|
88
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
89
|
+
rl.question(question, { signal }, (answer) => {
|
|
90
|
+
finishResolve(answer);
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
rl.question(question, (answer) => {
|
|
94
|
+
finishResolve(answer);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
};
|
|
22
100
|
const readStream = async (stream) => {
|
|
23
101
|
return await new Promise((resolve, reject) => {
|
|
24
102
|
let data = "";
|
|
@@ -36,10 +114,29 @@ const readStream = async (stream) => {
|
|
|
36
114
|
});
|
|
37
115
|
});
|
|
38
116
|
};
|
|
39
|
-
const
|
|
117
|
+
const getErrorCode = (error) => {
|
|
118
|
+
if (!error || typeof error !== "object") {
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
return error.code;
|
|
122
|
+
};
|
|
123
|
+
const readRcScript = async () => {
|
|
124
|
+
const rcPath = path__namespace.join(os__namespace.homedir(), ".funcityrc");
|
|
125
|
+
try {
|
|
126
|
+
const script = await promises.readFile(rcPath, "utf8");
|
|
127
|
+
return { path: rcPath, script };
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (getErrorCode(error) !== "ENOENT") {
|
|
130
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
131
|
+
console.warn(`warning: failed to read ${rcPath}: ${message}`);
|
|
132
|
+
}
|
|
133
|
+
return { path: rcPath };
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const reduceAndCollectResults = async (context, nodes, signal) => {
|
|
40
137
|
const resultList = [];
|
|
41
|
-
for (const
|
|
42
|
-
const results = await funcity.reduceNode(context,
|
|
138
|
+
for (const node2 of nodes) {
|
|
139
|
+
const results = await funcity.reduceNode(context, node2, signal);
|
|
43
140
|
for (const result of results) {
|
|
44
141
|
if (result !== void 0) {
|
|
45
142
|
resultList.push(result);
|
|
@@ -48,35 +145,90 @@ const reduceAndCollectResults = async (context, nodes) => {
|
|
|
48
145
|
}
|
|
49
146
|
return resultList;
|
|
50
147
|
};
|
|
148
|
+
const runCodeWithContext = async (context, warningLogs, script, signal) => {
|
|
149
|
+
const logs = [];
|
|
150
|
+
const tokens = funcity.runCodeTokenizer(script, logs);
|
|
151
|
+
const nodes = funcity.parseExpressions(tokens, logs);
|
|
152
|
+
if (logs.length >= 1) {
|
|
153
|
+
return { output: void 0, logs };
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
warningLogs.length = 0;
|
|
157
|
+
const results = await reduceAndCollectResults(context, nodes, signal);
|
|
158
|
+
const output = results.length > 0 ? results.map((result) => context.convertToString(result)).join("\n") : "";
|
|
159
|
+
return { output, logs: [...warningLogs] };
|
|
160
|
+
} catch (error) {
|
|
161
|
+
if (error instanceof funcity.FunCityReducerError) {
|
|
162
|
+
return { output: void 0, logs: [...warningLogs, error.info] };
|
|
163
|
+
}
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const runScriptWithContext = async (context, warningLogs, script, signal) => {
|
|
168
|
+
const logs = [];
|
|
169
|
+
const tokens = funcity.runTokenizer(script, logs);
|
|
170
|
+
const nodes = funcity.runParser(tokens, logs);
|
|
171
|
+
if (logs.length >= 1) {
|
|
172
|
+
return { output: void 0, logs };
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
warningLogs.length = 0;
|
|
176
|
+
const results = await reduceAndCollectResults(context, nodes, signal);
|
|
177
|
+
const output = results.map((result) => context.convertToString(result)).join("");
|
|
178
|
+
return { output, logs: [...warningLogs] };
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (error instanceof funcity.FunCityReducerError) {
|
|
181
|
+
return { output: void 0, logs: [...warningLogs, error.info] };
|
|
182
|
+
}
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
51
186
|
const createReplSession = () => {
|
|
52
|
-
const
|
|
53
|
-
|
|
187
|
+
const exitSymbol = /* @__PURE__ */ Symbol("exit");
|
|
188
|
+
const replReadline = createReplReadline();
|
|
189
|
+
const require2 = node.createRequireFunction();
|
|
190
|
+
const variables = funcity.buildCandidateVariables(funcity.fetchVariables, node.nodeJsVariables, {
|
|
191
|
+
require: require2,
|
|
192
|
+
prompt: "funcity> ",
|
|
193
|
+
exit: exitSymbol,
|
|
194
|
+
readline: replReadline
|
|
54
195
|
});
|
|
55
|
-
const
|
|
56
|
-
const reducerContext = funcity.createReducerContext(variables);
|
|
57
|
-
const evaluateLine = async (line) => {
|
|
58
|
-
|
|
59
|
-
const tokens = funcity.runCodeTokenizer(line,
|
|
60
|
-
const nodes = funcity.parseExpressions(tokens,
|
|
61
|
-
if (
|
|
196
|
+
const warningLogs = [];
|
|
197
|
+
const reducerContext = funcity.createReducerContext(variables, warningLogs);
|
|
198
|
+
const evaluateLine = async (line, signal) => {
|
|
199
|
+
const logs = [];
|
|
200
|
+
const tokens = funcity.runCodeTokenizer(line, logs);
|
|
201
|
+
const nodes = funcity.parseExpressions(tokens, logs);
|
|
202
|
+
if (logs.length >= 1) {
|
|
62
203
|
return {
|
|
63
204
|
output: void 0,
|
|
64
|
-
|
|
205
|
+
logs,
|
|
206
|
+
shouldExit: false
|
|
65
207
|
};
|
|
66
208
|
}
|
|
67
209
|
try {
|
|
68
|
-
|
|
69
|
-
const
|
|
210
|
+
warningLogs.length = 0;
|
|
211
|
+
const results = await reduceAndCollectResults(
|
|
212
|
+
reducerContext,
|
|
213
|
+
nodes,
|
|
214
|
+
signal
|
|
215
|
+
);
|
|
216
|
+
const shouldExit = results.some((result) => result === exitSymbol);
|
|
217
|
+
const outputResults = results.filter((result) => result !== exitSymbol);
|
|
218
|
+
const output = outputResults.length > 0 ? outputResults.map((result) => funcity.convertToString(result)).join("\n") : "";
|
|
70
219
|
return {
|
|
71
220
|
output,
|
|
72
|
-
|
|
221
|
+
logs: [...warningLogs],
|
|
222
|
+
shouldExit
|
|
73
223
|
};
|
|
74
224
|
} catch (error) {
|
|
75
225
|
if (error instanceof funcity.FunCityReducerError) {
|
|
76
|
-
|
|
226
|
+
const logs2 = [...warningLogs];
|
|
227
|
+
logs2.push(error.info);
|
|
77
228
|
return {
|
|
78
229
|
output: void 0,
|
|
79
|
-
|
|
230
|
+
logs: logs2,
|
|
231
|
+
shouldExit: false
|
|
80
232
|
};
|
|
81
233
|
}
|
|
82
234
|
throw error;
|
|
@@ -90,38 +242,103 @@ const createReplSession = () => {
|
|
|
90
242
|
});
|
|
91
243
|
return reducerContext.convertToString(prompt);
|
|
92
244
|
};
|
|
93
|
-
|
|
245
|
+
const setVariable = (name2, value) => {
|
|
246
|
+
reducerContext.setValue(name2, value, void 0);
|
|
247
|
+
};
|
|
248
|
+
return { evaluateLine, getPrompt, setVariable };
|
|
249
|
+
};
|
|
250
|
+
const isAbortError = (error) => {
|
|
251
|
+
if (!error || typeof error !== "object") {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
const errorRecord = error;
|
|
255
|
+
return errorRecord.name === "AbortError" || errorRecord.code === "ABORT_ERR";
|
|
94
256
|
};
|
|
95
|
-
const
|
|
257
|
+
const loadRcForRepl = async (session) => {
|
|
258
|
+
const { path: rcPath, script } = await readRcScript();
|
|
259
|
+
if (!script) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
session.setVariable("require", node.createRequireFunction(os__namespace.homedir()));
|
|
263
|
+
const { output, logs } = await session.evaluateLine(
|
|
264
|
+
script,
|
|
265
|
+
new AbortController().signal
|
|
266
|
+
);
|
|
267
|
+
if (logs.length > 0) {
|
|
268
|
+
funcity.outputErrors(rcPath, logs, console);
|
|
269
|
+
}
|
|
270
|
+
if (output) {
|
|
271
|
+
console.log(output);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
const runRepl = async (loadRc) => {
|
|
275
|
+
console.log(
|
|
276
|
+
`${name} [${version}-${git_commit_hash}]`
|
|
277
|
+
);
|
|
278
|
+
console.log(`Copyright (c) kouji Matsui (@kekyo@mi.kekyo.net)`);
|
|
279
|
+
console.log(`${repository_url}`);
|
|
280
|
+
console.log(`Type 'exit' to exit CLI`);
|
|
281
|
+
console.log("");
|
|
96
282
|
const session = createReplSession();
|
|
283
|
+
if (loadRc) {
|
|
284
|
+
await loadRcForRepl(session);
|
|
285
|
+
}
|
|
286
|
+
session.setVariable("require", node.createRequireFunction(process.cwd()));
|
|
97
287
|
const rl = readline.createInterface({
|
|
98
288
|
input: process.stdin,
|
|
99
289
|
output: process.stdout,
|
|
100
290
|
prompt: await session.getPrompt()
|
|
101
291
|
});
|
|
292
|
+
replReadlineInterface = rl;
|
|
102
293
|
let bufferedLine = "";
|
|
294
|
+
let isEvaluating = false;
|
|
295
|
+
let abortController = new AbortController();
|
|
103
296
|
const setPrompt = async (isContinuation) => {
|
|
104
297
|
rl.setPrompt(
|
|
105
298
|
isContinuation ? continuationPromptText : await session.getPrompt()
|
|
106
299
|
);
|
|
107
300
|
};
|
|
108
301
|
const hasLineContinuation = (line) => line.endsWith("\\");
|
|
109
|
-
const evaluateAndPrint = async (line) => {
|
|
302
|
+
const evaluateAndPrint = async (line, signal) => {
|
|
110
303
|
try {
|
|
111
|
-
const { output,
|
|
112
|
-
|
|
113
|
-
|
|
304
|
+
const { output, logs, shouldExit: shouldExit2 } = await session.evaluateLine(
|
|
305
|
+
line,
|
|
306
|
+
signal
|
|
307
|
+
);
|
|
308
|
+
if (logs.length > 0) {
|
|
309
|
+
funcity.outputErrors("<repl>", logs, console);
|
|
114
310
|
}
|
|
115
311
|
if (output) {
|
|
116
312
|
console.log(output);
|
|
117
313
|
}
|
|
314
|
+
return shouldExit2;
|
|
118
315
|
} catch (error) {
|
|
316
|
+
if (isAbortError(error)) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
119
319
|
const message = error instanceof Error ? error.message : String(error);
|
|
120
320
|
console.error(message);
|
|
321
|
+
return false;
|
|
121
322
|
}
|
|
122
323
|
};
|
|
123
324
|
await setPrompt(false);
|
|
124
325
|
rl.prompt();
|
|
326
|
+
const handleInterrupt = async () => {
|
|
327
|
+
if (!abortController.signal.aborted) {
|
|
328
|
+
abortController.abort();
|
|
329
|
+
}
|
|
330
|
+
abortController = new AbortController();
|
|
331
|
+
bufferedLine = "";
|
|
332
|
+
process.stdout.write("\nInterrupted\n");
|
|
333
|
+
if (!isEvaluating) {
|
|
334
|
+
await setPrompt(false);
|
|
335
|
+
rl.prompt();
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
rl.on("SIGINT", () => {
|
|
339
|
+
void handleInterrupt();
|
|
340
|
+
});
|
|
341
|
+
let shouldExit = false;
|
|
125
342
|
for await (const line of rl) {
|
|
126
343
|
if (bufferedLine) {
|
|
127
344
|
bufferedLine += `
|
|
@@ -136,27 +353,74 @@ ${line}`;
|
|
|
136
353
|
}
|
|
137
354
|
const logicalLine = bufferedLine;
|
|
138
355
|
bufferedLine = "";
|
|
139
|
-
|
|
356
|
+
isEvaluating = true;
|
|
357
|
+
try {
|
|
358
|
+
shouldExit = await evaluateAndPrint(logicalLine, abortController.signal);
|
|
359
|
+
} finally {
|
|
360
|
+
isEvaluating = false;
|
|
361
|
+
}
|
|
362
|
+
if (shouldExit) {
|
|
363
|
+
bufferedLine = "";
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
140
366
|
await setPrompt(false);
|
|
141
367
|
rl.prompt();
|
|
142
368
|
}
|
|
143
|
-
if (bufferedLine) {
|
|
144
|
-
|
|
369
|
+
if (!shouldExit && bufferedLine) {
|
|
370
|
+
isEvaluating = true;
|
|
371
|
+
try {
|
|
372
|
+
await evaluateAndPrint(bufferedLine, abortController.signal);
|
|
373
|
+
} finally {
|
|
374
|
+
isEvaluating = false;
|
|
375
|
+
}
|
|
145
376
|
}
|
|
146
377
|
rl.close();
|
|
378
|
+
replReadlineInterface = void 0;
|
|
147
379
|
};
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
380
|
+
const loadRcForContext = async (context, warningLogs) => {
|
|
381
|
+
const { path: rcPath, script } = await readRcScript();
|
|
382
|
+
if (!script) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
context.setValue("require", node.createRequireFunction(os__namespace.homedir()), void 0);
|
|
386
|
+
const { output, logs } = await runCodeWithContext(
|
|
387
|
+
context,
|
|
388
|
+
warningLogs,
|
|
389
|
+
script,
|
|
390
|
+
new AbortController().signal
|
|
391
|
+
);
|
|
392
|
+
if (logs.length > 0) {
|
|
393
|
+
funcity.outputErrors(rcPath, logs, console);
|
|
394
|
+
}
|
|
395
|
+
if (output) {
|
|
396
|
+
console.log(output);
|
|
397
|
+
}
|
|
153
398
|
};
|
|
154
|
-
const runScript = async (input) => {
|
|
399
|
+
const runScript = async (input, loadRc) => {
|
|
155
400
|
const isStdin = input === "-";
|
|
156
401
|
const source = isStdin ? "<stdin>" : input;
|
|
157
402
|
const script = isStdin ? await readStream(process.stdin) : await promises.readFile(input, "utf8");
|
|
158
|
-
const
|
|
159
|
-
const
|
|
403
|
+
const basePath = isStdin ? process.cwd() : path__namespace.dirname(path__namespace.resolve(input));
|
|
404
|
+
const variables = funcity.buildCandidateVariables(funcity.fetchVariables, node.nodeJsVariables, {
|
|
405
|
+
require: node.createRequireFunction(loadRc ? os__namespace.homedir() : basePath)
|
|
406
|
+
});
|
|
407
|
+
const warningLogs = [];
|
|
408
|
+
const reducerContext = funcity.createReducerContext(variables, warningLogs);
|
|
409
|
+
if (loadRc) {
|
|
410
|
+
await loadRcForContext(reducerContext, warningLogs);
|
|
411
|
+
}
|
|
412
|
+
reducerContext.setValue(
|
|
413
|
+
"require",
|
|
414
|
+
node.createRequireFunction(basePath),
|
|
415
|
+
void 0
|
|
416
|
+
);
|
|
417
|
+
const { output, logs } = await runScriptWithContext(
|
|
418
|
+
reducerContext,
|
|
419
|
+
warningLogs,
|
|
420
|
+
script,
|
|
421
|
+
new AbortController().signal
|
|
422
|
+
);
|
|
423
|
+
const hasError = funcity.outputErrors(source, logs, console);
|
|
160
424
|
if (hasError) {
|
|
161
425
|
process.exitCode = 1;
|
|
162
426
|
}
|
|
@@ -229,16 +493,19 @@ ${description}
|
|
|
229
493
|
`${version}-${git_commit_hash}`
|
|
230
494
|
);
|
|
231
495
|
program.showHelpAfterError(true);
|
|
232
|
-
program.
|
|
233
|
-
|
|
496
|
+
program.addOption(new commander.Option("--no-rc", "Do not load ~/.funcityrc"));
|
|
497
|
+
program.command("repl").summary("Start an interactive REPL session").action(async (_options, command) => {
|
|
498
|
+
const { rc } = command.parent?.opts() ?? { rc: true };
|
|
499
|
+
await runRepl(rc);
|
|
234
500
|
});
|
|
235
501
|
program.command("run").summary("Run a script from a file or stdin").addOption(
|
|
236
502
|
new commander.Option(
|
|
237
503
|
"-i, --input <path>",
|
|
238
504
|
'Input file path or "-" for stdin'
|
|
239
505
|
).default("-")
|
|
240
|
-
).action(async (options) => {
|
|
241
|
-
|
|
506
|
+
).action(async (options, command) => {
|
|
507
|
+
const { rc } = command.parent?.opts() ?? { rc: true };
|
|
508
|
+
await runScript(options.input, rc);
|
|
242
509
|
});
|
|
243
510
|
await program.parseAsync(injectDefaultCommand(argv));
|
|
244
511
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/generated/packageMetadata.ts","../src/cli.ts","../src/index.ts"],"sourcesContent":["// @ts-nocheck\n// This file is auto-generated by screw-up plugin\n// Do not edit manually\n\nexport const name = \"funcity-cli\";\nexport const version = \"0.5.0\";\nexport const description = \"A functional language interpreter with text processing\";\nexport const author = \"Kouji Matsui (@kekyo@mi.kekyo.net)\";\nexport const license = \"MIT\";\nexport const repository_url = \"https://github.com/kekyo/funcity.git\";\nexport const git_commit_hash = \"68a2ab1ac86b865b1c2ea37aa43816ee34d29540\";\n","// funcity - A functional language interpreter with text processing\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/funcity/\n\nimport { readFile } from 'fs/promises';\nimport readline from 'readline';\nimport { Command, Option } from 'commander';\nimport * as packageMetadata from './generated/packageMetadata';\nimport {\n buildCandidateVariables,\n convertToString,\n createReducerContext,\n emptyRange,\n nodeJsVariables,\n fetchVariables,\n outputErrors,\n parseExpressions,\n reduceExpressionNode,\n reduceNode,\n runCodeTokenizer,\n runScriptOnceToText,\n} from 'funcity';\nimport {\n FunCityBlockNode,\n FunCityErrorInfo,\n FunCityReducerError,\n FunCityReducerContext,\n} from 'funcity';\n\nconst continuationPromptText = '? ';\n\nconst readStream = async (stream: NodeJS.ReadableStream): Promise<string> => {\n return await new Promise((resolve, reject) => {\n let data = '';\n if (typeof stream.setEncoding === 'function') {\n stream.setEncoding('utf8');\n }\n stream.on('data', (chunk) => {\n data += String(chunk);\n });\n stream.on('end', () => {\n resolve(data);\n });\n stream.on('error', (error) => {\n reject(error);\n });\n });\n};\n\nconst reduceAndCollectResults = async (\n context: FunCityReducerContext,\n nodes: readonly FunCityBlockNode[]\n): Promise<unknown[]> => {\n const resultList: unknown[] = [];\n for (const node of nodes) {\n const results = await reduceNode(context, node);\n for (const result of results) {\n if (result !== undefined) {\n resultList.push(result);\n }\n }\n }\n return resultList;\n};\n\nexport interface ReplEvaluationResult {\n readonly output: string | undefined;\n readonly errors: FunCityErrorInfo[];\n}\n\nexport interface ReplSession {\n getPrompt: () => Promise<string>;\n evaluateLine: (line: string) => Promise<ReplEvaluationResult>;\n}\n\nexport const createReplSession = (): ReplSession => {\n const variables = buildCandidateVariables(nodeJsVariables, {\n prompt: 'funcity> ',\n });\n\n const errors: FunCityErrorInfo[] = [];\n const reducerContext = createReducerContext(variables);\n\n const evaluateLine = async (line: string): Promise<ReplEvaluationResult> => {\n errors.length = 0;\n const tokens = runCodeTokenizer(line, errors);\n const nodes = parseExpressions(tokens, errors);\n if (errors.length >= 1) {\n return {\n output: undefined,\n errors: [...errors],\n };\n }\n try {\n const results = await reduceAndCollectResults(reducerContext, nodes);\n const output =\n results.length > 0\n ? results.map((result) => convertToString(result)).join('\\n')\n : '';\n return {\n output,\n errors: [...errors],\n };\n } catch (error: unknown) {\n if (error instanceof FunCityReducerError) {\n errors.push(error.info);\n return {\n output: undefined,\n errors: [...errors],\n };\n }\n throw error;\n }\n };\n const getPrompt = async () => {\n const prompt = await reduceExpressionNode(reducerContext, {\n kind: 'variable',\n name: 'prompt',\n range: emptyRange,\n });\n return reducerContext.convertToString(prompt);\n };\n\n return { evaluateLine, getPrompt };\n};\n\nconst runRepl = async (): Promise<void> => {\n const session = createReplSession();\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: await session.getPrompt(),\n });\n\n let bufferedLine = '';\n\n const setPrompt = async (isContinuation: boolean) => {\n rl.setPrompt(\n isContinuation ? continuationPromptText : await session.getPrompt()\n );\n };\n\n const hasLineContinuation = (line: string): boolean => line.endsWith('\\\\');\n\n const evaluateAndPrint = async (line: string) => {\n try {\n const { output, errors } = await session.evaluateLine(line);\n if (errors.length > 0) {\n outputErrors('<repl>', errors, console);\n }\n if (output) {\n console.log(output);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n }\n };\n\n await setPrompt(false);\n rl.prompt();\n\n for await (const line of rl) {\n if (bufferedLine) {\n bufferedLine += `\\n${line}`;\n } else {\n bufferedLine = line;\n }\n\n if (hasLineContinuation(line)) {\n await setPrompt(true);\n rl.prompt();\n continue;\n }\n\n const logicalLine = bufferedLine;\n bufferedLine = '';\n await evaluateAndPrint(logicalLine);\n await setPrompt(false);\n rl.prompt();\n }\n\n if (bufferedLine) {\n await evaluateAndPrint(bufferedLine);\n }\n\n rl.close();\n};\n\nexport const runScriptToText = async (script: string) => {\n const variables = buildCandidateVariables(fetchVariables, nodeJsVariables);\n const errors: FunCityErrorInfo[] = [];\n const output = await runScriptOnceToText(script, { variables, errors });\n return { output, errors };\n};\n\nconst runScript = async (input: string): Promise<void> => {\n const isStdin = input === '-';\n const source = isStdin ? '<stdin>' : input;\n const script = isStdin\n ? await readStream(process.stdin)\n : await readFile(input, 'utf8');\n\n const { output, errors } = await runScriptToText(script);\n\n const hasError = outputErrors(source, errors, console);\n if (hasError) {\n process.exitCode = 1;\n }\n\n if (output) {\n process.stdout.write(output);\n }\n};\n\nconst findExplicitCommand = (\n args: readonly string[]\n): 'repl' | 'run' | undefined => {\n for (let index = 0; index < args.length; index++) {\n const arg = args[index]!;\n if (arg === '--') {\n const next = args[index + 1];\n if (next === 'repl' || next === 'run') {\n return next;\n }\n return undefined;\n }\n if (arg === '-i' || arg === '--input') {\n index += 1;\n continue;\n }\n if (arg.startsWith('--input=')) {\n continue;\n }\n if (arg.startsWith('-')) {\n continue;\n }\n return arg === 'repl' || arg === 'run' ? arg : undefined;\n }\n return undefined;\n};\n\nconst hasInputOption = (args: readonly string[]): boolean => {\n for (const arg of args) {\n if (arg === '--') {\n break;\n }\n if (arg === '-i' || arg === '--input' || arg.startsWith('--input=')) {\n return true;\n }\n }\n return false;\n};\n\nconst injectDefaultCommand = (argv: string[]): string[] => {\n const args = argv.slice(2);\n const explicitCommand = findExplicitCommand(args);\n if (explicitCommand) {\n return argv;\n }\n\n const hasHelp = args.some(\n (arg) =>\n arg === '-h' || arg === '--help' || arg === '-V' || arg === '--version'\n );\n if (hasHelp) {\n return argv;\n }\n\n const command = hasInputOption(args) ? 'run' : 'repl';\n const [execPath = 'node', scriptPath = 'funcity'] = argv;\n return [execPath, scriptPath, command, ...args];\n};\n\nexport const runMain = async (argv: string[] = process.argv): Promise<void> => {\n const program = new Command();\n\n program.name(packageMetadata.name);\n program.summary(packageMetadata.description);\n program.addHelpText(\n 'beforeAll',\n `${packageMetadata.name}\\n${packageMetadata.description}\\n`\n );\n program.version(\n `${packageMetadata.version}-${packageMetadata.git_commit_hash}`\n );\n program.showHelpAfterError(true);\n\n program\n .command('repl')\n .summary('Start an interactive REPL session')\n .action(async () => {\n await runRepl();\n });\n\n program\n .command('run')\n .summary('Run a script from a file or stdin')\n .addOption(\n new Option(\n '-i, --input <path>',\n 'Input file path or \"-\" for stdin'\n ).default('-')\n )\n .action(async (options: { input: string }) => {\n await runScript(options.input);\n });\n\n await program.parseAsync(injectDefaultCommand(argv));\n};\n","// funcity - A functional language interpreter with text processing\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/funcity/\n\nimport { runMain } from './cli';\n\nrunMain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n});\n"],"names":["reduceNode","buildCandidateVariables","nodeJsVariables","createReducerContext","runCodeTokenizer","parseExpressions","convertToString","FunCityReducerError","reduceExpressionNode","emptyRange","outputErrors","fetchVariables","runScriptOnceToText","readFile","Command","packageMetadata.name","packageMetadata.description","packageMetadata.version","packageMetadata.git_commit_hash","Option"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/generated/packageMetadata.ts","../src/cli.ts","../src/index.ts"],"sourcesContent":["// @ts-nocheck\n// This file is auto-generated by screw-up plugin\n// Do not edit manually\n\nexport const name = \"funcity-cli\";\nexport const version = \"0.6.0\";\nexport const description = \"A functional language interpreter with text processing\";\nexport const author = \"Kouji Matsui (@kekyo@mi.kekyo.net)\";\nexport const license = \"MIT\";\nexport const repository_url = \"https://github.com/kekyo/funcity\";\nexport const git_commit_hash = \"0ead9e15b1d6951acb7bf50d4850def586a23c47\";\n","// funcity - A functional language interpreter with text processing\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/funcity/\n\nimport { readFile } from 'fs/promises';\nimport * as os from 'os';\nimport * as path from 'path';\nimport readline from 'readline';\nimport { Command, Option } from 'commander';\n\nimport * as packageMetadata from './generated/packageMetadata';\nimport {\n FunCityBlockNode,\n FunCityFunctionContext,\n FunCityLogEntry,\n FunCityReducerError,\n FunCityReducerContext,\n FunCityWarningEntry,\n} from 'funcity';\nimport {\n buildCandidateVariables,\n convertToString,\n createReducerContext,\n emptyRange,\n fetchVariables,\n outputErrors,\n parseExpressions,\n reduceExpressionNode,\n reduceNode,\n runParser,\n runCodeTokenizer,\n runTokenizer,\n runScriptOnceToText,\n} from 'funcity';\nimport { createRequireFunction, nodeJsVariables } from 'funcity/node';\n\n//////////////////////////////////////////////////////////////////////////////\n\nconst continuationPromptText = '? ';\n\nlet replReadlineInterface: readline.Interface | undefined;\n\nconst createReplReadline = () => {\n const fallbackReadline = nodeJsVariables.readline as (\n this: FunCityFunctionContext,\n prompt?: unknown\n ) => Promise<string>;\n\n return async function (this: FunCityFunctionContext, prompt?: unknown) {\n if (!replReadlineInterface) {\n return await fallbackReadline.call(this, prompt);\n }\n\n const question = prompt === undefined ? '' : this.convertToString(prompt);\n const signal = this.abortSignal;\n\n if (signal?.aborted) {\n const abortError = new Error('Aborted');\n (abortError as { name?: string }).name = 'AbortError';\n throw abortError;\n }\n\n return await new Promise<string>((resolve, reject) => {\n const rl = replReadlineInterface!;\n let settled = false;\n\n const cleanup = () => {\n if (signal) {\n signal.removeEventListener('abort', onAbort);\n }\n };\n\n const finishResolve = (value: string) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n resolve(value);\n };\n\n const finishReject = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n reject(error);\n };\n\n const onAbort = () => {\n const abortError = new Error('Aborted');\n (abortError as { name?: string }).name = 'AbortError';\n finishReject(abortError);\n };\n\n if (signal) {\n signal.addEventListener('abort', onAbort, { once: true });\n rl.question(question, { signal }, (answer) => {\n finishResolve(answer);\n });\n } else {\n rl.question(question, (answer) => {\n finishResolve(answer);\n });\n }\n });\n };\n};\n\nconst readStream = async (stream: NodeJS.ReadableStream): Promise<string> => {\n return await new Promise((resolve, reject) => {\n let data = '';\n if (typeof stream.setEncoding === 'function') {\n stream.setEncoding('utf8');\n }\n stream.on('data', (chunk) => {\n data += String(chunk);\n });\n stream.on('end', () => {\n resolve(data);\n });\n stream.on('error', (error) => {\n reject(error);\n });\n });\n};\n\nconst getErrorCode = (error: unknown): string | undefined => {\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n return (error as { code?: string }).code;\n};\n\nconst readRcScript = async (): Promise<{\n path: string;\n script?: string;\n}> => {\n const rcPath = path.join(os.homedir(), '.funcityrc');\n try {\n const script = await readFile(rcPath, 'utf8');\n return { path: rcPath, script };\n } catch (error) {\n if (getErrorCode(error) !== 'ENOENT') {\n const message = error instanceof Error ? error.message : String(error);\n console.warn(`warning: failed to read ${rcPath}: ${message}`);\n }\n return { path: rcPath };\n }\n};\n\nconst reduceAndCollectResults = async (\n context: FunCityReducerContext,\n nodes: readonly FunCityBlockNode[],\n signal: AbortSignal\n): Promise<unknown[]> => {\n const resultList: unknown[] = [];\n for (const node of nodes) {\n const results = await reduceNode(context, node, signal);\n for (const result of results) {\n if (result !== undefined) {\n resultList.push(result);\n }\n }\n }\n return resultList;\n};\n\nconst runCodeWithContext = async (\n context: FunCityReducerContext,\n warningLogs: FunCityWarningEntry[],\n script: string,\n signal: AbortSignal\n): Promise<{ output: string | undefined; logs: FunCityLogEntry[] }> => {\n const logs: FunCityLogEntry[] = [];\n const tokens = runCodeTokenizer(script, logs);\n const nodes = parseExpressions(tokens, logs);\n if (logs.length >= 1) {\n return { output: undefined, logs };\n }\n\n try {\n warningLogs.length = 0;\n const results = await reduceAndCollectResults(context, nodes, signal);\n const output =\n results.length > 0\n ? results.map((result) => context.convertToString(result)).join('\\n')\n : '';\n return { output, logs: [...warningLogs] };\n } catch (error: unknown) {\n if (error instanceof FunCityReducerError) {\n return { output: undefined, logs: [...warningLogs, error.info] };\n }\n throw error;\n }\n};\n\nconst runScriptWithContext = async (\n context: FunCityReducerContext,\n warningLogs: FunCityWarningEntry[],\n script: string,\n signal: AbortSignal\n): Promise<{ output: string | undefined; logs: FunCityLogEntry[] }> => {\n const logs: FunCityLogEntry[] = [];\n const tokens = runTokenizer(script, logs);\n const nodes = runParser(tokens, logs);\n if (logs.length >= 1) {\n return { output: undefined, logs };\n }\n\n try {\n warningLogs.length = 0;\n const results = await reduceAndCollectResults(context, nodes, signal);\n const output = results\n .map((result) => context.convertToString(result))\n .join('');\n return { output, logs: [...warningLogs] };\n } catch (error: unknown) {\n if (error instanceof FunCityReducerError) {\n return { output: undefined, logs: [...warningLogs, error.info] };\n }\n throw error;\n }\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\nexport interface ReplEvaluationResult {\n readonly output: string | undefined;\n readonly logs: FunCityLogEntry[];\n readonly shouldExit: boolean;\n}\n\nexport interface ReplSession {\n evaluateLine: (\n line: string,\n signal: AbortSignal\n ) => Promise<ReplEvaluationResult>;\n getPrompt: () => Promise<string>;\n setVariable: (name: string, value: unknown) => void;\n}\n\nexport const createReplSession = (): ReplSession => {\n const exitSymbol = Symbol('exit');\n const replReadline = createReplReadline();\n const require = createRequireFunction();\n const variables = buildCandidateVariables(fetchVariables, nodeJsVariables, {\n require,\n prompt: 'funcity> ',\n exit: exitSymbol,\n readline: replReadline,\n });\n\n const warningLogs: FunCityWarningEntry[] = [];\n const reducerContext = createReducerContext(variables, warningLogs);\n\n const evaluateLine = async (\n line: string,\n signal: AbortSignal\n ): Promise<ReplEvaluationResult> => {\n // Tokenize and parse step\n const logs: FunCityLogEntry[] = [];\n const tokens = runCodeTokenizer(line, logs);\n const nodes = parseExpressions(tokens, logs);\n if (logs.length >= 1) {\n return {\n output: undefined,\n logs,\n shouldExit: false,\n };\n }\n\n // Reduce step\n try {\n warningLogs.length = 0;\n const results = await reduceAndCollectResults(\n reducerContext,\n nodes,\n signal\n );\n const shouldExit = results.some((result) => result === exitSymbol);\n const outputResults = results.filter((result) => result !== exitSymbol);\n const output =\n outputResults.length > 0\n ? outputResults.map((result) => convertToString(result)).join('\\n')\n : '';\n return {\n output,\n logs: [...warningLogs],\n shouldExit,\n };\n } catch (error: unknown) {\n if (error instanceof FunCityReducerError) {\n const logs: FunCityLogEntry[] = [...warningLogs];\n logs.push(error.info);\n return {\n output: undefined,\n logs,\n shouldExit: false,\n };\n }\n throw error;\n }\n };\n\n const getPrompt = async () => {\n const prompt = await reduceExpressionNode(reducerContext, {\n kind: 'variable',\n name: 'prompt',\n range: emptyRange,\n });\n return reducerContext.convertToString(prompt);\n };\n\n const setVariable = (name: string, value: unknown) => {\n reducerContext.setValue(name, value, undefined);\n };\n\n return { evaluateLine, getPrompt, setVariable };\n};\n\nconst isAbortError = (error: unknown): boolean => {\n if (!error || typeof error !== 'object') {\n return false;\n }\n const errorRecord = error as { name?: string; code?: string };\n return errorRecord.name === 'AbortError' || errorRecord.code === 'ABORT_ERR';\n};\n\nconst loadRcForRepl = async (session: ReplSession): Promise<void> => {\n const { path: rcPath, script } = await readRcScript();\n if (!script) {\n return;\n }\n\n session.setVariable('require', createRequireFunction(os.homedir()));\n const { output, logs } = await session.evaluateLine(\n script,\n new AbortController().signal\n );\n if (logs.length > 0) {\n outputErrors(rcPath, logs, console);\n }\n if (output) {\n console.log(output);\n }\n};\n\nconst runRepl = async (loadRc: boolean): Promise<void> => {\n console.log(\n `${packageMetadata.name} [${packageMetadata.version}-${packageMetadata.git_commit_hash}]`\n );\n console.log(`Copyright (c) kouji Matsui (@kekyo@mi.kekyo.net)`);\n console.log(`${packageMetadata.repository_url}`);\n console.log(`Type 'exit' to exit CLI`);\n console.log('');\n\n const session = createReplSession();\n if (loadRc) {\n await loadRcForRepl(session);\n }\n session.setVariable('require', createRequireFunction(process.cwd()));\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: await session.getPrompt(),\n });\n replReadlineInterface = rl;\n\n let bufferedLine = '';\n let isEvaluating = false;\n let abortController = new AbortController();\n\n const setPrompt = async (isContinuation: boolean) => {\n rl.setPrompt(\n isContinuation ? continuationPromptText : await session.getPrompt()\n );\n };\n\n const hasLineContinuation = (line: string): boolean => line.endsWith('\\\\');\n\n const evaluateAndPrint = async (line: string, signal: AbortSignal) => {\n try {\n const { output, logs, shouldExit } = await session.evaluateLine(\n line,\n signal\n );\n if (logs.length > 0) {\n outputErrors('<repl>', logs, console);\n }\n if (output) {\n console.log(output);\n }\n return shouldExit;\n } catch (error) {\n if (isAbortError(error)) {\n return false;\n }\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n return false;\n }\n };\n\n await setPrompt(false);\n rl.prompt();\n\n const handleInterrupt = async () => {\n if (!abortController.signal.aborted) {\n abortController.abort();\n }\n abortController = new AbortController();\n bufferedLine = '';\n process.stdout.write('\\nInterrupted\\n');\n if (!isEvaluating) {\n await setPrompt(false);\n rl.prompt();\n }\n };\n\n rl.on('SIGINT', () => {\n void handleInterrupt();\n });\n\n let shouldExit = false;\n\n for await (const line of rl) {\n if (bufferedLine) {\n bufferedLine += `\\n${line}`;\n } else {\n bufferedLine = line;\n }\n\n if (hasLineContinuation(line)) {\n await setPrompt(true);\n rl.prompt();\n continue;\n }\n\n const logicalLine = bufferedLine;\n bufferedLine = '';\n isEvaluating = true;\n try {\n shouldExit = await evaluateAndPrint(logicalLine, abortController.signal);\n } finally {\n isEvaluating = false;\n }\n if (shouldExit) {\n bufferedLine = '';\n break;\n }\n await setPrompt(false);\n rl.prompt();\n }\n\n if (!shouldExit && bufferedLine) {\n isEvaluating = true;\n try {\n await evaluateAndPrint(bufferedLine, abortController.signal);\n } finally {\n isEvaluating = false;\n }\n }\n\n rl.close();\n replReadlineInterface = undefined;\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\nexport const runScriptToText = async (script: string, basePath?: string) => {\n const require = createRequireFunction(basePath);\n const variables = buildCandidateVariables(fetchVariables, nodeJsVariables, {\n require,\n });\n const logs: FunCityLogEntry[] = [];\n const output = await runScriptOnceToText(script, { variables, logs });\n return { output, logs };\n};\n\nconst loadRcForContext = async (\n context: FunCityReducerContext,\n warningLogs: FunCityWarningEntry[]\n): Promise<void> => {\n const { path: rcPath, script } = await readRcScript();\n if (!script) {\n return;\n }\n\n context.setValue('require', createRequireFunction(os.homedir()), undefined);\n const { output, logs } = await runCodeWithContext(\n context,\n warningLogs,\n script,\n new AbortController().signal\n );\n if (logs.length > 0) {\n outputErrors(rcPath, logs, console);\n }\n if (output) {\n console.log(output);\n }\n};\n\nconst runScript = async (input: string, loadRc: boolean): Promise<void> => {\n const isStdin = input === '-';\n const source = isStdin ? '<stdin>' : input;\n const script = isStdin\n ? await readStream(process.stdin)\n : await readFile(input, 'utf8');\n\n const basePath = isStdin ? process.cwd() : path.dirname(path.resolve(input));\n const variables = buildCandidateVariables(fetchVariables, nodeJsVariables, {\n require: createRequireFunction(loadRc ? os.homedir() : basePath),\n });\n const warningLogs: FunCityWarningEntry[] = [];\n const reducerContext = createReducerContext(variables, warningLogs);\n\n if (loadRc) {\n await loadRcForContext(reducerContext, warningLogs);\n }\n reducerContext.setValue(\n 'require',\n createRequireFunction(basePath),\n undefined\n );\n const { output, logs } = await runScriptWithContext(\n reducerContext,\n warningLogs,\n script,\n new AbortController().signal\n );\n\n const hasError = outputErrors(source, logs, console);\n if (hasError) {\n process.exitCode = 1;\n }\n\n if (output) {\n process.stdout.write(output);\n }\n};\n\n//////////////////////////////////////////////////////////////////////////////\n\nconst findExplicitCommand = (\n args: readonly string[]\n): 'repl' | 'run' | undefined => {\n for (let index = 0; index < args.length; index++) {\n const arg = args[index]!;\n if (arg === '--') {\n const next = args[index + 1];\n if (next === 'repl' || next === 'run') {\n return next;\n }\n return undefined;\n }\n if (arg === '-i' || arg === '--input') {\n index += 1;\n continue;\n }\n if (arg.startsWith('--input=')) {\n continue;\n }\n if (arg.startsWith('-')) {\n continue;\n }\n return arg === 'repl' || arg === 'run' ? arg : undefined;\n }\n return undefined;\n};\n\nconst hasInputOption = (args: readonly string[]): boolean => {\n for (const arg of args) {\n if (arg === '--') {\n break;\n }\n if (arg === '-i' || arg === '--input' || arg.startsWith('--input=')) {\n return true;\n }\n }\n return false;\n};\n\nconst injectDefaultCommand = (argv: string[]): string[] => {\n const args = argv.slice(2);\n const explicitCommand = findExplicitCommand(args);\n if (explicitCommand) {\n return argv;\n }\n\n const hasHelp = args.some(\n (arg) =>\n arg === '-h' || arg === '--help' || arg === '-V' || arg === '--version'\n );\n if (hasHelp) {\n return argv;\n }\n\n const command = hasInputOption(args) ? 'run' : 'repl';\n const [execPath = 'node', scriptPath = 'funcity'] = argv;\n return [execPath, scriptPath, command, ...args];\n};\n\nexport const runMain = async (argv: string[] = process.argv): Promise<void> => {\n const program = new Command();\n\n program.name(packageMetadata.name);\n program.summary(packageMetadata.description);\n program.addHelpText(\n 'beforeAll',\n `${packageMetadata.name}\\n${packageMetadata.description}\\n`\n );\n program.version(\n `${packageMetadata.version}-${packageMetadata.git_commit_hash}`\n );\n program.showHelpAfterError(true);\n program.addOption(new Option('--no-rc', 'Do not load ~/.funcityrc'));\n\n program\n .command('repl')\n .summary('Start an interactive REPL session')\n .action(async (_options, command) => {\n const { rc } = command.parent?.opts() ?? { rc: true };\n await runRepl(rc);\n });\n\n program\n .command('run')\n .summary('Run a script from a file or stdin')\n .addOption(\n new Option(\n '-i, --input <path>',\n 'Input file path or \"-\" for stdin'\n ).default('-')\n )\n .action(async (options: { input: string }, command) => {\n const { rc } = command.parent?.opts() ?? { rc: true };\n await runScript(options.input, rc);\n });\n\n await program.parseAsync(injectDefaultCommand(argv));\n};\n","// funcity - A functional language interpreter with text processing\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/funcity/\n\nimport { runMain } from './cli';\n\nrunMain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n});\n"],"names":["nodeJsVariables","path","os","readFile","node","reduceNode","runCodeTokenizer","parseExpressions","FunCityReducerError","runTokenizer","runParser","require","createRequireFunction","buildCandidateVariables","fetchVariables","createReducerContext","convertToString","logs","reduceExpressionNode","emptyRange","name","outputErrors","packageMetadata.name","packageMetadata.version","packageMetadata.git_commit_hash","packageMetadata.repository_url","shouldExit","Command","packageMetadata.description","Option"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"git": {
|
|
3
3
|
"tags": [
|
|
4
|
-
"0.
|
|
4
|
+
"0.6.0"
|
|
5
5
|
],
|
|
6
6
|
"branches": [
|
|
7
7
|
"main"
|
|
8
8
|
],
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.6.0",
|
|
10
10
|
"commit": {
|
|
11
|
-
"hash": "
|
|
12
|
-
"shortHash": "
|
|
13
|
-
"date": "2026-01-
|
|
11
|
+
"hash": "0ead9e15b1d6951acb7bf50d4850def586a23c47",
|
|
12
|
+
"shortHash": "0ead9e1",
|
|
13
|
+
"date": "2026-01-14T20:03:18+09:00",
|
|
14
14
|
"message": "Merge branch 'develop'"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"version": "0.
|
|
17
|
+
"version": "0.6.0",
|
|
18
18
|
"author": "Kouji Matsui (@kekyo@mi.kekyo.net)",
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
|
-
"url": "https://github.com/kekyo/funcity
|
|
22
|
+
"url": "https://github.com/kekyo/funcity"
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/kekyo/funcity#readme",
|
|
25
25
|
"files": [
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"vite-plugin-dts": ">=3.0.0",
|
|
70
70
|
"vitest": ">=1.0.0"
|
|
71
71
|
},
|
|
72
|
-
"buildDate": "2026-01-
|
|
72
|
+
"buildDate": "2026-01-14T20:07:34+09:00"
|
|
73
73
|
}
|