| #!/usr/bin/env bun |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import React, { useEffect, useState } from 'react' |
| import { render, Box, Text, useApp } from 'ink' |
| import Image, { |
| InkPictureProvider, |
| type TerminalInfo, |
| useTerminalInfo, |
| } from '../index.ts' |
|
|
| |
| |
| |
| |
| |
| async function probeKittyDirect(): Promise<{ protocol: string }> { |
| return new Promise(resolve => { |
| const result = { protocol: 'no-response' } |
|
|
| if (!process.stdout.isTTY || !process.stdin.isTTY) { |
| resolve(result) |
| return |
| } |
|
|
| const origPush = process.stdin.push.bind(process.stdin) |
| let resolved = false |
|
|
| const finish = (label: string) => { |
| if (resolved) return |
| resolved = true |
| process.stdin.push = origPush as any |
| result.protocol = label |
| resolve(result) |
| } |
|
|
| process.stdin.push = ((chunk: any) => { |
| const str = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk) |
|
|
| |
| if (/\x1b_Gi=31;OK\x1b\\/.test(str)) { |
| finish('kitty-ok') |
| return origPush(chunk) |
| } |
|
|
| |
| if (/\x1b\[\?(\d+(?:;\d+)*)c/.test(str)) { |
| |
| setTimeout(() => finish('no-kitty'), 200) |
| } |
|
|
| return origPush(chunk) |
| }) as any |
|
|
| const query = |
| '\x1b[8m' + |
| '\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\' + |
| '\x1b[c' + |
| '\x1b[2K\r' + |
| '\x1b[0m' |
|
|
| try { |
| process.stdin.setRawMode?.(true) |
| require('fs').writeSync(process.stdout.fd, query) |
| } catch {} |
|
|
| setTimeout(() => finish('timeout'), 2000) |
| }) |
| } |
|
|
| function DetectionApp() { |
| const { exit } = useApp() |
| const terminalInfo = useTerminalInfo() |
| const [probeResult, setProbeResult] = useState<string>('probing...') |
|
|
| useEffect(() => { |
| probeKittyDirect().then(r => { |
| setProbeResult(JSON.stringify(r)) |
| }) |
| const timer = setTimeout(() => exit(), 5000) |
| return () => clearTimeout(timer) |
| }, [exit]) |
|
|
| const env: Record<string, string | undefined> = { |
| TERM_PROGRAM: process.env.TERM_PROGRAM, |
| TERM: process.env.TERM, |
| KITTY_WINDOW_ID: process.env.KITTY_WINDOW_ID, |
| GHOSTTY_RESOURCES_DIR: process.env.GHOSTTY_RESOURCES_DIR, |
| TERM_PROGRAM_VERSION: process.env.TERM_PROGRAM_VERSION, |
| COLORTERM: process.env.COLORTERM, |
| WEZTERM_PANE: process.env.WEZTERM_PANE, |
| KONSOLE_VERSION: process.env.KONSOLE_VERSION, |
| XTERM_VERSION: process.env.XTERM_VERSION, |
| VTE_VERSION: process.env.VTE_VERSION, |
| } |
|
|
| return ( |
| <Box flexDirection="column" paddingX={1}> |
| <Text bold underline color="cyan"> |
| Terminal Detection Diagnostic |
| </Text> |
| <Text>{' '}</Text> |
| |
| <Text bold color="yellow"> |
| Environment Variables: |
| </Text> |
| {Object.entries(env).map(([k, v]) => ( |
| <Text key={k}> |
| {' '} |
| {k}: {v ?? '(not set)'} |
| </Text> |
| ))} |
| <Text>{' '}</Text> |
| |
| <Text bold color="yellow"> |
| Direct Kitty Probe (raw escape sequence): |
| </Text> |
| <Text> {probeResult}</Text> |
| <Text>{' '}</Text> |
| |
| <Text bold color="yellow"> |
| InkPictureProvider TerminalInfo: |
| </Text> |
| <Text> |
| {' '}supportsKittyGraphics: {String(terminalInfo.supportsKittyGraphics)} |
| </Text> |
| <Text> |
| {' '}supportsSixelGraphics: {String(terminalInfo.supportsSixelGraphics)} |
| </Text> |
| <Text> |
| {' '}supportsITerm2Graphics: {String(terminalInfo.supportsITerm2Graphics)} |
| </Text> |
| <Text> |
| {' '}supportsUnicode: {String(terminalInfo.supportsUnicode)} |
| </Text> |
| <Text> |
| {' '}supportsColor: {String(terminalInfo.supportsColor)} |
| </Text> |
| <Text> |
| {' '}cell: {terminalInfo.cellWidth}x{terminalInfo.cellHeight} |
| </Text> |
| <Text> |
| {' '}terminal: {terminalInfo.terminalWidth}x{terminalInfo.terminalHeight} |
| </Text> |
| </Box> |
| ) |
| } |
|
|
| const { waitUntilExit } = render( |
| <InkPictureProvider> |
| <DetectionApp /> |
| </InkPictureProvider>, |
| ) |
| await waitUntilExit() |