Vim 使用配置指南

Vim 编辑器可以说在程序员届中享有盛誉,其丰富强大的插件和灵活的移动也使得开发起来事半功倍;但是 Vim 复杂的配置和极大的学习成本也让很多人望而生畏。
今天就来整理一下如何配置一个 Vim 开发环境环境。

说明

  1. 本人目前主要从事 PHP 开发工作,如果针对其他语言,可能还需要额外的其他配置

Vim 基本知识

Vim 的不同模式

我们知道 Vim 大概分为普通模式、插入模式、输入模式和可视模式,下面简单介绍一下各个模式的基本知识和区别

  1. 普通模式
    打开文件时的默认模式,无论在哪种模式下,按下Esc键就会进入普通模式。在这个模式下,可以移动光标,删除某个字符,删除某行,复制多行,粘贴多行。

下面是在普通模式下的基本快捷键

j 向上移动一行
k 向下移动一行
h 向左移动一格
k 向右移动一格
x 删除光标后的一个字符
dd 剪切光标所在的那一行,并复制
yy 复制光标所在的行
p 粘贴复制的内容
u 还原上一次的操作
ctr + r 回退上一次的还原操作

Vim 普通模式下的命令还有很多,想要熟练使用 Vim,掌握这些命令是必须的

  1. 插入模式
    在正常模式下按下 i 键,也叫插入模式,插入模式里可以进行文字的输入,在该模式下按Esc键切换到普通模式。
  2. 输入模式
    在正常模式下输入 “:” 或 “/” 进入命令行模式,在该模式下可以进行保存、搜索、替换、退出、显示行号等。

搜索

/word 光标之后查找字符串 word,按 n 向后搜索;
?word 光标之前查找字符串 word,按 n 向前搜索;

替换

:n1,n2/word1/word2/g
将 n1 到 n2 行之间的 word1 替换为 word2,不加g则只替换每行的第一个word1;
:1,$s/word1/word2/g
将文章中的 word1 替换为 word2,不加 g 则只替换每行的第一个word1;

其他

:w 保存文本 ;
:w! 强制保存;在root用户下,文件只读也能保存;
:q 退出vim ;
:q! 强制退出;
:wq 保存并退出;
:set nu 显示行号;
:set nonu 不显示行号;

  1. 可视模式

可视模式是选中一块区域进行操作,包括删除、替换、复制、粘贴、改变大小写等。
在正常模式下按 v(小写)进入字符文本,按 V(大写)进入行文本,按ctrl + v 进入块文本。然后使用上下左右键进行操作选中区域。
对选中的部分使用 d 进行删除,y 进行复制,p 进行粘贴,r 进行文本替换,gu 转换为小写,gU 转换为大写,g~ 大小写互换。

基本配置

Vim 配置文件一般是位于个人 home 下的 .vimrc (~/.vimrc)文件,我们的配置 Vim 也主要是针对这个文件进行修改
下面是 Vim 的一些基础配置

"设置字体
set guifont=Consolas:h12:cANSI

"设置搜索高亮 ,取消请使用set nohlsearch
set hlsearch

" 关闭 .swp 文件
set noswapfile

" 显示行号;取消显示可输入 set nonu
set number 

" 突出显示当前行
set cursorline

"去掉讨厌的有关 vim 一致性模式,避免以前版本的一些 bug 和局限.
set nocompatible

"否则无法使用退格键
set backspace=indent,eol,start

"开启语法高亮
syntax on

"设置命令历史记录为10条.
set history=100

"设置替换 tab 键 [缩进]
set expandtab

"设置 tab 键为4个空格.
set tabstop=4
set softtabstop=4

"设置当行之间交错时使用4个空格
set shiftwidth=4

"设置匹配模式,类似当输入一个左括号时会匹配相应的那个右括号
set showmatch

"搜索选项.(比如,键入"/bo",光标自动找到第一个"bo"所在的位置.)
set noincsearch

"字符集
set fileencodings=ucs-bom,utf-8,chinese,cp936

"颜色方案
colorscheme   desert
"colorscheme  peachpuff
"colorscheme  molokai
"colorscheme  ron
"colorscheme  default
"colorscheme  delek

"依据上面的对起格式,智能的选择对起方式,对于类似C语言编.
"set smartindent
"自动缩进
"set autoindent
"C风格缩进
set cindent

"设置文件类型
set filetype=php
"set filetype=go
"set filetype=html

" 用空格键来开关代码折叠
set foldenable
" 手动折叠代码
" set foldmethod=manual
" 按缩进自动折叠代码
" set foldmethod=indent
" 按语法高亮折叠代码
" set foldmethod=syntax
" 按标记折叠代码
set foldmethod=marker

" 设置替换输入,比如通过一下配置,可以通过输入 w3c + 回车,输入后面 HTML 基本模板内容
ab w3c <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><ESC>o<html     xmlns="http://www.w3.org/1999/xhtml"><CR><head><CR><title>1</title><CR><meta http-equiv="Content-Type" content="text/html; charset=utf-8">    <CR><script src="http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js" type="text/javascript"></script><CR><style><CR>body,ul,ol,li,p,h1    ,h2,h3,h4,h5,h6,form,fieldset,td,img,div{margin:0;padding:0;border:0;}<CR>/*,table notice:The table we often usered by develop so we exeges    is,if you publish you software please move on top of style css*/<CR>body{margin-top:0px;}<CR>ul,ol{list-style-type:none;}<CR>select,input,i    mg,select{vertical-align:middle;}<CR>.clearit{clear:both;}<CR></style><CR><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /><CR>    </head><CR><body><CR></body><CR></html><ESC>kO

关于折叠的用法

