rapydscript-ng 0.7.24 → 0.8.1

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 (132) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +80 -26
  3. package/bin/build.ts +117 -0
  4. package/bin/package.json +1 -0
  5. package/bin/rapydscript +65 -62
  6. package/build_wheels.py +133 -0
  7. package/editor-plugins/README.md +80 -0
  8. package/editor-plugins/nvim.lua +321 -0
  9. package/local-agent.md +28 -0
  10. package/package.json +4 -5
  11. package/publish.py +27 -17
  12. package/release/baselib-plain-pretty.js +448 -326
  13. package/release/baselib-plain-ugly.js +3 -3
  14. package/release/compiler.js +9027 -8139
  15. package/release/signatures.json +27 -27
  16. package/release/stdlib_modules.json +1 -0
  17. package/src/ast.pyj +428 -280
  18. package/src/baselib-builtins.pyj +49 -28
  19. package/src/baselib-containers.pyj +241 -226
  20. package/src/baselib-errors.pyj +8 -1
  21. package/src/baselib-internal.pyj +38 -23
  22. package/src/baselib-itertools.pyj +13 -7
  23. package/src/baselib-str.pyj +59 -84
  24. package/src/compiler.pyj +4 -4
  25. package/src/errors.pyj +3 -4
  26. package/src/lib/aes.pyj +46 -32
  27. package/src/lib/elementmaker.pyj +11 -9
  28. package/src/lib/encodings.pyj +15 -5
  29. package/src/lib/gettext.pyj +9 -4
  30. package/src/lib/math.pyj +106 -45
  31. package/src/lib/operator.pyj +10 -10
  32. package/src/lib/pythonize.pyj +2 -1
  33. package/src/lib/random.pyj +28 -21
  34. package/src/lib/re.pyj +492 -19
  35. package/src/lib/traceback.pyj +171 -29
  36. package/src/lib/uuid.pyj +2 -2
  37. package/src/output/classes.pyj +28 -27
  38. package/src/output/codegen.pyj +87 -83
  39. package/src/output/comments.pyj +8 -8
  40. package/src/output/exceptions.pyj +20 -21
  41. package/src/output/functions.pyj +66 -64
  42. package/src/output/literals.pyj +24 -23
  43. package/src/output/loops.pyj +84 -142
  44. package/src/output/modules.pyj +55 -68
  45. package/src/output/operators.pyj +40 -29
  46. package/src/output/statements.pyj +21 -15
  47. package/src/output/stream.pyj +82 -56
  48. package/src/output/utils.pyj +12 -8
  49. package/src/parse.pyj +971 -620
  50. package/src/string_interpolation.pyj +5 -3
  51. package/src/tokenizer.pyj +188 -148
  52. package/src/utils.pyj +32 -15
  53. package/test/_treeshake_mod.pyj +30 -0
  54. package/test/_treeshake_side_effect.pyj +9 -0
  55. package/test/ast_serialization.pyj +392 -0
  56. package/test/async.pyj +95 -0
  57. package/test/baselib.pyj +1 -2
  58. package/test/embedded_compiler.pyj +57 -0
  59. package/test/fmt.pyj +291 -0
  60. package/test/generic.pyj +16 -3
  61. package/test/imports.pyj +8 -6
  62. package/test/internationalization.pyj +38 -37
  63. package/test/lint.pyj +120 -117
  64. package/test/lsp.pyj +257 -0
  65. package/test/repl.pyj +70 -65
  66. package/test/sourcemaps.pyj +315 -0
  67. package/test/starargs.pyj +46 -39
  68. package/test/str.pyj +8 -0
  69. package/test/traceback.pyj +263 -0
  70. package/test/treeshaking.pyj +181 -0
  71. package/test/web_repl_export.pyj +88 -0
  72. package/tools/ast_serialize.mjs +557 -0
  73. package/tools/cli.mjs +531 -0
  74. package/tools/compile.mjs +205 -0
  75. package/tools/compiler.mjs +159 -0
  76. package/tools/{completer.js → completer.mjs} +6 -6
  77. package/tools/{embedded_compiler.js → embedded_compiler.mjs} +17 -13
  78. package/tools/export.js +109 -56
  79. package/tools/fmt.mjs +975 -0
  80. package/tools/{gettext.js → gettext.mjs} +46 -53
  81. package/tools/ini.mjs +175 -0
  82. package/tools/{lint.js → lint.mjs} +78 -55
  83. package/tools/lsp.mjs +964 -0
  84. package/tools/lsp_protocol.mjs +259 -0
  85. package/tools/lsp_symbols.mjs +418 -0
  86. package/tools/{msgfmt.js → msgfmt.mjs} +18 -18
  87. package/tools/{repl.js → repl.mjs} +56 -42
  88. package/tools/{self.js → self.mjs} +71 -46
  89. package/tools/sourcemap.mjs +123 -0
  90. package/tools/test.mjs +252 -0
  91. package/tools/treeshake.mjs +400 -0
  92. package/tools/{utils.js → utils.mjs} +26 -23
  93. package/tools/{web_repl.js → web_repl.mjs} +15 -13
  94. package/tools/web_repl_export.mjs +97 -0
  95. package/tree-sitter/README.md +101 -0
  96. package/tree-sitter/grammar.js +992 -0
  97. package/tree-sitter/package.json +43 -0
  98. package/tree-sitter/queries/highlights.scm +232 -0
  99. package/tree-sitter/queries/indents.scm +64 -0
  100. package/tree-sitter/queries/injections.scm +14 -0
  101. package/tree-sitter/queries/locals.scm +108 -0
  102. package/tree-sitter/src/grammar.json +4976 -0
  103. package/tree-sitter/src/node-types.json +2901 -0
  104. package/tree-sitter/src/parser.c +196465 -0
  105. package/tree-sitter/src/scanner.c +294 -0
  106. package/tree-sitter/src/tree_sitter/alloc.h +54 -0
  107. package/tree-sitter/src/tree_sitter/array.h +330 -0
  108. package/tree-sitter/src/tree_sitter/parser.h +286 -0
  109. package/tree-sitter/test/corpus/chaining.txt +99 -0
  110. package/tree-sitter/test/corpus/classes.txt +147 -0
  111. package/tree-sitter/test/corpus/comprehensions.txt +155 -0
  112. package/tree-sitter/test/corpus/containers.txt +242 -0
  113. package/tree-sitter/test/corpus/control_flow.txt +361 -0
  114. package/tree-sitter/test/corpus/decorators.txt +64 -0
  115. package/tree-sitter/test/corpus/existential.txt +102 -0
  116. package/tree-sitter/test/corpus/functions.txt +293 -0
  117. package/tree-sitter/test/corpus/imports.txt +117 -0
  118. package/tree-sitter/test/corpus/literals.txt +135 -0
  119. package/tree-sitter/test/corpus/operators.txt +296 -0
  120. package/tree-sitter/test/corpus/statements.txt +189 -0
  121. package/tree-sitter/test/corpus/strings.txt +90 -0
  122. package/tree-sitter/test/corpus/subscripts.txt +227 -0
  123. package/tree-sitter/tree-sitter.json +36 -0
  124. package/web-repl/env.js +35 -23
  125. package/web-repl/main.js +8 -8
  126. package/bin/export +0 -75
  127. package/bin/web-repl-export +0 -102
  128. package/tools/cli.js +0 -523
  129. package/tools/compile.js +0 -184
  130. package/tools/compiler.js +0 -84
  131. package/tools/ini.js +0 -65
  132. package/tools/test.js +0 -110
