pair-mode 0.3.0 → 0.3.3

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 (45) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +66 -9
  4. package/assets/syntax/clojure.yaml +36 -0
  5. package/assets/syntax/cmake.yaml +41 -0
  6. package/assets/syntax/crystal.yaml +71 -0
  7. package/assets/syntax/csharp.yaml +51 -0
  8. package/assets/syntax/dart.yaml +45 -0
  9. package/assets/syntax/elm.yaml +38 -0
  10. package/assets/syntax/erb.yaml +42 -0
  11. package/assets/syntax/erlang.yaml +45 -0
  12. package/assets/syntax/fsharp.yaml +48 -0
  13. package/assets/syntax/graphql.yaml +47 -0
  14. package/assets/syntax/groovy.yaml +111 -0
  15. package/assets/syntax/haml.yaml +16 -0
  16. package/assets/syntax/haskell.yaml +52 -0
  17. package/assets/syntax/ini.yaml +23 -0
  18. package/assets/syntax/java.yaml +36 -0
  19. package/assets/syntax/julia.yaml +56 -0
  20. package/assets/syntax/kotlin.yaml +65 -0
  21. package/assets/syntax/makefile.yaml +37 -0
  22. package/assets/syntax/nginx.yaml +22 -0
  23. package/assets/syntax/nim.yaml +27 -0
  24. package/assets/syntax/nix.yaml +32 -0
  25. package/assets/syntax/objc.yaml +60 -0
  26. package/assets/syntax/ocaml.yaml +43 -0
  27. package/assets/syntax/perl.yaml +58 -0
  28. package/assets/syntax/php.yaml +60 -0
  29. package/assets/syntax/r.yaml +30 -0
  30. package/assets/syntax/scala.yaml +32 -0
  31. package/assets/syntax/svelte.yaml +27 -0
  32. package/assets/syntax/swift.yaml +102 -0
  33. package/assets/syntax/vue.yaml +63 -0
  34. package/assets/syntax/xml.yaml +37 -0
  35. package/assets/syntax/zig.yaml +52 -0
  36. package/dist/claude-code.js +461 -149
  37. package/dist/cli.js +1490 -476
  38. package/dist/codex.js +461 -149
  39. package/dist/opencode.js +453 -142
  40. package/dist/pair-tui.js +172 -26
  41. package/dist/pi.js +508 -155
  42. package/package.json +4 -4
  43. package/skills/toggle/SKILL.md +24 -0
  44. package/commands/pair.md +0 -18
  45. package/skills/pair/SKILL.md +0 -20
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pair-mode",
3
- "version": "0.3.0",
3
+ "version": "0.3.3",
4
4
  "description": "Hold every proposed edit, annotate the diff line by line, and hand the notes back to the agent.",
