package lsp import ( "fmt" "os" "os/exec" ) type LSPServer struct { Name string `json:"name"` Language string `json:"language"` Command string `json:"command"` InstallCmd string `json:"install_cmd"` Installed bool `json:"installed"` } var knownServers = []LSPServer{ {Name: "gopls", Language: "go", Command: "gopls", InstallCmd: "go install golang.org/x/tools/gopls@latest"}, {Name: "pyright", Language: "python", Command: "pyright", InstallCmd: "npm install -g pyright"}, {Name: "typescript-language-server", Language: "typescript", Command: "typescript-language-server", InstallCmd: "npm install -g typescript-language-server typescript"}, {Name: "vscode-json-language-server", Language: "json", Command: "vscode-json-language-server", InstallCmd: "npm install -g vscode-langservers-extracted"}, {Name: "vscode-html-language-server", Language: "html", Command: "vscode-html-language-server", InstallCmd: "npm install -g vscode-langservers-extracted"}, {Name: "vscode-css-language-server", Language: "css", Command: "vscode-css-language-server", InstallCmd: "npm install -g vscode-langservers-extracted"}, {Name: "yaml-language-server", Language: "yaml", Command: "yaml-language-server", InstallCmd: "npm install -g yaml-language-server"}, {Name: "bash-language-server", Language: "bash", Command: "bash-language-server", InstallCmd: "npm install -g bash-language-server"}, {Name: "rust-analyzer", Language: "rust", Command: "rust-analyzer", InstallCmd: "rustup component add rust-analyzer"}, {Name: "clangd", Language: "c/c++", Command: "clangd", InstallCmd: ""}, {Name: "lua-language-server", Language: "lua", Command: "lua-language-server", InstallCmd: "npm install -g lua-language-server"}, {Name: "dockerfile-language-server", Language: "dockerfile", Command: "docker-langserver", InstallCmd: "npm install -g dockerfile-language-server-nodejs"}, {Name: "tailwindcss-language-server", Language: "tailwind", Command: "tailwindcss-language-server", InstallCmd: "npm install -g @tailwindcss/language-server"}, {Name: "svelte-language-server", Language: "svelte", Command: "svelteserver", InstallCmd: "npm install -g svelte-language-server"}, {Name: "vue-language-server", Language: "vue", Command: "vue-language-server", InstallCmd: "npm install -g @vue/language-server"}, {Name: "golangci-lint-langserver", Language: "go-lint", Command: "golangci-lint-langserver", InstallCmd: "go install github.com/nametake/golangci-lint-langserver@latest"}, } func ScanServers() []LSPServer { servers := make([]LSPServer, len(knownServers)) for i, s := range knownServers { servers[i] = s _, err := exec.LookPath(s.Command) servers[i].Installed = err == nil } return servers } func InstallServer(name string) error { for _, s := range knownServers { if s.Name == name { if s.InstallCmd == "" { return fmt.Errorf("%s has no auto-install command, install manually", name) } cmd := exec.Command("bash", "-c", s.InstallCmd) cmd.Env = os.Environ() if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("install %s: %s: %w", name, string(output), err) } return nil } } return fmt.Errorf("unknown LSP server: %s", name) } func InstallForLanguages(languages []string) []LSPServer { langMap := map[string][]string{ "go": {"gopls"}, "typescript": {"typescript-language-server", "vscode-json-language-server", "vscode-html-language-server", "vscode-css-language-server"}, "javascript": {"typescript-language-server", "vscode-json-language-server", "vscode-html-language-server", "vscode-css-language-server"}, "python": {"pyright"}, "rust": {"rust-analyzer"}, "c": {"clangd"}, "cpp": {"clangd"}, "json": {"vscode-json-language-server"}, "yaml": {"yaml-language-server"}, "bash": {"bash-language-server"}, "html": {"vscode-html-language-server"}, "css": {"vscode-css-language-server"}, "lua": {"lua-language-server"}, "docker": {"dockerfile-language-server"}, "svelte": {"svelte-language-server"}, "vue": {"vue-language-server"}, } installed := map[string]bool{} var results []LSPServer for _, lang := range languages { if servers, ok := langMap[lang]; ok { for _, srv := range servers { if installed[srv] { continue } installed[srv] = true if err := InstallServer(srv); err != nil { results = append(results, LSPServer{Name: srv, Language: lang, Installed: false}) } else { results = append(results, LSPServer{Name: srv, Language: lang, Installed: true}) } } } } return results }