日期 | 作者 | 版本 | 备注 |
---|---|---|---|
2021-03-24 | dingbin | V1.0 | |
C++程序员日常开发中不可避免地遇到变更电脑,变更服务器等事件时重建搭建C++开发环境切实过于沉重,须要消耗很多不必要的宝贵时间。vim 的YouCompleteMe(简称YCM) 插件能够实现较好的C/C++语言主动补全跳转性能,是利用vim进行C /C++代码编辑的必备神器之一。而后理论中YCM的装置及其简单,不仅依赖python动态链接库,还依赖特定高版本的gcc和clang或clangd和cmake等。筹备这些前置组件也很费时费力。有鉴于此,本文介绍一种新的玩法,并给出实际操作细节和间接可用的docker镜像成绩,即:构建基于Vim的C++补全跳转插件YouCompleteMe的Docker镜像,一键实现任意机器上C++开发环境搭建。具体操作办法介绍如下。
环境筹备
工夫: 2021-03-24
机器配置:CentOS Linux release 7.5.1804 (Core),8核 12G
创立根底的docker镜像
思考装置以后工夫下最新版本的vim和YoucompleteMe插件。参考YouCompleteMe官网介绍的装置办法要求vim/gcc/clang/clangd/cmake/python都在比拟高的版本下能力装置胜利。而咱们为了制作docker 镜像,因而不可能选很旧的根底os。参考YCM官网的倡议,咱们根底OS抉择ubuntu 20.04 LTS。hub.docker.com上间接现成的镜像文件。配置文件须要筹备好如下3个配置文件,本文间接贴出原文内容如下:
vim配置文件.vimrc
set nocompatible " be iMproved, requiredfiletype off " requiredset encoding=utf-8set rtp+=~/.vim/bundle/Vundle.vimcall vundle#begin()Plugin 'VundleVim/Vundle.vim'Plugin 'flazz/vim-colorschemes'Plugin 'godlygeek/csapprox'Plugin 'Valloric/YouCompleteMe'call vundle#end() " requiredfiletype plugin indent on " requiredset cstset csto=1 set nocsverbset csverb"set smd "set showmode"set sc "set showcmdset aw "set autowriteset awa "set autowriteallset title"使关上文件时使光标主动定位到上一次文件被敞开时的精确行if has("autocmd") autocmd BufRead *.txt set tw=78 au BufReadPost * exe "normal! g`\""endif"设置高亮关键字显示syntax enablesyntax on "等同于syn on"禁止在搜寻到文件两端时从新搜寻"set nows "set nowrapscan set ws"设置搜寻式的匹配字符串高亮显示set hls "set hlsearch"设置搜寻式的匹配字符串不高亮显示"set nohls "set nohlsearch "高亮光标所在的以后行set cursorlineset cul "相同的设置是set nocul"set nocul"搜寻时在未齐全输出结束要检索的文本时就开始检索set is "set incsearch"搜寻时在未齐全输出结束要检索的文本时不开始检索"set nois "set noincsearch"设置以backspace删除主动缩进的,行末回车,行首的字符,很有用set backspace=indent,eol,startset ic "相同是 set noic"set scs "相同是 set noscs"加强模式中的命令行主动实现操作,十分有用set wildmenu"设置代码折叠为按语法折叠"set foldmethod=syntax"设定折叠形式为手动set foldmethod=manual"设置启动vim时不要主动折叠代码set foldlevel=100set fdc=1 "set foldcolumn=1 "设置帮忙的语言为中文set helplang=cn"set helplang=en"实现C程序的缩进(indent)set cin "设置行号set nu"set nonu"设置256色调set t_Co=256"设置配色计划"colorscheme 简写成colo"colo colorful "colo white2 colo desert"colo night"colo navajo"colo lucius"colo blackdust"colo freya"colo darkslategray"colo torte"colo fruidle"colo colorful"设置编辑模式下状态栏标尺显示set ru "set ruler"设置编辑模式下状态栏标尺不显示"set noru "set noruler"记录历史的行数set history=1000"检测文件类型"filetype onfiletype plugin on" 开启文件类型检测 的插件和缩进开filetype plugin indent on "设置能够至上一行和下一行的字符按键set ww=b,s,<,>,[,] ",h,l"Alt组合键不映射到菜单上set winaltkeys=no"同时反对GBK和UTF-8编码set fileencodings=utf-8,ucs-bom,gbk,cp936set fileencoding=utf-8set encoding=utf-8"如果在终端环境下应用Vim,须要设置termencoding和终端所应用的编码统一。例如:set termencoding=utf-8 "设置更新ctags文件的快捷键"map <F3> : ! ${HOME}/tools/gen_tags_by_dingbin.bash "%:p:h" z6tags <CR>"map <F4> : ! ${HOME}/tools/gen_tags_by_dingbin.bash "%:p:h" oatags <CR>"map <F5> : ! ${HOME}/tools/gen_tags_by_dingbin.bash "%:p:h" qttags <CR>"===================================================================================================================="map <silent> <F4> : cs show <CR>: let @i = &tags <CR> :let @j = $CSCOPE_TAGS <CR> : !genvimtags -vimCtags <c-r>i -vimCscope <c-r>j <cr> :so ${VIM_SCRIPT_HOME}/configure/vimSourceFile <cr>"map <silent> <F5> : cs show <CR>: let @i = &tags <CR> :let @j = $CSCOPE_TAGS <CR> : !genvimtags -g -vimCtags <c-r>i -vimCscope <c-r>j <cr> :so ${VIM_SCRIPT_HOME}/configure/vimSourceFile <cr> "===================================================================================================================="设置grep插件的快捷键"nnoremap <silent> <F4> :Grep<CR>"-----------------------------------------------------"主动缩进的时候, 缩进尺寸为 4 个空格。"即shiftWidth,主动缩进的空格数,用于<<,>>,cindentset shiftwidth=4 "softtabstop,sts,默认是0,"执行编辑操作,如插入 <Tab> 或者应用 <BS> 时,把 <Tab> 算作空格的数目set softtabstop=4 "set sts=4"编辑时将所有 Tab 替换为空格。"该选项只在编辑时将 Tab 替换为空格, 如果关上一个曾经存在的文件, 并不会将已有的Tab 替换为空格。 "设置了该选项后,如果想输出tab制表符,先输出CTRL-V或CTRL-Q,再输出tab制表符set et "相同的设置是set noet"Tab 宽度为 4 个字符。set ts=4 "即set tabstop=4"Tab操作快捷方式!"nnoremap <C-TAB> :tabnext<CR><CR>:TlistClose<CR><CR>:TlistToggle<CR><CR>"nnoremap <C-S-TAB> :tabprev<CR><CR>:TlistClose<CR><CR>:TlistToggle<CR><CR>"nnoremap <C-TAB> :tabnext<CR><CR>:TlistClose<CR><CR>"nnoremap <C-S-TAB> :tabprev<CR><CR>:TlistClose<CR><CR>""对于tab的快捷键"map tn :tabnext<cr>"map tp :tabprevious<cr>"map td :tabnew .<cr>"map te :tabedit<SPACE>"map tc :tabclose<cr>""map tf :tabnew %:p<cr>:TlistClose<CR><CR>:TlistToggle<CR><CR>"map tf :tabnew %:p<cr>:TlistClose<CR><CR>"覆盖文件时不备份set nobackup "胜利保留文件之前备份 set wb "set writebackup"set nowb "set nowritebackup"插入括号时,短暂地跳转到匹配的对应括号set sm "set showmatch "短暂跳转到匹配括号的工夫set matchtime=2"设置魔术set magic "容许在有未保留的批改时切换缓冲区,此时的批改由 vim 负责保留set hidden "开启新行时应用智能主动缩进set smartindent set autoindent"关上一般文件类型的主动缩进。 该主动缩进不如 cindent 智能, 但它能够为你编辑非 C/C++ 文件提供肯定帮忙。set ai"选中状态下 Ctrl+c 复制"vmap <C-c> "+y"留神应用的过程中能够通过e和b键盘以word为单位后退或后退以抉择文本"set keymodel= "不应用此性能set keymodel=startsel,stopsel "应用此性能"visual 模式下标签查找(*,#)可用vnoremap * y<ESC>/<C-r>"<CR> vnoremap # y<ESC>?<C-r>"<CR> nnoremap g[ :tag <C-R>=expand("<cWORD>")<CR><CR>vnoremap g[ <ESC>:tag <C-r>*<CR>:inoremap ( ()<ESC>i:inoremap [ []<ESC>i:inoremap ;; <ESC>A;<CR>"插入模式下使Ctrl+ h,j,k,l四个键成果等同于挪动上、下、左、右方向键inoremap <C-h> <Left>inoremap <C-j> <Down>inoremap <C-k> <Up>inoremap <C-l> <Right>"插入模式下使ctrl+ w,b两个键成果等同于一般模式下ctrl+w(后退一个单词),ctrl+b("后退一个单词)inoremap <C-b> <C-o>binoremap <C-w> <C-o>w"插入模式下使ctrl+ f(front),Ctrl+e(end)两个键成果等同于一般模式下<home>,<end>键inoremap <C-e> <C-o><End>inoremap <C-f> <C-o><Home>"插入模式下ctrl + d,等效于一般模式下backspace键,"插入模式下ctrl + x,等效于一般模式下delete键,inoremap <C-d> <BS>inoremap <C-x> <Del>"指定在抉择文本时,光标所在位置也属于被选中的范畴set selection=inclusive"-----------------------------------------------------"-----------------------------------------------------"指定不折行。 如果一行太长, 超过屏幕宽度, 则向左边延长到屏幕里面。如果应用图形界面的话, 指定不折行视觉效果会好得多。set nowrap"set wrap"设置显示时一行的文本宽宽set tw=80 "set textwidth=80"增加程度滚动条。 如果你指定了不折行, 那为窗口增加一个程度滚动条就十分有必要了。set guioptions-=b"去除vim的GUI版本的toolbarset guioptions+=T"去除vim的GUI版本的menubarset guioptions+=m"设置断行,当一行的文字太长时,为主动智能在一个单词的两头"空白处断开到下一行显示,留神:这里的断行只用显示,并不在行末加<EOF>set lbr "set linebreak"关上断行模块对亚洲语言反对。 m 示意容许在两个汉字之间断行, 即便汉字之间没有呈现空格。"B 示意将两行合并为一行的时候, 汉字与汉字之间不要补空格。 该命令反对的更多的选项请参看用户手册。set fo+=mB"配置字体"set fileencoding=gbk"set guifont=Courier\ 11 "set guifont=Inconsolata\ Medium\ 9 "史上最难看的vim字体"set guifont=Bitstream_Vera_Sans_Mono:h10:cANSI"set gfw=幼圆:h10.5:cGB2312set guifont=Bitstream\ Vera\ Sans\ Mono\ 13"当右键单击窗口的时候, 弹出快捷菜单set mousemodel=popup"不应用抉择模式set selectmode="设置屏幕滚动的ctrl+d,ctrl+u的行数,默认是窗口的一半,即半屏set scr=4"-----------------------------------------------------"""""""""""""""""""""""""""""""""Taglist plugin settings """"""""""""""""""""""""""""""""let Tlist_Auto_Highlight_Tag = 1"let Tlist_Hightlight_Tag_On_BufEnter = 1"let Tlist_GainFocus_On_ToggleOpen = 0 "if 0 focus at code window, if 1 focus at tag window"""启动vim主动关上taglist"let Tlist_Auto_Open = 0 """ 不同时显示多个文件的 tag ,只显示以后文件的"let Tlist_Show_One_File = 1""" 如果 taglist 窗口是最初一个窗口,则退出 vim"let Tlist_Exit_OnlyWindow = 1"""让以后不被编辑的文件的办法列表主动折叠起来 "let Tlist_File_Fold_Auto_Close = 0"""把taglist窗口放在屏幕的右侧,缺省在左侧 "let Tlist_Use_Right_Window=1 """显示taglist菜单"let Tlist_Show_Menu = 1"""taglist window width"let Tlist_WinWidth = 40""let Tlist_Process_File_Always = 1""" 是否容许关上taglist窗口时主动加宽窗口, 默认为容许."let Tlist_Inc_Winwidth = 1"" 精简模式, 不同的tag类别之间没有空行, 默认为有空行"let Tlist_Compact_Format = 1"" tag是以何种程序排序, 以"order"还是"name", 默认是order, 能够用s切换,"let Tlist_Sort_Type = "order""""用<ALT> + 数字切换Tab窗口""用过Gnome-terminal的人都晓得, 在一个Terminal里关上多个TAB窗口, 用ALT+数字就能够""切换到相应的窗口. 很喜爱这个性能, 映射如下:""noremap <M-1> 1gt"noremap <M-2> 2gt"noremap <M-3> 3gt"noremap <M-4> 4gt"noremap <M-5> 5gt"noremap <M-6> 6gt"noremap <M-7> 7gt"noremap <M-8> 8gt"noremap <M-9> 9gt"noremap <M-0> 10gt"""""""""""""""""""""""""""""""""""Winmanager plugin settings """""""""""""""""""""""""""""""""设置界面宰割"let g:winManagerWindowLayout='FileExplorer|TagList'""let g:winManagerWindowLayout = BufExplorer,FileExplorer|TagList"""let g:winManagerWindowLayout = TagList|FileExplorer,BufExplorer""""设置winmanager的宽度,默认为25""let g:winManagerWidth = 30"""定义关上敞开winmanager按键"nmap wm :WMToggle<cr>""nmap <silent> <F8> :WMToggle<cr>"nmap <silent> <F4> :TlistToggle<cr>"""1)将插件显示在右侧""关上winmanager.vim,在function! <SID>StartWindowsManager()函数中批改:""将:wincmd H 批改为wincmd L:"" for now assume that the explorer windows always stay on the left."" TODO: make this optional later"" make the explorers window always stay on the right ---by chenyong"" wincmd H""wincmd L"""2)进入vim主动关上winmanager""在进入vim时主动关上winmanager"let g:AutoOpenWinManager = 0""相应的在winmanager.vim中批改:""set auto open Winmanager ""if g:AutoOpenWinManager ""autocmd VimEnter * nested call s:StartWindowsManager()|1wincmd w ""endif"""3)退出缓冲区时,主动退出vim""这个性能是参考了taglist的主动退出性能,在taglist.vim中批改的。""函数:function! s:Tlist_Window_Exit_Only_Window()中的winbunr(2)改为winbunr(3),""即只剩2个窗口时敞开,思考到2个窗口必定是同时存在,所以这样还是可行的: ""同时在vimrc中须要设置:""let Tlist_Exit_OnlyWindow=1"""""""""""""""""""""""""""""""""""QuickFix plugin settings """"""""""""""""""""""""""""""""nmap <F7> :cw<cr>:cn<cr>"nmap <F6> :cw<cr>:cp<cr>"nmap <F9> :cclose<cr>""""""""""""""""""""""""""""""""""""""""""""""""""""""""设定是否应用 quickfix 窗口来显示 cscope 后果"""""""""""""""""""""""""""""""""""""""""""""""""""""":set cscopequickfix=s-,g-,c-,d-,i-,t-,e-,f-""""cscope find"的用法:""cs find c|d|e|f|g|i|s|t name""0 或 s 查找本 C 符号(能够跳过正文)""1 或 g 查找本定义""2 或 d 查找本函数调用的函数""3 或 c 查找调用本函数的函数""4 或 t 查找本字符串""6 或 e 查找本 egrep 模式""7 或 f 查找本文件""8 或 i 查找蕴含本文件的文件"nmap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR>"nmap <C-_>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>"nmap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR>"""""""""""""""""""""""""""""""""""""""""""""""""""""""""头文件与源文件互相切换a.vim settings"""""""""""""""""""""""""""""""""""""""""""""""""""""""nnoremap <silent> <F12> :A<CR> ""A 在新Buffer中切换到c\h文件""AS 横向宰割窗口并关上c\h文件""AV 纵向宰割窗口并关上c\h文件""AT 新建一个标签页并关上c\h文件"""""""""""""""""""""""""""""""""""""""""""""""""""""""" F11 : set csto=1, F12 : set csto=0""""""""""""""""""""""""""""""""""""""""""""""""""""""nnoremap <silent> <F11> :set csto=1 <CR> "nnoremap <silent> <F12> :set csto=0 <CR> """" set cs hotkey"nmap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR>"nmap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR>"nmap <C-_>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>"nmap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR>""" Using 'CTRL-spacebar' then a search type makes the vim window"" split horizontally, with search result displayed in"" the new window.""nmap <S-Space>s :scs find s <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space>g :scs find g <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space>c :scs find c <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space>t :scs find t <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space>e :scs find e <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space>f :scs find f <C-R>=expand("<cfile>")<CR><CR>"nmap <S-Space>i :scs find i ^<C-R>=expand("<cfile>")<CR>$<CR>"nmap <S-Space>d :scs find d <C-R>=expand("<cword>")<CR><CR>""" Hitting CTRL-space *twice* before the search type does a vertical"" split instead of a horizontal one""nmap <S-Space><S-Space>s" \:vert scs find s <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space><S-Space>g" \:vert scs find g <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space><S-Space>c" \:vert scs find c <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space><S-Space>t" \:vert scs find t <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space><S-Space>e" \:vert scs find e <C-R>=expand("<cword>")<CR><CR>"nmap <S-Space><S-Space>i" \:vert scs find i ^<C-R>=expand("<cfile>")<CR>$<CR>"nmap <S-Space><S-Space>d" \:vert scs find d <C-R>=expand("<cword>")<CR><CR>function AddFileTitle()call append(0," ")call setline(1,"////////////////////////////////////////////////////////////////////////")call append(1,"/// @Filename " . expand("%:p:t"))call append(2,"/// @Description ")call append(3,"/// @Author DingBin")call append(4,"/// @Last modified " . strftime("%Y-%m-%d %H:%M"))call append(5,"////////////////////////////////////////////////////////////////////////")endfunctionfunction AddFileComment()call append(line(".") -1," ")call setline(line(".") -1,"////////////////////////////////////////////////////////////////////////")call append(line(".") - 1,"/// @brief :")call append(line(".") - 1,"/// @param :")call append(line(".") - 1,"/// @return :")call append(line(".") - 1,"////////////////////////////////////////////////////////////////////////")endfunctionfunction AddoaArrayFor()call append(line(".") -1," ")call setline(line(".") -1,"for (oaUInt4 i = 0; i < .getNumElements(); i++ )")endfunctionmap time :0,50/\/\/\/ *@Last modified/s#@Last modified.*$#\=strftime("@Last modified %Y-%m-%d %H:%M")#cmap addt :call AddFileTitle()<cr>map addc :call AddFileComment()<cr>map addf :call AddoaArrayFor()<cr>"nnoremap <C-1> 1gt "nnoremap <C-2> 2gt "nnoremap <A-3> 3gt"nnoremap <A-4> 4gt "nnoremap <A-5> 5gt "nnoremap <A-6> 6gt "nnoremap <A-7> 7gt "nnoremap <A-8> 8gt "nnoremap <A-9> 9gt "Mode Settingslet &t_SI.="\e[5 q" "SI = INSERT mode"let &t_SR.="\e[4 q" "SR = REPLACE modelet &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)"Cursor settings:" 1 -> blinking block" 2 -> solid block" 3 -> blinking underscore" 4 -> solid underscore" 5 -> blinking vertical bar" 6 -> solid vertical bar"let &t_SI = "\<Esc>]50;CursorShape=1\x7""let &t_SR = "\<Esc>]50;CursorShape=2\x7""let &t_EI = "\<Esc>]50;CursorShape=0\x7""-----------------------------------------------------"对于状态行配置"总是显示状态行set laststatus=2 "set ls=2 "----- 状态栏设置_BEGIN_ -----"显示以后文件名,文件格式,文件类型set statusline=%2*%n%m%r%h%w%*\ %F\ %1*[FORMAT=%2*%{&ff}:%{&fenc!=''?&fenc:&enc}%1*]\ [TYPE=%2*%Y%1*]\ [COL=%2*%03v%1*]\ [ROW=%2*%03l%1*/%3*%L(%p%%)%1*]\ "设置状态栏依据不同状态显示不同色彩function! InsertStatuslineColor(mode) if a:mode == 'i' hi statusline guibg=peru elseif a:mode == 'r' hi statusline guibg=blue else hi statusline guibg=red endifendfunctionau InsertEnter * call InsertStatuslineColor(v:insertmode)au InsertLeave * hi statusline guibg=lightGreen guifg=blackhi statusline guibg=lightGreen"状态行色彩highlight CursorLine cterm=NONE ctermbg=lightGray ctermfg=green highlight StatusLineNC cterm=NONE ctermbg=lightGray ctermfg=green "highlight CursorLine cterm=NONE ctermbg=lightGray ctermfg=green guifg=lightGray guibg=green"highlight StatusLineNC cterm=NONE ctermbg=lightGray ctermfg=green guibg=lightGray guifg=green "highlight CursorLine cterm=NONE ctermbg=lightGray ctermfg=green guifg=red guibg=Green"highlight StatusLineNC cterm=NONE ctermbg=lightGray ctermfg=green guifg=Gray guibg=White"highlight CursorLine cterm=NONE guifg=red guibg=Green"highlight StatusLineNC cterm=NONE guifg=Gray guibg=White"----- 状态栏设置_END_ -----"ycm configurationlet g:ycm_confirm_extra_conf = 0let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'let g:ycm_key_list_select_completion = ['<TAB>','<C-n>','<Down>']let g:ycm_key_list_previous_completion = ['<S-TAB>','<C-p>','<Up>']let g:ycm_complete_in_comments = 1 "在正文输出中也能补全let g:ycm_complete_in_strings = 1 "在字符串输出中也能补全let g:ycm_collect_identifiers_from_comments_and_strings = 0 "正文和字符串中的文字也会被支出补全let g:ycm_collect_identifiers_from_tags_files=1 " 开启 YCM 基于标签引擎let g:ycm_min_num_of_chars_for_completion=1 " 从第1个键入字符就开始列举匹配项let g:ycm_cache_omnifunc=0 " 禁止缓存匹配项,每次都从新生成匹配项"被动补全"let g:ycm_key_invoke_completion = '<S-Space>'let g:ycm_key_invoke_completion = '<c-k>'let g:ycm_seed_identifiers_with_syntax=1 " 语法关键字补全"nnoremap <leader>lo :lopen<CR> "open locationlist"nnoremap <leader>lc :lclose<CR> "close locationlist"inoremap <leader><leader> <C-x><C-o>let g:ycm_max_num_identifier_candidates = 50let g:ycm_auto_trigger = 1let g:ycm_error_symbol = '>>'let g:ycm_warning_symbol = '>'"YcmCompleter RefactorRename :重命名"YcmCompleter GoToSymbol nnoremap <leader>jo :YcmCompleter GoTo<CR> "跳转nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR> "跳转到定义或申明nnoremap <leader>jf :YcmCompleter GoToDefinition<CR> "跳转到定义nnoremap <leader>jl :YcmCompleter GoToDeclaration<CR> "跳转到申明nnoremap <leader>jt :YcmCompleter GetType<CR> "get类型nnoremap :js :YcmCompleter GoToSymbol nmap <leader>ji :YcmCompleter GoToInclude<CR> "跳转到include、申明或定义nmap <leader>jm :YcmCompleter GoToImprecise<CR> "跳转到实现nmap <leader>jr :YcmCompleter GoToReferences<CR> "跳转到援用nmap <leader>fi :YcmCompleter FixIt<CR> "依据Ycm的倡议修复谬误nnoremap <F6> :YcmForceCompileAndDiagnostics<CR> "从新编译和诊断nmap <F4> :YcmDiags<CR> "F4进行诊断
bash 配置文件.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)# for examples# If not running interactively, don't do anythingcase $- in *i*) ;; *) return;;esac# don't put duplicate lines or lines starting with space in the history.# See bash(1) for more optionsHISTCONTROL=ignoreboth# append to the history file, don't overwrite itshopt -s histappend# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)HISTSIZE=1000HISTFILESIZE=2000# check the window size after each command and, if necessary,# update the values of LINES and COLUMNS.shopt -s checkwinsize# If set, the pattern "**" used in a pathname expansion context will# match all files and zero or more directories and subdirectories.#shopt -s globstar# make less more friendly for non-text input files, see lesspipe(1)[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"# set variable identifying the chroot you work in (used in the prompt below)if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then debian_chroot=$(cat /etc/debian_chroot)fi# set a fancy prompt (non-color, unless we know we "want" color)case "$TERM" in xterm-color|*-256color) color_prompt=yes;;esac# uncomment for a colored prompt, if the terminal has the capability; turned# off by default to not distract the user: the focus in a terminal window# should be on the output of commands, not on the prompt#force_color_prompt=yesif [ -n "$force_color_prompt" ]; then if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then # We have color support; assume it's compliant with Ecma-48 # (ISO/IEC-6429). (Lack of such support is extremely rare, and such # a case would tend to support setf rather than setaf.) color_prompt=yes else color_prompt= fifiif [ "$color_prompt" = yes ]; then PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ 'else PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ 'fiunset color_prompt force_color_prompt# If this is an xterm set the title to user@host:dircase "$TERM" inxterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" ;;*) ;;esac# enable color support of ls and also add handy aliases#if [ -x /usr/bin/dircolors ]; then# test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"# alias ls='ls --color=auto'# #alias dir='dir --color=auto'# #alias vdir='vdir --color=auto'## alias grep='grep --color=auto'# alias fgrep='fgrep --color=auto'# alias egrep='egrep --color=auto'#fi# colored GCC warnings and errors#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'# some more ls aliasesalias ll='ls -alF'alias la='ls -A'alias l='ls -CF'# Add an "alert" alias for long running commands. Use like so:# sleep 10; alertalias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'# Alias definitions.# You may want to put all your additions into a separate file like# ~/.bash_aliases, instead of adding them here directly.# See /usr/share/doc/bash-doc/examples in the bash-doc package.if [ -f ~/.bash_aliases ]; then . ~/.bash_aliasesfi# enable programmable completion features (you don't need to enable# this, if it's already enabled in /etc/bash.bashrc and /etc/profile# sources /etc/bash.bashrc).if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fifi###################################################################################export EDITOR=vimalias tmux="tmux -2"myCdls(){ echo $@ if [ ""$@"" == "" ] ; then \cd $HOME else \cd "$@" fi pwd ls -lh}alias cd=myCdls
ycm根底的数据库配置文件.ycm_extra_conf.py
# This file is NOT licensed under the GPLv3, which is the license for the rest# of YouCompleteMe.## Here's the license text for this file:## This is free and unencumbered software released into the public domain.## Anyone is free to copy, modify, publish, use, compile, sell, or# distribute this software, either in source code form or as a compiled# binary, for any purpose, commercial or non-commercial, and by any# means.## In jurisdictions that recognize copyright laws, the author or authors# of this software dedicate any and all copyright interest in the# software to the public domain. We make this dedication for the benefit# of the public at large and to the detriment of our heirs and# successors. We intend this dedication to be an overt act of# relinquishment in perpetuity of all present and future rights to this# software under copyright law.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR# OTHER DEALINGS IN THE SOFTWARE.## For more information, please refer to <http://unlicense.org/>from distutils.sysconfig import get_python_incimport platformimport osimport subprocessimport ycm_coreDIR_OF_THIS_SCRIPT = os.path.abspath( os.path.dirname( __file__ ) )DIR_OF_THIRD_PARTY = os.path.join( DIR_OF_THIS_SCRIPT, 'third_party' )SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]# These are the compilation flags that will be used in case there's no# compilation database set (by default, one is not set).# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.flags = ['-Wall','-Wextra','-Wno-long-long','-Wno-variadic-macros','-Wthread-safety','-Wthread-safety-beta','-fexceptions','-DNDEBUG','-D_GLIBCXX_USE_CXX11_ABI=0', # esearch uses old ABI# THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which# language to use when compiling headers. So it will guess. Badly. So C++# headers will be compiled as C headers. You don't want that so ALWAYS specify# a "-std=<something>".# For a C project, you would set this to something like 'c99' instead of# 'c++11'.'-std=c++17',# ...and the same thing goes for the magic -x option which specifies the# language that the files to be compiled are written in. This is mostly# relevant for c++ headers.# For a C project, you would set this to 'c' instead of 'c++'.'-x', 'c++','-I', '/usr/local/include']# Set this to the absolute path to the folder (NOT the file!) containing the# compile_commands.json file to use that instead of 'flags'. See here for# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html## You can get CMake to generate this file for you by adding:# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 )# to your CMakeLists.txt file.## Most projects will NOT need to set this to anything; you can just change the# 'flags' list of compilation flags. Notice that YCM itself uses that approach.compilation_database_folder = ''if os.path.exists( compilation_database_folder ): database = ycm_core.CompilationDatabase( compilation_database_folder )else: database = Nonedef IsHeaderFile( filename ): extension = os.path.splitext( filename )[ 1 ] return extension in [ '.h', '.hxx', '.hpp', '.hh' ]def FindCorrespondingSourceFile( filename ): if IsHeaderFile( filename ): basename = os.path.splitext( filename )[ 0 ] for extension in SOURCE_EXTENSIONS: replacement_file = basename + extension if os.path.exists( replacement_file ): return replacement_file return filenamedef Settings( **kwargs ): if kwargs[ 'language' ] == 'cfamily': # If the file is a header, try to find the corresponding source file and # retrieve its flags from the compilation database if using one. This is # necessary since compilation databases don't have entries for header files. # In addition, use this source file as the translation unit. This makes it # possible to jump from a declaration in the header file to its definition # in the corresponding source file. filename = FindCorrespondingSourceFile( kwargs[ 'filename' ] ) if not database: return { 'flags': flags, 'include_paths_relative_to_dir': DIR_OF_THIS_SCRIPT, 'override_filename': filename } compilation_info = database.GetCompilationInfoForFile( filename ) if not compilation_info.compiler_flags_: return {} # Bear in mind that compilation_info.compiler_flags_ does NOT return a # python list, but a "list-like" StringVec object. final_flags = list( compilation_info.compiler_flags_ ) # NOTE: This is just for YouCompleteMe; it's highly likely that your project # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. try: final_flags.remove( '-stdlib=libc++' ) except ValueError: pass return { 'flags': final_flags, 'include_paths_relative_to_dir': compilation_info.compiler_working_dir_, 'override_filename': filename } return {}def GetStandardLibraryIndexInSysPath( sys_path ): for path in sys_path: if os.path.isfile( os.path.join( path, 'os.py' ) ): return sys_path.index( path ) raise RuntimeError( 'Could not find standard library path in Python path.' )def PythonSysPath( **kwargs ): sys_path = kwargs[ 'sys_path' ] for folder in os.listdir( DIR_OF_THIRD_PARTY ): if folder == 'python-future': folder = os.path.join( folder, 'src' ) sys_path.insert( GetStandardLibraryIndexInSysPath( sys_path ) + 1, os.path.realpath( os.path.join( DIR_OF_THIRD_PARTY, folder ) ) ) continue if folder == 'cregex': interpreter_path = kwargs[ 'interpreter_path' ] major_version = subprocess.check_output( [ interpreter_path, '-c', 'import sys; print( sys.version_info[ 0 ] )' ] ).rstrip().decode( 'utf8' ) folder = os.path.join( folder, 'regex_{}'.format( major_version ) ) sys_path.insert( 0, os.path.realpath( os.path.join( DIR_OF_THIRD_PARTY, folder ) ) ) return sys_path
最初是Dockerfile 编写如下:
##################################################################################################################docker build --no-cache -t xxx:1.0 #################################################################################################################FROM ubuntu:20.04MAINTAINER dingbin dingbinthu@163.comWORKDIR /rootCOPY Dockerfile ./COPY .bashrc ./COPY .vimrc ./COPY .ycm_extra_conf.py ./ENV DEBIAN_FRONTEND=noninteractiveENV TZ=Asia/ShanghaiRUN set -ex && apt-get update && apt-get upgrade -y &&apt-get install -y tzdata &&apt-get install -y net-tools rsync inetutils-ping git curl wget unzip &&apt-get install -y build-essential cmake vim-nox python3-dev &&git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim &&vim -c PluginInstall -c q -c q && \ cd ~/.vim/bundle/YouCompleteMe &&git submodule update --init --recursive && ./install.py --clangd-completerCMD vim
将以上4个文件搁置一个目录下,在任意一台装置了docker的x86_64机器上该目录下执行命令:
docker build --no-cache -t ycm-base:1.0
即可创立一个本地docker镜像名为:ycm-base:1.0
本文作者曾经按如上步骤创立好了一个可用的ycm 根底镜像,并上传到了hub.docker.com名为:apollo008/vim8-ycm:3.0 。地址是:https://hub.docker.com/repository/docker/apollo008/vim8-ycm-customize-user 读者可间接通过docker命令:docker pull apollo008/vim8-ycm:3.0 下载该镜像到本地应用即可。
创立定制用户的docker镜像
以上docker镜像创立的是root用户的。如果应用root账户登录进入docker容器中编辑文件后,必然是root用户所有,导致容器外其余用户没有权限编辑或浏览该文件。解决得方法是才上述根底vim-ycm镜像的根底上,用户本人在本地docker环境中迅速创立一个应用本人用户名(尤其是uid)的账户的ycm docker镜像,而后本地以该特定用户拜访该docker容器即可。之所以分成两个容器,是因为根底容器制作费时,切可能依赖外网,导致装置难以胜利,所以制作好上传至公共镜像仓库,不同用户在即镜像根底上定制一下本人的特定uid和username的本地镜像即可,操作步骤如下。
Dockerfile 内容如下:
FROM apollo008/vim8-ycm:3.0MAINTAINER dingbin dingbinthu@163.comWORKDIR /rootARG APP_UIDARG APP_GIDARG APP_USERARG APP_GROUPRUN set -ex && apt-get install -y sudo openssh-server && \ groupadd -o -g ${APP_GID} ${APP_GROUP} && \ useradd -m -s /bin/bash -o -u ${APP_UID} -g ${APP_GID} ${APP_USER} && \ mkdir -p /etc/sudoers.d && \ echo root:123456 | chpasswd && \ echo ${APP_USER}:123456 | chpasswd && \ echo "${APP_USER} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${APP_USER} && \ chmod 0440 /etc/sudoers.d/${APP_USER} && \ cp /root/.vim /home/${APP_USER}/ -rf && \ cp /root/.vimrc /home/${APP_USER}/ -rf && \ cp /root/.ycm_extra_conf.py /home/${APP_USER}/ -rf && \ chown -R ${APP_USER}:${APP_GROUP} /home/${APP_USER}/.vim && \ chown -R ${APP_USER}:${APP_GROUP} /home/${APP_USER}/.vimrc && \ chown -R ${APP_USER}:${APP_GROUP} /home/${APP_USER}/.ycm_extra_conf.py COPY --chown=${APP_USER}:${APP_GROUP} Dockerfile /home/${APP_USER}/ COPY --chown=${APP_USER}:${APP_GROUP} .bashrc /home/${APP_USER}/ WORKDIR /home/${APP_USER} USER ${APP_USER}CMD vim
该docker镜像内置的vim8.1和ycm是ubuntu 20.04 LTS 截至目前2021.03.22最新版的vim和ycm。 ~/.vimrc 中相应的配置都已欠缺,包含较为正当好看的配色计划。成果如下图。
本镜像用法是: 在本地执行如下命令 创立本人用户名比方work/user等的docker镜像。
docker build --no-cache -t myycm:latest --build-arg APP_USER=work --build-arg APP_GROUP=work --build-arg APP_UID=1000 --build-arg APP_GID=1001 .
镜像生成后举荐用法是:docker run -itd --name ycm1 -v hostPath:InDockerPath myycm:latest /bin/bash
docker exec -it ycm1 /bin/bash 而后在docker容器内的交互bash 上执行 vim xxx.cpp 编辑文件。防止频繁关上 docker container 相应速度慢。