MoreRSS

site iconISLAND修改

一名全栈开发者,前百度,现在一家数字货币交易所。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

ISLAND的 RSS 预览

使用 cc switch 和 cc desktop switch 快速切换 Claude Code 供应商

2026-04-29 14:55:00

在 AI 编程工具的世界里,Claude Code 无疑是当前最强大的选择之一。然而,随着各大云服务商纷纷推出自己的大语言模型 API,如何方便地在不同供应商之间切换,成为了一个实际的需求。今天就给大家介绍两款工具:cc switchcc desktop switch,帮助你快速切换 Claude Code 的模型供应商。

项目地址:

cc switch 是一款跨平台的桌面应用,专门用于管理 Claude Code、Codex、Gemini CLI、OpenCode 和 OpenClaw 这五款主流 AI 编程 CLI 工具的供应商配置。

  1. 统一管理:一个应用同时管理五个 CLI 工具的供应商配置
  2. 50+ 供应商预设:内置 AWS Bedrock、NVIDIA NIM 及众多社区中转服务,复制 API Key 即可一键导入
  3. 一键切换:主界面或系统托盘都能快速切换供应商
  4. MCP & Skills 统一管理:一个面板管理四个应用的 MCP 服务器和 Skills,支持双向同步
  5. 代理和故障转移:本地代理支持格式转换、自动故障转移、熔断器、供应商健康监控
  6. 使用和成本跟踪:仪表盘展示支出、请求数和 Token 趋势图表
  7. 会话管理器:跨应用浏览、搜索和恢复对话历史
  8. 云同步:支持 Dropbox、OneDrive、iCloud、NAS 或 WebDAV 服务器同步配置
  9. 跨平台:原生桌面应用,支持 Windows、macOS 和 Linux
  • Claude Code:Anthropic 的 AI 编程助手
  • Codex:OpenAI 的编程 CLI 工具
  • Gemini CLI:Google 的 AI CLI 工具
  • OpenCode:开源的 AI 编程工具
  • OpenClaw:新兴的 AI 编程工具
# 通过 Homebrew 安装(推荐)
brew tap farion1231/ccswitch
brew install --cask cc-switch

# 更新
brew upgrade --cask cc-switch

或者从 Releases 页面下载 CC-Switch-v{version}-macOS.dmg

Releases 页面下载:

  • CC-Switch-v{version}-Windows.msi 安装版
  • CC-Switch-v{version}-Windows-Portable.zip 便携版
# Arch Linux
paru -S cc-switch-bin

# 或从 Releases 下载 deb/rpm/AppImage

cc desktop switch 是一款专注于 Claude Desktop 官方桌面客户端 的轻量级配置工具。它和 cc switch 的定位不同:cc switch 主要面向 CLI 用户,而 cc desktop switch 专注于桌面版 Claude Desktop。

  1. 管理多个 API 提供商:DeepSeek、Kimi、智谱 GLM、阿里云百炼、SiliconFlow 等
  2. 一键写入配置:将选中的供应商配置直接写入 Claude Desktop 的本地配置
  3. 直连模式:Anthropic 兼容接口默认直连,关闭本工具后 Claude Desktop 仍可继续使用
  4. 实验兼容模式:保留 OpenAI/new-api/反代类接口的本机转发支持
  5. 基础连通测速:对提供商 API 地址做基础连通测试
  6. 中英文界面:支持中文/英文界面和浅色/深色模式
  1. 添加供应商:点击「Add Provider」→ 选择预设或创建自定义配置
  2. 切换供应商
    • 主界面:选中供应商 → 点击「Enable」
    • 系统托盘:直接点击供应商名称(即时生效)
  3. 生效方式:重启终端或对应的 CLI 工具(Claude Code 无需重启)
  4. 恢复官方:添加「Official Login」预设,重启 CLI 工具后按照其登录/OAuth 流程操作
  1. 启动 CC Desktop Switch
  2. 在弹出的桌面窗口里操作
  3. 选择快捷预设,填写自己的 API Key,必要时调整模型映射
  4. 点击「一键应用到 Claude Desktop」
  5. 完整重启 Claude Desktop 后测试

注意:只关闭聊天窗口通常不够,请在任务栏托盘里退出 Claude,或在任务管理器里确认没有残留的 Claude 进程。

