admin 管理员组文章数量: 887021
vim配置与基本操作
这份vim配置主要用于C family的开发与阅读。它面向大型项目,所以以下代码都将以linux kernal为例子展示。除去配置外也将记录一些vim的基本操作,辅助记忆~
1. vim基本配置
首先是一些编码、主题以及缩进的配置。创建一个***~/.vimrc***文件,所有vim相关的配置都可以在这个文件里面设置:
"设置文件编码
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
"设定leader键
let mapleader=','
let g:solarized_termcolors=256
"设置主题
syntax on
set background=dark
colorscheme onehalfdark
"常用主题onedark,xcodelight,xcodedark,xcodewwdc
"gotham,gotham256,solarized
set cursorline
"设置保持历史记录10000
set history=10000
"打开文件时禁止折叠
set nofoldenable
"按照语法高亮进行折叠
set fdm=indent
set display=lastline
" scrolloff控制光标上下的边距为多少时翻页,emmm,说的有点抽象,改改这个数字就很清楚了
set scrolloff=5
set matchtime=2
set matchpairs+=<:>
" 显示行号可以通过在命令行中设置:set nonumber关闭行号。要想永久关闭或者开启就要在vimrc中设置了
set number
set showcmd
set showmatch
" 设置文件不备份,这里被注释掉;
set nobackup
set noundofile
set noswapfile
"set backupext=.bak
"set backupdir=~/.vim/vim_bak/
"语法高亮
set syntax=on
" 去掉输入错误的提示声音
set noeb
" 在处理未保存或只读文件的时候,弹出确认
set confirm
" 自动缩进
set autoindent
set cindent
" 设置tab为四个空格空格代替Tab。空格比起制表符拥有更好的兼容性
" 注意: 插入模式下输入【ctrl+v+i】可以强制输入一个tab
" 针对已经存在的制表符,可以通过:%retab将制表符替换成四个空格
set tabstop=4 " tabstop 表示一个 tab 显示出来是多少个空格的长度,默认8
set softtabstop=4 " softtabstop 表示在编辑模式的时候按退格键的时候退回缩进的长度,当使用 expandtab 时特别有用
set expandtab " 当设置成 expandtab 时,缩进用空格来表示,noexpandtab 则是用制表符表示一个缩进
set autoindent " 自动缩进
set cindent " 自动缩进补充
set shiftwidth=4 " 自动缩进空白字符个数
" 行尾部的空格会显示红色
highlight WhitespaceEOL ctermbg=red guibg=red
match WhitespaceEOL /\s\+$/
" 显示行号
set number
" 历史记录数
set history=1000
"禁止生成临时文件
set nobackup
set noswapfile
"搜索忽略大小写
set ignorecase
set incsearch
set autoread
set autowrite
" 鼠标定位
" 鼠标定位和鼠标拷贝似乎不能共存,按住shift再使用鼠标拷贝
set mouse=a
" 设置光标的形态
" 普通模式下为光标方块,插入模式下为竖线
let &t_SI.="\e[6 q" "SI = INSERT mode
let &t_SR.="\e[4 q" "SR = REPLACE mode
let &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)
" 设置光标颜色
highlight Cursor guifg=white guibg=white
highlight iCursor guifg=white guibg=white
set guicursor=n-v-c:block-Cursor
set guicursor+=i:ver100-iCursor
set guicursor+=n-v-c:blinkon0
set guicursor+=i:blinkwait10
" 垂直分割线颜色
" 就是分页的时候的那条分割线
hi VertSplit guibg=#31312D guifg=#526A83 ctermfg=White ctermbg=Black term=none cterm=none gui=none
关于vim的自带主题可以在/usr/share/vim/vim81/colors
找到。可以在网上搜索自己喜欢的主题,然后将对应的colorscheme.vim文件放在这个文件夹下面,通过在vimrc中colorscheme xxxx
配置对应主题。或者也可以在vim normal模式下面通过命令行colorscheme xxxx
来配置,但是会被vimrc中的配置覆盖,请注意。
因为是在wsl使用的vim,鼠标操作对我还是蛮重要的,就设置了set mouse = a
,就是可以通过鼠标翻页。不过用这个设置之后就不能直接通过鼠标选择然后拷贝了。想要拷贝的话,需要通过鼠标选中然后按住shift再右键即可。但是这样拷贝的话还会把行号和换行符拷贝了,所以还得关掉行号显示,通过:set nonumber
来关掉行号,嘛,换行符就没法子了,不过讲道理拷贝那么多东西直接重定向一下不好么。ubuntu好久没用,但好像是没这么麻烦来着。
有几个设置tab的选项请原样按照上面来进行配置。可以通过再normal模式下:set list
显示制表符和换行符,用:set nolist
关闭。相应效果如下:
换行符显示为**$符号,而制表符显示为^I**符号。通过在normal模式下:%retab
就可以将制表符换成空格了。
还有一个leader键的设置,如上就是let mapleader=','
。这是一个快捷键映射,但是我用的比较少,太多快捷键容易记混,还是更喜欢在normal命令行下敲几个字母。一般有些键盘映射诸如map <leader>wq :wq<CR>
这样的映射啊,前面那个 <leader>就是就是自定义的前缀键了。通过这个键还是可以有很多骚操作的,但其实很多功能现在插件都有集成,不需要那么复杂,详见下面。
2. vim基本操作
VIM的基本模式有许多种,我自己常用的有以下四种。
-
一是normal模式,在这个模式下主要做的是命令行操作。打开vim就会进入normal模式,在任何情况下按ESC都可以进入normal模式。一般而言
:
符号后面接的是一些vim命令,?
和/
后面接的匹配模式。- 对于文件内容的操作,这些基本操作是必须记忆的
命令 效果 :w
:q
:wq
:q!
w是保存文件,q是退出vim,wq是保存并退出,q!是不保存强制退出 :N
N是数字,:N可以跳转到某行 i
o
在normal模式下按i与o可以进入insert模式,注意没有冒号 yy
yG
ygg
yNg
yy拷贝当前光标指向行,yG拷贝当前行到文档末的全部内容,ygg拷贝当前行到文档头的全部内容,yNG拷贝当前行到第N行的内容 p
粘贴( yxx
拷贝的内容或者dxx
删除的内容)ctrl+shift+v
从系统的剪切板中粘贴。ubuntu上面是这样,所以我把wsl的粘贴也配置成这样了 dd
dG
dgg
dNG
类似与y系列操作,不过这是删除操作。dd删除当前行,dG删除当前到文档尾部全部行,dgg删除当前到文档头部全部行,dNG删除当前行到第N行间全部内容。注意这里的删除类似剪切,可以通过p来粘贴刚刚被d指令删除的内容 u
ctrl+r
u
可以撤回,ctrl+r
是反撤回- 跳转,查找与替换。注意查找是用的linux自带的grep,效率比较低,所以如果要在整个项目内查找文本不建议使用内置命令,用riggrep替代之(见下文):
命令 效果 :N
N是行号,:N可以跳转到某行 gg
G
gg跳转至文件头部,G跳转至文件尾部 ctrl+]
g+ctrl+]
跳转到定义,需要ctags支持,见下文 ctrl+t
ctrl+o
两个命令都是跳转回上一个地方。但是ctrl+t只限定tag跳转,也就是通过 ctrl+]
的跳转。而ctrl+o更加通用,像用gg跳到文件头,可以ctrl+o调回来。但是ctrl+o在文件之间的跳转经常有bug…/parttern
?parttern
在当前文件中搜索。/是向下搜索,?是向上搜索。parttern是匹配模式,支持正则表达式(根据vim版本不同支持程度不同,但是通配符基本都会支持的) shift+*
shift+#
在当前文件中查找光标指向的符号 u
ctrl+r
u
可以撤回,ctrl+r
是反撤回:[addr]s/src/dst/[opt]
替换操作,src与dst都是匹配模式,支持一些通配符(根据vim的版本好像有不同,比较老的不支持正则)。命令是把src的内容替换成dst的内容。[addr]限定查找区域, %s
是全局查找,1,ns
表示第1行到第n行,s
表示当前行,.,$s
表示当前行到最后一行。[option]限定替换模式,g
表示替换匹配行中全部匹配内容,为空则只替换第一个匹配单词。如:1,100s/hello/world/g
就是把第1到100行所有的hello替换成world。 查找如图所示。在输入
/
或者?
后进入查找模式,为全匹配查找。该查找中使用了通配符.
。一般查找结果会高亮显示,在找到结果后按回车结束查找。通过n
与N
在查找结果之间跳转。小写的n是跳到下一个查找结果,大写的N与之相反。当然,如果是要在当前文件中查找光标指定的符号,不用/
然后再打一堆字那么麻烦,直接shift+#
就好,然后也可以通过n与N再查找结果之间跳转:
如果想要显示所有匹配的项,该怎么做呢?可以使用:%g/parttern/p
,效果如下:
是熟悉的more界面,这里显示了所有parttern匹配的行,并且可以通过:N
界面跳转。上面那个命令格式和替换指令很像,它的格式是这样的:{range}g/{parttern}/{cmd}
,range和替换指令相同,%g
就是全文查找。cmd默认为p
,也就是:print
,可以在quickfix中打印所有匹配行,其他可以参考help global
。不过后边会使用fzf对他进行替换
3. 多tab与分页:
命令 | 效果 |
---|---|
tabnew path/file | 新建一个tab,在该tab中打开文件 |
tabclose | 关闭当前tab。后边加路径可以关闭指定tab。通过:wq 也可以关闭tab |
tabmove - tabmove + | 左移(右移)tab,可以通过:help tabpage 查看更具体的操作 |
ctrl+pageup,ctrl+pagedown | 在tab之间切换 |
vsplit file split file | 打开文件并且水平/垂直切分窗口 |
ctrl +w +w | 在一个tab内部的不同的窗口之间跳转。包括quickfix,水平切分和垂直切分的窗口都可以通过这样跳转,但是不可以跳转到不同的tab。 |
多tab是我很喜欢的东西,尤其是拿来看代码,可以提供类似opengrok的体验。这里只是简单展示一下效果,tab这东西配合fzf才是真滴牛皮~,效果图如下。上面的一堆tab就像是浏览器里面的tab一样,通过ctrl+翻页键在不同tab间可以切换。多tab功能在vim7后就添加了,泛用性还是很不错的:
4. 杂项:
命令 | 效果 |
---|---|
:terminal | 生成终端,按ctrl+d退出 |
:set line/noline | 显示(不显示)制表符与换行符 |
:set number/nonumber | 显示(不显示)行号 |
:help xxxx | 查阅相关的帮助文档 |
- 二是insert模式,通过在normal模式下面输入i或者o进入insert模式,ESC退回normal模式。insert模式下面的编辑就类似于平时的编辑了,不多叙述。
- 三是visual模式,在normal下输入v、ctrl+v、V进入。三种方法所进入的选择模式不同,具体可以体验一下。在选择了对应的块后,可以对其进行复制、剪切、删除、拷贝操作,与normal上的操作是共同的。如下通过ctrl+r进入visual模式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z4aOiKnG-1635733121802)(img6.png)]
选中块后,按x或者d删除选择内容,按y拷贝选择内容。
- 四是replace模式,进入方式主要有三种,
r
,R
,RG
。r
模式进入单字符替换;R
模式进入多字符替换模式,RG
与R
的区别在于,前者一般将制表符打印为四个空格。但是在上述配置完成后,R
与RG
实际上就拥有了相同的效果。
3. VIM美化
vim美化着实没什么心得。主要就是colorscheme的设置了,上面也已经提过。通过将对应的xxxxxx.vim
拷贝到/usr/share/vim/vimxx/colors/
文件夹下面,然后在vimrc中设置colorscheme xxxxxx
,可以ls查看该文件夹下面有什么主题,vim自带的比较好看的主题有darkblue,其他就一般吧。我比较喜欢的主题是onehalf/vim/colors at master · sonph/onehalf (github),下载对应的onehalfdark.vim文件并按照上面步骤做即可。我装了个airline插件用于美化状态栏,嫌airline卡可以换成更加轻量的lightline。
"===============================================================
"powerline
set laststatus=2
let g:Powerline_symbols='unicode'
"===============================================================
"airline
" tabline,也就是上方的tab列表
let g:airline#extensions#tabline#enabled = 1
" 显示tab的分割
let g:airline#extensions#tabline#show_splits = 0
" 不显示buffer
let g:airline#extensions#tabline#show_buffers = 0
" tab的显示风格
let g:airline#extensions#tabline#alt_sep = 1
let g:airline#extensions#tabline#left_sep = ' '
" 不同tab的左间隔符
let g:airline#extensions#tabline#left_alt_sep = '◀'
let g:airline#extensions#tabline#tab_nr_type = 1 " tab number
let g:airline#extensions#tabline#show_tab_nr = 0
" let g:airline#extensions#tabline#formatter = 'default'
" 只显示文件名字
let g:airline#extensions#tabline#formatter = 'unique_tail'
" 超出长度显示...
let g:airline#extensions#tabline#overflow_marker = '…'
let g:airline_powerline_fonts = 1
" 关闭一堆不需要的
let g:airline#extensions#tabline#buffer_nr_show = 0
let g:airline#extensions#tabline#exclude_preview = 0
"if !exists('g:airline_symbols')
" let g:airline_symbols = {}
"endif
" 设置主题
let g:airline_theme="onedark"
let g:airline_left_sep = '▶'
let g:airline_left_alt_sep = '❯'
let g:airline_right_sep = '◀'
let g:airline_right_alt_sep = '❮'
上面的安装流程使用的是Plug.vim
,这个东西用起来很简单。首先在github上面找到plug.vim,然后把plug.vim拷贝到~/.vim/autoload/
下面,就ok了,~/.vim/auttoload
文件夹里面的插件在vim打开时自带运行。想要安装插件,像下面这样:
"plug插件管理器
call plug#begin('~/.vim/plugged')
"底部状态栏美化
"Plug 'vim-airline/vim-airline'
Plug 'Lokaltog/vim-powerline'
call plug#end()
filetype plugin indent on
想要安装啥就在上面的begin和end中间加一句Plug 'xxxxx'
,然后在命令行执行:PluginInstall
。更新插件的话,就是:PluginUpdate
。删除插件只要把vimrc里面对应的Plug 'xxxxx'
删除,然后执行PluginClean
就可以了。
airline的效果大概就是这样啦,简单但是够用。上面显示tab的名字和数量,每个tab显示tab编号以及文件名。下面会显示行号编码和文件类型什么的。这里本来有git状态显示,但是airline集成的话比较卡顿,所以并没有开启。
4. VIM代码阅览
vim要配合一些额外的部件来进行代码阅读。诸如查找定义,查找声明,查找函数引用,git状态之类。以下列出几个主要的插件以及我平时的使用方式:
1. ctags与cscope
这两兄弟跟随了vim许多年,最大的好处就是兼容性极强,管你服务器是ubuntu14还是20都能用。不过使用体验嘛,emmm,一言难尽,好处是在大型项目上面表现还行,但是ctags是真的有很多定义,尤其是对宏还有C++模板类,是查不出来的,略坑爹。
- 安装
在命令行中安装:
sudo apt install ctags cscope
# cscope兼容ctags
- 配置
" 设置tag跳转快捷键
nnoremap <leader>] g<C-]>
"=================================================================
" cscope
" cscope -Rbq,生成cscope数据库,使用方式类似ctags
" cscope find c name,查找调用该函数的函数
" set quickfix,把信息打到quickfix里面,不过还是全屏好用
" set cscopequickfix=s-,c-,d-,i-,t-,e-
" use both cscope and ctag for 'ctrl-]', ':ta', and 'vim -t'
" set cscopetag
" check cscope for definition of a symbol before checking ctags: set to 1
" if you want the reverse search order.
set csto=0
" add any cscope database in current directory
if filereadable("cscope.out")
cs add cscope.out
" else add the database pointed to by environment variable
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
" show msg when any other cscope db added
set cscopeverbose
" 设置输出文件信息长度,文件路径深度最高为五
:set cspc=5
" 设置输出信息的颜色,这里还需要改进,颜色设置不够显眼
:hi ModeMsg ctermfg=Blue
- 使用
首先在项目根目录下面用下面两个指令生成数据库:
ctags -R
cscope -Rbq
对于C++项目,可以ctags -R --c++-kinds=+px --fields=+iaS --extra=+q
来生成针对C++的tag。这两个指令-R选项都意味着在当前目录下递归生成tag。
这时候在该目录下面就应该出现了相应的tags文件与cscope.out文件,他们是跳转用的键值数据库。然后在根目录直接打开vim,并在normal模式下输入指令
:set tags=rootpath/tags
:cscope add rootpath/cscope.out
很麻烦是吧,所以在vimrc中加入对应的自动执行指令,这样每次打开根目录,就会检查是否存在tags文件与cscope文件,有的话就把他们加进来,没有的话,就没有了。为啥不创建?你创建个试试就知道了,比如在linux2.6的源码库下面创建这两玩意儿,多少得花个好几分钟。要是赶时间岂不是得把电脑砸了~
if filereadable("tags")
set tags+=./tags
endif
if filereadable("cscope.out")
cs add cscope.out
" else add the database pointed to by environment variable
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
经过一系列配置就可以使用了。这俩插件的主要作用就是查找与跳转到定义,以及查找函数被调用处:
-
ctrl+]
:跳转到符号定义,存在多个定义,会从数据库中自己选一个定义跳转过去 -
g+ctrl+]
:跳转到符号定义,存在多个定义,显示在quicktab中,自己可以选择一个 -
ctrl+t
:跳转回上一个地方 -
ctrl+o
:同样是跳转回上一个地方,但是用处更多,比如你用gg跳到文件头了,它也可以给你跳回来。就是用这个有时候跳着跳着就迷失了方向,所以我更喜欢ctrl+t或者buffer
-
[[
:跳转到当前函数头部 -
]]
:跳转到当前函数尾部,还有[]和][两个快捷键,类似的意思,一个是上一个函数尾,一个是下一个函数头 -
因为一般用的都是
g+ctrl+]
那个命令啦,这三个键简直反人类,所以给map一下:
nnoremap <leader>] g<C-]>
,这样直接按,+]
就可以跳转了,效果如下:
将光标移动到对应的符号上,然后按,+]
,就显示出了一堆定义的地方。在下面输入数字来进行跳转。
cscope find c FuncName
:查找调用函数的地方。查找结果和上面类似,当然也可以把该命令映射成快捷键:
nnoremap <leader>c :cs find c <C-R>=expand("<cword>")<CR><CR>
这样只要把光标放到函数上,然后按,+c
,就可以显示调用该函数的地方了,效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tPJifrBR-1635733121804)(img4.png)]
ctags与cscope的组合,配置完快捷键以后使用起来也不算太过麻烦,就像其他IDE也需要导入项目一样,这里无非多敲两命令。蛋疼的是他们两即便组合起来,还是偶尔出现找不到定义的情况(和代码风格也有关系,像linux内核那种到处是宏的地方确实难为他们了)。以及上述效果展示,我也找了一阵子但是只能显示出这种配色,因为它的匹配结果也是通过more来打印的,以后再慢慢改进吧~
2. gtags
gtags名字和上面两很像,就知道它是干啥的了。它是gnu家族的一元,可以对ctags和cscope做不到的进行补充。像ctags可以找到函数定义但是无法找到函数引用,而cscope虽然可以找到函数引用,但是对于C++支持不好,更别说java之类。gtags用处广泛,像是vscode的默认补全就是通过gtags生成的。安装起来很简单,ubuntu下直接安装:
sudo apt install global
gtags是上面两者的补充,所以不应该覆盖而是共存,见配置:
" gtags
set cscopetag " 使用 cscope 作为 tags 命令
set cscopeprg='gtags-cscope' " 使用 gtags-cscope 代替 cscope
"gtags.vim 设置项
let GtagsCscope_Auto_Load = 1
let CtagsCscope_Auto_Map = 1
let GtagsCscope_Quiet = 1
" 并不是禁止了cscope与ctags,gtags是在C++与java方面的补充
在这份配置中gtags兼容了cscope的接口,所以使用方式不变,快捷键也不变,和cscope一样。
3. tagbar与nerdtree
标签列表与文件树,没什么特别好说的,也是两个老插件,相对而言比较容易配置,傻瓜式拷贝就行:
"标签导航插件
Plug 'majutsushi/tagbar'
"文件树
Plug 'preservim/nerdtree'
"================================================================
"tagbar
"设置tagbar使用的ctags的插件,必须要设置对
let g:tagbar_ctags_bin='/usr/bin/ctags'
""设置tagbar的窗口宽度
let g:tagbar_width=35
"设置tagbar的窗口显示的位置,为右边
let g:tagbar_left=0
"打开文件自动 打开tagbar
"autocmd BufReadPost *.cpp,*.c,*.h,*.hpp,*,*.cxx call tagbar#autoopen()
"映射tagbar的快捷键
map <F9> :TagbarToggle<CR>
" 设置焦点在tagbar
let g:tagbar_autofocus=1
"==============================================================
"nerdtree
"vim打开空文件时直接打开文件树
"autocmd StdinReadPre * let s:std_in=1
"autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
"vim打开文件夹时打开文件树
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | exe 'cd '.argv()[0] | endif
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
" 文件树列表显示在左侧
let g:NERDTreeWinPos="left"
" 宽度为30
let g:NERDTreeWinSize=30
" let g:NERDTreeShowLineNumbers=1
" let g:neocomplcache_enable_at_startup = 1
" 将打开文件树的操作映射到F8键
nnoremap <F8> :NERDTreeToggle<cr>
" NERDTress File highlighting
function! NERDTreeHighlightFile(extension, fg, bg, guifg, guibg)
exec 'autocmd filetype nerdtree highlight ' . a:extension .' ctermbg='.a:bg .' ctermfg='. a:fg .' guibg='. a:guibg .' guifg='. a:guifg
exec 'autocmd filetype nerdtree syn match ' . a:extension .' #^\s\+.*'.a:extension .'$#'
endfunction
" 根据文件类型不同做的颜色配置。配合nerdtree的配色插件还蛮多的,做出vscode那种效果也是完全可以做到的
call NERDTreeHighlightFile('cpp', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('cc', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('c', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('h', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('hpp', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('md', 'blue', 'none', '#3366FF', '#151515')
call NERDTreeHighlightFile('json', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('html', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('css', 'cyan', 'none', 'cyan', '#151515')
call NERDTreeHighlightFile('js', 'Red', 'none', '#ffa500', '#151515')
通过F8打开或者关闭标签列表,通过F9打开或者关闭文件树,效果如下:
tagbar生成的tag列表是基于ctags的,通过zc或者zo关闭或者打开对应的列表,这个逻辑与vim类似。nerdtree文件树的root目录是根据vim打开时的位置确定的,可以通过大写的C来切换root目录。按F8或者F9后光标自动会跳转到文件数或者tagbar上,选择对应的tag然后回车就可以跳转到指定位置,然后可以用ctrl+t跳回来。对于文件树呢,它还支持鼠标操作,并且按t可以新建一个tab再跳转,按s为水平分割,i为垂直分割,具体可以看help,总之要比tagbar的功能丰富不少。
4. fzf与ripgrep
和上面两兄弟不同,fzf是新时代的先锋,具备异步,高集成,使用更加人性化诸多特点为一体。它的功能极度丰富,下面只是说一些我自己的探索结果:
- 安装,通过plug来进行。能通过plug安装的插件都是好文明:
sudo apt install fzf ripgrep
" 注意系统中要安装fzf,vim中也要安装
" 因为fzf一开始并不是为了vim而设置的,而是后来兼容的
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
这里还安装了Ripgrep,这是一个文本检索工具,类似于linux自带的grep,不过性能非常强劲,用它来配合fzf事半功倍。此外fzf默认使用linux下的find指令查找文件,也可以对其替换,比如我是用fd
,替换了find,如下:
sudo apt install fd-find
在/etc/profile或者~/.bashrc里面设置全局变量改变fzf的默认行为:
export FZF_DEFAULT_COMMAND="fdfind --exclude={.git,.idea,.vscode,tags} --type f"
# 默认是export FZF_DEFAULT_COMMAND="find"
# 这里用fdfind替换Linux原生find,并且不搜索一些文件/文件夹
- 配置
"fzf
"
" FZF -e name:在当前文件夹下精确匹配搜索文件
" Files name : 在当前文件夹下模糊匹配搜索文件,相当于FZF name
" Tags name :根据ctags生成的tags搜索标签
" Rg name :全文本模糊匹配,需要安装额外工具,详见官方md
" This is the default extra key bindings
" 默认的动作,回车是跳转,ctrl+t是打开一个新的tab然后跳转到指定位置
let g:fzf_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
" Default fzf layout
" - down / up / left / right
let g:fzf_layout = { 'down': '~40%' }
" In Neovim, you can set up fzf window using a Vim command
" let g:fzf_layout = { 'window': 'enew' }
" let g:fzf_layout = { 'window': '-tabnew' }
" let g:fzf_layout = { 'window': '10split enew' }
" Customize fzf colors to match your color scheme
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'hl': ['fg', 'Comment'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
\ 'hl+': ['fg', 'Statement'],
\ 'info': ['fg', 'PreProc'],
\ 'border': ['fg', 'Ignore'],
\ 'prompt': ['fg', 'Conditional'],
\ 'pointer': ['fg', 'Exception'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" Enable per-command history.
" CTRL-N and CTRL-P will be automatically bound to next-history and
" previous-history instead of down and up. If you don't like the change,
" explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS.
let g:fzf_history_dir = '~/.local/share/fzf-history'
" [Buffers] 如果可能跳到已存在窗口
let g:fzf_buffers_jump = 0
" [[B]Commits] 自定义被'git log'使用的选项
let g:fzf_commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
" [Tags] 定义用来产生tag的命令
let g:fzf_tags_command = 'ctags -R'
" [Commands] --expect expression for directly executing the command
let g:fzf_commands_expect = 'alt-enter,ctrl-x'
- 使用
命令 | 效果 |
---|---|
:Files xxxx | 从当前目录开始递归的搜索文件 |
:Rg xxxx | 使用Ripgrep,从当前目录开始递归搜索文本(类似的还有Ag,用的是sliversearch,速度不如Rg) |
:Rg -e xxxx | 使用正则表达式搜索 |
:Tags xxxx | 搜索tags,默认的tags是ctags |
:Buffers | 显示所有已经打开的buffer |
:Lines xxxx | 显示所有匹配的行 |
:Colors | 显示所有的配色主题 |
:HelpTags | 显示所有的帮助文档,这是个很有用的命令,fzf会从man page和vim文件夹中提取对应的help tag |
fzf的所有命令格式都类似,默认都是递归模糊搜索。按回车是跳转到指定位置,ctrl+t是打开一个新的tab再跳转,ctrl+s是打开一个水平分割窗口再跳转。
Files命令可以递归检索文件。一般我会在项目的根目录直接打开vim,然后使用:Files
搜索文件,默认的是进行模糊匹配,加上-e
选项可以用正则和全匹配:
quickfix的左侧是匹配到的文件,右侧是文件的预览窗口,按回车就可以打开文件。或者使用ctrl+t
,可以打开一个新的tab。
:Rg
命令可以快速检索对应的字符串,如果不输入-e
那就是默认模糊搜索。类似的,回车打开匹配处,ctrl+t
打开一个新的tab:
打开新的tab,相关tab的信息显示在右上角,文件路径会被压缩:
Buffers命令可以显示打开过的文件的历史,可以用它快速定位文件:
大部分情况下我会通过ctags与cscope来查找符号定义与符号引用(当然也包括gtags了),通过fzf来查找文件。如果无法找到相关定义,则使用Ripgrep来进行全文本搜索。通过vim的多tab机制以及fzf的buffer功能可以模拟类似浏览器的搜索与跳转体验。
像FZF这样的集成工具还是蛮多的,比如LeaderF,操作也都是类似的,不多加介绍了。LeaderF安装起来更简单,通过plug直接安装,像是没有权限无法安装fzf的话,LeaderF就是挺好的替换选项。
5. Mark.vim
生成高亮标记,在Mark - a little script to highlight several words in different colors simultaneously : vim online下载该插件,然后移动mark.vim到~/.vim/plugin
目录下就可以了。默认的快捷键是<leader>+m
,可以标记(取消标记)一个单词。:Mark
命令取消所有的标记:
" Mark " 打开vim时重置mark
set viminfo='64,<8192,s1024,!,h
效果如下,只要把光标移动到对应单词下面,就可以按<leader>+m标记单词。这个标记在不同的tab之间也会生效:
5. VIM中的C++自动补全与纠错
自动补全
现在C/C++补全以及不再是ycm一家独大,lsp(language server protocol)的出现简化了这方面的配置,像是vscode上面比较流行的基本都是lsp了。vim当然也有lsp,不过我这里还是用ycm,主要是用习惯了,ycm的一些特别的功能也很是有趣。另外,ycm在新近的版本中也实现了异步的补全功能,论性能还是不搓的。
- 安装
最简单的安装方法就是在plug中加上对应的语句,然后执行:PluginInstall
Plug 'ycm-core/YouCompleteMe'
不过因为要上外网,不用特殊方法这样是基本安装不了的。所以用了个取巧的法子(仅限于debian系):
sudo apt install vim-addon-manager
sudo apt install vim-youcompleteme
vim-addons install youcompleteme
这样安装还不够,需要一些额外配置。创建一个~/.ycm_extra_conf.py
文件,我自己的.ycm_extra_conf.py文件如下,对应配置要根据系统修改:
import os
import ycm_core
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-DNDEBUG',
'-std=c++20', # 支持的C++版本
'-x',
'c++',
'-I',
'/usr/include', # 补全所用的头文件
'-isystem',
'/usr/lib/gcc/x86_64-linux-gnu/9/', # 补全所用的头文件
'-isystem',
'-isystem'
'/usr/include/c++/9',
'-isystem',
]
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '', '.c', '.go']
def FlagsForFile( filename, **kwargs ):
return {
'flags': flags,
'do_cache': True
}
- 配置
这份配置是默认配置做了一些修改:
"==============================================================
"YCM
" 每次重新生成匹配项,禁止缓存匹配项
let g:ycm_cache_omnifunc=0
" 在注释中也不能补全
let g:ycm_complete_in_comments=0
" 关闭额外预览窗口
let g:ycm_add_preview_to_completeopt = 0
" 基于syntastic的代码诊断,觉得慢的话可以换成ale,我这里就关掉了
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
" 敲入几个字符开始触发补全
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>'
set completeopt=menu,menuone
let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'
let g:ycm_confirm_extra_conf = 0
noremap <c-z> <NOP>
" 选择补全语言
let g:ycm_semantic_triggers = {
\ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
\ 'cs,lua,javascript': ['re!\w{2}'],
\ }
" ycm补全框颜色
" 不过实际上这是设置了PMenu的高亮,可以通过:help highlight查看已经设置的高亮信息
highlight PMenu ctermfg=0 ctermbg=242 guifg=black guibg=darkgrey
highlight PMenuSel ctermfg=242 ctermbg=8 guifg=darkgrey guibg=black
" ycm获取类型信息
nnoremap ty :YcmCompleter GetType<CR>
配置完成直接使用就可以,ycm还有个有趣的东西就是获取类型信息,但是不够完善,主要可以用来看看模板信息以及auto的类型,上面就把看类型信息的方法映射到快捷键ty
,在normal模式下面按ty就可以看到符号类型了。顺带一提nnoremap
这个map,第一个n代表这是normal模式下的映射,nore表示非递归映射。补全效果如下图,补全框的色彩风格如上是可以自定义的:
纠错
代码纠错的插件就更多了,这里用的是ale,关闭了ycm自带的代码纠错。虽说现在ycm也实现了异步纠错(我放弃ycm纠错用ale就是因为一开始它是同步运行的),不过ale使用起来一直很顺手,我就没有换回ycm的打算了。
- 安装
" ale语法检查
Plug 'w0rp/ale'
" 然后执行:PluginInstall
- 配置
"================================================================
"ale
"始终开启标志列
let g:ale_sign_column_always = 0
let g:ale_set_highlights = 0
"自定义error和warning图标
let g:ale_sign_error = '✗'
let g:ale_sign_warning = '⚡'
"在vim自带的状态栏中整合ale,airline也可以显示这些信息
let g:ale_statusline_format = ['✗ %d', '⚡ %d', '✔ OK']
"显示Linter名称,出错或警告等相关信息
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
"普通模式下,sp前往上一个错误或警告,sn前往下一个错误或警告
nmap sp <Plug>(ale_previous_wrap)
nmap sn <Plug>(ale_next_wrap)
"<Leader>s触发/关闭语法检查
"文件内容发生变化时不进行检查
let g:ale_lint_on_text_changed = 'never'
"打开文件时不进行检查
let g:ale_lint_on_enter = 0
" C 语言配置检查参数
let g:ale_c_gcc_options = '-Wall -Werror -O2 -std=c11'
let g:ale_c_clang_options = '-Wall -Werror -O2 -std=c11'
let g:ale_c_cppcheck_options = ''
" C++ 配置检查参数
" 因为我使用的是clang++进行代码,clang++当前版本对于C++20支持一般,就先用C++17了
let g:ale_cpp_gcc_options = '-Wall -Werror -O2 -std=c++17'
7et g:ale_cpp_clang_options = '-Wall -Werror -O2 -std=c++17
let g:ale_cpp_cppcheck_options = ''
"
"使用clang对c和c++进行语法检查,对python使用pylint进行语法检查
let g:ale_linters = {
\ 'c++': ['clang++'],
\ 'c': ['clang'],
\ 'python' : ['flake8']
\}
代码纠错也是异步运行的,如果不想使用可以通过:ALEDisable
关闭。
杂项
- 彩虹花括号
" 彩虹括号
" 让不同层级的括号具有不同的颜色
"Plug 'luochen1990/rainbow'
Plug 'kien/rainbow_parentheses.vim'
"================================================================
"rainbow
let g:rbpt_colorpairs = [
\ ['brown', 'RoyalBlue3'],
\ ['Darkblue', 'SeaGreen3'],
\ ['darkgray', 'DarkOrchid3'],
\ ['darkgreen', 'firebrick3'],
\ ['darkcyan', 'RoyalBlue3'],
\ ['darkred', 'SeaGreen3'],
\ ['darkmagenta', 'DarkOrchid3'],
\ ['brown', 'firebrick3'],
\ ['gray', 'RoyalBlue3'],
\ ['darkmagenta', 'DarkOrchid3'],
\ ['Darkblue', 'firebrick3'],
\ ['darkgreen', 'RoyalBlue3'],
\ ['darkcyan', 'SeaGreen3'],
\ ['darkred', 'DarkOrchid3'],
\ ['red', 'firebrick3'],
\ ]
let g:rbpt_max = 16
let g:rbpt_loadcmd_toggle = 0
au VimEnter * RainbowParenthesesToggle
au Syntax * RainbowParenthesesLoadRound
au Syntax * RainbowParenthesesLoadSquare
au Syntax * RainbowParenthesesLoadBraces
效果展示:
- 自动括号匹配
"自动补全括号
Plug 'jiangmiao/auto-pairs'
- 缩进线
"缩进指示线,在编辑py和golang之类的时候很不错
Plug 'Yggdroot/indentLine'
效果展示:
- 更漂亮的语法高亮
" 针对C++的语法高亮
Plug 'octol/vim-cpp-enhanced-highlight'
6. 杂项
- 快速注释
没有用插件的必要吧,改改配置就行了。按F2插入文件头,F3插入修改注释
"=================================================================
map <F2> :call SetTitle()<CR>
func SetComment()
call setline(1,"/************************************************************************")
call append(line("."), "* Copyright (C),xxxxxxxxxxxxxxxxxxxxxxx")
call append(line(".")+1, "* ")
call append(line(".")+2, "* File Name :".expand("%:t"))
call append(line(".")+3, "* Author :张三")
call append(line(".")+4, "* Version :")
call append(line(".")+5, "* Date :".strftime("%Y-%m-%d"))
call append(line(".")+6, "* Description:")
call append(line(".")+7, "*")
call append(line(".")+8,"************************************************************************/")
call append(line(".")+9, "")
call append(line(".")+10, "")
endfunc
" 加入shell,Makefile注释
func SetComment_sh()
call setline(3, "#================================================================")
call setline(4, "# Copyright (C) xxxxxxxxxxxxxxxxxxxxxxx")
call setline(5, "# ")
call setline(6, "# File Name :".expand("%:t"))
call setline(7, "# Author :张三")
call setline(8, "# Version :")
call setline(9, "# Date :".strftime("%Y-%m-%d"))
call setline(10, "# Description:")
call setline(11, "#")
call setline(12, "#================================================================")
call setline(13, "")
call setline(14, "")
endfunc
" 定义函数SetTitle,自动插入文件头
func SetTitle()
if &filetype == 'make'
call setline(1,"")
call setline(2,"")
call SetComment_sh()
elseif &filetype == 'sh'
call setline(1,"#!/system/bin/sh")
call setline(2,"")
call SetComment_sh()
else
call SetComment()
if expand("%:e") == 'hpp'
call append(line(".")+10, "#ifndef _".toupper(expand("%:t:r"))."_H")
call append(line(".")+11, "#define _".toupper(expand("%:t:r"))."_H")
call append(line(".")+12, "#ifdef __cplusplus")
call append(line(".")+13, "extern \"C\"")
call append(line(".")+14, "{")
call append(line(".")+15, "#endif")
call append(line(".")+16, "")
call append(line(".")+17, "#ifdef __cplusplus")
call append(line(".")+18, "}")
call append(line(".")+19, "#endif")
call append(line(".")+20, "#endif //".toupper(expand("%:t:r"))."_H")
elseif expand("%:e") == 'h'
call append(line(".")+10, "#pragma once")
elseif &filetype == 'c'
call append(line(".")+10,"#include \"".expand("%:t:r").".h\"")
elseif &filetype == 'cpp'
call append(line(".")+10, "#include \"".expand("%:t:r").".h\"")
endif
endif
endfunc
map <F3> :call QuickComment()<CR>
func QuickComment()
if &filetype == 'make'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'c'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'sh'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'cpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'hpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
endif
endfunc
- F5编译并运行
写一些小代码的时候会用的。不过现在都有了内置terminal,感觉没啥存在意义了啊
"=================================================================
"Quickly Run
""""""""""""""""""""""
map <F5> :call CompileRunGcc()<CR>
func! CompileRunGcc()
exec "w"
if &filetype == 'c'
exec "!g++ % -o %<"
exec "!time ./%<"
elseif &filetype == 'cpp'
exec "!g++ % -o %<"
exec "!time ./%<"
elseif &filetype == 'java'
exec "!javac %"
exec "!time java %<"
elseif &filetype == 'sh'
:!time bash %
elseif &filetype == 'python'
exec "!time python3 %"
endif
endfunc
- 擅用跳转
除去G
,gg
,NG
这样基本的跳转指令外,[[
,]]
这两个指令也是很有意思的,可以跳到函数头和函数尾。此外ctrl+o指令可以少用,容易把buffer搞乱。多使用ctrl+t(跨文件跳转)以及fzf或者LeaderF的Buffer功能。
- terminal
在vim8.1之后实现了内置终端,asyncrun之类的插件也因此成为了历史。通过:terminal
就可以打开一个终端,包括了异步执行任务等等功能,详见:help terminal
- 编辑远程文件
远程编辑有三种法子,一是ssh到远程,不多说。二是将远程文件夹挂载到本地,如:
sshfs -C -o reconnect 张三@123.123.123.123:/root/path/project /path/project
/path/project必须得是空文件夹。卸载则使用:umount /path/project
。出去sshfs,还有nfs等其他远程挂载方式
第三种法子是直接用vim打开:
vim scp://张三@123.123.123.123:/root/path/project
这些挂载方式效率和网络息息相关,能用IDE自带的挂载还是会更好一些
7. TODO
- 有个很牛逼的插件叫vim-spector,用于可视化的调试代码(就是像vscode那样)。不过嘛暂时用不到,先记着再说。反正还是大代码看log,小代码手打gdb咯
- vim内置的一堆more是否有办法替换呢,虽然可以设置格式让输出不那么丑,但more用起来还是别扭,嗯,慢慢找吧
- ctags一系列工具生成了一堆tags文件,需要将他们全部移动到废弃的目录中,否则会污染项目
- ctags和cscope会直接跳转到指定位置,这个行为并不一定时我想要的,看看有没有办法改一改script换掉它的默认行为
8. 完整的vimrc
" 映射的一些常用的操作
" f8 : 打开当前文件大纲,包括class定义,方法,成员变量等(使用ctags)
" f9 : 打开文件树
" ctrl+]:跳转到符号定义处
" ,+c :跳转到符号被引用处
" ,+s :在tags中查找符号
" ,+m :高亮标记单词
"标签跳转:通过在项目根目录执行ctags -R生成tags文件,项目中的文件需要set tags=path/tags
"然后通过ctrl+]跳转到定义(或者g+ctrl+],会显示多个定义),通过ctrl+o跳转回去
"
"设置文件编码
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
"设定leader键,Mark.vim使用了leader键
let mapleader=','
let g:solarized_termcolors=256
"设置主题
syntax on
set background=dark
colorscheme onehalfdark
"常用主题onedark,xcodelight,xcodedark,xcodewwdc
"gotham,gotham256,solarized
set cursorline
"设置保持历史记录10000
set history=10000
"打开文件时禁止折叠
set nofoldenable
"按照语法高亮进行折叠
set fdm=indent
set display=lastline
set scrolloff=5
set matchtime=2
set matchpairs+=<:>
set number
set showcmd
set showmatch
" 设置文件不备份,这里被注释掉;
set nobackup
set noundofile
set noswapfile
"set backupext=.bak
"set backupdir=~/.vim/vim_bak/
"语法高亮
set syntax=on
" 去掉输入错误的提示声音
set noeb
" 在处理未保存或只读文件的时候,弹出确认
set confirm
" 自动缩进
set autoindent
set cindent
" 设置tab为四个空格空格代替Tab
" 注意: 插入模式下输入【ctrl+v+i】可以强制输入一个tab
set tabstop=4 " tabstop 表示一个 tab 显示出来是多少个空格的长度,默认8
set softtabstop=4 " softtabstop 表示在编辑模式的时候按退格键的时候退回缩进的长度,当使用 expandtab 时特别有用
set expandtab " 当设置成 expandtab 时,缩进用空格来表示,noexpandtab 则是用制表符表示一个缩进
set autoindent " 自动缩进
set cindent " 自动缩进补充
set shiftwidth=4 " 自动缩进空白字符个数
highlight WhitespaceEOL ctermbg=red guibg=red
match WhitespaceEOL /\s\+$/
" 显示行号
set number
" 历史记录数
set history=1000
"禁止生成临时文件
set nobackup
set noswapfile
"搜索忽略大小写
set ignorecase
set incsearch
set autoread
set autowrite
" 鼠标定位
" 鼠标定位和鼠标拷贝似乎不能共存,按住shift再使用鼠标拷贝
set mouse=a
" 普通模式下为光标方块,插入模式下为竖线
let &t_SI.="\e[6 q" "SI = INSERT mode
let &t_SR.="\e[4 q" "SR = REPLACE mode
let &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)
"光标颜色
highlight Cursor guifg=white guibg=white
highlight iCursor guifg=white guibg=white
set guicursor=n-v-c:block-Cursor
set guicursor+=i:ver100-iCursor
set guicursor+=n-v-c:blinkon0
set guicursor+=i:blinkwait10
set guitablabel=%N\ %f
"垂直分割线颜色
hi VertSplit guibg=#31312D guifg=#526A83 ctermfg=White ctermbg=Black term=none cterm=none gui=none
"plug插件管理器
call plug#begin('~/.vim/plugged')
"文件树
Plug 'preservim/nerdtree'
"Plug 'ryanoasis/vim-devicons'
"自动补全括号
Plug 'jiangmiao/auto-pairs'
"底部状态栏美化
"Plug 'vim-airline/vim-airline'
"Plug 'Lokaltog/vim-powerline'
"缩进指示线,在编辑py的时候很不错
Plug 'Yggdroot/indentLine'
"主题
Plug 'altercation/vim-colors-solarized'
"针对C++的语法高亮
Plug 'octol/vim-cpp-enhanced-highlight'
"ale语法检查
Plug 'w0rp/ale'
"标签导航插件
Plug 'majutsushi/tagbar'
"彩虹括号
"Plug 'luochen1990/rainbow'
Plug 'kien/rainbow_parentheses.vim'
"跳转与检索
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
call plug#end()
filetype plugin indent on
"==============================================================
"YCM
" 每次重新生成匹配项,禁止缓存匹配项
let g:ycm_cache_omnifunc=0
" 在注释中也不能补全
let g:ycm_complete_in_comments=0
"关闭额外预览窗口
let g:ycm_add_preview_to_completeopt = 0
"基于syntastic的代码诊断,觉得慢的话可以换成ale
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>'
set completeopt=menu,menuone
let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'
let g:ycm_confirm_extra_conf = 0
noremap <c-z> <NOP>
" 选择语言
let g:ycm_semantic_triggers = {
\ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
\ 'cs,lua,javascript': ['re!\w{2}'],
\ }
" ycm补全框颜色
highlight PMenu ctermfg=0 ctermbg=242 guifg=black guibg=darkgrey
highlight PMenuSel ctermfg=242 ctermbg=8 guifg=darkgrey guibg=black
" ycm获取类型信息
nnoremap ty :YcmCompleter GetType<CR>
"==============================================================
"nerdtree
"vim打开空文件时直接打开文件树
"autocmd StdinReadPre * let s:std_in=1
"autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
"vim打开文件夹时打开文件树
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") | exe 'NERDTree' argv()[0] | wincmd p | ene | exe 'cd '.argv()[0] | endif
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
" NERDTree.vim
" let g:NERDTreeWinPos="left"
let g:NERDTreeWinSize=30
" let g:NERDTreeShowLineNumbers=1
" let g:neocomplcache_enable_at_startup = 1
" 将打开文件树的操作映射到F8键
nnoremap <F8> :NERDTreeToggle<cr>
" NERDTress File highlighting
function! NERDTreeHighlightFile(extension, fg, bg, guifg, guibg)
exec 'autocmd filetype nerdtree highlight ' . a:extension .' ctermbg='.a:bg .' ctermfg='. a:fg .' guibg='. a:guibg .' guifg='. a:guifg
exec 'autocmd filetype nerdtree syn match ' . a:extension .' #^\s\+.*'.a:extension .'$#'
endfunction
call NERDTreeHighlightFile('cpp', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('cc', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('c', 'blue', 'none', 'blue', '#151515')
call NERDTreeHighlightFile('h', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('hpp', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('md', 'blue', 'none', '#3366FF', '#151515')
call NERDTreeHighlightFile('json', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('html', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('css', 'cyan', 'none', 'cyan', '#151515')
call NERDTreeHighlightFile('js', 'Red', 'none', '#ffa500', '#151515')
"================================================================
"ale
"始终开启标志列
let g:ale_sign_column_always = 0
let g:ale_set_highlights = 0
"自定义error和warning图标
let g:ale_sign_error = '✗'
let g:ale_sign_warning = '⚡'
"在vim自带的状态栏中整合ale
let g:ale_statusline_format = ['✗ %d', '⚡ %d', '✔ OK']
"显示Linter名称,出错或警告等相关信息
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
"普通模式下,sp前往上一个错误或警告,sn前往下一个错误或警告
nmap sp <Plug>(ale_previous_wrap)
nmap sn <Plug>(ale_next_wrap)
"<Leader>s触发/关闭语法检查
"文件内容发生变化时不进行检查
let g:ale_lint_on_text_changed = 'never'
"打开文件时不进行检查
let g:ale_lint_on_enter = 0
" C 语言配置检查参数
let g:ale_c_gcc_options = '-Wall -Werror -O2 -std=c11'
let g:ale_c_clang_options = '-Wall -Werror -O2 -std=c11'
let g:ale_c_cppcheck_options = ''
" C++ 配置检查参数
let g:ale_cpp_gcc_options = '-Wall -Werror -O2 -std=c++17'
let g:ale_cpp_clang_options = '-Wall -Werror -O2 -std=c++17'
let g:ale_cpp_cppcheck_options = ''
"
"使用clang对c和c++进行语法检查,对python使用pylint进行语法检查
let g:ale_linters = {
\ 'c++': ['clang++'],
\ 'c': ['clang'],
\ 'python' : ['flake8']
\}
"===============================================================
"powerline
set laststatus=2
let g:Powerline_symbols='unicode'
"===============================================================
"airline
" tabline,也就是上方的tab列表
let g:airline#extensions#tabline#enabled = 1
" 显示tab的分割
let g:airline#extensions#tabline#show_splits = 0
" 不显示buffer
let g:airline#extensions#tabline#show_buffers = 0
" tab的显示风格
let g:airline#extensions#tabline#alt_sep = 1
let g:airline#extensions#tabline#left_sep = ' '
let g:airline#extensions#tabline#left_alt_sep = '◀'
let g:airline#extensions#tabline#tab_nr_type = 1 " tab number
let g:airline#extensions#tabline#show_tab_nr = 0
" let g:airline#extensions#tabline#formatter = 'default'
" 只显示文件名字
let g:airline#extensions#tabline#formatter = 'unique_tail'
" 文件名过长则显示...
let g:airline#extensions#tabline#overflow_marker = '…'
let g:airline_powerline_fonts = 1
" 关闭一堆不需要的
let g:airline#extensions#tabline#buffer_nr_show = 0
let g:airline#extensions#tabline#exclude_preview = 0
"if !exists('g:airline_symbols')
" let g:airline_symbols = {}
"endif
let g:airline_theme="onedark"
let g:airline_left_sep = '▶'
let g:airline_left_alt_sep = '❯'
let g:airline_right_sep = '◀'
let g:airline_right_alt_sep = '❮'
"================================================================
"rainbow
let g:rbpt_colorpairs = [
\ ['brown', 'RoyalBlue3'],
\ ['Darkblue', 'SeaGreen3'],
\ ['darkgray', 'DarkOrchid3'],
\ ['darkgreen', 'firebrick3'],
\ ['darkcyan', 'RoyalBlue3'],
\ ['darkred', 'SeaGreen3'],
\ ['darkmagenta', 'DarkOrchid3'],
\ ['brown', 'firebrick3'],
\ ['gray', 'RoyalBlue3'],
\ ['darkmagenta', 'DarkOrchid3'],
\ ['Darkblue', 'firebrick3'],
\ ['darkgreen', 'RoyalBlue3'],
\ ['darkcyan', 'SeaGreen3'],
\ ['darkred', 'DarkOrchid3'],
\ ['red', 'firebrick3'],
\ ]
let g:rbpt_max = 16
let g:rbpt_loadcmd_toggle = 0
au VimEnter * RainbowParenthesesToggle
au Syntax * RainbowParenthesesLoadRound
au Syntax * RainbowParenthesesLoadSquare
au Syntax * RainbowParenthesesLoadBraces
"================================================================
"tagbar
"设置tagbar使用的ctags的插件,必须要设置对
let g:tagbar_ctags_bin='/usr/bin/ctags'
""设置tagbar的窗口宽度
let g:tagbar_width=35
"设置tagbar的窗口显示的位置,为右边
let g:tagbar_left=0
"打开文件自动 打开tagbar
"autocmd BufReadPost *.cpp,*.c,*.h,*.hpp,*,*.cxx call tagbar#autoopen()
"映射tagbar的快捷键
map <F9> :TagbarToggle<CR>
" 设置焦点在tagbar
let g:tagbar_autofocus=1
"=================================================================
" ctags
" 设置tag跳转快捷键
nnoremap <leader>] g<C-]>
" 添加已经存在的tags文件
if filereadable("tags")
set tags+=./tags
endif
" ctags -R --c++-kinds=+px --fields=+iaS --extra=+q
"=================================================================
"fzf
"
" FZF -e name:在当前文件夹下精确匹配搜索文件
" Files name : 在当前文件夹下模糊匹配搜索文件,相当于FZF name
" Tags name :根据ctags生成的tags搜索标签
" Ag name :全文本模糊匹配,需要安装额外工具,详见官方md
" This is the default extra key bindings
let g:fzf_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
" Default fzf layout
" - down / up / left / right
let g:fzf_layout = { 'down': '~40%' }
" In Neovim, you can set up fzf window using a Vim command
" let g:fzf_layout = { 'window': 'enew' }
" let g:fzf_layout = { 'window': '-tabnew' }
" let g:fzf_layout = { 'window': '10split enew' }
" Customize fzf colors to match your color scheme
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'hl': ['fg', 'Comment'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
\ 'hl+': ['fg', 'Statement'],
\ 'info': ['fg', 'PreProc'],
\ 'border': ['fg', 'Ignore'],
\ 'prompt': ['fg', 'Conditional'],
\ 'pointer': ['fg', 'Exception'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" Enable per-command history.
" CTRL-N and CTRL-P will be automatically bound to next-history and
" previous-history instead of down and up. If you don't like the change,
" explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS.
" fzf的缓存文件,加快查找
let g:fzf_history_dir = '~/.local/share/fzf-history'
" [Buffers] 如果可能跳到已存在窗口,这里关闭了
let g:fzf_buffers_jump = 0
" [[B]Commits] 自定义被'git log'使用的选项
let g:fzf_commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
" [Tags] 定义用来产生tag的命令,好像就ctags可以,gtags不兼容。LeaderF可以使用gtags
let g:fzf_tags_command = 'ctags -R'
" [Commands] --expect expression for directly executing the command
let g:fzf_commands_expect = 'alt-enter,ctrl-x'
" 历史缓存文件,加快查找速度
let g:fzf_history_dir = '~/.local/share/fzf-history'
"=================================================================
"=================================================================
" Mark
" 打开vim时重置mark
set viminfo='64,<8192,s1024,!,h
"=================================================================
" cscope
" cscope -Rbq,生成cscope数据库,使用方式类似ctags
" cscope find c name,查找调用该函数的函数
" set quickfix,把信息打到quickfix里面,不过还是全屏好用
" set cscopequickfix=s-,c-,d-,i-,t-,e-
" use both cscope and ctag for 'ctrl-]', ':ta', and 'vim -t'
" set cscopetag
" check cscope for definition of a symbol before checking ctags: set to 1
" if you want the reverse search order.
set csto=0
" add any cscope database in current directory
if filereadable("cscope.out")
cs add cscope.out
" else add the database pointed to by environment variable
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
" show msg when any other cscope db added
set cscopeverbose
" 设置输出文件信息长度,文件路径深度最高为五
:set cspc=5
" 设置输出信息的颜色
" 通过:highlight查看所有高亮属性
:hi ModeMsg ctermfg=Blue
:hi MoreMsg ctermfg=Red
:hi Directory term=bold ctermfg=114 guifg=#98c379
" 快捷键
nmap <leader>c :cs find c <C-R>=expand("<cword>")<CR><CR>
nnoremap <leader>s :Tags <C-R>=expand("<cword>")<CR><CR>
" 同时查找ctags和cscope的数据库
set cst
"=================================================================
" gtags
set cscopetag " 使用 cscope 作为 tags 命令
set cscopeprg='gtags-cscope' " 使用 gtags-cscope 代替 cscope
"gtags.vim 设置项
let GtagsCscope_Auto_Load = 1
let CtagsCscope_Auto_Map = 1
let GtagsCscope_Quiet = 1
" 并不是禁止了cscope与ctags,gtags是在C++与java方面的补充
"=================================================================
map <F2> :call SetTitle()<CR>
func SetComment()
call setline(1,"/************************************************************************")
call append(line("."), "* Copyright (C), xxxxxxxxxxxxxxxx.")
call append(line(".")+1, "* ")
call append(line(".")+2, "* File Name :".expand("%:t"))
call append(line(".")+3, "* Author :张三")
call append(line(".")+4, "* Version :")
call append(line(".")+5, "* Date :".strftime("%Y-%m-%d"))
call append(line(".")+6, "* Description:")
call append(line(".")+7, "*")
call append(line(".")+8,"************************************************************************/")
call append(line(".")+9, "")
call append(line(".")+10, "")
endfunc
" 加入shell,Makefile注释
func SetComment_sh()
call setline(3, "#================================================================")
call setline(4, "# Copyright (C),xxxxxxxxxxxxxxxxx.")
call setline(5, "# ")
call setline(6, "# File Name :".expand("%:t"))
call setline(7, "# Author :张三")
call setline(8, "# Version :")
call setline(9, "# Date :".strftime("%Y-%m-%d"))
call setline(10, "# Description:")
call setline(11, "#")
call setline(12, "#================================================================")
call setline(13, "")
call setline(14, "")
endfunc
" 定义函数SetTitle,自动插入文件头
func SetTitle()
if &filetype == 'make'
call setline(1,"")
call setline(2,"")
call SetComment_sh()
elseif &filetype == 'sh'
call setline(1,"#!/system/bin/sh")
call setline(2,"")
call SetComment_sh()
else
call SetComment()
if expand("%:e") == 'hpp'
call append(line(".")+10, "#ifndef _".toupper(expand("%:t:r"))."_H")
call append(line(".")+11, "#define _".toupper(expand("%:t:r"))."_H")
call append(line(".")+12, "#ifdef __cplusplus")
call append(line(".")+13, "extern \"C\"")
call append(line(".")+14, "{")
call append(line(".")+15, "#endif")
call append(line(".")+16, "")
call append(line(".")+17, "#ifdef __cplusplus")
call append(line(".")+18, "}")
call append(line(".")+19, "#endif")
call append(line(".")+20, "#endif //".toupper(expand("%:t:r"))."_H")
elseif expand("%:e") == 'h'
call append(line(".")+10, "#pragma once")
elseif &filetype == 'c'
call append(line(".")+10,"#include \"".expand("%:t:r").".h\"")
elseif &filetype == 'cpp'
call append(line(".")+10, "#include \"".expand("%:t:r").".h\"")
endif
endif
endfunc
map <F3> :call QuickComment()<CR>
func QuickComment()
if &filetype == 'make'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'c'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'sh'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'cpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'hpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
endif
endfunc
, "#endif")
call append(line(".")+20, "#endif //".toupper(expand("%:t:r"))."_H")
elseif expand("%:e") == 'h'
call append(line(".")+10, "#pragma once")
elseif &filetype == 'c'
call append(line(".")+10,"#include \"".expand("%:t:r").".h\"")
elseif &filetype == 'cpp'
call append(line(".")+10, "#include \"".expand("%:t:r").".h\"")
endif
endif
endfunc
map <F3> :call QuickComment()<CR>
func QuickComment()
if &filetype == 'make'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'c'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'sh'
call append(line("."), "# start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "# end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'cpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
elseif &filetype == 'hpp'
call append(line("."), "// start modified by 张三 in ".strftime("%Y-%m-%d")." ")
call append(line(".")+1, "// end modified by 张三 in ".strftime("%Y-%m-%d")." ")
endif
endfunc
版权声明:本文标题:用于C++项目的vim配置 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1726377718h948266.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论