[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:
147
scripts/patch-xterm-macos-column-selection.cjs
Normal file
147
scripts/patch-xterm-macos-column-selection.cjs
Normal file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env node
|
||||
/* global process, console */
|
||||
"use strict";
|
||||
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const EXPECTED_XTERM_VERSION = "6.1.0-beta.292";
|
||||
const FORCE_SELECTION_OPTION = "macOptionClickForcesSelection";
|
||||
const META_OPTION = "macOptionIsMeta".padEnd(FORCE_SELECTION_OPTION.length, " ");
|
||||
|
||||
// xterm normally treats macOptionClickForcesSelection and column selection as
|
||||
// mutually exclusive. Netcatty needs both when Option is not Meta: Option must
|
||||
// keep forcing local selection inside mouse-aware programs, and that local
|
||||
// selection must retain the standard macOS rectangular shape. Patch the pinned
|
||||
// bundles at install time and fail closed if upstream changes the expected code
|
||||
// shape.
|
||||
const PATCHES = [
|
||||
{
|
||||
file: "node_modules/@xterm/xterm/lib/xterm.js",
|
||||
original: "!(f.isMac&&this._optionsService.rawOptions.macOptionClickForcesSelection)",
|
||||
replacement: `!(f.isMac&&this._optionsService.rawOptions.${META_OPTION})`,
|
||||
preserveLength: true,
|
||||
},
|
||||
{
|
||||
file: "node_modules/@xterm/xterm/lib/xterm.mjs",
|
||||
original: "!(ie&&this._optionsService.rawOptions.macOptionClickForcesSelection)",
|
||||
replacement: `!(ie&&this._optionsService.rawOptions.${META_OPTION})`,
|
||||
preserveLength: true,
|
||||
},
|
||||
{
|
||||
file: "node_modules/@xterm/xterm/src/browser/services/SelectionService.ts",
|
||||
original: "return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.macOptionClickForcesSelection);",
|
||||
replacement: `return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.${META_OPTION});`,
|
||||
preserveStatementLength: true,
|
||||
},
|
||||
{
|
||||
file: "node_modules/@xterm/xterm/lib/xterm.js.map",
|
||||
original: "return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.macOptionClickForcesSelection);",
|
||||
replacement: `return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.${META_OPTION});`,
|
||||
preserveStatementLength: true,
|
||||
},
|
||||
{
|
||||
file: "node_modules/@xterm/xterm/lib/xterm.mjs.map",
|
||||
original: "return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.macOptionClickForcesSelection);",
|
||||
replacement: `return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.${META_OPTION});`,
|
||||
preserveStatementLength: true,
|
||||
},
|
||||
];
|
||||
|
||||
function sameLengthExpression(expression, length) {
|
||||
if (expression.length > length) throw new Error("replacement expression is too long");
|
||||
// Keep generated bundle offsets stable so the shipped source maps remain valid.
|
||||
return `${expression}${" ".repeat(length - expression.length)}`;
|
||||
}
|
||||
|
||||
function sameLengthStatement(statement, length) {
|
||||
if (!statement.endsWith(";") || statement.length > length) {
|
||||
throw new Error("replacement statement cannot preserve the target length");
|
||||
}
|
||||
return `${statement.slice(0, -1)}${" ".repeat(length - statement.length)};`;
|
||||
}
|
||||
|
||||
function replacementForPatch(patch) {
|
||||
if (!patch.replacement) throw new Error(`missing replacement for ${patch.file}`);
|
||||
if (patch.preserveLength) {
|
||||
return sameLengthExpression(patch.replacement, patch.original.length);
|
||||
}
|
||||
if (patch.preserveStatementLength) {
|
||||
return sameLengthStatement(patch.replacement, patch.original.length);
|
||||
}
|
||||
return patch.replacement;
|
||||
}
|
||||
|
||||
function patchXtermSource(source, patch) {
|
||||
const replacement = replacementForPatch(patch);
|
||||
|
||||
const originalCount = source.split(patch.original).length - 1;
|
||||
const patchedCount = source.split(replacement).length - 1;
|
||||
if (originalCount === 1 && patchedCount === 0) {
|
||||
return { source: source.replace(patch.original, replacement), changed: true };
|
||||
}
|
||||
if (originalCount === 0 && patchedCount === 1) {
|
||||
return { source, changed: false };
|
||||
}
|
||||
throw new Error(
|
||||
`${patch.file}: expected exactly one original or patched selection predicate ` +
|
||||
`(original=${originalCount}, patched=${patchedCount})`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} root
|
||||
* @param {Pick<typeof fs, "rmSync">} fsImpl
|
||||
*/
|
||||
function invalidateViteCache(root = process.cwd(), fsImpl = fs) {
|
||||
const cachePath = path.resolve(root, "node_modules/.vite");
|
||||
fsImpl.rmSync(cachePath, { recursive: true, force: true });
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
function patchInstalledXterm(root = process.cwd()) {
|
||||
const packageJsonPath = path.resolve(root, "node_modules/@xterm/xterm/package.json");
|
||||
const version = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
|
||||
if (version !== EXPECTED_XTERM_VERSION) {
|
||||
throw new Error(
|
||||
`unsupported @xterm/xterm version ${version}; expected ${EXPECTED_XTERM_VERSION}`,
|
||||
);
|
||||
}
|
||||
|
||||
let changed = 0;
|
||||
for (const patch of PATCHES) {
|
||||
const absolutePath = path.resolve(root, patch.file);
|
||||
const source = fs.readFileSync(absolutePath, "utf8");
|
||||
const result = patchXtermSource(source, patch);
|
||||
if (result.changed) {
|
||||
fs.writeFileSync(absolutePath, result.source);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
const viteCachePath = invalidateViteCache(root);
|
||||
return { changed, checked: PATCHES.length, version, viteCachePath };
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
try {
|
||||
const result = patchInstalledXterm();
|
||||
console.log(
|
||||
`[patch-xterm-macos-column-selection] version=${result.version} ` +
|
||||
`changed=${result.changed} checked=${result.checked} vite-cache=invalidated`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`[patch-xterm-macos-column-selection] ERROR: ${error.message}`);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
EXPECTED_XTERM_VERSION,
|
||||
PATCHES,
|
||||
invalidateViteCache,
|
||||
patchInstalledXterm,
|
||||
patchXtermSource,
|
||||
replacementForPatch,
|
||||
sameLengthExpression,
|
||||
sameLengthStatement,
|
||||
};
|
||||
Reference in New Issue
Block a user