我们看到 Vim 里面有常用的几个折叠方法,我们来主要介绍一下默认的 manual 折叠方法和 marker 折叠方法

  • manual 手动折叠,并且关闭 Vim 后所有的折叠都会消失
  • marker 标记折叠,按照标记进行折叠,关闭 Vim 后折叠并不会消失(推荐使用)

标记折叠方法使用

  1. 跳转到你要折叠的起始位置
  2. 在普通模式下输入 zf
  3. 跳转到你要折叠的结束位置
  4. 从你要折叠的起始位置到结束位置已经折叠并且标记起来了,并且下次用 Vim 打开文件,折叠依然存在

折叠常用命令
以下折叠的命令均在普通模式下输入

  1. zR 打开所有折叠
  2. zM 关闭所有折叠
  3. zE 删除所有的折叠标签

快捷键配置

快捷键映射是 Vim 的强大功能,下面我们就来看一下 Vim 快捷键映射的相关配置

Vim 快捷键基本知识

  1. Vim 快捷键又叫键盘映射,一般会在用户字自定义快捷键前加一个前置输入,这样可以避免和 Vim 自身的快捷键相互冲突
  2. Vim 设置快捷键有 map、nmap、imap、vmap 等命令,这些都是什么意思呢?

nore 表示非递归。
n 表示在普通模式下生效。
v 表示在可视模式下生效。
i 表示在插入模式下生效。

各个命令生效的模式如下表所示

Command 命令Normal 常规模式Visual 可视化模式Insert Only 插入模式Command Line命令行模式
mapyesyes
map!yesyes
nmapyes
vmapyes
imapyes
cmapyes

快捷键配置

"设置用户快捷键的前置输入为 ,
let mapleader = ","

"定义 mm返回最新修改的位置
map mm '.zz

"退出插入模式
imap <leader>q <ESC>

"F9定义函数和类的注释 文件位置
"下载php-doc.vim  放到  ~/.vim/plugin/php-doc.vim"
inoremap <F9> <ESC>:call PhpDocSingle()<CR>
nnoremap <F9> :call PhpDocSingle()<CR>
vnoremap <F9> :call PhpDocRange()<CR>

"设置行号
map <leader>1 :set nu<ENTER>

"取消设置行号
map <leader>2 :set nonu<ENTER>

"插入HTML注释
map <leader>3 O<!--<ESC>yyp2xA><ESC>ddpk

"以/**/格式注释掉一行
map <leader>4 O/**<ESC>yyp2xA/<ESC>ddpk

"在上一行加分隔线
map <leader>8 O/*------------------------------------------------------------------------*/<ESC>j

