Download packages/cli/src/ui/hooks/useKeypress.ts from Jimmi42/openCLI: direct link, hf CLI and curl.
- Browser
- Download file 2.77 kB
-
https://huggingface.co/Jimmi42/openCLI/resolve/main/packages/cli/src/ui/hooks/useKeypress.ts
- Command line
-
hf download hf://Jimmi42/openCLI/packages/cli/src/ui/hooks/useKeypress.ts
-
curl -L -o useKeypress.ts https://huggingface.co/Jimmi42/openCLI/resolve/main/packages/cli/src/ui/hooks/useKeypress.ts
2.77 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| 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; | |
| } | |
| /** | |
| * A hook that listens for keypress events from stdin, providing a | |
| * key object that mirrors the one from Node's `readline` module, | |
| * adding a 'paste' flag for characters input as part of a bracketed | |
| * paste (when enabled). | |
| * | |
| * Pastes are currently sent as a single key event where the full paste | |
| * is in the sequence field. | |
| * | |
| * @param onKeypress - The callback function to execute on each keypress. | |
| * @param options - Options to control the hook's behavior. | |
| * @param options.isActive - Whether the hook should be actively listening for input. | |
| */ | |
| 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 { | |
| // Handle special keys | |
| 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 we are in the middle of a paste, send what we have. | |
| if (isPaste) { | |
| onKeypressRef.current({ | |
| name: '', | |
| ctrl: false, | |
| meta: false, | |
| shift: false, | |
| paste: true, | |
| sequence: pasteBuffer.toString(), | |
| }); | |
| pasteBuffer = Buffer.alloc(0); | |
| } | |
| }; | |
| }, [isActive, stdin, setRawMode]); | |
| } | |