codemirror-lang-raku 0.0.0-stage → 0.2.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 ADDED
@@ -0,0 +1,82 @@
1
+ ## 0.2.0 (2026-10-07)
2
+
3
+ ### New features
4
+
5
+ - Regexes are highlighted inside: the literals `/…/`, `rx/…/`, `m/…/` and
6
+ the pattern of `s/…/…/`, and the body of a `token`, `rule` or `regex`
7
+ declaration. A `Regex` node has children for character classes (`CharacterClass`),
8
+ `<…>` assertions (`Assertion`), quoted literals, escapes, quantifiers
9
+ and anchors, variables, comments, and the blocks of code in it, which
10
+ are read as code.
11
+ - `multi foo(…) { }`, `proto foo(…) {*}` and `only foo(…) { }`, without the
12
+ word `sub`, are `RoutineDeclaration` nodes with a `RoutineName`. The
13
+ node has no declarator keyword, and `multi` is the node before it.
14
+ - Pod blocks have child nodes for their directives (`PodDirective`),
15
+ headings (`PodHeading`) and formatting codes (`PodStrong`,
16
+ `PodEmphasis`, `PodCode`, `PodLink`, `PodFormat`), which are highlighted.
17
+ - Variables, blocks and escapes are interpolated in the text of a
18
+ `qq:to` heredoc. Its `Heredoc` node has the children of a string that
19
+ interpolates.
20
+ - Variables, blocks and escapes are interpolated in `<<…>>` and `«…»`
21
+ word lists. Such a list can hold code over several lines, and can be
22
+ a subscript: `%h«$key»`, `:a<<b $c>>`.
23
+ - Completion offers the names that the document declares: the variables
24
+ and attributes in scope, routines, classes, enums, subsets and
25
+ constants, and after a `.` the methods.
26
+ - Completion also offers placeholder variables (`$^a`) in their block,
27
+ and variables without a sigil (`my \x`).
28
+ - A line that starts with a trait, as in `is export {` under
29
+ `sub f($a)`, is indented as the continuation of its statement.
30
+ - Toggling a block comment picks brackets that fit the selection:
31
+ `` #`[ … ] `` when the selection holds an unbalanced parenthesis, and so
32
+ on. A comment is removed whichever bracket it was written with.
33
+ - A line that continues a statement is indented one unit further: after
34
+ a line that ends in an operator or a comma, and when it starts with a
35
+ method call or an infix operator.
36
+ - The adverbs of a quote that switch kinds of interpolation on and off
37
+ are taken into account: `q:c{…}` interpolates blocks, `qq:!s[…]` does
38
+ not interpolate `$` variables. This covers `:c`, `:s`, `:a`, `:h`, `:f`,
39
+ `:b`, `:qq`, `:q` and their long names.
40
+ - An operator referred to as a routine, as in `&infix:<+>`, is a single
41
+ `VariableName`. Operator names can also be written as `circumfix:<[ ]>`
42
+ and `infix:['+']`.
43
+ - `q`, `qq`, `Q` and their variants take a bracket after blanks: `q {…}`,
44
+ `qw <a b>`.
45
+ - An adverb with an argument that is `False` or `0` is switched off:
46
+ `qq:c(False)[…]`.
47
+
48
+ ### Bug fixes
49
+
50
+ - A regex with bracket delimiters no longer ends at the `]` of a
51
+ character class in it: `rx[ <[a..z]> ]`.
52
+ - `multi foo`, `proto foo` and `only foo` declare a sub also when the
53
+ signature or the body starts on the next line.
54
+ - A long comment right after a type name (`my Foo # …`) no longer makes
55
+ every edit before it reparse the document up to that comment.
56
+ - After the built-in terms `pi`, `π`, `tau`, `τ`, `now`, `time` and `rand`, a
57
+ `/` or `<` is an operator whatever the spacing: `pi /2`.
58
+ - A keyword that is a routine and is called with parentheses, as in
59
+ `take(1)` or `not($x)`, is a plain name and not a keyword.
60
+ - The body of a regex declaration that is not closed ends before the next
61
+ `token`, `rule` or `regex` declaration, so that the declarations after
62
+ it are still found.
63
+ - A heredoc opener that is only mentioned in a string or in a comment no
64
+ longer starts a heredoc. Heredocs are now found from the quote tokens
65
+ of the line, not from its text.
66
+
67
+ ## 0.1.0 (2026-10-06)
68
+
69
+ ### New features
70
+
71
+ First release.
72
+
73
+ - Syntax highlighting with the standard tags of `@lezer/highlight`:
74
+ comments and Pod, quotes of all kinds with interpolation, heredocs,
75
+ regexes, numbers, variables with sigils and twigils, keywords, operators
76
+ and declarations
77
+ - A syntax tree with nodes for package, routine, regex, enum, subset and
78
+ constant declarations and their names
79
+ - Indentation, folding and matching of `{ }`, `( )` and `[ ]`, and folding
80
+ of Pod blocks, heredocs and embedded comments
81
+ - Completion of keywords and of the commonly used built-in types,
82
+ routines, methods and special variables
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2026 by Kan Fushihara
4
+ Copyright (C) 2021 by Marijn Haverbeke <marijnh@gmail.com> and others
5
+ (the CodeMirror language package template this project started from)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,239 @@
1
- # Temporary Holding Version
1
+ # codemirror-lang-raku
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm version](https://img.shields.io/npm/v/codemirror-lang-raku)](https://www.npmjs.com/package/codemirror-lang-raku)
4
+ [![Test](https://github.com/kan/codemirror-lang-raku/actions/workflows/test.yml/badge.svg)](https://github.com/kan/codemirror-lang-raku/actions/workflows/test.yml)
5
+ [![License: MIT](https://img.shields.io/npm/l/codemirror-lang-raku)](LICENSE)
6
+
7
+ [Raku](https://raku.org/) (formerly Perl 6) language support for the
8
+ [CodeMirror 6](https://codemirror.net/) code editor: syntax highlighting,
9
+ indentation, code folding, bracket matching and completion, built on a
10
+ [Lezer](https://lezer.codemirror.net/) grammar.
11
+
12
+ It covers comments and Pod, quotes of all kinds (`'…'`, `"…"`, `q` / `qq` /
13
+ `Q` with any delimiter, heredocs, `<word lists>`) with interpolation,
14
+ regexes, numbers, variables with sigils and twigils, keywords, operators,
15
+ blocks and declarations.
16
+
17
+ Try it in the [demo](https://kan.github.io/codemirror-lang-raku/), which
18
+ shows the syntax tree next to the editor.
19
+
20
+ > **Status: 0.x.** The node names of the syntax tree can still change
21
+ > between minor versions. See [Known limitations](#known-limitations) for
22
+ > what is missing.
23
+
24
+ ## Installation
25
+
26
+ ```sh
27
+ npm install codemirror-lang-raku
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```javascript
33
+ import {EditorView, basicSetup} from "codemirror"
34
+ import {raku} from "codemirror-lang-raku"
35
+
36
+ new EditorView({
37
+ doc: 'say "Hello, Raku!";',
38
+ extensions: [basicSetup, raku()],
39
+ parent: document.body
40
+ })
41
+ ```
42
+
43
+ Highlighting uses only the standard tags of `@lezer/highlight`, so any
44
+ CodeMirror theme or highlight style applies.
45
+
46
+ To load the language on demand, the way `@codemirror/language-data` does:
47
+
48
+ ```javascript
49
+ import {LanguageDescription} from "@codemirror/language"
50
+
51
+ const rakuDescription = LanguageDescription.of({
52
+ name: "Raku",
53
+ alias: ["perl6"],
54
+ extensions: ["raku", "rakumod", "rakutest", "rakudoc", "p6", "pl6", "pm6", "pod6"],
55
+ load: () => import("codemirror-lang-raku").then(m => m.raku())
56
+ })
57
+ ```
58
+
59
+ ## API Reference
60
+
61
+ <dl>
62
+ <dt><code><strong>raku</strong>() → LanguageSupport</code></dt>
63
+ <dd><p>Raku language support, with completion, and with block comment
64
+ tokens that fit the selection (<code>#`[ … ]</code> around text that holds an
65
+ unbalanced parenthesis).</p></dd>
66
+ <dt><code><strong>rakuLanguage</strong>: LRLanguage</code></dt>
67
+ <dd><p>A language provider based on the Lezer Raku parser, extended with
68
+ highlighting and indentation information.</p></dd>
69
+ <dt><code><strong>rakuCompletion</strong>: Extension</code></dt>
70
+ <dd><p>Completion of Raku keywords, of the commonly used built-in types,
71
+ routines, methods and special variables, and of the variables, routines,
72
+ types and methods that the document declares. <code>raku()</code> includes it. To
73
+ leave it out, use <code>rakuLanguage</code> in place of <code>raku()</code>.</p></dd>
74
+ <dt><code><strong>parser</strong>: LRParser</code></dt>
75
+ <dd><p>The Lezer parser for Raku, without the editor-specific node props.
76
+ Use <code>rakuLanguage.parser</code> for the configured one.</p></dd>
77
+ </dl>
78
+
79
+ ## Syntax tree
80
+
81
+ The grammar does not parse statements and expressions. It tokenizes the
82
+ input, nests brackets, and recognizes declarations, which is enough for
83
+ highlighting, folding and building an outline, and keeps the tree usable
84
+ on incomplete code.
85
+
86
+ | Node | Covers |
87
+ |---|---|
88
+ | `PackageDeclaration` | `class`, `role`, `grammar`, `module`, `package`, with a `PackageName` child, up to the body `Block` or the `;` of a `unit` declaration |
89
+ | `RoutineDeclaration` | `sub`, `method`, `submethod`, with a `RoutineName` child (absent for anonymous routines), up to the body `Block`. Also the `foo(…) { }` of `multi foo(…) { }`, which declares a sub without the word `sub`: that node starts with its `RoutineName` |
90
+ | `RegexDeclaration` | `token`, `rule`, `regex`, with a `RegexName` child, up to the body `Block`, which holds one `Regex` |
91
+ | `EnumDeclaration`, `SubsetDeclaration`, `ConstantDeclaration` | The declarator and its `EnumName`, `SubsetName` or `ConstantName` |
92
+ | `Block`, `Parens`, `Brackets` | `{ }`, `( )`, `[ ]` |
93
+ | `VariableName`, `AttributeName`, `SpecialVariable` | `$x` / `$^a`, `$!x` / `$.x`, `$*x` / `$?x` |
94
+ | `StringLiteral` | A quote of any kind. One that interpolates has `Escape`, `Interpolation`, variable, `Brackets`, `Parens` and `MethodCall` children |
95
+ | `Heredoc` | The text of a heredoc, from the line after its `q:to/END/` opener through its terminator. The opener is a `StringLiteral`. The text of a `qq:to` heredoc has the same children as a string that interpolates. The texts of the heredocs that one line opens are a single node |
96
+ | `Regex` | `/…/`, `rx//`, `m//`, `s///`, `tr///`, or the body of a regex declaration. Its children are `CharacterClass` (`<[a..z]>`), `Assertion` (`<name>`, `<?before …>`), `StringLiteral`, `Escape` (`\d`), `Operator` (quantifiers, `\|`, anchors), `VariableName` (`$x`, `$<name>`), `LineComment`, and a `Block` for each `{ }` of code |
97
+ | `LineComment`, `DocComment`, `BlockComment` | `#`, `#|` / `#=`, `` #`( ) `` |
98
+ | `Pod` | `=begin` … `=end` and the other Pod blocks. Its children are `PodDirective` (`=begin`, `=head1`, `=end pod`), `PodHeading` (the text after `=head1`), and the formatting codes `PodStrong` (`B<…>`), `PodEmphasis` (`I<…>`), `PodCode` (`C<…>`), `PodLink` (`L<…>`) and `PodFormat` (the others) |
99
+
100
+ Each declarator keyword is a child node named after the keyword (`class`,
101
+ `sub`, `token`, …). The words `unit`, `multi`, `proto`, `only`, `my` and
102
+ `our` are not part of the declaration node. They are the nodes right
103
+ before it, also in `multi foo(…) { }`, where the declaration node has no
104
+ declarator keyword.
105
+
106
+ ## Known limitations
107
+
108
+ Not supported yet:
109
+
110
+ - Nothing is highlighted in the replacement of `s/…/…/`, nor in
111
+ `tr/…/…/`.
112
+ - In a regex, a `<…>` is one
113
+ token, with the code or the nested `<…>` in it, and has to be closed on
114
+ its line unless it is a character class. Groups (`[ ]`, `( )`) and
115
+ adverbs (`:i`, `:my`) are plain text, so the text after `:my` is read
116
+ as regex.
117
+ - A heredoc is interpolated when everything interpolates in it, as in
118
+ `qq:to`. One that interpolates in part (`q:c:to`, `qq:!s:to`) is not
119
+ highlighted inside. When a line opens several heredocs, they are
120
+ interpolated only if all of them are. A `{` that is not closed in the
121
+ text takes the rest of the heredoc, with its terminator, for code.
122
+ - In Pod, a formatting code is one token: the codes inside it
123
+ (`B<I<…>>`) are not told apart. Formatting codes are left alone in a
124
+ block that is code (`=begin code`, `=code`, `=for code`), but not in a
125
+ code block inside another block, nor in an indented code paragraph.
126
+ Tables and the configuration after a directive (`:numbered`) are plain
127
+ text.
128
+ - A `<<…>>` or `«…»` word list that holds `{ }`, `( )` or `;` can span up
129
+ to 10 lines. A longer one is not taken to be a word list. Nothing is
130
+ interpolated in a list that holds an unbalanced `{` or its own
131
+ delimiter: it is a single token.
132
+ - A Pod block is read where a statement or a term can stand, not
133
+ everywhere that whitespace can: one between `class` and the name of
134
+ the class is not read as Pod.
135
+ - A quote adverb is switched off by the argument `False` or `0`, as in
136
+ `qq:c(False)[…]`. With any other argument, such as a variable, it
137
+ counts as switched on.
138
+ - The brackets of a block comment are picked for the `toggleBlockComment`
139
+ command. Text that unbalances every bracket that is tried gets
140
+ `` #`( `` … `)`, which then does not cover exactly that text.
141
+ - A user-defined operator is recognized where it is declared
142
+ (`sub infix:<+++>`) and as a routine (`&infix:<+++>`), not where it is
143
+ used as an operator.
144
+ - Completion does not know types. After a `.` it offers the built-in
145
+ methods and every method that the document declares, whatever the
146
+ invocant is. Names from other files are not offered.
147
+ - Completion takes a variable to be declared by `my`, `our`, `state` or
148
+ `has`, in a signature, after the `->` of a pointy block, or by being a
149
+ placeholder variable (`$^a`, `$:a`). A sigilless variable is offered
150
+ when it is declared with a backslash (`my \x`, `sub f(\x)`, `-> \x`),
151
+ not as a term (`my constant x`, `sub term:<x>`).
152
+ - In a string, only the code in `{ }` and in a subscript is completed,
153
+ not the method name of `"$x.name()"`.
154
+
155
+ Heuristics that can be wrong:
156
+
157
+ - A line is indented as the continuation of a statement when the line
158
+ before it ends in an operator or a comma, or when it starts with a
159
+ method call, with an operator that has a space after it, or with a
160
+ trait (`is`, `does`, `returns`, `handles`, `where`, `will`, as in
161
+ `is export {`). A statement that continues in another way is not
162
+ indented further. A line that starts with one of these words for
163
+ another reason, such as a call of the `is` of `Test`, is indented when
164
+ the line before it does not end in a `;` or a `}`. Inside `( )` and
165
+ `[ ]`, indentation follows the brackets only.
166
+ - A capitalized word is taken to be a type name.
167
+ - Whether `/` starts a regex and `<` starts a word list is decided from
168
+ the token before it. After a bare name, spacing decides: `say /x/` and
169
+ `say <a b>` are a regex and a word list, `foo / 2` and `n < 3` are not.
170
+ The built-in terms `pi`, `π`, `tau`, `τ`, `now`, `time` and `rand` are
171
+ followed by an operator whatever the spacing (`pi /2`), also when a
172
+ routine of your own has one of these names. After a closing brace, a
173
+ line break decides.
174
+ - A `<…>` right after a term is a subscript only when it holds plain words
175
+ on one line: `%h<key>`, but not `$a<$b`. A `<<…>>` or `«…»` that touches
176
+ the term before it is a subscript when it is at most 24 characters
177
+ long and starts and ends in a word, a variable or a quote: `%h«$key»`,
178
+ but not the hyper operators of `@a<<+>>@b` and `@a«R-»@b`. A hyper
179
+ operator that is a word and touches both of its operands, as in
180
+ `@a<<min>>@b`, is misread as a subscript.
181
+ - A `<<` or `«` where a term is expected starts a word list when a `>>`
182
+ or `»` follows, within 10 lines if there is a `{ }`, `( )` or `;` in
183
+ between. One that is being typed takes the code up to there for its
184
+ content.
185
+ - In a `<<…>>` word list, a `>>` in a subscript or a call that is
186
+ interpolated ends the list: `<<@a[1 >> 2]>>`. A heredoc that is opened
187
+ in a block in a word list or in a regex literal is not read as one.
188
+ - `q`, `qq`, `Q`, `m`, `rx`, `s`, `tr` and their variants start a quote
189
+ when a delimiter follows directly, so a sigilless `s/2` is misread.
190
+ `q`, `qq` and `Q` also take a bracket after blanks (`q {…}`), so a
191
+ routine or a sigilless variable of your own named `q`, before a block
192
+ or a subscript, is misread. The
193
+ regex words do not: `m {…}` and `s {…}` are calls.
194
+ - `%name` and `&name` are variables, except between two terms with no
195
+ space on either side: `$a%b`.
196
+ - After `multi`, `proto` or `only`, a name is taken to declare a sub when
197
+ a `(` or a `{` follows it, on the same line or the next:
198
+ `multi foo($x) { }`. One that follows a comment or more than 20
199
+ characters of whitespace is not seen, and a call such as `only foo(1)`, of a
200
+ routine of your own that is named `only`, is read as a declaration.
201
+ - A word spelled like a keyword is a keyword wherever it appears, except
202
+ as a method name, as a declared name, before `=>`, and for the
203
+ keywords that are routines (`take`, `return`, `next`, `not`, …) right
204
+ before a `(`: `take(1)`. A sigilless variable or a routine of your own
205
+ that is named like a keyword is highlighted as one.
206
+ - A quote that does not interpolate (`'…'`, `q{…}`), a regex and a
207
+ heredoc have to be closed. Otherwise their opener is read as ordinary
208
+ code.
209
+ - A quote that interpolates (`"…`, `qq[…`), a Pod block or an embedded
210
+ comment that is not closed runs to the end of the document.
211
+ - The body of a regex declaration that is not closed runs up to the next
212
+ line that starts a `token`, `rule` or `regex` declaration, or to the
213
+ end of the document.
214
+
215
+ ## Development
216
+
217
+ ```sh
218
+ npm install
219
+ npm test # builds, then runs the tests in test/
220
+ npm run dev # serves demo/, an editor next to the syntax tree of its content
221
+ ```
222
+
223
+ The demo loads the sources, so a change to the grammar shows up on reload.
224
+
225
+ To release a version:
226
+
227
+ 1. Run `npm version 1.2.3 --no-git-tag-version`, and turn the
228
+ `## Unreleased` heading of `CHANGELOG.md` into `## 1.2.3 (2026-01-31)`.
229
+ Commit and push.
230
+ 2. Run `npm publish` from that commit. It first runs the tests and checks
231
+ that `CHANGELOG.md` has that section and that nothing is uncommitted.
232
+ 3. Tag that commit `v1.2.3` and push the tag. A workflow then checks that
233
+ the tag matches `package.json` and that npm has the version, published
234
+ from that commit, and creates the GitHub release from the section of
235
+ `CHANGELOG.md`.
236
+
237
+ ## License
238
+
239
+ [MIT](LICENSE)