"手动折叠
"按大括号包围折叠
nmap <silent> <leader>q f{v%zf
"按中括号包围折叠
nmap <silent> <leader>[ f[v%zf

"切换标签
"向右切换标签
map <leader>w <C-W><C-W>
"向左切换标签
map <leader>e <C-W>h

" 切换 tab
"跳转到上一个 tab
map <leader>a :tabp<CR>
"跳转到下一个 tab
map <leader>f :tabn<CR>

" 管理 buffer
"关闭当前 buffer
nmap <leader>k :bd<CR>
"跳转到上一个 buffer
map <leader>s :bp<CR>
"跳转到下一个 buffer
map <leader>d :bn<CR>

"跳转到行尾回车
nmap <C-\> $a<CR><ESC>
" 当前行向下移动一行
nmap <C-j> ddp
" 当前行向上移动一行
nmap <C-k> dd<Up>P

" 插入模式下的移动快捷键
" 插入模式下移动到行首
inoremap <C-U> <Home>
" 插入模式下移动到行尾
inoremap <C-O> <End>

"插入模式下上下左右移动
inoremap <C-b> <Left>
inoremap <C-l> <Right>
inoremap <C-j> <Down>
inoremap <C-k> <Up>

"插入模式和普通模式下的保存快捷键
nnoremap <C-D> :w<CR>
inoremap <C-D> <ESC>:w<CR>i

"插入模式下代码提示
inoremap <leader>i <C-X><C-l>
inoremap <leader>o <C-X><C-O>

" 利用临时文件来实现复制、粘贴  
" ctrl+v 粘贴
" ctrl+c 复制
" ctrl+x 剪切

imap <C-V> <ESC>:r $HOME/.vim/.vimxfer<CR>i
nmap <C-V> :r $HOME/.vim/.vimxfer<CR>
vmap <C-V> c<ESC>:r $HOME/.vim/.vimxfer<CR>

"必须在可视模式下复制
vmap <C-C> :w! $HOME/.vim/.vimxfer<CR>
"实现ctrl+x 剪切 , 利用vim书签来做
vmap <C-X> ma:w! $HOME/.vim/.vimxfer<CR>V'ad

"因为我们要替换掉ctrl+c为复制, ctrl+v 为粘贴 , 所以重新定义块操作为 ,v
noremap <leader>v <C-V>

"重新定义ZZ , 同时清除复制缓存
map ZZ :!echo "" > $HOME/.vim/.vimxfer<CR>:wq<CR>

说明

  1. 实现利用 ctrl + cctrl + v 来复制、粘贴功能需要在创建 .vimxfer 文件(touch ~/.vim/.vimxfer

插件管理和配置

插件为 Vim 提供了强大的功能,Vim 有许多插件是通过 Vundle 管理的,接下来我们来介绍使用 Vundle 来安装管理插件

安装 Vundle

可以通过如下命令安装 Vundle

git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

Vundle 配置以及基本插件安装

set nocompatible              " be iMproved, required
filetype on                  " required
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'
Plugin 'fatih/vim-go'
Plugin 'godlygeek/tabular'
Plugin 'dgryski/vim-godef'
Plugin 'Blackrush/vim-gocode'
Plugin 'majutsushi/tagbar'
Plugin 'scrooloose/nerdtree'
Bundle 'jistr/vim-nerdtree-tabs'
Plugin 'Xuyuanp/nerdtree-git-plugin'

"React
"Plugin 'pangloss/vim-javascript'
"Plugin 'mxw/vim-jsx'
"Plugin 'jbgutierrez/vim-babel'

"Es6
"Plugin 'tomtom/tlib_vim'
"Plugin 'MarcWeber/vim-addon-mw-utils'
"Plugin 'garbas/vim-snipmate'
"Plugin 'isRuslan/vim-es6'
"Plugin 'cosminadrianpopescu/vim-tail'

"github
"Plugin 'git@github.com:relunctance/vimrc.git'
" 项目中字符或者函数名查找
Plugin 'relunctance/govim-find-func'
"Plugin 'bufexplore.zip'
Plugin 'cscope.vim'

"超级注释插件
Plugin 'tpope/vim-commentary'
call vundle#end()
filetype plugin indent on
"
" Brief help
":BundleList        - 列举列表(也就是.vimrc)中配置的所有插件
":BundleInstall     - 安装列表中的全部插件
":BundleInstall!    - 更新列表中的全部插件
":BundleSearch foo  - 查找foo插件
":BundleSearch! foo - 刷新foo插件缓存
":BundleClean       - 清除列表中没有的插件
":BundleClean!      - 清除列表中没有的插件
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line

做好这些配置之后,便可以在命令行模式下使用 PluginInstall 命令安装插件了

:BundleInstall

vim-plug

现在 Bundle 基本已经废弃了,一般用 vim-plug 来替代(vim-plug)

安装

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

vim-plug 配置

" 插件开始的位置
" 安装 vim-plug curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
"    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
" PlugInstall 安装插件
” 更多的配置见 git 文档
call plug#begin('~/.vim/plug')
set encoding=UTF-8
" 此处放准备安装的插件

" 主题配色
Plug 'morhetz/gruvbox'
" 状态栏插件,包括显示行号,列号,文件类型,文件名,以及Git状态
Last login: Thu Nov 18 14:33:14 2021 from 172.30.19.109
#####################################################
 .vimrc                                                                                                                                buffers
" markdown 预览
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() }, 'for': ['markdown', 'vim-plug']}
" markdown 中 latex 数学公式支持
" Plug 'iamcco/mathjax-support-for-mkdp'

Plug 'fatih/vim-go'
" 不生效,需要再看看
Plug 'AndrewRadev/splitjoin.vim'
Plug 'ctrlpvim/ctrlp.vim'
Plug 'godlygeek/tabular'
Plug 'Blackrush/vim-gocode'
Plug 'majutsushi/tagbar'
Plug 'scrooloose/nerdtree'
Plug 'jistr/vim-nerdtree-tabs'
Plug 'Xuyuanp/nerdtree-git-plugin'
Plug 'neoclide/coc.nvim', {'branch': 'release'}

"github
"项目中字符或者函数名查找
Plug 'relunctance/govim-find-func'

"超级注释插件
Plug 'tpope/vim-commentary'

" PHP 断点调试插件
Plug 'vim-vdebug/vdebug'

" 插件结束的位置,插件全部放在此行上面
call plug#end()

下面介绍一些重要插件以及其相关的快捷键

注释插件 tpope/vim-commentary

tpope/vim-commentary 是一款为代码添加注释的插件,下面是其相关配置

"vim-commentary
"gcc     注释当前行(普通模式)或者取消注释当前行
"gc      可视模式下,注释当前选中的部分,或者取消当前选中部分的注释
"gcu     撤销上一次注释的部分,可以是一行也可以是多行
"gcgc    撤销注释当前行和邻近的上下两行
"为python和shell等添加注释
autocmd FileType python,shell,coffee set commentstring=#\ %s
"修改注释风格
autocmd FileType java,php,go,c,cpp set commentstring=//\ %s

目录树插件 NerdTree

目录树插件 NerdTree 可以在左侧栏列出当前文件所在的目录树并管理文件和目录,类似IDE,可大大提高开发效率,实现效果如下:在这里插入图片描述
NerdTree 插件可以通过 Vundle 安装,下面我们来看一下插件的基本配置和用法

"NERD Tree
let NERDChristmasTree=1
let NERDTreeAutoCenter=1
let NERDTreeBookmarksFile= $HOME . '/.vim/bookmark.txt'     "书签保存位置,需要手动创建
let NERDTreeMouseMode=2
let NERDTreeShowBookmarks=1
let NERDTreeShowFiles=1
let NERDTreeShowHidden=1
let NERDTreeQuitOnOpen=1
let NERDTreeShowLineNumbers=1
let NERDTreeWinPos='left'                   "设置目录标签位置
let NERDTreeWinSize=40                    "设置目录标签宽度
nmap <silent> <leader>t :NERDTreeToggle<CR>    "关闭打开目录标签快捷键

NerdTree 常用命令

t : 在新 Tab 中打开选中文件/书签,并跳到新 Tab
T : 在新 Tab 中打开选中文件/书签,但不跳到新 Tab
i : split 一个新窗口打开选中文件,并跳到该窗口
gi : split 一个新窗口打开选中文件,但不跳到该窗口
s : vsplit 一个新窗口打开选中文件,并跳到该窗口
gs : vsplit 一个新 窗口打开选中文件,但不跳到该窗口
! : 执行当前文件
O : 递归打开选中 结点下的所有目录
x : 合拢选中结点的父目录
X : 递归 合拢选中结点下的所有目录
P : 跳到根结点
p : 跳到父结点
K : 跳到当前目录下同级的第一个结点
J : 跳到当前目录下同级的最后一个结点
k : 跳到当前目录下同级的前一个结点
j : 跳到当前目录下同级的后一个结点
u : 将当前根结点的父目录设为根目录,并变成合拢原根结点
U : 将当前根结点的父目录设为根目录,但保持展开原根结点
r : 递归刷新选中目录
R : 递归刷新根结点
m : 显示文件系统菜单,用于新建目录、文件
A : Zoom (maximize-minimize) the NERDTree window
? : 切换是否显示 Quick Help

以上命令需要在普通模式下,移动光标到 NerdTree 的窗口直接输入就可以

代码导航插件 Tagbar

Tagbar 是一款 Vim 下常用的代码函数、变量导航插件,效果如下图所示
在这里插入图片描述
使用这个插件需要安装 ctags 软件,并生成代码导航的 tags 文件

插件配置
在 vim 配置文件里面,我们需要对插件进行如下简单的配置

" Tag list (tagbar)
"
" 使用tagbar
" tagbar 关闭打开快捷键
nmap <silent> <leader>g :TagbarToggle<CR>
let g:tagbar_ctags_bin = '/usr/bin/ctags'
let g:tagbar_width = 60

插件常用命令

ctrl+n : Go to next top-level tag
ctrl+p : Go to previous top-level tag
x : Zoom window in/out
? : Toggle help

ctags 安装与使用

ctags(Generate tag files for source code)是 vim 下方便代码阅读的工具,它可以在命令行下帮助程序员很容易地浏览源代码。ctags 最先是用来生成 C 代码的 tags 文件,后来扩展成可以生成各类语言的 tags , 有些语言也有专有的 tags 生成工具(比如java的jtags, python的 ptags).

安装 ctags 软件

//centos 安装
yum install ctags

生成 tags 文件
在你的代码根目录下,运行如下代码

ctags --languages=PHP -R .

ctags 常用命令

ctrl+ ] 跳到光标所在函数或者结构体的定义处
ctrl+ o 返回之前的跳转
ctrl + i 回退 ctrl+ o 的跳转

GIT 文件状态插件 Xuyuanp/nerdtree-git-plugin

nerdtree-git-plugin 插件可以在 NerdTree 插件展示的文件树窗口上显示文件的 GIT 状态,只要经过以下配置就可以使用

let g:NERDTreeIndicatorMapCustom = {
    \ "Modified"  : "✹",
    \ "Staged"    : "✚",
    \ "Untracked" : "✭",
    \ "Renamed"   : "➜",
    \ "Unmerged"  : "═",
    \ "Deleted"   : "✖",
    \ "Dirty"     : "✗",
    \ "Clean"     : "✔︎",
    \ 'Ignored'   : '☒',
    \ "Unknown"   : "?"
    \ }

Go 语言开发插件

vim-go 是 go 相关的必备插件,下面是相关配置

"-------------------------------------vim-go------------------------------------------
" https://github.com/fatih/vim-go
" https://github.com/fatih/vim-go-tutorial  # vim-go 官方教程,最好过一遍
"
" :GoInstallBinaries 安装 vim-go 所需工具
" :GoDecls 函数搜索
" :GoDeclsDir 函数搜索
" :GoDef (或ctrl+]) 跳转到定义,但是如果是接口实现只能跳转到 interface 定义而非 struct 实现。
" 跳转到接口的实现 https://github.com/fatih/vim-go/issues/820
" :GoCallees 从函数调用处跳转到接口的真正实现,而不是接口定义 (在方法调用点使用 -> struct 方法实现列表)
" :GoCallers 找到当前函数被调用的地点
" :GoImplements 列出 struct 实现的接口

" # 常用的方便命令(命令模式Tab补全), 参考 https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt
" :GoRun, GoTest, GoTestFunc 运行代码和单测
" :GoImpl 为 struct 生成接口函数定义(光标放到struct定义上使用)。如果一个 interface 有很多需要实现的函数,比较方便
" :GoAddTags GoRemoveTags json 快速给 struct field 增加 json tag,支持 visual 模式多选。默认 tag 名是下划线命名
" :GoKeyify 把无名称初始化的 struct literals 转成包含字段名的初始化方式
" :GoIfErr 生成 if err 返回值(或者用 snippets)
" :GoChannelPeers 寻找可能的 channel 发送和接收点
" :GoFillStruct 给一个 struct 填充默认值
"
" :GoRename 快速重构, 修改函数,field 名
" :GoFreevars 查看选中区域的自由变量
" :GoGenerate 运行 go generate
"
" let g:go_def_mode='godef'  # 有时候 gopls 有问题可以用 godef 跳转,默认用 gopls
" let g:go_def_mode = 'godef'
let g:go_list_type = "quickfix"
let g:go_fmt_command = "goimports"
let g:go_decls_includes = "func,type"
" 自动显示函数信息
let g:go_auto_type_info = 1
set updatetime=100

" 开启自动寻找
let g:go_auto_sameids = 0

autocmd FileType go nmap <leader>b  <Plug>(go-build)
autocmd FileType go nmap <leader>r  <Plug>(go-run)
map <C-n> :cnext<CR>
map <C-m> :cprevious<CR>

autocmd FileType go nmap <leader>gt <Plug>(go-test)
autocmd FileType go nmap <leader>gtf <Plug>(go-test-func)
autocmd FileType go nmap <Leader>i <Plug>(go-describe)

autocmd Filetype go command! -bang A call go#alternate#Switch(<bang>0, 'edit')
autocmd Filetype go command! -bang AV call go#alternate#Switch(<bang>0, 'vsplit')
autocmd Filetype go command! -bang AS call go#alternate#Switch(<bang>0, 'split')
autocmd Filetype go command! -bang AT call go#alternate#Switch(<bang>0, 'tabe')

" run :GoBuild or :GoTestCompile based on the go file
function! s:build_go_files()
  let l:file = expand('%')
  if l:file =~# '^\f\+_test\.go$'
    call go#test#Test(0, 1)
  elseif l:file =~# '^\f\+\.go$'
    call go#cmd#Build(0)
  endif
endfunction

autocmd FileType go nmap <leader>b :<C-u>call <SID>build_go_files()<CR>
"Text objects
"if 函数内快
"af 函数外快
"

代码自动补全插件

之前我代码自动补全用的是 YCM,虽然也挺好用,但是装起来真的太费劲,后来发现可一个最新的代码补全插件coc,真的是太香了,支持不同的语言,最主要是安装配置简单,使用 vim-plug 就可以安装配置

coc 配置

"
" ======================== coc.nvim 插件配置 ======================
" 详细见 https://github.com/neoclide/coc.nvim#example-vim-configuration
" 不清楚作用,推荐配置里面有,详细见 https://github.com/neoclide/coc.nvim/issues/649
set nobackup
set nowritebackup
" 为消息留出更多的空间
set cmdheight=2

let g:coc_global_extensions = ['coc-json', 'coc-tsserver', 'coc-go', 'coc-sh', 'coc-snippets', 'coc-git', 'coc-phpls']

" 追踪到定义的位置
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
" 查看被谁引用
nmap <silent> gr <Plug>(coc-references)

" 预览窗口显示文档
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  elseif (coc#rpc#ready())
    call CocActionAsync('doHover')
  else
    execute '!' . &keywordprg . " " . expand('<cword>')
  endif
endfunction

autocmd CursorHold * silent call CocActionAsync('highlight')

" 重命名的快捷操作
nmap <leader>rn <Plug>(coc-rename)

" 关闭提示后手动唤醒提示
inoremap <silent><expr> <c-l> coc#refresh()

代码自动报错提示

普通 IDE 都有代码语法错误提示,那么 Vim 怎么实现这个功能呢,我们可以通过下面的配置实现

"定义检测 PHP 语法是否正确的函数
function! CompilePHP()
    let file = shellescape(expand('%:p'))
    let command = "silent !php72 -l " . file
    execute command
    if v:shell_error != 0
        silent !clear
        let command = "!php72 -l " . file
        execute command
    else
        redraw!
    endif
endfunction

"配置以 .php 文件结尾的文件保存的时候调用 CompilePHP 函数
autocmd BufWritePost *.php call CompilePHP()

"定义检测 shell 脚本的函数
function! CompileShell()
    let file = shellescape(expand('%:p'))
    let command = "silent !sh -n " . file
    execute command
    if v:shell_error != 0
        silent !clear
        let command = "!sh -n " . file
        execute command
    else
        redraw!
    endif
endfunction

"配置 .sh 结尾的文件保存的时候自动调用 CompileShell 函数
autocmd BufWritePost *.sh call CompileShell()

总结

下面将本文讲到的配置整理如下

"设置字体
set guifont=Consolas:h12:cANSI

"设置搜索高亮 ,取消请使用set nohlsearch
set hlsearch

" 关闭 .swp 文件
set noswapfile

" 显示行号;取消显示可输入 set nonu
set number

" 突出显示当前行
set cursorline

"去掉讨厌的有关 vim 一致性模式,避免以前版本的一些 bug 和局限.
set nocompatible

"否则无法使用退格键
set backspace=indent,eol,start

"开启语法高亮
syntax on

"设置命令历史记录为10条.
set history=100

"设置替换 tab 键 [缩进]
set expandtab

"设置 tab 键为4个空格.
set tabstop=4
set softtabstop=4

"设置当行之间交错时使用4个空格
set shiftwidth=4

"设置匹配模式,类似当输入一个左括号时会匹配相应的那个右括号
set showmatch

"搜索选项.(比如,键入"/bo",光标自动找到第一个"bo"所在的位置.)
set noincsearch

"字符集
set fileencodings=ucs-bom,utf-8,chinese,cp936


"依据上面的对起格式,智能的选择对起方式,对于类似C语言编.
"set smartindent
"自动缩进
"set autoindent
"C风格缩进
set cindent

"设置文件类型
" set filetype=php
set filetype=go
"set filetype=html

" 用空格键来开关代码折叠
set foldenable
" 手动折叠代码
" set foldmethod=manual
" 按缩进自动折叠代码
" set foldmethod=indent
" 按语法高亮折叠代码
" set foldmethod=syntax
" 按标记折叠代码
set foldmethod=marker

" Vim has a setting called autowrite that writes the content of the file automatically if you call :make
set autowrite

" 设置替换输入,比如通过一下配置,可以通过输入 w3c + 回车,输入后面 HTML 基本模板内容
ab w3c <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><ESC>o<html     xmlns="http://www.w3.org/1999/xhtml"><CR><head><CR><title>1</title><CR><meta http-equiv="Content-Type" content="text/html; charset=utf-8">    <CR><script src="http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js" type="text/javascript"></script><CR><style><CR>body,ul,ol,li,p,h1    ,h2,h3,h4,h5,h6,form,fieldset,td,img,div{margin:0;padding:0;border:0;}<CR>/*,table notice:The table we often usered by develop so we exeges    is,if you publish you software please move on top of style css*/<CR>body{margin-top:0px;}<CR>ul,ol{list-style-type:none;}<CR>select,input,i    mg,select{vertical-align:middle;}<CR>.clearit{clear:both;}<CR></style><CR><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /><CR>    </head><CR><body><CR></body><CR></html><ESC>kO

"快捷键配置
"设置用户快捷键的前置输入为 ,
let mapleader = ","

" 插件开始的位置
" 安装 vim-plug curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
"    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
call plug#begin('~/.vim/plug')
set encoding=UTF-8
" 此处放准备安装的插件

" 主题配色
Plug 'morhetz/gruvbox'
" 状态栏插件,包括显示行号,列号,文件类型,文件名,以及Git状态
Plug 'vim-airline/vim-airline'
" 状态栏目插件的主题,使用后可以使颜色看起来更加突出一点
Plug 'vim-airline/vim-airline-themes'
" 可以在导航中显示图标, 不过需要有字体支持,否则就是乱码
" https://github.com/ryanoasis/nerd-fonts
" 终端也需要字体配合,如我使用的是 firacode nerd font Regular
" 喜欢其他字体也可以,不过要使用带 nerd font 的字体
" Plug 'ryanoasis/vim-devicons'
" 可以在文档中显示 git 信息
Plug 'airblade/vim-gitgutter'
" markdown 预览
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() }, 'for': ['markdown', 'vim-plug']}
" markdown 中 latex 数学公式支持
" Plug 'iamcco/mathjax-support-for-mkdp'

