Mac下安裝Vundle管理YouCompleteMe插件

vim按鍵說明

除了上面簡(jiǎn)易范例的 i, o,a,Esc, :wq 之外,其實(shí) vim 還有非常多的按鍵可以使用

image
image

這些基本命令需要我們?cè)谑褂眠^程中不斷的總結(jié),這樣才會(huì)融會(huì)貫通。附上一張vim的鍵盤圖,哈哈。

image

vim插件之Vundle

先安裝vunble(如果沒有g(shù)it的先安裝git)

git clone http://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

安裝完成后如圖會(huì)有一個(gè)vundle文件

image

二、打開.vimrc文件在家目錄下(如果沒有新建一個(gè))

sudo vim ~/.vimrc

將以下內(nèi)容復(fù)制到.vimrc , 保存退出

"語法高亮
syntax on
"顯示行號(hào)
set number
"顯示光標(biāo)所在位置的行號(hào)和列號(hào)
set ruler
set wrap                      "自動(dòng)折行
set shiftwidth=4
set tabstop=4
set softtabstop=4
set expandtab                  "將tab替換為相應(yīng)數(shù)量空格
set smartindent
set backspace=2
"設(shè)置取消備份 禁止臨時(shí)文件生成
set nobackup
set noswapfile
"設(shè)置匹配模式 類似當(dāng)輸入一個(gè)左括號(hào)時(shí)會(huì)匹配相應(yīng)的那個(gè)右括號(hào)
set showmatch
"set laststatus=2   "命令行為兩行
"set fenc=utf-8     "文件編碼
"set mouse=a        "啟用鼠標(biāo)
"set ignorecase     "忽略大小寫
"set cursorline     "突出顯示當(dāng)前行
"set cursorcolumn   "突出顯示當(dāng)前列

set fdm=marker

"jj退出insert模式
"inoremap <C-j> <ESC>
inoremap jk <ESC>

"nmap ,v "+p
"vmap ,c "+y
"nmap ,c "+y
vmap ,c :w !pbcopy<CR><CR>
nmap ,c :w !pbcopy<CR><CR>
nmap ,v :r !pbpaste<CR><CR>

"設(shè)置vundle
set nocompatible              " be iMproved
filetype off                  " required!

set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

filetype plugin indent on     " required!
"vundle設(shè)置完畢

"Bundle 'taglist.vim'
"let Tlist_Ctags_Cmd='ctags'
"let Tlist_Show_One_File=1               "不同時(shí)顯示多個(gè)文件的tag,只顯示當(dāng)前文件的
"let Tlist_WinWidt =28                   "設(shè)置taglist的寬度
"let Tlist_Exit_OnlyWindow=1             "如果taglist窗口是最后一個(gè)窗口,則退出vim
"let Tlist_Use_Right_Window=1           "在右側(cè)窗口中顯示taglist窗口
"let Tlist_Use_Left_Windo =1             "在左側(cè)窗口中顯示taglist窗口

Bundle 'majutsushi/tagbar'
"nmap <Leader>tb :TagbarToggle<CR>      "快捷鍵設(shè)置
let g:tagbar_ctags_bin='ctags'          "ctags程序的路徑
let g:tagbar_width=20                   "窗口寬度的設(shè)置
map <F3> :Tagbar<CR>
map <C-t> :Tagbar<CR>
"autocmd BufReadPost *.cpp,*.c,*.h,*.hpp,*.cc,*.cxx call tagbar#autoopen()  "如果是c語言的程序的話,tagbar自動(dòng)開啟

Bundle 'scrooloose/nerdtree'
let NERDTreeWinPos='left'
let NERDTreeWinSize=25
let g:NERDTreeNodeDelimiter = "\u00a0"
"let g:NERDTreeNodeDelimiter = ''
"map <F2> :NERDTreeToggle<CR>
map <C-n> :NERDTreeToggle<CR>
"打開NERDTree
"autocmd vimenter * NERDTree
"光標(biāo)默認(rèn)在主窗口
"wincmd w
"autocmd VimEnter * wincmd w
"vim 退出時(shí)直接關(guān)閉NERDTree
"autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif

Bundle 'bling/vim-airline'
set laststatus=2

Bundle 'scrooloose/nerdcommenter'

let mapleader = ','
nnoremap <C-l> gt
nnoremap <C-h> gT
nnoremap <leader>t : tabe<CR>

"vim-multiple-cursors 多光標(biāo)選中
"Bundle 'terryma/vim-multiple-cursors'
"let g:multi_cursor_use_default_mapping=0
"let g:multi_cursor_start_key='<C-m>'
"let g:multi_cursor_start_word_key='g<C-m>'
"let g:multi_cursor_next_key='<C-m>'
"let g:multi_cursor_prev_key='<C-p>'
"let g:multi_cursor_skip_key='<C-x>'
"let g:multi_cursor_quit_key='<C-j>'

"MatchTagAlways
Bundle 'Valloric/MatchTagAlways'

"Markdown語法高亮
Bundle 'godlygeek/tabular'
"Bundle 'plasticboy/vim-markdown'
"markdown實(shí)時(shí)顯示
Bundle 'suan/vim-instant-markdown'

"indentLine 代碼縮進(jìn)線標(biāo)志線
Plugin 'Yggdroot/indentLine'
let g:indentLine_char = '┆'
let g:indentLine_color_term = 239
let g:indentLine_enabled = 1
"映射到ctrl+I鍵
"map <C-i> :IndentLinesToggle<CR>

"delimitMate 自動(dòng)補(bǔ)全引號(hào)(單引號(hào)/雙引號(hào)/反引號(hào)), 括號(hào)(()[]{})
Bundle 'Raimondi/delimitMate'

:w保存 , 然后進(jìn)入命令行模式

三、輸入一下命令回車 , 等待下載插件完成

: BundleInstall

四、然后讓.vimrc文件生效即可

source ~/.vimrc

如果這一步出錯(cuò)可以忽略

打開高亮渲染
在 ~/.vimrc 中配置

set nonu
syntax on

修復(fù) mac 下 vim 無法使用delete刪除文本的問題
在 ~/.vimrc 中配置

" fix mac vim delete error, so as set backspace=indent,eol,start
set backspace=2

安裝 Vundle
它的使用方法很簡(jiǎn)單,安裝一個(gè)插件只需要在.vimrc按照規(guī)則中添加 Plugin 的名稱,某些需要添加路徑,之后在 Vim 中使用:PluginInstall既可以自動(dòng)化安裝。

git 克隆 Vundle 工程到本地

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

修改.vimrc配置 Plugins。在.vimrc文件中添加如下內(nèi)容

set nocompatible " be iMproved, required
filetype off " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'

" The following are examples of different formats supported.
" Keep Plugin commands between vundle#begin/end.

" All of your Plugins must be added before the following line
call vundle#end() " required
filetype plugin indent on " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" Brief help
" :PluginList - lists configured plugins
" :PluginInstall - installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line

保存后進(jìn)入 vim 運(yùn)行命令

:PluginInstall

vundle 命令

# 安裝插件
:BundleInstall
# 更新插件
:BundleUpdate
# 清除不需要的插件
:BundleClean
# 列出當(dāng)前的插件
:BundleList
# 搜索插件
:BundleSearch

注意
插件配置不要在 call vundle#end() 之前,不然插件無法生效
如果配置錯(cuò)誤,需要重新配置后,在vim中運(yùn)行 :PluginInstall
安裝 YouCompleteMe
使用 Vundle 安裝 YouCompleteMe

在.vimrc中添加如下內(nèi)容 位置在call vundle#begin()和call vundle#end()之間

Bundle 'Valloric/YouCompleteMe'

在vim中運(yùn)行命令

:BundleInstall

編譯 YouCompleteMe
編譯過程需要CMake

brew install CMake

帶 C-family languages 語義支持的版本

cd ~/.vim/bundle/YouCompleteMe 
./install.sh --clang-completer

不帶 C-family languages 語義支持的版本

cd ~/.vim/bundle/YouCompleteMe
./install.sh

帶 C# 語義支持的版本

cd ~/.vim/bundle/YouCompleteMe
./install.sh --omnisharp-completer

帶 Go 語言語義支持的版本

cd ~/.vim/bundle/YouCompleteMe
./install.sh --gocode-completer

配置 YCM
在.vimrc中添加配置

" 自動(dòng)補(bǔ)全配置
set completeopt=longest,menu "讓Vim的補(bǔ)全菜單行為與一般IDE一致(參考VimTip1228)
autocmd InsertLeave * if pumvisible() == 0|pclose|endif "離開插入模式后自動(dòng)關(guān)閉預(yù)覽窗口
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>" "回車即選中當(dāng)前項(xiàng)
"上下左右鍵的行為 會(huì)顯示其他信息
inoremap <expr> <Down> pumvisible() ? "\<C-n>" : "\<Down>"
inoremap <expr> <Up> pumvisible() ? "\<C-p>" : "\<Up>"
inoremap <expr> <PageDown> pumvisible() ? "\<PageDown>\<C-p>\<C-n>" : "\<PageDown>"
inoremap <expr> <PageUp> pumvisible() ? "\<PageUp>\<C-p>\<C-n>" : "\<PageUp>"

