mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(tui): route Ctrl+K and Ctrl+W through macOS readline fallback
Makes Ctrl+K and Ctrl+W work in hermes --tui mode in macOS
This commit is contained in:
parent
b49a1b71a7
commit
ea9ddecc72
3 changed files with 31 additions and 7 deletions
|
|
@ -30,3 +30,22 @@ describe('platform action modifier', () => {
|
||||||
expect(isActionMod({ ctrl: false, meta: false, super: true })).toBe(false)
|
expect(isActionMod({ ctrl: false, meta: false, super: true })).toBe(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('isMacActionFallback', () => {
|
||||||
|
it('routes raw Ctrl+K and Ctrl+W to readline kill-to-end / delete-word on macOS', async () => {
|
||||||
|
const { isMacActionFallback } = await importPlatform('darwin')
|
||||||
|
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: false, super: false }, 'k', 'k')).toBe(true)
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: false, super: false }, 'w', 'w')).toBe(true)
|
||||||
|
// Must not fire when Cmd (meta/super) is held — those are distinct chords.
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: true, super: false }, 'k', 'k')).toBe(false)
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: false, super: true }, 'w', 'w')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('is a no-op on non-macOS (Linux routes Ctrl+K/W through isActionMod directly)', async () => {
|
||||||
|
const { isMacActionFallback } = await importPlatform('linux')
|
||||||
|
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: false, super: false }, 'k', 'k')).toBe(false)
|
||||||
|
expect(isMacActionFallback({ ctrl: true, meta: false, super: false }, 'w', 'w')).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -634,6 +634,8 @@ export function TextInput({
|
||||||
const actionHome = k.home || (!isMac && mod && inp === 'a') || isMacActionFallback(k, inp, 'a')
|
const actionHome = k.home || (!isMac && mod && inp === 'a') || isMacActionFallback(k, inp, 'a')
|
||||||
const actionEnd = k.end || (mod && inp === 'e') || isMacActionFallback(k, inp, 'e')
|
const actionEnd = k.end || (mod && inp === 'e') || isMacActionFallback(k, inp, 'e')
|
||||||
const actionDeleteToStart = (mod && inp === 'u') || isMacActionFallback(k, inp, 'u')
|
const actionDeleteToStart = (mod && inp === 'u') || isMacActionFallback(k, inp, 'u')
|
||||||
|
const actionKillToEnd = (mod && inp === 'k') || isMacActionFallback(k, inp, 'k')
|
||||||
|
const actionDeleteWord = (mod && inp === 'w') || isMacActionFallback(k, inp, 'w')
|
||||||
const range = selRange()
|
const range = selRange()
|
||||||
const delFwd = k.delete || fwdDel.current
|
const delFwd = k.delete || fwdDel.current
|
||||||
|
|
||||||
|
|
@ -697,7 +699,7 @@ export function TextInput({
|
||||||
} else {
|
} else {
|
||||||
v = v.slice(0, c) + v.slice(nextPos(v, c))
|
v = v.slice(0, c) + v.slice(nextPos(v, c))
|
||||||
}
|
}
|
||||||
} else if (mod && inp === 'w') {
|
} else if (actionDeleteWord) {
|
||||||
if (range) {
|
if (range) {
|
||||||
v = v.slice(0, range.start) + v.slice(range.end)
|
v = v.slice(0, range.start) + v.slice(range.end)
|
||||||
c = range.start
|
c = range.start
|
||||||
|
|
@ -717,7 +719,7 @@ export function TextInput({
|
||||||
v = v.slice(c)
|
v = v.slice(c)
|
||||||
c = 0
|
c = 0
|
||||||
}
|
}
|
||||||
} else if (mod && inp === 'k') {
|
} else if (actionKillToEnd) {
|
||||||
if (range) {
|
if (range) {
|
||||||
v = v.slice(0, range.start) + v.slice(range.end)
|
v = v.slice(0, range.start) + v.slice(range.end)
|
||||||
c = range.start
|
c = range.start
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,18 @@ export const isActionMod = (key: { ctrl: boolean; meta: boolean; super?: boolean
|
||||||
isMac ? key.meta || key.super === true : key.ctrl
|
isMac ? key.meta || key.super === true : key.ctrl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some macOS terminals rewrite Cmd navigation/deletion into readline control keys.
|
* Accept raw Ctrl+<letter> as an action shortcut on macOS, where `isActionMod`
|
||||||
* Treat those as action shortcuts too, but only for the specific fallbacks we
|
* otherwise means Cmd. Two motivations:
|
||||||
* have observed from terminals: Cmd+Left → Ctrl+A, Cmd+Right → Ctrl+E,
|
* - Some macOS terminals rewrite Cmd navigation/deletion into readline control
|
||||||
* Cmd+Backspace → Ctrl+U.
|
* keys (Cmd+Left → Ctrl+A, Cmd+Right → Ctrl+E, Cmd+Backspace → Ctrl+U).
|
||||||
|
* - Ctrl+K (kill-to-end) and Ctrl+W (delete-word-back) are standard readline
|
||||||
|
* bindings that users expect to work regardless of platform, even though
|
||||||
|
* no terminal rewrites Cmd into them.
|
||||||
*/
|
*/
|
||||||
export const isMacActionFallback = (
|
export const isMacActionFallback = (
|
||||||
key: { ctrl: boolean; meta: boolean; super?: boolean },
|
key: { ctrl: boolean; meta: boolean; super?: boolean },
|
||||||
ch: string,
|
ch: string,
|
||||||
target: 'a' | 'e' | 'u'
|
target: 'a' | 'e' | 'u' | 'k' | 'w'
|
||||||
): boolean => isMac && key.ctrl && !key.meta && key.super !== true && ch.toLowerCase() === target
|
): boolean => isMac && key.ctrl && !key.meta && key.super !== true && ch.toLowerCase() === target
|
||||||
|
|
||||||
/** Match action-modifier + a single character (case-insensitive). */
|
/** Match action-modifier + a single character (case-insensitive). */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue