detect-terminal
Version:
Detect the terminal program currently being used, with support for iTerm, Terminal.app, Hyper, iTerm2, ConEmu, Cmde,r Alacritty, Xterm, Terminator, Termux, Kitty, and others. Detection is based on environment variables and process-level indicators to iden
1 lines • 15.7 kB
Source Map (JSON)
{"version":3,"sources":["../../src/color.ts","../../src/normalize.ts","../../src/env.ts"],"sourcesContent":["import type { ColorLevel } from './types';\n\nconst TRUE_COLOR_PATTERN = /^(truecolor|24bits?)$/;\n\nexport const has256Color = (value: string | undefined): boolean => {\n return Boolean(value?.match(/256/));\n};\n\nexport const supportsTrueColor = (value: string | undefined): boolean => {\n return Boolean(value?.match(TRUE_COLOR_PATTERN));\n};\n\nexport const getColorSupport = (env: NodeJS.ProcessEnv) => {\n return {\n supports256Color: has256Color(env.TERM) || has256Color(env.COLORTERM),\n supportsTrueColor: supportsTrueColor(env.COLORTERM)\n };\n};\n\nconst NO_BASIC_COLOR_TERMINALS = new Set([\n 'dumb',\n 'linux_console',\n 'none',\n 'unknown',\n 'vt100'\n]);\n\nexport const getColorLevel = (\n env: NodeJS.ProcessEnv,\n terminal?: string | null,\n colorSupport = getColorSupport(env)\n): ColorLevel => {\n const { supports256Color, supportsTrueColor } = colorSupport;\n\n if (supportsTrueColor) {\n return 3;\n }\n\n if (supports256Color) {\n return 2;\n }\n\n if (terminal && !NO_BASIC_COLOR_TERMINALS.has(terminal)) {\n return 1;\n }\n\n if (env.TERM_PROGRAM || env.COLORTERM || env.TERMUX_VERSION) {\n return 1;\n }\n\n return 0;\n};\n","import type { DetectOptions } from './types';\nimport path from 'node:path';\n\nexport const AMBIGUOUS_ENV_TERMINALS = new Set([\n 'linux_console',\n 'truecolor_terminal',\n 'vt100',\n 'xterm',\n 'xterm_256color',\n 'xterm_truecolor'\n]);\n\nexport const SHELL_PROCESS_NAMES = new Set([\n 'bash',\n 'csh',\n 'dash',\n 'fish',\n 'ksh',\n 'login',\n 'node',\n 'nodejs',\n 'nu',\n 'sh',\n 'sudo',\n 'tcsh',\n 'zsh'\n]);\n\nexport const normalizeIdentifier = (value: string): string => {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_');\n};\n\nexport const normalizeAppName = (value: string, platform: NodeJS.Platform): string => {\n const appName = platform === 'darwin' ? path.parse(value).name : value;\n return normalizeIdentifier(appName);\n};\n\nexport const isAmbiguousEnvResult = (\n terminal: string | null,\n options: DetectOptions = {}\n): boolean => {\n if (!terminal) {\n return true;\n }\n\n if (options.preferOuter && (terminal === 'tmux' || terminal === 'screen')) {\n return true;\n }\n\n return AMBIGUOUS_ENV_TERMINALS.has(terminal);\n};\n\nexport const hasKonsoleEnvironment = (env: NodeJS.ProcessEnv): boolean => {\n return Object.keys(env).some(envVar => /konsole/i.test(envVar));\n};\n\nexport const normalizeParentProcessName = (processName: string): string | null => {\n const normalized = normalizeIdentifier(path.parse(processName).name);\n\n switch (normalized) {\n case 'alacritty':\n case 'aterm':\n case 'atomic_terminal':\n case 'eterm':\n case 'foot':\n case 'ghostty':\n case 'hyper':\n case 'kitty':\n case 'konsole':\n case 'kuake':\n case 'mate_terminal':\n case 'mrxvt':\n case 'powershell':\n case 'putty':\n case 'qterminal':\n case 'rio':\n case 'rxvt':\n case 'terminator':\n case 'terminology':\n case 'tilda':\n case 'tmux':\n case 'warp':\n case 'wezterm':\n case 'wterm':\n return normalized;\n case 'apple_terminal':\n case 'terminal':\n return 'terminal';\n case 'cmd':\n return 'cmd';\n case 'code':\n case 'code_insiders':\n return 'vscode';\n case 'conhost':\n return 'conhost';\n case 'gnome':\n case 'gnome_terminal':\n case 'gnome_terminal_server':\n case 'guake':\n return 'gnome_terminal';\n case 'iterm':\n case 'iterm2':\n return 'iterm';\n case 'login':\n case 'linux':\n return 'linux_console';\n case 'pwsh':\n return 'powershell';\n case 'screen':\n return 'screen';\n case 'terminal_app':\n return 'terminal_app';\n case 'urxvt':\n case 'urxvt256c':\n case 'urxvt256c_ml':\n case 'urxvt_ml':\n return 'rxvt';\n case 'wt':\n case 'windows_terminal':\n return 'windows_terminal';\n case 'xfce':\n case 'xfce_terminal':\n case 'xfce4_terminal':\n return 'xfce4_terminal';\n default: {\n if (normalized.startsWith('gnome_terminal')) {\n return 'gnome_terminal';\n }\n\n if (normalized.startsWith('warp')) {\n return 'warp';\n }\n\n return null;\n }\n }\n};\n","import type { DetectOptions, DetectionResult } from './types';\nimport { getColorSupport } from './color';\nimport {\n hasKonsoleEnvironment,\n normalizeAppName,\n normalizeIdentifier\n} from './normalize';\n\nconst colorVariant = (\n terminal: string,\n supports256Color: boolean,\n supportsTrueColor: boolean\n): string => {\n return supports256Color || supportsTrueColor ? `${terminal}_256color` : terminal;\n};\n\nconst normalizeTermProgram = (termProgram: string): string | null => {\n switch (termProgram) {\n case 'apple_terminal':\n return 'terminal';\n case 'eterm':\n return 'eterm';\n case 'gnome_terminal':\n case 'gnome_terminal_server':\n return 'gnome_terminal';\n case 'hyper':\n return 'hyper';\n case 'iterm_app':\n case 'iterm':\n case 'iterm2':\n return 'iterm';\n case 'kitty':\n return 'kitty';\n case 'konsole':\n return 'konsole';\n case 'mate_terminal':\n return 'mate_terminal';\n case 'powershell':\n return 'powershell';\n case 'putty':\n return 'putty';\n case 'qterminal':\n return 'qterminal';\n case 'rio':\n return 'rio';\n case 'rxvt':\n return 'rxvt';\n case 'terminal_app':\n return 'terminal_app';\n case 'terminal':\n return 'terminal';\n case 'terminator':\n return 'terminator';\n case 'termux':\n return 'termux';\n case 'vscode':\n return 'vscode';\n case 'warp':\n return 'warp';\n case 'wezterm':\n return 'wezterm';\n case 'xfce4_terminal':\n return 'xfce4_terminal';\n case 'alacritty':\n return 'alacritty';\n default:\n return null;\n }\n};\n\nconst detectFromTerm = (\n term: string,\n env: NodeJS.ProcessEnv,\n platform: NodeJS.Platform\n): string => {\n const { supports256Color, supportsTrueColor } = getColorSupport(env);\n\n if (term === 'xterm' || term === 'xterm_256color') {\n if (supportsTrueColor) {\n return 'xterm_truecolor';\n }\n\n if (env.VTE_VERSION) {\n const vteVersion = Number.parseInt(env.VTE_VERSION, 10);\n if (vteVersion >= 3803) {\n return colorVariant('gnome_terminal', supports256Color, supportsTrueColor);\n }\n }\n\n if (hasKonsoleEnvironment(env)) {\n return colorVariant('konsole', supports256Color, supportsTrueColor);\n }\n\n if (platform === 'darwin') {\n return 'terminal';\n }\n\n return term;\n }\n\n switch (term) {\n case 'linux':\n return 'linux_console';\n case 'gnome':\n case 'gnome_256color':\n case 'gnome_terminal':\n case 'gnome_terminal_256color':\n case 'guake':\n case 'terminator':\n return colorVariant('gnome_terminal', supports256Color, supportsTrueColor);\n case 'konsole':\n return colorVariant('konsole', supports256Color, supportsTrueColor);\n case 'rxvt':\n case 'rxvt_xpm':\n case 'rxvt_unicode':\n case 'rxvt_unicode_256color':\n case 'urxvt':\n case 'urxvt_ml':\n case 'urxvt256c':\n case 'urxvt256c_ml':\n return colorVariant('rxvt', term === 'rxvt' || supports256Color, supportsTrueColor);\n case 'xfce':\n case 'xfce_terminal':\n case 'xfce4_terminal':\n return 'xfce4_terminal';\n case 'eterm':\n return colorVariant('eterm', supports256Color, supportsTrueColor);\n case 'xterm_kitty':\n case 'kitty':\n return 'kitty';\n case 'screen':\n case 'screen_256color':\n return 'screen';\n case 'tmux':\n case 'tmux_256color':\n return 'tmux';\n case 'vt100':\n return 'vt100';\n case 'aterm':\n case 'atomic_terminal':\n case 'dopamine':\n case 'foot':\n case 'ghostty':\n case 'kuake':\n case 'rio':\n case 'terminology':\n case 'termux':\n case 'tilda':\n case 'wterm':\n case 'mrxvt':\n return term;\n default:\n if (/screen/.test(term)) return 'screen';\n if (/tmux/.test(term)) return 'tmux';\n if (/rxvt/.test(term)) return 'rxvt';\n if (/vt100/.test(term)) return 'vt100';\n if (/linux/.test(term)) return 'linux_console';\n if (/alacritty/.test(term)) return 'alacritty';\n if (/dopamine/.test(term)) return 'dopamine';\n if (/kitty/.test(term)) return 'kitty';\n if (/ghostty/.test(term)) return 'ghostty';\n if (/^foot/.test(term)) return 'foot';\n if (/^rio/.test(term)) return 'rio';\n return term;\n }\n};\n\nexport const detectFromEnvResult = (\n options: DetectOptions = {}\n): DetectionResult | null => {\n const env = options.env ?? process.env;\n const platform = options.platform ?? process.platform;\n const term = env.TERM ? normalizeIdentifier(env.TERM) : undefined;\n\n if (platform === 'android' && env.TERMUX_VERSION) {\n return { terminal: 'termux', source: 'env', generic: term };\n }\n\n if (!options.preferOuter && term) {\n if (term.startsWith('tmux')) {\n return { terminal: 'tmux', source: 'env', generic: term };\n }\n if (term.startsWith('screen')) {\n return { terminal: 'screen', source: 'env', generic: term };\n }\n }\n\n if (env.KITTY_PID) {\n return { terminal: 'kitty', source: 'env', generic: term };\n }\n\n if (env.GHOSTTY_RESOURCES_DIR) {\n return { terminal: 'ghostty', source: 'env', generic: term };\n }\n\n if (env.ALACRITTY_SOCKET || env.ALACRITTY_LOG) {\n return { terminal: 'alacritty', source: 'env', generic: term };\n }\n\n const termProgram = env.TERM_PROGRAM\n ? normalizeAppName(env.TERM_PROGRAM, platform)\n : undefined;\n\n if (termProgram) {\n return {\n terminal: normalizeTermProgram(termProgram) ?? termProgram,\n source: 'env',\n generic: term\n };\n }\n\n if (\n typeof env.VSCODE_PID !== 'undefined' ||\n (typeof env.TERM_PROGRAM_VERSION !== 'undefined' &&\n /vscode/i.test(env.TERM_PROGRAM_VERSION))\n ) {\n return { terminal: 'vscode', source: 'env', generic: term };\n }\n\n if (term && term !== 'unknown') {\n return {\n terminal: detectFromTerm(term, env, platform),\n source: 'env',\n generic: term\n };\n }\n\n const colorTerm = env.COLORTERM ? normalizeIdentifier(env.COLORTERM) : undefined;\n\n if (colorTerm === 'truecolor' || colorTerm === '24bit' || colorTerm === '24bits') {\n return { terminal: 'truecolor_terminal', source: 'env', generic: term };\n }\n\n if (colorTerm) {\n return { terminal: colorTerm, source: 'env', generic: term };\n }\n\n return null;\n};\n\nexport const detectFromEnv = (options: DetectOptions = {}): string | null => {\n return detectFromEnvResult(options)?.terminal ?? null;\n};\n"],"mappings":"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","names":["supportsTrueColor"]}