笔者使用 cc switch 已经有一段时间了,整体体验非常不错。以下是我的一些使用感受:

  1. 切换方便:相比手动修改配置文件,图形界面更加直观
  2. 多应用支持:同时支持 Claude Code、Codex、Gemini CLI 等多个应用
  3. 成本监控:可以清晰地看到各个供应商的使用情况
  4. 托盘运行:最小化到托盘后不会占用太多资源
  5. 预设丰富:内置 50+ 供应商预设,无需手动配置

cc switch 和 cc desktop switch 为 Claude Code 用户提供了便捷的供应商管理方案。两者的定位略有不同:

  • cc switch:面向 CLI 用户,统一管理 Claude Code、Codex、Gemini CLI、OpenCode、OpenClaw 五款工具
  • cc desktop switch:面向 Claude Desktop 桌面版用户,更轻量,专注于桌面客户端

无论你是需要测试不同模型的效果,还是想要找到性价比最高的供应商,这些工具都能满足你的需求。如果你正在使用 Claude Code,不妨试试这些工具,相信它们会给你带来不错的体验。


如果你对 AI 编程工具感兴趣,也可以看看我之前的文章:Neovim 入门指南系列,里面有很多关于编辑器配置和 AI 集成的相关内容。

用vscode开发 ios/macos App

2025-12-08 09:24:46

如何脱离 xcode 开发 iOS 是很多人在探索的方案。毕竟 xcode 编辑体验实在是太差了。

这里说的是脱离 xcode,而不是脱离 macOS。

这是今天要安利的工具 SweetPad。SweetPad 是 vscode 上的一个插件,插件可以实现在 vscode 中进行自动补全、调试、编译和运行、格式化、测试等功能。常见的开发场景中基本可以脱离 xcode 来使用。

LazyVim 使用

2025-02-15 13:45:30

在使用 Neovim 之前,我也花费了大量的时间进行配置自己的 Neovim 体系,无论是插件,快捷键还是 UI,都花费了大量的心思。 但是维护一套自己的配置说实话很费时间,例如插件的更新,版本升级等。

LazyVim 是一款已经 集成了大量插件的 Neovim 软件。 基本做到了开箱即用,方便快捷,大量的默认配置减少了上手时间,唯一的缺点可能就是快捷键不是自己熟悉的那套,需要修改或者适应。

LazyVim 的安装其实很简单,首先打开官方的启动模板 LazyVim/starter。 点击右上角 Use this template ,将模板 fork 成为自己的仓库。 接下来就是备份本地原有的配置,将自己的仓库 clone 下来。

简单来说就是一个命令进行备份 另外一个命令进行 clone。 这部分可以直接参考官方网站对于安装的介绍文档。

安装完成之后,启动就是一个已经有了大量基础配置的 neovim 了,基本做到了开箱即用。

完成 LazyVim 的配置,记得看一下是否系统安装了 fzf

在 LazyVim 的项目中,配置可以分成两大块:基础配置(config) 和 插件(plugins)。

config 配置主要是一些基础的配置,文件夹内区分了四个文件, 分别是基础配置(options.lua),快捷键配置(keymaps.lua),自动化命令(autocmds.lua)和 lazy 初始化配置。

默认 LazyVim 已经集成了很多插件,有的已经默认开启,有的需要手动开启。如果需要覆盖原有的插件配置或者安装新的插件, 可以在该文件夹下直接填写相关配置,最后在外层的 init.lua 中添加即可。

LazyVim 已经集成了大量的插件,并且默认了很多快捷键。默认的 Leader 为 空格。可以针对自己的习惯修改快捷键,也可以直接按下 Leader 来查看快捷键。

Keymaps

默认的快捷键我认为是比较合理,而且使用几次基本也会记住,这里我除了修改了一下 blink 候选提示的上下选择之后,并没有做其他修改。 默认的快捷键也可以在官方文档中找到 keymaps

LazyVim 一些默认的插件已经启用,但是除了默认插件,还有一些其他插件可以根据具体的情况按需使用。 通过 :LazyExtras 命令可以查看其他扩展插件。如果有自己使用的,需要的可以直接通过 x 进行启用。 需要注意的是启用后需要重新启动一些 neovim。

LazyVim 中自带了一些配置,例如 tab 为 2,在一些缩进比较多语言中,tab 为 2是比较友好的,例如 lua,但是对于一些项目,尤其是很团队合作的项目, tab 改成2 就会让代码一团乱。

options.lua 中新增一些 tab 相关的配置。

local opt = vim.opt
opt.expandtab = true
opt.tabstop = 4
opt.shiftwidth = 4
opt.softtabstop = 4

同时为了让 lua 还保持 tab 为2的缩进,在 autocmds.lua 中新增自动化命令。