Plug 'fatih/vim-go'
" 不生效,需要再看看
Plug 'AndrewRadev/splitjoin.vim'
Plug 'ctrlpvim/ctrlp.vim'
Plug 'godlygeek/tabular'
Plug 'Blackrush/vim-gocode'
Plug 'majutsushi/tagbar'
Plug 'scrooloose/nerdtree'
Plug 'jistr/vim-nerdtree-tabs'
Plug 'Xuyuanp/nerdtree-git-plugin'
Plug 'neoclide/coc.nvim', {'branch': 'release'}

"github
"项目中字符或者函数名查找
Plug 'relunctance/govim-find-func'

"超级注释插件
Plug 'tpope/vim-commentary'

" PHP 断点调试插件
Plug 'vim-vdebug/vdebug'

" 插件结束的位置,插件全部放在此行上面
call plug#end()

"-------------------------------------vdebug------------------------------------------
let g:vdebug_options = {
\    'timeout' : 200,
\    'server' : '',
\    'port' : 9100,
\    'on_close' : 'stop',
\    'break_on_open' : 1,
\    'ide_key' : '',
\    'debug_window_level' : 0,
\    'debug_file_level' : 0,
\    'debug_file' : '',
\    'path_maps' : {'{serverpath}': '{localpath}'},
\    'watch_window_style' : 'expanded',
\    'marker_default' : '⬦',
\    'marker_closed_tree' : '▸',
\    'marker_open_tree' : '▾',
\    'sign_breakpoint' : '▷',
\    'sign_current' : '▶',
\    'continuous_mode'  : 1,
\    'simplified_status': 1,
\    'layout': 'vertical',
\}

