[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
118
components/terminal/runtime/cursorPreference.ts
Normal file
118
components/terminal/runtime/cursorPreference.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import type { IDisposable, Terminal as XTerm } from "@xterm/xterm";
|
||||
import type { RefObject } from "react";
|
||||
|
||||
import type { TerminalSettings } from "../../../types";
|
||||
|
||||
type CursorPreferenceSettings = Pick<TerminalSettings, "cursorShape" | "cursorBlink">;
|
||||
|
||||
type MutableCursorOptions = {
|
||||
cursorStyle?: "block" | "bar" | "underline";
|
||||
cursorBlink?: boolean;
|
||||
};
|
||||
|
||||
type TerminalLike = {
|
||||
options: MutableCursorOptions;
|
||||
parser?: {
|
||||
registerCsiHandler?: (
|
||||
id: { prefix?: string; intermediates?: string; final: string },
|
||||
callback: (params: readonly (number | number[])[]) => boolean,
|
||||
) => IDisposable;
|
||||
};
|
||||
_core?: {
|
||||
coreService?: {
|
||||
decPrivateModes?: {
|
||||
cursorStyle?: "block" | "bar" | "underline";
|
||||
cursorBlink?: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const scheduleAfterDefaultHandler = (callback: () => void): void => {
|
||||
if (typeof queueMicrotask === "function") {
|
||||
queueMicrotask(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
|
||||
const hasCursorBlinkPrivateModeParam = (params: readonly (number | number[])[]): boolean => (
|
||||
params.some((param) => (
|
||||
Array.isArray(param)
|
||||
? param.includes(12)
|
||||
: param === 12
|
||||
))
|
||||
);
|
||||
|
||||
export const resolveUserCursorPreference = (
|
||||
settings: Partial<CursorPreferenceSettings> | undefined,
|
||||
): Required<CursorPreferenceSettings> => ({
|
||||
cursorShape: settings?.cursorShape ?? "block",
|
||||
cursorBlink: settings?.cursorBlink ?? true,
|
||||
});
|
||||
|
||||
export const applyUserCursorPreference = (
|
||||
term: TerminalLike,
|
||||
settings: Partial<CursorPreferenceSettings> | undefined,
|
||||
): void => {
|
||||
const preference = resolveUserCursorPreference(settings);
|
||||
const privateModes = term._core?.coreService?.decPrivateModes;
|
||||
if (privateModes) {
|
||||
privateModes.cursorStyle = undefined;
|
||||
privateModes.cursorBlink = undefined;
|
||||
}
|
||||
term.options.cursorStyle = preference.cursorShape;
|
||||
term.options.cursorBlink = preference.cursorBlink;
|
||||
};
|
||||
|
||||
export const applyUserCursorBlinkPreference = (
|
||||
term: TerminalLike,
|
||||
settings: Partial<CursorPreferenceSettings> | undefined,
|
||||
): void => {
|
||||
const preference = resolveUserCursorPreference(settings);
|
||||
const privateModes = term._core?.coreService?.decPrivateModes;
|
||||
if (privateModes) {
|
||||
privateModes.cursorBlink = undefined;
|
||||
}
|
||||
term.options.cursorBlink = preference.cursorBlink;
|
||||
};
|
||||
|
||||
export const installUserCursorPreferenceGuard = (
|
||||
term: XTerm | TerminalLike,
|
||||
terminalSettingsRef: RefObject<TerminalSettings | undefined>,
|
||||
): IDisposable | null => {
|
||||
const terminal = term as TerminalLike;
|
||||
const parser = terminal.parser;
|
||||
if (!parser?.registerCsiHandler) return null;
|
||||
const registerCsiHandler = parser.registerCsiHandler.bind(parser);
|
||||
|
||||
const applyBlinkPreference = () => applyUserCursorBlinkPreference(terminal, terminalSettingsRef.current);
|
||||
|
||||
const cursorStyleDisposable = registerCsiHandler({ intermediates: " ", final: "q" }, () => {
|
||||
scheduleAfterDefaultHandler(applyBlinkPreference);
|
||||
return false;
|
||||
});
|
||||
|
||||
const cursorBlinkSetDisposable = registerCsiHandler({ prefix: "?", final: "h" }, (params) => {
|
||||
if (hasCursorBlinkPrivateModeParam(params)) {
|
||||
scheduleAfterDefaultHandler(applyBlinkPreference);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const cursorBlinkResetDisposable = registerCsiHandler({ prefix: "?", final: "l" }, (params) => {
|
||||
if (hasCursorBlinkPrivateModeParam(params)) {
|
||||
scheduleAfterDefaultHandler(applyBlinkPreference);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
cursorStyleDisposable.dispose();
|
||||
cursorBlinkSetDisposable.dispose();
|
||||
cursorBlinkResetDisposable.dispose();
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user