MCPcopy Create free account
hub / github.com/modem-dev/hunk / openSelectedFileInEditor

Function openSelectedFileInEditor

src/ui/lib/openInEditor.ts:80–143  ·  view source on GitHub ↗
({
  basePath,
  file,
  renderer,
  selectedHunk,
}: {
  basePath?: string;
  file: DiffFile | undefined;
  renderer: Pick<CliRenderer, "suspend" | "resume" | "isDestroyed">;
  selectedHunk: DiffFile["metadata"]["hunks"][number] | undefined;
})

Source from the content-addressed store, hash-verified

78
79/** Open the selected file in $EDITOR, suspending TUI for terminal editors. */
80export function openSelectedFileInEditor({
81 basePath,
82 file,
83 renderer,
84 selectedHunk,
85}: {
86 basePath?: string;
87 file: DiffFile | undefined;
88 renderer: Pick<CliRenderer, "suspend" | "resume" | "isDestroyed">;
89 selectedHunk: DiffFile["metadata"]["hunks"][number] | undefined;
90}) {
91 if (!file) {
92 return "No file selected.";
93 }
94
95 const editor = process.env.EDITOR?.trim();
96 if (!editor) {
97 return "$EDITOR is not set.";
98 }
99
100 const absolutePath = resolveEditableFilePath(file.path, basePath);
101 if (!existsSync(absolutePath)) {
102 return `Cannot edit ${file.path}: file does not exist on disk.`;
103 }
104
105 const line = Math.max(1, selectedLine(file, selectedHunk));
106 const command = buildEditorCommand({
107 editor,
108 filePath: absolutePath,
109 line,
110 });
111
112 const shouldSuspend = shouldSuspendForEditor(editor);
113 if (shouldSuspend) {
114 renderer.suspend();
115 }
116
117 let exitCode = 0;
118 let failureMessage: string | null = null;
119 try {
120 const result = Bun.spawnSync([command.command, ...command.args], {
121 stdin: "inherit",
122 stdout: "inherit",
123 stderr: "inherit",
124 });
125 exitCode = result.exitCode;
126 } catch (error) {
127 failureMessage = error instanceof Error ? error.message : String(error);
128 }
129
130 if (shouldSuspend && !renderer.isDestroyed) {
131 renderer.resume();
132 }
133
134 if (failureMessage) {
135 return `Failed to launch editor: ${failureMessage}`;
136 }
137

Callers 2

AppFunction · 0.90

Calls 5

resolveEditableFilePathFunction · 0.85
selectedLineFunction · 0.85
buildEditorCommandFunction · 0.85
shouldSuspendForEditorFunction · 0.85
resumeMethod · 0.65

Tested by

no test coverage detected