refactor(tui): extract standalone package (#31193)
This commit is contained in:
parent
7a2c49e762
commit
106f8e94d6
84 changed files with 1147 additions and 1918 deletions
84
packages/tui/src/editor.ts
Normal file
84
packages/tui/src/editor.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import type { CliRenderer } from "@opentui/core"
|
||||
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"
|
||||
import { readFile, rm, writeFile } from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
import path from "node:path"
|
||||
import { spawn } from "node:child_process"
|
||||
import { resolveZedDbPath, resolveZedSelection } from "./editor-zed"
|
||||
|
||||
export async function openEditor(input: { value: string; renderer: CliRenderer; cwd?: string }) {
|
||||
const editor = process.env.VISUAL || process.env.EDITOR
|
||||
if (!editor) return
|
||||
const file = path.join(os.tmpdir(), `${Date.now()}.md`)
|
||||
await writeFile(file, input.value)
|
||||
input.renderer.suspend()
|
||||
input.renderer.currentRenderBuffer.clear()
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const parts = editor.split(" ")
|
||||
const child = spawn(parts[0]!, [...parts.slice(1), file], {
|
||||
cwd: input.cwd && existsSync(input.cwd) ? input.cwd : process.cwd(),
|
||||
stdio: "inherit",
|
||||
shell: process.platform === "win32",
|
||||
})
|
||||
child.on("error", reject)
|
||||
child.on("exit", (code, signal) => {
|
||||
if (code === 0) return resolve()
|
||||
reject(new Error(`Editor exited with ${signal ? `signal ${signal}` : `code ${code}`}`))
|
||||
})
|
||||
})
|
||||
return (await readFile(file, "utf8")) || undefined
|
||||
} finally {
|
||||
await rm(file, { force: true }).catch(() => {})
|
||||
input.renderer.currentRenderBuffer.clear()
|
||||
input.renderer.resume()
|
||||
input.renderer.requestRender()
|
||||
}
|
||||
}
|
||||
|
||||
export function discoverEditorConnection(directory: string) {
|
||||
const root = path.join(os.homedir(), ".claude", "ide")
|
||||
const contains = (parent: string) => {
|
||||
const resolved = path.resolve(parent)
|
||||
const relative = path.relative(resolved, path.resolve(directory))
|
||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative)) ? resolved.length : 0
|
||||
}
|
||||
try {
|
||||
return readdirSync(root)
|
||||
.filter((entry) => entry.endsWith(".lock"))
|
||||
.flatMap((entry) => {
|
||||
const file = path.join(root, entry)
|
||||
const port = Number.parseInt(path.basename(file, ".lock"), 10)
|
||||
if (!Number.isInteger(port) || port <= 0 || port > 65535) return []
|
||||
try {
|
||||
const value = JSON.parse(readFileSync(file, "utf8")) as Record<string, unknown>
|
||||
if (value.transport !== undefined && value.transport !== "ws") return []
|
||||
const folders = Array.isArray(value.workspaceFolders)
|
||||
? value.workspaceFolders.filter((item): item is string => typeof item === "string")
|
||||
: []
|
||||
const score = Math.max(0, ...folders.map(contains))
|
||||
if (!score) return []
|
||||
return [
|
||||
{
|
||||
url: `ws://127.0.0.1:${port}`,
|
||||
authToken: typeof value.authToken === "string" ? value.authToken : undefined,
|
||||
source: `lock:${port}`,
|
||||
score,
|
||||
mtime: statSync(file).mtimeMs,
|
||||
},
|
||||
]
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
.sort((left, right) => right.score - left.score || right.mtime - left.mtime)
|
||||
.map(({ url, authToken, source }) => ({ url, authToken, source }))[0]
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export const editorIntegration = {
|
||||
connection: discoverEditorConnection,
|
||||
selection: (directory: string) => resolveZedSelection(resolveZedDbPath() ?? "", directory),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue