当前位置: 首页 > news >正文

Neovim-配置教程

环境:Ubuntu 20.04

宿主机:windows (windows terminal)WSL2

NVIM:v0.10.0-dev

配置Neovim 需要保证流畅的github环境(以便于快速拉取插件),可以使用代理或是配置Github SSH key

本文已同步更新于个人博客:Neovim 配置教程 | ReturnTmp

本篇博客是学习掘金小册的学习笔记,有兴趣的朋友可以直接点击下文链接了解详情

小册链接:Neovim 配置实战:从0到1打造自己的IDE - nshen - 掘金小册 (juejin.cn)

成品示例图

在这里插入图片描述

配置文件整体结构

├── LICENSE
├── README.md
├── init.lua
└── lua├── autocmds.lua├── basic.lua├── colorscheme.lua├── keybindings.lua├── lsp│   ├── cmp.lua│   ├── config│   │   ├── bash.lua│   │   ├── emmet.lua│   │   ├── html.lua│   │   ├── json.lua│   │   ├── lua.lua│   │   ├── markdown.lua│   │   ├── pyright.lua│   │   ├── rust.lua│   │   └── ts.lua│   ├── formatter.lua│   ├── null-ls.lua│   ├── setup.lua│   └── ui.lua├── plugin-config│   ├── bufferline.lua│   ├── comment.lua│   ├── dashboard.lua│   ├── gitsigns.lua│   ├── indent-blankline.lua│   ├── lualine.lua│   ├── nvim-autopairs.lua│   ├── nvim-tree.lua│   ├── nvim-treesitter.lua│   ├── project.lua│   ├── surround.lua│   ├── telescope.lua│   ├── toggleterm.lua│   ├── vimspector.lua│   └── which-key.lua├── plugins.lua└── utils├── fix-yank.lua├── global.lua└── im-select.lua

首先 init.lua 是整个配置的入口文件,负责引用所有其他的模块,基本上想要打开或关闭某个插件只要在这里修改一行代码即可。

  • basic.lua: 基础配置,是对默认配置的一个重置。

  • colorscheme.lua: 我们安装的主题皮肤配置,在这里切换主题。

  • keybindings.lua: 快捷键的设置,所有插件的快捷键也都会放在这里。

  • plugins.lua: 插件安装管理,插件安装或卸载全在这里设置。

  • lsp 文件夹:

    是对 Neovim 内置 LSP 功能的配置,包括常见编程语言与语法提示等。

    • config 文件夹包含各种语言服务器单独的配置文件。
    • setup.lua 内置 LSP 的配置。
    • cmp.lua 语法自动补全补全的配置,包括各种补全源,与自定义代码段。
    • ui.lua: 对内置 LSP 功能增强和 UI 美化。
    • formatter.lua: 独立代码格式化功能。
  • plugin-config 文件夹: 是对第三方插件的配置,未来每添加一个插件,这里就多一个配置文件。

  • utils 文件夹: 是对常见问题的修改,包括输入法切换,针对 windows 的特殊配置等。

配置 Nerd Fonts

官网:Nerd Fonts - Iconic font aggregator, glyphs/icons collection, & fonts patcher

下载字体文件FiraCodeNerdFont-Regular.ttf下载之后双击ttf文件点击安装即可添加到系统字体文件中

配置步骤:

image-20230502100537624

image-20230502100559247

最后点击保存

安装 Neovim

旧版本卸载:sudo apt-get remove neovim

官网:Installing Neovim · neovim/neovim Wiki (github.com)

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt-get update
sudo apt-get install neovim

执行nvim --version,确保版本必须为 0.7 及以上。

执行nvim ~/.bashrc

alias vim='nvim'
alias vi='nvim'
alias v='nvim'

执行source ~/.bashrc重新加载配置文件

配置入口 init.lua

~/.config/nvim/init.lua 写入如下内容:

-- 基础设置
require('basic')

require 函数在 Lua 中用于加载一个模块,而这些模块通常位于 runtimepath 中的 lua/ 目录下,也就是我们的 ~/.config/nvim/lua/ 目录。

所以上边的代码,就是加载 ~/.config/nvim/lua/basic.lua 文件(注意:require 里没有 .lua 扩展名)。当然也可以创建 ~/.config/nvim/lua/basic/ 目录,在目录下边创建 init.lua 文件也是可以成功加载的。

创建基础配置文件~/.config/nvim/lua/basic.lua,并添加如下内容:

-- utf8
vim.g.encoding = "UTF-8"
vim.o.fileencoding = 'utf-8'
-- jkhl 移动时光标周围保留8行
vim.o.scrolloff = 8
vim.o.sidescrolloff = 8
-- 使用相对行号
vim.wo.number = true
vim.wo.relativenumber = true
-- 高亮所在行
vim.wo.cursorline = true
-- 显示左侧图标指示列
vim.wo.signcolumn = "yes"
-- 右侧参考线,超过表示代码太长了,考虑换行
vim.wo.colorcolumn = "80"
-- 缩进2个空格等于一个Tab
vim.o.tabstop = 2
vim.bo.tabstop = 2
vim.o.softtabstop = 2
vim.o.shiftround = true
-- >> << 时移动长度
vim.o.shiftwidth = 2
vim.bo.shiftwidth = 2
-- 空格替代tab
vim.o.expandtab = true
vim.bo.expandtab = true
-- 新行对齐当前行
vim.o.autoindent = true
vim.bo.autoindent = true
vim.o.smartindent = true
-- 搜索大小写不敏感,除非包含大写
vim.o.ignorecase = true
vim.o.smartcase = true
-- 搜索不要高亮
vim.o.hlsearch = false
-- 边输入边搜索
vim.o.incsearch = true
-- 命令行高为2,提供足够的显示空间
vim.o.cmdheight = 2
-- 当文件被外部程序修改时,自动加载
vim.o.autoread = true
vim.bo.autoread = true
-- 禁止折行
vim.wo.wrap = false
-- 光标在行首尾时<Left><Right>可以跳到下一行
vim.o.whichwrap = '<,>,[,]'
-- 允许隐藏被修改过的buffer
vim.o.hidden = true
-- 鼠标支持
vim.o.mouse = "a"
-- 禁止创建备份文件
vim.o.backup = false
vim.o.writebackup = false
vim.o.swapfile = false
-- smaller updatetime
vim.o.updatetime = 300
-- 设置 timeoutlen 为等待键盘快捷键连击时间500毫秒,可根据需要设置
vim.o.timeoutlen = 500
-- split window 从下边和右边出现
vim.o.splitbelow = true
vim.o.splitright = true
-- 自动补全不自动选中
vim.g.completeopt = "menu,menuone,noselect,noinsert"
-- 样式
vim.o.background = "dark"
vim.o.termguicolors = true
vim.opt.termguicolors = true
-- 不可见字符的显示,这里只把空格显示为一个点
vim.o.list = true
vim.o.listchars = "space:·"
-- 补全增强
vim.o.wildmenu = true
-- Dont' pass messages to |ins-completin menu|
vim.o.shortmess = vim.o.shortmess .. 'c'
-- 补全最多显示10行
vim.o.pumheight = 10
-- 永远显示 tabline
vim.o.showtabline = 2
-- 使用增强状态栏插件后不再需要 vim 的模式提示
vim.o.showmode = false

快捷键设置

创建lua/keybindings.lua

vim.g.mapleader = " "
vim.g.maplocalleader = " "local map = vim.api.nvim_set_keymap
-- 复用 opt 参数
local opt = {noremap = true, silent = true }-- 取消 s 默认功能
map("n", "s", "", opt)
-- windows 分屏快捷键
map("n", "sv", ":vsp<CR>", opt)
map("n", "sh", ":sp<CR>", opt)
-- 关闭当前
map("n", "sc", "<C-w>c", opt)
-- 关闭其他
map("n", "so", "<C-w>o", opt)
-- Alt + hjkl  窗口之间跳转
map("n", "<A-h>", "<C-w>h", opt)
map("n", "<A-j>", "<C-w>j", opt)
map("n", "<A-k>", "<C-w>k", opt)
map("n", "<A-l>", "<C-w>l", opt)-- 左右比例控制
map("n", "<C-Left>", ":vertical resize -2<CR>", opt)
map("n", "<C-Right>", ":vertical resize +2<CR>", opt)
map("n", "s,", ":vertical resize -20<CR>", opt)
map("n", "s.", ":vertical resize +20<CR>", opt)
-- 上下比例
map("n", "sj", ":resize +10<CR>", opt)
map("n", "sk", ":resize -10<CR>", opt)
map("n", "<C-Down>", ":resize +2<CR>", opt)
map("n", "<C-Up>", ":resize -2<CR>", opt)
-- 等比例
map("n", "s=", "<C-w>=", opt)-- Terminal相关
map("n", "<leader>t", ":sp | terminal<CR>", opt)
map("n", "<leader>vt", ":vsp | terminal<CR>", opt)
map("t", "<Esc>", "<C-\\><C-n>", opt)
map("t", "<A-h>", [[ <C-\><C-N><C-w>h ]], opt)
map("t", "<A-j>", [[ <C-\><C-N><C-w>j ]], opt)
map("t", "<A-k>", [[ <C-\><C-N><C-w>k ]], opt)
map("t", "<A-l>", [[ <C-\><C-N><C-w>l ]], opt)-- visual模式下缩进代码
map("v", "<", "<gv", opt)
map("v", ">", ">gv", opt)
-- 上下移动选中文本
map("v", "J", ":move '>+1<CR>gv-gv", opt)
map("v", "K", ":move '<-2<CR>gv-gv", opt)-- 上下滚动浏览
map("n", "<C-j>", "4j", opt)
map("n", "<C-k>", "4k", opt)
-- ctrl u / ctrl + d  只移动9行,默认移动半屏
map("n", "<C-u>", "9k", opt)
map("n", "<C-d>", "9j", opt)-- 在visual 模式里粘贴不要复制
map("v", "p", '"_dP', opt)-- 退出
map("n", "q", ":q<CR>", opt)
map("n", "qq", ":q!<CR>", opt)
map("n", "Q", ":qa!<CR>", opt)-- insert 模式下,跳到行首行尾
map("i", "<C-h>", "<ESC>I", opt)
map("i", "<C-l>", "<ESC>A", opt)

最后在init.lua中引入快捷键文件

-- 快捷键映射
require("keybindings")

插件配置

目前在 Neovim 最常见的插件管理器主要有 vim-plug 和 packer 两个。

安装步骤(请参照官网步骤):

执行git clone --depth 1 https://github.com/wbthomason/packer.nvim\ ~/.local/share/nvim/site/pack/packer/start/packer.nvim

安装成功后添加配置文件lua/plugins.lua,添加如下内容

local packer = require("packer")
packer.startup(function(use)-- Packer 可以管理自己本身use 'wbthomason/packer.nvim'-- 你的插件列表...
end)

init.lua中添加如下内容

-- Packer 插件管理
require("plugins")

配置生效后,Neovim 会增加以下命令。

  • :PackerCompile: 每次改变插件配置时,必须运行此命令或 PackerSync, 重新生成编译的加载文件
  • :PackerClean : 清除所有不用的插件
  • :PackerInstall : 清除,然后安装缺失的插件
  • :PackerUpdate : 清除,然后更新并安装插件
  • :PackerSync : 执行 PackerUpdate 后,再执行 PackerCompile
  • :PackerLoad : 立刻加载 opt 插件

通过上边的说明,我们观察到 :PackerSync 命令包含了 :PackerUpdate:PackerCompile,而 :PackerUpdate 又包含了 :PackerClean:PackerInstall 流程。

所以通常情况下,无论安装还是更新插件,我只需要下边这一条命令就够::PackerSync

每次修改完 lua/plugins.lua 这个文件后,保存退出,重新打开并调用 :PackerSync 就可以了

添加自动安装

lua/plugins.lua 文件,在最后添加

-- 每次保存 plugins.lua 自动安装插件
pcall(vim.cmd,[[augroup packer_user_configautocmd!autocmd BufWritePost plugins.lua source <afile> | PackerSyncaugroup end]]
)

注意:保证自己可以ping 通 github 的情况下,但是仍旧执行:PackerSync失败,按 R 多次拉取失败插件,如果依旧失败则在错误插件处点击回车,查看问题,具体问题具体分析,我一般多试几次 R 就会成功

配置主题

init.lua中添加如下内容:

-- 主题设置 (新增)
require("colorscheme")

lua/colorscheme.lua添加

local colorscheme = "tokyonight"
local status_ok, _ = pcall(vim.cmd, "colorscheme " .. colorscheme)
if not status_ok thenvim.notify("colorscheme " .. colorscheme .. " 没有找到!")return
end

安装第三方主题

lua/plugins.lua文件

packer.startup({function(use)-- Packer 可以升级自己use("wbthomason/packer.nvim")--------------------- colorschemes ---------------------- tokyonightuse("folke/tokyonight.nvim")--------------------------------------------------------- 略...
})

:w保存 p退出

其他主体配色链接:neovim-colorscheme · GitHub Topics

lua/plugins.lua添加插件配置后,修改 lua/colorscheme.luacolorscheme 变量为相应的主题即可

侧边栏文件浏览器

相关插件:

  • nvim-tree/nvim-tree.lua: A file explorer tree for neovim written in lua (github.com)

lua/plugins.lua 中添加

