mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-30 01:41:43 +00:00
fix(tui): readline parity on Linux — Ctrl+A = home, Alt+B/F word nav
textInput treated the platform action-mod (Cmd on macOS, Ctrl on Linux) as the sole word-boundary modifier. On Linux that meant: - Ctrl+A selected all instead of jumping to line start (contra standard readline and the hotkey doc in README.md which says `Ctrl+A` = Start of line). - Alt+B / Alt+F / Alt+Backspace / Alt+Delete were dropped, because `key.meta` was never consulted — the README already documented `Meta+B` / `Meta+F` as word nav. Gate select-all to macOS Cmd+A (`isMac && mod && inp === 'a'`), route Linux Ctrl+A through `actionHome`, and broaden every word-boundary predicate (b/f/Backspace/Delete and the modified arrow keys) from `mod` to `wordMod = mod || k.meta` so Alt chords work on Linux and Mac while existing Ctrl/Cmd chords keep working.
This commit is contained in:
parent
ce98e1ef11
commit
d86c886b31
21 changed files with 215 additions and 84 deletions
|
|
@ -277,8 +277,9 @@ function useFwdDelete(active: boolean) {
|
|||
|
||||
type PasteResult = { cursor: number; value: string } | null
|
||||
|
||||
const isPasteResultPromise = (value: PasteResult | Promise<PasteResult> | null | undefined): value is Promise<PasteResult> =>
|
||||
!!value && typeof (value as PromiseLike<PasteResult>).then === 'function'
|
||||
const isPasteResultPromise = (
|
||||
value: PasteResult | Promise<PasteResult> | null | undefined
|
||||
): value is Promise<PasteResult> => !!value && typeof (value as PromiseLike<PasteResult>).then === 'function'
|
||||
|
||||
export function TextInput({
|
||||
columns = 80,
|
||||
|
|
@ -522,9 +523,11 @@ export function TextInput({
|
|||
}
|
||||
|
||||
const range = selRange()
|
||||
|
||||
const nextValue = range
|
||||
? vRef.current.slice(0, range.start) + cleaned + vRef.current.slice(range.end)
|
||||
: vRef.current.slice(0, curRef.current) + cleaned + vRef.current.slice(curRef.current)
|
||||
|
||||
const nextCursor = range ? range.start + cleaned.length : curRef.current + cleaned.length
|
||||
|
||||
commit(nextValue, nextCursor)
|
||||
|
|
@ -591,7 +594,8 @@ export function TextInput({
|
|||
let c = curRef.current
|
||||
let v = vRef.current
|
||||
const mod = isActionMod(k)
|
||||
const actionHome = k.home || isMacActionFallback(k, inp, 'a')
|
||||
const wordMod = mod || k.meta
|
||||
const actionHome = k.home || (!isMac && mod && inp === 'a') || isMacActionFallback(k, inp, 'a')
|
||||
const actionEnd = k.end || (mod && inp === 'e') || isMacActionFallback(k, inp, 'e')
|
||||
const actionDeleteToStart = (mod && inp === 'u') || isMacActionFallback(k, inp, 'u')
|
||||
const range = selRange()
|
||||
|
|
@ -605,7 +609,7 @@ export function TextInput({
|
|||
return swap(redo, undo)
|
||||
}
|
||||
|
||||
if (mod && inp === 'a') {
|
||||
if (isMac && mod && inp === 'a') {
|
||||
return selectAll()
|
||||
}
|
||||
|
||||
|
|
@ -616,32 +620,32 @@ export function TextInput({
|
|||
clearSel()
|
||||
c = v.length
|
||||
} else if (k.leftArrow) {
|
||||
if (range && !mod) {
|
||||
if (range && !wordMod) {
|
||||
clearSel()
|
||||
c = range.start
|
||||
} else {
|
||||
clearSel()
|
||||
c = mod ? wordLeft(v, c) : prevPos(v, c)
|
||||
c = wordMod ? wordLeft(v, c) : prevPos(v, c)
|
||||
}
|
||||
} else if (k.rightArrow) {
|
||||
if (range && !mod) {
|
||||
if (range && !wordMod) {
|
||||
clearSel()
|
||||
c = range.end
|
||||
} else {
|
||||
clearSel()
|
||||
c = mod ? wordRight(v, c) : nextPos(v, c)
|
||||
c = wordMod ? wordRight(v, c) : nextPos(v, c)
|
||||
}
|
||||
} else if (mod && inp === 'b') {
|
||||
} else if (wordMod && inp === 'b') {
|
||||
clearSel()
|
||||
c = wordLeft(v, c)
|
||||
} else if (mod && inp === 'f') {
|
||||
} else if (wordMod && inp === 'f') {
|
||||
clearSel()
|
||||
c = wordRight(v, c)
|
||||
} else if (range && (k.backspace || delFwd)) {
|
||||
v = v.slice(0, range.start) + v.slice(range.end)
|
||||
c = range.start
|
||||
} else if (k.backspace && c > 0) {
|
||||
if (mod) {
|
||||
if (wordMod) {
|
||||
const t = wordLeft(v, c)
|
||||
v = v.slice(0, t) + v.slice(c)
|
||||
c = t
|
||||
|
|
@ -651,7 +655,7 @@ export function TextInput({
|
|||
c = t
|
||||
}
|
||||
} else if (delFwd && c < v.length) {
|
||||
if (mod) {
|
||||
if (wordMod) {
|
||||
const t = wordRight(v, c)
|
||||
v = v.slice(0, c) + v.slice(t)
|
||||
} else {
|
||||
|
|
@ -778,7 +782,9 @@ interface TextInputProps {
|
|||
focus?: boolean
|
||||
mask?: string
|
||||
onChange: (v: string) => void
|
||||
onPaste?: (e: PasteEvent) => { cursor: number; value: string } | Promise<{ cursor: number; value: string } | null> | null
|
||||
onPaste?: (
|
||||
e: PasteEvent
|
||||
) => { cursor: number; value: string } | Promise<{ cursor: number; value: string } | null> | null
|
||||
onSubmit?: (v: string) => void
|
||||
placeholder?: string
|
||||
value: string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue