-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add open-in-editor feature with Cmd+O shortcut #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3303d9a
6204eaf
c8f33b8
84b71e0
36314bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,9 +3,10 @@ fixPath(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { spawn } from "node:child_process"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import path from "node:path"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { BrowserWindow, app, dialog, ipcMain, session } from "electron"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { BrowserWindow, app, dialog, ipcMain, session, shell } from "electron"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EDITORS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IPC_CHANNELS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type TerminalCommandInput, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type TerminalCommandResult, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -125,6 +126,29 @@ function registerIpcHandlers(): void { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Shell handlers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ipcMain.handle( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IPC_CHANNELS.shellOpenInEditor, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async (_event, cwd: string, editor: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!cwd) throw new Error("cwd is required"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const editorDef = EDITORS.find((e) => e.id === editor); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!editorDef) throw new Error(`Unknown editor: ${editor}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!editorDef.command) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const error = await shell.openPath(cwd); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error) throw new Error(error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const child = spawn(editorDef.command, [cwd], { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| detached: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stdio: "ignore", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| child.on("error", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* ignore spawn failures for detached editors */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| child.unref(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+129
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n apps/desktop/src/main.ts | sed -n '135,153p'Repository: pingdotgg/codething-mvp Length of output: 848 🌐 Web query:
💡 Result:
So error handling is typically: import { shell } from "electron";
async function openFile(p: string) {
try {
const err = await shell.openPath(p);
if (err) {
// open failed; Electron returns an error message string
console.error("openPath failed:", err);
// show UI / log / fallback here
}
} catch (e) {
// for unexpected exceptions (e.g., bad argument types, other runtime issues)
console.error("openPath threw:", e);
}
}Key point: check the resolved string—don’t rely only on Citations:
🌐 Web query:
💡 Result: In Node.js,
A common safe pattern is to funnel both import { spawn } from 'node:child_process';
function spawnChecked(cmd, args, opts) {
const child = spawn(cmd, args, opts);
let settled = false;
const done = (err, result) => {
if (settled) return;
settled = true;
if (err) throw err; // or reject a Promise / call cb(err)
return result;
};
child.once('error', (err) => done(err)); // spawn/kill/IPC failure
child.once('close', (code, signal) => { // stdio fully closed
if (code === 0) return done(null, { code, signal });
done(Object.assign(new Error(`exit ${code ?? 'null'} (${signal ?? 'no-signal'})`), { code, signal }));
});
return child;
}Sources: Node.js References Citations:
Add error handling for 🛠️ Suggested fix- async (_event, cwd: string, editor: string) => {
- if (editor === "file-manager") {
- await shell.openPath(cwd);
- return;
- }
+ async (_event, cwd: string, editor: string) => {
+ if (!cwd) {
+ throw new Error("cwd is required");
+ }
+ if (editor === "file-manager") {
+ const error = await shell.openPath(cwd);
+ if (error) {
+ throw new Error(error);
+ }
+ return;
+ }
const EDITOR_COMMANDS: Record<string, { command: string; args: (cwd: string) => string[] }> = {
cursor: { command: "cursor", args: (p) => [p] },
};
const entry = EDITOR_COMMANDS[editor];
if (!entry) throw new Error(`Unknown editor: ${editor}`);
- const child = spawn(entry.command, entry.args(cwd), {
- detached: true,
- stdio: "ignore",
- });
- child.unref();
+ await new Promise<void>((resolve, reject) => {
+ const child = spawn(entry.command, entry.args(cwd), {
+ detached: true,
+ stdio: "ignore",
+ });
+ child.once("error", reject);
+ child.once("spawn", () => {
+ child.unref();
+ resolve();
+ });
+ });
},
);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Agent handlers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ipcMain.handle( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IPC_CHANNELS.agentSpawn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.