packer.startup({function(use)-- Packer 可以升级自己use("wbthomason/packer.nvim")-------------------------- plugins --------------------------------------------- nvim-tree (新增)use({ "kyazdani42/nvim-tree.lua", requires = "kyazdani42/nvim-web-devicons" })...略

配置 nvim-tree

lua/plugin-config/nvim-tree.lua

local status, nvim_tree = pcall(require, "nvim-tree")
if not status thenvim.notify("没有找到 nvim-tree")return
end-- 列表操作快捷键
local list_keys = require('keybindings').nvimTreeList
nvim_tree.setup({-- 不显示 git 状态图标git = {enable = false,},-- project plugin 需要这样设置update_cwd = true,update_focused_file = {enable = true,update_cwd = true,},-- 隐藏 .文件 和 node_modules 文件夹filters = {dotfiles = true,custom = { 'node_modules' },},view = {-- 宽度width = 40,-- 也可以 'right'side = 'left',-- 隐藏根目录hide_root_folder = false,-- 自定义列表中快捷键mappings = {custom_only = false,list = list_keys,},-- 不显示行数number = false,relativenumber = false,-- 显示图标signcolumn = 'yes',},actions = {open_file = {-- 首次打开大小适配resize_window = true,-- 打开文件时关闭quit_on_open = true,},},-- wsl install -g wsl-open-- https://github.com/4U6U57/wsl-open/system_open = {cmd = 'wsl-open', -- mac 直接设置为 open},
})
-- 自动关闭
vim.cmd([[autocmd BufEnter * ++nested if winnr('$') == 1 && bufname() == 'NvimTree_' . tabpagenr() | quit | endif
]])

上边代码就是 nvim-tree 的配置,可以根据注释进行修改。这里简单解释一下,值得注意的是 system_open 项,如果想要在 WSL 中用 Windows 系统默认设置打开文件,需要使用 Node.js 全局安装一个 wsl-open 包,使用命令 npm install -g wsl-open,如果不需要这个功能,也可以不用安装。 如果不是 Windows 系统也就不需要安装。

nvim-tree 初始化支持很多参数,如果想知道还有哪些其他的参数,可以运行 :h nvim-tree.setup 调出帮助文档查看。

lua/keybindings.lua添加

-- 插件快捷键
local pluginKeys = {}-- nvim-tree
-- alt + m 键打开关闭tree
map("n", "<A-m>", ":NvimTreeToggle<CR>", opt)
-- 列表快捷键
pluginKeys.nvimTreeList = {-- 打开文件或文件夹{ key = {"<CR>", "o", "<2-LeftMouse>"}, action = "edit" },-- 分屏打开文件{ key = "v", action = "vsplit" },{ key = "h", action = "split" },-- 显示隐藏文件{ key = "i", action = "toggle_custom" }, -- 对应 filters 中的 custom (node_modules){ key = ".", action = "toggle_dotfiles" }, -- Hide (dotfiles)-- 文件操作{ key = "<F5>", action = "refresh" },{ key = "a", action = "create" },{ key = "d", action = "remove" },{ key = "r", action = "rename" },{ key = "x", action = "cut" },{ key = "c", action = "copy" },{ key = "p", action = "paste" },{ key = "s", action = "system_open" },
}
return pluginKeys

init.lua添加

-- 插件配置
require("plugin-config.nvim-tree")

但是出现问题view.mappings.list has been deprecated in favour of on_attach.please run,应该是某些插件更新:相关链接:Migrating To on_attach · nvim-tree/nvim-tree.lua Wiki (github.com)

表明view.mappings and remove_keymaps已经启用需要移除

解决方案:

注释掉view.mappings

执行:NvimTreeGenerateOnAttach,复制nvim-tree-on-attach.lua中的内容粘贴到 nvim-tree.lua中(需要添加在setup之前)

添加

require("nvim-tree").setup({...on_attach = on_attach,
})

问题解决~

顶部标签页和底部信息栏

相关插件:

  • akinsho/bufferline.nvim: A snazzy bufferline for Neovim (github.com)
  • nvim-lualine/lualine.nvim: A blazing fast and easy to configure neovim statusline plugin written in pure lua. (github.com)
顶部标签页

lua/plugins.lua

packer.startup({function(use)-- Packer 可以升级自己use("wbthomason/packer.nvim")-------------------------- plugins --------------------------------------------- nvim-treeuse({ "kyazdani42/nvim-tree.lua", requires = "kyazdani42/nvim-web-devicons" })-- bufferline (新增)use({ "akinsho/bufferline.nvim", requires = { "kyazdani42/nvim-web-devicons", "moll/vim-bbye" }})...略

:w 保存,自动安装,安装完整按 q 退出

出现**GnuTLS recv error (-110)**问题

解决方案:

# 依次执行
apt-get install gnutls-bin
# 关闭 SSL 验证
git config --global http.sslVerify false
# 第二个命令是用于设置缓冲区大小
git config --global http.postBuffer 1048576000
# 或是
sudo update-alternatives --set fakeroot /usr/bin/fakeroot-tcp

这里我增加了一个 moll/vim-bbye 依赖,因为这个插件安装后会增加一个 :Bdelete 命令,相比内置的 :bdelete, 它删除 buffer 的同时,并不会搞乱布局 。 待会儿我们会配置 Bdelete 为关闭 Tab 的命令。

新建lua/plugin-config/bufferline.lua文件并添加内容

local status, bufferline = pcall(require, "bufferline")
if not status thenvim.notify("没有找到 bufferline")return
end-- bufferline 配置
-- https://github.com/akinsho/bufferline.nvim#configuration
bufferline.setup({options = {-- 关闭 Tab 的命令,这里使用 moll/vim-bbye 的 :Bdelete 命令close_command = "Bdelete! %d",right_mouse_command = "Bdelete! %d",-- 侧边栏配置-- 左侧让出 nvim-tree 的位置,显示文字 File Exploreroffsets = {{filetype = "NvimTree",text = "File Explorer",highlight = "Directory",text_align = "left",},},-- 使用 nvim 内置 LSP  后续课程会配置diagnostics = "nvim_lsp",-- 可选,显示 LSP 报错图标---@diagnostic disable-next-line: unused-localdiagnostics_indicator = function(count, level, diagnostics_dict, context)local s = " "for e, n in pairs(diagnostics_dict) dolocal sym = e == "error" and " " or (e == "warning" and " " or "")s = s .. n .. symendreturn send,},
})

lua/keybindings.lua

-- bufferline
-- 左右Tab切换
map("n", "<C-h>", ":BufferLineCyclePrev<CR>", opt)
map("n", "<C-l>", ":BufferLineCycleNext<CR>", opt)
-- 关闭
--"moll/vim-bbye"
map("n", "<C-w>", ":Bdelete!<CR>", opt)
map("n", "<leader>bl", ":BufferLineCloseRight<CR>", opt)
map("n", "<leader>bh", ":BufferLineCloseLeft<CR>", opt)
map("n", "<leader>bc", ":BufferLinePickClose<CR>", opt)

init.lua添加

require("plugin-config.bufferline")
底部信息栏

lua/plugins.lua

    -- lualine (新增)use({ "nvim-lualine/lualine.nvim", requires = { "kyazdani42/nvim-web-devicons" } })use("arkav/lualine-lsp-progress")

新建lua/plugin-config/lualine.lua

-- 如果找不到lualine 组件,就不继续执行
local status, lualine = pcall(require, "lualine")
if not status thenvim.notify("没有找到 lualine")return
endlualine.setup({options = {theme = "tokyonight",component_separators = { left = "|", right = "|" },-- https://github.com/ryanoasis/powerline-extra-symbolssection_separators = { left = " ", right = "" },},extensions = { "nvim-tree", "toggleterm" },sections = {lualine_c = {"filename",{"lsp_progress",spinner_symbols = { " ", " ", " ", " ", " ", " " },},},lualine_x = {"filesize",{"fileformat",-- symbols = {--   unix = '', -- e712--   dos = '', -- e70f--   mac = '', -- e711-- },symbols = {unix = "LF",dos = "CRLF",mac = "CR",},},"encoding","filetype",},},
})

init.lua添加

require("plugin-config.lualine")

模糊搜索快速查找文件

相关插件:nvim-telescope/telescope.nvim: Find, Filter, Preview, Pick. All lua, all the time. (github.com)

lua/plugins.lua

    -- telescope (新增)use { 'nvim-telescope/telescope.nvim', requires = { "nvim-lua/plenary.nvim" } }

:checkhealth telescope 检查依赖情况,这里通常会提示 ripgrep 不存在,因为 telescope 依赖以下两个项目。

  • sharkdp/fd: A simple, fast and user-friendly alternative to ‘find’ (github.com)
  • BurntSushi/ripgrep: ripgrep recursively searches directories for a regex pattern while respecting your gitignore (github.com)

解决方案:

# 20.04 安装 repgrep
sudo apt install ripgrep
# 18.04 安装 repgrep
sudo add-apt-repository ppa:x4121/ripgrep
sudo apt-get update
sudo apt install ripgrep
# 安装 fd
npm install -g fd-find

配置 node 环境

node

配置源,需要哪个版本可以将16替换为相应版本

curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -

安装

sudo apt-get update -y
sudo apt install -y nodejs

如果不想要自己配置指定版本源的情况下,可以直接执行

sudo apt update -y
sudo apt install nodejs npm

nvm

官网:nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions (github.com)

git clone nvm仓库时遇到如下错误

GnuTLS recv error (-110): The TLS connection 。。。

我是因为Ipv6的问题,可以git clone -4 指定使用Ipv4连接

但是执行ap-get update遇到问题:

Err:12 http://ppa.launchpad.net/x4121/ripgrep/ubuntu focal Release
404 Not Found [IP: 185.125.190.52 80]
Reading package lists…
E: The repository ‘http://ppa.launchpad.net/x4121/ripgrep/ubuntu focal Release’ does not have a Release file.

这是因为之前我执行过sudo add-apt-repository ppa:x4121/ripgrep所以可以直接手动删除

解决方案(自动移除再更新):

sudo apt-add-repository -r ppa:x4121/ripgrep
# 指的是先移除armagetronad-dev这个ppa包,再添加这个ppa包
sudo apt update -q

手动删除

cd /etc/apt/sources.list.d
rm x4121-ubuntu-ripgrep-focal.list
# .save 文件是备份,不需要管

后面我在使用更新插件包时爆出:Could not resolve host github.com

解决1(失败):

# 从全局配置文件中删除代理设置
git config --global --unset http.proxy
git config --global --unset https.proxy

解决2(成功):

我直接ping了下网络,发现不只是github连不上,而是整个WSL网络都不能使用,在宿主机中我查看WSL网络配置,发现未修复之前两个红框中的ip地址是没有的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ey8Oa3Ol-1683939661824)(null)]

直接在宿主机上使用管理员权限执行netsh winsock reset重启网络即可(注意:不需要重启)

下面解决方案没有试过,仅作为备用方案

解决3:

# 重启 WSL 指令 
$ wsl --shutdown 
# 之后就重新启动进入即可 
$ wsl

自定义启动页与项目列表

当我们在命令行中输入 nvim 不带任何路径并敲击回车的时候,就会打开这个界面,通常我们会在这个界面中配置最常用功能,比如打开最近编辑过的文件,快速打开项目文件夹,快速修改快捷键等。

使用官方配置的图像: Ascii Header Text · nvimdev/dashboard-nvim Wiki (github.com)

使用字体生成器:[Text to ASCII Art Generator (TAAG) (patorjk.com)](http://patorjk.com/software/taag/#p=display&f=ANSI Shadow&t=rettmp)

同样 plugins.lua 中添加:

    -- dashboard-nvim (新增)use("glepnir/dashboard-nvim")

创建 lua/plugin-config/dashboard.lua ,并添加:

local status, db = pcall(require, "dashboard")
if not status thenvim.notify("没有找到 dashboard")return
enddb.setup({theme = 'doom',config = {header = {
[[                                                     ]],
[[                                                     ]],
[[██████╗ ███████╗████████╗████████╗███╗   ███╗██████╗ ]],
[[██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝████╗ ████║██╔══██╗]],
[[██████╔╝█████╗     ██║      ██║   ██╔████╔██║██████╔╝]],
[[██╔══██╗██╔══╝     ██║      ██║   ██║╚██╔╝██║██╔═══╝ ]],
[[██║  ██║███████╗   ██║      ██║   ██║ ╚═╝ ██║██║     ]],
[[╚═╝  ╚═╝╚══════╝   ╚═╝      ╚═╝   ╚═╝     ╚═╝╚═╝     ]],
[[                                                     ]],
[[                [ version : 1.0.0 ]                  ]],
[[                                                     ]],}, --your headercenter = {{icon = "  ",desc = "Projects                            ",action = "Telescope projects",},{icon = "  ",desc = "Recently files                      ",action = "Telescope oldfiles",},{icon = "  ",desc = "Edit keybindings                    ",action = "edit ~/.config/nvim/lua/keybindings.lua",},{icon = "  ",desc = "Edit Projects                       ",action = "edit ~/.local/share/nvim/project_nvim/project_history",},},footer = {}  --your footer}
})

但是里面的 Telescope projects 并不是 telescope 内置的命令。需要安装ahmedkhalf/project.nvim插件,执行如下步骤

步骤

添加插件

-- project
use("ahmedkhalf/project.nvim")

确保lua/plugin-config/nvim-tree.lua文件中有如下代码:

nvim_tree.setup({--- 上略-- project plugin 需要这样设置update_cwd = true,update_focused_file = {enable = true,update_cwd = true,},-- 下略
}

创建lua/plugin-config/project.lua

local status, project = pcall(require, "project_nvim")
if not status thenvim.notify("没有找到 project_nvim")return
end-- nvim-tree 支持
vim.g.nvim_tree_respect_buf_cwd = 1project.setup({detection_methods = { "pattern" },patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", ".sln" },
})local status, telescope = pcall(require, "telescope")
if not status thenvim.notify("没有找到 telescope")return
end
pcall(telescope.load_extension, "projects")

init.lua

require("plugin-config.dashboard")
require("plugin-config.project")
手动编辑 project_history 列表

执行:lua print(require("project_nvim.utils.path").historyfile)

我得到了~/.local/share/nvim/project_nvim/project_history这个文件,直接编辑即可

添加

/root/.config/nvim

以后的话可以方便编写nvim项目配置 😃

语法高亮安装及配置

相关插件:nvim-treesitter/nvim-treesitter: Nvim Treesitter configurations and abstraction layer (github.com)

添加插件

    -- treesitter (新增)use({ "nvim-treesitter/nvim-treesitter", run = ":TSUpdate" })
手动安装Language parser

运行 :TSInstallInfo 命令查看 language parsers 列表与安装状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ihzik4QO-1683939658098)(C:\Users\86150\AppData\Roaming\Typora\typora-user-images\image-20230509193140841.png)]

安装::TSInstall javascript

卸载::TSUninstall javascript

安装后会在 packer 中生成相应语言的so文件

自动安装配置

lua/plugin-config/nvim-treesitter.lua

local status, treesitter = pcall(require, "nvim-treesitter.configs")
if not status thenvim.notify("没有找到 nvim-treesitter")return
endtreesitter.setup({-- 安装 language parser-- :TSInstallInfo 命令查看支持的语言ensure_installed = { "json", "html", "css", "vim", "lua", "javascript", "typescript", "tsx" },-- 启用代码高亮模块highlight = {enable = true,additional_vim_regex_highlighting = false,},
})

init.lua

require("plugin-config.nvim-treesitter")

稍微说下里面 nvim-treesitter 中的配置

增量选择模块

当你的光标在一个语法结点上时,可以设置一个增加键和一个减少键,敲击这两个,在表现上为不断外扩和收缩选中代码。

增加和减少结点的快捷键设置成了 回车退格 。通过不断的按 Enter 选择区域会从里层不断外扩, Backspace 则相反不断内收。

-- 启用增量选择模块
incremental_selection = {enable = true,keymaps = {init_selection = "<CR>",node_incremental = "<CR>",node_decremental = "<BS>",scope_incremental = "<TAB>",},
},
代码缩进

在 visual 模式中按 = 即可实现代码缩进

  -- 启用代码缩进模块 (=)indent = {enable = true,},
代码折叠

快捷键中设置了zc 组合键来折叠 {} 中的内容,还使用 zo 组合键来打开对应的折叠。

-- 开启 Folding 模块
vim.opt.foldmethod = "expr"
vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
-- 默认不要折叠
-- https://stackoverflow.com/questions/8316139/how-to-set-the-default-to-unfolded-when-you-open-a-file
vim.opt.foldlevel = 99

执行:TSModuleInfo查看是否成功

如果出现问题先执行TSUpdate看是否可以解决,无法解决查看官方issues或wiki

LSP 基础配置

目的:实现类似IDE的智能提示、语法检查和解析、悬停文档等交互体验

定义:LSP(Language Server Protocol) 语言服务协议,该协议定义了在编辑器或IDE与语言服务器之间使用的协议,该语言服务器提供了例如自动补全,转到定义,查找所有引用等的功能;语言服务器索引格式的目标是支持在开发工具中进行丰富的代码导航或者一个无需本地源码副本的WebUI。

开启 neovim 内置LSP

执行:h lsp查看quick start,里面的步骤如下

  • 使用包管理器安装语言服务器
  • 为每一种语言服务器配置LSP客户端
  • 配置快捷键(keymaps)和自动命令(autocmds)
配置客户端

安装插件:neovim/nvim-lspconfig: Quickstart configs for Nvim LSP (github.com)

配置语言服务器

安装插件:williamboman/nvim-lsp-installer: Further development has moved to https://github.com/williamboman/mason.nvim!

配置插件:

    --------------------- LSP --------------------use("williamboman/nvim-lsp-installer")-- Lspconfiguse({ "neovim/nvim-lspconfig" })
安装 LSP Server

运行:LspInstallInfo ,点击 i 即可安装相应的 Server ,进入之后安装 Lua server

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4tt5Dgq-1683939661761)(null)]

从最上面的介绍得知作者未来会用 mason.nvim 取代 nvim-lsp-installermason.nvim 项目支持更多的 server 安装,不仅仅是LSP Server 还支持 DAP servers、 linters、formatters 等等超过 150 个包,100+ 种编程语言,并且升级也是非常简单的

但是安装失败,直接重新安装即可成功

但是有时遇到could not find executable "unzip" in path 问题,可以使用如下命令

sudo apt-get install zip unzip

但是安装成功之后发现问题,我从issues中了解到是因为lua server的仓库地址发生变化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGkOjmCU-1683939659326)(null)]

