opencode-snippets 1.8.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -5
- package/dist/src/config.js +1 -1
- package/dist/src/expander.d.ts.map +1 -1
- package/dist/src/expander.js +65 -75
- package/dist/src/expander.js.map +1 -1
- package/dist/src/tui-search.d.ts +10 -0
- package/dist/src/tui-search.d.ts.map +1 -0
- package/dist/src/tui-search.js +79 -0
- package/dist/src/tui-search.js.map +1 -0
- package/dist/src/tui-trigger.d.ts +12 -0
- package/dist/src/tui-trigger.d.ts.map +1 -0
- package/dist/src/tui-trigger.js +46 -0
- package/dist/src/tui-trigger.js.map +1 -0
- package/dist/tui.d.ts +6 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.jsx +501 -0
- package/dist/tui.jsx.map +1 -0
- package/package.json +35 -4
- package/skill/snippets/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,8 @@ You could also make "current git status and staged changes" a shell-enabled snip
|
|
|
64
64
|
#testing-requirements
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
https://github.com/user-attachments/assets/76975a9e-e326-431e-8be5-39a9f6572851
|
|
68
|
+
|
|
67
69
|
`~/.config/opencode/snippet/full-review.md`:
|
|
68
70
|
```markdown
|
|
69
71
|
#code-standards
|
|
@@ -73,11 +75,26 @@ You could also make "current git status and staged changes" a shell-enabled snip
|
|
|
73
75
|
|
|
74
76
|
Compose base snippets into higher-level ones. Type `#full-review` to inject all standards at once, keeping each concern in its own maintainable file.
|
|
75
77
|
|
|
76
|
-
**The power:** Mix and match. Type `#tdd #careful` for test-driven development with extra caution.
|
|
78
|
+
**The power:** Mix and match. Type `#tdd #careful` for test-driven development with extra caution.
|
|
79
|
+
Build `/commit #conventional-commits #project-context` for context-aware commits. Create layered prompts from small, reusable pieces.
|
|
80
|
+
<img width="708" height="185" alt="image" src="https://github.com/user-attachments/assets/2c537c4b-6afe-4bb1-9fb4-484034f9ce8b" />
|
|
77
81
|
|
|
78
82
|
## Installation
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
```bash
|
|
85
|
+
opencode plug add opencode-snippets
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
This installs the package and wires up both the server plugin and the TUI plugin for autocompletion automatically.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
<details>
|
|
93
|
+
<summary>Manual Installation (or for AI agents)</summary>
|
|
94
|
+
|
|
95
|
+
If you edit config manually, the configurations are separate, so you need both entries yourself.
|
|
96
|
+
|
|
97
|
+
Required: add the package to your `opencode.json` plugins array:
|
|
81
98
|
|
|
82
99
|
```json
|
|
83
100
|
{
|
|
@@ -87,6 +104,45 @@ Add to your `opencode.json` plugins array:
|
|
|
87
104
|
}
|
|
88
105
|
```
|
|
89
106
|
|
|
107
|
+
Strongly recommended: add the same package to `tui.json` too:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"plugin": [
|
|
112
|
+
"opencode-snippets"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
<details>
|
|
118
|
+
<summary>Local Development</summary>
|
|
119
|
+
|
|
120
|
+
For local development with a `file:///` plugin path, point OpenCode at the package directory:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"plugins": [
|
|
125
|
+
"file:///D:/projects/opencode-snippets"
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Strongly recommended for local TUI testing too, wire the same package directory into `tui.json`:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"plugin": [
|
|
135
|
+
"file:///D:/projects/opencode-snippets"
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Using the directory lets OpenCode read the package manifest and discover both targets.
|
|
141
|
+
|
|
142
|
+
</details>
|
|
143
|
+
|
|
144
|
+
</details>
|
|
145
|
+
|
|
90
146
|
## Quick Start
|
|
91
147
|
|
|
92
148
|
**1. Create your global snippets directory:**
|
|
@@ -102,13 +158,13 @@ mkdir -p ~/.config/opencode/snippet
|
|
|
102
158
|
---
|
|
103
159
|
aliases: safe
|
|
104
160
|
---
|
|
105
|
-
Think step by step. Double-check your work before
|
|
161
|
+
Think step by step. Double-check your work before committing changes.
|
|
106
162
|
Ask clarifying questions if anything is ambiguous.
|
|
107
163
|
```
|
|
108
164
|
|
|
109
165
|
**3. Use it anywhere:**
|
|
110
166
|
|
|
111
|
-
https://github.com/user-attachments/assets/
|
|
167
|
+
https://github.com/user-attachments/assets/ebb303b5-d41b-4d87-8f08-eb1d730db5c8
|
|
112
168
|
|
|
113
169
|
## Where to Store Snippets
|
|
114
170
|
|
|
@@ -359,7 +415,7 @@ A default config file is created automatically on first run.
|
|
|
359
415
|
|
|
360
416
|
```jsonc
|
|
361
417
|
{
|
|
362
|
-
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/
|
|
418
|
+
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/v2.0.0/schema/config.schema.json",
|
|
363
419
|
"logging": {
|
|
364
420
|
"debug": false // Enable debug logging (logs: ~/.config/opencode/logs/snippets/daily/)
|
|
365
421
|
},
|
package/dist/src/config.js
CHANGED
|
@@ -22,7 +22,7 @@ const DEFAULT_CONFIG = {
|
|
|
22
22
|
*/
|
|
23
23
|
const DEFAULT_CONFIG_CONTENT = `{
|
|
24
24
|
// JSON Schema for editor autocompletion
|
|
25
|
-
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/
|
|
25
|
+
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/v2.0.0/schema/config.schema.json",
|
|
26
26
|
|
|
27
27
|
// Logging settings
|
|
28
28
|
"logging": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expander.d.ts","sourceRoot":"","sources":["../../src/expander.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYzF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAClD;
|
|
1
|
+
{"version":3,"file":"expander.d.ts","sourceRoot":"","sources":["../../src/expander.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYzF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAClD;AA+GD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,oBAAoB,GAAG,IAAI,CAoF7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,eAAe,EACzB,eAAe,sBAA4B,EAC3C,OAAO,GAAE,aAAkB,GAC1B,eAAe,CAgBjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAmB/D"}
|
package/dist/src/expander.js
CHANGED
|
@@ -4,6 +4,61 @@ import { logger } from "./logger.js";
|
|
|
4
4
|
* Maximum number of times a snippet can be expanded to prevent infinite loops
|
|
5
5
|
*/
|
|
6
6
|
const MAX_EXPANSION_COUNT = 15;
|
|
7
|
+
function addBlock(collector, type, snippetName, content, onInjectBlock) {
|
|
8
|
+
if (!content)
|
|
9
|
+
return;
|
|
10
|
+
const key = `${type}\u0000${snippetName.toLowerCase()}\u0000${content}`;
|
|
11
|
+
if (collector.seen.has(key))
|
|
12
|
+
return;
|
|
13
|
+
collector.seen.add(key);
|
|
14
|
+
collector[type].push(content);
|
|
15
|
+
if (type === "inject") {
|
|
16
|
+
onInjectBlock?.({ snippetName, content });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function expandText(text, registry, expansionCounts, collector, options) {
|
|
20
|
+
const { onInjectBlock } = options;
|
|
21
|
+
let expanded = text;
|
|
22
|
+
let hasChanges = true;
|
|
23
|
+
while (hasChanges) {
|
|
24
|
+
const previous = expanded;
|
|
25
|
+
let loopDetected = false;
|
|
26
|
+
PATTERNS.HASHTAG.lastIndex = 0;
|
|
27
|
+
expanded = expanded.replace(PATTERNS.HASHTAG, (match, name) => {
|
|
28
|
+
const snippet = registry.get(name.toLowerCase());
|
|
29
|
+
if (snippet === undefined) {
|
|
30
|
+
return match;
|
|
31
|
+
}
|
|
32
|
+
const key = snippet.name.toLowerCase();
|
|
33
|
+
const count = (expansionCounts.get(key) || 0) + 1;
|
|
34
|
+
if (count > MAX_EXPANSION_COUNT) {
|
|
35
|
+
logger.warn(`Loop detected: snippet '#${key}' expanded ${count} times (max: ${MAX_EXPANSION_COUNT})`);
|
|
36
|
+
loopDetected = true;
|
|
37
|
+
return match;
|
|
38
|
+
}
|
|
39
|
+
expansionCounts.set(key, count);
|
|
40
|
+
const parsed = parseSnippetBlocks(snippet.content, options);
|
|
41
|
+
if (parsed === null) {
|
|
42
|
+
logger.warn(`Failed to parse snippet '${key}', leaving hashtag unchanged`);
|
|
43
|
+
return match;
|
|
44
|
+
}
|
|
45
|
+
// User requirement: inline snippet text should replace every hashtag occurrence,
|
|
46
|
+
// but prepend/append/inject side effects should only be inserted once per snippet block.
|
|
47
|
+
for (const block of parsed.prepend) {
|
|
48
|
+
addBlock(collector, "prepend", snippet.name, expandText(block, registry, expansionCounts, collector, options), onInjectBlock);
|
|
49
|
+
}
|
|
50
|
+
for (const block of parsed.append) {
|
|
51
|
+
addBlock(collector, "append", snippet.name, expandText(block, registry, expansionCounts, collector, options), onInjectBlock);
|
|
52
|
+
}
|
|
53
|
+
for (const block of parsed.inject) {
|
|
54
|
+
addBlock(collector, "inject", snippet.name, expandText(block, registry, expansionCounts, collector, options), onInjectBlock);
|
|
55
|
+
}
|
|
56
|
+
return expandText(parsed.inline, registry, expansionCounts, collector, options);
|
|
57
|
+
});
|
|
58
|
+
hasChanges = expanded !== previous && !loopDetected;
|
|
59
|
+
}
|
|
60
|
+
return expanded;
|
|
61
|
+
}
|
|
7
62
|
/**
|
|
8
63
|
* Parses snippet content to extract inline text and prepend/append/inject blocks
|
|
9
64
|
*
|
|
@@ -113,83 +168,18 @@ export function parseSnippetBlocks(content, options = {}) {
|
|
|
113
168
|
* @returns ExpansionResult with text and collected blocks
|
|
114
169
|
*/
|
|
115
170
|
export function expandHashtags(text, registry, expansionCounts = new Map(), options = {}) {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
while (hasChanges) {
|
|
124
|
-
const previous = expanded;
|
|
125
|
-
let loopDetected = false;
|
|
126
|
-
// Reset regex state (global flag requires this)
|
|
127
|
-
PATTERNS.HASHTAG.lastIndex = 0;
|
|
128
|
-
// We need to collect blocks during replacement, so we track them here
|
|
129
|
-
const roundPrepend = [];
|
|
130
|
-
const roundAppend = [];
|
|
131
|
-
const roundInject = [];
|
|
132
|
-
expanded = expanded.replace(PATTERNS.HASHTAG, (match, name) => {
|
|
133
|
-
const key = name.toLowerCase();
|
|
134
|
-
const snippet = registry.get(key);
|
|
135
|
-
if (snippet === undefined) {
|
|
136
|
-
// Unknown snippet - leave as-is
|
|
137
|
-
return match;
|
|
138
|
-
}
|
|
139
|
-
// Track expansion count to prevent infinite loops
|
|
140
|
-
const count = (expansionCounts.get(key) || 0) + 1;
|
|
141
|
-
if (count > MAX_EXPANSION_COUNT) {
|
|
142
|
-
// Loop detected! Leave the hashtag as-is and stop expanding
|
|
143
|
-
logger.warn(`Loop detected: snippet '#${key}' expanded ${count} times (max: ${MAX_EXPANSION_COUNT})`);
|
|
144
|
-
loopDetected = true;
|
|
145
|
-
return match; // Leave as-is instead of error message
|
|
146
|
-
}
|
|
147
|
-
expansionCounts.set(key, count);
|
|
148
|
-
// Parse the snippet content for blocks
|
|
149
|
-
const parsed = parseSnippetBlocks(snippet.content, options);
|
|
150
|
-
if (parsed === null) {
|
|
151
|
-
// Parse error - leave hashtag unchanged
|
|
152
|
-
logger.warn(`Failed to parse snippet '${key}', leaving hashtag unchanged`);
|
|
153
|
-
return match;
|
|
154
|
-
}
|
|
155
|
-
// Recursively expand hashtags in prepend/append/inject blocks
|
|
156
|
-
const targets = [
|
|
157
|
-
[parsed.prepend, roundPrepend],
|
|
158
|
-
[parsed.append, roundAppend],
|
|
159
|
-
[parsed.inject, roundInject],
|
|
160
|
-
];
|
|
161
|
-
for (const [blocks, dest] of targets) {
|
|
162
|
-
for (const block of blocks) {
|
|
163
|
-
const r = expandHashtags(block, registry, expansionCounts, options);
|
|
164
|
-
dest.push(r.text);
|
|
165
|
-
roundPrepend.push(...r.prepend);
|
|
166
|
-
roundAppend.push(...r.append);
|
|
167
|
-
roundInject.push(...r.inject);
|
|
168
|
-
if (dest === roundInject && onInjectBlock) {
|
|
169
|
-
onInjectBlock({ snippetName: snippet.name, content: r.text });
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Recursively expand any hashtags in the inline content
|
|
174
|
-
const nestedResult = expandHashtags(parsed.inline, registry, expansionCounts, options);
|
|
175
|
-
// Collect blocks from nested expansion
|
|
176
|
-
roundPrepend.push(...nestedResult.prepend);
|
|
177
|
-
roundAppend.push(...nestedResult.append);
|
|
178
|
-
roundInject.push(...nestedResult.inject);
|
|
179
|
-
return nestedResult.text;
|
|
180
|
-
});
|
|
181
|
-
// Add this round's blocks to collected blocks
|
|
182
|
-
collectedPrepend.push(...roundPrepend);
|
|
183
|
-
collectedAppend.push(...roundAppend);
|
|
184
|
-
collectedInject.push(...roundInject);
|
|
185
|
-
// Only continue if the text actually changed AND no loop was detected
|
|
186
|
-
hasChanges = expanded !== previous && !loopDetected;
|
|
187
|
-
}
|
|
171
|
+
const collector = {
|
|
172
|
+
prepend: [],
|
|
173
|
+
append: [],
|
|
174
|
+
inject: [],
|
|
175
|
+
seen: new Set(),
|
|
176
|
+
};
|
|
177
|
+
const expanded = expandText(text, registry, expansionCounts, collector, options);
|
|
188
178
|
return {
|
|
189
179
|
text: expanded,
|
|
190
|
-
prepend:
|
|
191
|
-
append:
|
|
192
|
-
inject:
|
|
180
|
+
prepend: collector.prepend,
|
|
181
|
+
append: collector.append,
|
|
182
|
+
inject: collector.inject,
|
|
193
183
|
};
|
|
194
184
|
}
|
|
195
185
|
/**
|
package/dist/src/expander.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expander.js","sourceRoot":"","sources":["../../src/expander.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC;;GAEG;AACH,MAAM,mBAAmB,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"expander.js","sourceRoot":"","sources":["../../src/expander.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SnippetInfo } from "./types.js";
|
|
2
|
+
export interface HighlightPart {
|
|
3
|
+
text: string;
|
|
4
|
+
match: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function filterSnippets(snippets: SnippetInfo[], query: string): SnippetInfo[];
|
|
7
|
+
export declare function matchedAliases(snippet: SnippetInfo, query: string): string[];
|
|
8
|
+
export declare function snippetDescription(snippet: SnippetInfo): string;
|
|
9
|
+
export declare function highlightMatches(input: string, query: string): HighlightPart[];
|
|
10
|
+
//# sourceMappingURL=tui-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-search.d.ts","sourceRoot":"","sources":["../../src/tui-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AA0BD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAgBpF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAK5E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE/D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CA0B9E"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function scoreSnippet(snippet, query) {
|
|
2
|
+
if (!query)
|
|
3
|
+
return 0;
|
|
4
|
+
const needle = query.toLowerCase();
|
|
5
|
+
const name = snippet.name.toLowerCase();
|
|
6
|
+
const aliases = snippet.aliases.map((alias) => alias.toLowerCase());
|
|
7
|
+
const description = (snippet.description || "").toLowerCase();
|
|
8
|
+
if (name === needle)
|
|
9
|
+
return 0;
|
|
10
|
+
if (aliases.includes(needle))
|
|
11
|
+
return 1;
|
|
12
|
+
if (name.startsWith(needle))
|
|
13
|
+
return 2;
|
|
14
|
+
if (aliases.some((alias) => alias.startsWith(needle)))
|
|
15
|
+
return 3;
|
|
16
|
+
if (name.includes(needle))
|
|
17
|
+
return 4;
|
|
18
|
+
if (aliases.some((alias) => alias.includes(needle)))
|
|
19
|
+
return 5;
|
|
20
|
+
if (description.startsWith(needle))
|
|
21
|
+
return 6;
|
|
22
|
+
if (description.includes(needle))
|
|
23
|
+
return 7;
|
|
24
|
+
return Number.POSITIVE_INFINITY;
|
|
25
|
+
}
|
|
26
|
+
function sourceRank(snippet) {
|
|
27
|
+
return snippet.source === "project" ? 0 : 1;
|
|
28
|
+
}
|
|
29
|
+
export function filterSnippets(snippets, query) {
|
|
30
|
+
return [...snippets]
|
|
31
|
+
.map((snippet) => ({
|
|
32
|
+
snippet,
|
|
33
|
+
score: scoreSnippet(snippet, query.trim()),
|
|
34
|
+
}))
|
|
35
|
+
.filter((item) => Number.isFinite(item.score))
|
|
36
|
+
.sort((a, b) => {
|
|
37
|
+
if (a.score !== b.score)
|
|
38
|
+
return a.score - b.score;
|
|
39
|
+
const sourceDiff = sourceRank(a.snippet) - sourceRank(b.snippet);
|
|
40
|
+
if (sourceDiff !== 0)
|
|
41
|
+
return sourceDiff;
|
|
42
|
+
return a.snippet.name.localeCompare(b.snippet.name);
|
|
43
|
+
})
|
|
44
|
+
.map((item) => item.snippet);
|
|
45
|
+
}
|
|
46
|
+
export function matchedAliases(snippet, query) {
|
|
47
|
+
const needle = query.trim().toLowerCase();
|
|
48
|
+
if (!needle)
|
|
49
|
+
return [];
|
|
50
|
+
return snippet.aliases.filter((alias) => alias.toLowerCase().includes(needle));
|
|
51
|
+
}
|
|
52
|
+
export function snippetDescription(snippet) {
|
|
53
|
+
return (snippet.description || snippet.content).replace(/\s+/g, " ").trim();
|
|
54
|
+
}
|
|
55
|
+
export function highlightMatches(input, query) {
|
|
56
|
+
const needle = query.trim().toLowerCase();
|
|
57
|
+
if (!needle)
|
|
58
|
+
return [{ text: input, match: false }];
|
|
59
|
+
const haystack = input.toLowerCase();
|
|
60
|
+
const parts = [];
|
|
61
|
+
let start = 0;
|
|
62
|
+
while (start < input.length) {
|
|
63
|
+
const index = haystack.indexOf(needle, start);
|
|
64
|
+
if (index === -1) {
|
|
65
|
+
parts.push({ text: input.slice(start), match: false });
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
if (index > start) {
|
|
69
|
+
parts.push({ text: input.slice(start, index), match: false });
|
|
70
|
+
}
|
|
71
|
+
const end = index + needle.length;
|
|
72
|
+
parts.push({ text: input.slice(index, end), match: true });
|
|
73
|
+
start = end;
|
|
74
|
+
}
|
|
75
|
+
if (parts.length === 0)
|
|
76
|
+
return [{ text: input, match: false }];
|
|
77
|
+
return parts;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=tui-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-search.js","sourceRoot":"","sources":["../../src/tui-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface HashtagTriggerMatch {
|
|
2
|
+
start: number;
|
|
3
|
+
end: number;
|
|
4
|
+
query: string;
|
|
5
|
+
token: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function findTrailingHashtagTrigger(input: string): HashtagTriggerMatch | undefined;
|
|
8
|
+
export declare function replaceTrailingHashtag(input: string, name: string): string | undefined;
|
|
9
|
+
export declare function insertSnippetTag(input: string, name: string): string;
|
|
10
|
+
export declare function insertSnippetTrigger(input: string): string;
|
|
11
|
+
export declare function truncateSnippetPreview(input: string, max?: number): string;
|
|
12
|
+
//# sourceMappingURL=tui-trigger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-trigger.d.ts","sourceRoot":"","sources":["../../src/tui-trigger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAazF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKtF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAKvE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const HASHTAG_TRIGGER = /(^|\s)#([^\s#]*)$/;
|
|
2
|
+
export function findTrailingHashtagTrigger(input) {
|
|
3
|
+
const hit = input.match(HASHTAG_TRIGGER);
|
|
4
|
+
if (!hit)
|
|
5
|
+
return;
|
|
6
|
+
const query = hit[2] || "";
|
|
7
|
+
const token = `#${query}`;
|
|
8
|
+
return {
|
|
9
|
+
start: input.length - token.length,
|
|
10
|
+
end: input.length,
|
|
11
|
+
query,
|
|
12
|
+
token,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function replaceTrailingHashtag(input, name) {
|
|
16
|
+
const match = findTrailingHashtagTrigger(input);
|
|
17
|
+
if (!match)
|
|
18
|
+
return;
|
|
19
|
+
return `${input.slice(0, match.start)}#${name} `;
|
|
20
|
+
}
|
|
21
|
+
export function insertSnippetTag(input, name) {
|
|
22
|
+
const replaced = replaceTrailingHashtag(input, name);
|
|
23
|
+
if (replaced)
|
|
24
|
+
return replaced;
|
|
25
|
+
if (!input)
|
|
26
|
+
return `#${name} `;
|
|
27
|
+
if (/\s$/.test(input))
|
|
28
|
+
return `${input}#${name} `;
|
|
29
|
+
return `${input} #${name} `;
|
|
30
|
+
}
|
|
31
|
+
export function insertSnippetTrigger(input) {
|
|
32
|
+
if (findTrailingHashtagTrigger(input))
|
|
33
|
+
return input;
|
|
34
|
+
if (!input)
|
|
35
|
+
return "#";
|
|
36
|
+
if (/\s$/.test(input))
|
|
37
|
+
return `${input}#`;
|
|
38
|
+
return `${input} #`;
|
|
39
|
+
}
|
|
40
|
+
export function truncateSnippetPreview(input, max = 140) {
|
|
41
|
+
const text = input.replace(/\s+/g, " ").trim();
|
|
42
|
+
if (text.length <= max)
|
|
43
|
+
return text;
|
|
44
|
+
return `${text.slice(0, max - 3).trimEnd()}...`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=tui-trigger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-trigger.js","sourceRoot":"","sources":["../../src/tui-trigger.ts"],"names":[],"mappings":"AAOA,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,MAAM,UAAU,0BAA0B,CAAC,KAAa;IACtD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;IAE1B,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;QAClC,GAAG,EAAE,KAAK,CAAC,MAAM;QACjB,KAAK;QACL,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,IAAY;IAChE,MAAM,KAAK,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,IAAI,GAAG,CAAC;IAC/B,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC;IAElD,OAAO,GAAG,KAAK,KAAK,IAAI,GAAG,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,0BAA0B,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpD,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IACvB,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IAE1C,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,GAAG,GAAG,GAAG;IAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IAEpC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC;AAClD,CAAC"}
|
package/dist/tui.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../tui.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,eAAe,EAGhB,MAAM,yBAAyB,CAAC;AAypBjC,QAAA,MAAM,MAAM,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAG3C,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/tui.jsx
ADDED
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { RGBA } from "@opentui/core";
|
|
4
|
+
import { useKeyboard } from "@opentui/solid";
|
|
5
|
+
import { createEffect, createMemo, createResource, createSignal, Index, onCleanup, Show, } from "solid-js";
|
|
6
|
+
import { CONFIG } from "./src/constants.js";
|
|
7
|
+
import { ensureSnippetsDir, listSnippets, loadSnippets } from "./src/loader.js";
|
|
8
|
+
import { filterSnippets, highlightMatches, matchedAliases, snippetDescription, } from "./src/tui-search.js";
|
|
9
|
+
import { findTrailingHashtagTrigger, insertSnippetTag, insertSnippetTrigger, } from "./src/tui-trigger.js";
|
|
10
|
+
const id = "opencode-snippets:tui";
|
|
11
|
+
const PROMPT_SYNC_MS = 50;
|
|
12
|
+
const MENU_MAX_HEIGHT = 10;
|
|
13
|
+
const MOUSE_HOVER_SUPPRESS_MS = 150;
|
|
14
|
+
const HOME_PLACEHOLDERS = {
|
|
15
|
+
normal: [
|
|
16
|
+
"Fix a TODO in the codebase",
|
|
17
|
+
"What is the tech stack of this project?",
|
|
18
|
+
"Fix broken tests",
|
|
19
|
+
],
|
|
20
|
+
shell: ["ls -la", "git status", "pwd"],
|
|
21
|
+
};
|
|
22
|
+
const EMPTY_SNIPPET = `---
|
|
23
|
+
description: ""
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
`;
|
|
28
|
+
const INLINE_BORDER = {
|
|
29
|
+
border: ["left", "right"],
|
|
30
|
+
customBorderChars: {
|
|
31
|
+
topLeft: "",
|
|
32
|
+
bottomLeft: "",
|
|
33
|
+
vertical: "┃",
|
|
34
|
+
topRight: "",
|
|
35
|
+
bottomRight: "",
|
|
36
|
+
horizontal: " ",
|
|
37
|
+
bottomT: "",
|
|
38
|
+
topT: "",
|
|
39
|
+
cross: "",
|
|
40
|
+
leftT: "",
|
|
41
|
+
rightT: "",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
function sortSnippets(snippets) {
|
|
45
|
+
return [...snippets].sort((a, b) => {
|
|
46
|
+
if (a.source !== b.source) {
|
|
47
|
+
if (a.source === "project")
|
|
48
|
+
return -1;
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
return a.name.localeCompare(b.name);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function selectedText(theme) {
|
|
55
|
+
if (theme.background.a !== 0)
|
|
56
|
+
return theme.background;
|
|
57
|
+
const { r, g, b } = theme.primary;
|
|
58
|
+
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
59
|
+
return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255);
|
|
60
|
+
}
|
|
61
|
+
function renderHighlighted(text, query, fg) {
|
|
62
|
+
return highlightMatches(text, query).map((part) => {
|
|
63
|
+
if (!part.match)
|
|
64
|
+
return part.text;
|
|
65
|
+
return (<span style={{
|
|
66
|
+
fg,
|
|
67
|
+
underline: true,
|
|
68
|
+
}}>
|
|
69
|
+
{part.text}
|
|
70
|
+
</span>);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function normalizeSnippetName(input) {
|
|
74
|
+
return input
|
|
75
|
+
.trim()
|
|
76
|
+
.toLowerCase()
|
|
77
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
78
|
+
.replace(/-{2,}/g, "-")
|
|
79
|
+
.replace(/^-+|-+$/g, "");
|
|
80
|
+
}
|
|
81
|
+
async function ensureSnippetDraft(name, projectDir) {
|
|
82
|
+
const dir = await ensureSnippetsDir(projectDir);
|
|
83
|
+
const filePath = join(dir, `${name}${CONFIG.SNIPPET_EXTENSION}`);
|
|
84
|
+
if (!(await Bun.file(filePath).exists())) {
|
|
85
|
+
await Bun.write(filePath, EMPTY_SNIPPET);
|
|
86
|
+
}
|
|
87
|
+
return filePath;
|
|
88
|
+
}
|
|
89
|
+
async function openExternalEditor(api, filePath) {
|
|
90
|
+
const editor = Bun.env.VISUAL || Bun.env.EDITOR;
|
|
91
|
+
if (!editor)
|
|
92
|
+
return false;
|
|
93
|
+
api.renderer.suspend();
|
|
94
|
+
api.renderer.currentRenderBuffer.clear();
|
|
95
|
+
try {
|
|
96
|
+
const cmd = process.platform === "win32"
|
|
97
|
+
? ["cmd", "/c", `${editor} "${filePath.replace(/"/g, '\\"')}"`]
|
|
98
|
+
: [...editor.split(" "), filePath];
|
|
99
|
+
const proc = Bun.spawn(cmd, {
|
|
100
|
+
stdin: "inherit",
|
|
101
|
+
stdout: "inherit",
|
|
102
|
+
stderr: "inherit",
|
|
103
|
+
});
|
|
104
|
+
await proc.exited;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
api.renderer.currentRenderBuffer.clear();
|
|
109
|
+
api.renderer.resume();
|
|
110
|
+
api.renderer.requestRender();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function toPromptInfo(prompt, input) {
|
|
114
|
+
const current = prompt.current;
|
|
115
|
+
return {
|
|
116
|
+
input,
|
|
117
|
+
mode: current.mode,
|
|
118
|
+
parts: [...current.parts],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function setPromptInput(prompt, input) {
|
|
122
|
+
prompt.set(toPromptInfo(prompt, input));
|
|
123
|
+
}
|
|
124
|
+
async function getSnippets(api) {
|
|
125
|
+
const registry = await loadSnippets(api.state.path.directory);
|
|
126
|
+
return sortSnippets(listSnippets(registry));
|
|
127
|
+
}
|
|
128
|
+
function PromptWithSnippetAutocomplete(props) {
|
|
129
|
+
const [prompt, setPrompt] = createSignal();
|
|
130
|
+
const [dismissed, setDismissed] = createSignal();
|
|
131
|
+
const [selected, setSelected] = createSignal(0);
|
|
132
|
+
const [inputMode, setInputMode] = createSignal("keyboard");
|
|
133
|
+
const [ignoreMouseUntil, setIgnoreMouseUntil] = createSignal(0);
|
|
134
|
+
const [input, setInput] = createSignal("");
|
|
135
|
+
const [creating, setCreating] = createSignal(false);
|
|
136
|
+
const [snippets, { refetch: refetchSnippets }] = createResource(() => props.api.state.path.directory, () => getSnippets(props.api), {
|
|
137
|
+
initialValue: [],
|
|
138
|
+
});
|
|
139
|
+
const bind = (ref) => {
|
|
140
|
+
setPrompt(ref);
|
|
141
|
+
props.bindPrompt(ref);
|
|
142
|
+
props.hostRef?.(ref);
|
|
143
|
+
};
|
|
144
|
+
const lockKeyboardSelection = () => {
|
|
145
|
+
setInputMode("keyboard");
|
|
146
|
+
setIgnoreMouseUntil(Date.now() + MOUSE_HOVER_SUPPRESS_MS);
|
|
147
|
+
};
|
|
148
|
+
const allowMouseHover = () => Date.now() >= ignoreMouseUntil();
|
|
149
|
+
const syncPromptInput = (ref, nextInput) => {
|
|
150
|
+
setPromptInput(ref, nextInput);
|
|
151
|
+
setInput(nextInput);
|
|
152
|
+
};
|
|
153
|
+
createEffect(() => {
|
|
154
|
+
const ref = prompt();
|
|
155
|
+
if (!ref) {
|
|
156
|
+
setInput("");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// The prompt ref exposes current state but not an onInput hook, so mirror it.
|
|
160
|
+
const sync = () => {
|
|
161
|
+
const next = ref.current.input;
|
|
162
|
+
setInput((prev) => (prev === next ? prev : next));
|
|
163
|
+
};
|
|
164
|
+
sync();
|
|
165
|
+
const timer = setInterval(sync, PROMPT_SYNC_MS);
|
|
166
|
+
onCleanup(() => clearInterval(timer));
|
|
167
|
+
});
|
|
168
|
+
const match = createMemo(() => {
|
|
169
|
+
if (props.disabled || props.visible === false)
|
|
170
|
+
return;
|
|
171
|
+
return findTrailingHashtagTrigger(input());
|
|
172
|
+
});
|
|
173
|
+
const options = createMemo(() => {
|
|
174
|
+
const next = match();
|
|
175
|
+
if (!next)
|
|
176
|
+
return [];
|
|
177
|
+
return filterSnippets(snippets(), next.query.trim());
|
|
178
|
+
});
|
|
179
|
+
const query = createMemo(() => match()?.query.trim() || "");
|
|
180
|
+
const draftName = createMemo(() => normalizeSnippetName(query()));
|
|
181
|
+
const visible = createMemo(() => {
|
|
182
|
+
const next = match();
|
|
183
|
+
if (!next)
|
|
184
|
+
return false;
|
|
185
|
+
return dismissed() !== next.token;
|
|
186
|
+
});
|
|
187
|
+
const canCreate = createMemo(() => {
|
|
188
|
+
if (snippets.loading)
|
|
189
|
+
return false;
|
|
190
|
+
if (options().length > 0)
|
|
191
|
+
return false;
|
|
192
|
+
return !!query() && !!draftName();
|
|
193
|
+
});
|
|
194
|
+
const optionKey = createMemo(() => options()
|
|
195
|
+
.map((item) => item.name)
|
|
196
|
+
.join("\n"));
|
|
197
|
+
const menuHeight = createMemo(() => Math.min(MENU_MAX_HEIGHT, Math.max(1, options().length || 1)));
|
|
198
|
+
const activeRowId = createMemo(() => {
|
|
199
|
+
if (options().length > 0)
|
|
200
|
+
return options()[selected()]?.name;
|
|
201
|
+
if (canCreate())
|
|
202
|
+
return "create-snippet";
|
|
203
|
+
return undefined;
|
|
204
|
+
});
|
|
205
|
+
let scroll;
|
|
206
|
+
createEffect((prev) => {
|
|
207
|
+
const next = match();
|
|
208
|
+
if (!next) {
|
|
209
|
+
if (dismissed())
|
|
210
|
+
setDismissed(undefined);
|
|
211
|
+
return "";
|
|
212
|
+
}
|
|
213
|
+
const key = `${next.token}\n${optionKey()}`;
|
|
214
|
+
if (key !== prev) {
|
|
215
|
+
setSelected(0);
|
|
216
|
+
// Keep filtered keyboard navigation from getting stolen by synthetic mouse events.
|
|
217
|
+
lockKeyboardSelection();
|
|
218
|
+
setTimeout(() => {
|
|
219
|
+
scroll?.scrollTo(0);
|
|
220
|
+
}, 0);
|
|
221
|
+
}
|
|
222
|
+
return key;
|
|
223
|
+
});
|
|
224
|
+
createEffect(() => {
|
|
225
|
+
const row = activeRowId();
|
|
226
|
+
if (!visible() || !row)
|
|
227
|
+
return;
|
|
228
|
+
setTimeout(() => {
|
|
229
|
+
scroll?.scrollChildIntoView(row);
|
|
230
|
+
}, 0);
|
|
231
|
+
});
|
|
232
|
+
const choose = (index = selected()) => {
|
|
233
|
+
const item = options()[index];
|
|
234
|
+
if (!item)
|
|
235
|
+
return;
|
|
236
|
+
chooseItem(item);
|
|
237
|
+
};
|
|
238
|
+
const chooseItem = (item) => {
|
|
239
|
+
const ref = prompt();
|
|
240
|
+
if (!ref)
|
|
241
|
+
return;
|
|
242
|
+
const nextInput = insertSnippetTag(ref.current.input, item.name);
|
|
243
|
+
syncPromptInput(ref, nextInput);
|
|
244
|
+
ref.focus();
|
|
245
|
+
setDismissed(undefined);
|
|
246
|
+
};
|
|
247
|
+
createEffect(() => {
|
|
248
|
+
const ref = prompt();
|
|
249
|
+
if (!ref)
|
|
250
|
+
return;
|
|
251
|
+
let dispose;
|
|
252
|
+
const timer = setTimeout(() => {
|
|
253
|
+
dispose = props.api.command.register(() => [
|
|
254
|
+
{
|
|
255
|
+
title: "Accept snippet autocomplete",
|
|
256
|
+
value: "snippets.accept",
|
|
257
|
+
keybind: "input_submit",
|
|
258
|
+
category: "Prompt",
|
|
259
|
+
hidden: true,
|
|
260
|
+
enabled: ref.focused,
|
|
261
|
+
onSelect() {
|
|
262
|
+
const current = findTrailingHashtagTrigger(ref.current.input);
|
|
263
|
+
if (!current || dismissed() === current.token) {
|
|
264
|
+
ref.submit();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
// Prefer the rendered dropdown state so Enter follows what the user can see.
|
|
268
|
+
if (visible()) {
|
|
269
|
+
const rendered = options();
|
|
270
|
+
if (rendered.length > 0) {
|
|
271
|
+
const index = Math.min(selected(), rendered.length - 1);
|
|
272
|
+
chooseItem(rendered[index] ?? rendered[0]);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (canCreate()) {
|
|
276
|
+
void createSnippetDraft();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (snippets.loading) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const query = current.query.trim();
|
|
284
|
+
const live = filterSnippets(snippets(), query);
|
|
285
|
+
if (live.length > 0) {
|
|
286
|
+
const index = Math.min(selected(), live.length - 1);
|
|
287
|
+
chooseItem(live[index] ?? live[0]);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (normalizeSnippetName(query)) {
|
|
291
|
+
void createSnippetDraft();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
ref.submit();
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
]);
|
|
298
|
+
}, 0);
|
|
299
|
+
onCleanup(() => {
|
|
300
|
+
clearTimeout(timer);
|
|
301
|
+
dispose?.();
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
const createSnippetDraft = async () => {
|
|
305
|
+
const ref = prompt();
|
|
306
|
+
const name = draftName();
|
|
307
|
+
if (!ref || !name || creating())
|
|
308
|
+
return;
|
|
309
|
+
const current = findTrailingHashtagTrigger(ref.current.input);
|
|
310
|
+
const nextInput = current ? `${ref.current.input.slice(0, current.start)}#${name}` : `#${name}`;
|
|
311
|
+
const editor = Bun.env.VISUAL || Bun.env.EDITOR;
|
|
312
|
+
if (!editor) {
|
|
313
|
+
props.api.ui.toast({
|
|
314
|
+
variant: "warning",
|
|
315
|
+
message: "Set VISUAL or EDITOR to create snippets from the TUI.",
|
|
316
|
+
});
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
setCreating(true);
|
|
320
|
+
try {
|
|
321
|
+
syncPromptInput(ref, nextInput);
|
|
322
|
+
const filePath = await ensureSnippetDraft(name);
|
|
323
|
+
const opened = await openExternalEditor(props.api, filePath);
|
|
324
|
+
if (!opened) {
|
|
325
|
+
syncPromptInput(ref, nextInput);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
await refetchSnippets();
|
|
329
|
+
syncPromptInput(ref, nextInput);
|
|
330
|
+
setDismissed(undefined);
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
props.api.ui.toast({
|
|
334
|
+
variant: "error",
|
|
335
|
+
message: `Failed to create snippet: ${error instanceof Error ? error.message : String(error)}`,
|
|
336
|
+
});
|
|
337
|
+
syncPromptInput(ref, nextInput);
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
setCreating(false);
|
|
341
|
+
ref.focus();
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
useKeyboard((evt) => {
|
|
345
|
+
if (!visible())
|
|
346
|
+
return;
|
|
347
|
+
const name = evt.name?.toLowerCase();
|
|
348
|
+
const total = options().length;
|
|
349
|
+
const actionable = total > 0 || canCreate();
|
|
350
|
+
const isNavUp = name === "up";
|
|
351
|
+
const isNavDown = name === "down";
|
|
352
|
+
if (isNavUp) {
|
|
353
|
+
if (!actionable)
|
|
354
|
+
return;
|
|
355
|
+
lockKeyboardSelection();
|
|
356
|
+
if (total > 0) {
|
|
357
|
+
setSelected((selected() - 1 + total) % total);
|
|
358
|
+
}
|
|
359
|
+
evt.preventDefault();
|
|
360
|
+
evt.stopPropagation();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (isNavDown) {
|
|
364
|
+
if (!actionable)
|
|
365
|
+
return;
|
|
366
|
+
lockKeyboardSelection();
|
|
367
|
+
if (total > 0) {
|
|
368
|
+
setSelected((selected() + 1) % total);
|
|
369
|
+
}
|
|
370
|
+
evt.preventDefault();
|
|
371
|
+
evt.stopPropagation();
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (name === "escape") {
|
|
375
|
+
setDismissed(match()?.token);
|
|
376
|
+
evt.preventDefault();
|
|
377
|
+
evt.stopPropagation();
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (name === "tab") {
|
|
381
|
+
if (!actionable)
|
|
382
|
+
return;
|
|
383
|
+
if (total > 0) {
|
|
384
|
+
choose(selected());
|
|
385
|
+
}
|
|
386
|
+
else if (canCreate()) {
|
|
387
|
+
void createSnippetDraft();
|
|
388
|
+
}
|
|
389
|
+
evt.preventDefault();
|
|
390
|
+
evt.stopPropagation();
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
const emptyLabel = createMemo(() => {
|
|
394
|
+
if (snippets.loading && snippets().length === 0)
|
|
395
|
+
return "Loading snippets...";
|
|
396
|
+
if (snippets().length === 0)
|
|
397
|
+
return "No snippets found";
|
|
398
|
+
return "No matching snippets";
|
|
399
|
+
});
|
|
400
|
+
const addSnippetLabel = createMemo(() => {
|
|
401
|
+
if (creating())
|
|
402
|
+
return "Creating snippet...";
|
|
403
|
+
return `Add new Snippet #${draftName()}`;
|
|
404
|
+
});
|
|
405
|
+
const selectedFg = createMemo(() => selectedText(props.api.theme.current));
|
|
406
|
+
return (<box flexDirection="column">
|
|
407
|
+
<Show when={visible()}>
|
|
408
|
+
<box width="100%" borderColor={props.api.theme.current.border} {...INLINE_BORDER}>
|
|
409
|
+
<scrollbox ref={(r) => {
|
|
410
|
+
scroll = r;
|
|
411
|
+
}} backgroundColor={props.api.theme.current.backgroundMenu} height={menuHeight()} scrollbarOptions={{ visible: false }}>
|
|
412
|
+
<Index each={options()} fallback={<Show when={canCreate()} fallback={<box paddingLeft={1} paddingRight={1}>
|
|
413
|
+
<text fg={props.api.theme.current.textMuted}>{emptyLabel()}</text>
|
|
414
|
+
</box>}>
|
|
415
|
+
{/* biome-ignore lint/a11y/noStaticElementInteractions: OpenTUI rows intentionally handle mouse selection. */}
|
|
416
|
+
<box id="create-snippet" paddingLeft={1} paddingRight={1} backgroundColor={props.api.theme.current.primary} onMouseMove={() => {
|
|
417
|
+
if (!allowMouseHover())
|
|
418
|
+
return;
|
|
419
|
+
setInputMode("mouse");
|
|
420
|
+
}} onMouseDown={() => {
|
|
421
|
+
setInputMode("mouse");
|
|
422
|
+
}} onMouseUp={() => {
|
|
423
|
+
void createSnippetDraft();
|
|
424
|
+
}}>
|
|
425
|
+
<text fg={selectedFg()}>{addSnippetLabel()}</text>
|
|
426
|
+
</box>
|
|
427
|
+
</Show>}>
|
|
428
|
+
{(option, index) => (
|
|
429
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: OpenTUI rows intentionally handle mouse selection.
|
|
430
|
+
// biome-ignore lint/a11y/useKeyWithMouseEvents: Keyboard navigation is handled by the prompt-level key handler above.
|
|
431
|
+
<box id={option().name} paddingLeft={1} paddingRight={1} backgroundColor={index === selected() ? props.api.theme.current.primary : undefined} flexDirection="row" onMouseMove={() => {
|
|
432
|
+
if (!allowMouseHover())
|
|
433
|
+
return;
|
|
434
|
+
setInputMode("mouse");
|
|
435
|
+
}} onMouseOver={() => {
|
|
436
|
+
if (inputMode() !== "mouse" || !allowMouseHover())
|
|
437
|
+
return;
|
|
438
|
+
setSelected(index);
|
|
439
|
+
}} onMouseDown={() => {
|
|
440
|
+
setInputMode("mouse");
|
|
441
|
+
setSelected(index);
|
|
442
|
+
}} onMouseUp={() => choose(index)}>
|
|
443
|
+
<text fg={index === selected() ? selectedFg() : props.api.theme.current.text} flexShrink={0} wrapMode="none">
|
|
444
|
+
{renderHighlighted(`#${option().name}`, query(), index === selected() ? selectedFg() : props.api.theme.current.text)}
|
|
445
|
+
</text>
|
|
446
|
+
<Show when={matchedAliases(option(), query()).length > 0}>
|
|
447
|
+
<text fg={index === selected() ? selectedFg() : props.api.theme.current.textMuted} wrapMode="none" flexShrink={0}>
|
|
448
|
+
{renderHighlighted(` ${matchedAliases(option(), query()).length === 1 ? "alias" : "aliases"}: ${matchedAliases(option(), query()).join(", ")}`, query(), index === selected() ? selectedFg() : props.api.theme.current.textMuted)}
|
|
449
|
+
</text>
|
|
450
|
+
</Show>
|
|
451
|
+
<Show when={snippetDescription(option())}>
|
|
452
|
+
<text fg={index === selected() ? selectedFg() : props.api.theme.current.textMuted} wrapMode="none">
|
|
453
|
+
{renderHighlighted(` ${snippetDescription(option())}`, query(), index === selected() ? selectedFg() : props.api.theme.current.textMuted)}
|
|
454
|
+
</text>
|
|
455
|
+
</Show>
|
|
456
|
+
</box>)}
|
|
457
|
+
</Index>
|
|
458
|
+
</scrollbox>
|
|
459
|
+
</box>
|
|
460
|
+
</Show>
|
|
461
|
+
<props.api.ui.Prompt sessionID={props.sessionID} workspaceID={props.workspaceID} visible={props.visible} disabled={props.disabled} onSubmit={props.onSubmit} placeholders={props.placeholders} ref={bind} right={props.right}/>
|
|
462
|
+
</box>);
|
|
463
|
+
}
|
|
464
|
+
const tui = async (api) => {
|
|
465
|
+
let currentPrompt;
|
|
466
|
+
const bindPrompt = (ref) => {
|
|
467
|
+
currentPrompt = ref;
|
|
468
|
+
};
|
|
469
|
+
api.command.register(() => [
|
|
470
|
+
{
|
|
471
|
+
title: "Insert snippet",
|
|
472
|
+
value: "snippets.insert",
|
|
473
|
+
description: "Insert a # trigger into the current prompt",
|
|
474
|
+
category: "Prompt",
|
|
475
|
+
hidden: !currentPrompt,
|
|
476
|
+
onSelect() {
|
|
477
|
+
if (!currentPrompt)
|
|
478
|
+
return;
|
|
479
|
+
setPromptInput(currentPrompt, insertSnippetTrigger(currentPrompt.current.input));
|
|
480
|
+
currentPrompt.focus();
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
]);
|
|
484
|
+
api.slots.register({
|
|
485
|
+
order: 100,
|
|
486
|
+
slots: {
|
|
487
|
+
home_prompt(_ctx, value) {
|
|
488
|
+
return (<PromptWithSnippetAutocomplete api={api} bindPrompt={bindPrompt} hostRef={value.ref} workspaceID={value.workspace_id} placeholders={HOME_PLACEHOLDERS} right={<api.ui.Slot name="home_prompt_right" workspace_id={value.workspace_id}/>}/>);
|
|
489
|
+
},
|
|
490
|
+
session_prompt(_ctx, value) {
|
|
491
|
+
return (<PromptWithSnippetAutocomplete api={api} bindPrompt={bindPrompt} hostRef={value.ref} sessionID={value.session_id} visible={value.visible} disabled={value.disabled} onSubmit={value.on_submit} right={<api.ui.Slot name="session_prompt_right" session_id={value.session_id}/>}/>);
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
};
|
|
496
|
+
const plugin = {
|
|
497
|
+
id,
|
|
498
|
+
tui,
|
|
499
|
+
};
|
|
500
|
+
export default plugin;
|
|
501
|
+
//# sourceMappingURL=tui.jsx.map
|
package/dist/tui.jsx.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.jsx","sourceRoot":"","sources":["../tui.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-snippets",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Hashtag-based snippet expansion plugin for OpenCode - instant inline text shortcuts",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./server": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./tui": {
|
|
17
|
+
"types": "./dist/tui.d.ts",
|
|
18
|
+
"default": "./dist/tui.jsx"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
7
21
|
"type": "module",
|
|
8
22
|
"engines": {
|
|
9
23
|
"bun": ">=1.0.0"
|
|
@@ -33,14 +47,31 @@
|
|
|
33
47
|
"jsonc-parser": "^3.3.1"
|
|
34
48
|
},
|
|
35
49
|
"peerDependencies": {
|
|
36
|
-
"@opencode-ai/plugin": "
|
|
50
|
+
"@opencode-ai/plugin": "^1.4.7",
|
|
51
|
+
"@opentui/core": ">=0.1.99",
|
|
52
|
+
"@opentui/solid": ">=0.1.99",
|
|
53
|
+
"solid-js": ">=1.9.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"@opentui/core": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@opentui/solid": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"solid-js": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
37
65
|
},
|
|
38
66
|
"devDependencies": {
|
|
67
|
+
"@opentui/core": "0.1.99",
|
|
68
|
+
"@opentui/solid": "0.1.99",
|
|
39
69
|
"@biomejs/biome": "^2.3.11",
|
|
40
70
|
"@types/bun": "latest",
|
|
41
71
|
"@types/node": "^22",
|
|
42
72
|
"@typescript/native-preview": "^7.0.0-dev.20260120.1",
|
|
43
73
|
"husky": "^9.1.7",
|
|
74
|
+
"solid-js": "1.9.10",
|
|
44
75
|
"typescript": "^5"
|
|
45
76
|
},
|
|
46
77
|
"scripts": {
|
package/skill/snippets/SKILL.md
CHANGED
|
@@ -35,7 +35,7 @@ Full config example with all options:
|
|
|
35
35
|
```jsonc
|
|
36
36
|
{
|
|
37
37
|
// JSON Schema for editor autocompletion
|
|
38
|
-
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/
|
|
38
|
+
"$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/v2.0.0/schema/config.schema.json",
|
|
39
39
|
|
|
40
40
|
// Logging settings
|
|
41
41
|
"logging": {
|