vim.api.nvim_create_autocmd("FileType", {
  pattern = { "lua" },
  callback = function()
    vim.opt_local.expandtab = true
    vim.opt_local.tabstop = 2
    vim.opt_local.shiftwidth = 2
    vim.opt_local.softtabstop = 2
  end,
})

还有一个就是中文拼写问题,默认的 spell 一直检查,尤其是在进行 markdown 的时候,大量的波浪线导致编辑的感官太差,可以新增命令来解决。

vim.api.nvim_create_autocmd("FileType", {
  pattern = { "markdown", "txt" },
  callback = function()
    vim.opt_local.spell = false
  end,
})

VSCode Neovim

LazyVim 对 vscode 支持比较好,并且 vscode-neovim 也推荐使用 lazyvim。通过这个插件,可以让我们在 Vscode 中加载一些 Neovim 的插件,做到一个配置两处使用。

首先需要在 LazyExtras 中打开 Vscode 。 然后在 Vscode 中安装 Vscode Neovim 插件。

在 LazyVim 中可以通过 vim.g.vscode 来判断当前的运行环境。

首先是对快捷键进行配置,比如常用的重命名、格式化等。

local map = vim.keymap.set
if vim.g.vscode then
  map("n", "<leader>cf", "<Cmd>lua require('vscode').call('editor.action.formatDocument')<CR>", { desc = "Format" })
  map("v", "<leader>cf", "<Cmd>lua require('vscode').call('editor.action.formatSelection')<CR>", { desc = "Format" })
  map("n", "<leader>cr", "<Cmd>lua require('vscode').call('editor.action.rename')<CR>", { desc = "Rename" })
end

针对 Golang 开发,首先就是语言的相关配置:

  • LSP:通过 Mason 安装 gopls
  • Testing: 通过 LazyExtras 进行安装 test.core
  • DAP: 通过 Mason 安装 dlv

安装完成就可以进行编辑,运行,测试和调试。

可以通过 <Leader>tr 进行测试运行。

Go Testing

通过 <Leader>db 进行打断点。 通过 <Leader>dc 进行 Debug 运行。

Go Debug

分布式理论

2024-03-25 13:45:30

在分布式系统中最重要的一条理论为 CAP 理论。这个理论是由加州大学伯克利分校的计算机科学家 Eric Allen Brewer 在 2000 年提出的一个猜想,由 2002 年,麻省理工两位科学家发表了该猜想的证明,使得该猜想变成了一个定理。

CAP 定理中对分布式系统提出了三点,分别为:

  • 一致性(Consistency):多个副本的数据之间能够保持一致;
  • 可用性(Availability):每次请求都可以获取到正常的、非错误的响应,但是无法保证数据是最新的;
  • 分区容错性(Partition tolerance):系统的某个节点发生故障,仍然还可以对外提供一致性和可用性的服务。

CAP 理论

例如当前系统有两个 DB 分别为 DB0 和 DB1。

一致性是指在数据发生变化的时候(也就是写操作发生后),无论是谁获取到的数据(也就是读操作)也是一样的。

当用户1 通过写操作对 DB0 的数据进行修改后,那么无论用户1 还是 用户2 ,无论从 DB0 还是 DB1 读取,读取后的数据都应该是完全一样的,这就是所谓的一致性。

也就是 DB0 的数据发生了修改,应该由相关的机制告诉 DB1 也将相关的数据发生修改,保证该数据在不同的 DB 中是一样的。

当用户发出相关请求,无论 DB0 还是 DB1 都会返回相关的数据,但是这里不需要关心数据是否一致。

DB0 和 DB1 例如出现了问题,这个问题可能是网络问题,也有可能是其他硬件问题,导致了 DB0 和 DB1 的系统无法通信。这样 DB0 和 DB1 就成为了两个分区。即使 DB0 和 DB1 无法进行通信,但是 DB0 和 DB1 仍旧可以对外提供服务。

但是这种情况,在实际系统中无法避免这种情况,所以分区容错性是一个必选的条件。

既然 CAP 三条规则无法同时满足,那么就出现了上图中的三种情况,满足任意两条规则,也就是 CA,CP 和 AP 三种架构,但是分区容错性是必选的,这样我们就剩下 CP 和 AP 两种关系。

常见的 CP 软件有 Zookeeper,Zookeeper 为了保证数据的一致性,牺牲了可用性。任何时候 Zookeeper 的访问都能获取一致的结果,但是不保证每次服务请求都可以用。

而 AP 架构中,要求数据一致性并不是那么重要,允许不同的服务可以返回不同的数据。

CAP 理论并不是完美的,存在很多问题。例如 DB0 和 DB1 要保持数据的一致性,那么就会发生相关通信,通信是需要时间,这就导致了某些时刻数据是不同步的,常见的情况在主从的机器上的主从延迟,当延迟过大的时候,用户读取的数据是不一致的。

CAP 理论也并不完全是三选二(或者说二选一)的问题,例如分区容错性发生的概论很小,那么就没必要牺牲了 A 和 C。

BASE 理论算是 CAP 理论的延伸,是对 CAP 理论中一致性和可用性的权衡。在 CAP 中,所谓的一致性是指数据时时刻刻的都保持一致,也就是强一致性。上文中 CAP 的不足也说到,要保证时时刻刻数据的一致性是一件很困难的事情。而 BASE 理论就是对改问题的补充,既然很难做到强一致性,那么系统根据自身的业务特点,确保系统中的数据保证最终一致性也是可以的。

BASE 理论是 ebay 工程师 Dan Pritchett

BASE 是指 Basically Available, Soft State 和 Eventually Consistent 三个短语的缩写。

基本可用指的是系统出现故障后,但是还可以使用,但是可能比较正常系统上可能出现一些问题,例如响应时间上,服务降级牺牲部分功能等。

软状态指的是系统数据允许出现中间状态,例如数据库主从同步过程中会出现中间状态,这就是一种软状态。

最终一致性强调经过上述的软状态后,最后数据保持一致性。

BASE 理论的提出是通过牺牲系统的强一致性来保证系统的可用性,允许系统在一段时间内的数据是不一致的,但是要求最终数据的一致性。

一文看懂|分布式系统之CAP理论

分布式架构之CAP理论/AP架构/CP架构

neovim入门指南(四):LSP配置(下)

2024-03-02 08:06:25

neovim入门指南(三):LSP配置 上 中说了 lsp 是什么如何配置和启动。那么接下来就完成 lsp 的其他配置。本章节主要介绍下面几个方面的介绍:代码高亮,文件格式化,lsp 相关的 UI 美化。

在有了 lsp 之后,当我们编写代码发生错误的时候,就会有相应的提醒。如图下提示

lsp error

目前的错误还是字母,例如警告是W 。不太美观。对于这个来说,vim 开放了相关的接口,可以通过接口进行设置, neovim-diagnostic

仍旧在 lsp 的文件夹下建立 ui.lua 目录。

-- lsp/ui.lua
-- 对错误警告的图标
vim.diagnostic.config({
        virtual_text = true,
        signs = true,
 -- 在输入模式下也更新提示,设置为 true 也许会影响性能
 update_in_insert = true,
})
local signs = { Error = "󰅙", Info = "󰋼", Hint = "󰌵", Warn = "" }
for type, icon in pairs(signs) do
 local hl = "DiagnosticSign" .. type
 vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
end

其中 vim.diagnostic.config 是在配置提示文本,virtual_text 为错误信息提示.

目前的设置中,对于代码的高亮并不完美,需要采用一个插件了完成。tree-sitter 是一个用 rust 编写的高性能代码高亮的渲染工具,很多编辑器会采用它作为高亮功能的实现,比如说 Zed 。基于 tree sitter ,可以让我们的 neovim 的高亮更加完美。

这是来源于 nvim-treesitter 的一张图,图中左侧为未启用 treesitter 的代码高亮,右侧为启用后的效果。启用后的效果还是很明显的。

安装 tree-sitter 后,可以通过 TSInstall 来安装具体的语言高亮,例如 Rust 的高亮,可以直接使用 TSInstall rust 命令,或者使用 TSUpdate rust 命令进行更新。整体安装和配置还是比较简单的,这里不过多的解释。

代码格式化是一个很重要的功能,也是我们使用频率很高的功能。针对 Neovim 的代码格式化有很多种方式。这里主要介绍 null-ls。不幸的是,null-ls 已经归档来,不再进行维护,万幸的是,它的 fork 项目 none-ls 重新维护起来,而且目前还兼容 null-ls 的配置,如果你之前使用的是 null-ls,那么只需要将依赖地址由 jose-elias-alvarez/null-ls.nvim 改为 nvimtools/none-ls.nvim 即可。

安装好 none-ls,后可以通过 Mason 安装相关的 formatter,例如安装 lua 的 formatter。通过命令 :Mason 打开安装界面。

选择 stylua,进行安装。安装完成后就可以进行配置,在 lua/lsp 下新建文件,命名为 nonels.lua

-- lsp/nonels.lua
-- 即使是采用了 none-ls, 这里也是获取 null-ls
local status, null_ls = pcall(require, "null-ls")
if not status then
	vim.notify("没有找到 null-ls")
	return
end

local formatters = null.builtins.format

null_ls.setup({
    sources = {
        -- Stylua
        formatters.stylua,
        -- 其他 formatter 方式
    },
})

这样在我们进行编写代码的时候,进行相关格式化。在上一文中也进行了介绍,对快捷键进行了绑定。使用 <Leader>= 进行格式化。

关于前面,介绍了通过 cmp 插件进行了自动补全,通过 cmp 可以补充不同来源的代码。

我们使用一些 IDE 或者编辑器的时候,在补全的选项中是会展示一些图标,用来标识补全项的类型,例如变量、类名、方法或是接口等。

RustRover 自动补充样式。

RustRover Code Completion

VS Code 自动补全样式。

VSCode 自动补全

通过配置,也可以让 neovim 的提示实现上图效果。

当前自动补全的效果如图,前面为补全的字段,后面通过文字来标识补全的类型。

有一个插件叫做 lspkind ,可以通过安装该插件结合我们的 cmp 完成上述的样式。

在 lsp 下新建文件 kind.lua,配置 kind,这个可以在 lspkind,找到相关配置。

-- lsp/kind.lua
local lspkind = require("lspkind")
lspkind.init({
	mode = "symbol_text",
	preset = "codicons",
	symbol_map = {
		Text = "󰉿",
		Method = "󰆧",
		Function = "󰊕",
		Constructor = "",
		Field = "󰜢",
		Variable = "󰀫",
		Class = "󰠱",
		Interface = "",
		Module = "",
		Property = "󰜢",
		Unit = "󰑭",
		Value = "󰎠",
		Enum = "",
		Keyword = "󰌋",
		Snippet = "",
		Color = "󰏘",
		File = "󰈙",
		Reference = "󰈇",
		Folder = "󰉋",
		EnumMember = "",
		Constant = "󰏿",
		Struct = "󰙅",
		Event = "",
		Operator = "󰆕",
		TypeParameter = ""
	},
})

这里可以配置每个类别的图标,配置完成后在 cmp 中进行配置。主要是修改提示的样式。这里主要参考了 Github 上的一个样式,。在 formatting 中进行配置。

-- cmp.lua
cmp.setup({
    -- 省略其他代码
    formatting = {
        		completion = { border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, scrollbar = "║" },
		documentation = {
			border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" },
			scrollbar = "║",
		},
		format = lspkind.cmp_format({
			mode = "symbol",
			maxwidth = 20,
			ellipsis_char = "...",
			before = function(entry, vim_item)
				-- Get the full snippet (and only keep first line)
				local word = entry:get_insert_text()
				if entry.completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then
					word = vim.lsp.util.parse_snippet(word)
				end
				word = str.oneline(word)
				if
					entry.completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet
					and string.sub(vim_item.abbr, -1, -1) == "~"
				then
					word = word .. "~"
				end
				vim_item.abbr = word
				return vim_item
			end,
		}),
    }
    -- 省略其他代码
})

完成后的样式如图,基本和 VS Code 一样。

lspsage 可以极大的提高 nvim lsp 的体验。lspsage 的功能基本都是在增强和美化原有的 lsp 。具体的文档可以查看 nvimdev

lspsage 主要功能:

Finder: 用于高级 LSP 符号搜索的 UI
Diagnostic: 在诊断之间跳转并在漂亮的浮动窗口中显示它们
Peek Definition / Type Definition:查看定义/类型定义
悬停: 更漂亮的悬停操作
重命名: LSP 重命名和异步项目搜索和替换
调用层次传入/传出调用
Code Action: 具有实时预览的漂亮代码操作 UI
LightBulb: 类似 VSCode 的灯泡,指示可能的代码操作
面包屑: 类似于 WinBar 上的 IDE 符号纲要
大纲: 类似于 IDE 的符号纲要 实现: 轻松查看实现数量并快速跳转到它们
浮动终端: 一个简单的浮动终端
杂项: 适用于所有模块的选项

上面来自于官方文档的介绍。

Finder 的功能是一个类似 VS Code 的变量/函数 查看的界面,可以在界面上看到这个变量/函数的定义和调用地方。

-- keybindings.lua
-- 其他代码
pluginKeys.mapLSP = function(mapbuf) {
    -- 其他代码
    mapbuf("n", "gf", ":Lspsaga lsp_finder<CR>", opt) -- 新增
    -- 其他代码
}

这样在 normal 情况下按下 gf 就会出现上面的 finder 窗口。

Code Action 是一个非常重要的功能,可以根据代码上下文给出相关的提示或者代码改进。例如这块代码,Code Action 提醒我们可以直接转换为字面量的拼接。

Code Action 并不是 lspsaga 提供的,但是 lspsaga 给提供了一个漂亮的界面。在有 Code Action 的地方,会有一个黄色灯泡 💡 的提示。

下面绑定我们的快捷键。

-- keybindings.lua
pluginKeys.lspKeybinding = function(mapbuf)
 -- 省略其他代码
 -- code action
 -- mapbuf("n", "<leader>ca", ":lua vim.lsp.buf.code_action()<CR>", opt) -- 原有的
 mapbuf("n", "<leader>ca", ":Lspsaga code_action<CR>", opt) -- 替换为这个
end

lspsaga 提供了一个浮动终端窗口,可以在终端上执行任何命令。可以在 keybindings 中绑定这个快捷键,或者直接使用默认的快捷键 t ,来进行终端的打开和关闭。

lspsaga 还提供了很多功能,基本每个功能对我们都有帮助,这里就不做过多介绍了,大家可以看官方文档。

这里基本介绍完了 lsp 的常见功能和配置,剩下的大家可以通过需要进行安装和配置。

这里是我的配置 youngxhui/nvim 大家可以适当参考。

vim/neovim 使用的时候,的确是有一个较高的上手成本,尤其是方向键的习惯,当完全习惯了 h,j,kl 进行光标移动的时候,其实就离入门 vim/neovim 不远了。

当习惯了 vim 这一套风格之后,就会尝试把手头的编辑器/IDE 的快捷键都采用 vim ,而且在熟悉 vim 的快捷键后,真正的感觉到了手指在键盘上飞舞。

无论是 neovim 还是相关插件,更新迭代是很快的,也许当你看到这篇文章的时候,上述的很多配置都已经失效,或者相关插件已经停止维护,文章只是抛砖引玉,我相信你会找到合适自己的 nvim 配置。

我相信喜欢 vim/neovim 的人都是有一颗专研,喜欢折腾的心。正是这样的心才陪伴这个你我一步一步前进。

写到这里有感而发,下一篇我们将会介绍 DAP 。

neovim入门指南(三):LSP配置(上)

2023-09-04 18:10:02

对于一个编辑器来说,如果要完成例如自动补全,查找相关定义等功能是需要进行大量的开发的。不同的编辑器为了不同的语言都需要进行开发,而 LSP 的存在就是将这个过程检化。LSP 的全称为 Language Server Protocol,定义了编辑器和语言服务之间使用的协议。只要相关语言支持 LSP,那么编辑器只要符合相关要求实现即可完成例如自动补全等功能,而且不同的编辑器使用的体验是一致的。

目前支持 LSP 的编辑器有很多,例如大名鼎鼎的 Vscode。当然 vim 8 以后版本和 neovim 也都支持,具体支持的编辑器/IDE 列表可以看 LSP 的官方网站,同时支持 LSP 的语言也可以找到 支持语言

neovim 已经是支持 LSP 了,具体可以在相关的配置文档看到,该文档详细的描述了如何配置一个 LSP。相对来说,配置过程比较繁琐,所以官方又提供了另一个库 nvim-lspconfig。接下来我们就通过这个插件来配置 neovim 的 lsp。

与安装其他插件是一样的,只需要我们在 plugins_config.lua 中添加相关配置即可,这里不进行赘述了。安装完成后其实进行配置就可以启用 LSP 了,就是这么简单。例如支持 rust 的 LSP,只需要进行简单的配置。

lspconfig.rust_analyzer.setup {
  settings = {
    ['rust-analyzer'] = {},
  },
}

但是,nvim 只是 lsp 的客户端,那么就存在 lsp 的服务端。上面配置的 rust_analyzer 就是 rust 语言的服务端,就需要我们进行服务端的安装。rust_analyzer 的服务端地址是 rust-lang/rust-analyzer,需要将服务端下载并且安装好,这样每次编写rust的时候就会享受 lsp 的服务加成了。

