editprompt 0.5.1 → 0.6.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 +131 -22
- package/dist/index.js +262 -40
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -49,13 +49,25 @@ editprompt
|
|
|
49
49
|
|
|
50
50
|
### 🖥️ Tmux Integration
|
|
51
51
|
|
|
52
|
-
**Split window version:**
|
|
52
|
+
**Split window version (with pane resume):**
|
|
53
53
|
```tmux
|
|
54
|
-
bind -n M-q run-shell '
|
|
55
|
-
-
|
|
56
|
-
|
|
54
|
+
bind -n M-q run-shell '\
|
|
55
|
+
editprompt --resume --target-pane #{pane_id} || \
|
|
56
|
+
tmux split-window -v -l 10 -c "#{pane_current_path}" \
|
|
57
|
+
"editprompt --editor nvim --always-copy --target-pane #{pane_id}"'
|
|
57
58
|
```
|
|
58
59
|
|
|
60
|
+
**How it works:**
|
|
61
|
+
- **First time**: Creates a new editor pane if one doesn't exist
|
|
62
|
+
- **Subsequent times**: Focuses the existing editor pane instead of creating a new one
|
|
63
|
+
- **Bidirectional**: Pressing the same keybinding from within the editor pane returns you to the original target pane
|
|
64
|
+
|
|
65
|
+
This allows you to toggle between your target pane and editor pane using the same keybinding (`M-q`).
|
|
66
|
+
|
|
67
|
+
**Benefits:**
|
|
68
|
+
- Prevents pane proliferation and keeps your window management simple
|
|
69
|
+
- Switch between your work pane and editor pane while preserving your editing content
|
|
70
|
+
|
|
59
71
|
**Popup version:**
|
|
60
72
|
```tmux
|
|
61
73
|
bind -n M-q run-shell 'tmux display-popup -E \
|
|
@@ -66,34 +78,61 @@ bind -n M-q run-shell 'tmux display-popup -E \
|
|
|
66
78
|
|
|
67
79
|
|
|
68
80
|
### 🖼️ WezTerm Integration
|
|
81
|
+
|
|
69
82
|
```lua
|
|
70
83
|
{
|
|
71
84
|
key = "q",
|
|
72
85
|
mods = "OPT",
|
|
73
86
|
action = wezterm.action_callback(function(window, pane)
|
|
74
87
|
local target_pane_id = tostring(pane:pane_id())
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
|
|
89
|
+
-- Try to resume existing editor pane
|
|
90
|
+
local success, stdout, stderr = wezterm.run_child_process({
|
|
91
|
+
"/bin/zsh",
|
|
92
|
+
"-lc",
|
|
93
|
+
string.format(
|
|
94
|
+
"editprompt --resume --mux wezterm --target-pane %s",
|
|
95
|
+
target_pane_id
|
|
96
|
+
),
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
-- If resume failed, create new editor pane
|
|
100
|
+
if not success then
|
|
83
101
|
window:perform_action(
|
|
84
|
-
act.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
act.SplitPane({
|
|
103
|
+
direction = "Down",
|
|
104
|
+
size = { Cells = 10 },
|
|
105
|
+
command = {
|
|
106
|
+
args = {
|
|
107
|
+
"/bin/zsh",
|
|
108
|
+
"-lc",
|
|
109
|
+
string.format(
|
|
110
|
+
"editprompt --editor nvim --always-copy --mux wezterm --target-pane %s",
|
|
111
|
+
target_pane_id
|
|
112
|
+
),
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
pane
|
|
91
117
|
)
|
|
92
|
-
end
|
|
118
|
+
end
|
|
93
119
|
end),
|
|
94
120
|
},
|
|
95
121
|
```
|
|
96
122
|
|
|
123
|
+
**How it works:**
|
|
124
|
+
- **First time**: Creates a new editor pane if one doesn't exist
|
|
125
|
+
- **Subsequent times**: Focuses the existing editor pane instead of creating a new one
|
|
126
|
+
- **Bidirectional**: Pressing the same keybinding from within the editor pane returns you to the original target pane
|
|
127
|
+
|
|
128
|
+
This allows you to toggle between your target pane and editor pane using the same keybinding (`OPT-q`).
|
|
129
|
+
|
|
130
|
+
**Benefits:**
|
|
131
|
+
- Prevents pane proliferation and keeps your window management simple
|
|
132
|
+
- Switch between your work pane and editor pane while preserving your editing content
|
|
133
|
+
|
|
134
|
+
**Note:** The `-lc` flag ensures your shell loads the full login environment, making `editprompt` available in your PATH.
|
|
135
|
+
|
|
97
136
|
### 💡 Basic Usage
|
|
98
137
|
|
|
99
138
|
```bash
|
|
@@ -120,7 +159,7 @@ While editprompt is running, you can send content to the target pane or clipboar
|
|
|
120
159
|
|
|
121
160
|
```bash
|
|
122
161
|
# Run this command from within your editor session
|
|
123
|
-
editprompt "your content here"
|
|
162
|
+
editprompt -- "your content here"
|
|
124
163
|
```
|
|
125
164
|
|
|
126
165
|
This sends the content to the target pane (or clipboard) while keeping your editor open, so you can continue editing and send multiple times.
|
|
@@ -140,7 +179,7 @@ if vim.env.EDITPROMPT then
|
|
|
140
179
|
|
|
141
180
|
-- Execute editprompt command
|
|
142
181
|
vim.system(
|
|
143
|
-
{ "editprompt", content },
|
|
182
|
+
{ "editprompt", "--", content },
|
|
144
183
|
{ text = true },
|
|
145
184
|
function(obj)
|
|
146
185
|
vim.schedule(function()
|
|
@@ -233,6 +272,76 @@ bun test
|
|
|
233
272
|
bun run dev
|
|
234
273
|
```
|
|
235
274
|
|
|
275
|
+
### 💻 Testing During Development
|
|
276
|
+
|
|
277
|
+
When developing, you can test the built `dist/index.js` directly:
|
|
278
|
+
|
|
279
|
+
#### Neovim Configuration
|
|
280
|
+
|
|
281
|
+
```diff
|
|
282
|
+
- { "editprompt", "--", content },
|
|
283
|
+
+ { "node", vim.fn.expand("~/path/to/editprompt/dist/index.js"), "--", content },
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### WezTerm Configuration
|
|
287
|
+
|
|
288
|
+
```lua
|
|
289
|
+
-- In your wezterm.lua
|
|
290
|
+
local editprompt_cmd = "node " .. os.getenv("HOME") .. "/path/to/editprompt/dist/index.js"
|
|
291
|
+
|
|
292
|
+
{
|
|
293
|
+
key = "e",
|
|
294
|
+
mods = "OPT",
|
|
295
|
+
action = wezterm.action_callback(function(window, pane)
|
|
296
|
+
local target_pane_id = tostring(pane:pane_id())
|
|
297
|
+
|
|
298
|
+
local success, stdout, stderr = wezterm.run_child_process({
|
|
299
|
+
"/bin/zsh",
|
|
300
|
+
"-lc",
|
|
301
|
+
string.format(
|
|
302
|
+
"%s --resume --mux wezterm --target-pane %s",
|
|
303
|
+
editprompt_cmd,
|
|
304
|
+
target_pane_id
|
|
305
|
+
),
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
if not success then
|
|
309
|
+
window:perform_action(
|
|
310
|
+
act.SplitPane({
|
|
311
|
+
-- ...
|
|
312
|
+
command = {
|
|
313
|
+
args = {
|
|
314
|
+
"/bin/zsh",
|
|
315
|
+
"-lc",
|
|
316
|
+
string.format(
|
|
317
|
+
"%s --editor nvim --always-copy --mux wezterm --target-pane %s",
|
|
318
|
+
editprompt_cmd,
|
|
319
|
+
target_pane_id
|
|
320
|
+
),
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
}),
|
|
324
|
+
pane
|
|
325
|
+
)
|
|
326
|
+
end
|
|
327
|
+
end),
|
|
328
|
+
},
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### tmux Configuration
|
|
332
|
+
|
|
333
|
+
```tmux
|
|
334
|
+
# In your .tmux.conf
|
|
335
|
+
set-option -g @editprompt-cmd "node ~/path/to/editprompt/dist/index.js"
|
|
336
|
+
|
|
337
|
+
bind-key -n M-q run-shell '\
|
|
338
|
+
#{@editprompt-cmd} --resume --target-pane #{pane_id} || \
|
|
339
|
+
tmux split-window -v -l 10 -c "#{pane_current_path}" \
|
|
340
|
+
"#{@editprompt-cmd} --editor nvim --always-copy --target-pane #{pane_id}"'
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
This allows you to make changes, run `bun run build`, and test immediately without reinstalling globally.
|
|
344
|
+
|
|
236
345
|
## 🔍 Technical Details
|
|
237
346
|
|
|
238
347
|
### 🔄 Fallback Strategy
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,11 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
|
+
import Conf from "conf";
|
|
8
9
|
import clipboardy from "clipboardy";
|
|
9
10
|
|
|
10
11
|
//#region package.json
|
|
11
|
-
var version = "0.
|
|
12
|
+
var version = "0.6.0";
|
|
12
13
|
|
|
13
14
|
//#endregion
|
|
14
15
|
//#region src/config/constants.ts
|
|
@@ -37,8 +38,7 @@ function parseEnvVars(envStrings) {
|
|
|
37
38
|
for (const envString of envStrings) {
|
|
38
39
|
const [key, ...valueParts] = envString.split("=");
|
|
39
40
|
if (!key || valueParts.length === 0) throw new Error(`Invalid environment variable format: ${envString}`);
|
|
40
|
-
|
|
41
|
-
result[key] = value;
|
|
41
|
+
result[key] = valueParts.join("=");
|
|
42
42
|
}
|
|
43
43
|
return result;
|
|
44
44
|
}
|
|
@@ -47,19 +47,12 @@ function parseEnvVars(envStrings) {
|
|
|
47
47
|
//#region src/utils/tempFile.ts
|
|
48
48
|
function getFormattedDateTime() {
|
|
49
49
|
const now = /* @__PURE__ */ new Date();
|
|
50
|
-
|
|
51
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
52
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
53
|
-
const hours = String(now.getHours()).padStart(2, "0");
|
|
54
|
-
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
55
|
-
const seconds = String(now.getSeconds()).padStart(2, "0");
|
|
56
|
-
return `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
50
|
+
return `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}${String(now.getSeconds()).padStart(2, "0")}`;
|
|
57
51
|
}
|
|
58
52
|
async function createTempFile() {
|
|
59
53
|
const tempDir = join(tmpdir(), "editprompt-prompts");
|
|
60
54
|
await mkdir(tempDir, { recursive: true });
|
|
61
|
-
const
|
|
62
|
-
const filePath = join(tempDir, fileName);
|
|
55
|
+
const filePath = join(tempDir, `${TEMP_FILE_PREFIX}${getFormattedDateTime()}${TEMP_FILE_EXTENSION}`);
|
|
63
56
|
await writeFile(filePath, "", "utf-8");
|
|
64
57
|
return filePath;
|
|
65
58
|
}
|
|
@@ -89,18 +82,17 @@ async function launchEditor(editor, filePath, envVars, sendConfig) {
|
|
|
89
82
|
env: processEnv
|
|
90
83
|
});
|
|
91
84
|
editorProcess.on("error", (error) => {
|
|
92
|
-
reject(new Error(`Failed to launch editor: ${error.message}`));
|
|
85
|
+
reject(/* @__PURE__ */ new Error(`Failed to launch editor: ${error.message}`));
|
|
93
86
|
});
|
|
94
87
|
editorProcess.on("exit", (code) => {
|
|
95
88
|
if (code === 0) resolve();
|
|
96
|
-
else reject(new Error(`Editor exited with code: ${code}`));
|
|
89
|
+
else reject(/* @__PURE__ */ new Error(`Editor exited with code: ${code}`));
|
|
97
90
|
});
|
|
98
91
|
});
|
|
99
92
|
}
|
|
100
93
|
async function readFileContent(filePath) {
|
|
101
94
|
try {
|
|
102
|
-
|
|
103
|
-
return processContent(content);
|
|
95
|
+
return processContent(await readFile(filePath, "utf-8"));
|
|
104
96
|
} catch (error) {
|
|
105
97
|
throw new Error(`Failed to read file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
106
98
|
}
|
|
@@ -111,14 +103,139 @@ async function openEditorAndGetContent(editorOption, envVars, sendConfig) {
|
|
|
111
103
|
const parsedEnvVars = parseEnvVars(envVars);
|
|
112
104
|
try {
|
|
113
105
|
await launchEditor(editor, tempFilePath, parsedEnvVars, sendConfig);
|
|
114
|
-
|
|
115
|
-
return content;
|
|
106
|
+
return await readFileContent(tempFilePath);
|
|
116
107
|
} catch (error) {
|
|
117
108
|
if (error instanceof Error) throw error;
|
|
118
109
|
throw new Error("An unknown error occurred");
|
|
119
110
|
}
|
|
120
111
|
}
|
|
121
112
|
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/modules/tmux.ts
|
|
115
|
+
const execAsync$2 = promisify(exec);
|
|
116
|
+
async function getCurrentPaneId() {
|
|
117
|
+
const { stdout } = await execAsync$2("tmux display-message -p \"#{pane_id}\"");
|
|
118
|
+
return stdout.trim();
|
|
119
|
+
}
|
|
120
|
+
async function saveEditorPaneId(targetPaneId, editorPaneId) {
|
|
121
|
+
await execAsync$2(`tmux set-option -pt '${targetPaneId}' @editprompt_editor_pane '${editorPaneId}'`);
|
|
122
|
+
}
|
|
123
|
+
async function clearEditorPaneId(targetPaneId) {
|
|
124
|
+
await execAsync$2(`tmux set-option -pt '${targetPaneId}' @editprompt_editor_pane ""`);
|
|
125
|
+
}
|
|
126
|
+
async function getEditorPaneId(targetPaneId) {
|
|
127
|
+
try {
|
|
128
|
+
const { stdout } = await execAsync$2(`tmux show -pt '${targetPaneId}' -v @editprompt_editor_pane`);
|
|
129
|
+
return stdout.trim();
|
|
130
|
+
} catch {
|
|
131
|
+
return "";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function checkPaneExists(paneId) {
|
|
135
|
+
try {
|
|
136
|
+
const { stdout } = await execAsync$2("tmux list-panes -a -F \"#{pane_id}\"");
|
|
137
|
+
return stdout.split("\n").map((id) => id.trim()).includes(paneId);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function focusPane(paneId) {
|
|
143
|
+
await execAsync$2(`tmux select-pane -t '${paneId}'`);
|
|
144
|
+
}
|
|
145
|
+
async function markAsEditorPane(editorPaneId, targetPaneId) {
|
|
146
|
+
await execAsync$2(`tmux set-option -pt '${editorPaneId}' @editprompt_is_editor 1`);
|
|
147
|
+
await execAsync$2(`tmux set-option -pt '${editorPaneId}' @editprompt_target_pane '${targetPaneId}'`);
|
|
148
|
+
}
|
|
149
|
+
async function getTargetPaneId(editorPaneId) {
|
|
150
|
+
try {
|
|
151
|
+
const { stdout } = await execAsync$2(`tmux show -pt '${editorPaneId}' -v @editprompt_target_pane`);
|
|
152
|
+
return stdout.trim();
|
|
153
|
+
} catch {
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function isEditorPane(paneId) {
|
|
158
|
+
try {
|
|
159
|
+
const { stdout } = await execAsync$2(`tmux show -pt '${paneId}' -v @editprompt_is_editor`);
|
|
160
|
+
return stdout.trim() === "1";
|
|
161
|
+
} catch {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/modules/wezterm.ts
|
|
168
|
+
const execAsync$1 = promisify(exec);
|
|
169
|
+
const conf = new Conf({ projectName: "editprompt" });
|
|
170
|
+
async function getCurrentPaneId$1() {
|
|
171
|
+
try {
|
|
172
|
+
const { stdout } = await execAsync$1("wezterm cli list --format json");
|
|
173
|
+
const activePane = JSON.parse(stdout).find((pane) => pane.is_active === true);
|
|
174
|
+
return String(activePane?.pane_id);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.log(error);
|
|
177
|
+
return "";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function checkPaneExists$1(paneId) {
|
|
181
|
+
try {
|
|
182
|
+
const { stdout } = await execAsync$1("wezterm cli list --format json");
|
|
183
|
+
console.log(stdout);
|
|
184
|
+
return JSON.parse(stdout).some((pane) => String(pane.pane_id) === paneId);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.log(error);
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function getEditorPaneId$1(targetPaneId) {
|
|
191
|
+
try {
|
|
192
|
+
const data = conf.get(`wezterm.targetPane.pane_${targetPaneId}`);
|
|
193
|
+
if (typeof data === "object" && data !== null && "editorPaneId" in data) return String(data.editorPaneId);
|
|
194
|
+
return "";
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.log(error);
|
|
197
|
+
return "";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function clearEditorPaneId$1(targetPaneId) {
|
|
201
|
+
try {
|
|
202
|
+
const editorPaneId = await getEditorPaneId$1(targetPaneId);
|
|
203
|
+
conf.delete(`wezterm.targetPane.pane_${targetPaneId}`);
|
|
204
|
+
if (editorPaneId) conf.delete(`wezterm.editorPane.pane_${editorPaneId}`);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.log(error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function focusPane$1(paneId) {
|
|
210
|
+
await execAsync$1(`wezterm cli activate-pane --pane-id '${paneId}'`);
|
|
211
|
+
}
|
|
212
|
+
async function markAsEditorPane$1(editorPaneId, targetPaneId) {
|
|
213
|
+
try {
|
|
214
|
+
conf.set(`wezterm.targetPane.pane_${targetPaneId}`, { editorPaneId });
|
|
215
|
+
conf.set(`wezterm.editorPane.pane_${editorPaneId}`, { targetPaneId });
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.log(error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function getTargetPaneId$1(editorPaneId) {
|
|
221
|
+
try {
|
|
222
|
+
const data = conf.get(`wezterm.editorPane.pane_${editorPaneId}`);
|
|
223
|
+
if (typeof data === "object" && data !== null && "targetPaneId" in data) return String(data.targetPaneId);
|
|
224
|
+
return "";
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.log(error);
|
|
227
|
+
return "";
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function isEditorPaneFromConf(paneId) {
|
|
231
|
+
try {
|
|
232
|
+
return conf.has(`wezterm.editorPane.pane_${paneId}`);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.log(error);
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
122
239
|
//#endregion
|
|
123
240
|
//#region src/modules/process.ts
|
|
124
241
|
const execAsync = promisify(exec);
|
|
@@ -182,23 +299,98 @@ async function handleContentDelivery(content, mux, targetPane, alwaysCopy) {
|
|
|
182
299
|
//#endregion
|
|
183
300
|
//#region src/modes/openEditor.ts
|
|
184
301
|
async function runOpenEditorMode(options) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
302
|
+
if (options.targetPane && options.mux === "tmux") try {
|
|
303
|
+
const currentPaneId = await getCurrentPaneId();
|
|
304
|
+
await saveEditorPaneId(options.targetPane, currentPaneId);
|
|
305
|
+
await markAsEditorPane(currentPaneId, options.targetPane);
|
|
306
|
+
} catch {}
|
|
307
|
+
else if (options.targetPane && options.mux === "wezterm") try {
|
|
308
|
+
const currentPaneId = await getCurrentPaneId$1();
|
|
309
|
+
await markAsEditorPane$1(currentPaneId, options.targetPane);
|
|
310
|
+
} catch {}
|
|
196
311
|
try {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
312
|
+
const sendConfig = {
|
|
313
|
+
targetPane: options.targetPane,
|
|
314
|
+
mux: options.mux,
|
|
315
|
+
alwaysCopy: options.alwaysCopy
|
|
316
|
+
};
|
|
317
|
+
console.log("Opening editor...");
|
|
318
|
+
const content = await openEditorAndGetContent(options.editor, options.env, sendConfig);
|
|
319
|
+
if (!content) {
|
|
320
|
+
console.log("No content entered. Exiting.");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
await handleContentDelivery(content, options.mux, options.targetPane, options.alwaysCopy);
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
} finally {
|
|
330
|
+
if (options.targetPane && options.mux === "tmux") try {
|
|
331
|
+
await clearEditorPaneId(options.targetPane);
|
|
332
|
+
} catch {}
|
|
333
|
+
else if (options.targetPane && options.mux === "wezterm") try {
|
|
334
|
+
await clearEditorPaneId$1(options.targetPane);
|
|
335
|
+
} catch {}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/modes/resume.ts
|
|
341
|
+
async function runResumeMode(targetPane, mux) {
|
|
342
|
+
if (mux === "wezterm") {
|
|
343
|
+
const currentPaneId$1 = await getCurrentPaneId$1();
|
|
344
|
+
if (isEditorPaneFromConf(currentPaneId$1)) {
|
|
345
|
+
console.log("isEditor");
|
|
346
|
+
const originalTargetPaneId = await getTargetPaneId$1(currentPaneId$1);
|
|
347
|
+
if (!originalTargetPaneId) {
|
|
348
|
+
console.log("Not found originalTargetPaneId");
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
if (!await checkPaneExists$1(originalTargetPaneId)) {
|
|
352
|
+
console.log("Not exist originalTargetPaneId");
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
await focusPane$1(originalTargetPaneId);
|
|
356
|
+
process.exit(0);
|
|
357
|
+
}
|
|
358
|
+
console.log("not isEditor");
|
|
359
|
+
const editorPaneId$1 = await getEditorPaneId$1(targetPane);
|
|
360
|
+
console.log(`wezterm editorPaneId: ${editorPaneId$1}`);
|
|
361
|
+
if (editorPaneId$1 === "") {
|
|
362
|
+
console.log("Not found editorPaneId");
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
if (!await checkPaneExists$1(editorPaneId$1)) {
|
|
366
|
+
console.log("Not exist editorPaneId");
|
|
367
|
+
await clearEditorPaneId$1(targetPane);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
try {
|
|
371
|
+
await focusPane$1(editorPaneId$1);
|
|
372
|
+
process.exit(0);
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.log(`Can't focus editorPaneId: ${editorPaneId$1}\nerror: ${error}`);
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const currentPaneId = await getCurrentPaneId();
|
|
379
|
+
if (await isEditorPane(currentPaneId)) {
|
|
380
|
+
const originalTargetPaneId = await getTargetPaneId(currentPaneId);
|
|
381
|
+
if (!originalTargetPaneId) process.exit(1);
|
|
382
|
+
if (!await checkPaneExists(originalTargetPaneId)) process.exit(1);
|
|
383
|
+
await focusPane(originalTargetPaneId);
|
|
384
|
+
process.exit(0);
|
|
385
|
+
}
|
|
386
|
+
const editorPaneId = await getEditorPaneId(targetPane);
|
|
387
|
+
if (editorPaneId === "") process.exit(1);
|
|
388
|
+
if (!await checkPaneExists(editorPaneId)) {
|
|
389
|
+
await clearEditorPaneId(targetPane);
|
|
200
390
|
process.exit(1);
|
|
201
391
|
}
|
|
392
|
+
await focusPane(editorPaneId);
|
|
393
|
+
process.exit(0);
|
|
202
394
|
}
|
|
203
395
|
|
|
204
396
|
//#endregion
|
|
@@ -208,12 +400,10 @@ function readSendConfig() {
|
|
|
208
400
|
const targetPane = process.env.EDITPROMPT_TARGET_PANE;
|
|
209
401
|
const muxValue = process.env.EDITPROMPT_MUX || "tmux";
|
|
210
402
|
if (!VALID_MUX_TYPES.includes(muxValue)) throw new Error(`Invalid EDITPROMPT_MUX value: ${muxValue}. Must be one of: ${VALID_MUX_TYPES.join(", ")}`);
|
|
211
|
-
const mux = muxValue;
|
|
212
|
-
const alwaysCopy = process.env.EDITPROMPT_ALWAYS_COPY === "1";
|
|
213
403
|
return {
|
|
214
404
|
targetPane,
|
|
215
|
-
mux,
|
|
216
|
-
alwaysCopy
|
|
405
|
+
mux: muxValue,
|
|
406
|
+
alwaysCopy: process.env.EDITPROMPT_ALWAYS_COPY === "1"
|
|
217
407
|
};
|
|
218
408
|
}
|
|
219
409
|
|
|
@@ -238,13 +428,31 @@ async function runSendOnlyMode(rawContent) {
|
|
|
238
428
|
}
|
|
239
429
|
}
|
|
240
430
|
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region src/utils/argumentParser.ts
|
|
433
|
+
/**
|
|
434
|
+
* Extract raw content from CLI arguments
|
|
435
|
+
* Prioritizes ctx.rest (for -- separator) over ctx.positionals
|
|
436
|
+
*
|
|
437
|
+
* @param rest - Arguments passed after -- separator
|
|
438
|
+
* @param positionals - Positional arguments
|
|
439
|
+
* @returns Raw content string or undefined if no content provided
|
|
440
|
+
*/
|
|
441
|
+
function extractRawContent(rest, positionals) {
|
|
442
|
+
if (rest.length > 0) return rest.join(" ");
|
|
443
|
+
return positionals[0];
|
|
444
|
+
}
|
|
445
|
+
|
|
241
446
|
//#endregion
|
|
242
447
|
//#region src/index.ts
|
|
243
|
-
|
|
244
|
-
await cli(argv, {
|
|
448
|
+
await cli(process.argv.slice(2), {
|
|
245
449
|
name: "editprompt",
|
|
246
450
|
description: "A CLI tool that lets you write prompts for Claude Code using your favorite text editor",
|
|
247
451
|
args: {
|
|
452
|
+
resume: {
|
|
453
|
+
description: "Resume existing editor pane instead of creating new one",
|
|
454
|
+
type: "boolean"
|
|
455
|
+
},
|
|
248
456
|
editor: {
|
|
249
457
|
short: "e",
|
|
250
458
|
description: "Editor to use (overrides $EDITOR)",
|
|
@@ -278,7 +486,20 @@ await cli(argv, {
|
|
|
278
486
|
},
|
|
279
487
|
async run(ctx) {
|
|
280
488
|
try {
|
|
281
|
-
|
|
489
|
+
if (ctx.values.resume) {
|
|
490
|
+
if (!ctx.values["target-pane"]) {
|
|
491
|
+
console.error("Error: --target-pane is required when using --resume");
|
|
492
|
+
process.exit(1);
|
|
493
|
+
}
|
|
494
|
+
const mux$1 = ctx.values.mux || "tmux";
|
|
495
|
+
if (!isMuxType(mux$1)) {
|
|
496
|
+
console.error(`Error: Invalid mux type '${mux$1}'. Supported values: tmux, wezterm`);
|
|
497
|
+
process.exit(1);
|
|
498
|
+
}
|
|
499
|
+
await runResumeMode(ctx.values["target-pane"], mux$1);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const rawContent = extractRawContent(ctx.rest, ctx.positionals);
|
|
282
503
|
if (rawContent !== void 0) {
|
|
283
504
|
await runSendOnlyMode(rawContent);
|
|
284
505
|
return;
|
|
@@ -311,4 +532,5 @@ await cli(argv, {
|
|
|
311
532
|
}
|
|
312
533
|
}, { version });
|
|
313
534
|
|
|
314
|
-
//#endregion
|
|
535
|
+
//#endregion
|
|
536
|
+
export { };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "editprompt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"author": "eetann",
|
|
5
5
|
"description": "A CLI tool that lets you write prompts for CLI tools using your favorite text editor",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,17 +48,18 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@biomejs/biome": "1.9.4",
|
|
51
|
-
"@types/bun": "^1.
|
|
52
|
-
"@types/node": "^24.
|
|
53
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
54
|
-
"bumpp": "^10.
|
|
51
|
+
"@types/bun": "^1.3.0",
|
|
52
|
+
"@types/node": "^24.9.1",
|
|
53
|
+
"@typescript/native-preview": "^7.0.0-dev.20251021.1",
|
|
54
|
+
"bumpp": "^10.3.1",
|
|
55
55
|
"tsdown": "latest"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"clipboardy": "^4.0.0",
|
|
59
|
+
"conf": "^15.0.2",
|
|
59
60
|
"gunshi": "^0.26.3"
|
|
60
61
|
},
|
|
61
62
|
"peerDependencies": {
|
|
62
|
-
"typescript": "^5"
|
|
63
|
+
"typescript": "^5.8.3"
|
|
63
64
|
}
|
|
64
65
|
}
|