鉴于nvim-lsp-installer出现的各种问题,现在使用mason.nvim代替nvim-lsp-installer

步骤:

  • 运行:LspUninstallAll卸载nvim-lsp-installer
  • plugins.lua 替换 nvim-lsp-installer 插件为 mason.nvimmason-lspconfig.nvim
    use({ "williamboman/mason.nvim" })use({ "williamboman/mason-lspconfig.nvim" })
  • lua/lsp/setup.lua 相应部分替换为(这个文件后面会创建,现在先讲下)
local status, mason = pcall(require, "mason")
if not status thenvim.notify("没有找到 mason")return
endlocal status, mason_config = pcall(require, "mason-lspconfig")
if not status thenvim.notify("没有找到 mason-lspconfig")return
endlocal status, lspconfig = pcall(require, "lspconfig")
if not status thenvim.notify("没有找到 lspconfig")return
end-- :h mason-default-settings
-- ~/.local/share/nvim/mason
mason.setup({ui = {icons = {package_installed = "✓",package_pending = "➜",package_uninstalled = "✗",},},
})-- mason-lspconfig uses the `lspconfig` server names in the APIs it exposes - not `mason.nvim` package names
-- https://github.com/williamboman/mason-lspconfig.nvim/blob/main/doc/server-mapping.md
mason_config.setup({ensure_installed = {"lua_ls",},
})-- 安装列表
-- { key: 服务器名, value: 配置文件 }
-- key 必须为下列网址列出的 server name,不可以随便写
-- https://github.com/williamboman/nvim-lsp-installer#available-lsps
local servers = {lua_ls = require("lsp.config.lua"), -- lua/lsp/config/lua.lua
}for name, config in pairs(servers) doif config ~= nil and type(config) == "table" then-- 自定义初始化配置文件必须实现on_setup 方法config.on_setup(lspconfig[name])else-- 使用默认参数lspconfig[name].setup({})end
endrequire("lsp.ui")

保存之后默认安装到 ~/.local/share/nvim/mason

执行:Mason即可打开,操作基本和上面的一样,只不过多了 1,2,3,4,5 是上边TAB快捷键,按 2 即可切换到 LSP

Mason 仓库地址:Mason

配置 LSP Server

创建一个新的目录 lua/lsp/ 专门存放 lsp 相关的配置,使用:h mason-lspconfig-automatic-server-setup查看如何配置setup,或是直接看官网

创建lua/lsp/setup.lua

local status, mason = pcall(require, "mason")
if not status thenvim.notify("没有找到 mason")return
endlocal status, mason_config = pcall(require, "mason-lspconfig")
if not status thenvim.notify("没有找到 mason-lspconfig")return
endlocal status, lspconfig = pcall(require, "lspconfig")
if not status thenvim.notify("没有找到 lspconfig")return
end-- :h mason-default-settings
-- ~/.local/share/nvim/mason
mason.setup({ui = {icons = {package_installed = "✓",package_pending = "➜",package_uninstalled = "✗",},},
})-- mason-lspconfig uses the `lspconfig` server names in the APIs it exposes - not `mason.nvim` package names
-- https://github.com/williamboman/mason-lspconfig.nvim/blob/main/doc/server-mapping.md
mason_config.setup({ensure_installed = {"lua_ls",},
})-- 安装列表
-- { key: 服务器名, value: 配置文件 }
-- key 必须为下列网址列出的 server name,不可以随便写
-- https://github.com/williamboman/nvim-lsp-installer#available-lsps
local servers = {lua_ls = require("lsp.config.lua"), -- lua/lsp/config/lua.lua
}for name, config in pairs(servers) doif config ~= nil and type(config) == "table" then-- 自定义初始化配置文件必须实现on_setup 方法config.on_setup(lspconfig[name])else-- 使用默认参数lspconfig[name].setup({})end
endrequire("lsp.ui")
配置 lua Server

创建/lua/lsp/config/lua.lua

-- https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
local runtime_path = vim.split(package.path, ';')
table.insert(runtime_path, 'lua/?.lua')
table.insert(runtime_path, 'lua/?/init.lua')local opts = {settings = {Lua = {runtime = {-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)version = 'LuaJIT',-- Setup your lua pathpath = runtime_path,},diagnostics = {-- Get the language server to recognize the `vim` globalglobals = { 'vim' },},workspace = {-- Make the server aware of Neovim runtime fileslibrary = vim.api.nvim_get_runtime_file('', true),checkThirdParty = false,},-- Do not send telemetry data containing a randomized but unique identifiertelemetry = {enable = false,},},},flags = {debounce_text_changes = 150,},on_attach = function(client, bufnr)-- 禁用格式化功能,交给专门插件插件处理client.resolved_capabilities.document_formatting = falseclient.resolved_capabilities.document_range_formatting = falselocal function buf_set_keymap(...)vim.api.nvim_buf_set_keymap(bufnr, ...)end-- 绑定快捷键require('keybindings').mapLSP(buf_set_keymap)-- 保存时自动格式化vim.cmd('autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()')end,
}-- 查看目录等信息
return {on_setup = function(server)server:setup(opts)end,
}
配置 LSP 快捷键

lua/keybindings.lua

-- lsp 回调函数快捷键设置
pluginKeys.mapLSP = function(mapbuf)-- renamemapbuf("n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename()<CR>", opt)-- code actionmapbuf("n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>", opt)-- go xxmapbuf("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", opt)mapbuf("n", "gh", "<cmd>lua vim.lsp.buf.hover()<CR>", opt)mapbuf("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>", opt)mapbuf("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opt)mapbuf("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opt)-- diagnosticmapbuf("n", "gp", "<cmd>lua vim.diagnostic.open_float()<CR>", opt)mapbuf("n", "gk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opt)mapbuf("n", "gj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opt)mapbuf("n", "<leader>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opt)-- 没用到-- mapbuf('n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opt)-- mapbuf("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opt)-- mapbuf('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opt)-- mapbuf('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opt)-- mapbuf('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opt)-- mapbuf('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opt)
end

init.lua

-- 内置LSP (新增)
require("lsp.setup")

这里记录下:使用:verbose map可以查看所有生效的快捷键

基于 LSP 代码补全及自定义代码段

相关插件:hrsh7th/nvim-cmp: A completion plugin for neovim coded in Lua. (github.com)
相关概念:
  1. 补全引擎

    补全引擎就是为 Neovim 提供代码补全核心功能的插件,比如 nvim-cmp

  2. 补全源

    补全源就是补全引擎需要的数据来源,最常见的来源是来自 Language Server 提供的数据,它会知道某个类有哪些属性和方法等。

  3. snippet 引擎

    snippet 引擎就是自定义代码段的引擎,常见的有 vsnipluasnip

添加插件
    -- 补全引擎use("hrsh7th/nvim-cmp")-- snippet 引擎use("hrsh7th/vim-vsnip")-- 补全源use("hrsh7th/cmp-vsnip")use("hrsh7th/cmp-nvim-lsp") -- { name = nvim_lsp }use("hrsh7th/cmp-buffer") -- { name = 'buffer' },use("hrsh7th/cmp-path") -- { name = 'path' }use("hrsh7th/cmp-cmdline") -- { name = 'cmdline' }-- 常见编程语言代码段use("rafamadriz/friendly-snippets")

