/** * LSP CLI 命令 * 提供语言服务器的查询和安装功能 */ import { execSync, spawnSync } from 'child_process'; import { getUniqueServers, type ServerConfig, type InstallConfig } from './server.js'; import type { LanguageId } from './language.js'; // 服务器状态 export interface ServerStatus { id: string; displayName: string; description: string; command: string; installed: boolean; languages: LanguageId[]; install: InstallConfig; } /** * 检查命令是否存在 */ function commandExists(command: string): boolean { try { execSync(`which ${command}`, { stdio: 'ignore' }); return true; } catch { return false; } } /** * 检查包管理器是否可用 */ function hasPackageManager(manager: string): boolean { return commandExists(manager); } /** * 获取所有服务器状态 */ export function listServers(): ServerStatus[] { const servers = getUniqueServers(); return servers.map((server) => ({ id: server.id, displayName: server.config.displayName, description: server.config.description, command: server.config.command, installed: commandExists(server.config.command), languages: server.languages, install: server.config.install, })); } /** * 打印服务器列表 */ export function printServerList(): void { const servers = listServers(); console.log('\n语言服务器状态:\n'); console.log(' 状态 | 服务器 | 支持语言'); console.log(' ------+--------------------------------+------------------'); for (const server of servers) { const status = server.installed ? ' ✓ ' : ' ✗ '; const statusColor = server.installed ? '\x1b[32m' : '\x1b[31m'; const reset = '\x1b[0m'; const name = server.displayName.padEnd(30); const langs = server.languages.slice(0, 3).join(', ') + (server.languages.length > 3 ? '...' : ''); console.log(` ${statusColor}${status}${reset} | ${name} | ${langs}`); } const installed = servers.filter((s) => s.installed).length; console.log(`\n 已安装: ${installed}/${servers.length}\n`); } /** * 获取安装命令 */ function getInstallCommand(install: InstallConfig): { command: string; description: string } | null { // 优先使用 npm if (install.npm && hasPackageManager('npm')) { return { command: `npm install -g ${install.npm}`, description: 'npm', }; } // pip if (install.pip && hasPackageManager('pip3')) { return { command: `pip3 install ${install.pip}`, description: 'pip3', }; } if (install.pip && hasPackageManager('pip')) { return { command: `pip install ${install.pip}`, description: 'pip', }; } // go if (install.go && hasPackageManager('go')) { return { command: `go install ${install.go}`, description: 'go install', }; } // rustup if (install.rustup && hasPackageManager('rustup')) { return { command: `rustup component add ${install.rustup}`, description: 'rustup', }; } // cargo if (install.cargo && hasPackageManager('cargo')) { return { command: `cargo install ${install.cargo}`, description: 'cargo', }; } // brew if (install.brew && hasPackageManager('brew')) { return { command: `brew install ${install.brew}`, description: 'Homebrew', }; } // gem if (install.gem && hasPackageManager('gem')) { return { command: `gem install ${install.gem}`, description: 'RubyGems', }; } // custom if (install.custom) { return { command: install.custom, description: '自定义命令', }; } return null; } /** * 安装服务器 */ export async function installServer(serverId: string): Promise { const servers = listServers(); const server = servers.find( (s) => s.id === serverId || s.displayName.toLowerCase() === serverId.toLowerCase() ); if (!server) { console.error(`\x1b[31m错误: 未找到服务器 "${serverId}"\x1b[0m`); console.log('\n可用的服务器:'); servers.forEach((s) => console.log(` - ${s.displayName} (${s.id})`)); return false; } if (server.installed) { console.log(`\x1b[32m✓ ${server.displayName} 已安装\x1b[0m`); return true; } const installCmd = getInstallCommand(server.install); if (!installCmd) { console.error(`\x1b[31m无法自动安装 ${server.displayName}\x1b[0m`); if (server.install.manual) { console.log('\n手动安装说明:'); console.log(server.install.manual); } return false; } console.log(`\n正在安装 ${server.displayName}...`); console.log(`使用 ${installCmd.description}: ${installCmd.command}\n`); try { const result = spawnSync(installCmd.command, { shell: true, stdio: 'inherit', }); if (result.status === 0) { console.log(`\n\x1b[32m✓ ${server.displayName} 安装成功\x1b[0m`); return true; } else { console.error(`\n\x1b[31m✗ ${server.displayName} 安装失败\x1b[0m`); if (server.install.manual) { console.log('\n手动安装说明:'); console.log(server.install.manual); } return false; } } catch (error) { console.error(`\n\x1b[31m安装出错: ${error}\x1b[0m`); return false; } } /** * 安装所有服务器 */ export async function installAllServers(): Promise { const servers = listServers(); const notInstalled = servers.filter((s) => !s.installed); if (notInstalled.length === 0) { console.log('\x1b[32m所有语言服务器都已安装\x1b[0m'); return; } console.log(`\n将安装 ${notInstalled.length} 个语言服务器:\n`); notInstalled.forEach((s) => console.log(` - ${s.displayName}`)); console.log(''); let success = 0; let failed = 0; for (const server of notInstalled) { const result = await installServer(server.id); if (result) { success++; } else { failed++; } console.log(''); } console.log(`\n安装完成: ${success} 成功, ${failed} 失败`); } /** * 显示服务器详细信息 */ export function showServerInfo(serverId: string): void { const servers = listServers(); const server = servers.find( (s) => s.id === serverId || s.displayName.toLowerCase() === serverId.toLowerCase() ); if (!server) { console.error(`\x1b[31m错误: 未找到服务器 "${serverId}"\x1b[0m`); return; } const status = server.installed ? '\x1b[32m已安装\x1b[0m' : '\x1b[31m未安装\x1b[0m'; console.log(`\n${server.displayName}`); console.log('='.repeat(40)); console.log(`状态: ${status}`); console.log(`命令: ${server.command}`); console.log(`描述: ${server.description}`); console.log(`支持语言: ${server.languages.join(', ')}`); if (!server.installed) { const installCmd = getInstallCommand(server.install); if (installCmd) { console.log(`\n安装命令 (${installCmd.description}):`); console.log(` ${installCmd.command}`); } if (server.install.manual) { console.log('\n手动安装说明:'); console.log(server.install.manual); } } console.log(''); }