"youcompleteme 默認(rèn)tab s-tab 和自動(dòng)補(bǔ)全沖突
"let g:ycm_key_list_select_completion=['<c-n>']
let g:ycm_key_list_select_completion = ['<Down>']
"let g:ycm_key_list_previous_completion=['<c-p>']
let g:ycm_key_list_previous_completion = ['<Up>']
let g:ycm_confirm_extra_conf=0 "關(guān)閉加載.ycm_extra_conf.py提示

let g:ycm_collect_identifiers_from_tags_files=1 " 開啟 YCM 基于標(biāo)簽引擎
let g:ycm_min_num_of_chars_for_completion=2 " 從第2個(gè)鍵入字符就開始羅列匹配項(xiàng)
let g:ycm_cache_omnifunc=0 " 禁止緩存匹配項(xiàng),每次都重新生成匹配項(xiàng)
let g:ycm_seed_identifiers_with_syntax=1 " 語法關(guān)鍵字補(bǔ)全
nnoremap <F5> :YcmForceCompileAndDiagnostics<CR> "force recomile with syntastic
"nnoremap <leader>lo :lopen<CR> "open locationlist
"nnoremap <leader>lc :lclose<CR> "close locationlist
inoremap <leader><leader> <C-x><C-o>
"在注釋輸入中也能補(bǔ)全
let g:ycm_complete_in_comments = 1
"在字符串輸入中也能補(bǔ)全
let g:ycm_complete_in_strings = 1
"注釋和字符串中的文字也會(huì)被收入補(bǔ)全
let g:ycm_collect_identifiers_from_comments_and_strings = 0

nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR> " 跳轉(zhuǎn)到定義處

YCM 安裝錯(cuò)誤

首先插件需要安裝一些dependencies。包括build-essential,cmake,python-dev, python3-dev。在MacOS底下xcode-select --install 取代 Linux底下的‘sudo apt install build-essential’。python 和python 3之前安裝vim和macvim的時(shí)候其實(shí)已經(jīng)裝完了,缺少的只有cmake這個(gè)插件。

brew install cmake

然后在 /.vimrc文件中加入

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py'}

帶特定語言支持的安裝方式,上面語句改為

C-family languages

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --clang-completer'}

C# supportbrew install Mono

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --cs-completer'}

Go support

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --go-completer'}

Rust support: support brew install rust

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --rust-completer'}

Java support: support brew cask install java8

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --java-completer'}

全部安裝

Plug 'Valloric/YouCompleteMe',{'do':'python3 install.py --all'}

打開vim,輸入

:PlugInstall

自動(dòng)安裝所有。

/.vimrc文件中 YouCompleteMe的常用設(shè)置, 配置來源 http://howiefh.github.io/2015/05/22/vim-install-youcompleteme-plugin/

set completeopt=longest,menu    "讓Vim的補(bǔ)全菜單行為與一般IDE一致(參考VimTip1228)
autocmd InsertLeave * if pumvisible() == 0|pclose|endif "離開插入模式后自動(dòng)關(guān)閉預(yù)覽窗口
inoremap <expr> <CR>       pumvisible() ? "\<C-y>" : "\<CR>"    "回車即選中當(dāng)前項(xiàng)
"上下左右鍵的行為 會(huì)顯示其他信息
inoremap <expr> <Down>     pumvisible() ? "\<C-n>" : "\<Down>"
inoremap <expr> <Up>       pumvisible() ? "\<C-p>" : "\<Up>"
inoremap <expr> <PageDown> pumvisible() ? "\<PageDown>\<C-p>\<C-n>" : "\<PageDown>"
inoremap <expr> <PageUp>   pumvisible() ? "\<PageUp>\<C-p>\<C-n>" : "\<PageUp>"
" 跳轉(zhuǎn)到定義處
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
nnoremap <F6> :YcmForceCompileAndDiagnostics<CR>    "force recomile with syntastic
" nnoremap <leader>lo :lopen<CR>    "open locationlist
" nnoremap <leader>lc :lclose<CR>   "close locationlist
inoremap <leader><leader> <C-x><C-o>
let g:ycm_global_ycm_extra_conf = '~/.vim/.ycm_extra_conf.py'
" 不顯示開啟vim時(shí)檢查ycm_extra_conf文件的信息  
let g:ycm_confirm_extra_conf=0
" 開啟基于tag的補(bǔ)全,可以在這之后添加需要的標(biāo)簽路徑  
let g:ycm_collect_identifiers_from_tags_files=1
"注釋和字符串中的文字也會(huì)被收入補(bǔ)全
let g:ycm_collect_identifiers_from_comments_and_strings = 0
" 輸入第2個(gè)字符開始補(bǔ)全
let g:ycm_min_num_of_chars_for_completion=2
" 禁止緩存匹配項(xiàng),每次都重新生成匹配項(xiàng)
let g:ycm_cache_omnifunc=0
" 開啟語義補(bǔ)全
let g:ycm_seed_identifiers_with_syntax=1    
"在注釋輸入中也能補(bǔ)全
let g:ycm_complete_in_comments = 1
"在字符串輸入中也能補(bǔ)全
let g:ycm_complete_in_strings = 1
" 設(shè)置在下面幾種格式的文件上屏蔽ycm
let g:ycm_filetype_blacklist = {
      \ 'tagbar' : 1,
      \ 'nerdtree' : 1,
      \}
