jsmdcui 0.3.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.
Files changed (258) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/LICENSE +22 -0
  3. package/README.md +285 -0
  4. package/package.json +17 -0
  5. package/project_structure.txt +35 -0
  6. package/runmd.mjs +240 -0
  7. package/runtime/colorschemes/atom-dark.micro +33 -0
  8. package/runtime/colorschemes/bubblegum.micro +31 -0
  9. package/runtime/colorschemes/cmc-16.micro +47 -0
  10. package/runtime/colorschemes/cmc-tc.micro +43 -0
  11. package/runtime/colorschemes/darcula.micro +34 -0
  12. package/runtime/colorschemes/default.micro +1 -0
  13. package/runtime/colorschemes/dracula-tc.micro +49 -0
  14. package/runtime/colorschemes/dukedark-tc.micro +38 -0
  15. package/runtime/colorschemes/dukelight-tc.micro +38 -0
  16. package/runtime/colorschemes/dukeubuntu-tc.micro +38 -0
  17. package/runtime/colorschemes/geany.micro +29 -0
  18. package/runtime/colorschemes/gotham.micro +29 -0
  19. package/runtime/colorschemes/gruvbox-tc.micro +29 -0
  20. package/runtime/colorschemes/gruvbox.micro +26 -0
  21. package/runtime/colorschemes/material-tc.micro +36 -0
  22. package/runtime/colorschemes/monokai-dark.micro +28 -0
  23. package/runtime/colorschemes/monokai.micro +34 -0
  24. package/runtime/colorschemes/one-dark.micro +39 -0
  25. package/runtime/colorschemes/railscast.micro +37 -0
  26. package/runtime/colorschemes/simple.micro +33 -0
  27. package/runtime/colorschemes/solarized-tc.micro +31 -0
  28. package/runtime/colorschemes/solarized.micro +30 -0
  29. package/runtime/colorschemes/sunny-day.micro +29 -0
  30. package/runtime/colorschemes/twilight.micro +40 -0
  31. package/runtime/colorschemes/zenburn.micro +30 -0
  32. package/runtime/help/actions.md +161 -0
  33. package/runtime/help/cdp.md +119 -0
  34. package/runtime/help/colors.md +421 -0
  35. package/runtime/help/commands.md +161 -0
  36. package/runtime/help/copypaste.md +149 -0
  37. package/runtime/help/defaultkeys.md +148 -0
  38. package/runtime/help/help.md +285 -0
  39. package/runtime/help/keybindings.md +355 -0
  40. package/runtime/help/linter.md +90 -0
  41. package/runtime/help/options.md +709 -0
  42. package/runtime/help/plugins.md +544 -0
  43. package/runtime/help/tutorial.md +112 -0
  44. package/runtime/jsplugins/cdp/cdp-server.js +1161 -0
  45. package/runtime/jsplugins/cdp/cdp.js +192 -0
  46. package/runtime/jsplugins/chapter/chapter.js +108 -0
  47. package/runtime/jsplugins/diff/diff.js +46 -0
  48. package/runtime/jsplugins/example/example.js +110 -0
  49. package/runtime/jsplugins/linter/linter.js +281 -0
  50. package/runtime/plugins/autoclose/autoclose.lua +75 -0
  51. package/runtime/plugins/ftoptions/ftoptions.lua +17 -0
  52. package/runtime/plugins/literate/README.md +5 -0
  53. package/runtime/plugins/literate/literate.lua +55 -0
  54. package/runtime/plugins/status/help/status.md +21 -0
  55. package/runtime/plugins/status/status.lua +62 -0
  56. package/runtime/syntax/LICENSE +22 -0
  57. package/runtime/syntax/PowerShell.yaml +128 -0
  58. package/runtime/syntax/README.md +63 -0
  59. package/runtime/syntax/ada.yaml +43 -0
  60. package/runtime/syntax/apacheconf.yaml +59 -0
  61. package/runtime/syntax/arduino.yaml +101 -0
  62. package/runtime/syntax/asciidoc.yaml +51 -0
  63. package/runtime/syntax/asm.yaml +123 -0
  64. package/runtime/syntax/ats.yaml +99 -0
  65. package/runtime/syntax/awk.yaml +44 -0
  66. package/runtime/syntax/b.yaml +87 -0
  67. package/runtime/syntax/bat.yaml +57 -0
  68. package/runtime/syntax/c.yaml +60 -0
  69. package/runtime/syntax/caddyfile.yaml +23 -0
  70. package/runtime/syntax/cake.yaml +7 -0
  71. package/runtime/syntax/clojure.yaml +38 -0
  72. package/runtime/syntax/cmake.yaml +42 -0
  73. package/runtime/syntax/coffeescript.yaml +56 -0
  74. package/runtime/syntax/colortest.yaml +19 -0
  75. package/runtime/syntax/conky.yaml +17 -0
  76. package/runtime/syntax/cpp.yaml +91 -0
  77. package/runtime/syntax/crontab.yaml +36 -0
  78. package/runtime/syntax/crystal.yaml +72 -0
  79. package/runtime/syntax/csharp.yaml +52 -0
  80. package/runtime/syntax/css.yaml +44 -0
  81. package/runtime/syntax/csx.yaml +8 -0
  82. package/runtime/syntax/cuda.yaml +68 -0
  83. package/runtime/syntax/cython.yaml +52 -0
  84. package/runtime/syntax/d.yaml +121 -0
  85. package/runtime/syntax/dart.yaml +46 -0
  86. package/runtime/syntax/default.yaml +10 -0
  87. package/runtime/syntax/dockerfile.yaml +36 -0
  88. package/runtime/syntax/dot.yaml +29 -0
  89. package/runtime/syntax/elixir.yaml +30 -0
  90. package/runtime/syntax/elm.yaml +38 -0
  91. package/runtime/syntax/erb.yaml +42 -0
  92. package/runtime/syntax/erlang.yaml +45 -0
  93. package/runtime/syntax/fish.yaml +48 -0
  94. package/runtime/syntax/forth.yaml +34 -0
  95. package/runtime/syntax/fortran.yaml +64 -0
  96. package/runtime/syntax/freebsd-kernel.yaml +14 -0
  97. package/runtime/syntax/fsharp.yaml +48 -0
  98. package/runtime/syntax/gdscript.yaml +61 -0
  99. package/runtime/syntax/gemini.yaml +19 -0
  100. package/runtime/syntax/gentoo-ebuild.yaml +48 -0
  101. package/runtime/syntax/gentoo-etc-portage.yaml +23 -0
  102. package/runtime/syntax/git-commit.yaml +35 -0
  103. package/runtime/syntax/git-config.yaml +14 -0
  104. package/runtime/syntax/git-rebase-todo.yaml +19 -0
  105. package/runtime/syntax/gleam.yaml +69 -0
  106. package/runtime/syntax/glsl.yaml +26 -0
  107. package/runtime/syntax/gnuplot.yaml +15 -0
  108. package/runtime/syntax/go.yaml +62 -0
  109. package/runtime/syntax/godoc.yaml +17 -0
  110. package/runtime/syntax/golo.yaml +73 -0
  111. package/runtime/syntax/gomod.yaml +31 -0
  112. package/runtime/syntax/graphql.yaml +47 -0
  113. package/runtime/syntax/groff.yaml +30 -0
  114. package/runtime/syntax/groovy.yaml +111 -0
  115. package/runtime/syntax/haml.yaml +16 -0
  116. package/runtime/syntax/hare.yaml +52 -0
  117. package/runtime/syntax/haskell.yaml +52 -0
  118. package/runtime/syntax/hc.yaml +52 -0
  119. package/runtime/syntax/html.yaml +70 -0
  120. package/runtime/syntax/html4.yaml +25 -0
  121. package/runtime/syntax/html5.yaml +25 -0
  122. package/runtime/syntax/ini.yaml +23 -0
  123. package/runtime/syntax/inputrc.yaml +14 -0
  124. package/runtime/syntax/java.yaml +37 -0
  125. package/runtime/syntax/javascript.yaml +124 -0
  126. package/runtime/syntax/jinja2.yaml +19 -0
  127. package/runtime/syntax/json.yaml +39 -0
  128. package/runtime/syntax/jsonnet.yaml +92 -0
  129. package/runtime/syntax/julia.yaml +57 -0
  130. package/runtime/syntax/justfile.yaml +40 -0
  131. package/runtime/syntax/keymap.yaml +27 -0
  132. package/runtime/syntax/kickstart.yaml +16 -0
  133. package/runtime/syntax/kotlin.yaml +66 -0
  134. package/runtime/syntax/kvlang.yaml +67 -0
  135. package/runtime/syntax/ledger.yaml +14 -0
  136. package/runtime/syntax/lfe.yaml +17 -0
  137. package/runtime/syntax/lilypond.yaml +26 -0
  138. package/runtime/syntax/lisp.yaml +17 -0
  139. package/runtime/syntax/log.yaml +92 -0
  140. package/runtime/syntax/lua.yaml +111 -0
  141. package/runtime/syntax/mail.yaml +25 -0
  142. package/runtime/syntax/makefile.yaml +38 -0
  143. package/runtime/syntax/man.yaml +12 -0
  144. package/runtime/syntax/markdown.yaml +49 -0
  145. package/runtime/syntax/mc.yaml +23 -0
  146. package/runtime/syntax/meson.yaml +51 -0
  147. package/runtime/syntax/micro.yaml +34 -0
  148. package/runtime/syntax/mpdconf.yaml +13 -0
  149. package/runtime/syntax/msbuild.yaml +6 -0
  150. package/runtime/syntax/nanorc.yaml +16 -0
  151. package/runtime/syntax/nftables.yaml +30 -0
  152. package/runtime/syntax/nginx.yaml +22 -0
  153. package/runtime/syntax/nim.yaml +27 -0
  154. package/runtime/syntax/nix.yaml +32 -0
  155. package/runtime/syntax/nu.yaml +114 -0
  156. package/runtime/syntax/objc.yaml +60 -0
  157. package/runtime/syntax/ocaml.yaml +43 -0
  158. package/runtime/syntax/octave.yaml +83 -0
  159. package/runtime/syntax/odin.yaml +64 -0
  160. package/runtime/syntax/pascal.yaml +45 -0
  161. package/runtime/syntax/patch.yaml +14 -0
  162. package/runtime/syntax/peg.yaml +16 -0
  163. package/runtime/syntax/perl.yaml +58 -0
  164. package/runtime/syntax/php.yaml +60 -0
  165. package/runtime/syntax/pkg-config.yaml +12 -0
  166. package/runtime/syntax/po.yaml +12 -0
  167. package/runtime/syntax/pony.yaml +37 -0
  168. package/runtime/syntax/pov.yaml +21 -0
  169. package/runtime/syntax/privoxy-action.yaml +14 -0
  170. package/runtime/syntax/privoxy-config.yaml +10 -0
  171. package/runtime/syntax/privoxy-filter.yaml +12 -0
  172. package/runtime/syntax/proto.yaml +40 -0
  173. package/runtime/syntax/prql.yaml +84 -0
  174. package/runtime/syntax/puppet.yaml +22 -0
  175. package/runtime/syntax/python2.yaml +60 -0
  176. package/runtime/syntax/python3.yaml +80 -0
  177. package/runtime/syntax/r.yaml +32 -0
  178. package/runtime/syntax/raku.yaml +42 -0
  179. package/runtime/syntax/reST.yaml +18 -0
  180. package/runtime/syntax/renpy.yaml +15 -0
  181. package/runtime/syntax/rpmspec.yaml +43 -0
  182. package/runtime/syntax/ruby.yaml +73 -0
  183. package/runtime/syntax/rust.yaml +78 -0
  184. package/runtime/syntax/sage.yaml +60 -0
  185. package/runtime/syntax/scad.yaml +53 -0
  186. package/runtime/syntax/scala.yaml +33 -0
  187. package/runtime/syntax/sed.yaml +13 -0
  188. package/runtime/syntax/sh.yaml +69 -0
  189. package/runtime/syntax/sls.yaml +15 -0
  190. package/runtime/syntax/smalltalk.yaml +55 -0
  191. package/runtime/syntax/solidity.yaml +41 -0
  192. package/runtime/syntax/sql.yaml +35 -0
  193. package/runtime/syntax/stata.yaml +67 -0
  194. package/runtime/syntax/svelte.yaml +27 -0
  195. package/runtime/syntax/swift.yaml +103 -0
  196. package/runtime/syntax/systemd.yaml +16 -0
  197. package/runtime/syntax/tcl.yaml +18 -0
  198. package/runtime/syntax/terraform.yaml +87 -0
  199. package/runtime/syntax/tex.yaml +32 -0
  200. package/runtime/syntax/toml.yaml +56 -0
  201. package/runtime/syntax/twig.yaml +55 -0
  202. package/runtime/syntax/typescript.yaml +49 -0
  203. package/runtime/syntax/v.yaml +80 -0
  204. package/runtime/syntax/vala.yaml +26 -0
  205. package/runtime/syntax/verilog.yaml +60 -0
  206. package/runtime/syntax/vhdl.yaml +37 -0
  207. package/runtime/syntax/vi.yaml +31 -0
  208. package/runtime/syntax/vue.yaml +64 -0
  209. package/runtime/syntax/xml.yaml +37 -0
  210. package/runtime/syntax/xresources.yaml +14 -0
  211. package/runtime/syntax/yaml.yaml +34 -0
  212. package/runtime/syntax/yum.yaml +12 -0
  213. package/runtime/syntax/zig.yaml +52 -0
  214. package/runtime/syntax/zscript.yaml +72 -0
  215. package/runtime/syntax/zsh.yaml +52 -0
  216. package/single-exe/README.md +80 -0
  217. package/single-exe/assetsHelper.js +90 -0
  218. package/single-exe/assetsLoader.mjs +85 -0
  219. package/single-exe/compiled.js +149 -0
  220. package/single-exe/entry.mjs +9 -0
  221. package/single-exe/packAssets.sh +7 -0
  222. package/src/buffer/backup.js +160 -0
  223. package/src/buffer/buffer.js +126 -0
  224. package/src/buffer/fixed3-codec.js +140 -0
  225. package/src/buffer/loc.js +38 -0
  226. package/src/buffer/message.js +29 -0
  227. package/src/config/clean.js +172 -0
  228. package/src/config/colorscheme.js +99 -0
  229. package/src/config/config.js +122 -0
  230. package/src/config/defaults.js +109 -0
  231. package/src/cui/rpc.mjs +259 -0
  232. package/src/cui/server.mjs +116 -0
  233. package/src/display/ansi-style.js +60 -0
  234. package/src/highlight/highlighter.js +243 -0
  235. package/src/highlight/parser.js +225 -0
  236. package/src/index.js +8009 -0
  237. package/src/lua/engine.js +71 -0
  238. package/src/platform/archive.js +50 -0
  239. package/src/platform/clipboard.js +278 -0
  240. package/src/platform/commands.js +137 -0
  241. package/src/plugins/js-bridge.js +983 -0
  242. package/src/plugins/manager.js +674 -0
  243. package/src/runtime/assets.js +90 -0
  244. package/src/runtime/compiled.js +25 -0
  245. package/src/runtime/encodings.js +10 -0
  246. package/src/runtime/registry.js +134 -0
  247. package/src/screen/cell-buffer.js +81 -0
  248. package/src/screen/events.js +263 -0
  249. package/src/screen/screen.js +142 -0
  250. package/src/screen/vt100.js +571 -0
  251. package/src/shell/shell.js +70 -0
  252. package/testapp.md +55 -0
  253. package/tests/backup.test.js +133 -0
  254. package/tests/cmphex3b64.js +95 -0
  255. package/tests/pty-demo.js +492 -0
  256. package/tests/wv-client.js +96 -0
  257. package/tui +5 -0
  258. package/wui +5 -0
