首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
80 阅读
2
nvim番外之将配置的插件管理器更新为lazy
58 阅读
3
2018总结与2019规划
54 阅读
4
PDF标准详解(五)——图形状态
33 阅读
5
为 MariaDB 配置远程访问权限
30 阅读
心灵鸡汤
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
菜谱
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
登录
Search
标签搜索
c++
c
学习笔记
windows
文本操作术
编辑器
NeoVim
Vim
win32
VimScript
Java
emacs
linux
文本编辑器
elisp
反汇编
OLEDB
数据库编程
数据结构
内核编程
Masimaro
累计撰写
308
篇文章
累计收到
27
条评论
首页
栏目
心灵鸡汤
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
archlinux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
菜谱
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
页面
归档
友情链接
关于
搜索到
59
篇与
的结果
2022-09-08
从零开始配置vim(24)——自动补全
neovim 自带的代码补全的效果并不好,而且它分为好多类,如果需要人为的去判断使用路径补全、使用当前buffer中的单词补全、亦或者使用include 来进行补全,那样使用起来就很不方便了。针对代码的补全我们可以基于 lsp的配置使用插件来完成,这里我推荐使用 nvim-cmp插件安装我们使用下面的代码进行安装-- nvim-cmp use {'hrsh7th/cmp-nvim-lsp'} use {'hrsh7th/cmp-buffer'} use {'hrsh7th/cmp-path'} use {'hrsh7th/cmp-cmdline'} use {'hrsh7th/nvim-cmp'} -- vsnip use {'hrsh7th/cmp-vsnip'} use {'hrsh7th/vim-vsnip'} use {'rafamadriz/friendly-snippets'} -- lspkind use {'onsails/lspkind-nvim'}看着好像要安装好多插件,但是真正重要的就只有 nvim-cmp 剩下的以 cmp- 开头的都是在指定补全的来源,就像 neovim 自带补全功能可以来源于当前buffer、路径、引用一样,该插件的补全项也来源于各个地方。例如 cmp-nvim-lsp来源于语言的 lsp 服务端、cmp-buffer来源于当前 buffer 、cmd-path来源于路径配置我们还是按照原来的惯例进行配置,新增一个 plugin-config/cmp.lua 的配置文件,并且加载它require('plugin-config/cmp')在该配置文件中我们加入如下内容local cmp = require("cmp") local lspkind = require("lspkind") cmp.setup({ -- 设置代码片段引擎,用于根据代码片段补全 snippet = { expand = function(args) vim.fn["vsnip#anonymous"](args.body) end, }, window = { }, mapping = { -- 选择上一个 ['<C-p>'] = cmp.mapping.select_prev_item(), -- 选择下一个 ['<C-n>'] = cmp.mapping.select_next_item(), -- 出现补全 ['<A-.>'] = cmp.mapping(cmp.mapping.complete(), {'i', 'c'}), -- 取消补全 ['<A-,>'] = cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close(), }), -- 确认使用某个补全项 ['<CR>'] = cmp.mapping.confirm({ select = true, behavior = cmp.ConfirmBehavior.Replace }), -- 向上翻页 ['<C-u>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), {'i', 'c'}), -- 向下翻页 ['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(4), {'i', 'c'}), }, -- 补全来源 sources = cmp.config.sources({ {name = 'nvim_lsp'}, {name = 'vsnip'}, {name = 'buffer'}, {name = 'path'} }), --根据文件类型来选择补全来源 cmp.setup.filetype('gitcommit', { sources = cmp.config.sources({ {name = 'buffer'} }) }), -- 命令模式下输入 `/` 启用补全 cmp.setup.cmdline('/', { mapping = cmp.mapping.preset.cmdline(), sources = { { name = 'buffer' } } }), -- 命令模式下输入 `:` 启用补全 cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline(), sources = cmp.config.sources({ { name = 'path' } }, { { name = 'cmdline' } }) }), -- 设置补全显示的格式 formatting = { format = lspkind.cmp_format({ with_text = true, maxwidth = 50, before = function(entry, vim_item) vim_item.menu = "[" .. string.upper(entry.source.name) .. "]" return vim_item end }), }, })配置之后我们就可以使用自动补全相关功能了本篇的内容到此结束了,后面我们再次以 c/c++以及 python为例来演示如何进行 lsp相关的配置。帮助大家巩固一下这方面的内容。
2022年09月08日
4 阅读
0 评论
0 点赞
2022-09-07
从零开始配置vim(23)——lsp基础配置
上一章,我们初步认识了lsp,并且对 nvim-treesitter插件进行了配置,为编辑器提供了代码着色、自动格式化以及增量选中功能。算是初步体验了 lsp的相关功能。从这篇开始我们通过lsp的功能,进一步提升代码编辑、查阅等功能的体验neovim lsp早期想通过 neovim 使用 lsp 得通过一个额外的插件 nvim-coc 。它使用 nodejs实现,而且提供 lua 的接口。但是在 neovim 中混用不同编程语言有时候会出现莫名其妙的问题,比如我之前遇到的补全失效,但是过一段时间它自己又好了。好在 neovim 社区听从了程序员们对于 lsp 的呼唤,它内置了lsp 的客户端,并且为了方便配置服务端,它提供了一个名为 nvim-lspconfig 的插件。在现在的 neovim 版本下配置不同语言的 lsp已经很方便了,根据官方的文档,我们只需要4步即可安装 nvim-lspconfig 插件安装对应语言 lsp 的服务端针对 xx语言,添加语言的配置 require('lspconfig').xx.setup{…}检查 lsp 的服务端在该缓冲区是否正常运行 print(vim.inspect(vim.lsp.buf_get_clients()))安装 nvim-lspconfig好了,我们按照官方的提示,我们先来配置 lua 相关的内容,以便后期在写配置时可以有更好的编程体验。use {'neovim/nvim-lspconfig'}我们可以去微软的官方网站查看各个语言的服务端信息 https://microsoft.github.io/language-server-protocol/implementors/servers/安装对应服务端针对 lua 语言我们选中的是 sumneko/lua-language-server 这个服务端。根据 wiki 页面的安装方式,我们可以使用命令行自行安装。但是现在有了更方便的方式了我们使用 nvim-lsp-installer 插件进行安装。use { "williamboman/nvim-lsp-installer", "neovim/nvim-lspconfig", }我们还是一样,在plugin-config 目录下创建一个配置文件用来配置 nvim-lsp-installer 插件require("nvim-lsp-installer").setup {}我们可以使用 LspInstallInfo 命令来查看当前lsp服务的安装情况。我们使用 :LspInstall --sync [server] 来安装对应的服务端。其中 --sync 代表我们希望以同步的方式安装,也就是安装时会卡主 neovim 主体。使用下面的命令来安装 lua 的服务端:LspInstall --sync sumneko_lua我们可以在 这个页面 查看 nvim-lsp-installer 插件支持的各个语言对应的服务端针对lua进行配置安装完成之后,我们来配置 lua 相关的内容。不知道还记不记得我们之前介绍 文件类型的时候说过不同文件类型的配置都在 ~/.config/nvim/ftplugin 里面。我们在这个目录里面定义一个 lua.lua 的文件,写入以下内容-- 是否将 tab 替换为 space vim.bo.expandtab = true vim.bo.shiftwidth = 4 vim.bo.tabstop = 4 vim.bo.softtabstop = 4 -- 取消自动注释,当前行是注释时,按下回车键会默认添加一行注释,这里取消这一行为 vim.opt_local.formatoptions = vim.opt_local.formatoptions - {"r", "c", "o"}我们之前分析过 neovim 是如何实现文件类型检测的。在那篇文章中我们说它定义了自动命令,当检测到对应文件类型的时候会调用 ~/.config/nvim/ftplugin 目录中对应以文件类型命名的目录或者 lua 文件。使用这种方式有两个好处,第一个就是我们不用手动使用 require 来加载了,第二个好处就是可以根据文件类型动态的选择调用或者不调用,而且这个工作由 neovim 自动完成,不需要我们进行干预基于这些好处,我们在 ftplugin/lua.lua 中保存 lua 相关的配置。另外再在 ~/.config/nvim/lua 目录创建一个 lsp目录,专门用来保存语言的配置。然后再在 ftplugin/lua.lua 中加载它require('lsp/lua')我们在这个文件中添加 Lua 相关的lsp配置-- 定义快捷键 -- 根据官方的提示,这里我们使用 on_attach 表示当前缓冲加载服务端完成之后调用 local on_attach = function(client, bufnr) -- 跳转到声明 vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "<cmd>lua vim.lsp.buf.declaration()<CR>", {silent = true, noremap = true}) -- 跳转到定义 vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "<cmd>lua vim.lsp.buf.definition()<CR>", {silent = true, noremap = true}) -- 显示注释文档 vim.api.nvim_buf_set_keymap(bufnr, "n", "gh", "<cmd>lua vim.lsp.buf.hover()<CR>", {silent = true, noremap = true}) -- 跳转到实现 vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", {silent = true, noremap = true}) -- 跳转到引用位置 vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", {silent = true, noremap = true}) -- 以浮窗形式显示错误 vim.api.nvim_buf_set_keymap(bufnr, "n", "go", "<cmd>lua vim.diagnostic.open_float()<CR>", {silent = true, noremap = true}) vim.api.nvim_buf_set_keymap(bufnr, "n", "gp", "<cmd>lua vim.diagnostic.goto_prev()<CR>", {silent = true, noremap = true}) vim.api.nvim_buf_set_keymap(bufnr, "n", "gn", "<cmd>lua vim.diagnostic.goto_next()<CR>", {silent = true, noremap = true}) end require'lspconfig'.sumneko_lua.setup { settings = { Lua = { runtime = { -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) version = 'LuaJIT', }, diagnostics = { -- Get the language server to recognize the `vim` global globals = {'vim'}, }, workspace = { -- Make the server aware of Neovim runtime files library = vim.api.nvim_get_runtime_file("", true), }, -- Do not send telemetry data containing a randomized but unique identifier telemetry = { enable = false, }, }, }, on_attach = on_attach, }大部分的配置都是根据 sumneko_lua 官方的文档抄过来的,这里我们需要着重强调一下 on_attach 这里,根据 nvim-config 的描述,当 lsp 服务程序加载完成之后会调用我们在 on_attach 出指定的回调函数,在函数内部我们使用 vim.api.nvim_buf_set_keymap 仅仅针对当前加载了lsp 服务的缓冲区进行,而对于其他普通文件我们不需要用到这些快捷键。看到这里不知道小伙伴是否有点头晕了,这次我们安装了好多内容,也创建了不少配置文件,下面来回顾一下安装 nvim-lspconfig 来用于lsp的配置安装 nvim-lsp-installer 来安装不同语言的 lsp 服务端安装 sumneko_lua 作为 lua 语言的 lsp 服务端创建了一个 ~/.config/nvim/ftplugin 作为加载 lua 语言配置的入口创建了一个 ~/.config/nvim/lsp/lua.lua 保存lua 语言相关的配置本篇只讲了如何基于 neovim 官方给出的那4步来配置一个语言的 lsp 服务端,但是还有如何自动补全没有谈到,下节我们将开始讲解如何使用自动补全。敬请期待!
2022年09月07日
8 阅读
0 评论
0 点赞
2022-09-06
从零开始配置vim(22)——lsp简介与treesitter 配置
截止到上一篇文章,我们配置了neovim的很多内容了。具备了一些编辑器的常用功能了,而且可以胜任日常的文档编辑工作了。但是想作为一个可靠的代码编辑器还缺少重要的一环,即代码语法部分的支持。在过去的vim配置中,我们基于 you-complete-me这个插件配置。但是对于不懂c语言甚至vim的小白来说简直是灾难。各种兼容问题、报错频出,而且效果也远不如 visual studio code等编辑器。也有可能是我那个时候比较菜,当初针对 python配置的补全效果很一般只能补全内置函数,自己定义的类和方法无法补全,而且跳转时好时坏。后来我抛弃了vim很长一段时间。好在微软提供了lsp这个大杀器,让vim、emacs这类编辑器的代码编辑体验提升了很大一截。而且配置还相对简单。lsp 简介过去的编辑器包揽了诸如代码高亮、语法分析、跳转等功能,这样就导致了所有编辑器都有自己专有的一套显示、跳转等方案。而第三方编辑器想要达到完全相同的效果几乎是不可能的。但是微软提出的 lsp(language server protocol) 确改变了这一格局。lsp最重要的就是将语法分析、跳转、自动补全功能这些语言的核心功能和最终呈现效果分开。即server端主要提供了语法分析、补全、跳转的核心功能,而在客户端要做的就是调用服务端提供的这些功能来展示以及通过快捷键或者其他用户接口以便用户使用。而且语言服务器是以进程的方式单独运行,并不会影响客户端的运行。它们之间通过本地网络的形式进行信息交换用户在工具中打开一个的文件, 该工具通知语言服务器文档打开 ('textDocument/didOpen') 。 从现在起,有关文档内容不再位于文件系统上,而是保存在编辑器开辟的一块内容中用户进行编辑:该工具通知服务器文档更改 ('textDocument/didChange') ,程序语义信息由语言服务器更新。 发生这种情况时,语言服务器会分析此信息,并通知工具 ('textDocument/publishDiagnostics') 检测到的错误和警告,并且还可能返回一些可能的用于补全的内容用户对编辑器中的符号执行“转到定义”:该工具发送具有两个参数的“textDocument/definition”请求: (1) 文档 URI, (2) 从服务器启动 Go to Definition 请求的文本位置。 服务器使用文档 URI 和符号定义在文档中的位置进行响应。客户端接到返回后,根据服务器标记的位置进行跳转用户关闭文档 (文件) :工具发送“textDocument/didClose”通知,通知语言服务器文档现在不再处于内存中,并且将当前内容保存到文件系统中。treesitter 配置我们简单介绍过 neovim-treesitter 这个插件,它可以用来做代码高亮。它采用 lsp 协议实现,比起单纯使用正则表达式来说,它具有更好的渲染效果。那么我们体验 lsp 效果的第一步就来配置它吧。treesitter 想要工作,需要根据语言下载配套语言对应的语法解析模块,我们可以使用 :TSInstallInfo 来查看当前我们安装了哪些解析模块。我们发现并没有安装任何的模块,基于当前配置文件的工程,我们先来体验一下 lua 的效果。我们使用 :TSInstall <language>的命令可以下载指定语言的模块。这里我们使用 :TSInstall lua 来下载lua模块。后续我们可以使用 :TSUpdate lua 来更新该模块。跟 packer 类似的 :TSUpdate 即可以用来下载也可以用来更新。也就是一条命令就搞定了安装完成之后我们可以使用 :TSBufToggle highlight 来使用 treesitter 进行高亮如果我们每次都需要手工调用命令来进行高亮的话,就太不智能了。我们可以在配置文件中配置它自动加载语法高亮。require('nvim-treesitter.configs').setup({ -- 支持的语言 ensure_installed = {"html", "css", "vim", "lua", "javascript", "typescript", "c", "cpp", "python"}, -- 启用代码高亮 highlight = { enable = true, additional_vim_regex_highlighting = false }, --启用增量选择 incremental_selection = { enable = true, keymaps = { init_selection = '<CR>', node_incremental = '<CR>', node_decremental = '<BS>', scope_incremental = '<TAB>' } }, -- 启用基于 Treesitter 的代码格式化(=) indent = { enable = true }, }) -- 开启代码折叠 vim.wo.foldmethod = 'expr' vim.wo.foldexpr = 'nvim_treesitter#foldexpr()' -- 默认不折叠 vim.wo.foldlevel = 99我们来一条条的解释这些配置ensure_installed 表示需要支持哪些语言,如果里面设置了某些语言,那么在启动之后它会自动调用 :TSUpdate 来下载和更新对应语言的 server 部分。等它下载完了对应的语言模块之后,我们发现它已经很好的完成了代码着色的功能。增量选择可以一次选择一块的代码,依次扩大或者缩小所选择的语言块,我们使用回车来开始和扩大增量选择,使用退格键来减少增量选择代码块。各位小伙伴可以根据自己的习惯来定义快捷键另外我们可以使用 = 来格式化代码。为了方便我们定义自动命令,每当执行 :w 写入前前自动格式化代码local auto_indent = vim.api.nvim_create_augroup("AUTO_INDENT", {clear = true}) vim.api.nvim_create_autocmd({"BufWritePost"}, { pattern = "*", group = auto_indent, command = 'normal! gg=G``' })这里因为提前使用了 gg改变了光标位置,在格式化之后使用 \`\` 来回到上次跳转之前的位置。最后我们可以使用 zc 和 zo 来折叠和展开代码。不过我自己很少用,需要查看文件中的符号例如函数、变量等我可以使用其他插件来解决,如果要成块的跳转代码我比较喜欢使用 %。好了,到此为止我们先体验了一下基于 lsp 实现的 treesitter 的功能,后面将展开讲述 lsp 对一些语言的支持,敬请期待
2022年09月06日
14 阅读
0 评论
0 点赞
2022-09-05
从零开始配置vim(21)——会话管理
很多代码编辑器都有这么一个功能,重新进入编辑器之后能恢复上次打开的所有文件,窗口布局,有的甚至是上次设置的一些配置。那么vim是否也可以实现这样的功能呢?答案是肯定的。使用vim自带的会话管理和 viminfo 可以实现恢复上次打开文件和布局以及重置上次的配置它们二者分别保存了不同的内容,一般会将它们联合起来使用。会话一般保留上次打开的文件、窗口布局、以及一些全局设置viminfo 保留的是历史命令行记录、搜索替换模式记录、标签、非空寄存器的值、缓冲区列表、全局信息等等看起来很好像显的很杂一样,但是我觉得这些都不是需要记忆的,我们只需要知道使用使用 viminfo 和session可以恢复所有我们关心的内容即可,无需分辨哪些内容保存在哪个位置。我们使用自动命令来保存和加载它们,你甚至可能会忘记它们的存在。会话我们还是按照惯例,先来试试vim原生的内容我们可以使用 :mksession [file] 来保存一个当前的会话。再重新进入vim 的时候可以使用 :source session-file 来加载一个会话文件。在实际生成会话文件时,我们可以省略这个文件名,这个时候vim会自动生成一个采用默认文件名的会话文件。vim会默认在当前工作目录下生成一个 Session.vim的文件,我们打开这个文件发现它本质上就是一个vim的脚本,跟我们写的配置文件是一回事。各位小伙伴可以打开看看,试着读一下它里面具体在干嘛。我们来试着做一下这个实验,就以当前正在使用的 vim 配置这个工程。我们随机打开几个文件,然后执行 :mksession ,然后退出关闭vim之后,我们发现在项目的根目录也就是 ~/.config/nvim 下,生成一个了一个 Session.vim 。有兴趣的小伙伴可以打开来看看里面的内容。它其实就是一个vim脚本,跟我们写的配置是一回事接着我们试着在终端输入 nvim 不带任何参数,直接打开我们的欢迎界面,在该界面中输入 :source Session.vim 。执行完成之后我们发现,它帮助我们将显示还原成了上次退出之前的样子默认session要保存 哪些内容是由一个名为 sessionoption的变量决定的。不知道小伙伴还记不记得如何来查看一个变量现在的值?(:set sessionoption?) 。使用set在对应变量后面加上一个 ? 表示查询当前变量值。我们看到它目前保存这些内容 sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize。他们分别代表着空窗口、所有缓冲区、当前目录、折叠、帮助窗口、标签页、窗口大小。viminfo 文件vim每次在退出时会自动在用户的家目录保存一个名为 .viminfo 的文件,每次退出后都会发生覆盖行为。有时我们在编辑项目之后又重新打开vim编辑了另外一些内容,这个时候就有可能发生覆盖行为,把我们项目相关的内容给覆盖掉了,那这个时候该怎么办呢?好在vim提供了 :wviminfo命令来指定写入到哪个viminfo文件中。我们可以使用 :rviminfo来读入指定的viminfo文件。小伙伴可能有一个问题。既然Session.vim 是一个vim脚本,为什么不把所有设置都写在配置文件里面呢?我们可以这么做,但是提供一个额外的session功能可以根据项目来灵活的调整配置,我们将所有项目的通用配置保存在我们自己的配置文件里面,将某些项目特有的配置放到session中,由vim自己维护,这样vim能更好的适应不同的使用场合。viminfo 保存的是命令行,搜索记录这些,而且每次打开都会自动加载,所以就不像session 这样能很明显的看出效果。很明显的一个特征就是,即使我们这次打开仅仅只用了 :q 这一个命令,但是我们通过 q: 仍然可以看到之前几次打开时执行过的命令简单的配置为了防止小伙伴做无用功,我这里事先声明一下,针对会话管理我们是有专门的插件的。这里所做的配置在后面都会被我们弃用的,小伙伴可以不往自己的配置里面加了。但是想试试也可以,有些事只有自己亲手做了才能更好的理解首先我们希望它在退出的时候能自动保存Session和viminfo文件到对应的项目根目录下。在启动时能重新加载这些文件。自然要自动进行这些内容,我们想到的就是自动命令了。我们先来定义一个函数来保存这两个文件function save_session() local curdir = vim.api.nvim_eval([[getcwd()]]) local session_file = curdir .. "/Session.vim" vim.cmd([[mksession ]] .. session_file) local viminfo = curdir .. "/.viminfo" end在该函数中,我们使用 vim的 getcwd 命令来获取当前vim所在的工作目录。工作目录的概念我们在之前介绍vim的时候已经介绍过了,忘记的小伙伴请自行折回去复习。然后我们拼接一个字符串,让vim保存session和viminfo文件到当前工作目录中我们再来添加一个函数用来加载 session 内容。function load_session() local curdir = vim.api.nvim_eval([[getcwd()]]) local session_file = curdir .. "/Session.vim" local viminfo = curdir .. "/.viminfo" file, err = io.open(session_file, "r") if err == nil then file:close() vim.cmd([[source ]] .. session_file) end file, err = io.open(viminfo, "r") if err == nil then file:close() vim.cmd([[rviminfo ]] .. viminfo) end end与保存函数不同的是,我这里加了一个判断文件是否存在的代码,因为我们无法得知用户会在哪个目录下打开vim,无法事先知道该目录是否有这些文件,所以这里先判断一下,如果没有文件就不进行任何操作。最后我们添加一个自动命令组来自动保存和加载 session 文件和 viminfo文件。local auto_save_session = vim.api.nvim_create_augroup("AUTO_SAVE_SESSION", {clear = true}) vim.api.nvim_create_autocmd({"ExitPre"}, { pattern = "*", group = auto_save_session, callback = save_session }) vim.api.nvim_create_autocmd({"VimEnter"}, { pattern = "*", group = auto_save_session, callback = load_session })我们在终端直接输入 nvim 发现它自动恢复了上次打开的所有缓冲区。我们来试一下效果,先删除上一次生成的 Session.vim 文件,接着退出然后再次打开 vim ,我们发现它恢复到了打开之前的样子到此我们已经有了一个简单的自动加载session 和上次配置的功能。如果希望有更多的定制可以考虑使用插件,但是如果只是简单的需要此功能的,可以就这么配置或者自己改改配置达到自己的需求。auto-session 插件上面我们已经定义了可以自动加载和保存上次会话的功能。有的小伙伴可能觉得这个功能太简单了,我希望能给我提供更方便、更加灵活的使用方式,而且我们上面的配置有一个很大的问题,我输入 nvim init.lua 已经指定了要打开的文件,它仍然会打开之前保存的 session ,这里我再介绍一个能够管理 session 的插件—— auto-session ,它能有效的避免上面的问题。我们使用如下的语句来安装 auto-sessionuse {'rmagatti/auto-session'}然后按照惯例,新建文件并且添加配置require("auto-session").setup({ log_level = "error", -- 打开这些目录里面的内容时,不加载会话 auto_session_suppress_dirs = {"~/", "~/Projects", "~/Downloads", "/", "/ect", "/usr"} auto_session_enable_last_session = false, -- 保存session文件到 ~/.local/share/nvim/sessions目录 auto_session_root_dir = vim.fn.stdpath('data').."/sessions/", auto_session_enabled = true, auto_save_enabled = nil, auto_restore_enabled = nil, auto_session_use_git_branch = nil, -- the configs below are lua only bypass_session_save_file_types = nil })我们可以在 lualine 的配置文件中 sections 一节中添加 lualine_c = {require('auto-session-library').current_session_name} 来显示当前打开的会话名称最后根据官方的提示,我们可以给sessionoption 赋值,多保存两个内容vim.o.sessionoptions="blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal"这样我们如果打开了终端,下次进入时还可以恢复终端窗口最后我们再来补充一下之前 dashboard 的功能,之前定义的有一个恢复上次会话的功能{icon = " ", desc = 'Recently lastest session ', shortcut = "Leader s l", action = "RestoreSession"}我们可以在 custom_center 中添加这么一行,具体的位置可以看我提交到github中的仓库到此为止,关于session的配置就结束了。
2022年09月05日
6 阅读
0 评论
0 点赞
2022-09-01
从零开始配置vim(20)——模糊查询
在讲解vim的基础功能的时候,介绍过了vim的各种查询技巧,在同一个文件中进行搜索的话,那些技巧很有用。在多个文件中我们介绍了使用vim自带的 :grep命令进行搜索,使用quickfix 列表进行跳转,但是比起其他代码编辑器来说,总归有那么一些繁琐光是输入参数都已经很麻烦了,我想要像其他代码编辑器那样直接输入内容它就能基于工程来进行匹配。本篇文章我们将要来对它进行优化,达到这一目的。本次我们要介绍的是神级插件 telescope,一般只要介绍 neovim 配置的文章98%以上的都会推荐这个插件作为文件搜索和文本搜索的插件。我们自然也不能免俗,这里我也要介绍它,如果不介绍就显得有点不太专业了。虽然我也介绍,但是这个系列毕竟是从0开始配置vim,我会从安装到配置进行描述,希望能比其他的教程要详细一点。但是最详细的仍然是它的官方文档。安装我们使用下面的代码进行安装use { 'nvim-telescope/telescope.nvim', tag = '0.1.0', requires = { {'nvim-lua/plenary.nvim'} } }为了更好的使用体验可以安装一个 nvim-treesitter 插件,它主要用于代码高亮,它采用语法分析的形式对代码进行高亮,相比于使用正则表达式来说效果更好,后面会详细的介绍如何进行配置,加上它之后 telescope 插件将会更加强大。这个时候我们的安装代码应该改为use { 'nvim-telescope/telescope.nvim', tag = '0.1.0', requires = { {'nvim-lua/plenary.nvim'} , { 'nvim-treesitter/nvim-treesitter', run = function() require('nvim-treesitter.install').update({ with_sync = true }) end, }} }这里加上一个 run 的配置主要是安装 nvim-treesitter 插件之后,第一次会报错,后面是正常的,这句话是为了消除第一次加载时报错安装完成之后,我们就可以在命令中输入 :Telescope find_files 来按照名称搜索文件它常用的命令有如下几个find_files : 查找文件live_grep: 使用正则表达式来进行内容的搜索,它可以跨文件搜索buffers:查看当前打开的缓冲区,并且可以预览缓冲区的内容grep_string: 以当前光标所在单词进行搜索oldfile: 打开历史文件列表marks: 打开书签表jumplist: 打开跳转列表如果我们希望能够使用 live_grep 和 grep_string 的功能需要提前在系统上安装 ripgrep。例如在ubuntu 上可以使用下列命令安装sudo apt-get install ripgrep配置我们先对最常用的功能进行快捷键的映射vim.api.nvim_set_keymap("n", "<leader>ff", "<Cmd>Telescope find_files<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("n", "<leader>gg", "<Cmd>Telescope live_grep<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("n", "<leader>fm", "<Cmd>Telescope marks<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("n", "<leader>fj", "<Cmd>Telescope jumplist<CR>", {noremap = true, silent = true})不知道各位小伙伴是否还记得,我们在配置启动界面的时候留下了几个功能没有添加,现在我们有了这个插件之后就可以添加一部分了在 dashboard 的配置中,我们可以补充相关功能对应的命令如下db.custom_center = { {icon = " ", desc = 'Recently lastest session ', shortcut = "Leader s l", action = ""}, {icon = " ", desc = "Recently opened files ", shortcut = "Leader f h", action = "Telescope oldfiles"}, {icon = " ", desc = "Find File ", shortcut = "leader f f", action = "Telescope find_files"}, {icon = " ", desc = "File Browser ", shortcut = "leader f b", action = "Telescope file_browser" }, {icon = " ", desc = "Find Word ", shortcut = "leader g g", action = "Telescope live_grep"}, {icon = " ", desc = "Open Personal dotfiles ", shortcut = "leader e e", action = "edit $MYVIMRC"} }要使用 Telescope file_browser 的功能我们需要额外安装一个插件。它扩展了 Telescope 插件的功能use { "nvim-telescope/telescope-file-browser.nvim" }并且我们需要在 telescope 配置中加载这个扩展require('telescope').load_extension "file_browser"这样我们就完成了几乎所有的功能了,还差一个加载上次会话的功能,我们等到讨论会话的时候再来补上到现在我们的配置基本就结束了,我们目前仅仅只使用了它极为有限的功能。根据官方的文档,它有大量的导出函数用于各种功能,但是现在我们并不打算做太多的定制化开发,仅仅拿来用即可,所以目前的配置我认为已经够用了。各位小伙伴也可以根据自己的需求查阅官方文档进行额外的配置
2022年09月01日
8 阅读
0 评论
0 点赞
2022-08-31
从零开始配置vim(19)——终端配置
在上一篇文章中,我们熟悉了终端模式,并且配置了终端模式的一些操作。但是它总是有那么一点不符合我们的使用习惯。这篇我们将通过强大的插件来完善终端操作的体验。在介绍插件之前让我们先回退到上一个版本,我们把上一篇文章中的配置全部从配置文件中剔除。先别着急喷我把各位小伙伴带到沟里去了,动态的调整自己的配置是常有的事,例如我发现了某些好用的插件、某些自己的配置可以淘汰一些插件又或者改变操作习惯等等原因都会导致我们修改配置。所以还是事先习惯的好。toggleterm 插件介绍在 packer 中我们使用如下语句来进行安装use {"akinsho/toggleterm.nvim", tag = 'v2.*'}如果我们用的是 7.0及以上的neovim,可以使用它的 v2版本,否则版本这里应该写上 v1接着我们还是按照之前的惯例,新增一个配置文件并且在init.lua中引用local opt = require("toogleterm").setup({})之后我们可以使用 :ToggleTerm 来打开一个新终端相关配置我们可以对它进行一些简单的配置local opt = require("toggleterm").setup({ open_mapping = [[<c-\>]], -- 打开新终端后自动进入插入模式 start_in_insert = true -- 在当前buffer的下方打开新终端 direction = 'horizontal' })这里我们使用快捷键 <Ctrl+\> 来打开或者关闭终端。我们使用 start_in_insert 配置打开新终端后自动进入插入模式,这样就不需要使用自动命令自己干这个事情了。另外我这里仍然采用它默认的打开方式,默认在下方打开一个新终端,根据个人习惯可以改为弹出式窗口。根据官方文档,还支持 vertical、float、tab。相信各位小伙伴从名字上就能知道它们分别代表何种样式。在之前介绍终端的时候说过,可以使用 <Ctrl+\><Ctrl+n> 来退出终端模式,这里我们仍然对它进行快捷键绑定,仍然使用 来退出终端模式在退出终端模式之后,我们就可以使用相关快捷键来移动光标到指定窗口了,但是这里我们希望在终端模式中能够移动光标,所以这里还是使用快捷键映射的方式来解决这个问题vim.api.nvim_set_keymap("t", "<Esc>", "<C-\\><C-n>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>l", "<Cmd> wincmd l<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>h", "<Cmd> wincmd h<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>j", "<Cmd> wincmd j<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>k", "<Cmd> wincmd k<CR>", {noremap = true, silent = true})如果我们采取上一节的方案,将 l映射为
2022年08月31日
5 阅读
0 评论
0 点赞
2022-08-30
从零开始配置 vim(18)——终端模式
在进入下一个配置之前,先了解一下如何在 neovim 中使用它内置的终端。我们之前说过在命令模式中可以使用 !来执行shell命令。但是终归来说,执行和使用上不是那么方便,特别是混合使用 vim 命令和 shell 命令的时候。两个揉在一起显得那么混乱。好在从早期的 neovim和 8.0以后版本的vim已经内置了一个终端。基本用法首先我们可以使用 :echo has('terminal') 来查看当前版本是否有对应的终端,返回1则代表已经内置了一个终端。但是我的 neovim 本身是有终端的,这个命令在我这边执行的结果是0。具体原因我也不太清楚。有知道的小伙伴欢迎给我留言或者在评论区给出。我们可以输入 :term bash 来启动一个 bash 的 shell 环境。term 命令用来启动一个终端,当然我们也可以使用 :term zsh 或者 :term fish 来启动不同类型的 shell 环境我们发现,刚启动的终端仿佛至于普通模式中一般,可以使用诸如 h、j、k、l 等键来移动光标,使用 a、i 等来进入插入模式,此时左下角显示了一个 terminal 的字样,表示我们已经进入到了终端模式除了这种方式,我们还可以使用 :term cmd来创建终端执行终端命令。这种方式仅仅打开一个一次性终端,执行完输入命令之后,终端就结束了。而第一种方式能打开一个交互式终端。这种方式合适执行那种一次性的命令,例如编译当前程序这种命令它其实是打开了一个新的缓冲区,并在这个新缓冲区中渲染并模拟终端操作。我们可以在打开终端后,使用 :ls 来查看,此时它已经有了两个缓冲区我们之前介绍缓冲区的时候说过,:ls 命令可以查看缓冲区名称,而名称则是缓冲区所绑定的文件名。vim可以使用 :vsplit 或者 :edit 来创建新的缓冲区。结合这个逻辑,我们可以使用 :vsplit 在竖直位置创建新的终端。这里我们不需要输入那么长的一段直接使用 :vsplit term://zsh即可在普通的缓冲区中,可以使用 <ESC> 键从插入模式退出到普通模式,但是在终端的这个缓冲中,我们无法这么做,我们可以使用 <C-\><C-n> 来回到该缓冲区的普通模式,当然我们可以映射,只是这个时候模式我们应该使用 t 代表终端模式vim.api.nvim_set_keymap("t", "<ESC>", "<C-\\><C-n>", {noremap = true, silent = true})退回到普通模式之后,我们就可以将它当做一个普通的缓冲区来进行处理。包括关闭和跳转窗口。在后面设置快捷键的时候都可以用到这个先退回到普通模式,然后执行普通模式的操作终端相关配置到现在为止,我们已经了解了该如何打开、使用、并关闭终端。我们还是希望对它进行一些简单的配置,以便我们可以更方便的使用。快速打开关闭终端每次打开都要输入命令 :term 而且每次关闭都要先退出再关闭,我们希望它能够像vs code那样用一个快捷键快速打卡和关闭终端。我们先来实现快速打开的功能。我们只需要在普通模式下映射一个快捷键vim.api.nvim_set_keymap("n", "<A-=>", ":split term://zsh<CR>", {noremap = true, silent = true})我们再试着定义一个关闭终端的快捷键,我这里的实现思路是在终端模式中,先退回到普通模式,然后按照普通模式的思路来退出一个 buffervim.api.nvim_set_keymap("t", "<A-=>", "<C-\\><C-n>:bdelete! %<CR>", , {noremap = true, silent = true})因为终端的缓冲区是一个只读的缓冲区,这里我们结束时需要使用 ! 来强制结束窗口间跳转我们发现在打开终端之后,我们的 bufferline 插件为它分配了一个新的标签,我们还是沿用原先的使用 leader 的思路vim.api.nvim_set_keymap("t", "<leader>1", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>2", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>3", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>4", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>5", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>6", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>7", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>8", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>9", "<C-\\><C-n>:BufferLineGoToBuffer 1<CR>", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>bg", "<C-\\><C-n>:BufferLinePick<CR>", {noremap = true, silent = true})在普通模式下,终端只是一个普通的 buffer,可以在命令模式下执行 bufferline 的跳转命令。我们这里定义了在处于终端中的插入模式时使用的快捷键,这里我们应该先让它从插入模式退回到普通模式,这样我们就可以使用 bufferline 相关的命令了另外我们再来定义一些在分屏状态下可以进行跳转的快捷键。还是沿用我们之前在普通缓冲区定义的那些快捷键vim.api.nvim_set_keymap("t", "<leader>h", "<C-\\><C-n><C-w>h", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>l", "<C-\\><C-n><C-w>l", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>j", "<C-\\><C-n><C-w>j", {noremap = true, silent = true}) vim.api.nvim_set_keymap("t", "<leader>k", "<C-\\><C-n><C-w>k", {noremap = true, silent = true})这些主要用到的就是先退回到普通模式,然后执行普通模式的命令使用自动命令组对终端进行配置关于终端模式,我们能使用的事件主要是以下几个:TermOpen: 当我们打开一个终端时产生该事件TermEnter: 当我们在终端buffer中进入插入模式时,触发该事件TermLevel: 当我们退出终端模式时,触发该事件TermClose: 当我们关闭终端所在 buffer时触发该事件我们可以通过如下的测试代码来体会它们各自触发的时机vim.cmd[[ augroup TERM_MODE autocmd! autocmd TermOpen * echom "TermOpen Events" autocmd TermEnter * echom "TermEnter Events" autocmd TermLeave * echom "TermLeave Events" autocmd TermClose * echom "TermClose Events" augroup END ]]我们发现,执行 :term 打开终端 buffer 之后,会打印 TermOpen Events 字样。当我们使用 i 正式进入终端模式之后, TermEnter Events 会打印。使用 <ESC> 退出之后,TermLeave 会打印。而真正关闭该缓冲区之后, TermClose Events会被打印。从这个例子相信各位小伙伴能够理解这些事件触发的时机了。了解了这些之后,我们来利用它做一个小小的改变,每次打开终端总是要自己使用 i 或者 a 进入到插入模式才能开始在终端中输入命令,我想通过自动命令每次打开终端之后自动进入插入模式--打开终端后自动进入插入模式 local term_mode = vim.api.nvim_create_augroup("TERM_MODE", {clear = true}) vim.api.nvim_create_autocmd({"TermOpen"}, { pattern = "*", group = term_mode, command = [[normal i]] })需要注意的是这里 command 填入的命令模式下需要使用的指令,在命令模式下使用普通模式的指令需要使用 normal 作为前缀。到此位置我们主要介绍了终端模式中的一些基本操作,但是总会有那么一些不尽人意,例如无法以弹出式窗口的形式打开终端,无法轻松的自定义一些用于特定功能的终端,下一篇我们将要来介绍用插件来增强我们原始终端的能力,敬请期待!
2022年08月30日
6 阅读
0 评论
0 点赞
2022-08-19
从零开始配置 vim(17)——快捷键提示
之前我们定义了各种各样的快捷键,有为了增强功能自定义的,有针对插件的。数量一多有的时候就不那么容易记忆了。要是每次要去配置文件找我定义了哪些快捷键肯定会影响使用的。本篇将要介绍一个插件,它是快捷键的一个词典,可以快速找到我们想要的快捷键安装使用 packer 的小伙伴可以使用如下代码进行安装use {"folke/which-key.nvim"}然后我们新建一个文件作为它的配置文件,并写入如下代码require("which-key").setup({})这个时候我们使用一些快捷键并且在中间停顿一下就可以看到它已经给出了相关的提示了配置默认的配置已经足够好了,基本不需要我们对它的行为做某些配置。它真正强大的地方在于,我们可以自己注册快捷键到显示中去。有时候不知道什么原因某些插件或者我们自定义的快捷键无法显示时可以使用这个方法注册到显示中。假设我们现在有一个 <leader>ff 的键,它用来打开配置文件,但是它在 which-key 中没有显示出来,我们可以使用它的 register 方法来注册。该方法原型如下register(mappings, opts)它接收两个 table 参数,第一个表示需要注册的快捷键绑定,第二个是注册时的一些属性。mappings 中的字段主要用来定义快捷键以及它的显示文字,后面我们通过例子来体会它的具体参数opts 主要有下面几个参数mode: 表示模式,与nvim_set_keymap第一个参数中的模式相同prefix: 前置键,我们触发该条快捷键需要的前置键,一般使用leader作为前置键buffer: 命令对应的缓冲区id,用它来指定这个绑定作用于某个局部缓冲区silent: 同我们之间介绍的 nvim_set_keymap中的 silent含义noremap: 快捷键不进行递归传递接下来我们通过几个例子来体会它的用法local wk = require("which-key") wk.register({ f = { name = "myvimrc", -- 指定该快捷键组的名称 f = {":edit $MYVIMRC<CR>", "Open vimrc"}, -- 创建新的快捷键绑定 s = {":source $MYVIMRC<CR>", "reload vimrc", noremap = true}, -- 也可以只显示一个标签而不绑定到具体的快捷键 e = {"New File"} } }, {prefix = "<leader>"})通过上面的代码我们绑定了 <leader>ff、<leader>fs 和 <leader>fe 这三个快捷键。我们可以尝试一下执行 <leader>ff 发现它确实打开了我们的配置文件,而且我们稍微停顿一下它也给出了提示我们将这个改写一下wk.register({ ["<leader>"] = { f = { name = "myvimrc", -- 指定该快捷键组的名称 f = {":edit $MYVIMRC<CR>", "Open vimrc"}, -- 创建新的快捷键绑定 s = {":source $MYVIMRC<CR>", "reload vimrc", noremap = true}, -- 也可以只显示一个标签而不绑定到具体的快捷键 e = {"New File"} } } }, {silent = true, noremap = true})或者也可以改写为这样wk.register({ ["<leader>f"] = { name = "myvimrc", f = { ":edit $MYVIMRC<CR>", "Open vimrc" }, s = { ":source $MYVIMRC<CR>", "reload vimrc", noremap = true }, n = { "New File" }, }, })wk.register({ ["<leader>f"] = { name = "myvimrc" }, ["<leader>ff"] = { ":edit $MYVIMRC<CR>", "Open vimrc" }, ["<leader>fs"] = { ":source $MYVIMRC<CR>", "reload vimrc", noremap = true }, ["<leader>fn"] = { "New File" }, })到这里相信各位小伙伴应该已经明白了如何使用 mappings这个字段,它外层是每次按下的按键,最内层则用来绑定具体的命令和提示时显示的具体内容。一般来说我们用不到这个东西,但是如果希望动态的修改这个显示的内容,例如把快捷键归类,这个就很有用了。我们可以对照一下之前定义的快捷键,发现分屏相关的快捷键并没有显示出提示,这个时候我们就可以将它添加到对应的快捷键中wk.register({ ["s"] = { name = "split window", v = { ":vsp<CR>", "vertical split window" }, h = { ":sh<CR>", "horizontal split window"}, c = { ":close<CR>", "close this window"}, o = { ":only<CR>", "close all but this window"}, }, }, {noremap = true, silent = true})如果你不喜欢它用英文显示,还可以尝试 将所有英文提示改为中文,这是一个浩大的工程,有兴趣的小伙伴可以尝试一下查看所有快捷键绑定有时候我们不知道某个功能具体绑定到哪个键上面了,甚至不知道它有这个快捷键绑定,这个时候可以使用 :WhichKey 这个命令来检查一下。它默认有2个参数第一个参数是一个字符串,查看所有以此字符串为开头的快捷键,例如使用 :WhichKey <leader>s 来查看所有以 <leader>s开头的快捷键第二个参数一个是表示模式的字符,用来限定它只显示绑定在某个模式中的快捷键,例如 :WhichKey<leader>s n 只显示在 normal 模式下的快捷键好了,本篇的内容到此就结束了。
2022年08月19日
6 阅读
0 评论
0 点赞
2022-08-18
从零开始配置 vim(16)——启动界面配置
不知道各位小伙伴用过 spacevim或者 LunarVim又或者 doomvim或者其他的什么 vim配置框架,我们发现他们的启动界面都做的比较好看,而我们默认进入的启动界面则显得比较素了。这篇文章我们将来教大家使用插件打造属于自己的启动界面使用 dashboard-nvim 插件这部分我主要使用的是插件 dashboard-nvim 。与之前的插件类似,我们可以使用下面的语句来安装use {'glepnir/dashboard-nvim'}我们可以使用如下语句来加载该插件local db = require("dashboard")然后我们重新进入 neovim 之后,发现它已经给我们显示了一个默认的启动界面针对启动界面的配置分为三个部分,显示头信息、中间内容以及底部的内容。我们来分别对其进行配置配置显示头图中使用蓝色显示的 dashboard为显示头,我们可以使用 custom_header变量进行配置。官方贴心的给了很多使用ascii字符显示的图片可以供我们选择(ascii-text-header),例如我们使用如下的配置db.custom_header = { ' ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⣴⣶⣶⣶⣶⣶⠶⣶⣤⣤⣀⠀⠀⠀⠀⠀⠀ ', ' ⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⣿⣿⠁⠀⢀⠈⢿⢀⣀⠀⠹⣿⣿⣿⣦⣄⠀⠀⠀ ', ' ⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⠿⠀⠀⣟⡇⢘⣾⣽⠀⠀⡏⠉⠙⢛⣿⣷⡖⠀ ', ' ⠀⠀⠀⠀⠀⣾⣿⣿⡿⠿⠷⠶⠤⠙⠒⠀⠒⢻⣿⣿⡷⠋⠀⠴⠞⠋⠁⢙⣿⣄ ', ' ⠀⠀⠀⠀⢸⣿⣿⣯⣤⣤⣤⣤⣤⡄⠀⠀⠀⠀⠉⢹⡄⠀⠀⠀⠛⠛⠋⠉⠹⡇ ', ' ⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀⣀⣠⣤⣤⣤⣤⣤⣤⣤⣼⣇⣀⣀⣀⣛⣛⣒⣲⢾⡷ ', ' ⢀⠤⠒⠒⢼⣿⣿⠶⠞⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⣼⠃ ', ' ⢮⠀⠀⠀⠀⣿⣿⣆⠀⠀⠻⣿⡿⠛⠉⠉⠁⠀⠉⠉⠛⠿⣿⣿⠟⠁⠀⣼⠃⠀ ', ' ⠈⠓⠶⣶⣾⣿⣿⣿⣧⡀⠀⠈⠒⢤⣀⣀⡀⠀⠀⣀⣀⡠⠚⠁⠀⢀⡼⠃⠀⠀ ', ' ⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣷⣤⣤⣤⣤⣭⣭⣭⣭⣭⣥⣤⣤⣤⣴⣟⠁ ', }我们再次打开就发现头已经变成哆啦A梦了。如果你喜欢彩色样式的话,官方已经给出了解决办法了。可以通过 lolcat 或者 ueberzug 来生成彩色图片,然后嵌入到 custom_header 变量中。这里就不过多演示了定义中间部分中间部分表示的是它显示为 Please Config your own center section 这块的内容。我们可以使用 custom_center 来定义custom_center 是一个 table。它的每个部分对应着一条显示。每条显示和功能我们可以使用如下字段来进行定制icon : 当前显示图标desc:某个功能的描述信息,后面会原样显示出来shortcut:快捷键action:在某项位置回车时执行的命令我们按照官方给出的截图上的功能进行定义db.custom_center = { {icon = " ", desc = 'Recently lastest session ', shortcut = "Leader s l", action = ""}, {icon = " ", desc = "Recently opened files ", shortcut = "Leader f h", action = ""}, {icon = " ", desc = "Find File ", shortcut = "leader f f", action = ""}, {icon = " ", desc = "File Browser ", shortcut = "leader f b", action = ""}, {icon = " ", desc = "Find Word ", shortcut = "leader f w", action = ""}, {icon = " ", desc = "Open Personal dotfiles ", shortcut = "leader e e", action = "edit $MYVIMRC"} }其他地方的功能我们先不管,暂时在 action 这个字段上填上空,我们先实现最后打开个人配置文件那个位置的代码,我们在 action 中填入 edit $MYVIMRC。再次打开,我们发现它已经可以显示这些内容了并且我们在最后一项回车,发现它打开了当前配置文件各位可以尝试一下,它并不能帮助我们自动将 shortcut 字段与 action 结合绑定为快捷键。仅仅作为一行的几个元素进行显示而已。而 action 则是按下回车会执行的命令footer 定义footer这部分与之前定义 header类似,也是一个 table组成的字符串。 这里我们可以对他进行一些扩展,例如我这里可以使用下面的函数获取到底加载了哪些插件作为我们优化启动速度的依据db.custom_footer = function() local footer = {'', '🎉 Have fun with neovim'} if packer_plugins ~= nil then local count = #vim.tbl_keys(packer_plugins) footer[2] = '🎉 neovim loaded ' .. count .. ' plugins' for key, value in pairs(packer_plugins) do table.insert(footer, '✨ ' .. key) end end print(footer) return footer end我们再次重启 neovim 之后发现,它已经帮我们显示了它加载了哪些插件我们发现关于主题的插件它加载了两个,后面我们可以选择注释掉一个。本篇就到此结束了,剩下的插件我们在下一篇继续介绍
2022年08月18日
4 阅读
0 评论
0 点赞
2022-08-17
从零开始配置 vim(15)——状态栏配置
vim 下侧有一个状态栏,会显示当前打开的文件等一系列内容,只是我们很少去关注它。而且原生的vim也支持对状态栏进行自定义。这篇文章主要介绍如何自定义状态栏设置状态栏我们可以采用 set statusline 来设置状态栏。例如我们输入 :set statusline=%f\ -\ FileType=%y。之后我们可以发现它变成了如下这个样子statusline 的值是一个格式字符串。上述命令我们使用了 %f 表示当前文件名称 。从上面的命令中明显感觉到只输出两个内容就已经开始显的比较繁琐了,如果显示的内容多了是不是就更加难以阅读和书写了呢?好在我们还能使用 lua来做设置。上述内容可以翻译为如下的 lua代码vim.o.statusline = "%f - FileType=%y"我们保存之后发现下方的状态栏显示内容已经发生变化。控制边距和宽度如果你写过 c 或者其他编程语言中的输出语句,应该很容易理解如何控制输出的格式,一般使用类似 %4l` 这样的语句来控制该项占4个字符宽度。这里的设置也是类似的vim.o.statusline = "%20f - FileType=%y"它表示 文件名这项应该站20个字符宽度。最终效果如下所示默认它的边距是添加在左边的,这样会让左侧空出一大半,会显得比较难看,我们可以使用 -来使空白站位符显示在右侧vim.o.statusline = "%-20f - FileType=%y"当然我们也可以控制一下输出字符的最大长度,例如使用如下代码vim.o.statusline = "%0.10F - FileType=%y"使用 %F可以显示文件的全路径。这里我们发现全路径大于10个字符,但是它只是显示了10个字符。使用这个方法可以防止某些超长的字符串破坏了我之前的布局分割我们再来介绍一个符号 %=,它表示将 %= 后面的内容全局居右对齐,例如vim.o.statusline = "%f %= FileType=%y"将得到如下显示内容更多的关于各个标识符代表的含义可以使用 :help statusline 来查看。练习最后我们来做一个小练习,我们希望将状态栏显示为如下内容mode | filename[status] | currentline:totalline |encoding|filetype|其中 mode 代表当前所处模式、filename 代表文件名称、status 代表文件状态(是否可读写、是否保存)、currentline 代表光标当前所在行数、totalline 代表文件一共多少行、encoding 代表文件编码、filetype 代表文件类型我们通过查阅文档可以知道:文件名称可以使用 %f 来显示文件状态可以使用 %m 来显示当前行可以使用 %l当前buffer总行数可以使用 %L文件类型可以使用 %y 来显示至于当前模式和文件类型我们先不管它,根据这些内容我们可以写下如下代码vim.o.statusline = "mode|%f%m|%l:%L%=encoding|%y"[+] 表示对缓冲区所做的修改还没有写入到磁盘中。执行:w写入之后发现它直接消失了我们可以通过 vim.g.encoding 来获取当前文件的编码方式,因此我们改一下当前代码vim.o.statusline = "mode|%f%m|%l:%L%=" .. vim.g.encoding .. "|%y"我们发现此时的状态已经改过来了。最麻烦的是模式,vim 中提供了一个可以获取当前模式的函数 mode 。但是在 lua 接口中我没有找到对应的函数。因此我们仍然采用在 lua 中调用 vimscript 的方式。这次我们使用函数 vim.api.nvim_eval()。它可以执行 vim 命令并将返回执行的结果。我们可以定义一个函数返回当前所处模式function get_mode() local mode = vim.api.nvim_eval([[mode]]) if mode == "n" then return "Normal" elseif mode == "v" then return "Visual" elseif mode == "i" then return "Insert" else return "" end end这里我们为了演示只返回了 3中模式的字符串,更多模式可以查看vim的帮助文档我们希望模式改变时对应的就修改 mode 对应的字段,此时我们应该采用自动命令。查看vim的用户手册我们发现,针对模式变化这一事件有一个叫做 ModeChanged 的事件类型,因此我们可以写下一些代码local cmd_statusline = vim.api.nvim_create_autogroup("SET_STATUS_LINE", {clear = true}) vim.api.nvim_create_autocmd({"ModeChanged"}, { pattern = "*", group = cmd_statusline, callback = function() local win_id = vim.api.nvim_eval([[win_getid()]]) --获取当前window id vim.wo[win_id].statusline = get_mode() .. "|%f%m|%l:%L%=" .. vim.g.encoding .. "|%y" -- 使用 setlocal 针对窗口设置本地化配置 end )后面我们可以对字符串进行一些格式控制,这里就不展开了。我们将这些代码写到 init.lua中,保存后发现它大致效果如下我们发现就是简单的设置状态栏的工作也是比较麻烦的。而且有时候我们又想它好看,带点颜色什么的。这就更麻烦了。好在有大量的插件可以帮助我们来完成这一工作lualine 插件lualine 是一个用 lua 语言开发的 neovim 的状态栏美化插件,可以使用如下代码进行安装use { 'nvim-lualine/lualine.nvim', requires = { 'kyazdani42/nvim-web-devicons', opt = true } }我们创建 lualine 的配置文件,加入加载 lualine 的代码require("lualine").setup()然后在主配置文件中加载该文件require("plugin-config/lualine")lualine 官方提供了3种主题的配色,我们可以直接在代码中引用,例如我这里引用 evil_lualine 这个配置,然后将 theme改为之前我们安装的 tokyonight主题theme = "tokyonight"到这里我们已经完成了 状态栏的美化,其实主要靠插件,本篇一大部分写了如何使用原生的statusline 设置主要是自己手工设置比较有意思,而且也可以凑文章字数,其实你不知道statusline 这个也无所谓,很多插件都都对原生的方式进行了大量封装,而且能进行高度的自定义。完全可以满足你各种奇怪的口味。当然状态栏配置并不只有这一种插件,如果你知道有哪些状态栏的插件也欢迎在评论区留言给出
2022年08月17日
17 阅读
0 评论
0 点赞
1
2
3
...
6