mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-02 02:01:47 +00:00
fix: prefer vim over nano for $EDITOR fallback (CLI + TUI)
prompt_toolkit's default editor list is: $VISUAL, $EDITOR, /usr/bin/editor, /usr/bin/nano, /usr/bin/pico, /usr/bin/vi, /usr/bin/emacs — so when neither env var is set, the base CLI launched nano. The TUI fell back to a literal 'vi'. Same Ctrl+G keystroke, two different editors. Pick the same chain on both surfaces: $VISUAL → $EDITOR → vim → vi → nano CLI: override input_area.buffer._open_file_in_editor on the TextArea once at app build time. Local to that buffer; doesn't touch os.environ or affect other subprocesses. TUI: extract resolveEditor() into ui-tui/src/lib/editor.ts. PATH walk with accessSync(X_OK), no shelling out. Six-line unit test verifies the priority order and the multi-entry PATH walk.
This commit is contained in:
parent
5fac6c3440
commit
db7c5735f0
4 changed files with 128 additions and 1 deletions
66
ui-tui/src/lib/editor.test.ts
Normal file
66
ui-tui/src/lib/editor.test.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { chmodSync, mkdirSync, mkdtempSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { delimiter, join } from 'node:path'
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { resolveEditor } from './editor.js'
|
||||
|
||||
describe('resolveEditor', () => {
|
||||
let dir: string
|
||||
|
||||
const exe = (name: string) => {
|
||||
const path = join(dir, name)
|
||||
writeFileSync(path, '#!/bin/sh\nexit 0\n')
|
||||
chmodSync(path, 0o755)
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
dir = mkdtempSync(join(tmpdir(), 'editor-test-'))
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// tmp dir is small; let the OS reap it
|
||||
})
|
||||
|
||||
it('honors $VISUAL above all else', () => {
|
||||
expect(resolveEditor({ EDITOR: 'vim', PATH: dir, VISUAL: 'helix' })).toBe('helix')
|
||||
})
|
||||
|
||||
it('falls back to $EDITOR when $VISUAL is unset', () => {
|
||||
expect(resolveEditor({ EDITOR: 'nvim', PATH: dir })).toBe('nvim')
|
||||
})
|
||||
|
||||
it('prefers vim over vi over nano on $PATH', () => {
|
||||
exe('nano')
|
||||
exe('vi')
|
||||
const vim = exe('vim')
|
||||
|
||||
expect(resolveEditor({ PATH: dir })).toBe(vim)
|
||||
})
|
||||
|
||||
it('falls back to vi when only vi and nano exist', () => {
|
||||
exe('nano')
|
||||
const vi = exe('vi')
|
||||
|
||||
expect(resolveEditor({ PATH: dir })).toBe(vi)
|
||||
})
|
||||
|
||||
it('returns literal "vi" when nothing on PATH and no env', () => {
|
||||
mkdirSync(join(dir, 'empty'), { recursive: true })
|
||||
|
||||
expect(resolveEditor({ PATH: join(dir, 'empty') })).toBe('vi')
|
||||
})
|
||||
|
||||
it('walks multi-entry PATH', () => {
|
||||
const a = mkdtempSync(join(tmpdir(), 'editor-a-'))
|
||||
const b = mkdtempSync(join(tmpdir(), 'editor-b-'))
|
||||
|
||||
writeFileSync(join(b, 'vim'), '#!/bin/sh\n')
|
||||
chmodSync(join(b, 'vim'), 0o755)
|
||||
|
||||
expect(resolveEditor({ PATH: [a, b].join(delimiter) })).toBe(join(b, 'vim'))
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue