Neovim - 重构编辑器配置
目录
需求来源
在使用 Neovim 一年多以后,发现之前配置的 Neovim 中的很多功能用不上,显得 Neovim 中的配置十分地臃肿,因此打算重新写一份 Neovim 的配置指南,便于后面重新构建 Neovim,也给需要从零开始构建的朋友们一个参考。
现在配置的 Neovim 具有以下功能:
- 能够运行 $\LaTeX$ 并且支持实时预览,一键清理 $\LaTeX$ 的附属文件,支持正向搜索和反向搜索
- 能够方便地切换文件夹中和文件进行编辑,提供类似 VS Code 的文件浏览侧边栏
- 能够支持 $\LaTeX$,C++/C 和 Python 代码的高亮和自动补全
- 支持 C++/C 和 Python 代码的编译和运行
- 好看的主题和类 VS Code 的界面 UI
- 支持 Git 查看新增和修改的代码段,优化 Git 提交显示
- 支持彩虹配对括号和特殊注释高亮
- 自动高亮和当前光标下相对应的单词
- 显示不同缩进参考线
- 支持快速查询快捷键和 Git 记录查询
- 自动切换中英输入法
- 美观的状态栏以及丰富的图标支持
- 支持模糊搜索
- 支持给指定文本快速添加配对符号如括号、引号等
- 集成 Copilot AI 辅助代码和文本写作
- 支持快捷注释和取消注释代码块
- 提供缓冲区标签栏,支持快速切换缓冲区和鼠标操作
- 支持插件管理界面和懒加载
- 支持自定义代码片段替换和插入
如果想要开箱即用,我个人的 Neovim 配置的仓库地址:[neovim-config](https://github.com/chen-huaneng/neovim-config)
版本信息
我使用的系统是 Windows 10 22H2,我的 Neovim 版本信息如下:
1NVIM v0.11.3
2Build type: Release
3LuaJIT 2.1.1741730670
4
5 system vimrc file: "$VIM/sysinit.vim"
6 fall-back for $VIM: "C:/Program Files (x86)/nvim/share/nvim"
7
8Run :checkhealth for more info
Neovim 配置基础知识
Lua 语言
在配置 Neovim 的时候,尽量使用 Lua,因为这是 Neovim 而不是 Vim,如果对 Lua 不了解,可以快速了解一下基本的语法和语义: Learn Lua in Y Minutes。
配置文件路径
在 Windows 10 系统中,Neovim 的配置文件路径一般在 C:\Users\<UserName>\AppData\Local\nvim\
。默认会读取该文件夹下的 init.lua
或者 init.vim
文件,这也是配置文件的主入口,理论上来说可以将所有的配置都写到这个文件里面,但是这不是一个好做法,因此划分成不同的文件和目录来管理不同功能的配置会更好。
本篇教程配置 Neovim 之后的目录结构应该是下面的样子:
1.
2│ im-select.exe
3│ init.lua
4│ lazy-lock.json
5│
6├───lua
7│ │ bootstrap.lua
8│ │
9│ ├───core
10│ │ autocmds.lua
11│ │ functions.lua
12│ │ init.lua
13│ │ keymaps.lua
14│ │ options.lua
15│ │
16│ └───plugins
17│ │ autopairs.lua
18│ │ bufferline.lua
19│ │ colorscheme.lua
20│ │ comment.lua
21│ │ copilot.lua
22│ │ gitsigns.lua
23│ │ im-select.lua
24│ │ indent-blankline.lua
25│ │ local-highlight.lua
26│ │ lualine.lua
27│ │ luasnip.lua
28│ │ nvim-tree.lua
29│ │ nvim-web-devicons.lua
30│ │ rainbow-delimiters.lua
31│ │ surround.lua
32│ │ telescope.lua
33│ │ todo-comments.lua
34│ │ treesitter.lua
35│ │ vimtex.lua
36│ │ which-key.lua
37│ │
38│ └───lsp
39│ lspconfig.lua
40│ mason.lua
41│ nvim-cmp.lua
42│ vimtex-cmp.lua
43│
44└───snippets
45 tex.lua
解释如下:
init.lua
为 Neovim 配置的主入口,用于导入其他*.lua
文件。lua
目录,当我们在 Lua 中调用require
加载模块(文件)的时候,它会自动在lua
文件夹里进行搜索- 将路径分隔符从
/
替换为.
,然后去掉.lua
后缀就得到了require
的参数格式
- 将路径分隔符从
core
目录,用于管理核心配置和 Neovim 自带的配置plugins
目录,用于管理插件snippets
目录,用于管理自定义代码片段
选项配置
主要用到的就是 vim.g
、vim.opt
、vim.cmd
按键配置
在 Neovim 中进行按键绑定的语法如下:
1vim.keymap.set(<mode>, <key>, <action>, <opts>)
从零开始配置 Neovim
在配置 Neovim 的时候弄清楚每一个选项的意思是很有必要的,因此会尽量在本文中说明每个选项的含义,同时在配置中会有相应的注释,如果没有说明则该选项的意义在注释中可以找到,尽量让配置文件是 self-contained 而且可读性强。
安装 Neovim
我使用的是 Scoop,因此安装 Neovim 只需要在命令行中运行下面的指令就可以:
1scoop install main/neovim
安装完成之后如果不存在前面说的配置文件夹和相应的 init.lua
文件,直接创建目录并新建 init.lua
文件即可。每次修改配置文件后,将配置文件编辑保存,重启 Neovim 就能看到相应的效果。接下来会按照 Neovim 启动执行文件的顺序介绍各个模块。
init.lua
入口文件
Neovim 启动时首先加载的就是 init.lua
文件:
require("core")
加载lua/core/init.lua
,初始化所有核心编辑器设置require("bootstrap")
加载lua/boostrap.lua
,启动并配置lazy.nvim
插件管理器
init.lua
文件配置:
1require("core")
2require("bootstrap")
`lazy-lock.json` 文件由 `lazy.nvim` 自动生成和管理,用于锁定所有插件的 commit hash,确保在不同设备上或重装时能恢复到完全相同的插件版本,保证了配置的稳定性。
lua/core
核心配置
core/init.lua
核心模块的入口
作为 core
模块的入口,按顺序加载所有核心配置文件:
1require("core.keymaps")
2require("core.options")
3require("core.autocmds")
4require("core.functions")
core/keymaps.lua
定义全局快捷键
定义全局的快捷键和一些插件的快捷键:
1---------------------
2-- Basic name norm --
3---------------------
4
5--[[
6----------------------keymap---------------------------
7 <C-z> which means Ctrl-z, <C-p> for Ctrl-p, and so on
8 <CR> which means <Enter>
9 <S-m> which means Shift-m
10 <A-Left> which means Alt-Left arrow key
11 <BS> which means Backspace key
12------------------------mode---------------------------
13 'n': normal mode
14 'x': visual mode
15the difference between 'x', 'v' and 's' see: https://vi.stackexchange.com/questions/38859/what-does-mode-x-mean-in-neovim
16--]]
17
18---------------------------
19-- Define common options --
20---------------------------
21
22local opts = {
23 noremap = true, -- non-recursive
24 silent = true, -- do not show message
25}
26
27-- Shorten function name
28local keymap = vim.api.nvim_set_keymap
29
30--Remap space as leader key
31vim.g.mapleader = " "
32
33----------------------
34-- Built-in mapping --
35----------------------
36
37-- Unmappings <C-z> and set to no actions (<nop>) which used to disable these shortcut keys
38keymap("n", "<C-z>", "<nop>", opts)
39
40-- Press <Enter> to clear search highlights results
41keymap("n", "<CR>", "<cmd>noh<CR>", opts)
42
43-- Press <Shift-m> to open the help documentation for the word at the cursor
44keymap("n", "<S-m>", ':execute "help " . expand("<cword>")<cr>', opts)
45
46-- The 'Y' key is remapped to copy to the end of the line, and the 'E' key is mapped to jump to the end of the previous word
47keymap("n", "Y", "y$", opts)
48keymap("n", "E", "ge", opts)
49keymap("v", "Y", "y$", opts)
50keymap("v", "E", "ge", opts) -- causes errors with luasnip autocmp
51
52-- <S-h> and <S-l> are used to jump to the beginning and end of a row respectively
53keymap("v", "<S-h>", "g^", opts)
54keymap("v", "<S-l>", "g$", opts)
55keymap("n", "<S-h>", "g^", opts)
56keymap("n", "<S-l>", "g$", opts)
57
58-- Use <C-h>, <C-j>, <C-k>, and <C-l> to navigate quickly between windows
59keymap("n", "<C-h>", "<C-w>h", opts)
60keymap("n", "<C-j>", "<C-w>j", opts)
61keymap("n", "<C-k>", "<C-w>k", opts)
62keymap("n", "<C-l>", "<C-w>l", opts)
63
64-- Resize windows width and height with arrows
65-- delta: 2 lines
66keymap("n", "<C-Up>", ":resize -2<CR>", opts)
67keymap("n", "<C-Down>", ":resize +2<CR>", opts)
68keymap("n", "<C-Left>", ":vertical resize -2<CR>", opts)
69keymap("n", "<C-Right>", ":vertical resize +2<CR>", opts)
70
71-- Navigate between buffers through <TAB> and <S-TAB>
72keymap("n", "<TAB>", ":bnext<CR>", opts)
73keymap("n", "<S-TAB>", ":bprevious<CR>", opts)
74
75-- Can continuously use <Tab> or <S-Tab> to change the indentation in selection mode
76keymap("v", ">", ">gv", opts)
77keymap("v", "<", "<gv", opts)
78
79--------------------
80-- Telescope.nvim --
81--------------------
82
83-- Start the find_files function in the Telescope plugin to search for project files
84vim.keymap.set("n", "<C-p>", "<cmd>Telescope find_files<CR>", { remap = true })
85
86------------------
87-- Comment.nvim --
88------------------
89
90-- Toggle comments <Ctrl-/> line comments used to switch between the current line and the selected area
91keymap('n', '<C-_>', '<Plug>(comment_toggle_linewise_current)', opts)
92keymap('x', '<C-_>', '<Plug>(comment_toggle_linewise_visual)', opts)
93
94-----------------
95-- Copilot.vim --
96-----------------
97
98-- Change the shortcut key for accepting Copilot suggestions
99vim.keymap.set('i', '<C-R>', 'copilot#Accept("\\<CR>")', {
100 expr = true,
101 replace_keycodes = false
102})
103vim.g.copilot_no_tab_map = true
core/options.lua
全局选项配置
定义 Neovim 的全局选项配置:
1local options = {
2
3 -- GENERAL
4 timeoutlen = 500, -- time to wait for a mapped sequence to complete (in milliseconds), keyboard shortcut waiting time
5 updatetime = 300, -- faster completion (4000ms default), update the inspection interval time
6 swapfile = false, -- creates a swap file
7 undofile = true, -- enable persistent undo
8 writebackup = false, -- if a file is being edited by another program, it is not allowed to be edited
9 backup = false, -- backup file creation
10 confirm = true, -- a confirmation pops up when there is no save or the file is read-only
11
12 -- APPEARANCE
13 fileencoding = "UTF-8", -- the encoding written to a file
14 encoding = "UTF-8", -- UTF-8 encoding is used when processing text
15 guifont = "monospace:h17", -- the font used in graphical neovim applications
16 background = "dark", -- colorschemes that can be light or dark will be made dark
17 termguicolors = true, -- set term gui colors (most terminals support this)
18 conceallevel = 0, -- so that `` is visible in markdown files
19 number = true, -- show numbered lines
20 relativenumber = true, -- set relative numbered lines
21 numberwidth = 2, -- set number column width to 2 {default 4}
22 signcolumn = "yes", -- always show the sign column, otherwise it would shift the text each time
23 cursorline = true, -- highlight the current line
24 wrap = true, -- display lines as one long line, enable line breaks
25 showbreak = "↪ ", -- set indent of wrapped lines
26 cmdheight = 1, -- space in the neovim command line for displaying messages, command line height
27 pumheight = 10, -- pop up menu height, the height of the completed menu
28 wildmenu = true, -- display the completion menu
29 splitbelow = true, -- force all horizontal splits to go below current window
30 splitright = true, -- force all vertical splits to go to the right of current window
31 scrolloff = 999, -- minimal number of screen lines to keep above and below the cursor, achieve an effect similar to that of a Typora typewriter
32
33 -- INDENT
34 tabstop = 4, -- show 4 spaces for a tab
35 shiftwidth = 4, -- the number of spaces inserted for each indentation
36 softtabstop = 4, -- insert 4 spaces for a tab
37 expandtab = true, -- convert tabs to spaces
38 breakindent = true, -- tab wrapped lines
39 linebreak = true, -- companion to wrap, don't split words
40 backspace = "indent,eol,start", -- allow backspace on indent, end of line or insert mode start position
41 smarttab = true, -- automatically adjust the indentation length of the new line based on the indentation of the current line
42 shiftround = true, -- align to multiples of shiftwidth when moving with >> and <<
43 autoindent = true, -- indentation of the new line is aligned to the current line
44 smartindent = true, -- enable universal intelligent indentation
45
46 -- EDIT
47 spell = false, -- turns on spellchecker
48 clipboard = "unnamedplus", -- allows neovim to access the system clipboard
49 mouse = "a", -- allow the mouse to be used in neovim
50 ignorecase = true, -- ignore case in search patterns
51 smartcase = true, -- when searching for capital letters, it automatically distinguishes between upper and lower case
52 hlsearch = true, -- search highlighting
53 incsearch = true, -- when entering the search mode, each character input automatically jumps to the first matching result
54 showmatch = true, -- highlight the matching parentheses
55 virtualedit = "block", -- vitualblock mode doesn't get stuck at the end of line
56 inccommand = "split", -- shows all inline replacements in split
57 autoread = true, -- external file modifications are automatically loaded
58 whichwrap = "<,>,[,]", -- when the cursor is moved to the beginning or end of a line, it can be moved across lines
59 list = false, -- do not display invisible characters
60 listchars = "space:·,tab:>-", -- display methods of spaces and tabs
61}
62
63-- turns on all values in options table above
64for k, v in pairs(options) do
65 vim.opt[k] = v
66end
core/autocmds.lua
自动命令配置
设置自动命令,用于在特定事件发生时执行操作:
1local api = vim.api
2
3-- close help, man, qf, lspinfo with 'q'
4api.nvim_create_autocmd(
5 "FileType",
6 {
7 pattern = { "man", "help", "qf", "lspinfo" }, -- "startuptime",
8 command = "nnoremap <buffer><silent> q :close<CR>",
9 }
10)
11
12-- Terminal mappings
13--[[
14 The set_terminal_keymaps function is defined. In terminal mode, the shortcut key <esc> is mapped to <C-c>, which can be used to quickly exit terminal mode.
15 Navigate between different Windows with <C-h>, <C-j>, <C-k>, and <C-l>. When the terminal is opened (TermOpen), set_terminal_keymaps() is automatically called.
16 Press <C-w> to exit from Terminal mode to Normal mode.
17--]]
18function _G.set_terminal_keymaps()
19 local opts = { buffer = 0 }
20 vim.keymap.set('t', '<esc>', [[<C-c>]], opts)
21 vim.keymap.set('t', '<C-h>', [[<Cmd>wincmd h<CR>]], opts)
22 vim.keymap.set('t', '<C-j>', [[<Cmd>wincmd j<CR>]], opts)
23 vim.keymap.set('t', '<C-k>', [[<Cmd>wincmd k<CR>]], opts)
24 vim.keymap.set('t', '<C-l>', [[<Cmd>wincmd l<CR>]], opts)
25 vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
26end
27
28vim.api.nvim_create_autocmd({ "TermOpen" }, {
29 pattern = { "term://*" }, -- use term://*toggleterm#* for only ToggleTerm
30 command = "lua set_terminal_keymaps()",
31})
core/functions.lus
自定义函数
存放可被复用的自定义 Lua 函数:
1-- Used to find the word under the cursor
2function SearchWordUnderCursor()
3 local word = vim.fn.expand('<cword>') -- get the word under the cursor
4 require('telescope.builtin').live_grep({ default_text = word }) -- invoke the live_grep function of the Telescope plugin
5end
lua/bootstrap.lua
插件管理器
负责 lazy.nvim
插件管理器的安装和配置,主要功能:
- 自动检查
lazy.nvim
是否安装,如果未安装则从 Github 下载 - 调用
require("lazy").setup()
,并从lua/plugins
和lua/plugins/lsp
目录导入所有插件配置 - 自定义
lazy.nvim
的界面图标
文件配置:
1-- Bootstrap lazy.nvim
2local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
3-- Check if lazy.nvim is installed (check if the path exists)
4if not (vim.uv or vim.loop).fs_stat(lazypath) then
5 -- Define the remote repository address of lazy.nvim
6 local lazyrepo = "https://github.com/folke/lazy.nvim.git"
7 -- Clone the path from the repository to the local area
8 local out = vim.fn.system({
9 "git",
10 "clone",
11 "--filter=blob:none", -- Optimize cloning speed and only download necessary files
12 "--branch=stable", -- Use the stable branch
13 lazyrepo,
14 lazypath
15 })
16 -- If the clone fails (git returns a non-zero error code)
17 if vim.v.shell_error ~= 0 then
18 -- Display error messages and debug output
19 vim.api.nvim_echo({
20 { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
21 { out, "WarningMsg" },
22 { "\nPress any key to exit..." },
23 }, true, {})
24 -- Wait for the user to press the button and exit
25 vim.fn.getchar()
26 os.exit(1)
27 end
28end
29
30-- Add the path of the lazy.nvim plugin manager to the runtime path (rtp) of Neovim
31vim.opt.rtp:prepend(lazypath)
32
33-- Initialize the lazy.nvim plugin manager
34require("lazy").setup({
35 -- Plugin configuration module
36 { import = "plugins" }, -- main plugin directory (lua/plugins directory)
37 { import = "plugins.lsp" } -- LSP plugin directory (lua/plugins/lsp directory)
38}, {
39 -- Configuration options of the plugin manager
40 install = {
41 colorscheme = { "gruvbox" }, -- Automatically install the gruvbox color theme during installation
42 },
43 checker = {
44 enabled = true, -- Enables plugins version checking (check for updates)
45 notify = false, -- Does not pop up notifications when an update is detected
46 },
47 change_detection = {
48 notify = false, -- No notification pops up when the plugin file is changed
49 },
50 ui = {
51 icons = {
52 -- Custom UI icons
53 cmd = "⌘", -- command
54 config = "🛠", -- configuration
55 event = "📅", -- event
56 ft = "📂", -- file type
57 init = "⚙", -- initialization shell
58 keys = "🗝", -- keys binding
59 plugin = "🔌", -- plugins
60 runtime = "💻", -- running
61 require = "🌙", -- require invocation
62 source = "📄", -- source file
63 start = "🚀", -- start plugins
64 task = "📌", -- task
65 lazy = "💤 ", -- lazy plugins
66 },
67 },
68})
lua/plugins
插件配置
plugins/lsp
代码分析与补全
lsp/
目录用于存放所有与 LSP(Language Server Protocol)、代码补全和语法分析相关的插件。
lspconfig.lua
主配置文件
用于连接 mason
安装的 LSP 服务器到 Neovim 的 LSP 客户端。
1return {
2 "neovim/nvim-lspconfig",
3 event = { "BufReadPre", "BufNewFile" }, -- Load when opening/creating a new file
4 dependencies = {
5 { "hrsh7th/cmp-nvim-lsp" }, -- Provide LSP completion capability for auto-completion plugins (such as nvim-cmp)
6 { "antosha417/nvim-lsp-file-operations", config = true }, -- Automatically handle file operations (such as synchronizing file structures when renaming)
7 },
8 config = function()
9 -- import lspconfig plugin
10 local lspconfig = require("lspconfig")
11
12 -- import cmp-nvim-lsp plugin
13 local cmp_nvim_lsp = require("cmp_nvim_lsp")
14
15 -- used to enable autocompletion (assign to every lsp server config)
16 local default = cmp_nvim_lsp.default_capabilities()
17
18 -- change the diagnostic symbols in the sign column (gutter)
19 vim.diagnostic.config({
20 signs = {
21 text = {
22 [vim.diagnostic.severity.ERROR] = "", -- error
23 [vim.diagnostic.severity.WARN] = "", -- warning
24 [vim.diagnostic.severity.INFO] = "", -- information
25 [vim.diagnostic.severity.HINT] = "", -- hint
26 }
27 },
28 update_in_insert = true, -- real-time update diagnosis in insertion mode
29 underline = true, -- display error line
30 })
31
32 -- configure python server
33 lspconfig["pyright"].setup({
34 capabilities = default, -- enable default capabilities (including completion)
35 filetypes = { "python" }, -- only useful to .py file type
36 })
37
38 -- configure cpp server
39 lspconfig["clangd"].setup({
40 capabilities = default, -- enable default capabilities (including completion)
41 filetypes = { "h", "c", "cpp", "cc", "objc", "objcpp"}, -- supported file type
42 single_file_support = true, -- enable single-file mode (applicable to large-scale projects)
43 })
44 end,
45}
mason.lua
LSP 管理
核心的 LSP 管理工具,用于安装和管理 LSP 服务器、代码格式化工具(Formatter)和代码检查工具(Linter)。
1return {
2 "williamboman/mason.nvim",
3 ft ={ "py", "cpp", "c", "tex", "bib", "h", "cc", "objc", "objcpp" }, -- Specify the supported file types
4 dependencies = {
5 "williamboman/mason-lspconfig.nvim", -- Used for managing the installation and configuration of LSP servers
6 "WhoIsSethDaniel/mason-tool-installer.nvim", -- Used for managing the installation of development tools (such as formatters, linters)
7 },
8
9 config = function()
10 -- import mason
11 local mason = require("mason")
12
13 -- import mason-lspconfig
14 local mason_lspconfig = require("mason-lspconfig")
15
16 -- import mason-tool-installer
17 local mason_tool_installer = require("mason-tool-installer")
18
19 -- enable mason and configure icons
20 mason.setup({
21 ui = {
22 icons = {
23 package_installed = "✓", -- installed packages
24 package_pending = "➜", -- the package being installed
25 package_uninstalled = "✗", -- uninstalled package
26 },
27 },
28 })
29
30 mason_lspconfig.setup({
31 -- list of servers for mason to install
32 ensure_installed = {
33 "pyright", -- python LSP
34 "clangd", -- cpp LSP
35 },
36 -- auto-install configured servers (with lspconfig)
37 automatic_installation = true, -- not the same as ensure_installed
38 })
39
40 mason_tool_installer.setup({
41 ensure_installed = {
42 "clang-format", -- cpp formatter
43 "black", -- python formatter
44 "pylint", -- python linter
45 "flake8", -- Python static analysis
46 "bandit", -- Python security check
47 "cpplint", -- cpp linter
48 },
49 })
50 end,
51}
nvim-cmp.lua
自动补全
核心的自动补全引擎插件:
1return {
2 "hrsh7th/nvim-cmp",
3 event = { "InsertEnter", "CmdlineEnter" }, -- Load the plugin when entering in insert mode or command-line mode
4 dependencies = {
5 "hrsh7th/cmp-buffer", -- source for text in buffer
6 "hrsh7th/cmp-path", -- source for file system paths
7 "L3MON4D3/LuaSnip", -- snippet engine
8 "saadparwaiz1/cmp_luasnip", -- for autocompletion
9 -- "onsails/lspkind.nvim", -- vs-code like pictograms
10 "hrsh7th/cmp-cmdline", -- command-line mode completion
11 "petertriho/cmp-git", -- git command completion
12 "f3fora/cmp-spell", -- spelling check completion
13 "micangl/cmp-vimtex", -- LaTeX completion (VimTeX Plugin)
14 },
15 config = function()
16
17 local cmp = require("cmp")
18
19 local luasnip = require("luasnip")
20
21------------------------
22-- Icon configuration --
23------------------------
24
25 local kind_icons = {
26 article = "", -- article type (LaTeX)
27 book = "", -- book type (LaTeX)
28 incollection = "", -- collection type (LaTeX)
29 Function = "", -- function
30 Constructor = "", -- constructor
31 Text = "", -- plain text
32 Method = "", -- method
33 Field = "", -- field/attribute
34 Variable = "", -- variable
35 Class = "", -- class
36 Interface = "", -- interface
37 Module = "", -- module
38 Property = "", -- property
39 Unit = "", -- unit
40 Value = "", -- value
41 Enum = "", -- enumeration
42 Keyword = "", -- keyword
43 Snippet = "", -- code snippet
44 -- Color = "", -- color
45 Color = "", -- color
46 File = "", -- file
47 Reference = "", -- reference
48 Folder = "", -- folder
49 EnumMember = "", --enumeration member
50 spell = "",
51 -- EnumMember = "",
52 Constant = "", -- constant
53 Struct = "",
54 -- Struct = "",
55 Event = "", -- event
56 Operator = "", -- operator
57 TypeParameter = "", -- type parameter
58 }
59 -- find more here: https://www.nerdfonts.com/cheat-sheet
60
61----------------------
62-- Completion logic --
63----------------------
64
65 cmp.setup({
66 completion = {
67 completeopt = "menu,noselect", -- Complete menu behavior (not automatically selected)
68 keyword_length = 1, -- At least one character is entered to trigger completion
69 },
70 snippet = { -- configure how nvim-cmp interacts with snippet engine
71 expand = function(args)
72 luasnip.lsp_expand(args.body) -- Extend the snippet using LuaSnip
73 end,
74 },
75
76-----------------
77-- Key mapping --
78-----------------
79
80 mapping = cmp.mapping.preset.insert({
81 ["<CR>"] = cmp.mapping.confirm({ select = true }), -- Press Enter to confirm completion (no forced selection)
82
83 -- supertab
84 ["<Tab>"] = cmp.mapping(function(fallback)
85 if cmp.visible() then
86 cmp.select_next_item()
87 elseif luasnip.locally_jumpable(1) then
88 luasnip.jump(1)
89 elseif luasnip.expandable() then
90 luasnip.expand()
91 else
92 fallback()
93 end
94 end, { "i", "s" }),
95 ["<S-Tab>"] = cmp.mapping(function()
96 if cmp.visible() then
97 cmp.select_prev_item()
98 elseif luasnip.locally_jumpable(-1) then
99 luasnip.jump(-1)
100 else
101 -- fallback()
102 end
103 end, { "i", "s" }),
104 }),
105
106-----------------------------------
107-- Formatting for autocompletion --
108-----------------------------------
109
110 formatting = {
111 fields = { "kind", "abbr", "menu" }, -- Completed item display fields (type, abbreviation, source)
112 format = function(entry, vim_item)
113 vim_item.kind = string.format("%s", kind_icons[vim_item.kind]) -- Kind icons
114 vim_item.menu = ({
115 vimtex = vim_item.menu,
116 luasnip = "[Snippet]",
117 nvim_lsp = "[LSP]",
118 buffer = "[Buffer]",
119 spell = "[Spell]",
120 cmdline = "[CMD]",
121 path = "[Path]",
122 })[entry.source.name]
123 return vim_item
124 end,
125 },
126
127--------------------------------
128-- Sources for autocompletion --
129--------------------------------
130
131 sources = cmp.config.sources({
132 { name = "nvim_lsp" },
133 { name = "luasnip" }, -- snippets
134 { name = "vimtex" },
135 { name = "buffer", keyword_length = 3 }, -- text within current buffer
136 { name = "spell",
137 keyword_length = 4,
138 option = {
139 keep_all_entries = false,
140 enable_in_context = function()
141 return true -- Always enable spell check
142 end
143 },
144 },
145 { name = "path" },
146 }),
147
148-------------------------
149-- Other configuration --
150-------------------------
151
152 confirm_opts = {
153 behavior = cmp.ConfirmBehavior.Replace, -- Replace the current cursor content
154 select = false,
155 },
156 view = {
157 entries = 'custom', -- Customize the display method of completion items
158 },
159 window = {
160 completion = cmp.config.window.bordered(), -- Complete the window with a border
161 documentation = cmp.config.window.bordered(), -- Documentation window with a border
162 },
163 performance = {
164 trigger_debounce_time = 500,
165 throttle = 550,
166 fetching_timeout = 80,
167 },
168 })
169
170 -- `/` cmdline setup.
171 cmp.setup.cmdline('/', {
172 mapping = cmp.mapping.preset.cmdline(),
173 sources = {
174 {name = 'buffer'}
175 }
176 })
177
178 -- `:` cmdline setup.
179 cmp.setup.cmdline(':', {
180 mapping = cmp.mapping.preset.cmdline(),
181 sources = {
182 {name = 'path'},
183 {name = 'cmdline'}
184 }
185 })
186
187 end,
188}
vimtex-cmp.lua
$\LaTeX$ 支持
通过显示额外信息、符号和 BibTeX 解析,提升 LaTeX 编辑效率:
1return {
2 "micangl/cmp-vimtex",
3 ft = { "tex", "bib", "cls" }, -- Only loaded when .tex .bib .cls files are opened
4 config = function()
5 require('cmp_vimtex').setup({
6 additional_information = {
7 info_in_menu = true,
8 info_in_window = true,
9 info_max_length = 60,
10 match_against_info = true,
11 symbols_in_menu = true,
12 },
13 bibtex_parser = {
14 enabled = true,
15 },
16 })
17 end,
18}
plugins/autopairs.lua
自动补全括号
自动补全括号、引号等成对符号:
1return {
2 "windwp/nvim-autopairs",
3 event = { "InsertEnter" },
4 dependencies = {
5 "hrsh7th/nvim-cmp",
6 },
7 config = function()
8 -- import nvim-autopairs
9 local autopairs = require("nvim-autopairs")
10
11 -- configure autopairs
12 autopairs.setup({
13 check_ts = true, -- enable treesitter
14 disable_filetype = { "TelescopePrompt", "spectre_panel" },
15 disable_in_macro = true,
16 disable_in_replace_mode = true,
17 enable_moveright = true,
18 ignored_next_char = "",
19 enable_check_bracket_line = true, --- check bracket in same line
20 })
21
22 local Rule = require 'nvim-autopairs.rule'
23
24 local cond = require 'nvim-autopairs.conds'
25
26 autopairs.add_rules({
27 Rule("`", "'", "tex"),
28 Rule("$", "$", "tex"),
29 Rule(' ', ' ')
30 :with_pair(function(opts)
31 local pair = opts.line:sub(opts.col, opts.col + 1)
32 return vim.tbl_contains({ '$$', '()', '{}', '[]', '<>' }, pair)
33 end)
34 :with_move(cond.none())
35 :with_cr(cond.none())
36 :with_del(function(opts)
37 local col = vim.api.nvim_win_get_cursor(0)[2]
38 local context = opts.line:sub(col - 1, col + 2)
39 return vim.tbl_contains({ '$ $', '( )', '{ }', '[ ]', '< >' }, context)
40 end),
41 Rule("$ ", " ", "tex")
42 :with_pair(cond.not_after_regex(" "))
43 :with_del(cond.none()),
44 Rule("[ ", " ", "tex")
45 :with_pair(cond.not_after_regex(" "))
46 :with_del(cond.none()),
47 Rule("{ ", " ", "tex")
48 :with_pair(cond.not_after_regex(" "))
49 :with_del(cond.none()),
50 Rule("( ", " ", "tex")
51 :with_pair(cond.not_after_regex(" "))
52 :with_del(cond.none()),
53 Rule("< ", " ", "tex")
54 :with_pair(cond.not_after_regex(" "))
55 :with_del(cond.none()),
56 })
57
58 autopairs.get_rule('$'):with_move(function(opts)
59 return opts.char == opts.next_char:sub(1, 1)
60 end)
61
62 -- import nvim-cmp plugin (completions plugin)
63 local cmp = require("cmp")
64
65 -- import nvim-autopairs completion functionality
66 local cmp_autopairs = require("nvim-autopairs.completion.cmp")
67
68 -- make autopairs and completion work together
69 cmp.event:on(
70 'confirm_done',
71 cmp_autopairs.on_confirm_done({
72 filetypes = {
73 tex = false -- Disable for tex
74 }
75 })
76 )
77 end,
78}
bufferline.lua
缓冲区标签栏
在顶部显示一个类似 VSCode 的标签栏,用于展示和切换打开的缓冲区:
1return {
2 "akinsho/bufferline.nvim",
3 dependencies = { "nvim-tree/nvim-web-devicons" },
4 version = "*",
5 config = function()
6 local bufferline = require('bufferline')
7 bufferline.setup({
8 options = {
9 mode = "buffers",
10 separator_style = "slant",
11 close_command = "bdelete! %d", -- Use the Lua API to close the buffer
12 diagnostics = false, -- OR: | "nvim_lsp"
13 diagnostics_update_in_insert = false,
14 show_tab_indicators = false,
15 show_close_icon = false,
16 -- numbers = "ordinal", -- Display buffer numbers as ordinal numbers
17 sort_by = 'insert_after_current', -- OR: 'insert_at_end' | 'tabs' | 'extension' | 'relative_directory' | 'directory' | 'id' |
18 offsets = {
19 {
20 filetype = "NvimTree",
21 -- text = "Explorer",
22 text = function()
23 return vim.fn.getcwd()
24 end,
25 highlight = "Directory",
26 separator = "", -- use a "true" to enable the default, or set your own character
27 -- padding = 1
28 }
29 },
30 hover = {
31 enabled = true,
32 delay = 30,
33 reveal = { 'close' }
34 },
35 vim.api.nvim_create_autocmd("User", {
36 pattern = "AlphaReady",
37 desc = "disable tabline for alpha",
38 callback = function()
39 vim.opt.showtabline = 0
40 end,
41 }),
42 vim.api.nvim_create_autocmd("BufUnload", {
43 buffer = 0,
44 desc = "enable tabline after alpha",
45 callback = function()
46 vim.opt.showtabline = 2
47 end,
48 })
49 },
50 })
51 end,
52}
colorscheme.lua
颜色主题
设置 gruvbox
为主颜色主题,并覆盖了一些高亮组以优化显示效果:
1-- GRUVBOX
2return {
3 "ellisonleao/gruvbox.nvim",
4 priority = 1000, -- make sure to load this before all the other start plugins
5 config = function()
6 require("gruvbox").setup({
7 overrides = {
8 SignColumn = { bg = "#282828" },
9 NvimTreeCutHL = { fg = "#fb4934", bg = "#282828" },
10 NvimTreeCopiedHL = { fg = "#b8bb26", bg = "#282828" },
11 DiagnosticSignError = { fg = "#fb4934", bg = "#282828" },
12 DiagnosticSignWarn = { fg = "#fabd2f", bg = "#282828" },
13 DiagnosticSignHint = { fg = "#8ec07c", bg = "#282828" },
14 DiagnosticSignInfo = { fg = "#d3869b", bg = "#282828" },
15 }
16 })
17 vim.cmd("colorscheme gruvbox")
18 end,
19}
comment.lua
注释插件
强大的注释插件,通过 <C-/>
智能切换注释:
1return {
2 "numToStr/Comment.nvim",
3 event = { "BufReadPre", "BufNewFile" },
4 dependencies = {
5 "JoosepAlviste/nvim-ts-context-commentstring",
6 },
7 config = function()
8 -- import comment plugin safely
9 local comment = require("Comment")
10
11 local ts_context_commentstring = require("ts_context_commentstring.integrations.comment_nvim")
12
13 -- enable comment
14 comment.setup({
15 --Add a space b/w comment and the line
16 padding = true,
17 ---Whether the cursor should stay at its position
18 sticky = true,
19 ---Lines to be ignored while (un)comment
20 ignore = nil,
21 ---Function to call before (un)comment
22 pre_hook = ts_context_commentstring.create_pre_hook(), -- for commenting tsx and jsx files
23 mappings = {
24 ---Operator-pending mapping; `gcc` `gbc` `gc[count]{motion}` `gb[count]{motion}`
25 basic = false,
26 ---Extra mapping; `gco`, `gcO`, `gcA`
27 extra = false,
28 },
29 })
30 end,
31}
copilot.lua
集成 AI
集成 GitHub Copilot,提供 AI 代码建议:
1return {
2 "github/copilot.vim",
3 init = function()
4 vim.g.copilot_enabled = false -- Set Copilot to be disabled by default
5 end,
6}
gitsigns.lua
Git 状态集成
在行号列显示 Git 状态(新增、修改、删除):
1return {
2 "lewis6991/gitsigns.nvim",
3 event = { "BufReadPre", "BufNewFile" },
4 config = function()
5 require("gitsigns").setup({
6 signs = {
7 add = { text = "▎" },
8 change = { text = "▎" },
9 delete = { text = "▎" },
10 topdelete = { text = "▎" },
11 changedelete = { text = "▎" },
12 untracked = { text = "┆" },
13 },
14 signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
15 numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
16 linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
17 word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff`
18 watch_gitdir = {
19 interval = 1000,
20 follow_files = true,
21 },
22 attach_to_untracked = true,
23 current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame`
24 current_line_blame_opts = {
25 virt_text = true,
26 virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align'
27 delay = 1000,
28 ignore_whitespace = false,
29 },
30 sign_priority = 6,
31 update_debounce = 100,
32 status_formatter = nil, -- Use default
33 max_file_length = 40000,
34 preview_config = {
35 -- Options passed to nvim_open_win
36 border = "single",
37 style = "minimal",
38 relative = "cursor",
39 row = 0,
40 col = 1,
41 },
42 })
43 end
44}
im-select.lua
自动切换输入法
自动切换中英输入法:
1return {
2 "keaising/im-select.nvim",
3 config = function()
4 require("im_select").setup({})
5 end,
6}
indent-blankline.lua
显示缩进参考线
显示缩进参考线,使代码结构更清晰:
1return {
2 "lukas-reineke/indent-blankline.nvim",
3 version = "*",
4 event = { "BufReadPre", "BufNewFile" },
5 config = function()
6 require("ibl").setup({
7 indent = {
8 char = "│",
9 tab_char = "│",
10 highlight = "IblIndent",
11 smart_indent_cap = true,
12 priority = 1,
13 repeat_linebreak = true,
14 },
15 scope = {
16 enabled = true,
17 char = nil,
18 show_start = false,
19 show_end = false,
20 show_exact_scope = false,
21 injected_languages = true,
22 highlight = "IblScope",
23 priority = 1024,
24 include = {
25 node_type = { ["*"] = { "*" } }, -- makes lines show on all blocks
26 },
27 },
28 exclude = {
29 filetypes = {
30 "help",
31 "alpha",
32 "dashboard",
33 "NvimTree",
34 "Trouble",
35 "trouble",
36 "lazy",
37 "mason",
38 "notify",
39 "toggleterm",
40 "lspinfo",
41 "checkhealth",
42 "man",
43 "gitcommit",
44 "TelescopePrompt",
45 "TelescopeResults",
46 "",
47 },
48 buftypes = {
49 "terminal",
50 "nofile",
51 "quickfix",
52 "prompt",
53 },
54 },
55 })
56 end
local-highlight.lua
自动高亮
自动高亮光标下的所有相同单词:
1return {
2 'tzachar/local-highlight.nvim',
3 config = function()
4 require('local-highlight').setup({
5 -- file_types = {'python', 'cpp'}, -- If this is given only attach to this
6 -- OR attach to every filetype except:
7 disable_file_types = {},
8 hlgroup = 'Pmenu', -- change highlight color to value given in table found by running :highlight
9 cw_hlgroup = nil,
10 insert_mode = false,
11 animate = {
12 enabled = false,
13 },
14 })
15 end
16}
lualine.lua
丰富状态栏
配置一个功能丰富的状态栏,显示模式、Git 分支、诊断信息、文件名等:
1return {
2 "nvim-lualine/lualine.nvim",
3 dependencies = { "nvim-tree/nvim-web-devicons" },
4 config = function()
5 require('lualine').setup({
6 options = {
7 icons_enabled = true,
8 theme = 'gruvbox',
9 component_separators = { left = '', right = ''},
10 section_separators = { left = '', right = ''},
11 disabled_filetypes = {
12 statusline = {},
13 winbar = {},
14 },
15 ignore_focus = {},
16 always_divide_middle = true,
17 globalstatus = false,
18 refresh = {
19 statusline = 1000,
20 tabline = 1000,
21 winbar = 1000,
22 }
23 },
24 sections = {
25 lualine_a = {'mode'},
26 lualine_b = {'branch', 'diff', 'diagnostics'},
27 lualine_c = {'filename'},
28 lualine_x = {'encoding', 'fileformat', 'filetype'},
29 lualine_y = {'progress'},
30 lualine_z = {'location'}
31 },
32 inactive_sections = {
33 lualine_a = {},
34 lualine_b = {},
35 lualine_c = {'filename'},
36 lualine_x = {'location'},
37 lualine_y = {},
38 lualine_z = {}
39 },
40 tabline = {},
41 winbar = {},
42 inactive_winbar = {},
43 extensions = {}
44 })
45 end,
46}
luasnip.lua
代码段引擎
一个支持自定义代码段和引入网络代码段的引擎:
1return {
2 "L3MON4D3/LuaSnip",
3 -- follow latest release
4 version = "v2.*", -- Replace <CurrentMajor> by the latest released major (first number of latest release)
5 config = function()
6 local ls = require("luasnip")
7
8 ls.config.set_config({ -- Setting LuaSnip config
9 enable_autosnippets = true, -- Enable autotriggered snippets
10 store_selection_keys = "<Tab>", -- Use Tab (or some other key if you prefer) to trigger visual selection
11 update_events = "TextChanged, TextChangedI", -- Update text when type
12 })
13
14 local nvim_config_path = vim.fn.stdpath("config") -- get neovim configuration path
15 -- Lazy-load snippets, i.e. only load when required, e.g. for a given filetype
16 require("luasnip.loaders.from_lua").lazy_load({
17 paths = nvim_config_path .. "/snippets"
18 })
19
20 -- vim.keymap.set({"i"}, "<C-E>", function() ls.expand() end, {silent = true})
21 vim.keymap.set({"i", "s"}, "<Tab>", function() ls.jump( 1) end, {silent = true})
22 vim.keymap.set({"i", "s"}, "<S-Tab>", function() ls.jump(-1) end, {silent = true})
23
24 -- vim.keymap.set({"i", "s"}, "<C-W>", function()
25 -- if ls.choice_active() then
26 -- ls.change_choice(1)
27 -- end
28 -- end, {silent = true})
29 end,
30}
nvim-tree.lua
文件浏览侧边栏
一个高性能的文件浏览器侧边栏,替代了默认的 netrw
:
1return {
2 "nvim-tree/nvim-tree.lua",
3 cmd = {"NvimTreeToggle", "NvimTreeFocus"},
4 dependencies = { "nvim-tree/nvim-web-devicons" },
5 config = function()
6 local nvimtree = require("nvim-tree")
7
8 -- recommended settings from nvim-tree documentation
9 vim.g.loaded_netrw = 1
10 vim.g.loaded_netrwPlugin = 1
11
12 local function on_attach(bufnr)
13 local api = require('nvim-tree.api')
14
15 local function opts(desc)
16 return { desc = 'nvim-tree: ' .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true }
17 end
18
19 -- custom mappings
20 local keymap = vim.keymap -- for conciseness
21 keymap.set('n', '<CR>', api.node.open.tab, opts('Open'))
22 keymap.set('n', '<S-M>', api.node.show_info_popup, opts('Info'))
23 keymap.set('n', 'h', api.node.navigate.parent_close, opts('Close Directory'))
24 keymap.set('n', 'l', api.node.open.edit, opts('Open'))
25 keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
26 keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
27 keymap.set('n', '-', api.tree.change_root_to_parent, opts('Up'))
28 keymap.set('n', 'a', api.fs.create, opts('Create'))
29 keymap.set('n', 'y', api.fs.copy.node, opts('Copy'))
30 keymap.set('n', 'd', api.fs.remove, opts('Delete'))
31 keymap.set('n', 'D', api.fs.trash, opts('Trash'))
32 keymap.set('n', '?', api.tree.toggle_help, opts('Help'))
33 keymap.set('n', 'H', api.tree.toggle_hidden_filter, opts('Toggle Dotfiles'))
34 keymap.set('n', 'p', api.fs.paste, opts('Paste'))
35 keymap.set('n', 'O', api.node.navigate.parent, opts('Parent Directory'))
36 keymap.set('n', 'q', api.tree.close, opts('Close'))
37 keymap.set('n', 'r', api.fs.rename, opts('Rename'))
38 keymap.set('n', 'R', api.tree.reload, opts('Refresh'))
39 keymap.set('n', 'o', api.node.run.system, opts('System Open'))
40 keymap.set('n', 's', api.tree.search_node, opts('Search'))
41 keymap.set('n', 'v', api.node.open.vertical, opts('Vertical Split'))
42 keymap.set('n', 'x', api.fs.cut, opts('Cut'))
43 keymap.set('n', '<2-LeftMouse>', api.node.open.edit, opts('Open'))
44 end
45
46 -- configure nvim-tree
47 nvimtree.setup({
48 on_attach = on_attach,
49 actions = {
50 open_file = {
51 quit_on_open = true,
52 eject = true,
53 resize_window = true,
54 window_picker = {
55 enable = true,
56 picker = "default",
57 chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
58 exclude = {
59 filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" },
60 buftype = { "nofile", "terminal", "help" },
61 },
62 },
63 },
64 change_dir = {
65 enable = false,
66 global = false,
67 restrict_above_cwd = false,
68 },
69 use_system_clipboard = true,
70 expand_all = {
71 max_folder_discovery = 300,
72 exclude = {},
73 },
74 file_popup = {
75 open_win_config = {
76 col = 1,
77 row = 1,
78 relative = "cursor",
79 border = "shadow",
80 style = "minimal",
81 },
82 },
83 remove_file = {
84 close_window = true,
85 },
86 },
87 git = {
88 enable = true,
89 show_on_dirs = true,
90 -- show_on_open_dirs = true,
91 disable_for_dirs = {},
92 timeout = 500,
93 cygwin_support = false,
94 },
95 filters = {
96 git_ignored = false,
97 dotfiles = false,
98 git_clean = false,
99 no_buffer = false,
100 no_bookmark = false,
101 -- custom = { ".git" },
102 -- custom = { ".DS_Store" },
103 exclude = {},
104 },
105 update_focused_file = {
106 enable = true,
107 update_root = true,
108 ignore_list = {},
109 update_cwd = true,
110 },
111 renderer = {
112 add_trailing = false,
113 group_empty = false,
114 full_name = false,
115 root_folder_label = ":t",
116 indent_width = 2,
117 special_files = {},
118 symlink_destination = true,
119 highlight_git = false,
120 highlight_diagnostics = false,
121 highlight_opened_files = "none",
122 highlight_modified = "none",
123 highlight_bookmarks = "none",
124 highlight_clipboard = "name",
125 indent_markers = {
126 enable = false,
127 inline_arrows = true,
128 icons = {
129 corner = "└",
130 edge = "│",
131 item = "│",
132 bottom = "─",
133 none = " ",
134 },
135 },
136 icons = {
137 web_devicons = {
138 file = {
139 enable = true,
140 color = true,
141 },
142 folder = {
143 enable = false,
144 color = true,
145 },
146 },
147 git_placement = "before",
148 modified_placement = "after",
149 diagnostics_placement = "signcolumn",
150 bookmarks_placement = "signcolumn",
151 padding = " ",
152 symlink_arrow = " ➛ ",
153 show = {
154 file = true,
155 folder = true,
156 folder_arrow = true,
157 git = true,
158 modified = true,
159 diagnostics = true,
160 bookmarks = false,
161 },
162 glyphs = {
163 default = "",
164 -- toml = "", -- Change this to the desired icon for TOML files
165 symlink = "",
166 bookmark = "",
167 modified = "●",
168 folder = {
169 arrow_closed = "",
170 arrow_open = "",
171 default = "",
172 open = "",
173 empty = "",
174 empty_open = "",
175 symlink = "",
176 symlink_open = "",
177 },
178 git = {
179 unstaged = "➜",
180 staged = "✓",
181 unmerged = "",
182 renamed = "➜",
183 untracked = "★",
184 deleted = "✗",
185 -- deleted = "",
186 ignored = "◌",
187 },
188 },
189 },
190 },
191 diagnostics = {
192 enable = true,
193 show_on_dirs = true,
194 show_on_open_dirs = true,
195 debounce_delay = 50,
196 severity = {
197 min = vim.diagnostic.severity.HINT,
198 max = vim.diagnostic.severity.ERROR,
199 },
200 icons = {
201 hint = "",
202 info = "",
203 warning = "",
204 error = "",
205 },
206 },
207 hijack_cursor = false,
208 auto_reload_on_write = true,
209 disable_netrw = false,
210 hijack_netrw = true,
211 hijack_unnamed_buffer_when_opening = false,
212 root_dirs = {},
213 prefer_startup_root = false,
214 sync_root_with_cwd = false,
215 reload_on_bufenter = false,
216 respect_buf_cwd = false,
217 select_prompts = false,
218 sort = {
219 sorter = "name",
220 folders_first = true,
221 files_first = false,
222 },
223 view = {
224 centralize_selection = false,
225 cursorline = true,
226 debounce_delay = 15,
227 side = "left",
228 preserve_window_proportions = false,
229 number = false,
230 relativenumber = false,
231 signcolumn = "yes",
232 width = 30,
233 float = {
234 enable = false,
235 quit_on_focus_loss = true,
236 open_win_config = {
237 relative = "editor",
238 border = "rounded",
239 width = 30,
240 height = 30,
241 row = 1,
242 col = 1,
243 },
244 },
245 },
246 hijack_directories = {
247 enable = true,
248 auto_open = true,
249 },
250 system_open = {
251 cmd = "",
252 args = {},
253 },
254 modified = {
255 enable = false,
256 show_on_dirs = true,
257 show_on_open_dirs = true,
258 },
259 live_filter = {
260 prefix = "[FILTER]: ",
261 always_show_folders = true,
262 },
263 filesystem_watchers = {
264 enable = true,
265 debounce_delay = 50,
266 ignore_dirs = {},
267 },
268 trash = {
269 cmd = "gio trash",
270 },
271 tab = {
272 sync = {
273 open = false,
274 close = false,
275 ignore = {},
276 },
277 },
278 notify = {
279 threshold = vim.log.levels.ERROR,
280 absolute_path = true,
281 },
282 help = {
283 sort_by = "key",
284 },
285 ui = {
286 confirm = {
287 remove = true,
288 trash = true,
289 default_yes = true,
290 },
291 },
292 experimental = {},
293 log = {
294 enable = false,
295 truncate = false,
296 types = {
297 all = false,
298 config = false,
299 copy_paste = false,
300 dev = false,
301 diagnostics = false,
302 git = false,
303 profile = false,
304 watcher = false,
305 },
306 },
307 })
308 end
309}
nvim-web-devicons.lua
UI 组件
为各种 UI 组件(如 nvim-tree, lualine)提供文件类型图标:
1return {
2 "nvim-tree/nvim-web-devicons",
3 config = function()
4 require("nvim-web-devicons").set_icon({
5 gql = {
6 icon = "",
7 color = "#e535ab",
8 cterm_color = "199",
9 name = "GraphQL",
10 },
11 })
12 end,
13}
rainbow-delimiters.lua
彩虹符号
为配对的符号(比如 ()
,[]
,{}
)的不同层级添加不同的颜色,方便区分:
1return {
2 "hiphish/rainbow-delimiters.nvim",
3}
surround.lua
环绕符号增强
方便地添加、修改和删除环绕符号,例如将 hello
变为 "hello"
:
1return {
2 "kylechui/nvim-surround",
3 event = { "BufReadPre", "BufNewFile" },
4 version = "*", -- Use for stability; omit to use `main` branch for the latest features
5 config = function()
6 require("nvim-surround").setup({
7 keymaps = {
8 insert = false,
9 insert_line = false,
10 normal = false,
11 normal_cur = false,
12 normal_line = false,
13 normal_cur_line = false,
14 visual = "<S-s>", -- Press <S-s> and surround sign, like ( < " ' { [
15 visual_line = false,
16 delete = false,
17 change = false,
18 },
19 aliases = {
20 ["a"] = false,
21 ["b"] = false,
22 ["B"] = false,
23 ["r"] = false,
24 ["q"] = false,
25 ["s"] = false,
26 },
27 })
28 end
29}
telescope.lua
模糊搜索
一个高度可扩展的模糊搜索工具,用于快速查找文件、缓冲区、Git 提交、帮助文档等:
1return {
2 "nvim-telescope/telescope.nvim",
3 branch = "0.1.x",
4 dependencies = {
5 "nvim-lua/plenary.nvim",
6 "debugloop/telescope-undo.nvim",
7 {
8 "nvim-telescope/telescope-fzf-native.nvim",
9 build = "make",
10 },
11 "nvim-tree/nvim-web-devicons",
12 },
13 config = function()
14 local telescope = require("telescope")
15 local actions = require("telescope.actions")
16
17 telescope.setup({
18 defaults = {
19 path_display = { "truncate " },
20 mappings = {
21 i = {
22 -- ["<C-n>"] = actions.cycle_history_next,
23 -- ["<C-p>"] = actions.cycle_history_prev,
24
25 ["<C-j>"] = actions.move_selection_next,
26 ["<C-k>"] = actions.move_selection_previous,
27
28 ["<C-c>"] = actions.close,
29
30 ["<Down>"] = actions.move_selection_next,
31 ["<Up>"] = actions.move_selection_previous,
32
33 ["<CR>"] = actions.select_default,
34 -- ["<C-x>"] = actions.select_horizontal,
35 -- ["<C-v>"] = actions.select_vertical,
36 -- ["<C-t>"] = actions.select_tab,
37
38 ["<C-u>"] = actions.preview_scrolling_up,
39 ["<C-d>"] = actions.preview_scrolling_down,
40
41 ["<PageUp>"] = actions.results_scrolling_up,
42 ["<PageDown>"] = actions.results_scrolling_down,
43
44 ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse,
45 ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
46 ["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
47 ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
48 -- ["<C-l>"] = actions.complete_tag,
49 -- ["<C-_>"] = actions.which_key, -- keys from pressing <C-/>
50 },
51 n = {
52 ["<esc>"] = actions.close,
53 ["<CR>"] = actions.select_default,
54 -- ["<C-x>"] = actions.select_horizontal,
55 -- ["<C-v>"] = actions.select_vertical,
56 -- ["<C-t>"] = actions.select_tab,
57
58 ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse,
59 ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
60 ["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
61 ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
62
63 ["j"] = actions.move_selection_next,
64 ["k"] = actions.move_selection_previous,
65 ["K"] = actions.move_to_top,
66 -- ["M"] = actions.move_to_middle,
67 ["J"] = actions.move_to_bottom,
68
69 ["<Down>"] = actions.move_selection_next,
70 ["<Up>"] = actions.move_selection_previous,
71 ["gg"] = actions.move_to_top,
72 ["G"] = actions.move_to_bottom,
73
74 ["<C-u>"] = actions.preview_scrolling_up,
75 ["<C-d>"] = actions.preview_scrolling_down,
76
77 ["<PageUp>"] = actions.results_scrolling_up,
78 ["<PageDown>"] = actions.results_scrolling_down,
79
80 ["?"] = actions.which_key,
81 },
82 },
83 },
84 load_extension = {
85 "fzf",
86 "yank_history",
87 },
88 extensions = {
89 undo = {
90 mappings = {
91 i = {
92 ["<C-a>"] = require("telescope-undo.actions").yank_additions,
93 ["<C-d>"] = require("telescope-undo.actions").yank_deletions,
94 ["<C-u>"] = require("telescope-undo.actions").restore,
95 -- ["<C-Y>"] = require("telescope-undo.actions").yank_deletions,
96 -- ["<C-cr>"] = require("telescope-undo.actions").restore,
97 -- alternative defaults, for users whose terminals do questionable things with modified <cr>
98 },
99 n = {
100 ["y"] = require("telescope-undo.actions").yank_additions,
101 ["Y"] = require("telescope-undo.actions").yank_deletions,
102 ["u"] = require("telescope-undo.actions").restore,
103 },
104 },
105 },
106 },
107 })
108 end,
109}
todo-comments.lua
高亮代码注释
高亮代码中的 TODO
,WARNING
,NOTE
,HACK
,PERF
,FIX
等特殊注释:
1return {
2 "folke/todo-comments.nvim",
3 dependencies = { "nvim-lua/plenary.nvim" },
4 opts = {
5 }
6}
treesitter.lua
语法高亮
提供更快速、更精确的语法高亮和代码结构分析:
1return {
2 "nvim-treesitter/nvim-treesitter",
3 event = { "BufReadPre", "BufNewFile" },
4 build = ":TSUpdate",
5 dependencies = {
6 "JoosepAlviste/nvim-ts-context-commentstring",
7 "windwp/nvim-ts-autotag",
8 },
9 config = function()
10 require("nvim-treesitter.configs").setup({
11 -- enable syntax highlighting
12 highlight = {
13 enable = true,
14 disable = { "css", "latex", "markdown", "cls" }, -- list of language that will be disabled
15 },
16 -- enable indentation
17 indent = { enable = true },
18 -- enable autotagging (w/ nvim-ts-autotag plugin)
19 autotag = {
20 enable = false,
21 },
22 -- ensure these language parsers are installed
23 ensure_installed = {
24 "bash",
25 "lua",
26 "vim",
27 "gitignore",
28 "python",
29 "c",
30 "cpp",
31 "bibtex",
32 "vimdoc",
33 -- "latex",
34 },
35 auto_install = true,
36 ignore_install = { "latex" }, -- List of parsers to ignore installing
37 autopairs = {
38 enable = true,
39 },
40 -- indent = { enable = false, disable = { "latex", "python", "css" } },
41 incremental_selection = {
42 enable = true,
43 keymaps = {
44 init_selection = "<C-n>",
45 node_incremental = "<C-n>",
46 scope_incremental = false,
47 node_decremental = "<C-p>",
48 },
49 },
50 })
51
52 -- enable nvim-ts-context-commentstring plugin for commenting tsx and jsx
53 require("ts_context_commentstring").setup({})
54 end,
55}
vimtex.lua
$\LaTeX$ 集成
为 LaTeX 提供了强大的支持,包括编译、预览、目录、语法高亮等:
1return {
2 "lervag/vimtex",
3 ft = { "tex", "bib", "cls" }, -- 只在打开 .tex, .bib, .cls 文件时加载
4 init = function()
5 -- Indentation settings
6 vim.g.vimtex_indent_enabled = false -- Disable auto-indent from Vimtex
7 vim.g.tex_indent_items = false -- Disable indent for enumerate
8 vim.g.tex_indent_brace = false -- Disable brace indent
9
10 -- Suppression settings
11 vim.g.vimtex_quickfix_mode = 0 -- Suppress quickfix on save/build
12
13 -- Other settings
14 vim.g.vimtex_mappings_enabled = false -- Disable default mappings
15 vim.g.tex_flavor = 'latex' -- Set file type for TeX files
16 end,
17}
which-key.lua
编辑体验增强
当按下 <leader>
键后,弹窗提示所有可用的后续快捷键,同时定义了大量围绕文件、编译、Git 和 Telescope 的快捷键:
1return {
2 "folke/which-key.nvim",
3 commit = '*',
4 event = "VeryLazy",
5 init = function()
6 vim.o.timeout = true
7 vim.o.timeoutlen = 200
8 end,
9 opts = {
10 setup = {
11 show_help = true,
12 plugins = {
13 presets = {
14 operators = false, -- adds help for operators like d, y, ... and registers them for motion / text object completion
15 motions = false, -- adds help for motions
16 text_objects = false, -- help for text objects triggered after entering an operator
17 windows = false, -- default bindings on <c-w>
18 nav = false, -- misc bindings to work with windows
19 z = false, -- bindings for folds, spelling and others prefixed with z
20 g = false, -- bindings for prefixed with g
21 marks = false, -- shows a list of your marks on ' and `
22 registers = false, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
23 spelling = {
24 enabled = false, -- enabling this will show WhichKey when pressing z= to select spelling suggestions
25 suggestions = 10, -- how many suggestions should be shown in the list?
26 },
27 -- the presets plugin, adds help for a bunch of default keybindings in Neovim
28 -- No actual key bindings are created
29 },
30 },
31 key_labels = {
32 -- override the label used to display some keys. It doesn't effect WK in any other way.
33 -- For example:
34 -- ["<space>"] = "SPC",
35 -- ["<CR>"] = "RET",
36 -- ["<tab>"] = "TAB",
37 },
38 -- triggers = "auto", -- automatically setup triggers
39 triggers = { "<leader>" }, -- or specify a list manually
40 -- add operators that will trigger motion and text object completion
41 -- to enable native operators, set the preset / operators plugin above
42 -- operators = { gc = "Comments" },
43 icons = {
44 breadcrumb = "»", -- symbol used in the command line area that shows your active key combo
45 separator = "➜", -- symbol used between a key and it's label
46 group = "+", -- symbol prepended to a group
47 },
48 popup_mappings = {
49 scroll_down = "<c-d>", -- binding to scroll down inside the popup
50 scroll_up = "<c-u>", -- binding to scroll up inside the popup
51 },
52 window = {
53 border = "rounded", -- none, single, double, shadow
54 position = "bottom", -- bottom, top
55 margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left]
56 padding = { 2, 2, 2, 2 }, -- extra window padding [top, right, bottom, left]
57 winblend = 0,
58 zindex = 1000, -- positive value to position WhichKey above other floating windows.
59 },
60 layout = {
61 height = { min = 4, max = 25 }, -- min and max height of the columns
62 width = { min = 20, max = 50 }, -- min and max width of the columns
63 spacing = 3, -- spacing between columns
64 align = "left", -- align columns left, center or right
65 },
66 ignore_missing = true, -- enable this to hide mappings for which you didn't specify a label
67 hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate
68 triggers_nowait = {
69 },
70 triggers_blacklist = {
71 -- list of mode / prefixes that should never be hooked by WhichKey
72 -- this is mostly relevant for key maps that start with a native binding
73 -- most people should not need to change this
74 i = { "j", "k" },
75 v = { "j", "k" },
76 },
77 -- disable the WhichKey popup for certain buf types and file types.
78 -- Disabled by default for Telescope
79 disable = {
80 buftypes = {},
81 filetypes = {},
82 },
83 },
84 defaults = {
85 buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings
86 silent = true, -- use `silent` when creating keymaps
87 noremap = true, -- use `noremap` when creating keymaps
88 nowait = true, -- use `nowait` when creating keymaps
89 prefix = "<leader>",
90 mode = { "n", "v" },
91 d = { "<cmd>update! | bdelete!<CR>", "delete buffer" },
92 e = { "<cmd>NvimTreeToggle<CR>", "explorer" },
93 i = { "<cmd>VimtexTocOpen<CR>", "index" },
94 k = {
95 function()
96 -- Initialize variables
97 local filename = vim.fn.expand("%:p") -- Complete file path
98 local basename = vim.fn.expand("%:t:r") -- File names without extensions
99 local filetype = vim.bo.filetype -- Current file type
100 local deleted_files = {}
101 local messages = {}
102
103 -- Clean up the compiled products (c/cpp)
104 if filetype == "c" or filetype == "cpp" then
105 local targets = { ".exe", ".o" }
106 for _, ext in ipairs(targets) do
107 local file = basename .. ext
108 local full_path = vim.fn.fnamemodify(filename, ":h") .. "\\" .. file
109 if vim.fn.filereadable(full_path) == 1 then
110 os.remove(full_path)
111 table.insert(deleted_files, file)
112 end
113 end
114 end
115
116 -- Conditional execution of VimtexClean (LaTeX files only)
117 if filetype == "tex" then
118 vim.cmd("VimtexClean") -- Clean up LaTeX auxiliary files
119 table.insert(messages, "[LaTeX] already clean auxiliary files.")
120 end
121
122 -- Generate feedback information
123 if #deleted_files > 0 then
124 table.insert(messages, 1, "[Code] already clean compile files:\n" .. table.concat(deleted_files, "\n"))
125 end
126 if #messages == 0 then
127 table.insert(messages, "[Code] no auxiliary file need to clean.")
128 end
129
130 -- Show notification
131 vim.notify(table.concat(messages, "\n\n"), "info", {
132 title = "Clean Auxiliary",
133 timeout = 3000
134 })
135 end,
136 "kill aux"
137 },
138 q = { "<cmd>wa! | qa!<CR>", "quit" },
139 r = {
140 function()
141 local filename = vim.fn.expand("%:p")
142 local basename = vim.fn.expand("%:t:r")
143 local filetype = vim.bo.filetype
144 local cmd = ""
145 local quoted_filename = string.format('"%s"', filename) -- Handle paths containing Spaces
146
147 -- Dynamically select operations based on file types
148 if filetype == "tex" then
149 -- LaTeX file: Triggers VimtexCompile compilation
150 vim.cmd("VimtexCompile")
151 return
152 elseif filetype == "python" then
153 cmd = "python " .. quoted_filename
154 elseif filetype == "cpp" then
155 local exe_name = basename .. ".exe"
156 cmd = string.format("g++ %s -o %s && .\\%s", quoted_filename, exe_name, exe_name)
157 elseif filetype == "c" then
158 local exe_name = basename .. ".exe"
159 cmd = string.format("gcc %s -o %s && .\\%s", quoted_filename, exe_name, exe_name)
160 else
161 vim.notify("unsupported file type: " .. filetype, "error", { title = "Run/Compile" })
162 return
163 end
164
165 -- Execute the command and display the output
166 local output = vim.fn.system(cmd)
167 vim.api.nvim_echo({{output, "Normal"}}, false, {})
168 end,
169 "run code"
170 },
171 u = { "<cmd>Telescope undo<CR>", "undo history" },
172 v = { "<cmd>VimtexView<CR>", "view" },
173 w = { "<cmd>wa!<CR>", "write" },
174 a = {
175 name = "ACTIONS",
176 c = { "<cmd>vert sb<CR>", "create split" },
177 h = { "<cmd>LocalHighlightToggle<CR>", "local highlight toggle" },
178 j = { "<cmd>clo<CR>", "drop split" },
179 k = { "<cmd>clo<CR>", "kill split" },
180 m = { "<cmd>on<CR>", "max split" },
181 r = { "<cmd>VimtexErrors<CR>", "report errors" },
182 w = { "<cmd>VimtexCountWords!<CR>", "word count" },
183 },
184 c = {
185 name = "Copilot",
186 d = {
187 function()
188 vim.cmd("Copilot disable")
189 vim.notify("[Copilot] Copilot disabled", vim.log.levels.INFO, { title = "Copilot Status" })
190 end,
191 "disable Copilot"
192 },
193 e = {
194 function()
195 vim.cmd("Copilot enable")
196 vim.notify("[Copilot] Copilot enabled", vim.log.levels.INFO, { title = "Copilot Status" })
197 end,
198 "enable Copilot"
199 },
200 },
201 f = {
202 name = "FIND",
203 b = {
204 "<cmd>lua require('telescope.builtin').buffers(require('telescope.themes').get_dropdown{previewer = false})<CR>",
205 "buffers",
206 },
207 f = { "<cmd>Telescope live_grep theme=ivy<CR>", "project" },
208 g = { "<cmd>Telescope git_commits<CR>", "git history" },
209 h = { "<cmd>Telescope help_tags<CR>", "help" },
210 k = { "<cmd>Telescope keymaps<CR>", "keymaps" },
211 r = { "<cmd>Telescope registers<CR>", "registers" },
212 w = { "<cmd>lua SearchWordUnderCursor()<CR>", "word" },
213 r = { "<cmd>Telescope oldfiles<CR>", "recent" },
214 },
215 g = {
216 name = "GIT",
217 b = { "<cmd>Telescope git_branches<CR>", "checkout branch" },
218 c = { "<cmd>Telescope git_commits<CR>", "commits" },
219 d = { "<cmd>Gitsigns diffthis HEAD<CR>", "diff" },
220 k = { "<cmd>Gitsigns prev_hunk<CR>", "prev hunk" },
221 j = { "<cmd>Gitsigns next_hunk<CR>", "next hunk" },
222 l = { "<cmd>Gitsigns blame_line<CR>", "line blame" },
223 p = { "<cmd>Gitsigns preview_hunk<CR>", "preview hunk" },
224 t = { "<cmd>Gitsigns toggle_current_line_blame<CR>", "toggle blame" },
225 },
226 },
227 },
228 config = function(_, opts)
229 local wk = require("which-key")
230 wk.setup(opts.setup)
231 wk.register(opts.defaults)
232 end,
233}
snippets
文件夹
文件夹中的每一个文件对应于一种文件后缀相应的代码段,比如要配置 .tex
文件相应的 Neovim 加载的代码段,就创建一个 tex.lua
文件,这个文件中相应的代码段只会在 Neovim 打开对应于 .tex
文件时起作用。如果要配置对应于所有的文件类型的文件,就是说如果要配置代码段对所有的文件都生效,则要把相应的代码段放在 all.lua
文件中(如果没有这个文件可以创建一个)。
对应的教程可以参考:
tex.lua
$LaTeX$ 配置文件
1-- Summary: When `LS_SELECT_RAW` is populated with a visual selection, the function
2-- returns an insert node whose initial text is set to the visual selection.
3-- When `LS_SELECT_RAW` is empty, the function simply returns an empty insert node.
4local get_visual = function(args, parent)
5 if (#parent.snippet.env.LS_SELECT_RAW > 0) then
6 return sn(nil, i(1, parent.snippet.env.LS_SELECT_RAW))
7 else -- If LS_SELECT_RAW is empty, return a blank insert node
8 return sn(nil, i(1))
9 end
10end
11
12-- Example: expanding a snippet on a new line only.
13-- In a snippet file, first require the line_begin condition...
14-- ...then add `condition=line_begin` to any snippet's context table:
15local line_begin = require("luasnip.extras.expand_conditions").line_begin
16
17-- Include this `in_mathzone` function at the start of a snippets file...
18-- Then include `condition = in_mathzone` to any snippet you want to
19-- expand only in math contexts.
20local in_mathzone = function()
21 -- The `in_mathzone` function requires the VimTeX plugin
22 return vim.fn['vimtex#syntax#in_mathzone']() == 1
23end
24
25return {
26--------------------------------------------------
27-- Example: use of insert node placeholder text --
28--------------------------------------------------
29 s({ trig="hr", dscr="The hyperref package's href{}{} command (for url links)" },
30 fmta(
31 [[\href{<>}{<>}]],
32 {
33 i(1, "url"),
34 i(2, "display name"),
35 }
36 )
37 ),
38--------------------------------------------------------
39-- Example: italic font implementing visual selection --
40--------------------------------------------------------
41 s({ trig="tii", dscr="Expands 'tii' into LaTeX's textit{} command." },
42 fmta("\\textit{<>}",
43 {
44 d(1, get_visual),
45 }
46 )
47 ),
48----------------------------------
49-- A fun zero subscript snippet --
50----------------------------------
51 s({ trig='([%a%)%]%}])00', regTrig=true, wordTrig=false, snippetType="autosnippet" },
52 fmta(
53 "<>_{<>}",
54 {
55 f( function(_, snip) return snip.captures[1] end ),
56 t("0")
57 }
58 )
59 ),
60-----------------------------------
61-- Snippets for only in new line --
62-----------------------------------
63 -- HTML-like to insert directory hierarchy
64 s({ trig="h1", snippetType="autosnippet", condition=line_begin },
65 fmta(
66 [[\section{<>}]],
67 { d(1, get_visual) }
68 )
69 ),
70
71 s({ trig="h2", snippetType="autosnippet", condition=line_begin },
72 fmta(
73 [[\subsection{<>}]],
74 { d(1, get_visual) }
75 )
76 ),
77
78 s({ trig="h3", snippetType="autosnippet", condition=line_begin },
79 fmta(
80 [[\section{<>}]],
81 { d(1, get_visual) }
82 )
83 ),
84
85 -- Begin new environment
86 s({ trig="env", dscr="A generic new environmennt", condition=line_begin },
87 fmta(
88 [[
89 \begin{<>}
90 <>
91 \end{<>}
92 ]],
93 {
94 i(1),
95 i(2),
96 rep(1),
97 }
98 )
99 ),
100------------------------------------
101-- Snippets for only in math mode --
102------------------------------------
103 -- Fraction
104 s({ trig = "ff", snippetType="autosnippet", condition=in_mathzone },
105 fmta(
106 "\\frac{<>}{<>}",
107 {
108 i(1),
109 i(2),
110 }
111 )
112 ),
113
114 -- Greek letter
115 s({ trig=";a", snippetType="autosnippet", condition=in_mathzone },
116 {
117 t("\\alpha"),
118 }
119 ),
120 s({ trig=";b", snippetType="autosnippet", condition=in_mathzone },
121 {
122 t("\\beta"),
123 }
124 ),
125 s({ trig=";g", snippetType="autosnippet", condition=in_mathzone },
126 {
127 t("\\gamma"),
128 }
129 ),
130}