" let g:vdebug_keymap = {
" \    "run" : "<F5>",
" \    "run_to_cursor" : "<F9>",
" \    "step_over" : "<F2>",
" \    "step_into" : "<F3>",
" \    "step_out" : "<F4>",
" \    "close" : "<F6>",
" \    "detach" : "<F7>",
" \    "set_breakpoint" : "<F10>",
" \    "get_context" : "<F11>",
" \    "eval_under_cursor" : "<F12>",
" \    "eval_visual" : "<Leader>e",
" \}
"
let g:vdebug_keymap = {
\    "run" : "<Leader>/",
\    "step_over" : "3",
\    "run_to_cursor" : "4",
\    "step_into" : "5",
\    "step_out" : "6",
\    "detach" : "7",
\    "eval_under_cursor" : "8",
\    "eval_visual" : "9",
\    "close" : "0",
\    "set_breakpoint" : "<Leader>b",
\    "get_context" : "<leader>c"
\}

"-------------------------------------vim-go------------------------------------------
" https://github.com/fatih/vim-go
" https://github.com/fatih/vim-go-tutorial  # vim-go 官方教程,最好过一遍
"
" :GoInstallBinaries 安装 vim-go 所需工具
" :GoDecls 函数搜索
" :GoDeclsDir 函数搜索
" :GoDef (或ctrl+]) 跳转到定义,但是如果是接口实现只能跳转到 interface 定义而非 struct 实现。
" 跳转到接口的实现 https://github.com/fatih/vim-go/issues/820
" :GoCallees 从函数调用处跳转到接口的真正实现,而不是接口定义 (在方法调用点使用 -> struct 方法实现列表)
" :GoCallers 找到当前函数被调用的地点
" :GoImplements 列出 struct 实现的接口