package/tools/cli.mjs ADDED
@@ -0,0 +1,531 @@
1
+ /*
2
+ * cli.js
3
+ * Copyright (C) 2015 Kovid Goyal <kovid at kovidgoyal.net>
4
+ *
5
+ * Distributed under terms of the BSD license.
6
+ */
7
+
8
+ import path from 'path';
9
+ import * as utils from './utils.mjs';
10
+ import packageJson from '../package.json' with { type: 'json' };
11
+
12
+ var colored = utils.safe_colored;
13
+ var has_prop = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
14
+
15
+ function OptionGroup(name) {
16
+ this.name = name;
17
+ this.description = undefined;
18
+ this.extra = undefined;
19
+ this.options = {
20
+ 'string': {},
21
+ 'boolean': {},
22
+ 'alias': {},
23
+ 'default': {},
24
+ 'choices': {},
25
+ };
26
+
27
+ this.help = {};
28
+ this.seen = {};
29
+ }
30
+
31
+ var groups = {}, group;
32
+
33
+ function create_group(name, usage, description, extra) {
34
+ group = new OptionGroup(name);
35
+ group.description = description;
36
+ group.usage = name + ' [options] ' + usage;
37
+ groups[name] = group;
38
+
39
+ if (extra) group.extra = extra;
40
+
41
+ opt('help', 'h', 'bool', false, 'show this help message and exit');
42
+
43
+ opt('version', 'V', 'bool', false, 'show the version and exit');
44
+
45
+
46
+ }
47
+
48
+ var COL1 = 'yellow', COL2 = 'green';
49
+
50
+ function print_usage(group) { // {{{
51
+ var COL_WIDTH = 79;
52
+ var OPT_WIDTH = 23;
53
+
54
+ var usage = (group) ? group.usage : "[sub-command] ...";
55
+ console.log(colored('Usage:', COL1), colored(path.basename(process.argv[1]), COL2), usage, '\n');
56
+ if (!group) {
57
+ // Overall usage
58
+ help = ('RapydScript can perform many actions, depending on which' +
59
+ '\nsub-command is invoked. With no arguments, it will start a REPL,' +
60
+ '\nunless STDIN is a pipe, in which case it will compile whatever' +
61
+ '\nyou pass on STDIN and write the output to STDOUT. See the full' +
62
+ '\nlist of sub-commands below.');
63
+ console.log(help, '\n');
64
+ console.log(colored('Sub-commands:', COL1));
65
+ Object.keys(groups).forEach(function (name) {
66
+ console.log();
67
+ var dt = utils.wrap(groups[name].description.split('\n'), COL_WIDTH - OPT_WIDTH);
68
+ console.log(colored((name + utils.repeat(' ', OPT_WIDTH)).slice(0, OPT_WIDTH), COL2), dt[0]);
69
+ dt.slice(1).forEach(function (line) {
70
+ console.log(utils.repeat(' ', OPT_WIDTH), line);
71
+ });
72
+ });
73
+ return;
74
+ }
75
+
76
+ // Group specific usage
77
+
78
+ console.log(group.description);
79
+ if (group.extra) console.log('\n' + group.extra);
80
+ console.log(colored('\nOptions:', COL1));
81
+ var options = group.options;
82
+ var help = group.help;
83
+
84
+ Object.getOwnPropertyNames(options.alias).forEach(function (name) {
85
+ var optstr = ' --' + name.replace(/_/g, '-');
86
+ options.alias[name].forEach(function (alias) {
87
+ optstr += ', ' + ((alias.length > 1) ? '--' : '-') + alias.replace(/_/g, '-');
88
+ });
89
+ var ht = utils.wrap(help[name].split('\n'), COL_WIDTH - OPT_WIDTH);
90
+
91
+ if (optstr.length > OPT_WIDTH) console.log(colored(optstr, COL2));
92
+ else {
93
+ console.log(colored((optstr + utils.repeat(' ', OPT_WIDTH)).slice(0, OPT_WIDTH), COL2), ht[0]);
94
+ ht = ht.splice(1);
95
+ }
96
+ ht.forEach(function (line) {
97
+ console.log(utils.repeat(' ', OPT_WIDTH), line);
98
+ });
99
+ console.log();
100
+ });
101
+
102
+ } // }}}
103
+
104
+ // Process options {{{
105
+
106
+ function opt(name, aliases, type, default_val, help_text, choices) {
107
+ var options = group.options;
108
+ var seen = group.seen;
109
+ var help = group.help;
110
+
111
+ if (!type || type == 'bool') options.boolean[name] = true;
112
+ else if (type == 'string') {
113
+ options.string[name] = true;
114
+ if (choices) options.choices[name] = choices;
115
+ }
116
+
117
+ if (default_val !== undefined) options.default[name] = default_val;
118
+
119
+ if (aliases && aliases.length) {
120
+ aliases.split(',').forEach(function(alias) {
121
+ if (has_prop(seen, alias)) throw "The option name:" + alias + " has already been used.";
122
+ seen[alias] = true;
123
+ });
124
+ options.alias[name] = aliases.split(',');
125
+ } else options.alias[name] = [];
126
+
127
+ if (has_prop(seen, name)) throw "The option name:" + name + " has already been used.";
128
+ seen[name] = true;
129
+
130
+ help[name] = help_text;
131
+ }
132
+ // }}}
133
+
134
+ function parse_args() { // {{{
135
+ var ans = {'files':[]};
136
+ var name_map = {};
137
+ var state, options, group;
138
+
139
+ function plain_arg(arg) {
140
+ if (state !== undefined) ans[state] = arg;
141
+ else ans.files.push(arg);
142
+ state = undefined;
143
+ }
144
+
145
+ function handle_opt(arg) {
146
+ var oarg = arg;
147
+ var is_long_opt = (arg[0] === '-') ? true : false;
148
+ if (is_long_opt) arg = arg.substr(1);
149
+ if (state !== undefined) ans[state] = '';
150
+ state = undefined;
151
+ if (!is_long_opt && arg.length > 1) {
152
+ arg.split('').forEach(handle_opt);
153
+ return;
154
+ }
155
+ var val = arg.indexOf('=');
156
+ if (val > -1) {
157
+ var t = arg.substr(val + 1);
158
+ arg = arg.substr(0, val);
159
+ val = t;
160
+ } else val = undefined;
161
+
162
+ var name = name_map[arg.replace(/-/g, '_')];
163
+ if (!name) {
164
+ print_usage(group);
165
+ console.error('\nThe option:', colored('-' + oarg, 'red'), 'is not recognized');
166
+ process.exit(1);
167
+ }
168
+ if (has_prop(options.boolean, name)) {
169
+ if (!val) val = 'true';
170
+ if (val === 'true' || val === '1') val = true;
171
+ else if (val === 'false' || val === '0') val = false;
172
+ else { console.error('The value:', colored(val, 'red'), 'is invalid for the boolean option:', colored(name, 'red')); process.exit(1); }
173
+ ans[name] = val;
174
+ } else {
175
+ if (val !== undefined) ans[name] = val;
176
+ else state = name;
177
+ }
178
+ }
179
+
180
+ var all_args = process.argv.slice(2);
181
+ ans.auto_mode = false;
182
+ if (has_prop(groups, all_args[0])) {
183
+ ans.mode = all_args[0];
184
+ all_args = all_args.slice(1);
185
+ } else {
186
+ // this check is not robust, but, it will only fail if the repl mode takes any non-boolean options
187
+ var has_files = all_args.filter(function (a) { return a[0] !== '-'; }).length > 0;
188
+ ans.mode = (!has_files && process.stdin.isTTY) ? 'repl' : 'compile';
189
+ ans.auto_mode = true;
190
+ }
191
+ options = groups[ans.mode].options;
192
+
193
+ Object.getOwnPropertyNames(options.default).forEach(function(name) { ans[name] = options['default'][name]; });
194
+
195
+ Object.getOwnPropertyNames(options.alias).forEach(function(name) {
196
+ name_map[name] = name;
197
+ options.alias[name].forEach(function (alias) { name_map[alias] = name; });
198
+ });
199
+
200
+ var options_ended = false;
201
+
202
+ all_args.forEach(function(arg) {
203
+ if (options_ended) plain_arg(arg);
204
+ else if (arg === '--') options_ended = true;
205
+ else if (arg === '-') plain_arg(arg);
206
+
207
+ else if (arg[0] === '-') handle_opt(arg.substr(1));
208
+
209
+ else plain_arg(arg);
210
+ });
211
+ if (state !== undefined) plain_arg('');
212
+ Object.keys(options.choices).forEach(function(name) {
213
+ var allowed = options.choices[name];
214
+ if (allowed.indexOf(ans[name]) < 0) {
215
+ print_usage(groups[ans.mode]);
216
+ console.error('The value "' + colored(ans[name], 'red') + '" is not allowed for ' + colored(name, 'red') + '. Allowed values: ' + options.choices[name].join(', '));
217
+ process.exit(1);
218
+ }
219
+ });
220
+ return ans;
221
+ } // }}}
222
+
223
+ create_group('compile', "[input1.pyj input2.pyj ...]", `Compile RapydScript source code into JavaScript
224
+ output. You can also pipe the source code into
225
+ stdin.`);
226
+
227
+ opt("output", 'o', 'string', '', `Output file (default STDOUT)`);
228
+
229
+ opt("bare", 'b', 'bool', false, `Remove the module wrapper that prevents RapydScript
230
+ scope from bleeding into other JavaScript logic`);
231
+
232
+ opt("keep_docstrings", 'd', 'bool', false, `Keep the docstrings in the generated JavaScript as __doc__
233
+ attributes on functions, classes and modules. Normally,
234
+ the docstring are deleted to reduce download size.`);
235
+
236
+ opt("discard_asserts", 'a', 'bool', false, `Discard any assert statements. If you use assert statements
237
+ for debugging, then use this option to generate an optimized build
238
+ without the assert statements.`);
239
+
240
+ opt("uglify", 'u', 'bool', false, `Minify the output instead of pretty printing it.`);
241
+
242
+ opt("omit_baselib", 'm', 'bool', false, `Omit baselib functions. Use this if you have a
243
+ different way of ensuring they're imported. For example,
244
+ you could import one of the baselib-plain-*.js files directly
245
+ into the global namespace.`);
246
+
247
+ opt("js_version", 'js,j', 'string', '6', `The JavaScript version to output. ES 6
248
+ compatible JavaScript is output. Only ES 6 is supported.`, ['6']);
249
+
250
+ opt("import_path", "p", 'string', '', `A list of paths in which to look for imported modules.
251
+ Multiple paths must be separated by the path separator
252
+ (: on Unix and ; on Windows). You can also use the
253
+ environment variable RAPYDSCRIPT_IMPORT_PATH for this,
254
+ with identical syntax. Note that these directories
255
+ are searched before the builtin paths, which means you
256
+ can use them to replace builtin modules.`);
257
+
258
+ opt("filename_for_stdin", "P", 'string', '', `filename to use for data piped into STDIN. Imports will
259
+ be resolved relative to the directory this filename is in.
260
+ Note, that you can also use the --import-path option to
261
+ add directories to the import path.`);
262
+
263
+ opt("cache_dir", "C", 'string', '', `directory to use to store the cached files generated
264
+ by the compiler. Normally, these are stored right next to
265
+ every compiled pyj file, with the extension pyj-cached. This
266
+ option allows them to be consolidated in a single directory.`);
267
+
268
+ opt("comments", undefined, 'string', '', `Preserve copyright comments in the output.
269
+ By default this works like Google Closure, keeping
270
+ JSDoc-style comments that contain "@license" or
271
+ "@preserve". You can optionally pass one of the
272
+ following arguments to this flag:
273
+ - "all" to keep all comments
274
+ - a valid JS regexp (needs to start with a slash) to
275
+ keep only comments that match.
276
+
277
+ Note that currently not *all* comments can be kept
278
+ when compression is on, because of dead code removal
279
+ or cascading statements into sequences.`);
280
+
281
+ opt("stats", undefined, 'bool', false, `Display operations run time on STDERR.`);
282
+
283
+ opt("tree_shaking", 'T,tree-shake', 'bool', false, `Enable tree shaking (dead code elimination). Removes
284
+ unused top-level functions and classes from the compiled
285
+ output. If an imported module is referenced only from
286
+ dead code, its import is removed entirely. Stdlib
287
+ modules that are not used are also removed.
288
+ Defaults to off. You can use the @no_prune decorator
289
+ to prevent functions or classes from being pruned
290
+ even when they are unused.`);
291
+
292
+ opt("execute", 'x,exec', 'bool', false, `Compile and execute the RapydScript code, all in
293
+ one invocation. Useful if you wish to use RapydScript for
294
+ scripting. Note that you can also use the -o option to
295
+ have the compiled JavaScript written out to a file
296
+ before being executed. If you specify this option you
297
+ should not specify the -m option to omit the baselib, or
298
+ execution will fail.`);
299
+
300
+ opt("source_map_line_offset", '', 'number', 0, `Shift all generated line numbers in the source map by
301
+ this many lines. Useful when the compiled JavaScript will
302
+ be embedded inside a larger file (e.g. prepended with a
303
+ header), so that debugger mappings remain accurate.`);
304
+
305
+ opt("source_map", 'S,sm', 'string', '', `Generate a source map and write it to the specified
306
+ file path. A source map allows debuggers to map
307
+ positions in the compiled JavaScript back to the
308
+ original RapydScript source. When --output is set,
309
+ a //# sourceMappingURL comment is automatically
310
+ appended to the JavaScript output. When outputting
311
+ to stdout, the comment is omitted since no output
312
+ path is available to compute the URL.`);
313
+
314
+ create_group('repl', '', `Run a Read-Eval-Print-Loop (REPL). This allows
315
+ you to type and run RapydScript at a live
316
+ command prompt.`);
317
+
318
+ opt("no_js", '', 'bool', false, `Do not display the compiled JavaScript before executing
319
+ it.`);
320
+
321
+ create_group('lint', "[input1.pyj input2.pyj ...]", `Run the RapydScript linter. This will find various
322
+ possible problems in the .pyj files you specify and
323
+ write messages about them to stdout. Use - to read from STDIN.
324
+ The main check it performs is for unused/undefined
325
+ symbols, like pyflakes does for python.`,
326
+ `In addition to the command line options listed below,
327
+ you can also control the linter in a couple of other ways.
328
+
329
+ In the actual source files, you can turn off specific checks
330
+ on a line by line basis by adding: # noqa:check1,check2...
331
+ to the end of the line. For example:
332
+
333
+ f() # noqa: undef
334
+
335
+ will prevent the linter from showing undefined symbol
336
+ errors for this line. You can also turn off individual checks
337
+ at the file level, by putting the noqa directive on a
338
+ line by itself near the top of the file, for example:
339
+
340
+ # noqa: undef
341
+
342
+ Similarly, you can tell the linter
343
+ about global (builtin) symbols with a comment near the top
344
+ of the file, for example:
345
+
346
+ # globals:assert,myglobalvar
347
+
348
+ This will prevent the linter form treating these names as
349
+ undefined symbols.
350
+
351
+ Finally, the linter looks for a setup.cfg file in the
352
+ directory containing the file being linted or any of its
353
+ parent directories. You can both turn off individual checks
354
+ and define project specific global symbols in the setup.cfg
355
+ file, like this:
356
+
357
+ [rapydscript]
358
+ globals=myglobalvar,otherglobalvar
359
+ noqa=undef,eol-semicolon`);
360
+
361
+ opt("globals", 'g,b,builtins', 'string', '', `Comma separated list of additional names that the linter will
362
+ treat as global symbols. It ignores undefined errors for
363
+ global symbols.`);
364
+
365
+ opt("noqa", 'e,ignore,exclude', 'string', '', `Comma separated list of linter checks to skip. The linter
366
+ will not report errors corresponding to these checks.
367
+ The check names are output in the linter's normal output, you
368
+ can also list all check names with --noqa-list.`);
369
+
370
+ opt("errorformat", 'f,s,style', 'string', 'human', `Output the results in the specified format. Valid formats are:
371
+ human - output is suited for reading by humans (the default)
372
+ json - output is in JSON format
373
+ vim - output can be consumed easily by vim's errorformat
374
+ directive. Format is:
375
+ filename:line:col:errortype:token:message [identifier]
376
+ undef - output only the names of undefined symbols in a form that
377
+ can be easily copy/pasted`, ['human', 'json', 'vim', 'undef']);
378
+
379
+ opt("noqa_list", '', 'bool', false, `List all available linter checks, with a brief
380
+ description, and exit.`);
381
+
382
+ opt('stdin_filename', '', 'string', 'STDIN', `The filename for data read from STDIN. If not specified
383
+ STDIN is used.`);
384
+
385
+ opt('input_list', 'l', 'string', '', `Read the list of input files from the specified file,
386
+ one filename per line. Use - to read the list from STDIN.
387
+ Cannot be combined with - as an input file.`);
388
+
389
+ create_group('test', '[test1 test2...]', `Run RapydScript tests. You can specify the name of
390
+ individual test files to only run tests from those
391
+ files. For example:
392
+ test baselib functions`);
393
+
394
+ create_group('self', '', `Compile the compiler itself. It will only actually
395
+ compile if something has changed since the last time
396
+ it was called. To force a recompilation, simply
397
+ delete lib/signatures.json`);
398
+
399
+ opt("complete", 'c,f,full', 'bool', false, `Run the compilation repeatedly, as many times as neccessary,
400
+ so that the compiler is built with the most upto date version
401
+ of itself.`);
402
+
403
+ opt("test", 't', 'bool', false, `Run the test suite after building completes.`);
404
+
405
+ opt("profile", 'p', 'bool', false, `Run a CPU profiler which will output its data to
406
+ self.cpuprofile. The data can then be analysed with
407
+ node-inspector.`);
408
+
409
+ create_group('gettext', "[input1.pyj input_dir ...]", `Extract strings marked for translation from the specified
410
+ source files and directories.`,
411
+ `Directories are scanned recursively for .pyj files. If no
412
+ arguments are specified, the source code is read from stdin.
413
+
414
+ Translatable string are output on stdout in the .po format.
415
+ Translatable strings are detected in the input as literal
416
+ string arguments to the functions _(), gettext() and ngettext().`);
417
+
418
+ opt("omit_header", 'm', 'bool', false, `Do not write header with 'msgid ""' entry.`);
419
+
420
+ opt("package_name", '', 'string', 'XXX', `Set the package name in the header`);
421
+
422
+ opt("package_version", '', 'string', 'XXX', `Set the package version in the header`);
423
+
424
+ opt("bugs_address", 'bug_address', 'string', 'bugs@example.com', `Set the email address for bug reports in the header`);
425
+
426
+ create_group('msgfmt', "", `Compile a .po file into a .json file that can
427
+ be used to load translations in a browser.`,
428
+ `The .po file is read from
429
+ stdin and the .json file written to stdout. Note
430
+ that it is assumed the .po file is encoded in UTF-8.
431
+ If you .po file is in some other encoding, you will need to
432
+ convert it to UTF-8 first.`);
433
+
434
+ opt("use_fuzzy", 'f', 'bool', false, `Use fuzzy translations, they are ignored by default.`);
435
+
436
+ create_group('web-repl-export', '<output-directory>', `Export the web REPL to a directory. Creates a
437
+ self-contained set of files including index.html that
438
+ you can open in a browser to use the RapydScript web REPL.`);
439
+
440
+ create_group('fmt', "[input1.pyj dir1 ...]", `Format RapydScript source code according to PEP8
441
+ style guidelines (adapted sensibly for RapydScript
442
+ specific syntax such as multi-line anonymous functions).`,
443
+ `If files and/or directories are specified, they are formatted in place.
444
+ Directories are scanned recursively for .pyj files. Use the --check-only
445
+ option to instead report files that would be reformatted without changing
446
+ them.
447
+
448
+ If no files or directories are specified, the source code is read from
449
+ STDIN and the formatted result is written to STDOUT.`);
450
+
451
+ opt("line_length", 'l', 'string', '80', `The maximum allowed line length. Lines longer than this
452
+ are wrapped where it is safe to do so. Defaults to 80.
453
+ If not specified, the value is read from pyproject.toml
454
+ (searched upward from the current directory) under
455
+ [tool.ruff], [tool.black], or [tool.isort].`);
456
+
457
+ opt("preferred_quote", 'q', 'string', 'single', `The preferred quote character for string literals. Either
458
+ "single" or "double". A string is only re-quoted when doing
459
+ so does not increase the number of backslash escapes.
460
+ Defaults to single. If not specified, the value is read from
461
+ pyproject.toml (searched upward from the current directory)
462
+ under [tool.ruff.format], [tool.ruff.lint.flake8-quotes],
463
+ or [tool.flake8].`, ['single', 'double']);
464
+
465
+ opt("check_only", 'c', 'bool', false, `Do not modify files. Instead, print the names of files that
466
+ would be reformatted (and any lines that exceed the maximum
467
+ length) to STDERR. Exit with a status of 1 if any issues are
468
+ found, otherwise 0.`);
469
+
470
+ opt("join_lines", 'j', 'bool', false, `Join multi-line statements that fit within the maximum line
471
+ length onto a single line. Disabled by default: source line
472
+ breaks inside statements are preserved as long as no line
473
+ exceeds the maximum length.`);
474
+
475
+ create_group('lsp', "", `Run a Language Server Protocol (LSP) server for RapydScript.
476
+ The server communicates over stdin/stdout using the standard
477
+ LSP JSON-RPC framing and provides code completion, diagnostics,
478
+ hover information, code actions, document formatting, go to
479
+ definition, find all references and symbol renaming.`,
480
+ `The server is meant to be launched by an LSP client (editor). It
481
+ reads requests from STDIN and writes responses to STDOUT, so do
482
+ not use it interactively.
483
+
484
+ Imports are resolved using the same --import-path option as the
485
+ compile sub-command. Diagnostics reuse the linter and add checks
486
+ for unresolved imports. Document formatting reuses the fmt
487
+ sub-command and is controlled by the --line-length and
488
+ --preferred-quote options.`);
489
+
490
+ opt("import_path", "p", 'string', '', `A list of paths in which to look for imported modules, used to
491
+ resolve imports for diagnostics and go-to-definition. Multiple
492
+ paths must be separated by the path separator (: on Unix and ; on
493
+ Windows). You can also use the environment variable
494
+ RAPYDSCRIPT_IMPORT_PATH for this, with identical syntax.`);
495
+
496
+ opt("line_length", 'l', 'string', '80', `The maximum allowed line length used by the document formatter.
497
+ Lines longer than this are wrapped where it is safe to do so.
498
+ Defaults to 80. If not specified, the value is read from
499
+ pyproject.toml (searched upward from the working directory)
500
+ under [tool.ruff], [tool.black], or [tool.isort].`);
501
+
502
+ opt("preferred_quote", 'q', 'string', 'single', `The preferred quote character used by the document formatter.
503
+ Either "single" or "double". Defaults to single. If not
504
+ specified, the value is read from pyproject.toml (searched
505
+ upward from the working directory) under [tool.ruff.format],
506
+ [tool.ruff.lint.flake8-quotes], or [tool.flake8].`, ['single', 'double']);
507
+
508
+ opt("join_lines", 'j', 'bool', false, `Join multi-line statements that fit within the maximum line
509
+ length onto a single line. Disabled by default: source line
510
+ breaks inside statements are preserved as long as no line
511
+ exceeds the maximum length.`);
512
+
513
+
514
+ export var argv = parse_args();
515
+ if (typeof argv.js_version === 'string') {
516
+ argv.js_version = parseInt(argv.js_version);
517
+ if (isNaN(argv.js_version)) {
518
+ console.log('--js-version must be a number');
519
+ process.exit(1);
520
+ }
521
+ }
522
+
523
+ if (argv.help) {
524
+ print_usage((!argv.auto_mode) ? groups[argv.mode]: undefined);
525
+ process.exit(0);
526
+ }
527
+
528
+ if (argv.version) {
529
+ console.log(packageJson.name + ' ' + packageJson.version);
530
+ process.exit(0);
531
+ }