"youcompleteme  默認(rèn)tab  s-tab 和 ultisnips 沖突
let g:ycm_key_list_select_completion = ['<Down>']
let g:ycm_key_list_previous_completion = ['<Up>']
" 修改對(duì)C函數(shù)的補(bǔ)全快捷鍵,默認(rèn)是CTRL + space,修改為ALT + ;
let g:ycm_key_invoke_completion = '<M-;>'
" SirVer/ultisnips 代碼片斷
" Trigger configuration. Do not use <tab> if you use https://github.com/Valloric/YouCompleteMe.
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
let g:UltiSnipsListSnippets="<c-e>"
"定義存放代碼片段的文件夾,使用自定義和默認(rèn)的,將會(huì)的到全局,有沖突的會(huì)提示
let g:UltiSnipsSnippetDirectories=["plugged/vim-snippets/UltiSnips"]
" 參考https://github.com/Valloric/YouCompleteMe/issues/36#issuecomment-62941322
" 解決ultisnips和ycm tab沖突,如果不使用下面的辦法解決可以參考
" https://github.com/Valloric/YouCompleteMe/issues/36#issuecomment-63205056的配置
" begin
" let g:ycm_key_list_select_completion=['<C-n>', '<Down>']
" let g:ycm_key_list_previous_completion=['<C-p>', '<Up>']
" let g:UltiSnipsExpandTrigger="<Tab>"
" let g:UltiSnipsJumpForwardTrigger="<Tab>"                                           
" let g:UltiSnipsJumpBackwardTrigger="<S-Tab>"
" end
" UltiSnips completion function that tries to expand a snippet. If there's no
" snippet for expanding, it checks for completion window and if it's
" shown, selects first element. If there's no completion window it tries to
" jump to next placeholder. If there's no placeholder it just returns TAB key 
function! g:UltiSnips_Complete()
    call UltiSnips#ExpandSnippet()
    if g:ulti_expand_res == 0
        if pumvisible()
            return "\<C-n>"
        else
            call UltiSnips#JumpForwards()
            if g:ulti_jump_forwards_res == 0
               return "\<TAB>"
            endif
        endif
    endif
    return ""
endfunction
au BufEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
" Expand snippet or return
let g:ulti_expand_res = 1
function! Ulti_ExpandOrEnter()
    call UltiSnips#ExpandSnippet()
    if g:ulti_expand_res
        return ''
    else
        return "\<return>"
endfunction
" Set <space> as primary trigger
inoremap <return> <C-R>=Ulti_ExpandOrEnter()<CR>

~/.vim/.ycm_extra_conf.py文件示范

import os
import os.path
import fnmatch
import logging
import ycm_core
import re

BASE_FLAGS = [
        '-Wall',
        '-Wextra',
        '-Werror',
        '-Wno-long-long',
        '-Wno-variadic-macros',
        '-fexceptions',
        '-ferror-limit=10000',
        '-DNDEBUG',
        '-std=c++11',
        '-xc++',
        '-I/usr/lib/',
        '-I/usr/include/'
        ]

SOURCE_EXTENSIONS = [
        '.cpp',
        '.cxx',
        '.cc',
        '.c',
        '.m',
        '.mm'
        ]

SOURCE_DIRECTORIES = [
        'src',
        'lib'
        ]

