|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useEffect, useRef } from 'react'; |
|
|
import { useStdin } from 'ink'; |
|
|
import readline from 'readline'; |
|
|
|
|
|
export interface Key { |
|
|
name: string; |
|
|
ctrl: boolean; |
|
|
meta: boolean; |
|
|
shift: boolean; |
|
|
paste: boolean; |
|
|
sequence: string; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function useKeypress( |
|
|
onKeypress: (key: Key) => void, |
|
|
{ isActive }: { isActive: boolean }, |
|
|
) { |
|
|
const { stdin, setRawMode } = useStdin(); |
|
|
const onKeypressRef = useRef(onKeypress); |
|
|
|
|
|
useEffect(() => { |
|
|
onKeypressRef.current = onKeypress; |
|
|
}, [onKeypress]); |
|
|
|
|
|
useEffect(() => { |
|
|
if (!isActive || !stdin.isTTY) { |
|
|
return; |
|
|
} |
|
|
|
|
|
setRawMode(true); |
|
|
|
|
|
const rl = readline.createInterface({ input: stdin }); |
|
|
let isPaste = false; |
|
|
let pasteBuffer = Buffer.alloc(0); |
|
|
|
|
|
const handleKeypress = (_: unknown, key: Key) => { |
|
|
if (key.name === 'paste-start') { |
|
|
isPaste = true; |
|
|
} else if (key.name === 'paste-end') { |
|
|
isPaste = false; |
|
|
onKeypressRef.current({ |
|
|
name: '', |
|
|
ctrl: false, |
|
|
meta: false, |
|
|
shift: false, |
|
|
paste: true, |
|
|
sequence: pasteBuffer.toString(), |
|
|
}); |
|
|
pasteBuffer = Buffer.alloc(0); |
|
|
} else { |
|
|
if (isPaste) { |
|
|
pasteBuffer = Buffer.concat([pasteBuffer, Buffer.from(key.sequence)]); |
|
|
} else { |
|
|
|
|
|
if (key.name === 'return' && key.sequence === '\x1B\r') { |
|
|
key.meta = true; |
|
|
} |
|
|
onKeypressRef.current({ ...key, paste: isPaste }); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
readline.emitKeypressEvents(stdin, rl); |
|
|
stdin.on('keypress', handleKeypress); |
|
|
|
|
|
return () => { |
|
|
stdin.removeListener('keypress', handleKeypress); |
|
|
rl.close(); |
|
|
setRawMode(false); |
|
|
|
|
|
|
|
|
if (isPaste) { |
|
|
onKeypressRef.current({ |
|
|
name: '', |
|
|
ctrl: false, |
|
|
meta: false, |
|
|
shift: false, |
|
|
paste: true, |
|
|
sequence: pasteBuffer.toString(), |
|
|
}); |
|
|
pasteBuffer = Buffer.alloc(0); |
|
|
} |
|
|
}; |
|
|
}, [isActive, stdin, setRawMode]); |
|
|
} |
|
|
|