summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-29 22:00:08 -0400
committerDax Raad <[email protected]>2025-06-29 22:00:08 -0400
commit72d48759d73ec6f16c22c96a6eb765572e95717f (patch)
tree6c5e3c42023c8abf64c91bb1b295f4eac896610a
parent986144b377a9a95b17e5f7549d7bb598ad44bede (diff)
downloadopencode-72d48759d73ec6f16c22c96a6eb765572e95717f.tar.gz
opencode-72d48759d73ec6f16c22c96a6eb765572e95717f.zip
add ruby formatter and lsp
-rw-r--r--packages/opencode/src/format/formatter.ts27
-rw-r--r--packages/opencode/src/lsp/index.ts2
-rw-r--r--packages/opencode/src/lsp/language.ts8
-rw-r--r--packages/opencode/src/lsp/server.ts164
4 files changed, 133 insertions, 68 deletions
diff --git a/packages/opencode/src/format/formatter.ts b/packages/opencode/src/format/formatter.ts
index dd0d9279c..60ca6a32c 100644
--- a/packages/opencode/src/format/formatter.ts
+++ b/packages/opencode/src/format/formatter.ts
@@ -131,3 +131,30 @@ export const ruff: Info = {
return Bun.which("ruff") !== null
},
}
+
+export const rubocop: Info = {
+ name: "rubocop",
+ command: ["rubocop", "--autocorrect", "$FILE"],
+ extensions: [".rb", ".rake", ".gemspec", ".ru"],
+ async enabled() {
+ return Bun.which("rubocop") !== null
+ },
+}
+
+export const standardrb: Info = {
+ name: "standardrb",
+ command: ["standardrb", "--fix", "$FILE"],
+ extensions: [".rb", ".rake", ".gemspec", ".ru"],
+ async enabled() {
+ return Bun.which("standardrb") !== null
+ },
+}
+
+export const htmlbeautifier: Info = {
+ name: "htmlbeautifier",
+ command: ["htmlbeautifier", "$FILE"],
+ extensions: [".erb", ".html.erb"],
+ async enabled() {
+ return Bun.which("htmlbeautifier") !== null
+ },
+}
diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts
index f29dec378..d29cd83a9 100644
--- a/packages/opencode/src/lsp/index.ts
+++ b/packages/opencode/src/lsp/index.ts
@@ -28,7 +28,7 @@ export namespace LSP {
export async function touchFile(input: string, waitForDiagnostics?: boolean) {
const extension = path.parse(input).ext
const s = await state()
- const matches = LSPServer.All.filter((x) =>
+ const matches = Object.values(LSPServer).filter((x) =>
x.extensions.includes(extension),
)
for (const match of matches) {
diff --git a/packages/opencode/src/lsp/language.ts b/packages/opencode/src/lsp/language.ts
index 926555a12..6c0da51b0 100644
--- a/packages/opencode/src/lsp/language.ts
+++ b/packages/opencode/src/lsp/language.ts
@@ -63,6 +63,14 @@ export const LANGUAGE_EXTENSIONS: Record<string, string> = {
".cshtml": "razor",
".razor": "razor",
".rb": "ruby",
+ ".rake": "ruby",
+ ".gemspec": "ruby",
+ ".ru": "ruby",
+ ".erb": "erb",
+ ".html.erb": "erb",
+ ".js.erb": "erb",
+ ".css.erb": "erb",
+ ".json.erb": "erb",
".rs": "rust",
".scss": "scss",
".sass": "sass",
diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts
index 26160120a..bc438e0c3 100644
--- a/packages/opencode/src/lsp/server.ts
+++ b/packages/opencode/src/lsp/server.ts
@@ -19,78 +19,108 @@ export namespace LSPServer {
spawn(app: App.Info): Promise<Handle | undefined>
}
- export const All: Info[] = [
- {
- id: "typescript",
- extensions: [
- ".ts",
- ".tsx",
- ".js",
- ".jsx",
- ".mjs",
- ".cjs",
- ".mts",
- ".cts",
- ],
- async spawn(app) {
- const tsserver = await Bun.resolve(
- "typescript/lib/tsserver.js",
- app.path.cwd,
- ).catch(() => {})
- if (!tsserver) return
- const proc = spawn(
- BunProc.which(),
- ["x", "typescript-language-server", "--stdio"],
- {
- env: {
- ...process.env,
- BUN_BE_BUN: "1",
- },
+ export const Typescript: Info = {
+ id: "typescript",
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"],
+ async spawn(app) {
+ const tsserver = await Bun.resolve(
+ "typescript/lib/tsserver.js",
+ app.path.cwd,
+ ).catch(() => {})
+ if (!tsserver) return
+ const proc = spawn(
+ BunProc.which(),
+ ["x", "typescript-language-server", "--stdio"],
+ {
+ env: {
+ ...process.env,
+ BUN_BE_BUN: "1",
},
- )
- return {
- process: proc,
- initialization: {
- tsserver: {
- path: tsserver,
- },
+ },
+ )
+ return {
+ process: proc,
+ initialization: {
+ tsserver: {
+ path: tsserver,
},
- }
- },
+ },
+ }
},
- {
- id: "golang",
- extensions: [".go"],
- async spawn() {
- let bin = Bun.which("gopls", {
- PATH: process.env["PATH"] + ":" + Global.Path.bin,
+ }
+
+ export const Gopls: Info = {
+ id: "golang",
+ extensions: [".go"],
+ async spawn() {
+ let bin = Bun.which("gopls", {
+ PATH: process.env["PATH"] + ":" + Global.Path.bin,
+ })
+ if (!bin) {
+ log.info("installing gopls")
+ const proc = Bun.spawn({
+ cmd: ["go", "install", "golang.org/x/tools/gopls@latest"],
+ env: { ...process.env, GOBIN: Global.Path.bin },
+ stdout: "pipe",
+ stderr: "pipe",
+ stdin: "pipe",
+ })
+ const exit = await proc.exited
+ if (exit !== 0) {
+ log.error("Failed to install gopls")
+ return
+ }
+ bin = path.join(
+ Global.Path.bin,
+ "gopls" + (process.platform === "win32" ? ".exe" : ""),
+ )
+ log.info(`installed gopls`, {
+ bin,
})
- if (!bin) {
- log.info("installing gopls")
- const proc = Bun.spawn({
- cmd: ["go", "install", "golang.org/x/tools/gopls@latest"],
- env: { ...process.env, GOBIN: Global.Path.bin },
- stdout: "pipe",
- stderr: "pipe",
- stdin: "pipe",
- })
- const exit = await proc.exited
- if (exit !== 0) {
- log.error("Failed to install gopls")
- return
- }
- bin = path.join(
- Global.Path.bin,
- "gopls" + (process.platform === "win32" ? ".exe" : ""),
- )
- log.info(`installed gopls`, {
- bin,
- })
+ }
+ return {
+ process: spawn(bin!),
+ }
+ },
+ }
+
+ export const RubyLsp: Info = {
+ id: "ruby-lsp",
+ extensions: [".rb", ".rake", ".gemspec", ".ru"],
+ async spawn() {
+ let bin = Bun.which("ruby-lsp", {
+ PATH: process.env["PATH"] + ":" + Global.Path.bin,
+ })
+ if (!bin) {
+ const ruby = Bun.which("ruby")
+ const gem = Bun.which("gem")
+ if (!ruby || !gem) {
+ log.info("Ruby not found, please install Ruby first")
+ return
}
- return {
- process: spawn(bin!),
+ log.info("installing ruby-lsp")
+ const proc = Bun.spawn({
+ cmd: ["gem", "install", "ruby-lsp", "--bindir", Global.Path.bin],
+ stdout: "pipe",
+ stderr: "pipe",
+ stdin: "pipe",
+ })
+ const exit = await proc.exited
+ if (exit !== 0) {
+ log.error("Failed to install ruby-lsp")
+ return
}
- },
+ bin = path.join(
+ Global.Path.bin,
+ "ruby-lsp" + (process.platform === "win32" ? ".exe" : ""),
+ )
+ log.info(`installed ruby-lsp`, {
+ bin,
+ })
+ }
+ return {
+ process: spawn(bin!, ["--stdio"]),
+ }
},
- ]
+ }
}