mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 16:08:05 +00:00
fix(terminal): Open OSC 8 hyperlinks in the system browser
This commit is contained in:
@@ -11,7 +11,7 @@ import type { EmbeddedTerminal, EmbeddedTerminalOptions } from "@/workbench/cont
|
||||
import { useProject } from "@/platform/project";
|
||||
import { workflowSettings } from "@/platform/workflowSettings";
|
||||
import { findTerminalLinks } from "./links";
|
||||
import { fontFor, openExternal, openFileLink } from "./session";
|
||||
import { LINK_HANDLER, fontFor, openExternal, openFileLink } from "./session";
|
||||
import { readTerminalTheme, remeasureWhenFontsLoad } from "./theme";
|
||||
|
||||
const live = new Set<Terminal>();
|
||||
@@ -26,6 +26,7 @@ export function createEmbeddedTerminal(host: HTMLElement, opts: EmbeddedTerminal
|
||||
const settings = workflowSettings().terminal;
|
||||
const font = fontFor(settings);
|
||||
const term = new Terminal({
|
||||
linkHandler: LINK_HANDLER,
|
||||
fontFamily: font.family,
|
||||
fontSize: font.size,
|
||||
lineHeight: font.lineHeight,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* lives in a detached host element owned by the session (not by React), so a
|
||||
* session survives its tool window being hidden or its pane being re-mounted.
|
||||
*/
|
||||
import { Terminal, type IDisposable, type ILink } from "@xterm/xterm";
|
||||
import { Terminal, type IDisposable, type ILink, type ILinkHandler } from "@xterm/xterm";
|
||||
import { FitAddon } from "@xterm/addon-fit";
|
||||
import { SearchAddon, type ISearchOptions } from "@xterm/addon-search";
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
@@ -105,6 +105,18 @@ export async function openExternal(url: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OSC 8 hyperlinks (`claude` / `gh` login links…): open in the system browser.
|
||||
* xterm's default confirms with `window.confirm` and then calls `window.open`,
|
||||
* which does nothing in the app's webview.
|
||||
*/
|
||||
export const LINK_HANDLER: ILinkHandler = {
|
||||
activate: (event, uri) => {
|
||||
event.preventDefault();
|
||||
if (/^https?:\/\//i.test(uri)) void openExternal(uri);
|
||||
},
|
||||
};
|
||||
|
||||
export async function openFileLink(link: Extract<TerminalLink, { kind: "file" }>, cwd: string) {
|
||||
const selection = link.line ? { line: link.line - 1, col: Math.max(0, (link.col ?? 1) - 1) } : undefined;
|
||||
const path = resolvePath(link.path, cwd);
|
||||
@@ -188,6 +200,7 @@ export class TerminalSession {
|
||||
// Same width as the IDE's scrollbars (global.css); the slider is styled there too (Terminal.module.css).
|
||||
overviewRuler: { width: 10 },
|
||||
theme: readTerminalTheme(),
|
||||
linkHandler: LINK_HANDLER,
|
||||
});
|
||||
this.term.loadAddon(this.fit);
|
||||
this.term.loadAddon(this.searchAddon);
|
||||
|
||||
Reference in New Issue
Block a user