cli: +edit-config works properly when editor command contains arguments (#11898)

If `$EDITOR` or `$VISUAL` contained arguments, not just the path to an
editor (e.g. `zed --new`) `+edit-config` would fail because we were
treating the whole command as a path. Instead, wrap the command with
`/bin/sh -c <command>` so that the shell can separate the path from the
arguments.

Fixes #11897
pull/11934/head
Mitchell Hashimoto 2026-03-28 08:57:30 -07:00 committed by GitHub
commit 608bc7d24d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 18 additions and 6 deletions

View File

@ -136,19 +136,31 @@ fn runInner(alloc: Allocator, stderr: *std.Io.Writer) !u8 {
return 1;
}
const command = command: {
var buffer: std.io.Writer.Allocating = .init(alloc);
defer buffer.deinit();
const writer = &buffer.writer;
try writer.writeAll(editor);
try writer.writeByte(' ');
{
var sh: internal_os.ShellEscapeWriter = .init(writer);
try sh.writer.writeAll(path);
try sh.writer.flush();
}
try writer.flush();
break :command try buffer.toOwnedSliceSentinel(0);
};
defer alloc.free(command);
// We require libc because we want to use std.c.environ for envp
// and not have to build that ourselves. We can remove this
// limitation later but Ghostty already heavily requires libc
// so this is not a big deal.
comptime assert(builtin.link_libc);
const editorZ = try alloc.dupeZ(u8, editor);
defer alloc.free(editorZ);
const pathZ = try alloc.dupeZ(u8, path);
defer alloc.free(pathZ);
const err = std.posix.execvpeZ(
editorZ,
&.{ editorZ, pathZ },
"/bin/sh",
&.{ "/bin/sh", "-c", command },
std.c.environ,
);