但是这样做有几个问题,当然也不能算问题,只是不太方便。

  1. 对于多语言使用者来说,需要手动安装多个 lsp 服务端,目前 lsp 的服务端应该是没有统一的下载安装地址,需要手动寻找;
  2. 每次服务端进行更新,都需要重新下载安装;
  3. 新换设备之后,无法开箱即用,需要重复上述的方式重新开始一次。

面对上面的不方便,你可能已经想到很多解决方法,例如写个脚本进行一键安装和更新常用的 lsp 服务端。这样基本解决了上面说的所有问题。正如你想的那样,今天的第二位主角 williamboman/mason.nvim

mason 是一个可以方便的管理 LSP 服务端,DAP 服务端,Linter 和 格式化工具的插件。安装它之后,上面所说的问题将不是问题。

为了让 mason 和 nvim-lspconfig 更好的配合,这里还需要安装另一个插件 williamboman/mason-lspconfig.nvim

同样的安装这里不多赘述,主要是进行相关的配置。这里为了区别其他的插件,我们在 lua 目录下建立新的文件夹 lsp,用来专门存放 lsp 的配置。

首先还是加载我们的插件。在 lsp 文件夹中新建 mason.lua 文件,在文件中新增下面的配置。配置主要是在加载插件。

-- mason.lua
local mason_status, mason = pcall(require, "mason")
if not mason_status then
 vim.notify("没有找到 mason")
 return
end

local nlsp_status, nvim_lsp = pcall(require, "lspconfig")
if not nlsp_status then
 vim.notify("没有找到 lspconfig")
 return
end

local mlsp_status, mason_lspconfig = pcall(require, "mason-lspconfig")
if not mlsp_status then
 vim.notify("没有找到 mason-lspconfig")
 return
end


mason.setup()
mason_lspconfig.setup({})

配置完成后,重新启动 nvim,此时就可以采用 mason 进行 LSP 的服务端进行管理了。只需要按下 :Mason 即可。你将会看到如下的界面。

Mason 界面

通过界面上的帮助可以看到如何使用,通过数字可以选择不同的服务端项目,2 为 LSP , 3 为 DSP 等。今天只是使用 LSP,可以直接按 2,选择到 LSP 界面,进行 LSP 安装。仍旧是通过 jk 进行滑动。第一个安装的 lsp 服务端为 lua 语言的服务端:lua-language-server。这个是 lua 语言的语言服务,有 lsp 之后,我们之后无论是配置 nvim 还是编写 lua 都会有 lsp 服务的加持。按下 i 进行安装。

稍等片刻,安装完成。接下来就是配置,让 nvim 知道我们的 lsp 已经安装,在合适的时候进行启动。

-- mason.lua
nvim_lsp.lua_ls.setup({
 on_init = function(client)
  local path = client.workspace_folders[1].name
  if not vim.loop.fs_stat(path .. "/.luarc.json") and not vim.loop.fs_stat(path .. "/.luarc.jsonc") then
   client.config.settings = vim.tbl_deep_extend("force", client.config.settings, {
    Lua = {
     runtime = {
      version = "LuaJIT",
     },
     workspace = {
      checkThirdParty = false,
      library = {
       vim.env.VIMRUNTIME,
      },
     },
    },
   })

   client.notify("workspace/didChangeConfiguration", { settings = client.config.settings })
  end
  return true
 end,
})

这样 lua 的 lsp 就配置成功了,当我们编写 lua 脚本的时候,如果发生错误就会有相关提醒。当然这只是 lsp 最基础的功能,例如代码跳转,代码补全等需要我们进行配置。

发生错误时的提示

基本所有的 lsp 的配置都可以在 server_configurations.md 中找到,当然 lua_ls 也不例外,上面的配置就是直接从文档中复制的 😄。

当前的 LSP 配置已经支持代码跳转,code action 等功能。例如查看当前变量或者函数的文档,可以使用这个命令 :lua vim.lsp.buf.hover()

相关的命令还有其他

功能 命令
文档显示 :lua vim.lsp.buf.hover()
查看定义 :lua vim.lsp.buf.definition()
重命名 :lua vim.lsp.buf.rename()
查询实现 :lua vim.lsp.buf.implementation()
查询引用 :lua vim.lsp.buf.refreences()
查询声明 :lua vim.lsp.buf.declaration()
格式化 :lua vim.lsp.buf.format()
Code action :lua vim.lsp.buf.code_action()

对于这些基础功能来说,每次需要的时候都在命令模式下敲一堆,速度的确是很慢的。所以,可以将上述的命令定义为快捷键,这样每次只需要进行快捷键进行完成上述功能。

打开我们之前设置快捷键的配置文件 keybinding.lua,新增上述功能的配置。