@@ -0,0 +1,281 @@
1
+ // linter.js — JS port of linter.lua
2
+ // Runs linters on save, adds gutter messages via bp.Buf.AddMessage.
3
+ // micro global is available as globalThis.micro.
4
+
5
+ import { basename, dirname } from "node:path";
6
+
7
+ const GOOS = process.platform === "win32" ? "windows" : process.platform;
8
+ const devnull = GOOS === "windows" ? "NUL" : "/dev/null";
9
+
10
+ // ── Linter registry ───────────────────────────────────────────────────────────
11
+
12
+ const linters = new Map();
13
+
14
+ function makeLinter(name, filetype, cmd, args, errorformat, {
15
+ os: osList = [], whitelist = false, domatch = false, loffset = 0, coffset = 0,
16
+ } = {}) {
17
+ linters.set(name, { filetype, cmd, args, errorformat, osList, whitelist, domatch, loffset, coffset });
18
+ }
19
+
20
+ function removeLinter(name) { linters.delete(name); }
21
+
22
+ // ── Registrations (mirrors linter.lua preinit) ────────────────────────────────
23
+
24
+ makeLinter("gcc", "c", "gcc", ["-fsyntax-only", "-Wall", "-Wextra", "%f"], "%f:%l:%c:.+: %m");
25
+ makeLinter("g++", "c++", "g++", ["-fsyntax-only", "-Wall", "-Wextra", "%f"], "%f:%l:%c:.+: %m");
26
+ makeLinter("dmd", "d", "dmd", ["-color=off", "-o-", "-w", "-wi", "-c", "%f"], "%f%(%l%):.+: %m");
27
+ makeLinter("ldc2", "d", "ldc2", ["--o-", "--vcolumns", "-w", "-c", "%f"], "%f%(%l,%c%):[^:]+: %m");
28
+ makeLinter("gdc", "d", "gdc", ["-fsyntax-only", "-Wall", "-Wextra", "%f"], "%f:%l:%c:.+: %m");
29
+ makeLinter("eslint", "javascript", "eslint", ["-f", "json", "--no-ignore", "%f"], null); // JSON parsing
30
+ makeLinter("gobuild", "go", "go", ["build", "-o", devnull, "%d"], "%f:%l:%c:? %m");
31
+ makeLinter("govet", "go", "go", ["vet"], "%f:%l:%c: %m");
32
+ makeLinter("clippy", "rust", "cargo", ["clippy", "--message-format", "short"], "%f:%l:%c: %m");
33
+ makeLinter("hlint", "haskell", "hlint", ["%f"], "%f:%(?%l[,:]%c%)?.-: %m");
34
+ makeLinter("javac", "java", "javac", ["-d", "%d", "%f"], "%f:%l: error: %m");
35
+ makeLinter("jshint", "javascript", "jshint", ["%f"], "%f: line %l,.+, %m");
36
+ makeLinter("literate", "literate", "lit", ["-c", "%f"], "%f:%l:%m", { domatch: true });
37
+ makeLinter("luacheck", "lua", "luacheck", ["--no-color", "%f"], "%f:%l:%c: %m");
38
+ makeLinter("nim", "nim", "nim", ["check", "--listFullPaths", "--stdout", "--hints:off", "%f"], "%f.%l, %c. %m");
39
+ makeLinter("clang", "objective-c", "xcrun", ["clang", "-fsyntax-only", "-Wall", "-Wextra", "%f"], "%f:%l:%c:.+: %m");
40
+ makeLinter("pyflakes", "python", "pyflakes", ["%f"], "%f:%l:.-:? %m");
41
+ makeLinter("mypy", "python", "mypy", ["%f"], "%f:%l: %m");
42
+ makeLinter("pylint", "python", "pylint", ["--output-format=parseable", "--reports=no", "%f"], "%f:%l: %m");
43
+ makeLinter("ruff", "python", "ruff", ["check", "--output-format=concise", "%f"], "%f:%l:%c: %m");
44
+ makeLinter("flake8", "python", "flake8", ["%f"], "%f:%l:%c: %m");
45
+ makeLinter("shfmt", "shell", "shfmt", ["%f"], "%f:%l:%c: %m");
46
+ makeLinter("shellcheck", "shell", "shellcheck", ["-f", "gcc", "%f"], "%f:%l:%c:.+: %m");
47
+ makeLinter("swiftc", "swift", "xcrun", ["swiftc", "%f"], "%f:%l:%c:.+: %m", { os: ["darwin"], whitelist: true });
48
+ makeLinter("swiftc-linux","swift", "swiftc", ["%f"], "%f:%l:%c:.+: %m", { os: ["linux"], whitelist: true });
49
+ makeLinter("yaml", "yaml", "yamllint", ["--format", "parsable", "%f"], "%f:%l:%c:.+ %m");
50
+ makeLinter("nix-linter", "nix", "nix-linter", ["%f"], "%m at %f:%l:%c", { os: ["linux"], whitelist: true });
51
+
52
+ // ── Errorformat → JS regex ────────────────────────────────────────────────────
53
+
54
+ function parseErrorformat(ef) {
55
+ const captures = [];
56
+ let out = "";
57
+ let i = 0;
58
+
59
+ while (i < ef.length) {
60
+ if (ef[i] === "%") {
61
+ const next = ef[i + 1] ?? "";
62
+ i += 2;
63
+ switch (next) {
64
+ case "f": captures.push("f"); out += "(.+?)"; break;
65
+ case "l": captures.push("l"); out += "(\\d+)"; break;
66
+ case "c": captures.push("c"); out += "(\\d+)"; break;
67
+ case "m": captures.push("m"); out += "(.+)"; break;
68
+ case "%": out += "%"; break;
69
+ case "d": out += "\\d"; break;
70
+ case "D": out += "\\D"; break;
71
+ case "s": out += "\\s"; break;
72
+ case "S": out += "\\S"; break;
73
+ case "w": out += "\\w"; break;
74
+ case "W": out += "\\W"; break;
75
+ case "a": out += "[a-zA-Z]"; break;
76
+ default:
77
+ // Lua punctuation escape → literal, JS-escaped
78
+ out += next.replace(/[.+*?^${}()|[\]\\]/g, "\\$&");
79
+ break;
80
+ }
81
+ continue;
82
+ }
83
+
84
+ if (ef[i] === "[") {
85
+ let cls = "[";
86
+ i++;
87
+ while (i < ef.length && ef[i] !== "]") {
88
+ if (ef[i] === "%") {
89
+ const nc = ef[i + 1] ?? "";
90
+ i += 2;
91
+ if (nc === "s") cls += "\\s";
92
+ else if (nc === "S") cls += "\\S";
93
+ else if (nc === "d") cls += "\\d";
94
+ else if (nc === "w") cls += "\\w";
95
+ else if (nc === "%") cls += "%";
96
+ else cls += nc;
97
+ } else {
98
+ cls += ef[i++];
99
+ }
100
+ }
101
+ cls += "]";
102
+ if (ef[i] === "]") i++;
103
+ out += cls;
104
+ continue;
105
+ }
106
+
107
+ // Lua `.-` (lazy any) → JS `.*?`
108
+ if (ef[i] === "." && ef[i + 1] === "-") {
109
+ out += ".*?";
110
+ i += 2;
111
+ continue;
112
+ }
113
+
114
+ // `|` is literal in Lua patterns but special in JS regex
115
+ if (ef[i] === "|" || ef[i] === "{" || ef[i] === "}") {
116
+ out += "\\" + ef[i++];
117
+ continue;
118
+ }
119
+
120
+ out += ef[i++];
121
+ }
122
+
123
+ return { regex: new RegExp(out), captures };
124
+ }
125
+
126
+ const _parsedCache = new Map();
127
+ function getParsed(ef) {
128
+ if (!_parsedCache.has(ef)) _parsedCache.set(ef, parseErrorformat(ef));
129
+ return _parsedCache.get(ef);
130
+ }
131
+
132
+ // ── eslint JSON output parsing ────────────────────────────────────────────────
133
+
134
+ function parseEslintJson(output, bufPath) {
135
+ let results;
136
+ try { results = JSON.parse(output); } catch { return null; }
137
+ if (!Array.isArray(results)) return null;
138
+
139
+ const msgs = [];
140
+ const bufBase = basename(bufPath);
141
+ for (const file of results) {
142
+ if (!file?.messages || basename(file.filePath ?? "") !== bufBase) continue;
143
+ for (const m of file.messages) {
144
+ msgs.push({
145
+ line: m.line ?? 1,
146
+ col: m.column ?? 1,
147
+ msg: m.message ?? "",
148
+ severity: (m.severity ?? 2) >= 2 ? micro.buffer.MTError : micro.buffer.MTWarning,
149
+ });
150
+ }
151
+ }
152
+ return msgs;
153
+ }
154
+
155
+ // ── OS filter ─────────────────────────────────────────────────────────────────
156
+
157
+ function checkFtMatch(ft, v) {
158
+ let ftmatch = v.domatch ? new RegExp(v.filetype).test(ft) : ft === v.filetype;
159
+ if (!ftmatch) return false;
160
+ const hasOS = v.osList.includes(GOOS);
161
+ if (!hasOS && v.whitelist) return false;
162
+ if (hasOS && !v.whitelist) return false;
163
+ return true;
164
+ }
165
+
166
+ // ── Spawn + parse ─────────────────────────────────────────────────────────────
167
+
168
+ async function spawnAndCollect(argv) {
169
+ let proc;
170
+ try {
171
+ proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe", stdin: "ignore" });
172
+ } catch (err) {
173
+ micro.pushLintLog(`[linter:${argv[0]}] spawn failed: ${err.message}`);
174
+ return null;
175
+ }
176
+ const dec = new TextDecoder();
177
+ const readAll = async (stream) => {
178
+ const chunks = [];
179
+ if (!stream) return "";
180
+ const reader = stream.getReader();
181
+ while (true) {
182
+ const { done, value } = await reader.read();
183
+ if (done) break;
184
+ chunks.push(dec.decode(value, { stream: true }));
185
+ }
186
+ return chunks.join("");
187
+ };
188
+ try {
189
+ const [out, err] = await Promise.all([readAll(proc.stdout), readAll(proc.stderr)]);
190
+ await proc.exited;
191
+ return out + err;
192
+ } catch (err) {
193
+ micro.pushLintLog(`[linter:${argv[0]}] read failed: ${err.message}`);
194
+ return null;
195
+ }
196
+ }
197
+
198
+ async function lint(bufAdapter, linterName, v) {
199
+ const file = bufAdapter.Path ?? bufAdapter.path ?? "";
200
+ const dir = dirname(file) || ".";
201
+
202
+ const argv = [v.cmd, ...v.args.map(a => a.replace(/%f/g, file).replace(/%d/g, dir))];
203
+ const output = await spawnAndCollect(argv);
204
+ if (output == null) return;
205
+
206
+ bufAdapter.ClearMessages(linterName);
207
+
208
+ // eslint: JSON path
209
+ if (v.errorformat === null) {
210
+ const msgs = parseEslintJson(output, file);
211
+ if (!msgs) {
212
+ if (output.trim()) micro.pushLintLog(`[linter:${linterName}]\n${output.trim()}`);
213
+ return;
214
+ }
215
+ for (const { line, col, msg, severity } of msgs) {
216
+ const start = micro.buffer.Loc(col - 1 + v.coffset, line - 1 + v.loffset);
217
+ const end = micro.buffer.Loc(col + v.coffset, line - 1 + v.loffset);
218
+ bufAdapter.AddMessage(micro.buffer.newMessage(linterName, msg, start, end, severity));
219
+ }
220
+ micro.render();
221
+ return;
222
+ }
223
+
224
+ // Generic errorformat path
225
+ const { regex, captures } = getParsed(v.errorformat);
226
+ const hasCol = captures.includes("c");
227
+ const bufBase = basename(file);
228
+
229
+ for (let rawLine of output.split("\n")) {
230
+ rawLine = rawLine.replace(/^\s+|\s+$/g, "");
231
+ if (!rawLine) continue;
232
+ const m = regex.exec(rawLine);
233
+ if (!m) continue;
234
+
235
+ const capMap = {};
236
+ captures.forEach((k, idx) => { capMap[k] = m[idx + 1]; });
237
+
238
+ if (!capMap.f || basename(capMap.f) !== bufBase) continue;
239
+
240
+ const lineNum = Number(capMap.l ?? 1);
241
+ const colNum = Number(capMap.c ?? 1);
242
+ const msg = capMap.m ?? "";
243
+
244
+ let bmsg;
245
+ if (hasCol && capMap.c != null) {
246
+ const start = micro.buffer.Loc(colNum - 1 + v.coffset, lineNum - 1 + v.loffset);
247
+ const end = micro.buffer.Loc(colNum + v.coffset, lineNum - 1 + v.loffset);
248
+ bmsg = micro.buffer.newMessage(linterName, msg, start, end, micro.buffer.MTError);
249
+ } else {
250
+ bmsg = micro.buffer.newMessageAtLine(linterName, msg, lineNum + v.loffset, micro.buffer.MTError);
251
+ }
252
+ bufAdapter.AddMessage(bmsg);
253
+ }
254
+ micro.render();
255
+ }
256
+
257
+ async function runLinter(bp) {
258
+ const ft = bp.Buf.FileType();
259
+ const buf = bp.Buf;
260
+
261
+ for (const [name, v] of linters) {
262
+ if (!checkFtMatch(ft, v)) continue;
263
+ lint(buf, name, v).catch(e => micro.pushLintLog(`[linter:${name}] ${e.message}`));
264
+ }
265
+ }
266
+
267
+ // ── Hook registration ─────────────────────────────────────────────────────────
268
+
269
+ micro.on("init", () => {
270
+ micro.MakeCommand("lint", async (bp) => {
271
+ await bp.Save();
272
+ await runLinter(bp);
273
+ });
274
+ });
275
+
276
+ micro.on("onSave", (bp) => {
277
+ runLinter(bp).catch(e => micro.pushLintLog(`[linter:onSave] ${e.message}`));
278
+ });
279
+
280
+ // Expose API for user init.js to override linter definitions
281
+ globalThis.linter = { makeLinter, removeLinter, linters };
@@ -0,0 +1,75 @@
1
+ VERSION = "1.0.0"
2
+
3
+ local uutil = import("micro/util")
4
+ local utf8 = import("utf8")
5
+ local autoclosePairs = {"\"\"", "''", "``", "()", "{}", "[]"}
6
+ local autoNewlinePairs = {"()", "{}", "[]"}
7
+
8
+ function charAt(str, i)
9
+ -- lua indexing is one off from go
10
+ return uutil.RuneAt(str, i-1)
11
+ end
12
+
13
+ function onRune(bp, r)
14
+ for i = 1, #autoclosePairs do
15
+ if r == charAt(autoclosePairs[i], 2) then
16
+ local curLine = bp.Buf:Line(bp.Cursor.Y)
17
+
18
+ if charAt(curLine, bp.Cursor.X+1) == charAt(autoclosePairs[i], 2) then
19
+ bp:Backspace()
20
+ bp:CursorRight()
21
+ break
22
+ end
23
+
24
+ if bp.Cursor.X > 1 and (uutil.IsWordChar(charAt(curLine, bp.Cursor.X-1)) or charAt(curLine, bp.Cursor.X-1) == charAt(autoclosePairs[i], 1)) then
25
+ break
26
+ end
27
+ end
28
+ if r == charAt(autoclosePairs[i], 1) then
29
+ local curLine = bp.Buf:Line(bp.Cursor.Y)
30
+
31
+ if bp.Cursor.X == uutil.CharacterCountInString(curLine) or not uutil.IsWordChar(charAt(curLine, bp.Cursor.X+1)) then
32
+ -- the '-' here is to derefence the pointer to bp.Cursor.Loc which is automatically made
33
+ -- when converting go structs to lua
34
+ -- It needs to be dereferenced because the function expects a non pointer struct
35
+ bp.Buf:Insert(-bp.Cursor.Loc, charAt(autoclosePairs[i], 2))
36
+ bp:CursorLeft()
37
+ break
38
+ end
39
+ end
40
+ end
41
+ return true
42
+ end
43
+
44
+ function preInsertNewline(bp)
45
+ local curLine = bp.Buf:Line(bp.Cursor.Y)
46
+ local curRune = charAt(curLine, bp.Cursor.X)
47
+ local nextRune = charAt(curLine, bp.Cursor.X+1)
48
+ local ws = uutil.GetLeadingWhitespace(curLine)
49
+
50
+ for i = 1, #autoNewlinePairs do
51
+ if curRune == charAt(autoNewlinePairs[i], 1) then
52
+ if nextRune == charAt(autoNewlinePairs[i], 2) then
53
+ bp.Buf:Insert(-bp.Cursor.Loc, "\n" .. ws)
54
+ bp:StartOfLine()
55
+ bp:CursorLeft()
56
+ bp:InsertNewline()
57
+ bp:InsertTab()
58
+ return false
59
+ end
60
+ end
61
+ end
62
+
63
+ return true
64
+ end
65
+
66
+ function preBackspace(bp)
67
+ for i = 1, #autoclosePairs do
68
+ local curLine = bp.Buf:Line(bp.Cursor.Y)
69
+ if charAt(curLine, bp.Cursor.X+1) == charAt(autoclosePairs[i], 2) and charAt(curLine, bp.Cursor.X) == charAt(autoclosePairs[i], 1) then
70
+ bp:Delete()
71
+ end
72
+ end
73
+
74
+ return true
75
+ end
@@ -0,0 +1,17 @@
1
+ VERSION = "1.0.0"
2
+
3
+ function onBufferOpen(b)
4
+ local ft = b:FileType()
5
+
6
+ if ft == "go" or
7
+ ft == "makefile" then
8
+ b:SetOption("tabstospaces", "off")
9
+ elseif ft == "fish" or
10
+ ft == "python" or
11
+ ft == "python2" or
12
+ ft == "python3" or
13
+ ft == "yaml" or
14
+ ft == "nim" then
15
+ b:SetOption("tabstospaces", "on")
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # Literate Micro
2
+
3
+ Support for reading `.lit` files from [zyedidia/Literate](https://github.com/zyedidia/Literate).
4
+
5
+ This plugin will automatically detect the filetype and highlight the correct language inside the code blocks.
@@ -0,0 +1,55 @@
1
+ VERSION = "1.0.0"
2
+
3
+ local config = import("micro/config")
4
+
5
+ function startswith(str, start)
6
+ return string.sub(str,1,string.len(start))==start
7
+ end
8
+
9
+ function endswith(str, endStr)
10
+ return endStr=='' or string.sub(str,-string.len(endStr))==endStr
11
+ end
12
+
13
+ function split(string, sep)
14
+ local sep, fields = sep or ":", {}
15
+ local pattern = string.format("([^%s]+)", sep)
16
+ string:gsub(pattern, function(c) fields[#fields+1] = c end)
17
+ return fields
18
+ end
19
+
20
+ function onBufferOpen(buf)
21
+ if not endswith(buf.Path, ".lit") then
22
+ return
23
+ end
24
+
25
+ local codetype = "unknown"
26
+ for i=1,buf:LinesNum() do
27
+ local line = buf:Line(i-1)
28
+ if startswith(line, "@code_type") then
29
+ codetype = split(line, " ")[2]
30
+ break
31
+ end
32
+ end
33
+
34
+ local syntaxFile = ""
35
+ syntaxFile = syntaxFile .. "filetype: literate-" .. codetype .. "\n"
36
+ syntaxFile = syntaxFile .. "detect:\n"
37
+ syntaxFile = syntaxFile .. " filename: \"\\\\.lit$\"\n"
38
+ syntaxFile = syntaxFile .. "rules:\n"
39
+ syntaxFile = syntaxFile .. " - include: \"markdown\"\n"
40
+ syntaxFile = syntaxFile .. " - special: \"^(@s|@title|@code_type|@comment_type|@include|@change|@change_end)\"\n"
41
+ syntaxFile = syntaxFile .. " - special: \"(@add_css|@overwrite_css|@colorscheme|@compiler|@error_format|@book)\"\n"
42
+ syntaxFile = syntaxFile .. " - default:\n"
43
+ syntaxFile = syntaxFile .. " start: \"---.*$\"\n"
44
+ syntaxFile = syntaxFile .. " end: \"---$\"\n"
45
+ syntaxFile = syntaxFile .. " limit-group: \"identifier\"\n"
46
+ syntaxFile = syntaxFile .. " rules:\n"
47
+ syntaxFile = syntaxFile .. " - special:\n"
48
+ syntaxFile = syntaxFile .. " start: \"@\\\\{\"\n"
49
+ syntaxFile = syntaxFile .. " end: \"\\\\}\"\n"
50
+ syntaxFile = syntaxFile .. " - include: " .. codetype .. "\n"
51
+
52
+ config.AddRuntimeFileFromMemory(config.RTSyntax, "literate.yaml", syntaxFile)
53
+ config.Reload()
54
+ buf:UpdateRules()
55
+ end
@@ -0,0 +1,21 @@
1
+ # Status
2
+
3
+ The status plugin provides some functions for modifying the status line.
4
+
5
+ Using the `statusformatl` and `statusformatr` options, the exact contents
6
+ of the status line can be modified. Please see the documentation for
7
+ those options (`> help options`) for more information.
8
+
9
+ This plugin provides functions that can be used in the status line format:
10
+
11
+ * `status.branch`: returns the name of the current git branch in the repository
12
+ where the file is located.
13
+ * `status.hash`: returns the hash of the current git commit in the repository
14
+ where the file is located.
15
+ * `status.paste`: returns "" if the paste option is disabled and "PASTE"
16
+ if it is enabled.
17
+ * `status.lines`: returns the number of lines in the buffer.
18
+ * `status.vcol`: returns the visual column number of the cursor.
19
+ * `status.bytes`: returns the number of bytes in the current buffer.
20
+ * `status.size`: returns the size of the current buffer in a human-readable
21
+ format.
@@ -0,0 +1,62 @@
1
+ VERSION = "1.0.0"
2
+
3
+ local micro = import("micro")
4
+ local buffer = import("micro/buffer")
5
+ local config = import("micro/config")
6
+ local shell = import("micro/shell")
7
+ local filepath = import("filepath")
8
+ local humanize = import("humanize")
9
+ local strings = import("strings")
10
+
11
+ function init()
12
+ micro.SetStatusInfoFn("status.branch")
13
+ micro.SetStatusInfoFn("status.hash")
14
+ micro.SetStatusInfoFn("status.paste")
15
+ micro.SetStatusInfoFn("status.vcol")
16
+ micro.SetStatusInfoFn("status.lines")
17
+ micro.SetStatusInfoFn("status.bytes")
18
+ micro.SetStatusInfoFn("status.size")
19
+ config.AddRuntimeFile("status", config.RTHelp, "help/status.md")
20
+ end
21
+
22
+ function lines(b)
23
+ return tostring(b:LinesNum())
24
+ end
25
+
26
+ function vcol(b)
27
+ return tostring(b:GetActiveCursor():GetVisualX(false))
28
+ end
29
+
30
+ function bytes(b)
31
+ return tostring(b:Size())
32
+ end
33
+
34
+ function size(b)
35
+ return humanize.Bytes(b:Size())
36
+ end
37
+
38
+ local function parseRevision(b, opt)
39
+ if b.Type.Kind ~= buffer.BTInfo then
40
+ local dir = filepath.Dir(b.Path)
41
+ local str, err = shell.ExecCommand("git", "-C", dir, "rev-parse", opt, "HEAD")
42
+ if err == nil then
43
+ return strings.TrimSpace(str)
44
+ end
45
+ end
46
+ return ""
47
+ end
48
+
49
+ function branch(b)
50
+ return parseRevision(b, "--abbrev-ref")
51
+ end
52
+
53
+ function hash(b)
54
+ return parseRevision(b, "--short")
55
+ end
56
+
57
+ function paste(b)
58
+ if config.GetGlobalOption("paste") then
59
+ return "PASTE "
60
+ end
61
+ return ""
62
+ end
@@ -0,0 +1,22 @@
1
+ Micro's syntax files are licensed under the MIT "Expat" License:
2
+
3
+ Copyright (c) 2020: Zachary Yedidia, et al.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,128 @@
1
+ # PowerShell syntax highlighting file for micro - https://micro-editor.github.io/
2
+ # PowerShell syntax taken from: https://github.com/PowerShell/EditorSyntax
3
+
4
+ filetype: powershell
5
+
6
+ detect:
7
+ filename: "\\.ps(1|m1|d1)$"
8
+
9
+ rules:
10
+ # - comment.block: # Block Comment
11
+ # - comment.doc: # Doc Comment
12
+ # - comment.line: # Line Comment
13
+ # - comment.shebang: # Shebang Line
14
+
15
+ # - constant: # Constant
16
+ # - constant.bool: # Constant (true, false)
17
+ # - constant.interpolation:
18
+ # - constant.number: # Constant (null)
19
+ # - constant.specialChar:
20
+ # - constant.string: # String
21
+ # - constant.string.char:
22
+ # - constant.string.url: # Uri
23
+ # - constant.unicode:
24
+
25
+ # - identifier: # Also used for functions
26
+ # - identifier.class: # Also used for functions
27
+ # - identifier.macro:
28
+ # - identifier.var:
29
+
30
+ # - preproc: # Preprocessor
31
+ # - preproc.DebugIdentifier: # Preprocessor
32
+ # - preproc.shebang: # The #! at the beginning of a file that tells the os what script interpreter to use
33
+
34
+ # - special: # Special (global|local|private|script|using|workflow)
35
+
36
+ # - statement: # Statements Keywords
37
+ # - statement.built_in:
38
+ # - statement.declaration: # Declaration Keywords
39
+ # - statement.meta: # Meta
40
+ # - statement.reserved: # Reserved Keywords
41
+
42
+ # - symbol
43
+ # - symbol.brackets: # {}()[] and sometimes <>
44
+ # - symbol.operator: # Operators
45
+ # - symbol.tag: # For html tags, among other things
46
+
47
+ # - type
48
+ # - type.collections: # Collections (array, hashtable)
49
+ # - type.ctypes: # CTypes (CBool, CChar, etc.)
50
+ # - type.keyword: # If you want a special highlight for keywords like 'private'
51
+ # - type.storage: # Storage Types (int, uint, string, etc.)
52
+
53
+ # Class
54
+ - identifier.class: "class +[A-Za-z0-9]+ *((:) +[A-Za-z0-9.]+)?"
55
+ - identifier.class: "(function)(?:([[:space:]][A-Za-z0-9]+[[:space:]]*))"
56
+
57
+ # Verbs taken from PwSh 6.0.2
58
+ - identifier: "(Add|Approve|Assert|Backup|Block|Build|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy)[-][A-Za-z0-9]+"
59
+ - identifier: "(Debug|Deny|Deploy|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide)[-][A-Za-z0-9]+"
60
+ - identifier: "(Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push)[-][A-Za-z0-9]+"
61
+ - identifier: "(Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke)[-][A-Za-z0-9]+"
62
+ - identifier: "(Save|Search|Select|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Test|Trace)[-][A-Za-z0-9]+"
63
+ - identifier: "(Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Write)[-][A-Za-z0-9]+"
64
+ - identifier.var: "\\$(?i)((Global|Local|Private|Script|Using|Workflow)[:])?[A-Za-z0-9]*"
65
+
66
+
67
+ # Expression and types
68
+ - type: "\\[\\b([A-Za-z]+|[A-Za-z]+[0-9]+)\\b\\]"
69
+
70
+ # Keywords
71
+ - statement: "\\b(alias|as|begin|break|catch|continue|data|default|define|do|dynamicparam)\\b"
72
+ - statement: "\\b(else|elseif|end|exit|finally|for|foreach|foreach-object|from|if|in|inlinescript)\\b"
73
+ - statement: "\\b(parallel|param|process|return|switch|throw|trap|try|until|using|var|where|where-object|while)\\b"
74
+
75
+ # Special Keywords
76
+ - special: "\\b(break|continue|exit)\\b"
77
+
78
+ - symbol.brackets: "(\\{|\\})"
79
+ - symbol.brackets: "(\\(|\\))"
80
+ - symbol.brackets: "(\\[|\\])"
81
+ - symbol.operator: "[\\-+/*=<>?:!~%&|]"
82
+ - symbol.operator: "[[:space:]][-](ne|eq|gt|ge|lt|le|like|notlike|match|notmatch|contains|notcontains|in|notin|replace|is|isnot)[[:space:]]"
83
+
84
+ # Constants
85
+ - constant.bool: "\\b\\$(true|false|null)\\b"
86
+ - constant.number: "\\b([0-9._]+|0x[A-Fa-f0-9_]+|0b[0-1_]+)[FL]?\\b"
87
+
88
+ # Expression Mode String
89
+ - constant.string:
90
+ start: "\""
91
+ end: "\""
92
+ #skip: "\\\\."
93
+ rules:
94
+ - constant.specialChar: "\\\\([btnfr]|'|\\\"|\\\\)"
95
+ - constant.specialChar: "\\\\u[A-Fa-f0-9]{4}"
96
+
97
+ # Argument Mode String
98
+ - constant.string:
99
+ start: "'"
100
+ end: "'"
101
+ #skip: "\\\\."
102
+ rules:
103
+ - constant.specialChar: "\\\\([btnfr]|'|\\\"|\\\\)"
104
+ - constant.specialChar: "\\\\u[A-Fa-f0-9]{4}"
105
+
106
+ # Line Comment
107
+ - comment:
108
+ start: "#"
109
+ end: "$"
110
+ rules:
111
+ - todo: "(TODO|XXX|FIXME|BUG):?"
112
+
113
+ # Block Comment
114
+ - comment:
115
+ start: "<#"
116
+ end: "#>"
117
+ rules:
118
+ - todo: "(TODO|XXX|FIXME|BUG):?"
119
+
120
+ # Embedded C#
121
+ - default:
122
+ start: "@\""
123
+ end: "\"@"
124
+ rules:
125
+ - include: "csharp"
126
+
127
+ # Todo
128
+ - todo: "(TODO|XXX|FIXME|BUG):?"