summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrari404 <[email protected]>2025-12-13 00:50:09 -0500
committerGitHub <[email protected]>2025-12-12 23:50:09 -0600
commit8917a4c609362d407a8a4e2f25423d474215edda (patch)
tree2531fbf28ead093869949f7e3e4f2b78ce5b7f4c
parent5d7a52f8b8d2334348467778a049a4cc96a0dca4 (diff)
downloadopencode-8917a4c609362d407a8a4e2f25423d474215edda.tar.gz
opencode-8917a4c609362d407a8a4e2f25423d474215edda.zip
feat: add texlab language server and latexindent formatter (#5251)
-rw-r--r--packages/opencode/src/format/formatter.ts9
-rw-r--r--packages/opencode/src/lsp/server.ts84
2 files changed, 93 insertions, 0 deletions
diff --git a/packages/opencode/src/format/formatter.ts b/packages/opencode/src/format/formatter.ts
index bcde6e7aa..4e49bb324 100644
--- a/packages/opencode/src/format/formatter.ts
+++ b/packages/opencode/src/format/formatter.ts
@@ -275,3 +275,12 @@ export const terraform: Info = {
return Bun.which("terraform") !== null
},
}
+
+export const latexindent: Info = {
+ name: "latexindent",
+ command: ["latexindent", "-w", "-s", "$FILE"],
+ extensions: [".tex"],
+ async enabled() {
+ return Bun.which("latexindent") !== null
+ },
+}
diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts
index daee7db73..5230117ee 100644
--- a/packages/opencode/src/lsp/server.ts
+++ b/packages/opencode/src/lsp/server.ts
@@ -1386,4 +1386,88 @@ export namespace LSPServer {
}
},
}
+
+ export const TexLab: Info = {
+ id: "texlab",
+ extensions: [".tex", ".bib"],
+ root: NearestRoot([".latexmkrc", "latexmkrc", ".texlabroot", "texlabroot"]),
+ async spawn(root) {
+ let bin = Bun.which("texlab", {
+ PATH: process.env["PATH"] + ":" + Global.Path.bin,
+ })
+
+ if (!bin) {
+ if (Flag.OPENCODE_DISABLE_LSP_DOWNLOAD) return
+ log.info("downloading texlab from GitHub releases")
+
+ const response = await fetch("https://api.github.com/repos/latex-lsp/texlab/releases/latest")
+ if (!response.ok) {
+ log.error("Failed to fetch texlab release info")
+ return
+ }
+
+ const release = (await response.json()) as {
+ tag_name?: string
+ assets?: { name?: string; browser_download_url?: string }[]
+ }
+ const version = release.tag_name?.replace("v", "")
+ if (!version) {
+ log.error("texlab release did not include a version tag")
+ return
+ }
+
+ const platform = process.platform
+ const arch = process.arch
+
+ const texArch = arch === "arm64" ? "aarch64" : "x86_64"
+ const texPlatform = platform === "darwin" ? "macos" : platform === "win32" ? "windows" : "linux"
+ const ext = platform === "win32" ? "zip" : "tar.gz"
+ const assetName = `texlab-${texArch}-${texPlatform}.${ext}`
+
+ const assets = release.assets ?? []
+ const asset = assets.find((a) => a.name === assetName)
+ if (!asset?.browser_download_url) {
+ log.error(`Could not find asset ${assetName} in texlab release`)
+ return
+ }
+
+ const downloadResponse = await fetch(asset.browser_download_url)
+ if (!downloadResponse.ok) {
+ log.error("Failed to download texlab")
+ return
+ }
+
+ const tempPath = path.join(Global.Path.bin, assetName)
+ await Bun.file(tempPath).write(downloadResponse)
+
+ if (ext === "zip") {
+ await $`unzip -o -q ${tempPath}`.cwd(Global.Path.bin).nothrow()
+ }
+ if (ext === "tar.gz") {
+ await $`tar -xzf ${tempPath}`.cwd(Global.Path.bin).nothrow()
+ }
+
+ await fs.rm(tempPath, { force: true })
+
+ bin = path.join(Global.Path.bin, "texlab" + (platform === "win32" ? ".exe" : ""))
+
+ if (!(await Bun.file(bin).exists())) {
+ log.error("Failed to extract texlab binary")
+ return
+ }
+
+ if (platform !== "win32") {
+ await $`chmod +x ${bin}`.nothrow()
+ }
+
+ log.info("installed texlab", { bin })
+ }
+
+ return {
+ process: spawn(bin, {
+ cwd: root,
+ }),
+ }
+ },
+ }
}