opencode-vim 0.0.3 → 0.0.5
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/README.md +2 -0
- package/assets/demo.gif +0 -0
- package/bun.lock +63 -0
- package/docs/configuration.md +18 -0
- package/package.json +4 -1
- package/src/modules/vim/index.tsx +66 -1
- package/src/modules/vim/vimee.ts +3 -3
- package/src/plugin.tsx +23 -1
- package/src/update.ts +109 -0
package/README.md
CHANGED
package/assets/demo.gif
ADDED
|
Binary file
|
package/bun.lock
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"@vimee/core": "^0.3.0",
|
|
11
11
|
"solid-js": "^1.9.12",
|
|
12
12
|
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@opencode-ai/plugin": "1.14.30",
|
|
15
|
+
},
|
|
13
16
|
},
|
|
14
17
|
},
|
|
15
18
|
"packages": {
|
|
@@ -79,6 +82,22 @@
|
|
|
79
82
|
|
|
80
83
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
|
81
84
|
|
|
85
|
+
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],
|
|
86
|
+
|
|
87
|
+
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="],
|
|
88
|
+
|
|
89
|
+
"@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="],
|
|
90
|
+
|
|
91
|
+
"@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="],
|
|
92
|
+
|
|
93
|
+
"@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="],
|
|
94
|
+
|
|
95
|
+
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],
|
|
96
|
+
|
|
97
|
+
"@opencode-ai/plugin": ["@opencode-ai/plugin@1.14.30", "", { "dependencies": { "@opencode-ai/sdk": "1.14.30", "effect": "4.0.0-beta.57", "zod": "4.1.8" }, "peerDependencies": { "@opentui/core": ">=0.1.105", "@opentui/solid": ">=0.1.105" }, "optionalPeers": ["@opentui/core", "@opentui/solid"] }, "sha512-O1y6qR349R5XJtB76Vx4TO/uvLkqNvdsgxtj2ZpWoygb3rtrkuVMiBsrcL2WfuyyaLJnPmbnkeigcdm42r09Hg=="],
|
|
98
|
+
|
|
99
|
+
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.14.30", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-OgPEDvALekHZIjByo/okJ699aLPn+XtsVxgZxUqE8TlzAG7TtskMGFl0fro8O0T2p+nkOT/LstnKGbECvc0+YA=="],
|
|
100
|
+
|
|
82
101
|
"@opentui/core": ["@opentui/core@0.2.1", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.1", "@opentui/core-darwin-x64": "0.2.1", "@opentui/core-linux-arm64": "0.2.1", "@opentui/core-linux-x64": "0.2.1", "@opentui/core-win32-arm64": "0.2.1", "@opentui/core-win32-x64": "0.2.1" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-tXFD2NeznXzZa02yOsQ/D0o/06GBqVrPR7VdmgqI+ZChcS7NY/QgNQGgAZUditW2vezFcxlgTqoCgQaZFqRfGQ=="],
|
|
83
102
|
|
|
84
103
|
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vT8rgeNdkzD84wCcS5zmrSVFgR/SjeVr+2FNM/icTjwKh9Jq3cY6UY7/EFck3PRjrmanNu4zw7W5lFKSpMxnPQ=="],
|
|
@@ -95,6 +114,8 @@
|
|
|
95
114
|
|
|
96
115
|
"@opentui/solid": ["@opentui/solid@0.2.1", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.1", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-/vlW9SmcqkarbMwB4JaIwwS3ovo42DSwAnyM04pjJVhG7DzKKwdUzozQMRgvEDZZ7oGYQRvHyVAfL8GCLh0AZw=="],
|
|
97
116
|
|
|
117
|
+
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
118
|
+
|
|
98
119
|
"@vimee/core": ["@vimee/core@0.3.0", "", {}, "sha512-aC44fw6HhmjrbJMafAk3oUZIDpFbgNebbDsWwMIFD0WwnOUZPETgzU3HYQetmwz0e38JY3I/g8CJXRQjspgJZw=="],
|
|
99
120
|
|
|
100
121
|
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
|
@@ -119,12 +140,18 @@
|
|
|
119
140
|
|
|
120
141
|
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
|
121
142
|
|
|
143
|
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
144
|
+
|
|
122
145
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
|
123
146
|
|
|
124
147
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
125
148
|
|
|
149
|
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
150
|
+
|
|
126
151
|
"diff": ["diff@9.0.0", "", {}, "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw=="],
|
|
127
152
|
|
|
153
|
+
"effect": ["effect@4.0.0-beta.57", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g=="],
|
|
154
|
+
|
|
128
155
|
"electron-to-chromium": ["electron-to-chromium@1.5.345", "", {}, "sha512-F9JXQGiMrz6yVNPI2qOVPvB9HzjH5cGzhs8oJ6A28V5L/YnzN/0KsuiibqF+F1Fd9qxFzD1BUnYSd8JfULxTwg=="],
|
|
129
156
|
|
|
130
157
|
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
|
@@ -135,8 +162,12 @@
|
|
|
135
162
|
|
|
136
163
|
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
|
137
164
|
|
|
165
|
+
"fast-check": ["fast-check@4.7.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ=="],
|
|
166
|
+
|
|
138
167
|
"find-babel-config": ["find-babel-config@2.1.2", "", { "dependencies": { "json5": "^2.2.3" } }, "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg=="],
|
|
139
168
|
|
|
169
|
+
"find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],
|
|
170
|
+
|
|
140
171
|
"find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="],
|
|
141
172
|
|
|
142
173
|
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
|
@@ -153,14 +184,20 @@
|
|
|
153
184
|
|
|
154
185
|
"html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="],
|
|
155
186
|
|
|
187
|
+
"ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
|
|
188
|
+
|
|
156
189
|
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
|
157
190
|
|
|
191
|
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
192
|
+
|
|
158
193
|
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
|
159
194
|
|
|
160
195
|
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
|
161
196
|
|
|
162
197
|
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
|
163
198
|
|
|
199
|
+
"kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
|
|
200
|
+
|
|
164
201
|
"locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="],
|
|
165
202
|
|
|
166
203
|
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
|
@@ -173,6 +210,14 @@
|
|
|
173
210
|
|
|
174
211
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
175
212
|
|
|
213
|
+
"msgpackr": ["msgpackr@1.11.10", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA=="],
|
|
214
|
+
|
|
215
|
+
"msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="],
|
|
216
|
+
|
|
217
|
+
"multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
|
|
218
|
+
|
|
219
|
+
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
|
|
220
|
+
|
|
176
221
|
"node-releases": ["node-releases@2.0.38", "", {}, "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw=="],
|
|
177
222
|
|
|
178
223
|
"p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
|
@@ -185,6 +230,8 @@
|
|
|
185
230
|
|
|
186
231
|
"path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="],
|
|
187
232
|
|
|
233
|
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
234
|
+
|
|
188
235
|
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
|
189
236
|
|
|
190
237
|
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
|
@@ -193,6 +240,8 @@
|
|
|
193
240
|
|
|
194
241
|
"pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="],
|
|
195
242
|
|
|
243
|
+
"pure-rand": ["pure-rand@8.4.0", "", {}, "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A=="],
|
|
244
|
+
|
|
196
245
|
"reselect": ["reselect@4.1.8", "", {}, "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="],
|
|
197
246
|
|
|
198
247
|
"resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
|
|
@@ -205,6 +254,10 @@
|
|
|
205
254
|
|
|
206
255
|
"seroval-plugins": ["seroval-plugins@1.5.2", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg=="],
|
|
207
256
|
|
|
257
|
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
258
|
+
|
|
259
|
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
260
|
+
|
|
208
261
|
"solid-js": ["solid-js@1.9.12", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw=="],
|
|
209
262
|
|
|
210
263
|
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
@@ -213,16 +266,26 @@
|
|
|
213
266
|
|
|
214
267
|
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
|
215
268
|
|
|
269
|
+
"toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="],
|
|
270
|
+
|
|
216
271
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
217
272
|
|
|
218
273
|
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
|
|
219
274
|
|
|
275
|
+
"uuid": ["uuid@13.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw=="],
|
|
276
|
+
|
|
220
277
|
"web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="],
|
|
221
278
|
|
|
279
|
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
280
|
+
|
|
222
281
|
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
|
223
282
|
|
|
283
|
+
"yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="],
|
|
284
|
+
|
|
224
285
|
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
|
|
225
286
|
|
|
287
|
+
"zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
|
|
288
|
+
|
|
226
289
|
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
|
227
290
|
|
|
228
291
|
"parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
package/docs/configuration.md
CHANGED
|
@@ -13,6 +13,7 @@ Add `opencode-vim` to the `plugin` array in your OpenCode `tui.jsonc` file:
|
|
|
13
13
|
[
|
|
14
14
|
"./plugin/opencode-vim",
|
|
15
15
|
{
|
|
16
|
+
"autoUpdate": true,
|
|
16
17
|
"vim": {
|
|
17
18
|
"defaultMode": "insert"
|
|
18
19
|
}
|
|
@@ -33,6 +34,7 @@ If your plugin is installed somewhere else, change the plugin path to match your
|
|
|
33
34
|
[
|
|
34
35
|
"./plugin/opencode-vim",
|
|
35
36
|
{
|
|
37
|
+
"autoUpdate": true,
|
|
36
38
|
"vim": {
|
|
37
39
|
"defaultMode": "insert",
|
|
38
40
|
"keymapTimeout": 500,
|
|
@@ -67,6 +69,22 @@ If your plugin is installed somewhere else, change the plugin path to match your
|
|
|
67
69
|
|
|
68
70
|
## Options
|
|
69
71
|
|
|
72
|
+
### `autoUpdate`
|
|
73
|
+
|
|
74
|
+
Updates `opencode-vim` automatically when a newer npm version is available.
|
|
75
|
+
|
|
76
|
+
Default:
|
|
77
|
+
|
|
78
|
+
```jsonc
|
|
79
|
+
"autoUpdate": true
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
|
|
84
|
+
```jsonc
|
|
85
|
+
"autoUpdate": false
|
|
86
|
+
```
|
|
87
|
+
|
|
70
88
|
### `defaultMode`
|
|
71
89
|
|
|
72
90
|
The mode the prompt starts in.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-vim",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"exports": {
|
|
5
5
|
"./tui": {
|
|
6
6
|
"import": "./tui.tsx"
|
|
@@ -11,5 +11,8 @@
|
|
|
11
11
|
"@opentui/solid": "^0.2.1",
|
|
12
12
|
"solid-js": "^1.9.12",
|
|
13
13
|
"@vimee/core": "^0.3.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@opencode-ai/plugin": "1.14.30"
|
|
14
17
|
}
|
|
15
18
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
import type { KeyEvent, ParsedKey } from "@opentui/core"
|
|
2
3
|
import { useKeyboard } from "@opentui/solid"
|
|
3
4
|
import { onCleanup } from "solid-js"
|
|
4
5
|
import type { PromptContext, PromptModule } from "../../prompt/types"
|
|
5
|
-
import { applyVimCursorStyle } from "./actions"
|
|
6
|
+
import { applyVimCursorStyle, focusedInput } from "./actions"
|
|
6
7
|
import type { VimConfig } from "./config"
|
|
7
8
|
import { createVimConfig } from "./config"
|
|
8
9
|
import { keyNotation } from "./keys"
|
|
@@ -63,6 +64,19 @@ function VimKeyboard(props: { ctx: PromptContext; config: VimConfig; state: Retu
|
|
|
63
64
|
return
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
if (passThroughKey(event, key, props.state.mode())) {
|
|
68
|
+
preparePassThroughKey(props.ctx, key, props.state.mode())
|
|
69
|
+
syncCursorStyle(true)
|
|
70
|
+
props.ctx.requestRender()
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (sendNavigationKey(event, props.ctx, key, props.state.mode())) {
|
|
75
|
+
syncCursorStyle(true)
|
|
76
|
+
props.ctx.requestRender()
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
66
80
|
const consumed = vimee.handle(event, key, props.ctx)
|
|
67
81
|
if (consumed) {
|
|
68
82
|
event.preventDefault()
|
|
@@ -94,3 +108,54 @@ function readablePending(sequence: string) {
|
|
|
94
108
|
if (!sequence) return undefined
|
|
95
109
|
return sequence.replaceAll("><", " ")
|
|
96
110
|
}
|
|
111
|
+
|
|
112
|
+
function passThroughKey(event: KeyEvent, key: string, mode: string) {
|
|
113
|
+
if (mode !== "normal") return false
|
|
114
|
+
return event.super === true || isArrowKey(key) || key === "<CR>"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function preparePassThroughKey(ctx: PromptContext, key: string, mode: string) {
|
|
118
|
+
if (mode !== "normal" || key !== "<CR>") return
|
|
119
|
+
const input = focusedInput(ctx)
|
|
120
|
+
if (!input?.plainText || input.cursorOffset === undefined) return
|
|
121
|
+
input.cursorOffset = Math.min(input.cursorOffset + 1, input.plainText.length)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function sendNavigationKey(event: KeyEvent, ctx: PromptContext, key: string, mode: string) {
|
|
125
|
+
if (mode !== "normal") return false
|
|
126
|
+
const forwarded = navigationKey(key)
|
|
127
|
+
if (!forwarded) return false
|
|
128
|
+
|
|
129
|
+
event.preventDefault()
|
|
130
|
+
event.stopPropagation()
|
|
131
|
+
ctx.api.renderer.keyInput.processParsedKey(forwarded)
|
|
132
|
+
return true
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function navigationKey(key: string): ParsedKey | undefined {
|
|
136
|
+
if (key === "h") return arrowKey("left", "\u001B[D")
|
|
137
|
+
if (key === "j") return arrowKey("down", "\u001B[B")
|
|
138
|
+
if (key === "k") return arrowKey("up", "\u001B[A")
|
|
139
|
+
if (key === "l") return arrowKey("right", "\u001B[C")
|
|
140
|
+
return undefined
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function isArrowKey(key: string) {
|
|
144
|
+
return key === "<Left>" || key === "<Down>" || key === "<Up>" || key === "<Right>"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function arrowKey(name: string, sequence: string): ParsedKey {
|
|
148
|
+
return {
|
|
149
|
+
name,
|
|
150
|
+
ctrl: false,
|
|
151
|
+
meta: false,
|
|
152
|
+
shift: false,
|
|
153
|
+
option: false,
|
|
154
|
+
sequence,
|
|
155
|
+
number: false,
|
|
156
|
+
raw: sequence,
|
|
157
|
+
eventType: "press",
|
|
158
|
+
source: "raw",
|
|
159
|
+
super: true,
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/modules/vim/vimee.ts
CHANGED
|
@@ -149,7 +149,7 @@ export function createVimeeAdapter(state: VimState, config: VimConfig, log: VimL
|
|
|
149
149
|
|
|
150
150
|
function handleInsertMode(event: KeyEvent, key: string, ctx: PromptContext, map: PromptMap, cursor: CursorPosition, offset: number) {
|
|
151
151
|
if (key === "Escape") {
|
|
152
|
-
cancelPendingInsert(ctx, offset)
|
|
152
|
+
cancelPendingInsert(ctx, offset, false)
|
|
153
153
|
sync(map, cursor)
|
|
154
154
|
const result = processKeystroke(key, vim, buffer, event.ctrl, false)
|
|
155
155
|
vim = result.newCtx
|
|
@@ -221,12 +221,12 @@ export function createVimeeAdapter(state: VimState, config: VimConfig, log: VimL
|
|
|
221
221
|
}, config.keymapTimeout)
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
function cancelPendingInsert(ctx: PromptContext, offset?: number) {
|
|
224
|
+
function cancelPendingInsert(ctx: PromptContext, offset?: number, flush = true) {
|
|
225
225
|
if (!keybinds?.isPending()) return
|
|
226
226
|
if (timer) clearTimeout(timer)
|
|
227
227
|
timer = undefined
|
|
228
228
|
keybinds.cancel()
|
|
229
|
-
flushPendingInsert(ctx, pendingInsert, offset)
|
|
229
|
+
if (flush) flushPendingInsert(ctx, pendingInsert, offset)
|
|
230
230
|
pendingInsert = ""
|
|
231
231
|
state.setPending("")
|
|
232
232
|
}
|
package/src/plugin.tsx
CHANGED
|
@@ -4,8 +4,24 @@ import { PromptRoot } from "./prompt/root"
|
|
|
4
4
|
import type { PromptModule } from "./prompt/types"
|
|
5
5
|
import { createVimModule } from "./modules/vim"
|
|
6
6
|
import { createSnippetsModule } from "./modules/snippets"
|
|
7
|
+
import { checkAutoUpdate } from "./update"
|
|
8
|
+
|
|
9
|
+
const tui: TuiPlugin = async (api, options, meta) => {
|
|
10
|
+
if (readAutoUpdate(options)) {
|
|
11
|
+
let timer: Timer | undefined
|
|
12
|
+
api.lifecycle.onDispose(() => {
|
|
13
|
+
if (timer) clearTimeout(timer)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
void checkAutoUpdate(meta, api.lifecycle.signal).then((result) => {
|
|
17
|
+
if (!result.updated) return
|
|
18
|
+
|
|
19
|
+
timer = setTimeout(() => {
|
|
20
|
+
api.ui.toast({ variant: "info", message: "Updating opencode-vim. Restart OpenCode to finish." })
|
|
21
|
+
}, 5000)
|
|
22
|
+
}).catch(() => {})
|
|
23
|
+
}
|
|
7
24
|
|
|
8
|
-
const tui: TuiPlugin = async (api, options) => {
|
|
9
25
|
const moduleCache = new Map<string, PromptModule[]>()
|
|
10
26
|
const createModules = (key: string) => {
|
|
11
27
|
const cached = moduleCache.get(key)
|
|
@@ -43,6 +59,12 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
43
59
|
})
|
|
44
60
|
}
|
|
45
61
|
|
|
62
|
+
function readAutoUpdate(options: unknown) {
|
|
63
|
+
if (!options || typeof options !== "object") return true
|
|
64
|
+
const value = (options as { autoUpdate?: unknown }).autoUpdate
|
|
65
|
+
return typeof value === "boolean" ? value : true
|
|
66
|
+
}
|
|
67
|
+
|
|
46
68
|
function hasSnippetsPlugin(api: TuiPluginApi) {
|
|
47
69
|
return configHasSnippets(api.state.config.plugin) || configHasSnippets(api.tuiConfig.plugin) || api.plugins.list().some(pluginHasSnippets)
|
|
48
70
|
}
|
package/src/update.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises"
|
|
2
|
+
import { dirname, join } from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
import type { TuiPluginMeta } from "@opencode-ai/plugin/tui"
|
|
5
|
+
|
|
6
|
+
type PackageJson = {
|
|
7
|
+
name?: string
|
|
8
|
+
version?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type UpdateResult =
|
|
12
|
+
| { updated: true; name: string; current: string; latest: string }
|
|
13
|
+
| { updated: false; error: "remove_failed"; name: string; current: string; latest: string }
|
|
14
|
+
| { updated: false }
|
|
15
|
+
|
|
16
|
+
export async function checkAutoUpdate(meta: TuiPluginMeta, signal: AbortSignal): Promise<UpdateResult> {
|
|
17
|
+
if (meta.source !== "npm") return { updated: false }
|
|
18
|
+
|
|
19
|
+
const packageDir = await findPackageDir()
|
|
20
|
+
if (!packageDir) return { updated: false }
|
|
21
|
+
|
|
22
|
+
const pkg = await readPackageJson(join(packageDir, "package.json"))
|
|
23
|
+
if (!pkg.name || !pkg.version) return { updated: false }
|
|
24
|
+
|
|
25
|
+
const latest = await fetchLatestVersion(pkg.name, signal)
|
|
26
|
+
if (!latest || !isVersionNewer(latest, pkg.version)) return { updated: false }
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await rm(packageDir, { recursive: true, force: true })
|
|
30
|
+
} catch {
|
|
31
|
+
return { updated: false, error: "remove_failed", name: pkg.name, current: pkg.version, latest }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { updated: true, name: pkg.name, current: pkg.version, latest }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function findPackageDir() {
|
|
38
|
+
let dir = dirname(fileURLToPath(import.meta.url))
|
|
39
|
+
for (;;) {
|
|
40
|
+
const packagePath = join(dir, "package.json")
|
|
41
|
+
const pkg = await readPackageJson(packagePath)
|
|
42
|
+
if (pkg?.name === "opencode-vim") return dir
|
|
43
|
+
|
|
44
|
+
const parent = dirname(dir)
|
|
45
|
+
if (parent === dir) return undefined
|
|
46
|
+
dir = parent
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function readPackageJson(path: string): Promise<PackageJson | undefined> {
|
|
51
|
+
try {
|
|
52
|
+
const file = Bun.file(path)
|
|
53
|
+
if (!(await file.exists())) return undefined
|
|
54
|
+
const data = await file.json()
|
|
55
|
+
return data && typeof data === "object" ? (data as PackageJson) : undefined
|
|
56
|
+
} catch {
|
|
57
|
+
return undefined
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function fetchLatestVersion(name: string, signal: AbortSignal) {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`, { signal })
|
|
64
|
+
if (!response.ok) return undefined
|
|
65
|
+
const data = await response.json()
|
|
66
|
+
return data && typeof data === "object" && typeof data.version === "string" ? data.version : undefined
|
|
67
|
+
} catch {
|
|
68
|
+
return undefined
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isVersionNewer(latest: string, current: string) {
|
|
73
|
+
const next = parseVersion(latest)
|
|
74
|
+
const prev = parseVersion(current)
|
|
75
|
+
if (!next || !prev) return false
|
|
76
|
+
|
|
77
|
+
for (let i = 0; i < 3; i++) {
|
|
78
|
+
if (next.parts[i] !== prev.parts[i]) return next.parts[i] > prev.parts[i]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!next.pre.length && prev.pre.length) return true
|
|
82
|
+
if (next.pre.length && !prev.pre.length) return false
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < Math.max(next.pre.length, prev.pre.length); i++) {
|
|
85
|
+
const a = next.pre[i]
|
|
86
|
+
const b = prev.pre[i]
|
|
87
|
+
if (a === undefined) return false
|
|
88
|
+
if (b === undefined) return true
|
|
89
|
+
if (a === b) continue
|
|
90
|
+
|
|
91
|
+
const aNumber = /^\d+$/.test(a) ? Number(a) : undefined
|
|
92
|
+
const bNumber = /^\d+$/.test(b) ? Number(b) : undefined
|
|
93
|
+
if (aNumber !== undefined && bNumber !== undefined) return aNumber > bNumber
|
|
94
|
+
if (aNumber !== undefined) return false
|
|
95
|
+
if (bNumber !== undefined) return true
|
|
96
|
+
return a > b
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function parseVersion(version: string) {
|
|
103
|
+
const match = version.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.+)?$/)
|
|
104
|
+
if (!match) return undefined
|
|
105
|
+
return {
|
|
106
|
+
parts: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
107
|
+
pre: match[4]?.split(".") ?? [],
|
|
108
|
+
}
|
|
109
|
+
}
|