feat(cli): add Sublime Text and Emacs Client editors, improve error messages and documentation#21090
feat(cli): add Sublime Text and Emacs Client editors, improve error messages and documentation#21090alberti42 wants to merge 23 commits into
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the external editor integration for the CLI, making it more robust and user-friendly. It expands the range of supported editors, provides more informative feedback for common configuration issues, and updates all relevant documentation to guide users effectively. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request adds support for Sublime Text and Emacs Client as external editors and enhances error handling for editor configurations, along with clear documentation updates. However, a critical command injection vulnerability was identified in packages/cli/src/ui/utils/editorUtils.ts due to the unsafe handling of VISUAL and EDITOR environment variables, potentially leading to Remote Code Execution. Additionally, one issue in the new test code requires attention for correctness.
| default: undefined as string | undefined, | ||
| description: 'The preferred editor to open files in.', | ||
| description: | ||
| 'The preferred editor to open files in. Must be one of the built-in supported identifiers — run /editor in the CLI for the full list. Power users who need an editor not in this list can leave this unset and configure $VISUAL or $EDITOR in their shell environment instead.', |
There was a problem hiding this comment.
This descript is too long. Descriptions need to fit in the UI.
There was a problem hiding this comment.
Thanks for reviewing it. I shortened the description.
| @@ -41,8 +41,8 @@ | |||
| "properties": { | |||
| "preferredEditor": { | |||
| "title": "Preferred Editor", | |||
| "description": "The preferred editor to open files in.", | |||
| "markdownDescription": "The preferred editor to open files in.\n\n- Category: `General`\n- Requires restart: `no`", | |||
| "description": "The preferred editor to open files in. Must be one of the built-in supported identifiers — run /editor in the CLI for the full list. Power users who need an editor not in this list can leave this unset and configure $VISUAL or $EDITOR in their shell environment instead.", | |||
There was a problem hiding this comment.
Tweak so you can specify a separate longer markdown description from the short description suitable for the TUI.
There was a problem hiding this comment.
I shortened the description in 15bda94.
The file schemas/settings.schema.json is automatically generated by npm run docs:settings.
The new commit already contains the newly generated one.
Head branch was pushed to by a user without write access
jacob314 requested a shorter description to fit the TUI. This was already addressed in PR google-gemini#21090 via settingsSchema.ts. Regenerate schema from source of truth and restore the accepted-values table in configuration.md.
|
Update: I've integrated the work from the duplicate PR #21377 by @AnanthKini1 into this branch. His commits have been cherry-picked on top of mine with authorship preserved. His additions beyond what was already in this PR:
I also fixed a documentation issue: schemas/settings.schema.json and docs/reference/configuration.md are auto-generated from settingsSchema.ts, so I moved the enum values there to make them permanent. |
| "node_modules/@octokit/core": { | ||
| "version": "7.0.5", | ||
| "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.5.tgz", | ||
| "integrity": "sha512-t54CUOsFMappY1Jbzb7fetWeO0n6K0k/4+/ZpkS+3Joz8I4VcvY9OiEBFRYISqaI2fq5sCiPtAjRDOzVYG8m+Q==", |
There was a problem hiding this comment.
revert changes to this file
There was a problem hiding this comment.
Done: I removed the package-lock.json changes from the commit history.
| or leave unset to use $VISUAL/$EDITOR. | ||
| `, | ||
| showInDialog: false, | ||
| options: [ |
There was a problem hiding this comment.
these duplicate options in editor.ts. Please Refactor so they don't have to be duplicated or remove this. Including these entries here isn't crucial as this is hidden from the settings dialog but would be nice to have so it ends up in settings.schema.json
There was a problem hiding this comment.
Done. The fix is in commit "refactor: derive preferredEditor options from EDITOR_OPTIONS"
| } else { | ||
| // Heuristic fallback for commands not in the registry | ||
| const lower = envCommand.toLowerCase(); | ||
| const isGui = ['code', 'cursor', 'subl', 'zed', 'atom'].some((g) => |
There was a problem hiding this comment.
add these to a const rather than including them here
There was a problem hiding this comment.
done → changes are in commit "refactor: extract HEURISTIC_GUI_COMMANDS const"
| 'error', | ||
| '[editorUtils] external editor spawn error', | ||
| err, | ||
| const spawnErr = err as NodeJS.ErrnoException; |
There was a problem hiding this comment.
emitFeedback is preferred to throwing an exception. why this change?
There was a problem hiding this comment.
done: see commit "fix: replace throw with emitFeedback in openFileInEditor"
| const editorExtraArgs: Partial<Record<EditorType, string[]>> = { | ||
| emacsclient: ['-nw'], // Force terminal (no-window) mode | ||
| vscode: ['--new-window'], // Force a new window to open the file directly | ||
| vscodium: ['--new-window'], |
There was a problem hiding this comment.
addubg new window will be frustrating for some users. If I have a project open in vscode why do I want a new window? Would suggest protecting this behind a setting.
There was a problem hiding this comment.
done: see commit → "feat: guard --new-window behind openEditorInNewWindow setting"
jacob314
left a comment
There was a problem hiding this comment.
Added some comments. once these are addressed this can be approved.
jacob314 requested a shorter description to fit the TUI. This was already addressed in PR google-gemini#21090 via settingsSchema.ts. Regenerate schema from source of truth and restore the accepted-values table in configuration.md.
19b1f71 to
1fcb713
Compare
alberti42
left a comment
There was a problem hiding this comment.
I split the resolution of concerns into different commits for easier review/understanding. If needed, we can squash things at the end.
| or leave unset to use $VISUAL/$EDITOR. | ||
| `, | ||
| showInDialog: false, | ||
| options: [ |
There was a problem hiding this comment.
Done. The fix is in commit "refactor: derive preferredEditor options from EDITOR_OPTIONS"
| } else { | ||
| // Heuristic fallback for commands not in the registry | ||
| const lower = envCommand.toLowerCase(); | ||
| const isGui = ['code', 'cursor', 'subl', 'zed', 'atom'].some((g) => |
There was a problem hiding this comment.
done → changes are in commit "refactor: extract HEURISTIC_GUI_COMMANDS const"
| 'error', | ||
| '[editorUtils] external editor spawn error', | ||
| err, | ||
| const spawnErr = err as NodeJS.ErrnoException; |
There was a problem hiding this comment.
done: see commit "fix: replace throw with emitFeedback in openFileInEditor"
| const editorExtraArgs: Partial<Record<EditorType, string[]>> = { | ||
| emacsclient: ['-nw'], // Force terminal (no-window) mode | ||
| vscode: ['--new-window'], // Force a new window to open the file directly | ||
| vscodium: ['--new-window'], |
There was a problem hiding this comment.
done: see commit → "feat: guard --new-window behind openEditorInNewWindow setting"
1fcb713 to
d4ec629
Compare
3ab2c79 to
b47ae45
Compare
jacob314 requested a shorter description to fit the TUI. This was already addressed in PR google-gemini#21090 via settingsSchema.ts. Regenerate schema from source of truth and restore the accepted-values table in configuration.md.
|
@cocosheng-g Thanks for following up. The code is now ready for being re-reviewed. |
1. Added 'sublime' to GUI_EDITORS
2. Added sublime: 'Sublime Text' to EDITOR_DISPLAY_NAMES
3. Added sublime: { win32: ['subl'], default: ['subl'] } to editorCommands
4. Added a case 'sublime' in getDiffCommand with ['--wait', oldPath] (Sublime doesn't support --diff)
And in editor.test.ts: added sublime to the hasValidEditorCommand, getDiffCommand, openDiff, and allowEditorTypeInSandbox test suites.
packages/core/src/utils/editor.ts:
- Added 'emacsclient' to TERMINAL_EDITORS
- Added emacsclient: 'Emacs Client' to EDITOR_DISPLAY_NAMES
- Added emacsclient: { win32: ['emacsclient'], default: ['emacsclient'] } to editorCommands
- Added case 'emacsclient' in getDiffCommand using emacsclient -nw --eval "(ediff ...)"
packages/cli/src/ui/utils/editorUtils.ts:
- Added -nw flag injection for emacsclient when opening a file (equivalent to the -i NONE treatment for vim)
packages/core/src/utils/editor.test.ts:
- Added emacsclient to hasValidEditorCommand, getDiffCommand, openDiff, and allowEditorTypeInSandbox test suites
Instead of crashing with an unhandled promise rejection, users now get a clear message whether their preferredEditor setting is invalid or their $VISUAL/$EDITOR command can't be found.
jacob314 requested a shorter description to fit the TUI. This was already addressed in PR google-gemini#21090 via settingsSchema.ts. Regenerate schema from source of truth and restore the accepted-values table in configuration.md.
Change preferredEditor type to 'enum' and add options so the schema generator permanently emits the accepted values list in configuration.md and the enum array in settings.schema.json without manual edits.
… EditorSettingsDialog
b47ae45 to
ec05450
Compare
|
Dear Jacob (@jacob314), I wanted to check with you what you think the status of this PR is. You had reviewed it before, and I believe I took care of all your comments. Please let us know if you need more time and/or need to have a more thorough review of the code. Thanks! PS I just rebased it, and luckily there were no conflicts. |
Summary
Addresses #21084 by improving external editor support across three areas: adds
Sublime Text and Emacs Client to the built-in editor list, emits clear
error messages when editor configuration is invalid or a command is missing, and
extends the documentation and JSON schema for
preferredEditor.Details
New editors (
packages/core/src/utils/editor.ts):sublime): added as a GUI editor using thesublcommand.Opens files with
--wait. Diff view opens the new file only, assubldoesnot support a
--diffflag.emacsclient): added as a terminal editor. Automaticallyinjects
-nw(terminal mode) when opening a file. Diff view usesemacsclient -nw --eval "(ediff ...)", consistent with the existingemacsimplementation.
Error handling (
packages/cli/src/ui/utils/editorUtils.ts):Two cases that previously produced a cryptic internal error are now handled
gracefully:
preferredEditor: validates the editor type before use andemits a user-friendly message instead of a generic error. For example,
setting
"preferredEditor": "nvim"(the binary name) instead of thesupported identifier
"neovim"previously produced:$VISUAL/$EDITORcommand: detectsENOENTon spawn and emitsa clear message pointing the user to check their environment variable.
Note:
$VISUAL/$EDITORcontinue to accept any editor command, not just thebuilt-in supported types, preserving full flexibility for power users.
Documentation (
docs/reference/configuration.md,schemas/settings.schema.json,packages/cli/src/config/settingsSchema.ts):descriptionfield forpreferredEditorinsettingsSchema.tshas beenupdated to explain the built-in identifier requirement, the
/editorcommandas the canonical way to discover supported values, and the
$VISUAL/$EDITORescape hatch for power users. Both
docs/reference/configuration.mdandschemas/settings.schema.jsonare regenerated from this source and updatedaccordingly.
Related Issues
Closes #21084
Note for maintainers: enum constraint in the JSON schema
The current implementation leaves
preferredEditortyped as a plainstringinsettingsSchema.ts, so the JSON schema carries noenumconstraint and IDEsoffer no autocomplete for valid editor identifiers.
A cleaner solution would be to change the definition to
type: 'enum'and listthe supported values via
options, mirroring howdefaultApprovalModeisdefined. This would cause the generation script to emit an
enumarray in theJSON schema and a
Values:line in the documentation automatically, and wouldkeep everything in sync with the code. For example:
This is a slightly more invasive change (it touches the settings type system and
may affect dialog rendering), so I have left it out of this PR. I am happy to
implement it based on your feedback.
How to Validate
Sublime Text:
"preferredEditor": "sublime"in~/.gemini/settings.jsonCTRL-Xto open the external editorEmacs Client:
emacs --daemon"preferredEditor": "emacsclient"in~/.gemini/settings.jsonCTRL-Xto open the external editor-nw) and wait until the bufferis closed
Graceful error for unrecognized
preferredEditor:"preferredEditor": "emacsclient -nw"in~/.gemini/settings.jsonCTRL-Xin Gemini CLIEditor 'emacsclient -nw' is not recognized or not installed. Run /editor to pick a supported editor, or set $VISUAL/$EDITOR in your shell to your preferred editor.Graceful error for missing
$VISUAL/$EDITORcommand:export EDITOR="nonexistent-editor"in your shellpreferredEditorfromsettings.jsonCTRL-Xin Gemini CLICould not find editor 'nonexistent-editor'. Check your $VISUAL/$EDITOR setting.Pre-Merge Checklist