5
5
  "author": {
6
6
  "name": "ofrusch",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pair-mode",
3
- "version": "0.3.0",
3
+ "version": "0.3.3",
4
4
  "description": "Hold every proposed edit, annotate the diff line by line, and hand the notes back to the agent.",
5
5
  "author": {
6
6
  "name": "ofrusch",
package/README.md CHANGED
@@ -16,12 +16,10 @@ When enabled, your agent will push diffs to your editing interface of choice (yo
16
16
 
17
17
  ## Install
18
18
 
19
- ```
20
- npm install -g pair-mode
21
- pair-mode setup
22
- ```
19
+ Pick one of two paths. A plugin covers one CLI and needs no setup step. The npm install
20
+ covers every CLI on your machine and gives you the `pair-mode` command.
23
21
 
24
- ### Or install it as a plugin
22
+ ### As a plugin
25
23
 
26
24
  A plugin resolves its own path at runtime, so it needs no global install and no setup step.
27
25
 
@@ -29,7 +27,7 @@ Claude Code:
29
27
 
30
28
  ```
31
29
  /plugin marketplace add oFrusch/pair-mode
32
- /plugin install pair-mode
30
+ /plugin install pair-mode@pair-mode
33
31
  ```
34
32
 
35
33
  Codex:
@@ -39,9 +37,16 @@ codex plugin marketplace add oFrusch/pair-mode
39
37
  codex plugin add pair-mode@pair-mode
40
38
  ```
41
39
 
42
- The plugin registers the hook and the `/pair` command for that one CLI. Run
43
- `npm install -g pair-mode` as well if you want the `pair-mode` command on your PATH, which
44
- `pair-mode watch` and `pair-mode config` need.
40
+ The plugin registers the hook and the `pair` command for that one CLI. Add the npm install
41
+ below if you also want `pair-mode watch` or `pair-mode config`, because both need the
42
+ `pair-mode` command on your PATH.
43
+
44
+ ### From npm
45
+
46
+ ```
47
+ npm install -g pair-mode
48
+ pair-mode setup
49
+ ```
45
50
 
46
51
  Install pair-mode globally before you run setup. Setup writes the install path into each CLI's config as an absolute path. `npx pair-mode setup` runs from a package cache that npm later prunes, which would leave every hook pointing at a deleted file. Setup detects that case and stops.
47
52
 
@@ -81,6 +86,14 @@ This is what will render your diff if you choose to use one of the CLI-based app
81
86
  | nvim | Yes | Yes. Same `matchadd()` overlay as vim. |
82
87
  | nano | Yes | No. nano has no syntax engine here, so a changed row gets the diff band only. |
83
88
 
89
+ Pair mode names the language from the extension first, then the exact filename, then the
90
+ shebang on the first line. So `Gemfile`, `Dockerfile`, `Makefile`, and an extensionless
91
+ script all get colour. A brand new file has nothing on disk yet, so its first review reads
92
+ no shebang.
93
+
94
+ The pair pane and the web view colour every language Shiki bundles. micro colours the 54
95
+ languages that ship a syntax asset.
96
+
84
97
  Keys:
85
98
 
86
99
  - pair: see [Keymap](#keymap) below.
@@ -119,6 +132,50 @@ If you want to do all your development in one terminal pane while using either C
119
132
  Session mode moves the review out of the agent's process. The hook posts to a Unix
120
133
  socket and waits. A client you start (another terminal tab or the web view) renders the review and allows you to provide your annotations.
121
134
 
135
+ ### One socket per agent session
136
+
137
+ `pair-mode on` inside an agent session reads that session's id, turns pair mode on for that
138
+ session alone, and prints the session id. It mints no socket. Run `pair-mode watch <id>`
139
+ with the id it printed, and that watcher mints the socket. Another session in the same
140
+ checkout gets its own socket and never sees the first session's diffs.
141
+
142
+ `pair-mode on <dir>` from a plain terminal keeps the old behaviour. It writes a directory
143
+ flag, and its socket catches every session that has no socket of its own.
144
+
145
+ A bare `pair-mode off` inside a session turns pair mode off for that session only. It never
146
+ clears a directory flag, so it never silences another session. `pair-mode off <dir>` names
147
+ its target and clears the directory flag.
148
+
149
+ ### Finding a session
150
+
151
+ ```
152
+ pair-mode sessions
153
+ ```
154
+
155
+ That prints every live session with its id, its label, how many watchers are attached, and
156
+ how many reviews are queued. It also removes any socket whose watcher has died.
157
+
158
+ ```
159
+ pair-mode connect
160
+ ```
161
+
162
+ That opens the same list, interactive. `j`, `k`, and the arrow keys move the cursor. `Enter`
163
+ watches the session under the cursor. `q` quits.
164
+
165
+ `pair-mode watch <id>` attaches directly when you already know the id. It mints the socket
166
+ when nothing owns it yet, which is how a session first gets a watcher. An id that is not
167
+ `s-` followed by eight hex characters is rejected as a typo.
168
+
169
+ A session flag outlives the agent that wrote it. `pair-mode sessions` removes a session flag
170
+ and a session opt-out once the session has had no socket for fourteen days, and it says how
171
+ many it removed.
172
+
173
+ Several watchers can watch one session at once, in a terminal or in a browser. The first one
174
+ to watch a session owns its socket. Every later one attaches to that socket as a viewer. Each
175
+ attached client receives every diff, and the first answer wins. The others see the review
176
+ withdraw. A browser tab therefore joins a session a terminal pane already owns, and closing
177
+ the tab leaves that pane serving.
178
+
122
179
  ### Session mode config
123
180
 
124
181
  Set `transport` to `"session"`, then pick a client.
@@ -0,0 +1,36 @@
1
+ filetype: clojure
2
+
3
+ detect:
4
+ filename: "\\.(clj[sc]?|edn)$"
5
+
6
+ rules:
7
+ # Constants
8
+ - constant.bool: "\\b(true|false)\\b"
9
+ - constant.macro: "\\b(nil)\\b"
10
+ # Valid numbers
11
+ - constant.number: "[\\-]?[0-9]+?\\b"
12
+ - constant.number: "0x[0-9][A-Fa-f]+?\\b"
13
+ - constant.number: "[\\-]?(3[0-6]|2[0-9]|1[0-9]|[2-9])r[0-9A-Z]+?\\b"
14
+ # Invalid numbers
15
+ - error: "[\\-]?([4-9][0-9]|3[7-9]|1|0)r[0-9A-Z]+?\\b"
16
+
17
+ # Symbols
18
+ - symbol.operator: "[=>+\\-*/'?]"
19
+
20
+ # Types/casting
21
+ - type: "\\b(byte|short|(big)?int(eger)?|long|float|num|bigdec|rationalize)\\b"
22
+
23
+ # String highlighting
24
+ - constant.string:
25
+ start: '"'
26
+ end: '"'
27
+ skip: "\\\\."
28
+ rules:
29
+ - constant.specialChar: "(\\\\u[0-9A-fa-f]{4,4}|\\\\newline|\\\\space|\\\\tab|\\\\formfeed|\\\\backspace|\\\\return|\\\\.)"
30
+
31
+ # Comments
32
+ - comment:
33
+ start: ";"
34
+ end: "$"
35
+ rules:
36
+ - todo: "(TODO|XXX|FIXME):?"
@@ -0,0 +1,41 @@
1
+ filetype: cmake
2
+
3
+ detect:
4
+ filename: "(CMakeLists\\.txt|\\.cmake)$"
5
+
6
+ rules:
7
+ - identifier.var: "^[[:space:]]*[A-Z0-9_]+"
8
+ - preproc: "^[[:space:]]*(include|include_directories|include_external_msproject)\\b"
9
+
10
+ - statement: "^[[:space:]]*\\b((else|end)?if|else|(end)?while|(end)?foreach|break)\\b"
11
+ - statement: "\\b(COPY|NOT|COMMAND|PROPERTY|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)\\b[[:space:]]"
12
+ - statement: "[[:space:]]\\b(OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))\\b[[:space:]]"
13
+
14
+ - special: "^[[:space:]]*\\b((end)?(function|macro)|return)"
15
+
16
+ - constant.string:
17
+ start: '"'
18
+ end: '"'
19
+ skip: "\\\\."
20
+ rules:
21
+ - constant.specialChar: "\\\\."
22
+
23
+ - constant.string:
24
+ start: "'"
25
+ end: "'"
26
+ skip: "\\\\."
27
+ rules:
28
+ - constant.specialChar: "\\\\."
29
+
30
+ - preproc:
31
+ start: "\\$(\\{|ENV\\{)"
32
+ end: "\\}"
33
+ rules: []
34
+
35
+ - identifier.macro: "\\b(APPLE|UNIX|WIN32|CYGWIN|BORLAND|MINGW|MSVC(_IDE|60|71|80|90)?)\\b"
36
+
37
+ - comment:
38
+ start: "#"
39
+ end: "$"
40
+ rules:
41
+ - todo: "(TODO|XXX|FIXME):?"
@@ -0,0 +1,71 @@
1
+ filetype: crystal
2
+
3
+ detect:
4
+ filename: "\\.cr$"
5
+
6
+ rules:
7
+ # Asciibetical list of reserved words
8
+ - statement: "\\b(abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|in|include|instance_sizeof|lib|loop|macro|module|next|of|out|pointerof|private|protected|raise|require|rescue|return|select|self|sizeof|spawn|struct|super|then|type|typeof|uninitialized|union|unless|until|verbatim|when|while|with|yield)\\b"
9
+ # Constants
10
+ - constant: "\\b(true|false|nil)\\b"
11
+ - constant.number: "\\b[0-9]+\\b"
12
+ # Ones that can't be in the same regex because they include non-words.
13
+ # The nil? one has to be after the constants.
14
+ - statement: "\\b(nil\\?|as(\\?|\\b)|is_a\\?|responds_to\\?)"
15
+ - type: "(\\$|@|@@)?\\b[A-Z]+[0-9A-Z_a-z]*"
16
+ # Crystal "symbols"
17
+ - constant: "([ ]|^):[0-9A-Z_]+\\b"
18
+ # Some unique things we want to stand out
19
+ - constant: "\\b(__FILE__|__LINE__)\\b"
20
+ # Regular expressions
21
+ - constant: "/([^/]|(\\\\/))*/[iomx]*|%r\\{([^}]|(\\\\}))*\\}[iomx]*"
22
+
23
+ # Shell command expansion is in `backticks` or like %x{this}. These are
24
+ # "double-quotish" (to use a perlism).
25
+ - constant.string: "`[^`]*`|%x\\{[^}]*\\}"
26
+
27
+ - constant.string:
28
+ start: "`"
29
+ end: "`"
30
+ rules: []
31
+
32
+ - constant.string:
33
+ start: "%x\\{"
34
+ end: "\\}"
35
+ rules: []
36
+
37
+ - constant.string:
38
+ start: '"'
39
+ end: '"'
40
+ skip: "\\\\."
41
+ rules:
42
+ - constant.specialChar: "\\\\."
43
+ - symbol.brackets:
44
+ start: "#\\{"
45
+ end: "\\}"
46
+ rules:
47
+ - default: ".*"
48
+
49
+ - constant.string:
50
+ start: "'"
51
+ end: "'"
52
+ skip: "\\\\."
53
+ rules:
54
+ - constant.specialChar: "\\\\."
55
+
56
+ - comment:
57
+ start: "#"
58
+ end: "$"
59
+ rules:
60
+ - todo: "(TODO|XXX|FIXME):?"
61
+
62
+ - comment.bright:
63
+ start: "##"
64
+ end: "$"
65
+ rules:
66
+ - todo: "(TODO|XXX|FIXME):?"
67
+
68
+ - constant:
69
+ start: "<<-?'?EOT'?"
70
+ end: "^EOT"
71
+ rules: []
@@ -0,0 +1,51 @@
1
+ filetype: csharp
2
+
3
+ detect:
4
+ filename: "\\.cs$"
5
+
6
+ rules:
7
+ # Class
8
+ - identifier.class: "class +[A-Za-z0-9]+ *((:) +[A-Za-z0-9.]+)?"
9
+
10
+ # Annotation
11
+ - identifier.var: "@[A-Za-z]+"
12
+
13
+ - preproc: "^[[:space:]]*#[[:space:]]*(define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)"
14
+ - identifier: "([A-Za-z0-9_]*[[:space:]]*[()])"
15
+ - type: "\\b(bool|byte|sbyte|char|decimal|double|float|IntPtr|int|uint|long|ulong|managed|unmanaged|nint|nuint|object|short|ushort|string|base|this|var|void)\\b"
16
+ - statement: "\\b(alias|as|case|catch|checked|default|do|dynamic|else|finally|fixed|for|foreach|goto|if|is|lock|new|null|return|switch|throw|try|unchecked|when|while|with)\\b"
17
+ - statement: "\\b(abstract|add|and|args|async|await|class|const|delegate|enum|event|explicit|extern|file|get|global|implicit|in|init|internal|interface|nameof|namespace|not|notnull|operator|or|out|override|params|partial|private|protected|public|readonly|record|ref|remove|required|scoped|sealed|set|sizeof|stackalloc|static|struct|typeof|unsafe|using|value|virtual|volatile|yield)\\b"
18
+ # LINQ-only keywords (ones that cannot be used outside of a LINQ query - lots others can)
19
+ - statement: "\\b(from|where|select|group|info|orderby|join|let|in|on|equals|by|ascending|descending)\\b"
20
+ - special: "\\b(break|continue)\\b"
21
+ - constant.bool: "\\b(true|false)\\b"
22
+ - symbol.operator: "[\\-+/*=<>?:!~%&|]"
23
+ - constant.number: "\\b([0-9._]+|0x[A-Fa-f0-9_]+|0b[0-1_]+)[FL]?\\b"
24
+
25
+ - constant.string:
26
+ start: '"'
27
+ end: '"'
28
+ skip: "\\\\."
29
+ rules:
30
+ - constant.specialChar: "\\\\([btnfr]|'|\\\"|\\\\)"
31
+ - constant.specialChar: "\\\\u[A-Fa-f0-9]{4}"
32
+
33
+ - constant.string:
34
+ start: "'"
35
+ end: "'"
36
+ skip: "\\\\."
37
+ rules:
38
+ - constant.specialChar: "\\\\([btnfr]|'|\\\"|\\\\)"
39
+ - constant.specialChar: "\\\\u[A-Fa-f0-9]{4}"
40
+
41
+ - comment:
42
+ start: "//"
43
+ end: "$"
44
+ rules:
45
+ - todo: "(TODO|XXX|FIXME):?"
46
+
47
+ - comment:
48
+ start: "/\\*"
49
+ end: "\\*/"
50
+ rules:
51
+ - todo: "(TODO|XXX|FIXME):?"
@@ -0,0 +1,45 @@
1
+ filetype: dart
2
+
3
+ detect:
4
+ filename: "\\.dart$"
5
+
6
+ rules:
7
+ - constant.number: "\\b[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\\b"
8
+ - constant.number: "\\b[-+]?([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?"
9
+ - constant.number: "\\b[-+]?([0-9]+[EePp][+-]?[0-9]+)[fFlL]?"
10
+ - identifier: "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]"
11
+ - statement: "\\b(break|case|catch|continue|default|else|finally)\\b"
12
+ - statement: "\\b(for|function|get|if|in|as|is|new|return|set|switch|final|await|async|sync)\\b"
13
+ - statement: "\\b(switch|this|throw|try|var|void|while|with|import|library|part|const|export)\\b"
14
+ - constant: "\\b(true|false|null)\\b"
15
+ - type: "\\b(List|String)\\b"
16
+ - type: "\\b(int|num|double|bool)\\b"
17
+ - statement: "[-+/*=<>!~%?:&|]"
18
+ - constant: "/[^*]([^/]|(\\\\/))*[^\\\\]/[gim]*"
19
+ - constant: "\\\\[0-7][0-7]?[0-7]?|\\\\x[0-9a-fA-F]+|\\\\[bfnrt'\"\\?\\\\]"
20
+
21
+ - comment:
22
+ start: "//"
23
+ end: "$"
24
+ rules:
25
+ - todo: "TODO:?"
26
+
27
+ - comment:
28
+ start: "/\\*"
29
+ end: "\\*/"
30
+ rules:
31
+ - todo: "TODO:?"
32
+
33
+ - constant.string:
34
+ start: '"'
35
+ end: '"'
36
+ skip: "\\\\."
37
+ rules:
38
+ - constant.specialChar: "\\\\."
39
+
40
+ - constant.string:
41
+ start: "'"
42
+ end: "'"
43
+ skip: "\\\\."
44
+ rules:
45
+ - constant.specialChar: "\\\\."
@@ -0,0 +1,38 @@
1
+ filetype: elm
2
+
3
+ detect:
4
+ filename: "\\.elm$"
5
+
6
+ rules:
7
+ - statement: "\\b(as|alias|case|else|exposing|if|import|in|let|module|of|port|then|type|)\\b"
8
+ - statement: "(\\=|\\:|\\->)"
9
+ - type: "\\b([A-Z][A-Za-z\\d]*)\\b"
10
+ - identifier: "^([a-z][A-Za-z\\d]*)\\b"
11
+ - constant.string:
12
+ start: '"""'
13
+ end: '"""'
14
+ skip: "\\\\."
15
+ rules:
16
+ - constant.specialChar: "\\\\."
17
+ - constant.string:
18
+ start: '"'
19
+ end: '"'
20
+ skip: "\\\\."
21
+ rules:
22
+ - constant.specialChar: "\\\\."
23
+ - constant.string:
24
+ start: "'"
25
+ end: "'"
26
+ skip: "\\\\."
27
+ rules:
28
+ - constant.specialChar: "\\\\."
29
+ - comment:
30
+ start: "--"
31
+ end: "$"
32
+ rules:
33
+ - todo: "(TODO|XXX|FIXME):?"
34
+ - comment:
35
+ start: "\\{-"
36
+ end: "-\\}"
37
+ rules:
38
+ - todo: "(TODO|XXX|FIXME):?"
@@ -0,0 +1,42 @@
1
+ filetype: erb
2
+
3
+ detect:
4
+ filename: "\\.erb$|\\.rhtml$"
5
+
6
+ rules:
7
+ - error: "<[^!].*?>"
8
+ - symbol.tag: "(?i)<[/]?(a(bbr|cronym|ddress|pplet|rea|rticle|side|udio)?|b(ase(font)?|d(i|o)|ig|lockquote|r)?|ca(nvas|ption)|center|cite|co(de|l|lgroup)|d(ata(list)?|d|el|etails|fn|ialog|ir|l|t)|em(bed)?|fieldset|fig(caption|ure)|font|form|(i)?frame|frameset|h[1-6]|hr|i|img|in(put|s)|kbd|keygen|label|legend|li(nk)?|ma(in|p|rk)|menu(item)?|met(a|er)|nav|no(frames|script)|o(l|pt(group|ion)|utput)|p(aram|icture|re|rogress)?|q|r(p|t|uby)|s(trike)?|samp|se(ction|lect)|small|source|span|strong|su(b|p|mmary)|textarea|time|track|u(l)?|var|video|wbr)( .*|>)*?>"
9
+ - symbol.tag.extended: "(?i)<[/]?(body|div|html|head(er)?|footer|title|table|t(body|d|h(ead)?|r|foot))( .*|>)*?>"
10
+ - preproc: "(?i)<[/]?(script|style)( .*|>)*?>"
11
+ - special: "&[^;[[:space:]]]*;"
12
+ - symbol: "[:=]"
13
+ - identifier: "(alt|bgcolor|height|href|id|label|longdesc|name|onclick|onfocus|onload|onmouseover|size|span|src|style|target|type|value|width)="
14
+ - constant.string: '"[^"]*"'
15
+ - constant.number: "(?i)#[0-9a-fA-F]{6,6}"
16
+ - constant.string.url: "(ftp(s)?|http(s)?|git|chrome)://[^ ]+"
17
+ - comment: "<!--.+?-->"
18
+ - preproc: "<!DOCTYPE.+?>"
19
+ - default:
20
+ start: "<%"
21
+ end: "%>"
22
+ rules: []
23
+
24
+ - preproc: "<%|%>"
25
+ - red: "&[^;[[:space:]]]*;"
26
+ - statement: "\\b(BEGIN|END|alias|and|begin|break|case|class|def|defined\\?|do|else|elsif|end|ensure|false|for|if|in|module|next|nil|not|or|redo|rescue|retry|return|self|super|then|true|undef|unless|until|when|while|yield)\\b"
27
+ - identifier.var: "(\\$|@|@@)?\\b[A-Z]+[0-9A-Z_a-z]*"
28
+ - magenta: "(?i)([ ]|^):[0-9A-Z_]+\\b"
29
+ - identifier.macro: "\\b(__FILE__|__LINE__)\\b"
30
+ - brightmagenta: "!/([^/]|(\\\\/))*/[iomx]*|%r\\{([^}]|(\\\\}))*\\}[iomx]*"
31
+ - brightblue: "`[^`]*`|%x\\{[^}]*\\}"
32
+ - constant.string: "\"([^\"]|(\\\\\"))*\"|%[QW]?\\{[^}]*\\}|%[QW]?\\([^)]*\\)|%[QW]?<[^>]*>|%[QW]?\\[[^]]*\\]|%[QW]?\\$[^$]*\\$|%[QW]?\\^[^^]*\\^|%[QW]?![^!]*!"
33
+ - brightgreen: "#\\{[^}]*\\}"
34
+ - green: "'([^']|(\\\\'))*'|%[qw]\\{[^}]*\\}|%[qw]\\([^)]*\\)|%[qw]<[^>]*>|%[qw]\\[[^]]*\\]|%[qw]\\$[^$]*\\$|%[qw]\\^[^^]*\\^|%[qw]![^!]*!"
35
+ - comment: "#[^{].*$|#$"
36
+ - comment.bright: "##[^{].*$|##$"
37
+ - identifier.macro:
38
+ start: "<<-?'?EOT'?"
39
+ end: "^EOT"
40
+ rules: []
41
+
42
+ - todo: "(XXX|TODO|FIXME|\\?\\?\\?)"
@@ -0,0 +1,45 @@
1
+ filetype: erlang
2
+
3
+ detect:
4
+ filename: "\\.erl$"
5
+
6
+ rules:
7
+ - identifier: "\\b[A-Z][0-9a-z_]*\\b"
8
+ # See: https://erlang.org/doc/reference_manual/data_types.html
9
+ - constant.number: "\\b[0-9]+(\\.[0-9]+)?(e-?[0-9]+)?\\b"
10
+ - constant.number: "\\b[0-9]{1,2}\\#[a-zA-Z0-9]+\\b"
11
+ - constant.bool: "\\b(true|false)\\b"
12
+ - constant.number: "\\$\\\\?\\S{1}"
13
+ # See: https://erlang.org/doc/reference_manual/introduction.html
14
+ - statement: "\\b(after|and|andalso|band|begin|bnot|bor|bsl|bsr|bxor|case|catch|cond|div|end|fun|if|let|not|of|or|orelse|receive|rem|try|when|xor)\\b"
15
+ # See: https://erlang.org/doc/reference_manual/macros.html
16
+ - preproc: "\\-(module|export|record|include|include_lib|define|undef|ifdef|ifndef|else|endif|if|elif|error|warning)\\b"
17
+ - identifier.macro: "\\?[A-Z0-9_]+\\b"
18
+ # See: https://erlang.org/doc/man/erlang.html
19
+ - special: "\\b(ext_binary|binary|iovec|message_queue_data|time(_unit|stamp)|abs|apply|atom(_to_binary|_to_list)|binary_(part|to_atom|to_existing_atom|to_float|to_integer|to_list|to_term)|bit(_size|string_to_list)|byte_size|ceil|check_(old_code|process_code)|date|delete_module|demonitor|disconnect_node|element|erase|error|exit|float(_to_binary|_to_list)?|floor|garbage_collect|get|group_leader|halt|integer(_to_binary|to_list)|iolist_(size|to_binary)|is_(alive|atom|binary|bitstring|boolean|float|function|integer|list|map|map_key|number|pid|port|process_alive|record|reference|tuple|length)|link|list_to_(atom|binary|bitstring|existing_atom|float|integer|pid|port|ref|tuple)|load_module|make_ref|map_(get|size)|max|min|module_loaded|monitor(_node)?|nodes?|now|open_port|pid_to_list|port(_close|command|connect|control|to_list)|pre_loaded|process(_flag|_info|es)|purge_module|put|register(ed)?|round|self|setelement|size|spawn(_link|_monitor|_opt|_binary)?|statistics|trunc|tuple_(size|to_list)|unlink|unregister|whereis)\\b"
20
+ # See: https://erlang.org/doc/reference_manual/data_types.html#atom
21
+ - symbol:
22
+ start: "'"
23
+ end: "'"
24
+ skip: "\\\\."
25
+ rules: []
26
+ # - constant.specialChar: "%."
27
+ # - constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
28
+ # - constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
29
+ - constant.string:
30
+ start: '"'
31
+ end: '"'
32
+ skip: "\\\\."
33
+ rules:
34
+ - constant.specialChar: "%."
35
+ - constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
36
+ - constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
37
+ - comment:
38
+ start: "\\(\\*"
39
+ end: "\\*\\)"
40
+ rules:
41
+ - todo: "(TODO|FIXME|WONTFIX|NOTE|HACK):?"
42
+ - comment:
43
+ start: "%"
44
+ end: "$"
45
+ rules: []
@@ -0,0 +1,48 @@
1
+ filetype: fsharp
2
+
3
+ detect:
4
+ filename: "\\.fs?$"
5
+
6
+ rules:
7
+ - identifier: "\\b[A-Z][0-9a-z_]{2,}\\b"
8
+ #declarations
9
+ - statement: "\\b(let|val|method|in|and|rec|private|virtual|constraint)\\b"
10
+ #structure items
11
+ - type: "\\b(type|open|class|module|exception|external)\\b"
12
+ #patterns
13
+ - statement: "\\b(fun|function|functor|match|try|with)\\b"
14
+ #patterns-modifiers
15
+ - statement: "\\b(as|when|of)\\b"
16
+ #conditions
17
+ - statement: "\\b(if|then|else)\\b"
18
+ #blocs
19
+ - type: "\\b(begin|end|object|struct|sig|for|while|do|done|to|downto)\\b"
20
+ #constantes
21
+ - constant.bool: "\\b(true|false)\\b"
22
+ #modules/classes
23
+ - special: "\\b(include|inherit|initializer)\\b"
24
+ #expr modifiers
25
+ - special: "\\b(new|ref|mutable|lazy|assert|raise)\\b"
26
+ #keywords which don't exist in ocaml
27
+ - type: "\\b(base|delegate|downcast|extern|finally|fixed|global|inline|interface|internal|let!|member|namespace|null|override|private|public)\\b"
28
+ - type: "\\b(return|return!|select|static|upcast|use|use!|void|yield|yield!)\\b"
29
+ - constant.string:
30
+ start: "'"
31
+ end: "'"
32
+ skip: "\\\\."
33
+ rules:
34
+ - constant.specialChar: "%."
35
+ - constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
36
+ - constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
37
+ - constant.string:
38
+ start: '"'
39
+ end: '"'
40
+ skip: "\\\\."
41
+ rules:
42
+ - constant.specialChar: "%."
43
+ - constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
44
+ - constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
45
+ - comment:
46
+ start: "\\(\\*"
47
+ end: "\\*\\)"
48
+ rules: []
@@ -0,0 +1,47 @@
1
+ filetype: graphql
2
+
3
+ detect:
4
+ filename: "\\.(gql|graphql)$"
5
+
6
+ rules:
7
+ - type: "\\b(?:(query|mutation|subscription|type|input|scalar|fragment|schema|union|on|extends?))\\b"
8
+
9
+ # scalar types
10
+ - statement: "\\b(ID|Int|Float|Boolean|String|Datetime|Null)\\b"
11
+
12
+ # introspection types
13
+ - statement: "(__\\w+)"
14
+
15
+ # parameters
16
+ - statement: "((\\w+)(?:\\:([\\s]*)?)(?:\\$))"
17
+
18
+ # directive locations
19
+ - statement: "\\b(QUERY|MUTATION|SUBSCRIPTION|FIELD|FRAGMENT_DEFINITION|FRAGMENT_SPREAD|INLINE_FRAGMENT|SCHEMA|SCALAR|OBJECT|FIELD_DEFINITION|ARGUMENT_DEFINITION|INTERFACE|UNION|ENUM|ENUM_VALUE|INPUT_OBJECT|INPUT_FIELD_DEFINITION)\\b"
20
+
21
+ # directives
22
+ - constant: "(@\\w+)"
23
+
24
+ # root types
25
+ - constant: "\\b(Query|Mutation|Subscription|Schema|Root)\\b"
26
+
27
+ # variables
28
+ - special: "(\\$\\w+)"
29
+
30
+ # required symbol
31
+ - special: "(!)"
32
+
33
+ - symbol: "(:|=|\\||\\(|\\)|\\{|\\}|\\[|\\])"
34
+
35
+ - constant.bool: "\\b(true|false)\\b"
36
+
37
+ - constant.string:
38
+ start: '"'
39
+ end: '"'
40
+ skip: "\\\\."
41
+ rules:
42
+ - constant.specialChar: "\\\\."
43
+
44
+ - comment:
45
+ start: "#"
46
+ end: "$"
47
+ rules: []