注意:只有 hrsh7th/nvim-cmp 是补全引擎插件本身,其他 cmp-xxx 基本都是插件补全来源,也就是说当你输入一个变量的时候,可以从多个来源显示补全的内容。

像 hrsh7th/cmp-nvim-lsp 就是 Neovim 内置 LSP 提供的补全内容,hrsh7th/cmp-buffer 补全当前 buffer 的内容, hrsh7th/cmp-cmdline 是命令行的补全,hrsh7th/cmp-path 则是用来补全路径,如果配置了这个,当输入一个路径的时候会补全路径

创建lua/lsp/cmp.lua

local cmp = require("cmp")cmp.setup({-- 指定 snippet 引擎snippet = {expand = function(args)-- For `vsnip` users.vim.fn["vsnip#anonymous"](args.body)-- For `luasnip` users.-- require('luasnip').lsp_expand(args.body)-- For `ultisnips` users.-- vim.fn["UltiSnips#Anon"](args.body)-- For `snippy` users.-- require'snippy'.expand_snippet(args.body)end,},-- 补全源sources = cmp.config.sources({{ name = "nvim_lsp" },-- For vsnip users.{ name = "vsnip" },-- For luasnip users.-- { name = 'luasnip' },--For ultisnips users.-- { name = 'ultisnips' },-- -- For snippy users.-- { name = 'snippy' },}, { { name = "buffer" }, { name = "path" } }),-- 快捷键设置mapping = require("keybindings").cmp(cmp),
})-- / 查找模式使用 buffer 源
cmp.setup.cmdline("/", {mapping = cmp.mapping.preset.cmdline(),sources = {{ name = "buffer" },},
})-- : 命令行模式中使用 path 和 cmdline 源.
cmp.setup.cmdline(":", {mapping = cmp.mapping.preset.cmdline(),sources = cmp.config.sources({{ name = "path" },}, {{ name = "cmdline" },}),
})

lua/keybindings.lua添加

-- nvim-cmp 自动补全
pluginKeys.cmp = function(cmp)return {-- 出现补全["<A-.>"] = cmp.mapping(cmp.mapping.complete(), {"i", "c"}),-- 取消补全["<A-,>"] = cmp.mapping({i = cmp.mapping.abort(),c = cmp.mapping.close()}),-- 上一个["<C-k>"] = cmp.mapping.select_prev_item(),-- 下一个["<C-j>"] = cmp.mapping.select_next_item(),-- 确认["<CR>"] = cmp.mapping.confirm({select = true,behavior = cmp.ConfirmBehavior.Replace}),-- 如果窗口内容太多,可以滚动["<C-u>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), {"i", "c"}),["<C-d>"] = cmp.mapping(cmp.mapping.scroll_docs(4), {"i", "c"}),}
end

init.lua

require("lsp.cmp") --  (新增)

LSP 功能增强

UI 插件,同时 lspage还可以自定义快捷键,对于我自己而言我认为有些地方文字更加直观,如果有些朋友需要美化可自行查找

弹窗显示错误

当一行代码很长的时候,右侧的提示文字就会显示不全

之前配置过 gp 快捷键使用弹窗显示错误,可以有效解决

功能增强
相关插件:kkharji/lspsaga.nvim: The neovim language-server-client UI (github.com)
添加插件
	use("tami5/lspsaga.nvim" )

创建lua/lsp/ui.lua

local lspsaga = require 'lspsaga'
lspsaga.setup { -- defaults ...debug = false,use_saga_diagnostic_sign = true,-- diagnostic signerror_sign = "",warn_sign = "",hint_sign = "",infor_sign = "",diagnostic_header_icon = "   ",-- code action title iconcode_action_icon = " ",code_action_prompt = {enable = true,sign = true,sign_priority = 40,virtual_text = true,},finder_definition_icon = "  ",finder_reference_icon = "  ",max_preview_lines = 10,finder_action_keys = {-- open = "o",open = "<CR>",vsplit = "s",split = "i",-- quit = "q",quit = "<ESC>",scroll_down = "<C-f>",scroll_up = "<C-b>",},code_action_keys = {-- quit = "q",quit = "<ESC>",exec = "<CR>",},rename_action_keys = {-- quit = "<C-c>",quit = "<ESC>",exec = "<CR>",},definition_preview_icon = "  ",border_style = "single",rename_prompt_prefix = "➤",rename_output_qflist = {enable = false,auto_open_qflist = false,},server_filetype_map = {},diagnostic_prefix_format = "%d. ",diagnostic_message_format = "%m %c",highlight_prefix = false,
}

lua/keybindings.lua中的mapLSP 函数替换为

-- lsp 回调函数快捷键设置
pluginKeys.mapLSP = function(mapbuf)-- rename--[[Lspsaga 替换 rnmapbuf("n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename()<CR>", opt)--]]mapbuf("n", "<leader>rn", "<cmd>Lspsaga rename<CR>", opt)-- code action--[[Lspsaga 替换 camapbuf("n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>", opt)--]]mapbuf("n", "<leader>ca", "<cmd>Lspsaga code_action<CR>", opt)-- go xx--[[mapbuf('n', 'gd', '<cmd>Lspsaga preview_definition<CR>', opt)--]]mapbuf("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", opt)--[[Lspsaga 替换 ghmapbuf("n", "gh", "<cmd>lua vim.lsp.buf.hover()<CR>", opt)--]]mapbuf("n", "gh", "<cmd>Lspsaga hover_doc<cr>", opt)--[[Lspsaga 替换 grmapbuf("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opt)--]]mapbuf("n", "gr", "<cmd>Lspsaga lsp_finder<CR>", opt)--[[Lspsaga 替换 gp, gj, gkmapbuf("n", "gp", "<cmd>lua vim.diagnostic.open_float()<CR>", opt)mapbuf("n", "gj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opt)mapbuf("n", "gk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opt)--]]-- diagnosticmapbuf("n", "gp", "<cmd>Lspsaga show_line_diagnostics<CR>", opt)mapbuf("n", "gj", "<cmd>Lspsaga diagnostic_jump_next<cr>", opt)mapbuf("n", "gk", "<cmd>Lspsaga diagnostic_jump_prev<cr>", opt)mapbuf("n", "<leader>f", "<cmd>lua vim.lsp.buf.format({ bufnr = bufnr })<CR>", opt)-- 未用-- mapbuf("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>", opt)-- mapbuf("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opt)-- mapbuf('n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opt)-- mapbuf("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opt)-- mapbuf('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opt)-- mapbuf('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opt)-- mapbuf('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opt)-- mapbuf('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opt)
end

init.lua

require("lsp.ui")

代码格式化

之前lua/keybindings.lua定义过格式化快捷键

mapbuf("n", "<leader>f", "<cmd>lua vim.lsp.buf.format({ bufnr = bufnr })<CR>", opt)

但是你会发现格式化不起作用,这是因为使用的 Lua Language Server 并没有实现格式化功能。

格式化方案有如下两种:

  • 第一种是使用专门的格式化插件;
  • 第二种是给 Language Server 注入格式化功能。

这里只讲解第二种

相关插件:jose-elias-alvarez/null-ls.nvim: Use Neovim as a language server to inject LSP diagnostics, code actions, and more via Lua. (github.com)
添加插件
    -- 代码格式化use({ "jose-elias-alvarez/null-ls.nvim", requires = "nvim-lua/plenary.nvim" })
添加配置文件 lua/lsp/null-ls.lua
local status, null_ls = pcall(require, "null-ls")
if not status thenvim.notify("没有找到 null-ls")return
endlocal formatting = null_ls.builtins.formattingnull_ls.setup({debug = false,sources = {-- Formatting -----------------------  brew install shfmtformatting.shfmt,-- StyLuaformatting.stylua,-- frontendformatting.prettier.with({ -- 只比默认配置少了 markdownfiletypes = {"javascript","javascriptreact","typescript","typescriptreact","vue","css","scss","less","html","json","yaml","graphql",},prefer_local = "node_modules/.bin",}),-- formatting.fixjson,-- formatting.black.with({ extra_args = { "--fast" } }),},-- 保存自动格式化on_attach = function(client, bufnr)if client.supports_method("textDocument/formatting") thenvim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })vim.api.nvim_create_autocmd("BufWritePre", {group = augroup,buffer = bufnr,callback = function()-- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) insteadvim.lsp.buf.format({ bufnr = bufnr })-- vim.lsp.buf.formatting_sync()end,})endend,
})

init.lua

require("lsp.null-ls")

安装之后可以运行:LspInfo查看绑定的Language Server

image-20230512122954608

然后我们可以看到有两个 LSP 了,null-ls 作为通用 LSP,可以在任何 filetypes 中运行。

然后执行:NullLsInfo查看源的激活情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4BqlCgg-1683939661651)(null)]

之后的话即可使用:lua vim.lsp.buf.format()命令或是直接使用快捷键<leader>f进行格式化

但是我们会发现包如下错误,这是因为相应语言应该配置相应的Code Formatter,显示报错就是缺少Lua语言的StyLua,其它语言可以自行配置相应的Formatter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iIOB3ONA-1683939661588)(null)]

下面展示如何配置stylua

配置环境

stylua 需要配置 rust 环境 ,rust官网:安装 Rust - Rust 程序设计语言 (rust-lang.org)

因为我是使用WSL,因此直接执行如下命令即可

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

执行source "$HOME/.cargo/env"

执行rustc --version看是否成功,失败则看是否添加~/.cargo/bin路径到环境变量中

安装步骤

执行

cargo install stylua

输出stylua -V看是否成功

出现问题