HEADER_EXTENSIONS = [
        '.h',
        '.hxx',
        '.hpp',
        '.hh'
        ]

HEADER_DIRECTORIES = [
        'include'
        ]

def IsHeaderFile(filename):
    extension = os.path.splitext(filename)[1]
    return extension in HEADER_EXTENSIONS

def GetCompilationInfoForFile(database, filename):
    if IsHeaderFile(filename):
        basename = os.path.splitext(filename)[0]
        for extension in SOURCE_EXTENSIONS:
            # Get info from the source files by replacing the extension.
            replacement_file = basename + extension
            if os.path.exists(replacement_file):
                compilation_info = database.GetCompilationInfoForFile(replacement_file)
                if compilation_info.compiler_flags_:
                    return compilation_info
            # If that wasn't successful, try replacing possible header directory with possible source directories.
            for header_dir in HEADER_DIRECTORIES:
                for source_dir in SOURCE_DIRECTORIES:
                    src_file = replacement_file.replace(header_dir, source_dir)
                    if os.path.exists(src_file):
                        compilation_info = database.GetCompilationInfoForFile(src_file)
                        if compilation_info.compiler_flags_:
                            return compilation_info
        return None
    return database.GetCompilationInfoForFile(filename)

def FindNearest(path, target, build_folder):
    candidate = os.path.join(path, target)
    if(os.path.isfile(candidate) or os.path.isdir(candidate)):
        logging.info("Found nearest " + target + " at " + candidate)
        return candidate;

    parent = os.path.dirname(os.path.abspath(path));
    if(parent == path):
        raise RuntimeError("Could not find " + target);

    if(build_folder):
        candidate = os.path.join(parent, build_folder, target)
        if(os.path.isfile(candidate) or os.path.isdir(candidate)):
            logging.info("Found nearest " + target + " in build folder at " + candidate)
            return candidate;

    return FindNearest(parent, target, build_folder)

def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
    if not working_directory:
        return list(flags)
    new_flags = []
    make_next_absolute = False
    path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
    for flag in flags:
        new_flag = flag

        if make_next_absolute:
            make_next_absolute = False
            if not flag.startswith('/'):
                new_flag = os.path.join(working_directory, flag)

        for path_flag in path_flags:
            if flag == path_flag:
                make_next_absolute = True
                break

            if flag.startswith(path_flag):
                path = flag[ len(path_flag): ]
                new_flag = path_flag + os.path.join(working_directory, path)
                break

        if new_flag:
            new_flags.append(new_flag)
    return new_flags

def FlagsForClangComplete(root):
    try:
        clang_complete_path = FindNearest(root, '.clang_complete')
        clang_complete_flags = open(clang_complete_path, 'r').read().splitlines()
        return clang_complete_flags
    except:
        return None

def FlagsForInclude(root):
    try:
        include_path = FindNearest(root, 'include')
        flags = []
        for dirroot, dirnames, filenames in os.walk(include_path):
            for dir_path in dirnames:
                real_path = os.path.join(dirroot, dir_path)
                flags = flags + ["-I" + real_path]
        return flags
    except:
        return None

def FlagsForCompilationDatabase(root, filename):
    try:
        # Last argument of next function is the name of the build folder for
        # out of source projects
        compilation_db_path = FindNearest(root, 'compile_commands.json', 'build')
        compilation_db_dir = os.path.dirname(compilation_db_path)
        logging.info("Set compilation database directory to " + compilation_db_dir)
        compilation_db =  ycm_core.CompilationDatabase(compilation_db_dir)
        if not compilation_db:
            logging.info("Compilation database file found but unable to load")
            return None
        compilation_info = GetCompilationInfoForFile(compilation_db, filename)
        if not compilation_info:
            logging.info("No compilation info for " + filename + " in compilation database")
            return None
        return MakeRelativePathsInFlagsAbsolute(
                compilation_info.compiler_flags_,
                compilation_info.compiler_working_dir_)
    except:
        return None

def FlagsForFile(filename):
    root = os.path.realpath(filename);
    compilation_db_flags = FlagsForCompilationDatabase(root, filename)
    if compilation_db_flags:
        final_flags = compilation_db_flags
    else:
        final_flags = BASE_FLAGS
        clang_flags = FlagsForClangComplete(root)
        if clang_flags:
            final_flags = final_flags + clang_flags
        include_flags = FlagsForInclude(root)
        if include_flags:
            final_flags = final_flags + include_flags
    return {
            'flags': final_flags,
            'do_cache': True
            }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容