vim按键说明
除了上面简易范例的 i, o,a,Esc, :wq 之外,其实 vim 还有非常多的按键可以使用
这些基本命令需要我们在使用过程中不断的总结,这样才会融会贯通。附上一张vim的键盘图,哈哈。
vim插件之Vundle
先安装vunble(如果没有git的先安装git)
git clone http://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
安装完成后如图会有一个vundle文件
二、打开.vimrc文件在家目录下(如果没有新建一个)
sudo vim ~/.vimrc
将以下内容复制到.vimrc , 保存退出
"语法高亮
syntax on
"显示行号
set number
"显示光标所在位置的行号和列号
set ruler
set wrap "自动折行
set shiftwidth=4
set tabstop=4
set softtabstop=4
set expandtab "将tab替换为相应数量空格
set smartindent
set backspace=2
"设置取消备份 禁止临时文件生成
set nobackup
set noswapfile
"设置匹配模式 类似当输入一个左括号时会匹配相应的那个右括号
set showmatch
"set laststatus=2 "命令行为两行
"set fenc=utf-8 "文件编码
"set mouse=a "启用鼠标
"set ignorecase "忽略大小写
"set cursorline "突出显示当前行
"set cursorcolumn "突出显示当前列
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>
"设置vundle
set nocompatible " be iMproved
filetype off " required!
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()
filetype plugin indent on " required!
"vundle设置完毕
"Bundle 'taglist.vim'
"let Tlist_Ctags_Cmd='ctags'
"let Tlist_Show_One_File=1 "不同时显示多个文件的tag,只显示当前文件的
"let Tlist_WinWidt =28 "设置taglist的宽度
"let Tlist_Exit_OnlyWindow=1 "如果taglist窗口是最后一个窗口,则退出vim
"let Tlist_Use_Right_Window=1 "在右侧窗口中显示taglist窗口
"let Tlist_Use_Left_Windo =1 "在左侧窗口中显示taglist窗口
Bundle 'majutsushi/tagbar'
"nmap <Leader>tb :TagbarToggle<CR> "快捷键设置
let g:tagbar_ctags_bin='ctags' "ctags程序的路径
let g:tagbar_width=20 "窗口宽度的设置
map <F3> :Tagbar<CR>
map <C-t> :Tagbar<CR>
"autocmd BufReadPost *.cpp,*.c,*.h,*.hpp,*.cc,*.cxx call tagbar#autoopen() "如果是c语言的程序的话,tagbar自动开启
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
"光标默认在主窗口
"wincmd w
"autocmd VimEnter * wincmd w
"vim 退出时直接关闭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 多光标选中
"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实时显示
Bundle 'suan/vim-instant-markdown'
"indentLine 代码缩进线标志线
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 自动补全引号(单引号/双引号/反引号), 括号(()[]{})
Bundle 'Raimondi/delimitMate'
:w保存 , 然后进入命令行模式
三、输入一下命令回车 , 等待下载插件完成
: BundleInstall
四、然后让.vimrc文件生效即可
source ~/.vimrc
如果这一步出错可以忽略
打开高亮渲染
在 ~/.vimrc 中配置
set nonu
syntax on
修复 mac 下 vim 无法使用delete删除文本的问题
在 ~/.vimrc 中配置
" fix mac vim delete error, so as set backspace=indent,eol,start
set backspace=2
安装 Vundle
它的使用方法很简单,安装一个插件只需要在.vimrc按照规则中添加 Plugin 的名称,某些需要添加路径,之后在 Vim 中使用:PluginInstall既可以自动化安装。
git 克隆 Vundle 工程到本地
git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
修改.vimrc配置 Plugins。在.vimrc文件中添加如下内容
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
保存后进入 vim 运行命令
:PluginInstall
vundle 命令
# 安装插件
:BundleInstall
# 更新插件
:BundleUpdate
# 清除不需要的插件
:BundleClean
# 列出当前的插件
:BundleList
# 搜索插件
:BundleSearch
注意
插件配置不要在 call vundle#end() 之前,不然插件无法生效
如果配置错误,需要重新配置后,在vim中运行 :PluginInstall
安装 YouCompleteMe
使用 Vundle 安装 YouCompleteMe
在.vimrc中添加如下内容 位置在call vundle#begin()和call vundle#end()之间
Bundle 'Valloric/YouCompleteMe'
在vim中运行命令
: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中添加配置
" 自动补全配置
set completeopt=longest,menu "让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)
autocmd InsertLeave * if pumvisible() == 0|pclose|endif "离开插入模式后自动关闭预览窗口
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>" "回车即选中当前项
"上下左右键的行为 会显示其他信息
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 默认tab s-tab 和自动补全冲突
"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 "关闭加载.ycm_extra_conf.py提示
let g:ycm_collect_identifiers_from_tags_files=1 " 开启 YCM 基于标签引擎
let g:ycm_min_num_of_chars_for_completion=2 " 从第2个键入字符就开始罗列匹配项
let g:ycm_cache_omnifunc=0 " 禁止缓存匹配项,每次都重新生成匹配项
let g:ycm_seed_identifiers_with_syntax=1 " 语法关键字补全
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>
"在注释输入中也能补全
let g:ycm_complete_in_comments = 1
"在字符串输入中也能补全
let g:ycm_complete_in_strings = 1
"注释和字符串中的文字也会被收入补全
let g:ycm_collect_identifiers_from_comments_and_strings = 0
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR> " 跳转到定义处
YCM 安装错误
首先插件需要安装一些dependencies。包括build-essential,cmake,python-dev, python3-dev。在MacOS底下xcode-select --install
取代 Linux底下的‘sudo apt install build-essential’。python 和python 3之前安装vim和macvim的时候其实已经装完了,缺少的只有cmake这个插件。
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
自动安装所有。
/.vimrc
文件中 YouCompleteMe的常用设置, 配置来源 http://howiefh.github.io/2015/05/22/vim-install-youcompleteme-plugin/
set completeopt=longest,menu "让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)
autocmd InsertLeave * if pumvisible() == 0|pclose|endif "离开插入模式后自动关闭预览窗口
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>" "回车即选中当前项
"上下左右键的行为 会显示其他信息
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>"
" 跳转到定义处
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时检查ycm_extra_conf文件的信息
let g:ycm_confirm_extra_conf=0
" 开启基于tag的补全,可以在这之后添加需要的标签路径
let g:ycm_collect_identifiers_from_tags_files=1
"注释和字符串中的文字也会被收入补全
let g:ycm_collect_identifiers_from_comments_and_strings = 0
" 输入第2个字符开始补全
let g:ycm_min_num_of_chars_for_completion=2
" 禁止缓存匹配项,每次都重新生成匹配项
let g:ycm_cache_omnifunc=0
" 开启语义补全
let g:ycm_seed_identifiers_with_syntax=1
"在注释输入中也能补全
let g:ycm_complete_in_comments = 1
"在字符串输入中也能补全
let g:ycm_complete_in_strings = 1
" 设置在下面几种格式的文件上屏蔽ycm
let g:ycm_filetype_blacklist = {
\ 'tagbar' : 1,
\ 'nerdtree' : 1,
\}
"youcompleteme 默认tab s-tab 和 ultisnips 冲突
let g:ycm_key_list_select_completion = ['<Down>']
let g:ycm_key_list_previous_completion = ['<Up>']
" 修改对C函数的补全快捷键,默认是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>"
"定义存放代码片段的文件夹,使用自定义和默认的,将会的到全局,有冲突的会提示
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
}