格式化之后里面的空格就都变成了"^I", 原本应该是“·”的

直接将basic.lua文件中设置vim.o.listchars = "space:·,tab:··"或是设置vim.o.list = false

前端开发必要配置

配置语法高亮

执行:TSInstall css scss json html vue javascript typescript

执行:TSInstallInfo查看安装情况

配置 LSP

lua/lsp/setup.lua

mason_config.setup({ensure_installed = {"lua_ls", "html", "cssls"}
})
...
local servers = {lua_ls = require("lsp.config.lua"),-- 新增html = require("lsp.config.html"),cssls = require("lsp.config.css")
}

创建lsp/common-config.lua

local M = {}M.keyAttach = function(bufnr)local function buf_set_keymap(mode, lhs, rhs)vim.keymap.set(mode, lhs, rhs, { noremap = true, silent = true, buffer = bufnr })end-- 绑定快捷键require("keybindings").mapLSP(buf_set_keymap)
end-- 禁用格式化功能,交给专门插件插件处理
M.disableFormat = function(client)if vim.fn.has("nvim-0.8") == 1 thenclient.server_capabilities.documentFormattingProvider = falseclient.server_capabilities.documentRangeFormattingProvider = falseelseclient.resolved_capabilities.document_formatting = falseclient.resolved_capabilities.document_range_formatting = falseend
end-- M.capabilities = require("cmp_nvim_lsp").update_capabilities(vim.lsp.protocol.make_client_capabilities())
M.capabilities = require("cmp_nvim_lsp").default_capabilities()M.flags = {debounce_text_changes = 150,
}return M

创建lsp/config/html.lua

local common = require("lsp.common-config")
local opts = {capabilities = common.capabilities,flags = common.flags,on_attach = function(client, bufnr)-- 禁用本身语言格式化common.disableFormat(client)common.keyAttach(bufnr)end,
}
return {on_setup = function(server)server.setup(opts)end,
}

创建lsp/config/css.lua

local common = require("lsp.common-config")
local opts = {capabilities = common.capabilities,flags = common.flags,on_attach = function(client, bufnr)common.disableFormat(client)common.keyAttach(bufnr)end,settings = {css = {validate = true,-- tailwindcsslint = {unknownAtRules = "ignore",},},less = {validate = true,lint = {unknownAtRules = "ignore",},},scss = {validate = true,lint = {unknownAtRules = "ignore",},},},
}return {on_setup = function(server)server.setup(opts)end,
}

上面不禁用的话也是可以的,只不过会和默认的null-ls中的 prettier 格式化冲突,每次格式化都需要选择

注意html、css文件均是需要项目根目录有package.json文件和prettier依赖

# 创建package.json并安装prettier依赖,顺便把eslint也配置上
npm init -y && npm i -D prettier eslint
Emmet LSP 配置

使用 emmet 可是使用简单的语法可以快速打出 HTML 结构标签

创建lua/lsp/config/emmet.lua

local opts = {filetypes = { "html", "typescriptreact", "javascriptreact", "css", "sass", "scss", "less" },
}
return {on_setup = function(server)server.setup(opts)end,
}

lua/lsp/setup.lua修改

mason_config.setup({ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls"}
})
...
local servers = {lua_ls = require("lsp.config.lua"),html = require("lsp.config.html"),cssls = require("lsp.config.css"),-- 新增emmet_ls = require("lsp.config.emmet")
}
配置 jsonls

JSON Schema Store 插件,即JSON增强包

plugins.lua添加插件

-- JSON 增强
use("b0o/schemastore.nvim")

新建lua/lsp/config/json.lua

local common = require("lsp.common-config")
local opts = {capabilities = common.capabilities,flags = common.flags,on_attach = function(client, bufnr)-- use fixjson to format-- https://github.com/rhysd/fixjsoncommon.disableFormat(client)common.keyAttach(bufnr)end,settings = {json = {schemas = require("schemastore").json.schemas(),},},
}return {on_setup = function(server)server.setup(opts)end,
}

lsp/config/setup.lua修改

mason_config.setup({ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls","jsonls"}
})local servers = {lua_ls = require("lsp.config.lua"),html = require("lsp.config.html"),cssls = require("lsp.config.css"),emmet_ls = require("lsp.config.emmet"),-- 新增jsonls = require("lsp.config.json")
}
配置 tssserver

添加TS增强包插件

use({ "jose-elias-alvarez/nvim-lsp-ts-utils", requires = "nvim-lua/plenary.nvim" })

创建lsp/config/ts.lua

local common = require("lsp.common-config")
local keybindings = require("keybindings")
local ts_utils = require("nvim-lsp-ts-utils")
local opts = {flags = common.flags,capabilities = common.capabilities,-- https://github.com/jose-elias-alvarez/nvim-lsp-ts-utils/blob/main/lua/nvim-lsp-ts-utils/utils.lua-- 传入 tsserver 初始化参数-- make inlay hints workinit_options = {hostInfo = "neovim",preferences = {includeInlayParameterNameHints = "all",includeInlayParameterNameHintsWhenArgumentMatchesName = true,includeInlayFunctionParameterTypeHints = true,includeInlayVariableTypeHints = true,includeInlayPropertyDeclarationTypeHints = true,includeInlayFunctionLikeReturnTypeHints = true,includeInlayEnumMemberValueHints = true,},},on_attach = function(client, bufnr)common.disableFormat(client)common.keyAttach(bufnr)-- defaultsts_utils.setup({debug = false,disable_commands = false,enable_import_on_completion = false,-- import allimport_all_timeout = 5000, -- ms-- lower numbers = higher priorityimport_all_priorities = {same_file = 1, -- add to existing import statementlocal_files = 2, -- git files or files with relative path markersbuffer_content = 3, -- loaded buffer contentbuffers = 4, -- loaded buffer names},import_all_scan_buffers = 100,import_all_select_source = false,-- if false will avoid organizing importsalways_organize_imports = true,-- filter diagnosticsfilter_out_diagnostics_by_severity = {},-- https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.jsonfilter_out_diagnostics_by_code = {80001,},-- inlay hintsauto_inlay_hints = true,inlay_hints_highlight = "Comment",inlay_hints_priority = 200, -- priority of the hint extmarksinlay_hints_throttle = 150, -- throttle the inlay hint requestinlay_hints_format = { -- format options for individual hint kindType = {},Parameter = {},Enum = {},-- Example format customization for `Type` kind:-- Type = {--     highlight = "Comment",--     text = function(text)--         return "->" .. text:sub(2)--     end,-- },},-- update imports on file moveupdate_imports_on_move = false,require_confirmation_on_move = false,watch_dir = nil,})-- required to fix code action ranges and filter diagnosticsts_utils.setup_client(client)-- no default maps, so you may want to define some herekeybindings.mapTsLSP(bufnr)end,
}return {on_setup = function(server)server.setup(opts)end,
}

同样setup.lua修改

mason_config.setup({ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "tsserver"}
})-- 安装列表
-- { key: 服务器名, value: 配置文件 }
-- key 必须为下列网址列出的 server name,不可以随便写
-- https://github.com/williamboman/nvim-lsp-installer#available-lsps
local servers = {lua_ls = require("lsp.config.lua"),html = require("lsp.config.html"),cssls = require("lsp.config.css"),emmet_ls = require("lsp.config.emmet"),jsonls = require("lsp.config.json"),-- 新增tsserver = require("lsp.config.ts")
}

添加快捷键lua/keybindings.lua

-- typescript 快捷键
pluginKeys.mapTsLSP = function(mapbuf)mapbuf("n", "gs", ":TSLspOrganize<CR>", opt)mapbuf("n", "gr", ":TSLspRenameFile<CR>", opt)mapbuf("n", "gi", ":TSLspImportAll<CR>", opt)
end
  • gs 删除不用的 import 语句并重新排序。
  • gr 用于改变文件名,同时其他文件中引用该文件的文件名也会被修改。
  • gi 导入当前文件的所有依赖,并且会自动排序
ESLint 和 Prettier 配置

null-ls 中除了格式化 Formatting,还有Diagnostics(红字错误提示) 和 Code Actions(代码触发的行为)

lsp/null-ls.lua修改为