-- keybinding.lua
-- lsp 快捷键设置
pluginKeys.lspKeybinding = function(mapbuf)
 -- rename
 mapbuf("n", "<leader>r", ":lua vim.lsp.buf.rename<CR>", opt)
 -- code action
 mapbuf("n", "<leader>ca", ":lua vim.lsp.buf.code_action()<CR>", opt)
 -- go to definition
 mapbuf("n", "gd", ":lua vim.lsp.buf.definition()<CR>", opt)
 -- show hover
 mapbuf("n", "gh", ":lua vim.lsp.buf.hover()<CR>", opt)
 -- format
 mapbuf("n", "<leader>=", ":lua vim.lsp.buf.format { async = true }<CR>", opt)
end

完成快捷键的配置,那么就可以将快捷键绑定到刚刚配置的 lsp 服务端了。

-- mason.lua
function LspKeybind(client, bufnr)
 local function buf_set_keymap(...)
  vim.api.nvim_buf_set_keymap(bufnr, ...)
 end
 -- 绑定快捷键
 require("keybinding").lspKeybinding(buf_set_keymap)
end

接下来可以完成快捷键的绑定。

-- mason.lua
nvim_lsp.lua_ls.setup({
 on_attach = LspKeybind,
 on_init = function(client)
    -- 省略其他配置
 end,
})

这样就完成了 lua 的 lsp 的配置,在编写 lua 的时候就可以使用文档查看,code Action 等功能。

目前这些 lsp 的服务都要手动下载,对于一些日常使用的服务,我们可以通过配置,在第一次加载配置的时候,当机器上没有相关的服务的时候,自动下载,这样来说,基本实现了我们上述提出的问题。

-- mason.lua
mason_lspconfig.setup({
 automatic_installation = true,
 ensure_installed = { "lua_ls", "rust_analyzer" },
})

这样配置,如果我们本地没有安装 lua 和 rust 的 lsp,会自动进行下载安装。

直到目前,在 lsp 的加持下,其实编辑体验已经变得非常棒了,而且开发速率也会大幅提升,虽然 lsp 是支持自动补全功能的,但是上面其实一直没有提及。主要是单单靠 neovim 的功能还不够强大,需要插件的配置。

hrsh7th/nvim-cmp 是一个采用 lua 编写的补全引擎,通过 cmp 及 cmp 的相关插件,会将 neovim 的自动补全达到一个新的高度。

这里除了 nvim-cmp,再推荐几个 cmp 的相关插件。更多的相关插件可以在 wiki 中找到

同样不赘述安装。在 lsp 文件夹中新建 cmp.lua 文件夹。

-- cmp.lua
local status, cmp = pcall(require, "cmp")
if not status then
    vim.notify("找不到 cmp")
    return
end

剩下了就可以将之前的补全源进行配置。这里贴出我的补全源。

sources = cmp.config.sources({
	{ name = "codeium" }, -- 需要安装 codeium.nvim
	{ name = "nvim_lsp" },
	-- For vsnip users.
	{ name = "vsnip" },
}, {
	{ name = "buffer" },
	{ name = "path" },
}),

此时当我们进行输入的时候就可以看到自动补全的提示了。对于自动补全的提示,上下选择并且上屏,我们可以设置快捷键,来满足我们的使用习惯。

和之前设置快捷键一样,在 keybindings.lua 中添加相关配置。

-- keybindings.lua
pluginKeys.cmp = function(cmp)
 return {
  -- 出现补全
  ["<A-.>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
  -- 取消
  ["<A-,>"] = cmp.mapping({
   i = cmp.mapping.abort(),
   c = cmp.mapping.close(),
  }),
  -- 上一个
  ["<C-k>"] = cmp.mapping.select_prev_item(),
  -- 下一个
  ["<C-j>"] = cmp.mapping.select_next_item(),
  -- 确认
  ["<CR>"] = cmp.mapping.confirm({
   select = true,
   behavior = cmp.ConfirmBehavior.Replace,
  }),
 }
end

最后在 cmp.lua 中使用这些快捷键即可。

cmp.setup({
    -- 省略其他配置
    mapping = require("keybindings").cmp(cmp),
})

这样便可以完成自动补全的配置了。

目前为止,已经完成 nvim 的 lsp 的相关配置,并且添加了自动补全。篇幅限制,剩下如何美化 lsp 提示,美化自动补全等我们下篇再说。

我的 neovim 相关配置,可以提供大家进行参考 youngxhui/nvim