editprompt 1.2.0 → 1.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.
- package/README.md +44 -5
- package/dist/index.js +329 -164
- package/package.json +34 -28
package/README.md
CHANGED
|
@@ -19,7 +19,6 @@ A CLI tool that lets you write prompts for CLI tools using your favorite text ed
|
|
|
19
19
|
- **💬 Quote and Reply**: Collect multiple text selections and reply to specific parts of AI responses
|
|
20
20
|
- **📝 Multi-line Commands**: Complex SQL queries, JSON payloads, and structured prompts
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
## ✨ Features
|
|
24
23
|
|
|
25
24
|
- 🖊️ **Editor Integration**: Use your preferred text editor to write prompts
|
|
@@ -29,7 +28,6 @@ A CLI tool that lets you write prompts for CLI tools using your favorite text ed
|
|
|
29
28
|
- 📋 **Quote Buffering**: Collect text selections and send them as quoted replies
|
|
30
29
|
- 📋 **Clipboard Fallback**: Automatically copies to clipboard if sending fails
|
|
31
30
|
|
|
32
|
-
|
|
33
31
|
## 📦 Installation
|
|
34
32
|
|
|
35
33
|
```bash
|
|
@@ -97,7 +95,6 @@ For replying to specific parts of AI responses:
|
|
|
97
95
|
|
|
98
96
|
Perfect for addressing multiple points in long AI responses.
|
|
99
97
|
|
|
100
|
-
|
|
101
98
|
## ⚙️ Setup & Configuration
|
|
102
99
|
|
|
103
100
|
### Basic Setup
|
|
@@ -127,7 +124,6 @@ bind -n M-q run-shell '\
|
|
|
127
124
|
"editprompt open --editor nvim --always-copy --target-pane #{pane_id}"'
|
|
128
125
|
```
|
|
129
126
|
|
|
130
|
-
|
|
131
127
|
### WezTerm Integration
|
|
132
128
|
|
|
133
129
|
```lua
|
|
@@ -173,7 +169,6 @@ bind -n M-q run-shell '\
|
|
|
173
169
|
|
|
174
170
|
**Note:** The `-lc` flag ensures your shell loads the full login environment, making `editprompt` available in your PATH.
|
|
175
171
|
|
|
176
|
-
|
|
177
172
|
### Editor Integration (Send Without Closing)
|
|
178
173
|
|
|
179
174
|
While editprompt is running, you can send content to the target pane or clipboard without closing the editor. This allows you to iterate quickly on your prompts.
|
|
@@ -197,6 +192,7 @@ editprompt input --auto-send --send-key "C-m" -- "your content here"
|
|
|
197
192
|
This sends the content to the target pane (or clipboard) while keeping your editor open, so you can continue editing and send multiple times.
|
|
198
193
|
|
|
199
194
|
**Options:**
|
|
195
|
+
|
|
200
196
|
- `--auto-send`: Automatically sends the content and returns focus to your editor pane (requires multiplexer)
|
|
201
197
|
- `--send-key <key>`: Customize the key to send after content (requires `--auto-send`)
|
|
202
198
|
- tmux format: `Enter` (default), `C-a`, etc.
|
|
@@ -217,6 +213,7 @@ bind-key -T copy-mode-vi C-e { send-keys -X pipe "editprompt collect --target-pa
|
|
|
217
213
|
```
|
|
218
214
|
|
|
219
215
|
**Usage:**
|
|
216
|
+
|
|
220
217
|
1. Enter tmux copy mode (`prefix + [`)
|
|
221
218
|
2. Select text using vi-mode keybindings
|
|
222
219
|
3. Press `Ctrl-e` to add the selection as a quote
|
|
@@ -257,6 +254,7 @@ return {
|
|
|
257
254
|
```
|
|
258
255
|
|
|
259
256
|
**Usage:**
|
|
257
|
+
|
|
260
258
|
1. Select text in WezTerm (by dragging with mouse or using copy mode)
|
|
261
259
|
2. Press `Ctrl-e` to add the selection as a quote
|
|
262
260
|
3. Repeat to collect multiple quotes
|
|
@@ -273,6 +271,7 @@ editprompt dump
|
|
|
273
271
|
This copies all collected quotes to the clipboard and clears the buffer, ready for your reply.
|
|
274
272
|
|
|
275
273
|
**Complete workflow:**
|
|
274
|
+
|
|
276
275
|
1. AI responds with multiple points
|
|
277
276
|
2. Select each point in copy mode and press `Ctrl-e`
|
|
278
277
|
3. Open your editor pane and run `editprompt dump`
|
|
@@ -280,6 +279,7 @@ This copies all collected quotes to the clipboard and clears the buffer, ready f
|
|
|
280
279
|
5. Send to AI
|
|
281
280
|
|
|
282
281
|
**How quote buffering works:**
|
|
282
|
+
|
|
283
283
|
- **tmux**: Quotes are stored in pane variables, automatically cleaned up when the pane closes
|
|
284
284
|
- **WezTerm**: Quotes are stored in a configuration file associated with the pane
|
|
285
285
|
- Text is intelligently processed: removes common indentation, handles line breaks smartly
|
|
@@ -358,3 +358,42 @@ editprompt open --env NVIM_CONFIG=minimal
|
|
|
358
358
|
#### Target Pane Environment Variable
|
|
359
359
|
|
|
360
360
|
When using the send-without-closing feature or dump, editprompt sets `EDITPROMPT_TARGET_PANE` to the target pane ID. This is automatically used by `editprompt input` and `editprompt dump` commands.
|
|
361
|
+
|
|
362
|
+
### Logging Options
|
|
363
|
+
|
|
364
|
+
editprompt uses structured logging via [LogTape](https://logtape.org/). The following flags are available on all subcommands:
|
|
365
|
+
|
|
366
|
+
| Flag | Description |
|
|
367
|
+
| ------------------- | ------------------------------------------ |
|
|
368
|
+
| `--quiet` / `-q` | Suppress all log output |
|
|
369
|
+
| `--verbose` / `-v` | Enable debug-level log output |
|
|
370
|
+
| `--log-file <path>` | Write logs to the specified file (appends) |
|
|
371
|
+
|
|
372
|
+
You can also configure logging via environment variables:
|
|
373
|
+
|
|
374
|
+
| Environment Variable | Description |
|
|
375
|
+
| ---------------------- | ---------------------------------------------------- |
|
|
376
|
+
| `EDITPROMPT_LOG_FILE` | Path to log file (same as `--log-file`) |
|
|
377
|
+
| `EDITPROMPT_LOG_LEVEL` | Log level (e.g. `debug`, `info`, `warning`, `error`) |
|
|
378
|
+
|
|
379
|
+
**Log level resolution priority:**
|
|
380
|
+
|
|
381
|
+
1. `--quiet` → suppresses all logs
|
|
382
|
+
2. `--verbose` → sets level to `debug`
|
|
383
|
+
3. `EDITPROMPT_LOG_LEVEL` → uses the specified level
|
|
384
|
+
4. Default: `info`
|
|
385
|
+
|
|
386
|
+
### Send-Key Delay
|
|
387
|
+
|
|
388
|
+
When using `--auto-send` with `editprompt input`, a delay is inserted before sending the key to allow the target process to finish processing the content.
|
|
389
|
+
|
|
390
|
+
| Environment Variable | Description | Default |
|
|
391
|
+
| --------------------------- | -------------------------------------------- | ------- |
|
|
392
|
+
| `EDITPROMPT_SEND_KEY_DELAY` | Delay in milliseconds before sending the key | `1000` |
|
|
393
|
+
|
|
394
|
+
**Auto-detection:** editprompt automatically adjusts the delay based on content:
|
|
395
|
+
|
|
396
|
+
- **Content with image paths** → uses `EDITPROMPT_SEND_KEY_DELAY` (default: `1000` ms)
|
|
397
|
+
- **Content without image paths** → uses `200` ms
|
|
398
|
+
|
|
399
|
+
Supported image extensions: `.png`, `.webp`, `.avif`, `.jpg`/`.jpeg`, `.gif` (case-insensitive)
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { configureSync, getAnsiColorFormatter, getLogger, getTextFormatter, parseLogLevel, withFilter } from "@logtape/logtape";
|
|
2
3
|
import { cli, define } from "gunshi";
|
|
4
|
+
import { appendFileSync } from "node:fs";
|
|
3
5
|
import { exec, spawn } from "node:child_process";
|
|
4
6
|
import { promisify } from "node:util";
|
|
5
7
|
import Conf from "conf";
|
|
@@ -8,23 +10,86 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
8
10
|
import { tmpdir } from "node:os";
|
|
9
11
|
import { join } from "node:path";
|
|
10
12
|
|
|
13
|
+
//#region src/modules/logger.ts
|
|
14
|
+
function resolveLogFilePath(options) {
|
|
15
|
+
if (options.logFile) return options.logFile;
|
|
16
|
+
const envPath = process.env.EDITPROMPT_LOG_FILE;
|
|
17
|
+
if (envPath) return envPath;
|
|
18
|
+
}
|
|
19
|
+
function resolveFileLogLevel(options) {
|
|
20
|
+
if (options.verbose) return "debug";
|
|
21
|
+
const envLevel = process.env.EDITPROMPT_LOG_LEVEL;
|
|
22
|
+
if (envLevel) return parseLogLevel(envLevel);
|
|
23
|
+
return "info";
|
|
24
|
+
}
|
|
25
|
+
function resolveLogLevel(options) {
|
|
26
|
+
if (options.quiet) return null;
|
|
27
|
+
if (options.verbose) return "debug";
|
|
28
|
+
const envLevel = process.env.EDITPROMPT_LOG_LEVEL;
|
|
29
|
+
if (envLevel) return parseLogLevel(envLevel);
|
|
30
|
+
return "info";
|
|
31
|
+
}
|
|
32
|
+
function setupLogger(options = {}) {
|
|
33
|
+
const stderrLevel = resolveLogLevel(options);
|
|
34
|
+
const stderrFormatter = getAnsiColorFormatter({
|
|
35
|
+
timestamp: "time-timezone",
|
|
36
|
+
level: "ABBR"
|
|
37
|
+
});
|
|
38
|
+
const rawStderrSink = (record) => {
|
|
39
|
+
process.stderr.write(stderrFormatter(record));
|
|
40
|
+
};
|
|
41
|
+
const sinks = { stderr: stderrLevel === null ? () => {} : withFilter(rawStderrSink, stderrLevel) };
|
|
42
|
+
const loggerSinks = ["stderr"];
|
|
43
|
+
const logFilePath = resolveLogFilePath(options);
|
|
44
|
+
const fileLogLevel = resolveFileLogLevel(options);
|
|
45
|
+
if (logFilePath) try {
|
|
46
|
+
appendFileSync(logFilePath, "");
|
|
47
|
+
const fileFormatter = getTextFormatter({
|
|
48
|
+
timestamp: "date-time-timezone",
|
|
49
|
+
level: "ABBR"
|
|
50
|
+
});
|
|
51
|
+
const rawFileSink = (record) => {
|
|
52
|
+
appendFileSync(logFilePath, fileFormatter(record));
|
|
53
|
+
};
|
|
54
|
+
sinks.file = withFilter(rawFileSink, fileLogLevel);
|
|
55
|
+
loggerSinks.push("file");
|
|
56
|
+
} catch {
|
|
57
|
+
process.stderr.write(`Warning: Cannot write to log file '${logFilePath}', continuing without file logging.\n`);
|
|
58
|
+
}
|
|
59
|
+
configureSync({
|
|
60
|
+
sinks,
|
|
61
|
+
loggers: [{
|
|
62
|
+
category: ["editprompt"],
|
|
63
|
+
sinks: loggerSinks,
|
|
64
|
+
lowestLevel: "trace"
|
|
65
|
+
}, {
|
|
66
|
+
category: ["logtape", "meta"],
|
|
67
|
+
lowestLevel: null
|
|
68
|
+
}]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
11
73
|
//#region package.json
|
|
12
|
-
var version = "1.
|
|
74
|
+
var version = "1.3.0";
|
|
13
75
|
|
|
14
76
|
//#endregion
|
|
15
77
|
//#region src/modules/tmux.ts
|
|
16
78
|
const execAsync$1 = promisify(exec);
|
|
17
|
-
|
|
79
|
+
const logger$10 = getLogger(["editprompt", "tmux"]);
|
|
80
|
+
async function getCurrentPaneId$1() {
|
|
81
|
+
const envPaneId = process.env.TMUX_PANE?.trim();
|
|
82
|
+
if (envPaneId) return envPaneId;
|
|
18
83
|
const { stdout } = await execAsync$1("tmux display-message -p \"#{pane_id}\"");
|
|
19
84
|
return stdout.trim();
|
|
20
85
|
}
|
|
21
86
|
async function saveEditorPaneId$1(targetPaneId, editorPaneId) {
|
|
22
87
|
await execAsync$1(`tmux set-option -pt '${targetPaneId}' @editprompt_editor_pane '${editorPaneId}'`);
|
|
23
88
|
}
|
|
24
|
-
async function clearEditorPaneId(targetPaneId) {
|
|
89
|
+
async function clearEditorPaneId$1(targetPaneId) {
|
|
25
90
|
await execAsync$1(`tmux set-option -pt '${targetPaneId}' @editprompt_editor_pane ""`);
|
|
26
91
|
}
|
|
27
|
-
async function getEditorPaneId(targetPaneId) {
|
|
92
|
+
async function getEditorPaneId$1(targetPaneId) {
|
|
28
93
|
try {
|
|
29
94
|
const { stdout } = await execAsync$1(`tmux show -pt '${targetPaneId}' -v @editprompt_editor_pane`);
|
|
30
95
|
return stdout.trim();
|
|
@@ -32,7 +97,7 @@ async function getEditorPaneId(targetPaneId) {
|
|
|
32
97
|
return "";
|
|
33
98
|
}
|
|
34
99
|
}
|
|
35
|
-
async function checkPaneExists(paneId) {
|
|
100
|
+
async function checkPaneExists$1(paneId) {
|
|
36
101
|
try {
|
|
37
102
|
const { stdout } = await execAsync$1("tmux list-panes -a -F \"#{pane_id}\"");
|
|
38
103
|
return stdout.split("\n").map((id) => id.trim()).includes(paneId);
|
|
@@ -40,16 +105,16 @@ async function checkPaneExists(paneId) {
|
|
|
40
105
|
return false;
|
|
41
106
|
}
|
|
42
107
|
}
|
|
43
|
-
async function focusPane(paneId) {
|
|
108
|
+
async function focusPane$1(paneId) {
|
|
44
109
|
await execAsync$1(`tmux select-pane -t '${paneId}'`);
|
|
45
110
|
}
|
|
46
|
-
async function markAsEditorPane(editorPaneId, targetPaneIds) {
|
|
111
|
+
async function markAsEditorPane$1(editorPaneId, targetPaneIds) {
|
|
47
112
|
await execAsync$1(`tmux set-option -pt '${editorPaneId}' @editprompt_is_editor 1`);
|
|
48
113
|
const uniqueTargetPaneIds = [...new Set(targetPaneIds)];
|
|
49
114
|
await execAsync$1(`tmux set-option -pt '${editorPaneId}' @editprompt_target_panes '${uniqueTargetPaneIds.join(",")}'`);
|
|
50
115
|
for (const targetPaneId of uniqueTargetPaneIds) await saveEditorPaneId$1(targetPaneId, editorPaneId);
|
|
51
116
|
}
|
|
52
|
-
async function getTargetPaneIds(editorPaneId) {
|
|
117
|
+
async function getTargetPaneIds$1(editorPaneId) {
|
|
53
118
|
try {
|
|
54
119
|
const { stdout } = await execAsync$1(`tmux show -pt '${editorPaneId}' -v @editprompt_target_panes`);
|
|
55
120
|
const value = stdout.trim();
|
|
@@ -85,14 +150,14 @@ async function appendToQuoteVariable(paneId, content) {
|
|
|
85
150
|
async function clearQuoteVariable(targetPaneId) {
|
|
86
151
|
await execAsync$1(`tmux set-option -pt '${targetPaneId}' @editprompt_quote ""`);
|
|
87
152
|
}
|
|
88
|
-
async function sendKeyToTmuxPane(paneId, key) {
|
|
89
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
153
|
+
async function sendKeyToTmuxPane(paneId, key, delay = 1e3) {
|
|
154
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
90
155
|
await execAsync$1(`tmux send-keys -t '${paneId}' '${key}'`);
|
|
91
156
|
}
|
|
92
157
|
async function inputToTmuxPane(paneId, content) {
|
|
93
158
|
await execAsync$1(`tmux if-shell -t '${paneId}' '[ "#{pane_in_mode}" = "1" ]' "copy-mode -q -t '${paneId}'"`);
|
|
94
159
|
await execAsync$1(`tmux send-keys -t '${paneId}' -- '${content.replace(/'/g, "'\\''")}'`);
|
|
95
|
-
|
|
160
|
+
logger$10.debug("Content sent to tmux pane: {paneId}", { paneId });
|
|
96
161
|
}
|
|
97
162
|
|
|
98
163
|
//#endregion
|
|
@@ -102,67 +167,68 @@ const conf = new Conf({ projectName });
|
|
|
102
167
|
|
|
103
168
|
//#endregion
|
|
104
169
|
//#region src/modules/wezterm.ts
|
|
170
|
+
const logger$9 = getLogger(["editprompt", "wezterm"]);
|
|
105
171
|
const execAsync = promisify(exec);
|
|
106
|
-
async function getCurrentPaneId
|
|
172
|
+
async function getCurrentPaneId() {
|
|
107
173
|
try {
|
|
108
174
|
const { stdout } = await execAsync("wezterm cli list --format json");
|
|
109
175
|
const activePane = JSON.parse(stdout).find((pane) => pane.is_active === true);
|
|
110
176
|
return String(activePane?.pane_id);
|
|
111
177
|
} catch (error) {
|
|
112
|
-
|
|
178
|
+
logger$9.debug("getCurrentPaneId failed: {error}", { error });
|
|
113
179
|
return "";
|
|
114
180
|
}
|
|
115
181
|
}
|
|
116
|
-
async function checkPaneExists
|
|
182
|
+
async function checkPaneExists(paneId) {
|
|
117
183
|
try {
|
|
118
184
|
const { stdout } = await execAsync("wezterm cli list --format json");
|
|
119
|
-
|
|
185
|
+
logger$9.debug("wezterm cli list output: {stdout}", { stdout });
|
|
120
186
|
return JSON.parse(stdout).some((pane) => String(pane.pane_id) === paneId);
|
|
121
187
|
} catch (error) {
|
|
122
|
-
|
|
188
|
+
logger$9.debug("checkPaneExists failed: {error}", { error });
|
|
123
189
|
return false;
|
|
124
190
|
}
|
|
125
191
|
}
|
|
126
192
|
async function saveEditorPaneId(targetPaneId, editorPaneId) {
|
|
127
|
-
|
|
193
|
+
logger$9.debug("Saving editor pane ID to conf key: wezterm.targetPane.pane_{targetPaneId}", { targetPaneId });
|
|
128
194
|
try {
|
|
129
195
|
conf.set(`wezterm.targetPane.pane_${targetPaneId}`, { editorPaneId });
|
|
130
196
|
} catch (error) {
|
|
131
|
-
|
|
197
|
+
logger$9.debug("saveEditorPaneId failed: {error}", { error });
|
|
132
198
|
}
|
|
133
199
|
}
|
|
134
|
-
async function getEditorPaneId
|
|
200
|
+
async function getEditorPaneId(targetPaneId) {
|
|
135
201
|
try {
|
|
136
202
|
const data = conf.get(`wezterm.targetPane.pane_${targetPaneId}`);
|
|
137
203
|
if (typeof data === "object" && data !== null && "editorPaneId" in data) return String(data.editorPaneId);
|
|
138
204
|
return "";
|
|
139
205
|
} catch (error) {
|
|
140
|
-
|
|
206
|
+
logger$9.debug("getEditorPaneId failed: {error}", { error });
|
|
141
207
|
return "";
|
|
142
208
|
}
|
|
143
209
|
}
|
|
144
|
-
async function clearEditorPaneId
|
|
210
|
+
async function clearEditorPaneId(targetPaneId) {
|
|
145
211
|
try {
|
|
146
|
-
const editorPaneId = await getEditorPaneId
|
|
212
|
+
const editorPaneId = await getEditorPaneId(targetPaneId);
|
|
147
213
|
conf.delete(`wezterm.targetPane.pane_${targetPaneId}`);
|
|
148
214
|
if (editorPaneId) conf.delete(`wezterm.editorPane.pane_${editorPaneId}`);
|
|
149
215
|
} catch (error) {
|
|
150
|
-
|
|
216
|
+
logger$9.debug("clearEditorPaneId failed: {error}", { error });
|
|
151
217
|
}
|
|
152
218
|
}
|
|
153
|
-
async function focusPane
|
|
219
|
+
async function focusPane(paneId) {
|
|
154
220
|
await execAsync(`wezterm cli activate-pane --pane-id '${paneId}'`);
|
|
155
221
|
}
|
|
156
|
-
async function markAsEditorPane
|
|
222
|
+
async function markAsEditorPane(editorPaneId, targetPaneIds) {
|
|
157
223
|
try {
|
|
158
224
|
const uniqueTargetPaneIds = [...new Set(targetPaneIds)];
|
|
159
225
|
conf.set(`wezterm.editorPane.pane_${editorPaneId}`, { targetPaneIds: uniqueTargetPaneIds });
|
|
160
226
|
for (const targetPaneId of uniqueTargetPaneIds) await saveEditorPaneId(targetPaneId, editorPaneId);
|
|
161
227
|
} catch (error) {
|
|
162
|
-
|
|
228
|
+
logger$9.debug("markAsEditorPane failed: {error}", { error });
|
|
163
229
|
}
|
|
164
230
|
}
|
|
165
|
-
async function getTargetPaneIds
|
|
231
|
+
async function getTargetPaneIds(editorPaneId) {
|
|
166
232
|
try {
|
|
167
233
|
const data = conf.get(`wezterm.editorPane.pane_${editorPaneId}`);
|
|
168
234
|
if (typeof data === "object" && data !== null && "targetPaneIds" in data) {
|
|
@@ -171,7 +237,7 @@ async function getTargetPaneIds$1(editorPaneId) {
|
|
|
171
237
|
}
|
|
172
238
|
return [];
|
|
173
239
|
} catch (error) {
|
|
174
|
-
|
|
240
|
+
logger$9.debug("getTargetPaneIds failed: {error}", { error });
|
|
175
241
|
return [];
|
|
176
242
|
}
|
|
177
243
|
}
|
|
@@ -179,7 +245,7 @@ function isEditorPaneFromConf(paneId) {
|
|
|
179
245
|
try {
|
|
180
246
|
return conf.has(`wezterm.editorPane.pane_${paneId}`);
|
|
181
247
|
} catch (error) {
|
|
182
|
-
|
|
248
|
+
logger$9.debug("isEditorPaneFromConf failed: {error}", { error });
|
|
183
249
|
return false;
|
|
184
250
|
}
|
|
185
251
|
}
|
|
@@ -197,7 +263,7 @@ async function appendToQuoteText(paneId, content) {
|
|
|
197
263
|
} else newData = { quote_text: content };
|
|
198
264
|
conf.set(`wezterm.targetPane.pane_${paneId}`, newData);
|
|
199
265
|
} catch (error) {
|
|
200
|
-
|
|
266
|
+
logger$9.debug("appendToQuoteText failed: {error}", { error });
|
|
201
267
|
}
|
|
202
268
|
}
|
|
203
269
|
async function getQuoteText(paneId) {
|
|
@@ -206,7 +272,7 @@ async function getQuoteText(paneId) {
|
|
|
206
272
|
if (typeof data === "object" && data !== null && "quote_text" in data) return String(data.quote_text);
|
|
207
273
|
return "";
|
|
208
274
|
} catch (error) {
|
|
209
|
-
|
|
275
|
+
logger$9.debug("getQuoteText failed: {error}", { error });
|
|
210
276
|
return "";
|
|
211
277
|
}
|
|
212
278
|
}
|
|
@@ -215,15 +281,16 @@ async function clearQuoteText(paneId) {
|
|
|
215
281
|
const key = `wezterm.targetPane.pane_${paneId}.quote_text`;
|
|
216
282
|
if (conf.has(key)) conf.delete(key);
|
|
217
283
|
} catch (error) {
|
|
218
|
-
|
|
284
|
+
logger$9.debug("clearQuoteText failed: {error}", { error });
|
|
219
285
|
}
|
|
220
286
|
}
|
|
221
|
-
async function sendKeyToWeztermPane(paneId, key) {
|
|
287
|
+
async function sendKeyToWeztermPane(paneId, key, delay = 1e3) {
|
|
288
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
222
289
|
await execAsync(`wezterm cli send-text --no-paste --pane-id '${paneId}' $'${key}'`);
|
|
223
290
|
}
|
|
224
291
|
async function inputToWeztermPane(paneId, content) {
|
|
225
292
|
await execAsync(`wezterm cli send-text --no-paste --pane-id '${paneId}' -- '${content.replace(/'/g, "'\\''")}'`);
|
|
226
|
-
|
|
293
|
+
logger$9.debug("Content sent to wezterm pane: {paneId}", { paneId });
|
|
227
294
|
}
|
|
228
295
|
|
|
229
296
|
//#endregion
|
|
@@ -237,8 +304,12 @@ async function inputToWeztermPane(paneId, content) {
|
|
|
237
304
|
* @returns Raw content string or undefined if no content provided
|
|
238
305
|
*/
|
|
239
306
|
function extractRawContent(rest, positionals) {
|
|
240
|
-
if (rest.length > 0)
|
|
241
|
-
|
|
307
|
+
if (rest.length > 0) {
|
|
308
|
+
const joined = rest.join(" ");
|
|
309
|
+
if (joined.trim() !== "") return joined;
|
|
310
|
+
}
|
|
311
|
+
const first = positionals[0];
|
|
312
|
+
if (first !== void 0 && first.trim() !== "") return first;
|
|
242
313
|
}
|
|
243
314
|
|
|
244
315
|
//#endregion
|
|
@@ -361,6 +432,7 @@ function processQuoteText(text, options) {
|
|
|
361
432
|
|
|
362
433
|
//#endregion
|
|
363
434
|
//#region src/modes/common.ts
|
|
435
|
+
const logger$8 = getLogger(["editprompt", "delivery"]);
|
|
364
436
|
function isMuxType(value) {
|
|
365
437
|
return value === "tmux" || value === "wezterm";
|
|
366
438
|
}
|
|
@@ -374,8 +446,8 @@ async function inputContentToPane(content, mux, targetPaneId) {
|
|
|
374
446
|
}
|
|
375
447
|
async function focusFirstSuccessPane(mux, targetPanes, failedPanes) {
|
|
376
448
|
const firstSuccessPane = targetPanes.find((p) => !failedPanes.includes(p));
|
|
377
|
-
if (firstSuccessPane) if (mux === "tmux") await focusPane(firstSuccessPane);
|
|
378
|
-
else await focusPane
|
|
449
|
+
if (firstSuccessPane) if (mux === "tmux") await focusPane$1(firstSuccessPane);
|
|
450
|
+
else await focusPane(firstSuccessPane);
|
|
379
451
|
}
|
|
380
452
|
async function handleContentDelivery(content, mux, targetPanes) {
|
|
381
453
|
if (!content) return {
|
|
@@ -388,9 +460,9 @@ async function handleContentDelivery(content, mux, targetPanes) {
|
|
|
388
460
|
if (targetPanes.length === 0) {
|
|
389
461
|
try {
|
|
390
462
|
await copyToClipboard(content);
|
|
391
|
-
|
|
463
|
+
logger$8.info("Content copied to clipboard.");
|
|
392
464
|
} catch (error) {
|
|
393
|
-
|
|
465
|
+
logger$8.warn(`Failed to copy to clipboard: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
394
466
|
}
|
|
395
467
|
return {
|
|
396
468
|
successCount: 0,
|
|
@@ -408,7 +480,7 @@ async function handleContentDelivery(content, mux, targetPanes) {
|
|
|
408
480
|
success: true
|
|
409
481
|
});
|
|
410
482
|
} catch (error) {
|
|
411
|
-
|
|
483
|
+
logger$8.warn(`Failed to send to pane ${targetPane}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
412
484
|
results.push({
|
|
413
485
|
pane: targetPane,
|
|
414
486
|
success: false
|
|
@@ -418,13 +490,13 @@ async function handleContentDelivery(content, mux, targetPanes) {
|
|
|
418
490
|
const failedPanes = results.filter((r) => !r.success).map((r) => r.pane);
|
|
419
491
|
const allSuccess = successCount === targetPanes.length;
|
|
420
492
|
const allFailed = successCount === 0;
|
|
421
|
-
if (allSuccess)
|
|
493
|
+
if (allSuccess) logger$8.info("Content sent successfully to all panes!");
|
|
422
494
|
else if (allFailed) {
|
|
423
|
-
|
|
424
|
-
|
|
495
|
+
logger$8.error("All target panes failed to receive content.");
|
|
496
|
+
logger$8.info("Falling back to clipboard...");
|
|
425
497
|
await copyToClipboard(content);
|
|
426
|
-
|
|
427
|
-
} else
|
|
498
|
+
logger$8.info("Content copied to clipboard.");
|
|
499
|
+
} else logger$8.warn(`Content sent to ${successCount}/${targetPanes.length} panes. Failed panes: ${failedPanes.join(", ")}`);
|
|
428
500
|
return {
|
|
429
501
|
successCount,
|
|
430
502
|
totalCount: targetPanes.length,
|
|
@@ -436,6 +508,7 @@ async function handleContentDelivery(content, mux, targetPanes) {
|
|
|
436
508
|
|
|
437
509
|
//#endregion
|
|
438
510
|
//#region src/modes/args.ts
|
|
511
|
+
const logger$7 = getLogger(["editprompt"]);
|
|
439
512
|
const ARG_MUX = {
|
|
440
513
|
short: "m",
|
|
441
514
|
description: "Multiplexer type (tmux or wezterm, default: tmux)",
|
|
@@ -470,17 +543,31 @@ const ARG_OUTPUT = {
|
|
|
470
543
|
type: "string",
|
|
471
544
|
multiple: true
|
|
472
545
|
};
|
|
546
|
+
const ARG_LOG_FILE = {
|
|
547
|
+
description: "Write logs to the specified file (appends)",
|
|
548
|
+
type: "string"
|
|
549
|
+
};
|
|
550
|
+
const ARG_QUIET = {
|
|
551
|
+
short: "q",
|
|
552
|
+
description: "Suppress all log output",
|
|
553
|
+
type: "boolean"
|
|
554
|
+
};
|
|
555
|
+
const ARG_VERBOSE = {
|
|
556
|
+
short: "v",
|
|
557
|
+
description: "Enable debug-level log output",
|
|
558
|
+
type: "boolean"
|
|
559
|
+
};
|
|
473
560
|
function validateMux(value) {
|
|
474
561
|
const muxValue = value || "tmux";
|
|
475
562
|
if (!isMuxType(muxValue)) {
|
|
476
|
-
|
|
563
|
+
logger$7.error(`Invalid multiplexer type '${muxValue}'. Supported values: ${SUPPORTED_MUXES.join(", ")}`);
|
|
477
564
|
process.exit(1);
|
|
478
565
|
}
|
|
479
566
|
return muxValue;
|
|
480
567
|
}
|
|
481
568
|
function validateTargetPane(value, commandName) {
|
|
482
569
|
if (!value || typeof value !== "string") {
|
|
483
|
-
|
|
570
|
+
logger$7.error(`--target-pane is required for ${commandName} command`);
|
|
484
571
|
process.exit(1);
|
|
485
572
|
}
|
|
486
573
|
return value;
|
|
@@ -493,6 +580,7 @@ function normalizeTargetPanes(value) {
|
|
|
493
580
|
|
|
494
581
|
//#endregion
|
|
495
582
|
//#region src/modes/collect.ts
|
|
583
|
+
const logger$6 = getLogger(["editprompt", "collect"]);
|
|
496
584
|
const SUPPORTED_OUTPUTS = ["buffer", "stdout"];
|
|
497
585
|
async function readStdin() {
|
|
498
586
|
return new Promise((resolve, reject) => {
|
|
@@ -516,7 +604,7 @@ function normalizeCollectOutputs(value) {
|
|
|
516
604
|
const uniqueOutputs = [...new Set(outputs)];
|
|
517
605
|
const invalid = uniqueOutputs.filter((v) => !SUPPORTED_OUTPUTS.includes(v));
|
|
518
606
|
if (invalid.length > 0) {
|
|
519
|
-
|
|
607
|
+
logger$6.error(`Invalid output(s) '${invalid.join(", ")}'. Supported values: ${SUPPORTED_OUTPUTS.join(", ")}`);
|
|
520
608
|
process.exit(1);
|
|
521
609
|
}
|
|
522
610
|
return uniqueOutputs;
|
|
@@ -532,7 +620,7 @@ async function runCollectMode(mux, targetPaneId, rawContent, outputs = ["buffer"
|
|
|
532
620
|
else if (mux === "wezterm") await appendToQuoteText(targetPaneId, processedText);
|
|
533
621
|
} else if (output === "stdout") process.stdout.write(processedText);
|
|
534
622
|
} catch (error) {
|
|
535
|
-
|
|
623
|
+
logger$6.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
536
624
|
process.exit(1);
|
|
537
625
|
}
|
|
538
626
|
}
|
|
@@ -543,9 +631,17 @@ const collectCommand = define({
|
|
|
543
631
|
mux: ARG_MUX,
|
|
544
632
|
"target-pane": ARG_TARGET_PANE_SINGLE,
|
|
545
633
|
output: ARG_OUTPUT,
|
|
546
|
-
"no-quote": ARG_NO_QUOTE
|
|
634
|
+
"no-quote": ARG_NO_QUOTE,
|
|
635
|
+
"log-file": ARG_LOG_FILE,
|
|
636
|
+
quiet: ARG_QUIET,
|
|
637
|
+
verbose: ARG_VERBOSE
|
|
547
638
|
},
|
|
548
639
|
async run(ctx) {
|
|
640
|
+
setupLogger({
|
|
641
|
+
quiet: Boolean(ctx.values.quiet),
|
|
642
|
+
verbose: Boolean(ctx.values.verbose),
|
|
643
|
+
logFile: ctx.values["log-file"]
|
|
644
|
+
});
|
|
549
645
|
const targetPane = validateTargetPane(ctx.values["target-pane"], "collect");
|
|
550
646
|
const mux = validateMux(ctx.values.mux);
|
|
551
647
|
const outputs = normalizeCollectOutputs(ctx.values.output);
|
|
@@ -554,7 +650,7 @@ const collectCommand = define({
|
|
|
554
650
|
if (mux === "wezterm") {
|
|
555
651
|
rawContent = extractRawContent(ctx.rest, ctx.positionals);
|
|
556
652
|
if (rawContent === void 0) {
|
|
557
|
-
|
|
653
|
+
logger$6.error("Text content is required for collect mode with wezterm. Use: editprompt collect --mux wezterm --target-pane <id> -- \"<text>\"");
|
|
558
654
|
process.exit(1);
|
|
559
655
|
}
|
|
560
656
|
}
|
|
@@ -568,35 +664,41 @@ const VALID_MUX_TYPES = ["tmux", "wezterm"];
|
|
|
568
664
|
function readSendConfig() {
|
|
569
665
|
const muxValue = process.env.EDITPROMPT_MUX || "tmux";
|
|
570
666
|
if (!VALID_MUX_TYPES.includes(muxValue)) throw new Error(`Invalid EDITPROMPT_MUX value: ${muxValue}. Must be one of: ${VALID_MUX_TYPES.join(", ")}`);
|
|
667
|
+
const mux = muxValue;
|
|
668
|
+
const alwaysCopy = process.env.EDITPROMPT_ALWAYS_COPY === "1";
|
|
669
|
+
const delayValue = process.env.EDITPROMPT_SEND_KEY_DELAY;
|
|
670
|
+
const parsedDelay = delayValue ? Number.parseInt(delayValue, 10) : NaN;
|
|
571
671
|
return {
|
|
572
|
-
mux
|
|
573
|
-
alwaysCopy
|
|
672
|
+
mux,
|
|
673
|
+
alwaysCopy,
|
|
674
|
+
sendKeyDelay: Number.isNaN(parsedDelay) ? 1e3 : parsedDelay
|
|
574
675
|
};
|
|
575
676
|
}
|
|
576
677
|
|
|
577
678
|
//#endregion
|
|
578
679
|
//#region src/modes/dump.ts
|
|
680
|
+
const logger$5 = getLogger(["editprompt", "dump"]);
|
|
579
681
|
async function runDumpMode() {
|
|
580
682
|
try {
|
|
581
683
|
const config = readSendConfig();
|
|
582
684
|
let currentPaneId;
|
|
583
685
|
let isEditor;
|
|
584
686
|
if (config.mux === "tmux") {
|
|
585
|
-
currentPaneId = await getCurrentPaneId();
|
|
687
|
+
currentPaneId = await getCurrentPaneId$1();
|
|
586
688
|
isEditor = await isEditorPane(currentPaneId);
|
|
587
689
|
} else {
|
|
588
|
-
currentPaneId = await getCurrentPaneId
|
|
690
|
+
currentPaneId = await getCurrentPaneId();
|
|
589
691
|
isEditor = isEditorPaneFromConf(currentPaneId);
|
|
590
692
|
}
|
|
591
693
|
if (!isEditor) {
|
|
592
|
-
|
|
694
|
+
logger$5.error("Current pane is not an editor pane");
|
|
593
695
|
process.exit(1);
|
|
594
696
|
}
|
|
595
697
|
let targetPanes;
|
|
596
|
-
if (config.mux === "tmux") targetPanes = await getTargetPaneIds(currentPaneId);
|
|
597
|
-
else targetPanes = await getTargetPaneIds
|
|
698
|
+
if (config.mux === "tmux") targetPanes = await getTargetPaneIds$1(currentPaneId);
|
|
699
|
+
else targetPanes = await getTargetPaneIds(currentPaneId);
|
|
598
700
|
if (targetPanes.length === 0) {
|
|
599
|
-
|
|
701
|
+
logger$5.error("No target panes registered for this editor pane");
|
|
600
702
|
process.exit(1);
|
|
601
703
|
}
|
|
602
704
|
const quoteContents = [];
|
|
@@ -615,15 +717,24 @@ async function runDumpMode() {
|
|
|
615
717
|
process.stdout.write(combinedContent.replace(/\n{3,}$/, "\n\n"));
|
|
616
718
|
process.exit(0);
|
|
617
719
|
} catch (error) {
|
|
618
|
-
|
|
720
|
+
logger$5.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
619
721
|
process.exit(1);
|
|
620
722
|
}
|
|
621
723
|
}
|
|
622
724
|
const dumpCommand = define({
|
|
623
725
|
name: "dump",
|
|
624
726
|
description: "Output and clear collected quoted text from environment variables",
|
|
625
|
-
args: {
|
|
626
|
-
|
|
727
|
+
args: {
|
|
728
|
+
"log-file": ARG_LOG_FILE,
|
|
729
|
+
quiet: ARG_QUIET,
|
|
730
|
+
verbose: ARG_VERBOSE
|
|
731
|
+
},
|
|
732
|
+
async run(ctx) {
|
|
733
|
+
setupLogger({
|
|
734
|
+
quiet: Boolean(ctx.values.quiet),
|
|
735
|
+
verbose: Boolean(ctx.values.verbose),
|
|
736
|
+
logFile: ctx.values["log-file"]
|
|
737
|
+
});
|
|
627
738
|
await runDumpMode();
|
|
628
739
|
}
|
|
629
740
|
});
|
|
@@ -638,55 +749,57 @@ function processContent(content) {
|
|
|
638
749
|
|
|
639
750
|
//#endregion
|
|
640
751
|
//#region src/modes/input.ts
|
|
641
|
-
|
|
752
|
+
const logger$4 = getLogger(["editprompt", "input"]);
|
|
753
|
+
async function runInputMode(rawContent, autoSend, sendKey, sendKeyDelay) {
|
|
642
754
|
const content = processContent(rawContent);
|
|
643
755
|
if (!content) {
|
|
644
|
-
|
|
756
|
+
logger$4.info("No content to send. Exiting.");
|
|
645
757
|
return;
|
|
646
758
|
}
|
|
647
759
|
const config = readSendConfig();
|
|
648
760
|
let currentPaneId;
|
|
649
761
|
let isEditor;
|
|
650
762
|
if (config.mux === "tmux") {
|
|
651
|
-
currentPaneId = await getCurrentPaneId();
|
|
763
|
+
currentPaneId = await getCurrentPaneId$1();
|
|
652
764
|
isEditor = await isEditorPane(currentPaneId);
|
|
653
765
|
} else {
|
|
654
|
-
currentPaneId = await getCurrentPaneId
|
|
766
|
+
currentPaneId = await getCurrentPaneId();
|
|
655
767
|
isEditor = isEditorPaneFromConf(currentPaneId);
|
|
656
768
|
}
|
|
657
769
|
if (!isEditor) {
|
|
658
|
-
|
|
770
|
+
logger$4.error("Current pane is not an editor pane");
|
|
659
771
|
process.exit(1);
|
|
660
772
|
}
|
|
661
773
|
let targetPanes;
|
|
662
|
-
if (config.mux === "tmux") targetPanes = await getTargetPaneIds(currentPaneId);
|
|
663
|
-
else targetPanes = await getTargetPaneIds
|
|
774
|
+
if (config.mux === "tmux") targetPanes = await getTargetPaneIds$1(currentPaneId);
|
|
775
|
+
else targetPanes = await getTargetPaneIds(currentPaneId);
|
|
664
776
|
if (targetPanes.length === 0) {
|
|
665
|
-
|
|
777
|
+
logger$4.error("No target panes registered for this editor pane");
|
|
666
778
|
process.exit(1);
|
|
667
779
|
}
|
|
668
780
|
if (autoSend) {
|
|
669
781
|
const key = sendKey || (config.mux === "wezterm" ? "\\r" : "C-m");
|
|
782
|
+
const delay = /\.(png|webp|avif|jpe?g|gif)\b/i.test(content) ? sendKeyDelay ?? 1e3 : 200;
|
|
670
783
|
let successCount = 0;
|
|
671
784
|
for (const targetPane of targetPanes) try {
|
|
672
785
|
if (config.mux === "wezterm") {
|
|
673
786
|
await inputToWeztermPane(targetPane, content);
|
|
674
|
-
await sendKeyToWeztermPane(targetPane, key);
|
|
787
|
+
await sendKeyToWeztermPane(targetPane, key, delay);
|
|
675
788
|
} else {
|
|
676
789
|
await inputToTmuxPane(targetPane, content);
|
|
677
|
-
await sendKeyToTmuxPane(targetPane, key);
|
|
790
|
+
await sendKeyToTmuxPane(targetPane, key, delay);
|
|
678
791
|
}
|
|
679
792
|
successCount++;
|
|
680
793
|
} catch (error) {
|
|
681
|
-
|
|
794
|
+
logger$4.error(`Failed to send to pane ${targetPane}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
682
795
|
}
|
|
683
796
|
if (config.alwaysCopy) {
|
|
684
797
|
await copyToClipboard(content);
|
|
685
|
-
|
|
798
|
+
logger$4.info("Also copied to clipboard.");
|
|
686
799
|
}
|
|
687
|
-
if (successCount > 0)
|
|
800
|
+
if (successCount > 0) logger$4.info("Content sent and submitted successfully!");
|
|
688
801
|
else {
|
|
689
|
-
|
|
802
|
+
logger$4.error("All target panes failed to receive content");
|
|
690
803
|
process.exit(1);
|
|
691
804
|
}
|
|
692
805
|
return;
|
|
@@ -695,12 +808,12 @@ async function runInputMode(rawContent, autoSend, sendKey) {
|
|
|
695
808
|
const result = await handleContentDelivery(content, config.mux, targetPanes);
|
|
696
809
|
if (config.alwaysCopy && !result.allFailed) {
|
|
697
810
|
await copyToClipboard(content);
|
|
698
|
-
|
|
811
|
+
logger$4.info("Also copied to clipboard.");
|
|
699
812
|
}
|
|
700
813
|
if (result.successCount > 0) await focusFirstSuccessPane(config.mux, targetPanes, result.failedPanes);
|
|
701
814
|
if (result.allFailed) process.exit(1);
|
|
702
815
|
} catch (error) {
|
|
703
|
-
|
|
816
|
+
logger$4.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
704
817
|
process.exit(1);
|
|
705
818
|
}
|
|
706
819
|
}
|
|
@@ -715,21 +828,30 @@ const inputCommand = define({
|
|
|
715
828
|
"send-key": {
|
|
716
829
|
description: "Key to send after content (requires --auto-send)",
|
|
717
830
|
type: "string"
|
|
718
|
-
}
|
|
831
|
+
},
|
|
832
|
+
"log-file": ARG_LOG_FILE,
|
|
833
|
+
quiet: ARG_QUIET,
|
|
834
|
+
verbose: ARG_VERBOSE
|
|
719
835
|
},
|
|
720
836
|
async run(ctx) {
|
|
837
|
+
setupLogger({
|
|
838
|
+
quiet: Boolean(ctx.values.quiet),
|
|
839
|
+
verbose: Boolean(ctx.values.verbose),
|
|
840
|
+
logFile: ctx.values["log-file"]
|
|
841
|
+
});
|
|
721
842
|
const rawContent = extractRawContent(ctx.rest, ctx.positionals);
|
|
722
843
|
if (rawContent === void 0) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
844
|
+
logger$4.error("Content is required for input command");
|
|
845
|
+
logger$4.error("Usage: editprompt input \"your content\"");
|
|
846
|
+
logger$4.error(" or: editprompt input -- \"your content\"");
|
|
726
847
|
process.exit(1);
|
|
727
848
|
}
|
|
728
849
|
if (ctx.values["send-key"] && !ctx.values["auto-send"]) {
|
|
729
|
-
|
|
850
|
+
logger$4.error("--send-key requires --auto-send to be enabled");
|
|
730
851
|
process.exit(1);
|
|
731
852
|
}
|
|
732
|
-
|
|
853
|
+
const config = readSendConfig();
|
|
854
|
+
await runInputMode(rawContent, Boolean(ctx.values["auto-send"]), ctx.values["send-key"], config.sendKeyDelay);
|
|
733
855
|
}
|
|
734
856
|
});
|
|
735
857
|
|
|
@@ -825,23 +947,25 @@ async function openEditorAndGetContent(editorOption, envVars, sendConfig) {
|
|
|
825
947
|
|
|
826
948
|
//#endregion
|
|
827
949
|
//#region src/modes/openEditor.ts
|
|
950
|
+
const logger$3 = getLogger(["editprompt", "open"]);
|
|
828
951
|
async function runOpenEditorMode(options) {
|
|
829
952
|
if (options.targetPanes.length > 0 && options.mux === "tmux") try {
|
|
830
|
-
await markAsEditorPane(await getCurrentPaneId(), options.targetPanes);
|
|
953
|
+
await markAsEditorPane$1(await getCurrentPaneId$1(), options.targetPanes);
|
|
831
954
|
} catch {}
|
|
832
955
|
else if (options.targetPanes.length > 0 && options.mux === "wezterm") try {
|
|
833
|
-
const currentPaneId = await getCurrentPaneId
|
|
834
|
-
await markAsEditorPane
|
|
956
|
+
const currentPaneId = await getCurrentPaneId();
|
|
957
|
+
await markAsEditorPane(currentPaneId, options.targetPanes);
|
|
835
958
|
} catch {}
|
|
836
959
|
try {
|
|
837
960
|
const sendConfig = {
|
|
838
961
|
mux: options.mux,
|
|
839
|
-
alwaysCopy: options.alwaysCopy
|
|
962
|
+
alwaysCopy: options.alwaysCopy,
|
|
963
|
+
sendKeyDelay: Number.parseInt(process.env.EDITPROMPT_SEND_KEY_DELAY || "", 10) || 1e3
|
|
840
964
|
};
|
|
841
|
-
|
|
965
|
+
logger$3.info("Opening editor...");
|
|
842
966
|
const content = await openEditorAndGetContent(options.editor, options.env, sendConfig);
|
|
843
967
|
if (!content) {
|
|
844
|
-
|
|
968
|
+
logger$3.info("No content entered. Exiting.");
|
|
845
969
|
return;
|
|
846
970
|
}
|
|
847
971
|
try {
|
|
@@ -850,20 +974,20 @@ async function runOpenEditorMode(options) {
|
|
|
850
974
|
console.log(content);
|
|
851
975
|
if (options.alwaysCopy && !result.allFailed) {
|
|
852
976
|
await copyToClipboard(content);
|
|
853
|
-
|
|
977
|
+
logger$3.info("Also copied to clipboard.");
|
|
854
978
|
}
|
|
855
979
|
if (options.targetPanes.length > 0 && result.successCount > 0) await focusFirstSuccessPane(options.mux, options.targetPanes, result.failedPanes);
|
|
856
980
|
if (!result.allSuccess) process.exit(1);
|
|
857
981
|
} catch (error) {
|
|
858
|
-
|
|
982
|
+
logger$3.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
859
983
|
process.exit(1);
|
|
860
984
|
}
|
|
861
985
|
} finally {
|
|
862
986
|
if (options.targetPanes.length > 0 && options.mux === "tmux") try {
|
|
863
|
-
for (const targetPane of options.targetPanes) await clearEditorPaneId(targetPane);
|
|
987
|
+
for (const targetPane of options.targetPanes) await clearEditorPaneId$1(targetPane);
|
|
864
988
|
} catch {}
|
|
865
989
|
else if (options.targetPanes.length > 0 && options.mux === "wezterm") try {
|
|
866
|
-
for (const targetPane of options.targetPanes) await clearEditorPaneId
|
|
990
|
+
for (const targetPane of options.targetPanes) await clearEditorPaneId(targetPane);
|
|
867
991
|
} catch {}
|
|
868
992
|
}
|
|
869
993
|
}
|
|
@@ -875,6 +999,9 @@ const openCommand = define({
|
|
|
875
999
|
"target-pane": ARG_TARGET_PANE_MULTI,
|
|
876
1000
|
editor: ARG_EDITOR,
|
|
877
1001
|
"always-copy": ARG_ALWAYS_COPY,
|
|
1002
|
+
"log-file": ARG_LOG_FILE,
|
|
1003
|
+
quiet: ARG_QUIET,
|
|
1004
|
+
verbose: ARG_VERBOSE,
|
|
878
1005
|
env: {
|
|
879
1006
|
short: "E",
|
|
880
1007
|
description: "Environment variables to set (e.g., KEY=VALUE)",
|
|
@@ -883,6 +1010,11 @@ const openCommand = define({
|
|
|
883
1010
|
}
|
|
884
1011
|
},
|
|
885
1012
|
async run(ctx) {
|
|
1013
|
+
setupLogger({
|
|
1014
|
+
quiet: Boolean(ctx.values.quiet),
|
|
1015
|
+
verbose: Boolean(ctx.values.verbose),
|
|
1016
|
+
logFile: ctx.values["log-file"]
|
|
1017
|
+
});
|
|
886
1018
|
await runOpenEditorMode({
|
|
887
1019
|
mux: validateMux(ctx.values.mux),
|
|
888
1020
|
targetPanes: normalizeTargetPanes(ctx.values["target-pane"]),
|
|
@@ -895,39 +1027,40 @@ const openCommand = define({
|
|
|
895
1027
|
|
|
896
1028
|
//#endregion
|
|
897
1029
|
//#region src/modes/register.ts
|
|
1030
|
+
const logger$2 = getLogger(["editprompt", "register"]);
|
|
898
1031
|
async function runRegisterMode(options) {
|
|
899
1032
|
if (options.targetPanes.length === 0) {
|
|
900
|
-
|
|
1033
|
+
logger$2.error("--target-pane is required for register command");
|
|
901
1034
|
process.exit(1);
|
|
902
1035
|
}
|
|
903
1036
|
let editorPaneId;
|
|
904
1037
|
if (options.editorPane) editorPaneId = options.editorPane;
|
|
905
1038
|
else if (options.mux === "tmux") {
|
|
906
|
-
editorPaneId = await getCurrentPaneId();
|
|
1039
|
+
editorPaneId = await getCurrentPaneId$1();
|
|
907
1040
|
if (!await isEditorPane(editorPaneId)) {
|
|
908
|
-
|
|
1041
|
+
logger$2.error("Current pane is not an editor pane. Please run this command from an editor pane or specify --editor-pane.");
|
|
909
1042
|
process.exit(1);
|
|
910
1043
|
}
|
|
911
1044
|
} else if (options.mux === "wezterm") {
|
|
912
|
-
editorPaneId = await getCurrentPaneId
|
|
1045
|
+
editorPaneId = await getCurrentPaneId();
|
|
913
1046
|
if (!isEditorPaneFromConf(editorPaneId)) {
|
|
914
|
-
|
|
1047
|
+
logger$2.error("Current pane is not an editor pane. Please run this command from an editor pane or specify --editor-pane.");
|
|
915
1048
|
process.exit(1);
|
|
916
1049
|
}
|
|
917
1050
|
} else {
|
|
918
|
-
|
|
1051
|
+
logger$2.error("Unsupported multiplexer");
|
|
919
1052
|
process.exit(1);
|
|
920
1053
|
}
|
|
921
1054
|
try {
|
|
922
1055
|
let existingPanes = [];
|
|
923
|
-
if (options.mux === "tmux") existingPanes = await getTargetPaneIds(editorPaneId);
|
|
924
|
-
else if (options.mux === "wezterm") existingPanes = await getTargetPaneIds
|
|
1056
|
+
if (options.mux === "tmux") existingPanes = await getTargetPaneIds$1(editorPaneId);
|
|
1057
|
+
else if (options.mux === "wezterm") existingPanes = await getTargetPaneIds(editorPaneId);
|
|
925
1058
|
const mergedTargetPanes = [...new Set([...existingPanes, ...options.targetPanes])];
|
|
926
|
-
if (options.mux === "tmux") await markAsEditorPane(editorPaneId, mergedTargetPanes);
|
|
927
|
-
else if (options.mux === "wezterm") await markAsEditorPane
|
|
928
|
-
|
|
1059
|
+
if (options.mux === "tmux") await markAsEditorPane$1(editorPaneId, mergedTargetPanes);
|
|
1060
|
+
else if (options.mux === "wezterm") await markAsEditorPane(editorPaneId, mergedTargetPanes);
|
|
1061
|
+
logger$2.info(`Editor pane ${editorPaneId} registered with target panes: ${mergedTargetPanes.join(", ")}`);
|
|
929
1062
|
} catch (error) {
|
|
930
|
-
|
|
1063
|
+
logger$2.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
931
1064
|
process.exit(1);
|
|
932
1065
|
}
|
|
933
1066
|
}
|
|
@@ -941,9 +1074,17 @@ const registerCommand = define({
|
|
|
941
1074
|
short: "e",
|
|
942
1075
|
description: "Editor pane ID (defaults to current pane)",
|
|
943
1076
|
type: "string"
|
|
944
|
-
}
|
|
1077
|
+
},
|
|
1078
|
+
"log-file": ARG_LOG_FILE,
|
|
1079
|
+
quiet: ARG_QUIET,
|
|
1080
|
+
verbose: ARG_VERBOSE
|
|
945
1081
|
},
|
|
946
1082
|
async run(ctx) {
|
|
1083
|
+
setupLogger({
|
|
1084
|
+
quiet: Boolean(ctx.values.quiet),
|
|
1085
|
+
verbose: Boolean(ctx.values.verbose),
|
|
1086
|
+
logFile: ctx.values["log-file"]
|
|
1087
|
+
});
|
|
947
1088
|
await runRegisterMode({
|
|
948
1089
|
mux: validateMux(ctx.values.mux),
|
|
949
1090
|
targetPanes: normalizeTargetPanes(ctx.values["target-pane"]),
|
|
@@ -954,68 +1095,72 @@ const registerCommand = define({
|
|
|
954
1095
|
|
|
955
1096
|
//#endregion
|
|
956
1097
|
//#region src/modes/resume.ts
|
|
1098
|
+
const logger$1 = getLogger(["editprompt", "resume"]);
|
|
957
1099
|
async function runResumeMode(targetPane, mux) {
|
|
958
1100
|
if (mux === "wezterm") {
|
|
959
|
-
const currentPaneId
|
|
960
|
-
if (isEditorPaneFromConf(currentPaneId
|
|
961
|
-
|
|
962
|
-
const originalTargetPaneIds = await getTargetPaneIds
|
|
1101
|
+
const currentPaneId = await getCurrentPaneId();
|
|
1102
|
+
if (isEditorPaneFromConf(currentPaneId)) {
|
|
1103
|
+
logger$1.debug("Current pane is an editor pane");
|
|
1104
|
+
const originalTargetPaneIds = await getTargetPaneIds(currentPaneId);
|
|
963
1105
|
if (originalTargetPaneIds.length === 0) {
|
|
964
|
-
|
|
1106
|
+
logger$1.debug("No target pane IDs found for editor pane");
|
|
965
1107
|
process.exit(1);
|
|
966
1108
|
}
|
|
967
1109
|
let focused = false;
|
|
968
|
-
for (const paneId of originalTargetPaneIds) if (await checkPaneExists
|
|
969
|
-
await focusPane
|
|
1110
|
+
for (const paneId of originalTargetPaneIds) if (await checkPaneExists(paneId)) {
|
|
1111
|
+
await focusPane(paneId);
|
|
970
1112
|
focused = true;
|
|
971
1113
|
break;
|
|
972
1114
|
}
|
|
973
1115
|
if (!focused) {
|
|
974
|
-
|
|
1116
|
+
logger$1.debug("All target panes do not exist");
|
|
975
1117
|
process.exit(1);
|
|
976
1118
|
}
|
|
977
1119
|
process.exit(0);
|
|
978
1120
|
}
|
|
979
|
-
|
|
980
|
-
const editorPaneId
|
|
981
|
-
|
|
982
|
-
if (editorPaneId
|
|
983
|
-
|
|
1121
|
+
logger$1.debug("Current pane is not an editor pane");
|
|
1122
|
+
const editorPaneId = await getEditorPaneId(targetPane);
|
|
1123
|
+
logger$1.debug("wezterm editorPaneId: {editorPaneId}", { editorPaneId });
|
|
1124
|
+
if (editorPaneId === "") {
|
|
1125
|
+
logger$1.debug("Editor pane ID not found");
|
|
984
1126
|
process.exit(1);
|
|
985
1127
|
}
|
|
986
|
-
if (!await checkPaneExists
|
|
987
|
-
|
|
988
|
-
await clearEditorPaneId
|
|
1128
|
+
if (!await checkPaneExists(editorPaneId)) {
|
|
1129
|
+
logger$1.debug("Editor pane does not exist");
|
|
1130
|
+
await clearEditorPaneId(targetPane);
|
|
989
1131
|
process.exit(1);
|
|
990
1132
|
}
|
|
991
1133
|
try {
|
|
992
|
-
await focusPane
|
|
1134
|
+
await focusPane(editorPaneId);
|
|
993
1135
|
process.exit(0);
|
|
994
1136
|
} catch (error) {
|
|
995
|
-
|
|
1137
|
+
logger$1.debug("Can't focus editorPaneId: {editorPaneId}, error: {error}", {
|
|
1138
|
+
editorPaneId,
|
|
1139
|
+
error
|
|
1140
|
+
});
|
|
996
1141
|
process.exit(1);
|
|
997
1142
|
}
|
|
998
1143
|
}
|
|
999
|
-
const currentPaneId = await getCurrentPaneId();
|
|
1144
|
+
const currentPaneId = await getCurrentPaneId$1();
|
|
1000
1145
|
if (await isEditorPane(currentPaneId)) {
|
|
1001
|
-
const originalTargetPaneIds = await getTargetPaneIds(currentPaneId);
|
|
1146
|
+
const originalTargetPaneIds = await getTargetPaneIds$1(currentPaneId);
|
|
1002
1147
|
if (originalTargetPaneIds.length === 0) process.exit(1);
|
|
1003
1148
|
let focused = false;
|
|
1004
|
-
for (const paneId of originalTargetPaneIds) if (await checkPaneExists(paneId)) {
|
|
1005
|
-
await focusPane(paneId);
|
|
1149
|
+
for (const paneId of originalTargetPaneIds) if (await checkPaneExists$1(paneId)) {
|
|
1150
|
+
await focusPane$1(paneId);
|
|
1006
1151
|
focused = true;
|
|
1007
1152
|
break;
|
|
1008
1153
|
}
|
|
1009
1154
|
if (!focused) process.exit(1);
|
|
1010
1155
|
process.exit(0);
|
|
1011
1156
|
}
|
|
1012
|
-
const editorPaneId = await getEditorPaneId(targetPane);
|
|
1157
|
+
const editorPaneId = await getEditorPaneId$1(targetPane);
|
|
1013
1158
|
if (editorPaneId === "") process.exit(1);
|
|
1014
|
-
if (!await checkPaneExists(editorPaneId)) {
|
|
1015
|
-
await clearEditorPaneId(targetPane);
|
|
1159
|
+
if (!await checkPaneExists$1(editorPaneId)) {
|
|
1160
|
+
await clearEditorPaneId$1(targetPane);
|
|
1016
1161
|
process.exit(1);
|
|
1017
1162
|
}
|
|
1018
|
-
await focusPane(editorPaneId);
|
|
1163
|
+
await focusPane$1(editorPaneId);
|
|
1019
1164
|
process.exit(0);
|
|
1020
1165
|
}
|
|
1021
1166
|
const resumeCommand = define({
|
|
@@ -1023,15 +1168,24 @@ const resumeCommand = define({
|
|
|
1023
1168
|
description: "Resume existing editor pane or focus back to target pane",
|
|
1024
1169
|
args: {
|
|
1025
1170
|
mux: ARG_MUX,
|
|
1026
|
-
"target-pane": ARG_TARGET_PANE_SINGLE
|
|
1171
|
+
"target-pane": ARG_TARGET_PANE_SINGLE,
|
|
1172
|
+
"log-file": ARG_LOG_FILE,
|
|
1173
|
+
quiet: ARG_QUIET,
|
|
1174
|
+
verbose: ARG_VERBOSE
|
|
1027
1175
|
},
|
|
1028
1176
|
async run(ctx) {
|
|
1177
|
+
setupLogger({
|
|
1178
|
+
quiet: Boolean(ctx.values.quiet),
|
|
1179
|
+
verbose: Boolean(ctx.values.verbose),
|
|
1180
|
+
logFile: ctx.values["log-file"]
|
|
1181
|
+
});
|
|
1029
1182
|
await runResumeMode(validateTargetPane(ctx.values["target-pane"], "resume"), validateMux(ctx.values.mux));
|
|
1030
1183
|
}
|
|
1031
1184
|
});
|
|
1032
1185
|
|
|
1033
1186
|
//#endregion
|
|
1034
1187
|
//#region src/modes/stash.ts
|
|
1188
|
+
const logger = getLogger(["editprompt", "stash"]);
|
|
1035
1189
|
function getStashKey(mux, targetPaneId) {
|
|
1036
1190
|
return `${mux}.targetPane.pane_${targetPaneId}.stash`;
|
|
1037
1191
|
}
|
|
@@ -1078,21 +1232,21 @@ async function getTargetPaneForStash() {
|
|
|
1078
1232
|
let currentPaneId;
|
|
1079
1233
|
let isEditor;
|
|
1080
1234
|
if (config.mux === "tmux") {
|
|
1081
|
-
currentPaneId = await getCurrentPaneId();
|
|
1235
|
+
currentPaneId = await getCurrentPaneId$1();
|
|
1082
1236
|
isEditor = await isEditorPane(currentPaneId);
|
|
1083
1237
|
} else {
|
|
1084
|
-
currentPaneId = await getCurrentPaneId
|
|
1238
|
+
currentPaneId = await getCurrentPaneId();
|
|
1085
1239
|
isEditor = isEditorPaneFromConf(currentPaneId);
|
|
1086
1240
|
}
|
|
1087
1241
|
if (!isEditor) {
|
|
1088
|
-
|
|
1242
|
+
logger.error("Current pane is not an editor pane");
|
|
1089
1243
|
process.exit(1);
|
|
1090
1244
|
}
|
|
1091
1245
|
let targetPanes;
|
|
1092
|
-
if (config.mux === "tmux") targetPanes = await getTargetPaneIds(currentPaneId);
|
|
1093
|
-
else targetPanes = await getTargetPaneIds
|
|
1246
|
+
if (config.mux === "tmux") targetPanes = await getTargetPaneIds$1(currentPaneId);
|
|
1247
|
+
else targetPanes = await getTargetPaneIds(currentPaneId);
|
|
1094
1248
|
if (targetPanes.length === 0) {
|
|
1095
|
-
|
|
1249
|
+
logger.error("No target panes registered for this editor pane");
|
|
1096
1250
|
process.exit(1);
|
|
1097
1251
|
}
|
|
1098
1252
|
return {
|
|
@@ -1103,13 +1257,13 @@ async function getTargetPaneForStash() {
|
|
|
1103
1257
|
async function runPush(rest, positionals) {
|
|
1104
1258
|
const rawContent = extractRawContent(rest, positionals);
|
|
1105
1259
|
if (rawContent === void 0 || rawContent.trim() === "") {
|
|
1106
|
-
|
|
1107
|
-
|
|
1260
|
+
logger.error("Content is required for stash push");
|
|
1261
|
+
logger.error("Usage: editprompt stash push -- \"your content\"");
|
|
1108
1262
|
process.exit(1);
|
|
1109
1263
|
}
|
|
1110
1264
|
const { mux, targetPaneId } = await getTargetPaneForStash();
|
|
1111
1265
|
const key = await pushStash(mux, targetPaneId, rawContent);
|
|
1112
|
-
|
|
1266
|
+
logger.info("Stashed with key: {key}", { key });
|
|
1113
1267
|
}
|
|
1114
1268
|
async function runList() {
|
|
1115
1269
|
const { mux, targetPaneId } = await getTargetPaneForStash();
|
|
@@ -1120,8 +1274,8 @@ async function runApply(key) {
|
|
|
1120
1274
|
const { mux, targetPaneId } = await getTargetPaneForStash();
|
|
1121
1275
|
const content = getStashContent(mux, targetPaneId, key);
|
|
1122
1276
|
if (content === "") {
|
|
1123
|
-
if (key)
|
|
1124
|
-
else
|
|
1277
|
+
if (key) logger.error("No stash entry found with key: {key}", { key });
|
|
1278
|
+
else logger.error("No stash entries found");
|
|
1125
1279
|
process.exit(1);
|
|
1126
1280
|
}
|
|
1127
1281
|
process.stdout.write(content);
|
|
@@ -1129,18 +1283,18 @@ async function runApply(key) {
|
|
|
1129
1283
|
async function runDrop(key) {
|
|
1130
1284
|
const { mux, targetPaneId } = await getTargetPaneForStash();
|
|
1131
1285
|
if (!dropStash(mux, targetPaneId, key)) {
|
|
1132
|
-
if (key)
|
|
1133
|
-
else
|
|
1286
|
+
if (key) logger.error("No stash entry found with key: {key}", { key });
|
|
1287
|
+
else logger.error("No stash entries found");
|
|
1134
1288
|
process.exit(1);
|
|
1135
1289
|
}
|
|
1136
|
-
|
|
1290
|
+
logger.info("Stash entry dropped");
|
|
1137
1291
|
}
|
|
1138
1292
|
async function runPop(key) {
|
|
1139
1293
|
const { mux, targetPaneId } = await getTargetPaneForStash();
|
|
1140
1294
|
const content = getStashContent(mux, targetPaneId, key);
|
|
1141
1295
|
if (content === "") {
|
|
1142
|
-
if (key)
|
|
1143
|
-
else
|
|
1296
|
+
if (key) logger.error("No stash entry found with key: {key}", { key });
|
|
1297
|
+
else logger.error("No stash entries found");
|
|
1144
1298
|
process.exit(1);
|
|
1145
1299
|
}
|
|
1146
1300
|
process.stdout.write(content);
|
|
@@ -1169,8 +1323,17 @@ function parseKeyOption(args) {
|
|
|
1169
1323
|
const stashCommand = define({
|
|
1170
1324
|
name: "stash",
|
|
1171
1325
|
description: "Stash prompts for later use",
|
|
1172
|
-
args: {
|
|
1326
|
+
args: {
|
|
1327
|
+
"log-file": ARG_LOG_FILE,
|
|
1328
|
+
quiet: ARG_QUIET,
|
|
1329
|
+
verbose: ARG_VERBOSE
|
|
1330
|
+
},
|
|
1173
1331
|
async run(ctx) {
|
|
1332
|
+
setupLogger({
|
|
1333
|
+
quiet: Boolean(ctx.values.quiet),
|
|
1334
|
+
verbose: Boolean(ctx.values.verbose),
|
|
1335
|
+
logFile: ctx.values["log-file"]
|
|
1336
|
+
});
|
|
1174
1337
|
const args = ctx.positionals.slice(1);
|
|
1175
1338
|
if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
|
|
1176
1339
|
showHelp();
|
|
@@ -1195,8 +1358,8 @@ const stashCommand = define({
|
|
|
1195
1358
|
await runPop(parseKeyOption(subArgs));
|
|
1196
1359
|
break;
|
|
1197
1360
|
default:
|
|
1198
|
-
|
|
1199
|
-
|
|
1361
|
+
logger.error("Unknown subcommand '{subcommand}'", { subcommand });
|
|
1362
|
+
logger.error("");
|
|
1200
1363
|
showHelp();
|
|
1201
1364
|
process.exit(1);
|
|
1202
1365
|
}
|
|
@@ -1210,16 +1373,18 @@ await cli(process.argv.slice(2), {
|
|
|
1210
1373
|
description: "A CLI tool that lets you write prompts for CLI tools using your favorite text editor",
|
|
1211
1374
|
args: {},
|
|
1212
1375
|
async run() {
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1376
|
+
setupLogger();
|
|
1377
|
+
const logger = getLogger(["editprompt"]);
|
|
1378
|
+
logger.error("Subcommand is required");
|
|
1379
|
+
logger.error("");
|
|
1380
|
+
logger.error("Migration guide from old to new syntax:");
|
|
1381
|
+
logger.error(" editprompt → editprompt open");
|
|
1382
|
+
logger.error(" editprompt --resume → editprompt resume");
|
|
1383
|
+
logger.error(" editprompt -- \"text\" → editprompt input \"text\"");
|
|
1384
|
+
logger.error(" editprompt --quote → editprompt collect");
|
|
1385
|
+
logger.error(" editprompt --capture → editprompt dump");
|
|
1386
|
+
logger.error("");
|
|
1387
|
+
logger.error("For details: https://github.com/eetann/editprompt/?tab=readme-ov-file");
|
|
1223
1388
|
process.exit(1);
|
|
1224
1389
|
}
|
|
1225
1390
|
}, {
|
package/package.json
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "editprompt",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"author": "eetann",
|
|
3
|
+
"version": "1.3.0",
|
|
5
4
|
"description": "A CLI tool that lets you write prompts for CLI tools using your favorite text editor",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"clipboard",
|
|
8
|
+
"command-line",
|
|
9
|
+
"editor",
|
|
10
|
+
"prompt",
|
|
11
|
+
"text-editor",
|
|
12
|
+
"tmux"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/eetann/editprompt",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/eetann/editprompt/issues"
|
|
17
|
+
},
|
|
6
18
|
"license": "MIT",
|
|
19
|
+
"author": "eetann",
|
|
7
20
|
"repository": {
|
|
8
21
|
"type": "git",
|
|
9
22
|
"url": "https://github.com/eetann/editprompt.git"
|
|
10
23
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"url": "https://github.com/eetann/editprompt/issues"
|
|
24
|
+
"bin": {
|
|
25
|
+
"editprompt": "./dist/index.js"
|
|
14
26
|
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"editor",
|
|
18
|
-
"prompt",
|
|
19
|
-
"tmux",
|
|
20
|
-
"clipboard",
|
|
21
|
-
"command-line",
|
|
22
|
-
"text-editor"
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
23
29
|
],
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
26
|
-
},
|
|
27
30
|
"type": "module",
|
|
28
|
-
"files": ["dist"],
|
|
29
31
|
"main": "./dist/index.js",
|
|
30
32
|
"module": "./dist/index.js",
|
|
31
33
|
"types": "./dist/index.d.ts",
|
|
@@ -33,31 +35,35 @@
|
|
|
33
35
|
".": "./dist/index.js",
|
|
34
36
|
"./package.json": "./package.json"
|
|
35
37
|
},
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
38
40
|
},
|
|
39
41
|
"scripts": {
|
|
40
42
|
"build": "tsdown",
|
|
41
43
|
"dev": "tsdown --watch",
|
|
42
|
-
"lint": "
|
|
43
|
-
"
|
|
44
|
+
"lint": "oxlint --type-aware && oxfmt --check",
|
|
45
|
+
"lint:fix": "oxlint --type-aware --fix && oxfmt",
|
|
46
|
+
"format": "oxfmt --write .",
|
|
44
47
|
"typecheck": "tsgo --noEmit",
|
|
45
48
|
"release": "bun run lint && bun run typecheck && bun run test && bun run build && bumpp",
|
|
46
49
|
"test": "bun test",
|
|
47
50
|
"test:watch": "bun test --watch"
|
|
48
51
|
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@logtape/logtape": "^2.0.2",
|
|
54
|
+
"clipboardy": "^4.0.0",
|
|
55
|
+
"conf": "^15.0.2",
|
|
56
|
+
"gunshi": "^0.29.2"
|
|
57
|
+
},
|
|
49
58
|
"devDependencies": {
|
|
50
|
-
"@biomejs/biome": "1.9.4",
|
|
51
59
|
"@types/bun": "^1.3.2",
|
|
52
60
|
"@types/node": "^24.10.1",
|
|
53
61
|
"@typescript/native-preview": "^7.0.0-dev.20251119.1",
|
|
54
62
|
"bumpp": "^10.3.1",
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
"conf": "^15.0.2",
|
|
60
|
-
"gunshi": "v0.27.0-beta.3"
|
|
63
|
+
"oxfmt": "^0.35.0",
|
|
64
|
+
"oxlint": "^1.50.0",
|
|
65
|
+
"oxlint-tsgolint": "^0.15.0",
|
|
66
|
+
"tsdown": "^0.20.3"
|
|
61
67
|
},
|
|
62
68
|
"peerDependencies": {
|
|
63
69
|
"typescript": "^5.8.3"
|