summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/opencode/src/lsp/server.ts122
-rw-r--r--packages/web/src/content/docs/lsp.mdx1
2 files changed, 123 insertions, 0 deletions
diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts
index 49b55aba7..3969a64e8 100644
--- a/packages/opencode/src/lsp/server.ts
+++ b/packages/opencode/src/lsp/server.ts
@@ -838,4 +838,126 @@ export namespace LSPServer {
}
},
}
+
+ export const LuaLS: Info = {
+ id: "lua-ls",
+ root: NearestRoot([
+ ".luarc.json",
+ ".luarc.jsonc",
+ ".luacheckrc",
+ ".stylua.toml",
+ "stylua.toml",
+ "selene.toml",
+ "selene.yml",
+ ]),
+ extensions: [".lua"],
+ async spawn(root) {
+ let bin = Bun.which("lua-language-server", {
+ PATH: process.env["PATH"] + ":" + Global.Path.bin,
+ })
+
+ if (!bin) {
+ if (Flag.OPENCODE_DISABLE_LSP_DOWNLOAD) return
+ log.info("downloading lua-language-server from GitHub releases")
+
+ const releaseResponse = await fetch("https://api.github.com/repos/LuaLS/lua-language-server/releases/latest")
+ if (!releaseResponse.ok) {
+ log.error("Failed to fetch lua-language-server release info")
+ return
+ }
+
+ const release = await releaseResponse.json()
+
+ const platform = process.platform
+ const arch = process.arch
+ let assetName = ""
+
+ let lualsArch: string = arch
+ if (arch === "arm64") lualsArch = "arm64"
+ else if (arch === "x64") lualsArch = "x64"
+ else if (arch === "ia32") lualsArch = "ia32"
+
+ let lualsPlatform: string = platform
+ if (platform === "darwin") lualsPlatform = "darwin"
+ else if (platform === "linux") lualsPlatform = "linux"
+ else if (platform === "win32") lualsPlatform = "win32"
+
+ const ext = platform === "win32" ? "zip" : "tar.gz"
+
+ assetName = `lua-language-server-${release.tag_name}-${lualsPlatform}-${lualsArch}.${ext}`
+
+ const supportedCombos = [
+ "darwin-arm64.tar.gz",
+ "darwin-x64.tar.gz",
+ "linux-x64.tar.gz",
+ "linux-arm64.tar.gz",
+ "win32-x64.zip",
+ "win32-ia32.zip",
+ ]
+
+ const assetSuffix = `${lualsPlatform}-${lualsArch}.${ext}`
+ if (!supportedCombos.includes(assetSuffix)) {
+ log.error(`Platform ${platform} and architecture ${arch} is not supported by lua-language-server`)
+ return
+ }
+
+ const asset = release.assets.find((a: any) => a.name === assetName)
+ if (!asset) {
+ log.error(`Could not find asset ${assetName} in latest lua-language-server release`)
+ return
+ }
+
+ const downloadUrl = asset.browser_download_url
+ const downloadResponse = await fetch(downloadUrl)
+ if (!downloadResponse.ok) {
+ log.error("Failed to download lua-language-server")
+ return
+ }
+
+ const tempPath = path.join(Global.Path.bin, assetName)
+ await Bun.file(tempPath).write(downloadResponse)
+
+ // Unlike zls which is a single self-contained binary,
+ // lua-language-server needs supporting files (meta/, locale/, etc.)
+ // Extract entire archive to dedicated directory to preserve all files
+ const installDir = path.join(Global.Path.bin, `lua-language-server-${lualsArch}-${lualsPlatform}`)
+
+ // Remove old installation if exists
+ const stats = await fs.stat(installDir).catch(() => undefined)
+ if (stats) {
+ await fs.rm(installDir, { force: true, recursive: true })
+ }
+
+ await fs.mkdir(installDir, { recursive: true })
+
+ if (ext === "zip") {
+ await $`unzip -o -q ${tempPath} -d ${installDir}`.quiet().nothrow()
+ } else {
+ await $`tar -xzf ${tempPath} -C ${installDir}`.nothrow()
+ }
+
+ await fs.rm(tempPath, { force: true })
+
+ // Binary is located in bin/ subdirectory within the extracted archive
+ bin = path.join(installDir, "bin", "lua-language-server" + (platform === "win32" ? ".exe" : ""))
+
+ if (!(await Bun.file(bin).exists())) {
+ log.error("Failed to extract lua-language-server binary")
+ return
+ }
+
+ if (platform !== "win32") {
+ await $`chmod +x ${bin}`.nothrow()
+ }
+
+ log.info(`installed lua-language-server`, { bin })
+ }
+
+ return {
+ process: spawn(bin, {
+ cwd: root,
+ }),
+ }
+ },
+ }
}
diff --git a/packages/web/src/content/docs/lsp.mdx b/packages/web/src/content/docs/lsp.mdx
index da7d5dde8..97aadab57 100644
--- a/packages/web/src/content/docs/lsp.mdx
+++ b/packages/web/src/content/docs/lsp.mdx
@@ -28,6 +28,7 @@ OpenCode comes with several built-in LSP servers for popular languages:
| svelte | .svelte | Auto-installs for Svelte projects |
| astro | .astro | Auto-installs for Astro projects |
| jdtls | .java | `Java SDK (version 21+)` installed |
+| lua-ls | .lua | Auto-installs for Lua projects |
LSP servers are automatically enabled when one of the above file extensions are detected and the requirements are met.