rapydscript-ng 0.7.24 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +72 -26
- package/bin/package.json +1 -0
- package/bin/rapydscript +65 -62
- package/editor-plugins/nvim/rapydscript/README.md +184 -0
- package/editor-plugins/nvim/rapydscript/bin/rapydscript.so +0 -0
- package/editor-plugins/nvim/rapydscript/ftdetect/rapydscript.lua +10 -0
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/health.lua +88 -0
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/init.lua +279 -0
- package/local-agent.md +28 -0
- package/package.json +4 -5
- package/release/baselib-plain-pretty.js +448 -326
- package/release/baselib-plain-ugly.js +3 -3
- package/release/compiler.js +2528 -1672
- package/release/signatures.json +17 -17
- package/src/ast.pyj +73 -25
- package/src/baselib-builtins.pyj +2 -2
- package/src/baselib-containers.pyj +153 -151
- package/src/baselib-internal.pyj +3 -3
- package/src/baselib-str.pyj +5 -5
- package/src/lib/aes.pyj +1 -1
- package/src/lib/encodings.pyj +1 -1
- package/src/lib/pythonize.pyj +1 -1
- package/src/lib/re.pyj +2 -2
- package/src/lib/traceback.pyj +165 -28
- package/src/lib/uuid.pyj +1 -1
- package/src/output/codegen.pyj +10 -3
- package/src/output/functions.pyj +31 -40
- package/src/output/literals.pyj +11 -14
- package/src/output/loops.pyj +25 -87
- package/src/output/modules.pyj +5 -47
- package/src/output/statements.pyj +1 -1
- package/src/output/stream.pyj +58 -31
- package/src/parse.pyj +777 -427
- package/src/tokenizer.pyj +16 -4
- package/src/utils.pyj +1 -1
- package/test/_treeshake_mod.pyj +30 -0
- package/test/_treeshake_side_effect.pyj +9 -0
- package/test/ast_serialization.pyj +392 -0
- package/test/async.pyj +95 -0
- package/test/baselib.pyj +1 -2
- package/test/embedded_compiler.pyj +57 -0
- package/test/fmt.pyj +201 -0
- package/test/generic.pyj +7 -3
- package/test/imports.pyj +8 -6
- package/test/internationalization.pyj +38 -37
- package/test/lint.pyj +120 -117
- package/test/lsp.pyj +222 -0
- package/test/repl.pyj +70 -65
- package/test/sourcemaps.pyj +315 -0
- package/test/starargs.pyj +46 -39
- package/test/traceback.pyj +263 -0
- package/test/treeshaking.pyj +181 -0
- package/test/web_repl_export.pyj +88 -0
- package/tools/ast_serialize.mjs +557 -0
- package/tools/cli.mjs +510 -0
- package/tools/compile.mjs +201 -0
- package/tools/compiler.mjs +127 -0
- package/tools/{completer.js → completer.mjs} +6 -6
- package/tools/{embedded_compiler.js → embedded_compiler.mjs} +17 -13
- package/tools/export.js +109 -56
- package/tools/fmt.mjs +735 -0
- package/tools/{gettext.js → gettext.mjs} +46 -53
- package/tools/{ini.js → ini.mjs} +9 -10
- package/tools/{lint.js → lint.mjs} +78 -55
- package/tools/lsp.mjs +914 -0
- package/tools/lsp_protocol.mjs +259 -0
- package/tools/lsp_symbols.mjs +418 -0
- package/tools/{msgfmt.js → msgfmt.mjs} +18 -18
- package/tools/{repl.js → repl.mjs} +52 -41
- package/tools/{self.js → self.mjs} +56 -46
- package/tools/sourcemap.mjs +123 -0
- package/tools/test.mjs +152 -0
- package/tools/treeshake.mjs +400 -0
- package/tools/{utils.js → utils.mjs} +26 -23
- package/tools/{web_repl.js → web_repl.mjs} +15 -13
- package/tools/web_repl_export.mjs +93 -0
- package/tree-sitter/README.md +101 -0
- package/tree-sitter/grammar.js +992 -0
- package/tree-sitter/package.json +43 -0
- package/tree-sitter/queries/rapydscript/highlights.scm +232 -0
- package/tree-sitter/queries/rapydscript/indents.scm +64 -0
- package/tree-sitter/queries/rapydscript/injections.scm +14 -0
- package/tree-sitter/queries/rapydscript/locals.scm +108 -0
- package/tree-sitter/src/grammar.json +4976 -0
- package/tree-sitter/src/node-types.json +2901 -0
- package/tree-sitter/src/parser.c +196465 -0
- package/tree-sitter/src/scanner.c +294 -0
- package/tree-sitter/src/tree_sitter/alloc.h +54 -0
- package/tree-sitter/src/tree_sitter/array.h +330 -0
- package/tree-sitter/src/tree_sitter/parser.h +286 -0
- package/tree-sitter/test/corpus/chaining.txt +99 -0
- package/tree-sitter/test/corpus/classes.txt +147 -0
- package/tree-sitter/test/corpus/comprehensions.txt +155 -0
- package/tree-sitter/test/corpus/containers.txt +242 -0
- package/tree-sitter/test/corpus/control_flow.txt +361 -0
- package/tree-sitter/test/corpus/decorators.txt +64 -0
- package/tree-sitter/test/corpus/existential.txt +102 -0
- package/tree-sitter/test/corpus/functions.txt +293 -0
- package/tree-sitter/test/corpus/imports.txt +117 -0
- package/tree-sitter/test/corpus/literals.txt +135 -0
- package/tree-sitter/test/corpus/operators.txt +296 -0
- package/tree-sitter/test/corpus/statements.txt +189 -0
- package/tree-sitter/test/corpus/strings.txt +90 -0
- package/tree-sitter/test/corpus/subscripts.txt +227 -0
- package/tree-sitter/tree-sitter.json +36 -0
- package/web-repl/env.js +35 -23
- package/web-repl/main.js +8 -8
- package/bin/export +0 -75
- package/bin/web-repl-export +0 -102
- package/tools/cli.js +0 -523
- package/tools/compile.js +0 -184
- package/tools/compiler.js +0 -84
- package/tools/test.js +0 -110
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
version 0.8.0
|
|
2
|
+
=======================
|
|
3
|
+
|
|
4
|
+
* Implement generation of source maps via the --source-map option
|
|
5
|
+
* Implement dead code removal via the --tree-shaking option
|
|
6
|
+
* Add support for async and await
|
|
7
|
+
* Implement a ``fmt`` command for code formatting and an ``lsp`` command for a Language Server
|
|
8
|
+
* Implement a tree sitter grammar so that robust syntax highlighting is potentially available in all editors
|
|
9
|
+
* Implement a neovim plugin that enables treesitter based syntax highlighting and LSP server for ``.pyj`` files
|
|
10
|
+
* Implement support for importing user modules in the embedded compiler
|
|
11
|
+
* Double the compilation speed, especially useful for large projects
|
|
12
|
+
* Drop support for ES5
|
|
13
|
+
* List objects are now unmodified JS Arrays for greater performance. Python
|
|
14
|
+
list methods continue to work.
|
|
15
|
+
* Change the cache format to cache only the AST and not final output so that
|
|
16
|
+
the cache can be re-used regardless of output and tree shaking options
|
|
17
|
+
* Make the compiler internally use async IO. This means the embedded compiler
|
|
18
|
+
functions are also async.
|
|
19
|
+
|
|
1
20
|
version 0.7.24
|
|
2
21
|
=======================
|
|
3
22
|
|
package/README.md
CHANGED
|
@@ -42,11 +42,13 @@ backwards compatible) features. For more on the forking, [see the bottom of this
|
|
|
42
42
|
- [Method Binding](#method-binding)
|
|
43
43
|
- [Iterators](#iterators)
|
|
44
44
|
- [Generators](#generators)
|
|
45
|
+
- [Asnyc and Await](#async-and-await)
|
|
45
46
|
- [Modules](#modules)
|
|
46
47
|
- [Exception Handling](#exception-handling)
|
|
47
48
|
- [Scope Control](#scope-control)
|
|
48
49
|
- [Available Libraries](#available-libraries)
|
|
49
50
|
- [Linter](#linter)
|
|
51
|
+
- [Language Server (LSP)](#language-server-lsp)
|
|
50
52
|
- [Making RapydScript even more pythonic](#making-rapydscript-even-more-pythonic)
|
|
51
53
|
- [Advanced Usage Topics](#advanced-usage-topics)
|
|
52
54
|
- [Browser Compatibility](#browser-compatibility)
|
|
@@ -1254,9 +1256,12 @@ syntax.
|
|
|
1254
1256
|
Generators create JavaScript iterator objects. For differences between python
|
|
1255
1257
|
and JavaScript iterators, see the section on iterators above.
|
|
1256
1258
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1259
|
+
Async and Await
|
|
1260
|
+
------------------
|
|
1261
|
+
|
|
1262
|
+
Python's ``async`` and ``await`` keywords are supported, but note that async
|
|
1263
|
+
functions return JavaScript Promise objects not co-routines. This is so that
|
|
1264
|
+
they interoperate with the JS ecosystem and browser APIs in particular.
|
|
1260
1265
|
|
|
1261
1266
|
Modules
|
|
1262
1267
|
-------
|
|
@@ -1427,6 +1432,41 @@ that the linter will not raise undefined errors for. You can turn off
|
|
|
1427
1432
|
individual checks that you do not find useful. See ``rapydscript lint -h`` for
|
|
1428
1433
|
details.
|
|
1429
1434
|
|
|
1435
|
+
Language Server (LSP)
|
|
1436
|
+
-----------------------
|
|
1437
|
+
|
|
1438
|
+
RapydScript ships with a Language Server Protocol server so that editors can
|
|
1439
|
+
offer rich language support for ``.pyj`` files. Start it with:
|
|
1440
|
+
|
|
1441
|
+
rapydscript lsp
|
|
1442
|
+
|
|
1443
|
+
The server talks the standard LSP JSON-RPC protocol over stdin/stdout, so it is
|
|
1444
|
+
meant to be launched by an editor/LSP client rather than run interactively. It
|
|
1445
|
+
provides:
|
|
1446
|
+
|
|
1447
|
+
- **Code completion** — in-scope symbols, builtins and keywords, plus member
|
|
1448
|
+
completion for imported modules (``mod.<complete>``).
|
|
1449
|
+
- **Diagnostics** — the same checks as the ``lint`` sub-command, plus warnings
|
|
1450
|
+
for imports that cannot be resolved in the import path. The parser recovers
|
|
1451
|
+
from syntax errors, so a file that is being edited is still analysed (and
|
|
1452
|
+
multiple errors can be reported at once).
|
|
1453
|
+
- **Hover** — the kind, origin and docstring of the symbol under the cursor.
|
|
1454
|
+
- **Code actions** — quick fixes such as removing an unused import/local,
|
|
1455
|
+
silencing a check with a ``# noqa`` comment, and formatting the document.
|
|
1456
|
+
- **Document formatting** — the same formatter as the ``fmt`` sub-command,
|
|
1457
|
+
controlled by ``--line-length`` and ``--preferred-quote``.
|
|
1458
|
+
- **Go to definition** — including jumping into imported modules.
|
|
1459
|
+
- **Find all references** — resolved across files through the import graph.
|
|
1460
|
+
- **Rename** — renames a symbol everywhere it is used across the workspace.
|
|
1461
|
+
|
|
1462
|
+
Imports are resolved with the same ``--import-path`` (``-p``) option as the
|
|
1463
|
+
``compile`` sub-command, so point it at your project's import directories. For
|
|
1464
|
+
example:
|
|
1465
|
+
|
|
1466
|
+
rapydscript lsp --import-path src:vendor --line-length 100
|
|
1467
|
+
|
|
1468
|
+
See ``rapydscript lsp -h`` for the full list of options.
|
|
1469
|
+
|
|
1430
1470
|
Making RapydScript even more pythonic
|
|
1431
1471
|
---------------------------------------
|
|
1432
1472
|
|
|
@@ -1454,11 +1494,9 @@ Advanced Usage Topics
|
|
|
1454
1494
|
|
|
1455
1495
|
#### Browser Compatibility
|
|
1456
1496
|
|
|
1457
|
-
RapydScript compiles your code
|
|
1458
|
-
|
|
1459
|
-
``--js-version`` option
|
|
1460
|
-
code is smaller and faster than the ES 5 version, but is not as widely
|
|
1461
|
-
compatible.
|
|
1497
|
+
RapydScript compiles your code to ES 6 compatible JavaScript. Any modern
|
|
1498
|
+
browser or Node.js version that supports ES 6 will run the output. The
|
|
1499
|
+
``--js-version`` option only accepts ``6``.
|
|
1462
1500
|
|
|
1463
1501
|
#### Tabs vs Spaces
|
|
1464
1502
|
|
|
@@ -1491,9 +1529,9 @@ To do so, simply include the [embeddable rapydscript compiler](https://sw.kovidg
|
|
|
1491
1529
|
in your page, and use it to compile arbitrary RapydScript code.
|
|
1492
1530
|
|
|
1493
1531
|
You create the compiler by calling: `RapydScript.create_embedded_compiler()` and compile
|
|
1494
|
-
code with `compiler.compile(code)`.
|
|
1495
|
-
|
|
1496
|
-
HTML below for an example.
|
|
1532
|
+
code with `await compiler.compile(code)`. Both calls return Promises, so you must use
|
|
1533
|
+
`async`/`await` (or `.then()`) to get the results. You can execute the resulting JavaScript
|
|
1534
|
+
using the standard `eval()` function. See the sample HTML below for an example.
|
|
1497
1535
|
|
|
1498
1536
|
```html
|
|
1499
1537
|
<!DOCTYPE html>
|
|
@@ -1503,9 +1541,9 @@ HTML below for an example.
|
|
|
1503
1541
|
<title>Test embedded RapydScript</title>
|
|
1504
1542
|
<script charset="UTF-8" src="https://sw.kovidgoyal.net/rapydscript/repl/rapydscript.js"></script>
|
|
1505
1543
|
<script>
|
|
1506
|
-
|
|
1507
|
-
var
|
|
1508
|
-
|
|
1544
|
+
window.onload = async function() {
|
|
1545
|
+
var compiler = await RapydScript.create_embedded_compiler();
|
|
1546
|
+
var js = await compiler.compile("def hello_world():\n a='RapydScript is cool!'\n print(a)\n alert(a)");
|
|
1509
1547
|
document.body.textContent = js;
|
|
1510
1548
|
eval(js);
|
|
1511
1549
|
eval('hello_world()');
|
|
@@ -1519,20 +1557,28 @@ window.onload = function() {
|
|
|
1519
1557
|
There are a couple of caveats when using the embedded compiler:
|
|
1520
1558
|
|
|
1521
1559
|
* It only works when run in a modern browser (one that supports ES6) so no
|
|
1522
|
-
Internet Explorer.
|
|
1523
|
-
an option to the compile() method, like this:
|
|
1524
|
-
```
|
|
1525
|
-
compiler.compile(code, {js_version:5})
|
|
1526
|
-
```
|
|
1527
|
-
Note that doing this means that you cannot use generators and the
|
|
1528
|
-
yield keyword in your RapydScript code.
|
|
1560
|
+
Internet Explorer.
|
|
1529
1561
|
|
|
1530
|
-
*
|
|
1531
|
-
|
|
1562
|
+
* To implement importing of modules you need to create a virtual file system
|
|
1563
|
+
like this, before calling ``create_embedded_compiler()``:
|
|
1532
1564
|
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1565
|
+
```
|
|
1566
|
+
RapydScript.virtual_file_system = {
|
|
1567
|
+
read_file: my_read_file,
|
|
1568
|
+
write_file: my_write_file,
|
|
1569
|
+
stat_file: my_stat_file
|
|
1570
|
+
}
|
|
1571
|
+
```
|
|
1572
|
+
These functions should have the same signature and semantics as the
|
|
1573
|
+
``fs.promises.readFile, fs.promises.writeFile and fs.promises.statFile``
|
|
1574
|
+
functions from Node. Currently only the ``mtimeMs`` field from the stat
|
|
1575
|
+
result is needed. They will be passed file paths starting with ``__vfs__/``
|
|
1576
|
+
and should read/write/stat them as needed.
|
|
1577
|
+
|
|
1578
|
+
* To generate the embedded compiler yourself (rapydscript.js)
|
|
1579
|
+
run `rapydscript web-repl-export /path/to/export/directory`.
|
|
1580
|
+
Then you can simply open the ``index.html`` file in that directory in a browser
|
|
1581
|
+
to see the web REPL in action.
|
|
1536
1582
|
|
|
1537
1583
|
Internationalization
|
|
1538
1584
|
-------------------------
|
package/bin/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|
package/bin/rapydscript
CHANGED
|
@@ -1,70 +1,73 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
// vim:ft=javascript:ts=4:et
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import * as utils from '../tools/utils.mjs';
|
|
8
|
+
import { create_compiler } from '../tools/compiler.mjs';
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
|
|
12
|
+
var start_time = new Date().getTime();
|
|
13
|
+
|
|
14
|
+
var { argv } = await import('../tools/cli.mjs');
|
|
15
|
+
|
|
16
|
+
var base_path = path.normalize(path.join(path.dirname(__filename), ".."));
|
|
17
|
+
var src_path = path.join(base_path, 'src');
|
|
18
|
+
var lib_path = path.join(base_path, 'dev');
|
|
19
|
+
if (!(await utils.path_exists(path.join(lib_path, 'compiler.js')))) lib_path = path.join(base_path, 'release');
|
|
9
20
|
|
|
10
|
-
|
|
21
|
+
// Create compiler instance once, then expose it synchronously via the global
|
|
22
|
+
// so bundled modules (repl, gettext, etc.) can call create_rapydscript_compiler() synchronously.
|
|
23
|
+
const _compiler_instance = await create_compiler();
|
|
24
|
+
globalThis.create_rapydscript_compiler = () => _compiler_instance;
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
console.error('RapydScript needs ES 6 generators, update your version of nodejs');
|
|
16
|
-
process.exit(1);
|
|
26
|
+
if (argv.mode === 'self') {
|
|
27
|
+
if (argv.files.length > 0) {
|
|
28
|
+
console.error("WARN: Ignoring input files since --self was passed");
|
|
17
29
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
var start_time = new Date().getTime();
|
|
25
|
-
var path = require('path');
|
|
26
|
-
|
|
27
|
-
var argv = load('cli').argv;
|
|
28
|
-
|
|
29
|
-
var base_path = path.normalize(path.join(path.dirname(module.filename), ".."));
|
|
30
|
-
var src_path = path.join(base_path, 'src');
|
|
31
|
-
var lib_path = path.join(base_path, 'dev');
|
|
32
|
-
if (!utils.path_exists(path.join(lib_path, 'compiler.js'))) lib_path = path.join(base_path, 'release');
|
|
33
|
-
|
|
34
|
-
if (argv.mode === 'self') {
|
|
35
|
-
if (argv.files.length > 0) {
|
|
36
|
-
console.error("WARN: Ignoring input files since --self was passed");
|
|
37
|
-
}
|
|
38
|
-
load('self')(base_path, src_path, lib_path, argv.complete, argv.profile);
|
|
39
|
-
if (argv.test) {
|
|
40
|
-
console.log('\nRunning test suite...\n');
|
|
41
|
-
argv.files = []; // Ensure all tests are run
|
|
42
|
-
load('test')(argv, base_path, src_path, path.join(base_path, 'dev'));
|
|
43
|
-
}
|
|
44
|
-
process.exit(0);
|
|
45
|
-
} else
|
|
46
|
-
|
|
47
|
-
if (argv.mode === 'test') {
|
|
48
|
-
load('test')(argv, base_path, src_path, lib_path);
|
|
49
|
-
} else
|
|
50
|
-
|
|
51
|
-
if (argv.mode === 'lint') {
|
|
52
|
-
load('lint').cli(argv, base_path, src_path, lib_path);
|
|
53
|
-
} else
|
|
54
|
-
|
|
55
|
-
if (argv.mode === 'repl') {
|
|
56
|
-
load('repl')({'lib_path':lib_path, 'imp_path':path.join(src_path, 'lib'), show_js:!argv.no_js});
|
|
57
|
-
} else
|
|
58
|
-
|
|
59
|
-
if (argv.mode === 'gettext') {
|
|
60
|
-
load('gettext').cli(argv, base_path, src_path, lib_path);
|
|
61
|
-
} else
|
|
62
|
-
|
|
63
|
-
if (argv.mode === 'msgfmt') {
|
|
64
|
-
load('msgfmt').cli(argv, base_path, src_path, lib_path);
|
|
65
|
-
} else
|
|
66
|
-
|
|
67
|
-
{
|
|
68
|
-
load('compile')(start_time, argv, base_path, src_path, lib_path);
|
|
30
|
+
await (await import('../tools/self.mjs')).default(base_path, src_path, lib_path, argv.complete, argv.profile);
|
|
31
|
+
if (argv.test) {
|
|
32
|
+
console.log('\nRunning test suite...\n');
|
|
33
|
+
argv.files = []; // Ensure all tests are run
|
|
34
|
+
await (await import('../tools/test.mjs')).default(argv, base_path, src_path, path.join(base_path, 'dev'));
|
|
69
35
|
}
|
|
36
|
+
process.exit(0);
|
|
37
|
+
} else
|
|
38
|
+
|
|
39
|
+
if (argv.mode === 'test') {
|
|
40
|
+
await (await import('../tools/test.mjs')).default(argv, base_path, src_path, lib_path);
|
|
41
|
+
} else
|
|
42
|
+
|
|
43
|
+
if (argv.mode === 'lint') {
|
|
44
|
+
await (await import('../tools/lint.mjs')).cli(argv, base_path, src_path, lib_path);
|
|
45
|
+
} else
|
|
46
|
+
|
|
47
|
+
if (argv.mode === 'fmt') {
|
|
48
|
+
await (await import('../tools/fmt.mjs')).cli(argv, base_path, src_path, lib_path);
|
|
49
|
+
} else
|
|
50
|
+
|
|
51
|
+
if (argv.mode === 'lsp') {
|
|
52
|
+
await (await import('../tools/lsp.mjs')).cli(argv, base_path, src_path, lib_path);
|
|
53
|
+
} else
|
|
54
|
+
|
|
55
|
+
if (argv.mode === 'repl') {
|
|
56
|
+
await (await import('../tools/repl.mjs')).default({'lib_path':lib_path, 'imp_path':path.join(src_path, 'lib'), show_js:!argv.no_js});
|
|
57
|
+
} else
|
|
58
|
+
|
|
59
|
+
if (argv.mode === 'gettext') {
|
|
60
|
+
await (await import('../tools/gettext.mjs')).cli(argv, base_path, src_path, lib_path);
|
|
61
|
+
} else
|
|
62
|
+
|
|
63
|
+
if (argv.mode === 'msgfmt') {
|
|
64
|
+
(await import('../tools/msgfmt.mjs')).cli(argv, base_path, src_path, lib_path);
|
|
65
|
+
} else
|
|
66
|
+
|
|
67
|
+
if (argv.mode === 'web-repl-export') {
|
|
68
|
+
await (await import('../tools/web_repl_export.mjs')).default(base_path, lib_path, argv);
|
|
69
|
+
} else
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
await (await import('../tools/compile.mjs')).default(start_time, argv, base_path, src_path, lib_path);
|
|
70
73
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# rapydscript.nvim
|
|
2
|
+
|
|
3
|
+
Neovim plugin that wires up the RapydScript LSP server (`rapydscript lsp`) as a
|
|
4
|
+
native Neovim LSP client for `.pyj` files.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
Provided by the LSP server — no extra plugins required:
|
|
9
|
+
|
|
10
|
+
- **Completions** — in-scope symbols, builtins, keywords, and member completion (`mod.<TAB>`)
|
|
11
|
+
- **Diagnostics** — lint checks and unresolved import warnings, updated as you type
|
|
12
|
+
- **Hover** (`K`) — kind, origin, and docstring of the symbol under the cursor
|
|
13
|
+
- **Go to definition** (`gd`) — including jumping into imported modules
|
|
14
|
+
- **Find references** (`gr`) — resolved across files through the import graph
|
|
15
|
+
- **Rename** (`<leader>rn`) — renames everywhere across the workspace
|
|
16
|
+
- **Code actions** (`<leader>ca`) — remove unused import/local, add `# noqa`, format document
|
|
17
|
+
- **Document formatting** (`<leader>f`) — same as `rapydscript fmt`
|
|
18
|
+
- **Document symbols** — outline view via any symbols picker
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- Neovim ≥ 0.10
|
|
23
|
+
- `rapydscript` on your `$PATH` (install with `npm install -g rapydscript-ng`), or the
|
|
24
|
+
plugin directory must be inside a RapydScript repository checkout (the repo's own
|
|
25
|
+
`bin/rapydscript` is used automatically as a fallback)
|
|
26
|
+
- **Syntax highlighting only**: a C compiler on your `$PATH` is required to compile the
|
|
27
|
+
tree-sitter parser the first time the plugin loads. On Linux/macOS any `cc`-compatible
|
|
28
|
+
compiler works (gcc, clang, etc.). On Windows, `cl` (MSVC) or `clang-cl` must be
|
|
29
|
+
available — run Neovim from a Visual Studio Developer Command Prompt, or add the
|
|
30
|
+
compiler to your `PATH` manually. LSP features work regardless of whether compilation
|
|
31
|
+
succeeds.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
### lazy.nvim
|
|
36
|
+
|
|
37
|
+
```lua
|
|
38
|
+
{
|
|
39
|
+
dir = '/path/to/editor-plugins/nvim/rapydscript',
|
|
40
|
+
ft = 'rapydscript',
|
|
41
|
+
opts = {},
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Example with options:**
|
|
46
|
+
|
|
47
|
+
```lua
|
|
48
|
+
{
|
|
49
|
+
dir = "/path/to/editor-plugins/nvim/rapydscript",
|
|
50
|
+
ft = "rapydscript",
|
|
51
|
+
opts = {
|
|
52
|
+
line_length = 100,
|
|
53
|
+
preferred_quote = "double",
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Manual (no plugin manager)
|
|
59
|
+
|
|
60
|
+
Add the plugin directory to your runtime path and call `setup()`:
|
|
61
|
+
|
|
62
|
+
```lua
|
|
63
|
+
-- in ~/.config/nvim/init.lua
|
|
64
|
+
vim.opt.rtp:prepend("/path/to/rapydscript/nvim-lsp-plugin")
|
|
65
|
+
require("rapydscript").setup()
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configuration reference
|
|
69
|
+
|
|
70
|
+
| Key | Type | Default | Description |
|
|
71
|
+
|-----|------|---------|-------------|
|
|
72
|
+
| `cmd` | `string[]` | `{"rapydscript","lsp"}` | Command used to start the server |
|
|
73
|
+
| `import_path_patterns` | `string[]` | `{".", "src", "src/pyj"}` | Glob patterns relative to the project root; matching directories that contain `.pyj` files are passed automatically as `--import-path` |
|
|
74
|
+
| `line_length` | `number\|nil` | `nil` | Max line length for the formatter, passed as `--line-length` |
|
|
75
|
+
| `preferred_quote` | `string\|nil` | `nil` | `"single"` or `"double"`, passed as `--preferred-quote` |
|
|
76
|
+
| `filetypes` | `string[]` | `{"rapydscript"}` | Filetypes that trigger server attachment |
|
|
77
|
+
| `root_markers` | `string[]` | `{".git","package.json","rapydscript.json"}` | Files/dirs used to detect the project root |
|
|
78
|
+
|
|
79
|
+
### Automatic import path detection
|
|
80
|
+
|
|
81
|
+
When a project root is found (via `root_markers`), the plugin expands each pattern in
|
|
82
|
+
`import_path_patterns` as a glob relative to that root. Any matching directory that
|
|
83
|
+
contains at least one `.pyj` file is added to the server's import search path
|
|
84
|
+
automatically — no manual configuration needed for standard project layouts.
|
|
85
|
+
|
|
86
|
+
If no project root is detected the setting has no effect.
|
|
87
|
+
|
|
88
|
+
To add custom search locations alongside the defaults:
|
|
89
|
+
|
|
90
|
+
```lua
|
|
91
|
+
opts = {
|
|
92
|
+
import_path_patterns = { ".", "src", "src/pyj", "vendor/pyj" },
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
To disable auto-detection entirely, pass an empty list:
|
|
97
|
+
|
|
98
|
+
```lua
|
|
99
|
+
opts = {
|
|
100
|
+
import_path_patterns = {},
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Changing settings at runtime
|
|
105
|
+
|
|
106
|
+
The server accepts live setting updates via the LSP
|
|
107
|
+
`workspace/didChangeConfiguration` notification — no restart needed. Call
|
|
108
|
+
`require("rapydscript").update_settings(opts)` with any subset of the two
|
|
109
|
+
settings keys:
|
|
110
|
+
|
|
111
|
+
```lua
|
|
112
|
+
require("rapydscript").update_settings({
|
|
113
|
+
line_length = 100, -- new max line length for the formatter
|
|
114
|
+
preferred_quote = "double", -- "single" or "double"
|
|
115
|
+
})
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Only the keys you pass are updated; the rest keep their current values.
|
|
119
|
+
|
|
120
|
+
### Neovim user commands
|
|
121
|
+
|
|
122
|
+
A convenient way to expose this as editor commands — add to your config after
|
|
123
|
+
`setup()`:
|
|
124
|
+
|
|
125
|
+
```lua
|
|
126
|
+
-- :RapydLineLength 100
|
|
127
|
+
vim.api.nvim_create_user_command("RapydLineLength", function(args)
|
|
128
|
+
require("rapydscript").update_settings({ line_length = tonumber(args.args) })
|
|
129
|
+
end, { nargs = 1, desc = "Set RapydScript LSP line length" })
|
|
130
|
+
|
|
131
|
+
-- :RapydQuote double
|
|
132
|
+
vim.api.nvim_create_user_command("RapydQuote", function(args)
|
|
133
|
+
require("rapydscript").update_settings({ preferred_quote = args.args })
|
|
134
|
+
end, { nargs = 1, desc = "Set RapydScript LSP preferred quote style" })
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### In lazy.nvim config
|
|
138
|
+
|
|
139
|
+
If you want the commands available automatically, put them in the `config`
|
|
140
|
+
function:
|
|
141
|
+
|
|
142
|
+
```lua
|
|
143
|
+
{
|
|
144
|
+
dir = "/path/to/rapydscript/nvim-lsp-plugin",
|
|
145
|
+
ft = "rapydscript",
|
|
146
|
+
opts = { line_length = 100 },
|
|
147
|
+
config = function(_, opts)
|
|
148
|
+
require("rapydscript").setup(opts)
|
|
149
|
+
|
|
150
|
+
vim.api.nvim_create_user_command("RapydLineLength", function(args)
|
|
151
|
+
require("rapydscript").update_settings({ line_length = tonumber(args.args) })
|
|
152
|
+
end, { nargs = 1 })
|
|
153
|
+
|
|
154
|
+
vim.api.nvim_create_user_command("RapydQuote", function(args)
|
|
155
|
+
require("rapydscript").update_settings({ preferred_quote = args.args })
|
|
156
|
+
end, { nargs = 1 })
|
|
157
|
+
end,
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Changes to `line_length` and `preferred_quote` take effect on the next format operation.
|
|
162
|
+
|
|
163
|
+
## Keymaps
|
|
164
|
+
|
|
165
|
+
The plugin does not define any keymaps — it relies on the standard Neovim LSP
|
|
166
|
+
keymaps that are set up by `vim.lsp.buf.*`. A minimal set to add to your LSP
|
|
167
|
+
`on_attach` or a `LspAttach` autocmd:
|
|
168
|
+
|
|
169
|
+
```lua
|
|
170
|
+
vim.api.nvim_create_autocmd("LspAttach", {
|
|
171
|
+
callback = function(ev)
|
|
172
|
+
local buf = ev.buf
|
|
173
|
+
local map = function(mode, lhs, rhs)
|
|
174
|
+
vim.keymap.set(mode, lhs, rhs, { buffer = buf })
|
|
175
|
+
end
|
|
176
|
+
map("n", "K", vim.lsp.buf.hover)
|
|
177
|
+
map("n", "gd", vim.lsp.buf.definition)
|
|
178
|
+
map("n", "gr", vim.lsp.buf.references)
|
|
179
|
+
map("n", "<leader>rn", vim.lsp.buf.rename)
|
|
180
|
+
map("n", "<leader>ca", vim.lsp.buf.code_action)
|
|
181
|
+
map("n", "<leader>f", function() vim.lsp.buf.format({ async = true }) end)
|
|
182
|
+
end,
|
|
183
|
+
})
|
|
184
|
+
```
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
local M = {}
|
|
2
|
+
|
|
3
|
+
local function ver_str(v)
|
|
4
|
+
return v and table.concat(v, ".") or "unknown"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
function M.check()
|
|
8
|
+
local h = vim.health
|
|
9
|
+
local rs_ok, rs = pcall(require, "rapydscript")
|
|
10
|
+
if not rs_ok then
|
|
11
|
+
h.start("rapydscript")
|
|
12
|
+
h.error("Failed to load plugin: " .. tostring(rs))
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
-- Binary -------------------------------------------------------------------
|
|
17
|
+
h.start("rapydscript binary")
|
|
18
|
+
local info = rs._binary_info
|
|
19
|
+
local sys = info.system
|
|
20
|
+
local repo = info.repo
|
|
21
|
+
|
|
22
|
+
if sys then
|
|
23
|
+
if sys.rejected then
|
|
24
|
+
h.error(string.format(
|
|
25
|
+
"System binary rejected: %s (v%s < minimum 0.8.0)",
|
|
26
|
+
sys.path, ver_str(sys.version)
|
|
27
|
+
))
|
|
28
|
+
elseif sys.version then
|
|
29
|
+
h.ok(string.format("System binary: %s (v%s)", sys.path, ver_str(sys.version)))
|
|
30
|
+
else
|
|
31
|
+
h.warn(string.format("System binary: %s (version unknown)", sys.path))
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
h.warn("rapydscript not found on PATH")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if repo then
|
|
38
|
+
h.ok(string.format("Repo binary: %s (v%s)", repo.path, ver_str(repo.version)))
|
|
39
|
+
else
|
|
40
|
+
h.info("No repo binary present")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if not sys and not repo then
|
|
44
|
+
h.error("No rapydscript binary found — LSP will not start")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
-- Tree-sitter --------------------------------------------------------------
|
|
48
|
+
h.start("rapydscript tree-sitter")
|
|
49
|
+
if rs._ts_so then
|
|
50
|
+
h.ok("Parser compiled: " .. rs._ts_so)
|
|
51
|
+
else
|
|
52
|
+
h.warn("Tree-sitter parser not compiled (syntax highlighting unavailable)")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
-- LSP clients --------------------------------------------------------------
|
|
56
|
+
h.start("rapydscript LSP")
|
|
57
|
+
local clients = vim.lsp.get_clients({ name = "rapydscript" })
|
|
58
|
+
if #clients == 0 then
|
|
59
|
+
h.warn("No active rapydscript LSP client")
|
|
60
|
+
else
|
|
61
|
+
for _, client in ipairs(clients) do
|
|
62
|
+
local cmd_str = type(client.config.cmd) == "table"
|
|
63
|
+
and table.concat(client.config.cmd, " ")
|
|
64
|
+
or tostring(client.config.cmd)
|
|
65
|
+
h.ok(string.format("Client #%d root: %s", client.id, client.config.root_dir or "?"))
|
|
66
|
+
h.info("cmd: " .. cmd_str)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
-- Settings -----------------------------------------------------------------
|
|
71
|
+
h.start("rapydscript settings")
|
|
72
|
+
local opts = rs._active_opts
|
|
73
|
+
if not opts then
|
|
74
|
+
h.warn("setup() has not been called — showing defaults")
|
|
75
|
+
opts = rs.defaults
|
|
76
|
+
else
|
|
77
|
+
h.ok("setup() called")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
h.info("cmd: " .. table.concat(opts.cmd, " "))
|
|
81
|
+
h.info("line_length: " .. tostring(opts.line_length))
|
|
82
|
+
h.info("preferred_quote: " .. tostring(opts.preferred_quote))
|
|
83
|
+
h.info("filetypes: " .. table.concat(opts.filetypes, ", "))
|
|
84
|
+
h.info("root_markers: " .. table.concat(opts.root_markers, ", "))
|
|
85
|
+
h.info("import_path_patterns: " .. table.concat(opts.import_path_patterns, ", "))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
return M
|