Download packages/cli/src/ui/hooks/useFocus.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 2.04 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/hooks/useFocus.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/ui/hooks/useFocus.ts
-
curl -L -o useFocus.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/hooks/useFocus.ts
2.04 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { useStdin, useStdout } from 'ink'; | |
| import { useEffect, useState } from 'react'; | |
| import { useKeypress } from './useKeypress.js'; | |
| // ANSI escape codes to enable/disable terminal focus reporting | |
| export const ENABLE_FOCUS_REPORTING = '\x1b[?1004h'; | |
| export const DISABLE_FOCUS_REPORTING = '\x1b[?1004l'; | |
| // ANSI escape codes for focus events | |
| export const FOCUS_IN = '\x1b[I'; | |
| export const FOCUS_OUT = '\x1b[O'; | |
| export const useFocus = (): { | |
| isFocused: boolean; | |
| hasReceivedFocusEvent: boolean; | |
| } => { | |
| const { stdin } = useStdin(); | |
| const { stdout } = useStdout(); | |
| const [isFocused, setIsFocused] = useState(true); | |
| const [hasReceivedFocusEvent, setHasReceivedFocusEvent] = useState(false); | |
| useEffect(() => { | |
| const handleData = (data: Buffer) => { | |
| const sequence = data.toString(); | |
| const lastFocusIn = sequence.lastIndexOf(FOCUS_IN); | |
| const lastFocusOut = sequence.lastIndexOf(FOCUS_OUT); | |
| if (lastFocusIn > lastFocusOut) { | |
| setHasReceivedFocusEvent(true); | |
| setIsFocused(true); | |
| } else if (lastFocusOut > lastFocusIn) { | |
| setHasReceivedFocusEvent(true); | |
| setIsFocused(false); | |
| } | |
| }; | |
| // Enable focus reporting | |
| stdout?.write(ENABLE_FOCUS_REPORTING); | |
| stdin?.on('data', handleData); | |
| return () => { | |
| // Disable focus reporting on cleanup | |
| stdout?.write(DISABLE_FOCUS_REPORTING); | |
| stdin?.removeListener('data', handleData); | |
| }; | |
| }, [stdin, stdout]); | |
| useKeypress( | |
| (_) => { | |
| if (!isFocused) { | |
| // If the user has typed a key, and we cannot possibly be focused out. | |
| // This is a workaround for some tmux use cases. It is still useful to | |
| // listen for the true FOCUS_IN event as well as that will update the | |
| // focus state earlier than waiting for a keypress. | |
| setIsFocused(true); | |
| } | |
| }, | |
| { isActive: true }, | |
| ); | |
| return { | |
| isFocused, | |
| hasReceivedFocusEvent, | |
| }; | |
| }; | |