local status, null_ls = pcall(require, "null-ls")
if not status thenvim.notify("没有找到 null-ls")return
endlocal formatting = null_ls.builtins.formatting
local diagnostics = null_ls.builtins.diagnostics
local code_actions = null_ls.builtins.code_actionsnull_ls.setup({debug = false,sources = { -- Formatting -----------------------  brew install shfmtformatting.shfmt, -- StyLuaformatting.stylua, -- frontendformatting.prettier.with({ -- 只比默认配置少了 markdownfiletypes = {"javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "css", "scss", "less","html", "json", "yaml", "graphql"},prefer_local = "node_modules/.bin"}), -- Diagnostics  ---------------------diagnostics.eslint.with({prefer_local = "node_modules/.bin"}), -- code actions ---------------------code_actions.gitsigns, code_actions.eslint.with({prefer_local = "node_modules/.bin"})},-- #{m}: message-- #{s}: source name (defaults to null-ls if not specified)-- #{c}: code (if available)diagnostics_format = "[#{s}] #{m}",-- 保存自动格式化on_attach = function(client, bufnr)if client.supports_method("textDocument/formatting") thenvim.api.nvim_clear_autocmds({group = augroup,buffer = bufnr})vim.api.nvim_create_autocmd("BufWritePre", {group = augroup,buffer = bufnr,callback = function()-- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) insteadvim.lsp.buf.format({bufnr = bufnr})-- vim.lsp.buf.formatting_sync()end})endend
})

code_actions.gitsigns 没有安装可以注释掉

使用<leader>ca调用 Code Action 自动修复快捷键

Rust 开发配置

前文已安装rust环境,此处不赘述

语法高亮

plugin-config/nvim-treesitter.lua中的ensure_installed中添加"rust"

或是执行:TSInstall rust

代码提示

lsp/setup.lua

mason_config.setup({ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "rust_analyzer"}
})
...
local servers = {-- 新增rust_analyzer = require("lsp.config.rust"),
}

lsp/config/rust.lua

local common = require("lsp.common-config")
local opts = {capabilities = common.capabilities,flags = common.flags,on_attach = function(client, bufnr)common.disableFormat(client)common.keyAttach(bufnr)end,settings = {-- to enable rust-analyzer settings visit:-- https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/generated_config.adoc["rust-analyzer"] = {-- enable clippy on savecheckOnSave = {command = "clippy",},},},
}return {on_setup = function(server)local ok_rt, rust_tools = pcall(require, "rust-tools")if not ok_rt thenprint("Failed to load rust tools, will set up `rust_analyzer` without `rust-tools`.")server.setup(opts)else-- We don't want to call lspconfig.rust_analyzer.setup() when using rust-toolsrust_tools.setup({server = opts,-- dap = require("dap.nvim-dap.config.rust"),})endend,
}

添加 Rust 增强包插件

-- Rust 增强
use("simrat39/rust-tools.nvim")
代码格式化

安装相应 Formtter

rustup component add rustfmt

null-ls.lua

source中添加

-- rustfmt
formatting.rustfmt,

filetypes中添加"rust"

其他配置

自动补全括号

插件仓库:windwp/nvim-autopairs: autopairs for neovim written by lua (github.com)

引入插件

use("windwp/nvim-autopairs")

创建lua/plugin-config/nvim-autopairs.lua

-- https://github.com/windwp/nvim-autopairs
local status, autopairs = pcall(require, "nvim-autopairs")
if not status thenvim.notify("没有找到 nvim-autopairs")return
end
autopairs.setup({check_ts = true,ts_config = {lua = { "string" }, -- it will not add a pair on that treesitter nodejavascript = { "template_string" },java = false, -- don't check treesitter on java},
})
-- If you want insert `(` after select function or method item
local cmp_autopairs = require("nvim-autopairs.completion.cmp")
local cmp = require("cmp")
cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done({ map_char = { tex = "" } }))

init.lua

快速注释插件

插件仓库:numToStr/Comment.nvim: // Smart and powerful comment plugin for neovim. Supports treesitter, dot repeat, left-right/up-down motions, hooks, and more (github.com)

添加插件

use("numToStr/Comment.nvim")

创建lua/plugin-config/comment.lua

local status, comment = pcall(require, "Comment")
if not status thenvim.notify("没有找到 Comment")return
endlocal default_opts = {---Add a space b/w comment and the line---@type boolean|fun():booleanpadding = true,---Whether the cursor should stay at its position---NOTE: This only affects NORMAL mode mappings and doesn't work with dot-repeat---@type booleansticky = true,---Lines to be ignored while comment/uncomment.---Could be a regex string or a function that returns a regex string.---Example: Use '^$' to ignore empty lines---@type string|fun():stringignore = nil,---LHS of toggle mappings in NORMAL + VISUAL mode---@type tabletoggler = {---Line-comment toggle keymapline = "gcc",---Block-comment toggle keymapblock = "gbc",},---LHS of operator-pending mappings in NORMAL + VISUAL mode---@type tableopleader = {---Line-comment keymapline = "gc",---Block-comment keymapblock = "gb",},---LHS of extra mappings---@type tableextra = {---Add comment on the line aboveabove = "gcO",---Add comment on the line belowbelow = "gco",---Add comment at the end of lineeol = "gcA",},---Create basic (operator-pending) and extended mappings for NORMAL + VISUAL mode---NOTE: If `mappings = false` then the plugin won't create any mappings---@type boolean|tablemappings = {---Operator-pending mapping---Includes `gcc`, `gbc`, `gc[count]{motion}` and `gb[count]{motion}`---NOTE: These mappings can be changed individually by `opleader` and `toggler` configbasic = true,---Extra mapping---Includes `gco`, `gcO`, `gcA`extra = false,---Extended mapping---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`extended = false,},---Pre-hook, called before commenting the line---@type fun(ctx: Ctx):stringpre_hook = nil,---Post-hook, called after commenting is done---@type fun(ctx: Ctx)post_hook = nil,
}-- 关闭了extra快捷键,只用keybindings里定义的基础快捷键
comment.setup(vim.tbl_deep_extend("force", default_opts, require("keybindings").comment))

定义快捷键 keybindings.lua gcc 快捷键作为行注释,gbc 快捷键作为块注释

-- 代码注释插件
-- see ./lua/plugin-config/comment.lua
pluginKeys.comment = {-- Normal 模式快捷键toggler = {line = "gcc", -- 行注释block = "gbc", -- 块注释},-- Visual 模式opleader = {line = "gc",bock = "gb",},
}

init.lua中引入

require("plugin-config.comment")
Surround 配置

引入插件

    -- surrounduse("ur4ltz/surround.nvim")

lua/plugin-config/surround.lua

local status, surround = pcall(require, "surround")
if not status thenvim.notify("没有找到 surround")return
endsurround.setup({mappings_style = "surround",
})

init.lua

surround 官方快捷键如下

Normal Mode - Sandwich Mode
Provides key mapping to add surrounding characters.( visually select then press s<char> or press sa{motion}{char})
Provides key mapping to replace surrounding characters.( sr<from><to> )
Provides key mapping to delete surrounding characters.( sd<char> )
ss repeats last surround command.
Normal Mode - Surround Mode
Provides key mapping to add surrounding characters.( visually select then press s<char> or press ys{motion}{char})
Provides key mapping to replace surrounding characters.( cs<from><to> )
Provides key mapping to delete surrounding characters.( ds<char> )
Insert Mode
<c-s><char> will insert both pairs in insert mode.
<c-s><char><space> will insert both pairs in insert mode with surrounding whitespace.
<c-s><char><c-s> will insert both pairs on newlines insert mode.

常用快捷键

  • ds<char>
  • cs<from><to>
  • ys{motion}{char}
其他问题

我在推送仓库时频繁遇到GnuTLS recv error (-110)

解决链接:git - GnuTLS recv error (-110)

#!/bin/bash
set -e
sudo apt-get install build-essential fakeroot dpkg-dev -y
sudo apt-get build-dep git -y
sudo apt-get install libcurl4-openssl-dev -y
cd ~
mkdir source-git
cd source-git/
apt-get source git
cd git-2.*.*/
sed -i -- 's/libcurl4-gnutls-dev/libcurl4-openssl-dev/' ./debian/control
sed -i -- '/TEST\s*=\s*test/d' ./debian/rules
dpkg-buildpackage -rfakeroot -b -uc -us
sudo dpkg -i ../git_*ubuntu*.deb

直接运行这个脚本即可

之后推送遇到remote: Support for password authentication was removed on August 13, 2021问题,虽然我不太清楚我配了SSH key,为什么还是走的密码验证,但是我还是按照他的提示来做获取token,直接github首页中Setting->Developer settings->Personal access tokens 生成token

执行

git remote set-url origin https://<your_token>@github.com/<USERNAME>/<REPO>.git

最后即可免密推送

结语

对我自己而言,配置的这些功能虽然少,但是暂时够用,如果追求更多的功能,可以直接用小册作者的仓库,或是其他优秀仓库

其实我觉得其实作为个人使用来说,没有特殊需求的情况下不是很推荐自己配置,只需要看懂本篇博客,然后可以做到更改别人写好的配置即可

还有就是切忌盲目复制粘贴,一定要看官方文档

本篇博客示例配置仓库:ReturnTmp/rettmp-nvim

掘金小册作者仓库:https://github.com/nshen/learn-neovim-lua

注意:v2分支是neovim 8.0+适用

或是直接使用作者的新仓库:nshen/InsisVim: 🗃 An out-of-the-box Neovim IDE solution that setup development environment in an incredibly simple way. (github.com)

除了小册作者的配置仓库,这里再推荐一个优秀Neovim配置仓库:ayamir/nvimdots: A well configured and structured Neovim. (github.com)

至此Neovim配置学习就结束了😄

相关文章:

Neovim-配置教程

环境&#xff1a;Ubuntu 20.04 宿主机&#xff1a;windows &#xff08;windows terminal&#xff09;WSL2 NVIM&#xff1a;v0.10.0-dev 配置Neovim 需要保证流畅的github环境&#xff08;以便于快速拉取插件&#xff09;&#xff0c;可以使用代理或是配置Github SSH key 本文…...

Windows管理内存的3种方式——堆、虚拟内存、共享内存

一、操作系统管理内存概述 在 Windows 操作系统中&#xff0c;每个进程都被分配了 4GB 的虚拟地址空间&#xff0c;这被称为进程的虚拟地址空间。虚拟地址空间提供了一个抽象的地址空间&#xff0c;使得每个进程都可以认为它拥有自己的独立内存空间。这个虚拟地址空间被分为两…...

PCM/FM解调原理与Matlab算法仿真

调制的作用是将调制信息的频谱从低频搬移到高频,以适合信道传输。关于调制的原理,在上一节中已经讲过了。在这一节中,主要讲解FM的解调原理。与调制相对应的是在接收端需要解调过程将调制信息复原,所以解调是影响通信系统性能的重要技术。 解调方法按照是否需要载波恢复的…...

我的『1024』创作纪念日

目录 ◐机缘 ◑收获 ◐日常 ◑成就 ◐憧憬 记得&#xff0c;2020年07月22日我撰写了第1篇技术博客&#xff1a;《遗传算法实例解析》在这平凡的一天&#xff0c;我赋予了它不平凡的意义也许是立志成为一名专业T作者、也许是记录一段刚实践的经验但在那一刻&#xff0c;我已…...

Python ---> 衍生的数据技术

我的个人博客主页&#xff1a;如果’真能转义1️⃣说1️⃣的博客主页 关于Python基本语法学习---->可以参考我的这篇博客&#xff1a;《我在VScode学Python》 随着人工智能技术的发展&#xff0c;挖掘和分析商业运用大数据已经成为一种推动应用&#xff0c; 推动社会发展起着…...

【27】linux进阶——rpm软件包的管理

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…...

HTTP第六讲——键入网址再按下回车,后面究竟发生了什么?

使用 IP 地址访问 Web 服务器 首先我们运行 www 目录下的“start”批处理程序&#xff0c;启动本机的 OpenResty 服务器&#xff0c;启动后可以用“list”批处理确认服务是否正常运行。 然后我们打开 Wireshark&#xff0c;选择“HTTP TCP port(80)”过滤器&#xff0c;再鼠标…...

layui目录和项目引入

1.目录结构如下 ├─css //css目录 │ │─modules //模块css目录&#xff08;一般如果模块相对较大&#xff0c;我们会单独提取&#xff0c;比如下面三个&#xff1a;&#xff09; │ │ ├─laydate │ │ ├─layer │ │ └─layim │ └─layui.css //核心样式文件…...

Ubuntu22.04 将EFI启动分区迁移到另一块硬盘

机器上有两块硬盘, 一块已经安装了Win10, 另一块新装Ubuntu22.04, 在新硬盘上划分分区的时候, 有分出256M给 BOOT EFI, 但是安装的时候没注意, 启动分区不知道怎的跑到 Windows 所在的硬盘上了 记录一下将 /boot/efi 分区迁移至 Ubuntu 所在硬盘, 并创建 Grub 的记录. 预留的…...

只要学会这些AI工具,一个人就是一家营销咨询公司

本教程收集于:AIGC从入门到精通教程 只要学会这些AI工具,一个人就是一家营销咨询公司 随着AI工具的不断涌现,您只需掌握市面上热门的AI工具,便可独自开展营销咨询公司。通过一系列AI工具,您可以为企业提供全案服务,收获丰厚回报。 例如,在协助一家美妆初创公司出海时,…...

[离散数学] 函数

文章目录 函数判断函数的条件复合函数复合函数的性质 逆函数 函数 判断函数的条件 dom F A ⇔ \Leftrightarrow ⇔所有x 都有 F&#xff08;x&#xff09;与之对应 有唯一的与其对应 < x , y > ∈ f ∧ < y , z > ∈ f ⇒ y z <x,y>\in f \land <y,z…...

好家伙,又一份牛逼笔记面世了...

最近网传的一些裁员的消息&#xff0c;搞的人心惶惶。已经拿到大厂offer的码友来问我&#xff1a;大厂还能去&#xff0c;去了会不会被裁。 还在学习的网友来问我&#xff1a;现在还要冲互联网么&#xff1f; 我是认为大家不用恐慌吧&#xff0c;该看啥看啥&#xff0c;该学啥…...

基于nodejs+vue3 的高仿网易云音乐

大家好&#xff0c;我是小寻&#xff0c;欢迎大家关注我的公众号&#xff1a;工具优选&#xff0c;加入前端、java群聊哦&#xff01; 今天给大家分享一个超高水准的项目&#xff1a;基于nodejsvue3研发的高仿网易云音乐&#xff0c;项目内容出自寻码网&#xff01; 技术栈&a…...

MySQL数据库用户管理以及数据库用户授权

一、数据库用户管理 1、新建用户 CREATE USER 用户名来源地址 [IDENTIFIED BY [PASSWORD] 密码]; ---------------------------------------------------------------------------------------------------------- 用户名&#xff1a;指定将创建的用户名 来源地址&#xff1a…...

全面分析生物技术的优缺点以及应用场景

一、 引言 生物识别技术具有不可撤销性、高度便利性和较低错误率等优势&#xff0c;在安全领域中也备受瞩目。然而&#xff0c;对于生物识别技术在应对安全挑战方面的可靠性和有效性&#xff0c;但争议并未被完全解决 二、生物识别技术的介绍 所谓生物识别技术就是&#xff0c;…...

OpenAI是什么?

OpenAI是一家人工智能技术公司&#xff0c;成立于2015年&#xff0c;总部位于美国旧金山。它的创始人包括埃隆马斯克等多名知名人士&#xff0c;公司的目标是推进人工智能技术的发展&#xff0c;同时确保人工智能的发展不会对人类造成负面影响。 OpenAI在研究和开发各种人工智能…...

量子计算——新兴领域的前沿技术

随着人类社会文明的不断进步&#xff0c;计算技术也在不断发展。传统计算机在过去的几十年中快速发展&#xff0c;计算速度、存储能力等方面发生了天翻地覆的变化。但随着大数据、人工智能、区块链等新兴领域的迅速崛起&#xff0c;传统计算机的发展似乎面临了瓶颈。在这样的背…...

.Net平台下OpenGL绘制图形(1)(VS2019,Winform,C#)

1、介绍 OpenGL&#xff08;英语&#xff1a;Open Graphics Library&#xff0c;译名&#xff1a;开放图形库或者“开放式图形库”&#xff09;是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口&#xff08;API&#xff09;。这个接口由近350个不同的函数调用组成…...

Casso的创作纪念日

机缘 注册CSDN的时候才刚上大学&#xff0c;到现在使用CSDN已经四年了&#xff0c;距发布第一篇文章却只刚过去一百多天&#xff0c;刚看到这个提醒消息的时候只感慨时间过得真快&#xff0c;自己也在慢慢成长着&#xff0c;当初刚开始学习的时候&#xff0c;查资料用得最多的就…...

Bernhard‘s Talk on Towards Causal NLP 笔记

因果学习系列笔记 这是我的 GitHub 因果学习笔记仓库 https://github.com/xin007-kong/ryCausalLearning&#xff0c;欢迎 star&#x1f929; 讲者是 Bernhard Schlkopf talk 链接&#xff1a;(41) Bernhard Schoelkopf | Towards Causal NLP | KeynoteEMNLP 2021 Causal Infer…...

ES6模块化规范

在没有ES6模块化规范前&#xff0c;有像AMD、CMD这样的浏览器模块化规范&#xff0c;还有像CommonJS这样的服务端模块化规范。 2015年&#xff0c;JS终于推出了官方的模块化规范&#xff0c;为了统一各种规范&#xff0c;我们简称ES6 模块化。 ES6目前作为JS的内置模块化系统&a…...

红黑树下岗,内核新数据结构上场:maple tree!

在外界看来&#xff0c;Linux 内核的内部似乎变化很少&#xff0c;尤其是像内存管理子系统&#xff08;memory-management subsystem&#xff09;这样的子系统。然而&#xff0c;开发人员时常需要更换内部接口来解决某些长期存在的问题。比如&#xff0c;其中一个问题就是用来保…...

Angular开发之——Angular打包部署项目(04)

一 概述 ng build 构建应用lite-server介绍及安装lite-server部署应用IIS管理器部署应用 二 ng build 构建应用 2.1 执行如下指令构建应用 ng build2.2 构建完成后&#xff0c;会创建一个 dist 文件夹 2.3 直接打开index.html会出错(需要借助于服务器部署) 三 lite-server介…...

深度优先搜索算法思想,题型总结与题目清单(不断更新)

深度优先搜索 深度优先搜索&#xff08;Depth-First Search&#xff0c;简称DFS&#xff09;是一种用于遍历或搜索树或图的算法。这个名称直接来自于这个算法的操作方式&#xff1a;它沿着某一路径深入遍历直到无法继续&#xff0c;然后再回溯进行下一条路径的遍历。 DFS的主要…...

网页三剑客之 CSS

css 在这里不会介绍太多&#xff0c;我们主要重点介绍两个&#xff1a;选择器和盒子模型就够用了。这里看个乐就好了&#xff0c;没有那么多重点&#xff0c;只是简单的认识一下下CSS。 CSS 是什么 CSS 是层叠样式表 (Cascading Style Sheets)的缩写它存在的意义就是&#xf…...

Maven(1)--- Maven入门指南

当然&#xff0c;我可以为你提供Maven的详细介绍&#xff0c;并按照6篇文章的方式进行详细展开。下面是第一篇的内容&#xff0c;采用Markdown格式输出&#xff1a; Maven入门指南 什么是Maven&#xff1f; Maven是一个强大的项目管理工具&#xff0c;被广泛应用于Java项目开…...

C# 实现 Websocket通讯聊天 (管用、超好使,点个赞)

1、背景 WebSocket出现之前&#xff0c;Web端为了实现即时通讯&#xff0c;所用的技术都是Ajax轮询(polling)。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP request&#xff0c;然后由服务器返回最新的数据给客服端的浏览器…...

知识点回顾(一)

1.final,finally ,finalize final?修饰符&#xff08;关键字&#xff09;如果一个类被声明为final&#xff0c;意味着它不能再派生出新的子类&#xff0c;不能作为父类被继承。因此一个类不能既被声明为 abstract的&#xff0c;又被声明为final的。将变量或方法声明为final&…...

verflow属性的常用值详解

什么是overflow 在CSS中&#xff0c;overflow是“溢出”的意思&#xff0c;该属性规定当内容溢出元素框时发生的事情&#xff0c;设置内容是否会被修剪&#xff0c;溢出部分是否会被隐藏&#xff1b;例如当属性值设置为“visible”则内容不会被修剪&#xff0c;为“hidden”则内…...

算法怎么算:贪心算法

总有人在小白面前说&#xff1a;我是搞算法的&#xff0c;不是码农。又或者在想要进阶的时候&#xff0c;有人问你&#xff1a;你懂算法吗&#xff1f; 所有&#xff0c;算法到底是什么&#xff1f; 从目的性来说&#xff1a;它是计算方法&#xff0c;用来达到自己目的的方式…...