pair-mode 0.2.1 → 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 +12 -0
  2. package/.codex-plugin/plugin.json +29 -0
  3. package/README.md +79 -0
  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/hooks/codex.json +17 -0
  43. package/hooks/hooks.json +16 -0
  44. package/package.json +8 -3
  45. package/skills/toggle/SKILL.md +24 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "pair-mode",
3
+ "version": "0.3.3",
4
+ "description": "Hold every proposed edit, annotate the diff line by line, and hand the notes back to the agent.",
5
+ "author": {
6
+ "name": "ofrusch",
7
+ "email": "owenc343@gmail.com"
8
+ },
9
+ "homepage": "https://github.com/oFrusch/pair-mode#readme",
10
+ "repository": "https://github.com/oFrusch/pair-mode.git",
11
+ "license": "MIT"
12
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "pair-mode",
3
+ "version": "0.3.3",
4
+ "description": "Hold every proposed edit, annotate the diff line by line, and hand the notes back to the agent.",
5
+ "author": {
6
+ "name": "ofrusch",
7
+ "url": "https://github.com/oFrusch"
8
+ },
9
+ "homepage": "https://github.com/oFrusch/pair-mode#readme",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "code-review",
13
+ "diff",
14
+ "hooks",
15
+ "pair-programming",
16
+ "terminal"
17
+ ],
18
+ "hooks": "./hooks/codex.json",
19
+ "skills": "./skills/",
20
+ "interface": {
21
+ "displayName": "Pair Mode",
22
+ "shortDescription": "Review each proposed edit before it lands",
23
+ "longDescription": "Pair mode intercepts every proposed edit. It renders the diff in a terminal pane or a browser page, collects notes anchored to line numbers, then holds the edit and returns those notes to the agent. A review you close with no notes applies the edit as proposed.",
24
+ "developerName": "ofrusch",
25
+ "category": "Engineering",
26
+ "websiteURL": "https://github.com/oFrusch/pair-mode",
27
+ "logo": "./assets/duck.png"
28
+ }
29
+ }
package/README.md CHANGED
@@ -16,6 +16,33 @@ When enabled, your agent will push diffs to your editing interface of choice (yo
16
16
 
17
17
  ## Install
18
18
 
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.
21
+
22
+ ### As a plugin
23
+
24
+ A plugin resolves its own path at runtime, so it needs no global install and no setup step.
25
+
26
+ Claude Code:
27
+
28
+ ```
29
+ /plugin marketplace add oFrusch/pair-mode
30
+ /plugin install pair-mode@pair-mode
31
+ ```
32
+
33
+ Codex:
34
+
35
+ ```
36
+ codex plugin marketplace add oFrusch/pair-mode
37
+ codex plugin add pair-mode@pair-mode
38
+ ```
39
+
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
+
19
46
  ```
20
47
  npm install -g pair-mode
21
48
  pair-mode setup
@@ -59,6 +86,14 @@ This is what will render your diff if you choose to use one of the CLI-based app
59
86
  | nvim | Yes | Yes. Same `matchadd()` overlay as vim. |
60
87
  | nano | Yes | No. nano has no syntax engine here, so a changed row gets the diff band only. |
61
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
+
62
97
  Keys:
63
98
 
64
99
  - pair: see [Keymap](#keymap) below.
@@ -97,6 +132,50 @@ If you want to do all your development in one terminal pane while using either C
97
132
  Session mode moves the review out of the agent's process. The hook posts to a Unix
98
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.
99
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
+
100
179
  ### Session mode config
101
180
 
102
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: []