" # 常用的方便命令(命令模式Tab补全), 参考 https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt
" :GoRun, GoTest, GoTestFunc 运行代码和单测
" :GoImpl 为 struct 生成接口函数定义(光标放到struct定义上使用)。如果一个 interface 有很多需要实现的函数,比较方便
" :GoAddTags GoRemoveTags json 快速给 struct field 增加 json tag,支持 visual 模式多选。默认 tag 名是下划线命名
" :GoKeyify 把无名称初始化的 struct literals 转成包含字段名的初始化方式
" :GoIfErr 生成 if err 返回值(或者用 snippets)
" :GoChannelPeers 寻找可能的 channel 发送和接收点
" :GoFillStruct 给一个 struct 填充默认值
"
" :GoRename 快速重构, 修改函数,field 名
" :GoFreevars 查看选中区域的自由变量
" :GoGenerate 运行 go generate
"
" let g:go_def_mode='godef'  # 有时候 gopls 有问题可以用 godef 跳转,默认用 gopls
" let g:go_def_mode = 'godef'
let g:go_list_type = "quickfix"
let g:go_fmt_command = "goimports"
let g:go_decls_includes = "func,type"
" 自动显示函数信息
let g:go_auto_type_info = 1
set updatetime=100

" 开启自动寻找
let g:go_auto_sameids = 0

autocmd FileType go nmap <leader>b  <Plug>(go-build)
autocmd FileType go nmap <leader>r  <Plug>(go-run)
map <C-n> :cnext<CR>
map <C-m> :cprevious<CR>

autocmd FileType go nmap <leader>gt <Plug>(go-test)
autocmd FileType go nmap <leader>gtf <Plug>(go-test-func)
autocmd FileType go nmap <Leader>i <Plug>(go-describe)

autocmd Filetype go command! -bang A call go#alternate#Switch(<bang>0, 'edit')
autocmd Filetype go command! -bang AV call go#alternate#Switch(<bang>0, 'vsplit')
autocmd Filetype go command! -bang AS call go#alternate#Switch(<bang>0, 'split')
autocmd Filetype go command! -bang AT call go#alternate#Switch(<bang>0, 'tabe')

" run :GoBuild or :GoTestCompile based on the go file
function! s:build_go_files()
  let l:file = expand('%')
  if l:file =~# '^\f\+_test\.go$'
    call go#test#Test(0, 1)
  elseif l:file =~# '^\f\+\.go$'
    call go#cmd#Build(0)
  endif
endfunction

autocmd FileType go nmap <leader>b :<C-u>call <SID>build_go_files()<CR>
"Text objects
"if 函数内快
"af 函数外快
"
"-------------------------------------AndrewRadev/splitjoin.vim------------------------------------------
"Now type gS. This will split the struct expression into multiple lines.
"And you can even reverse it. If your cursor is still on the foo variable, execute gJ in normal mode.
" ======================== 主题配色设置 ===========================
" 开启24bit的颜色,开启这个颜色会更漂亮一些
set termguicolors
" 主题配色
colorscheme gruvbox
" 主题背景 dark-深色; light-浅色
set background=dark
"颜色方案
"colorscheme   desert
"colorscheme  peachpuff
"colorscheme  molokai
"colorscheme  ron
"colorscheme  default
"colorscheme  delek
" =================================================================
"
"
"======================== vim-airline 插件配置 ===================
" 状态栏目使用主题, 还可以使用 dark, simple, solarized light 等
" 更多主题 https://github.com/vim-airline/vim-airline/wiki/Screenshots
let g:airline_theme='dark'
" 安装字体后,启用这个选项后在状态栏可以看到图标
" 需要先安装 powerline 字体才可以 sudo apt-get install fonts-powerline
" 如果没有安装 powerline 字体不要启用这个选项,否则会显示乱码
" 如果 vim-devicons 插件配置好了就可以忽略 powerline 字体,这个插件包含
" 了字体图标,并且更加漂亮
" let g:airline_powerline_fonts = 1

" 启动顶部的 tabline , 可以显示打开的 buffers, 显示多 tab 标签
let g:airline#extensions#tabline#enabled = 1

" " 设置切换 tab 标签(buffer)的快捷键
" let g:airline#extensions#tabline#buffer_idx_mode = 1
"  nmap <leader>1 <Plug>AirlineSelectTab1
"  nmap <leader>2 <Plug>AirlineSelectTab2
"  nmap <leader>3 <Plug>AirlineSelectTab3
"  nmap <leader>4 <Plug>AirlineSelectTab4
"  nmap <leader>5 <Plug>AirlineSelectTab5
"  nmap <leader>6 <Plug>AirlineSelectTab6
"  nmap <leader>7 <Plug>AirlineSelectTab7
"  nmap <leader>8 <Plug>AirlineSelectTab8
"  nmap <leader>9 <Plug>AirlineSelectTab9
"  nmap <leader>0 <Plug>AirlineSelectTab0
"  nmap <leader>h <Plug>AirlineSelectPrevTab
"  nmap <leader>l <Plug>AirlineSelectNextTab
" =================================================================
"
" ======================== markdwon 插件配置 ======================
" 更多的配置见 https://github.com/iamcco/markdown-preview.nvim
" vim 打开markdown 文档是否自动预览, 0 - 否, 1 - 是, 默认: 0
" let g:mkdp_auto_start = 1

" 关闭 markdown 是否自动关闭预览文件, 0 - 否, 1 - 是, 默认: 1
" let g:mkdp_auto_close = 1

" 在启动 markdown 预览时是否在终端回显 url
" 如显示: Preview page: http://127.0.0.1:8472/page/1
let g:mkdp_echo_preview_url = 1

" markdwon 的快捷键
map <silent> <F5> <Plug>MarkdownPreview
map <silent> <F6> <Plug>StopMarkdownPreview
" =================================================================
"
" ======================== coc.nvim 插件配置 ======================
" 详细见 https://github.com/neoclide/coc.nvim#example-vim-configuration
" 不清楚作用,推荐配置里面有,详细见 https://github.com/neoclide/coc.nvim/issues/649
set nobackup
set nowritebackup
" 为消息留出更多的空间
set cmdheight=2

let g:coc_global_extensions = ['coc-json', 'coc-tsserver', 'coc-go', 'coc-sh', 'coc-snippets', 'coc-git', 'coc-phpls']

" 追踪到定义的位置
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
" 查看被谁引用
nmap <silent> gr <Plug>(coc-references)

" 预览窗口显示文档
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  elseif (coc#rpc#ready())
    call CocActionAsync('doHover')
  else
    execute '!' . &keywordprg . " " . expand('<cword>')
  endif
endfunction

autocmd CursorHold * silent call CocActionAsync('highlight')

" 重命名的快捷操作
nmap <leader>rn <Plug>(coc-rename)

" 关闭提示后手动唤醒提示
inoremap <silent><expr> <c-l> coc#refresh()
"
"-------------------------------------vim-commentary----------------------------------
"gcc     注释当前行(普通模式)或者取消注释当前行
"gc      可视模式下,注释当前选中的部分,或者取消当前选中部分的注释
"gcu     撤销上一次注释的部分,可以是一行也可以是多行
"gcgc    撤销注释当前行和邻近的上下两行
"为python和shell等添加注释
autocmd FileType python,shell,coffee set commentstring=#\ %s
"修改注释风格
autocmd FileType java,php,go,c,cpp set commentstring=//\ %s

"------------------------------------------NERD Tree-----------------------------------
let NERDChristmasTree=1
let NERDTreeAutoCenter=1
let NERDTreeBookmarksFile= $HOME . '/.vim/bookmark.txt'     "书签保存位置,需要手动创建
let NERDTreeMouseMode=2
let NERDTreeShowBookmarks=1
let NERDTreeShowFiles=1
let NERDTreeShowHidden=1
let NERDTreeQuitOnOpen=1
let NERDTreeShowLineNumbers=1
let NERDTreeWinPos='left'                   "设置目录标签位置
let NERDTreeWinSize=40                    "设置目录标签宽度
nmap <silent> <leader>t :NERDTreeToggle<CR>    "关闭打开目录标签快捷键

" ------------------------------——-----Tag list (tagbar)--------------------------------------
"
" 使用tagbar
" tagbar 关闭打开快捷键
nmap <silent> <leader>g :TagbarToggle<CR>
let g:tagbar_ctags_bin = '/usr/bin/ctags'
let g:tagbar_width = 60

" ------------------------------——-----bufferhint--------------------------------------
nnoremap - :call bufferhint#Popup()<CR>
nnoremap \ :call bufferhint#LoadPrevious()<CR>
"-----------------------------------nerdtree-git-plugin-----------------------------------------
let g:NERDTreeGitStatusIndicatorMapCustom = {
    \ "Modified"  : "✹",
    \ "Staged"    : "✚",
    \ "Untracked" : "✭",
    \ "Renamed"   : "➜",
    \ "Unmerged"  : "═",
    \ "Deleted"   : "✖",
    \ "Dirty"     : "✗",
    \ "Clean"     : "✔︎",
    \ 'Ignored'   : '☒',
    \ "Unknown"   : "?"
    \ }

autocmd BufEnter Nerd_tree_* NERDTreeRefreshRoot


" 代码报错提示
"定义检测 PHP 语法是否正确的函数
function! CompilePHP()
    let file = shellescape(expand('%:p'))
    let command = "silent !php74 -l " . file
    execute command
    if v:shell_error != 0
        silent !clear
        let command = "!php74 -l " . file
        execute command
    else
        redraw!
    endif
endfunction

"配置以 .php 文件结尾的文件保存的时候调用 CompilePHP 函数
autocmd BufWritePost *.php call CompilePHP()

"定义检测 shell 脚本的函数
function! CompileShell()
    let file = shellescape(expand('%:p'))
    let command = "silent !sh -n " . file
    execute command
    if v:shell_error != 0
        silent !clear
        let command = "!sh -n " . file
        execute command
    else
        redraw!
    endif
endfunction

"配置 .sh 结尾的文件保存的时候自动调用 CompileShell 函数
autocmd BufWritePost *.sh call CompileShell()

"定义 mm返回最新修改的位置
map mm '.zz

"退出插入模式
imap <leader>q <ESC>

"设置行号
map <leader>1 :set nu<ENTER>

"取消设置行号
map <leader>2 :set nonu<ENTER>

"插入HTML注释
map <leader>3 O<!--<ESC>yyp2xA><ESC>ddpk

"以/**/格式注释掉一行
map <leader>4 O/**<ESC>yyp2xA/<ESC>ddpk

"在上一行加分隔线
map <leader>8 O/*------------------------------------------------------------------------*/<ESC>j

"手动折叠
"按大括号包围折叠
"nmap <silent> <leader>q f{v%zf
""按中括号包围折叠
"nmap <silent> <leader>[ f[v%zf

"切换标签
"向右切换标签
map <leader>w <C-W><C-W>
"向左切换标签
map <leader>e <C-W>h

" 切换 tab
"跳转到上一个 tab
map <leader>a :tabp<CR>
"跳转到下一个 tab
map <leader>f :tabn<CR>

" 管理 buffer
"关闭当前 buffer
nmap <leader>k :bd<CR>
"跳转到上一个 buffer
map <leader>s :bp<CR>
"跳转到下一个 buffer
map <leader>d :bn<CR>

"跳转到行尾回车
nmap <C-\> $a<CR><ESC>

" 向下移动10行
nmap <C-j> 10j
" 向上移动10行
nmap <C-k> 10k
" 向左移动5格
nmap <C-h> 5h
" 向右移动5格
nmap <C-l> 5l

" 插入模式下的移动快捷键
" 插入模式下移动到行首
inoremap <C-U> <Home>
" 插入模式下移动到行尾
inoremap <C-O> <End>

"插入模式下上下左右移动
inoremap <C-b> <Left>
inoremap <C-l> <Right>
inoremap <C-j> <Down>
inoremap <C-k> <Up>

"插入模式和普通模式下的保存快捷键
nnoremap <C-D> :w<CR>
inoremap <C-D> <ESC>:w<CR>i

" 全选当前文档
nmap <leader>aa ggvG$

"插入模式下代码提示
inoremap <leader>i <C-X><C-l>
inoremap <leader>o <C-X><C-O>

" 利用临时文件来实现复制、粘贴
" ctrl+v 粘贴
" ctrl+c 复制
" ctrl+x 剪切
imap <C-V> <ESC>:r $HOME/.vim/.vimxfer<CR>i
nmap <C-V> :r $HOME/.vim/.vimxfer<CR>
vmap <C-V> c<ESC>:r $HOME/.vim/.vimxfer<CR>

"必须在可视模式下复制
vmap <C-C> :w! $HOME/.vim/.vimxfer<CR>
"实现ctrl+x 剪切 , 利用vim书签来做
vmap <C-X> ma:w! $HOME/.vim/.vimxfer<CR>V'ad

"因为我们要替换掉ctrl+c为复制, ctrl+v 为粘贴 , 所以重新定义块操作为 ,v
noremap <leader>v <C-V>

"重新定义ZZ , 同时清除复制缓存
map ZZ :!echo "" > $HOME/.vim/.vimxfer<CR>:wq<CR>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值