├── .gitignore ├── .gitmodules ├── README.md ├── UltiSnips ├── all.snippets ├── c.snippets ├── go.snippets ├── python.snippets └── snippets.snippets ├── autoload └── plug.vim ├── install.sh ├── others ├── iterm2-colors-solarized │ ├── README.md │ ├── Solarized Dark.itermcolors │ └── Solarized Light.itermcolors └── tern-project ├── vimrc └── vimrc.bundles /.gitignore: -------------------------------------------------------------------------------- 1 | bundle 2 | *.pyc 3 | *.bak 4 | *.bk 5 | configs 6 | myconfig.sh 7 | init.vim 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NFhook/k-vim/b2fbba1a96bb426b70e590ccac46d2065749b71d/.gitmodules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | k-vim 2 | ======================= 3 | 4 | 5 | > VERSION: 9.2 6 | 7 | > LAST_UPDATE_TIME: 2017-07-29 8 | 9 | > 本次更新: 小版本更新, 支持vim8异步语法检查 10 | 11 | 详细 [更新日志](https://github.com/wklken/k-vim/wiki/UPDATE_LOG) 12 | 13 | # 目标 14 | 15 | > Just a Better Vim Config. Keep it Simple. 16 | 17 | 18 | **PS**: 服务器端无插件`k-vim`简化版本(curl直接设置vimrc即可)[vim-for-server](https://github.com/wklken/vim-for-server) / vscode-vim配置(尽量一致的键位) [k-vim-vscode](https://github.com/wklken/k-vim-vscode) 19 | 20 | **PPS**: 一份tmux配置 [k-tmux](https://github.com/wklken/k-tmux) 21 | 22 | --------------------------------- 23 | 24 | --------------------------------- 25 | 26 | # 截图 27 | 28 | solarized主题 29 | 30 | ![solarized](https://github.com/wklken/gallery/blob/master/vim/solarized.png?raw=true) 31 | 32 | molokai主题 33 | 34 | ![molokai](https://github.com/wklken/gallery/blob/master/vim/molokai.png?raw=true) 35 | 36 | --------------------------------- 37 | --------------------------------- 38 | 39 | # 安装步骤 40 | 41 | ### 1. clone 到本地 42 | 43 | ``` 44 | git clone https://github.com/wklken/k-vim.git 45 | ``` 46 | 47 | 48 | ### 2. 安装依赖包 49 | 50 | 51 | ##### 2.1 系统依赖 # ctags, ag(the_silver_searcher) 52 | 53 | ``` 54 | # ubuntu 55 | sudo apt-get install ctags 56 | sudo apt-get install build-essential cmake python-dev #编译YCM自动补全插件依赖 57 | sudo apt-get install silversearcher-ag 58 | 59 | # centos 60 | sudo yum install python-devel.x86_64 61 | sudo yum groupinstall 'Development Tools' 62 | sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 63 | sudo yum install the_silver_searcher 64 | sudo yum install cmake 65 | 66 | # mac 67 | brew install ctags 68 | brew install the_silver_searcher 69 | ``` 70 | 71 | ##### 2.2 使用Python 72 | 73 | ``` 74 | sudo pip install flake8 yapf 75 | ``` 76 | 77 | ##### 2.3 如果使用Javascript(不需要的跳过) 78 | 79 | ``` 80 | # 安装jshint和jslint,用于javascript语法检查 81 | # 需要nodejs支持,各个系统安装见文档 https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager 82 | 83 | # ubuntu 84 | sudo apt-get install nodejs npm 85 | sudo npm install -g jslint 86 | sudo npm install jshint -g 87 | sudo npm install -g eslint eslint-plugin-standard eslint-plugin-promise eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-html babel-eslint 88 | 89 | # mac 90 | brew install node 91 | npm install jshint -g 92 | npm install jslint -g 93 | npm install -g eslint eslint-plugin-standard eslint-plugin-promise eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-html babel-eslint 94 | ``` 95 | 96 | 97 | ### 3. 安装 98 | 99 | ``` 100 | 进入目录, 执行安装 101 | # 注意原先装过的童鞋, 重装时,不要到~/.vim下执行(这是软连接指向k-vim真是目录),必须到k-vim原生目录执行 102 | # 会进入安装插件的列表,一安装是从github clone的,完全取决于网速, 之后会自动编译 YCM, 编译失败的话需要手动编译, 有问题见YCM文档 103 | # 如果发现有插件安装失败 可以进入vim, 执行`:PlugInstall' 104 | 105 | cd k-vim/ 106 | sh -x install.sh 107 | ``` 108 | 109 | ------------------------ 110 | ------------------------ 111 | 112 | # 移除安装 113 | 114 | ``` 115 | cd ~ && rm -rf .vim .vimrc .vimrc.bundles && cd - 116 | ``` 117 | 118 | --------------------------------- 119 | --------------------------------- 120 | 121 | # 常见问题 122 | 123 | 详见 [wiki](https://github.com/wklken/k-vim/wiki) 以及 [issues](https://github.com/wklken/k-vim/issues) 124 | 125 | 126 | ------------------------ 127 | ------------------------ 128 | 129 | # 插件 130 | 131 | ### 选择安装插件集合 132 | 133 | 编辑vimrc.bundles中 134 | 135 | ``` 136 | " more options: ['json', 'nginx', 'golang', 'ruby', 'less', 'json', ] 137 | let g:bundle_groups=['python', 'javascript', 'markdown', 'html', 'css', 'tmux', 'beta'] 138 | ``` 139 | 140 | 选定集合后, 使用插件管理工具进行安装/更新 141 | 142 | ### 插件管理 143 | 144 | 使用 [vim-plug](https://github.com/junegunn/vim-plug) 管理插件 145 | 146 | `vim-plug` 常见问题: [vim-plug faq](https://github.com/junegunn/vim-plug/wiki/faq) / [YCM timeout](https://github.com/junegunn/vim-plug/wiki/faq#youcompleteme-timeout) 147 | /[YCM 国人在国内做的镜像](https://github.com/LooEv/A-bridge-to-YouCompleteMe) 148 | 149 | 管理插件的命令 150 | 151 | ``` 152 | :PlugInstall install 安装插件 153 | :PlugUpdate install or update 更新插件 154 | :PlugClean remove plugin not in list 删除本地无用插件 155 | :PlugUpgrade Upgrade vim-plug itself 升级本身 156 | :PlugStatus Check the status of plugins 查看插件状态 157 | ``` 158 | 159 | 160 | 161 | ### 插件列表 162 | 163 | 说明/演示/自定义快捷键等, 待处理 164 | 165 | ------------------------ 166 | ------------------------ 167 | 168 | 169 | # 自定义快捷键 170 | 171 | ``` 172 | 注意, 以下 ',' 代表 173 | 1. 可以自己修改vimrc中配置,决定是否开启鼠标 174 | 175 | set mouse-=a " 鼠标暂不启用, 键盘党.... 176 | set mouse=a " 开启鼠标 177 | 178 | 2. 退出vim后,内容显示在终端屏幕, 可以用于查看和复制, 如果不需要可以关掉 179 | 好处:误删什么的,如果以前屏幕打开,可以找回....惨痛的经历 180 | 181 | set t_ti= t_te= 182 | 183 | 3. 可以自己修改vimrc决定是否使用方向键进行上下左右移动,默认关闭,强迫自己用 hjkl,可以注解 184 | hjkl 上下左右 185 | 186 | map 187 | map 188 | map 189 | map 190 | 191 | 4. 上排F功能键 192 | 193 | F1 废弃这个键,防止调出系统帮助 194 | F2 set nu/nonu,行号开关,用于鼠标复制代码用 195 | F3 set list/nolist,显示可打印字符开关 196 | F4 set wrap/nowrap,换行开关 197 | F5 set paste/nopaste,粘贴模式paste_mode开关,用于有格式的代码粘贴 198 | F6 syntax on/off,语法开关,关闭语法可以加快大文件的展示 199 | 200 | F9 tagbar 201 | F10 运行当前文件(quickrun) 202 | 203 | 5. 分屏移动 204 | 205 | ctrl + j/k/h/l 进行上下左右窗口跳转,不需要ctrl+w+jkhl 206 | 207 | 6. 搜索 208 | 空格,进入搜索状态 209 | / 同上 210 | ,/ 去除匹配高亮 211 | 212 | (交换了#/* 号键功能, 更符合直觉, 其实是离左手更近) 213 | # 正向查找光标下的词 214 | * 反向查找光标下的词 215 | 216 | 优化搜索保证结果在屏幕中间 217 | 218 | 7. tab操作 219 | ctrl+t 新建一个tab 220 | 221 | (hjkl) 222 | ,th 切第1个tab 223 | ,tl 切最后一个tab 224 | ,tj 下一个tab 225 | ,tk 前一个tab 226 | 227 | ,tn 下一个tab(next) 228 | ,tp 前一个tab(previous) 229 | 230 | ,td 关闭tab 231 | ,te tabedit 232 | ,tm tabm 233 | 234 | ,1 切第1个tab 235 | ,2 切第2个tab 236 | ... 237 | ,9 切第9个tab 238 | ,0 切最后一个tab 239 | 240 | ,tt 最近使用两个tab之间切换 241 | (可修改配置位 ctrl+o, 但是ctrl+o/i为系统光标相关快捷键, 故不采用) 242 | 243 | 8. buffer操作(不建议, 建议使用ctrlspace插件来操作) 244 | [b 前一个buffer 245 | ]b 后一个buffer 246 | <- 前一个buffer 247 | -> 后一个buffer 248 | 249 | 250 | 9. 按键修改 251 | Y =y$ 复制到行尾 252 | U =Ctrl-r 253 | ,sa select all,全选 254 | gv 选中并高亮最后一次插入的内容 255 | ,v 选中段落 256 | kj 代替,不用到角落去按esc了 257 | 258 | ,q :q,退出vim 259 | ,w :w, 保存当前文件 260 | 261 | ctrl+n 相对/绝对行号切换 262 | normal模式下回车选中当前项 263 | 264 | 更多细节优化: 265 | 1. j/k 对于换行展示移动更友好 266 | 2. HL 修改成 ^$, 更方便在同行移动 267 | 3. ; 修改成 : ,一键进入命令行模式,不需要按shift 268 | 4. 命令行模式 ctrl+a/e 到开始结尾 269 | 5. <和> 代码缩进后自动再次选中, 方便连续多次缩进, esc退出 270 | 6. 对py文件,保存自动去行尾空白,打开自动加行首代码 271 | 7. 'w!!'强制保存, 即使readonly 272 | 8. 去掉错误输入提示 273 | 9. 交换\`和', '能跳转到准确行列位置 274 | 10. python/ruby 等, 保存时自动去行尾空白 275 | 11. 统一所有分屏打开的操作位v/s[nerdtree/ctrlspace] (特殊ctrlp ctrl+v/x) 276 | 12. ',zz' 代码折叠toggle 277 | 13. python使用"""添加docstring会自动补全三引号 278 | 14. Python使用#进行注释时, 自动缩进 279 | ``` 280 | 281 | ------------------------ 282 | ------------------------ 283 | 284 | ### UPDATE_LOG 285 | 286 | version 9.2 287 | 288 | ``` 289 | 插件部分: 290 | 1. 增加 w0rp/ale 异步语法检查插件, 用户vim版本为8.0时自动启用. 非8时, 启用默认scrooloose/syntastic, 两套插件快捷键一致 291 | 2. 切换使用flake8作为python风格检查(pip install pep8) 292 | 3. 启用yapf作为python代码格式化(pip install yapf) 293 | 4. 启用eslint作为javascript代码检查 294 | 5. YCM 设置回车选中不再弹补全框 295 | 296 | 细节: 297 | 1. 新增快捷键 gv 选中并高亮最后一次插入的内容 298 | ``` 299 | 300 | ### Contributors 301 | 302 | thx a lot. 可以给我提pull request:) 303 | 304 | 查看详情 [git-contributors](https://github.com/wklken/k-vim/graphs/contributors) 305 | 306 | ### Inspire 307 | 308 | 1. vimrc文件布局`vimrc+vimrc.bundles`配置方式参考 [maximum-awesome](https://github.com/square/maximum-awesome) 309 | 310 | 2. install.sh 参考`spf13-vim` 的`bootstrap.sh` [spf13-vim](https://github.com/spf13/spf13-vim) 311 | 312 | 2. 插件管理使用[Vim-plug](https://github.com/junegunn/vim-plug) 313 | 314 | 3. 自动补全 [YCM](https://github.com/Valloric/YouCompleteMe) 315 | 316 | 4. 插件挑选 [VimAwesome](http://vimawesome.com/) 317 | 318 | ### Resources 319 | 320 | [链接](http://www.wklken.me/posts/2014/10/03/vim-resources.html) 321 | 322 | ### Donation 323 | 324 | 如果你认为对你有所帮助, You can Buy me a coffee:) 325 | 326 | 327 | ![donation](https://raw.githubusercontent.com/wklken/gallery/master/donation/donation_w.jpg) 328 | 329 | ### Stargazers over time 330 | 331 | [![Stargazers over time](https://starchart.cc/wklken/k-vim.svg)](https://starchart.cc/wklken/k-vim) 332 | 333 | 334 | ------------------------ 335 | ------------------------ 336 | 337 | The End! 338 | 339 | wklken (凌岳/pythoner/vim党预备党员) 340 | 341 | Github: https://github.com/wklken 342 | 343 | Blog: [http://www.wklken.me](http://www.wklken.me) 344 | 345 | 2013-06-11 于深圳 346 | 347 | 348 | -------------------------------------------------------------------------------- /UltiSnips/all.snippets: -------------------------------------------------------------------------------- 1 | # Global snippets 2 | 3 | snippet Copy 4 | Copyright (c) ${1:`!v g:snips_author`} <${2:`!v g:snips_author_email`}>. All Rights Reserved. 5 | $0 6 | endsnippet 7 | 8 | 9 | 10 | snippet date 11 | `!v strftime("%Y-%m-%d %H:%M:%S")` 12 | endsnippet 13 | 14 | 15 | 16 | snippet datez 17 | `!v strftime("%Y-%m-%d %H:%M:%S %z")` 18 | endsnippet 19 | 20 | 21 | 22 | snippet ts 23 | vim: set ts=${1:4} sw=${2:$1}${3: MORE OPTIONS}:$0 24 | endsnippet 25 | 26 | 27 | 28 | snippet ddate 29 | `!v strftime("%B %d, %Y")` 30 | endsnippet 31 | 32 | snippet sdate 33 | `!v strftime("%Y.%m.%d")` 34 | endsnippet 35 | 36 | snippet blog 37 | Title: ${1} 38 | Slug: ${2} 39 | Date: ${3} 40 | Category: ${4} 41 | Tags: ${5} 42 | 43 | endsnippet 44 | 45 | 46 | snippet /td 47 | /* TODO: ${1} 48 | */ 49 | endsnippet 50 | 51 | snippet /mk 52 | /* MARK: ${1} 53 | */ 54 | endsnippet 55 | 56 | snippet mko 57 | ${_(u'')}${1} 58 | endsnippet 59 | 60 | snippet mkl 61 | ' + gettext("") + '${1} 62 | endsnippet 63 | 64 | snippet rms 65 | # TODO: remove this 66 | endsnippet 67 | 68 | snippet nqa 69 | # noqa 70 | endsnippet 71 | -------------------------------------------------------------------------------- /UltiSnips/c.snippets: -------------------------------------------------------------------------------- 1 | snippet r 2 | return ${1}; 3 | endsnippet 4 | -------------------------------------------------------------------------------- /UltiSnips/go.snippets: -------------------------------------------------------------------------------- 1 | snippet pa 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | ${1} 10 | } 11 | endsnippet 12 | 13 | snippet fu 14 | func ${1}(${2}) ${3} { 15 | ${4} 16 | } 17 | endsnippet 18 | 19 | snippet pr 20 | println(${1}) 21 | endsnippet 22 | 23 | snippet ty 24 | type ${1} struct { 25 | ${2} 26 | } 27 | endsnippet 28 | 29 | snippet t 30 | true${1} 31 | endsnippet 32 | 33 | snippet f 34 | false${1} 35 | endsnippet 36 | 37 | snippet r 38 | return${1} 39 | endsnippet 40 | 41 | snippet s 42 | string${1} 43 | endsnippet 44 | 45 | snippet fpl 46 | fmt.Println("${1}") 47 | endsnippet 48 | 49 | snippet fpf 50 | fmt.Printf("${1}", ${2}) 51 | endsnippet 52 | 53 | snippet err 54 | if err != nil { 55 | ${1} 56 | } 57 | endsnippet 58 | 59 | snippet /* 60 | /* 61 | ${1} 62 | 63 | 64 | */ 65 | endsnippet 66 | 67 | 68 | -------------------------------------------------------------------------------- /UltiSnips/python.snippets: -------------------------------------------------------------------------------- 1 | ########### header and bottom 2 | snippet code "coding:utf-8" 3 | # coding: utf-8 4 | endsnippet 5 | 6 | snippet main "if main" 7 | if __name__ == '__main__': 8 | ${1} 9 | endsnippet 10 | 11 | ########### import 12 | snippet im "import" 13 | import ${1} 14 | endsnippet 15 | 16 | snippet imp "import" 17 | import ${1:module} 18 | ${2} 19 | endsnippet 20 | 21 | snippet fim "from . import ." 22 | from ${1} import ${2} 23 | endsnippet 24 | 25 | 26 | snippet from "from . import ." 27 | from ${1} import ${2} 28 | endsnippet 29 | 30 | ########### single char 31 | snippet t "True" 32 | True${1} 33 | endsnippet 34 | 35 | snippet f "False" 36 | False${1} 37 | endsnippet 38 | 39 | snippet n "None" 40 | None${1} 41 | endsnippet 42 | 43 | snippet r "return" 44 | return ${1} 45 | endsnippet 46 | 47 | snippet s "self." 48 | self.${1} 49 | endsnippet 50 | 51 | snippet p "print" 52 | print ${1} 53 | endsnippet 54 | 55 | snippet pr "print " 56 | print "${1}" 57 | endsnippet 58 | 59 | snippet pri "print ''" 60 | print '${1}' 61 | endsnippet 62 | 63 | snippet prt "print trace" 64 | print "TRACK ================= ${1}", ${2} 65 | endsnippet 66 | 67 | snippet rep "repr" 68 | repr(${1}) 69 | endsnippet 70 | 71 | snippet repr "repr" 72 | repr(${1}) 73 | endsnippet 74 | 75 | snippet _ "__func__" 76 | __${1:init}__${2} 77 | endsnippet 78 | 79 | snippet # "# xxxx" 80 | # ${1} 81 | endsnippet 82 | 83 | snippet a "assert" 84 | assert ${1} 85 | endsnippet 86 | 87 | snippet isi "isinstance" 88 | isinstance(${1}, ${2}) 89 | endsnippet 90 | 91 | ############# 逻辑控制 92 | snippet el "else" 93 | else: 94 | ${0:# TODO} 95 | endsnippet 96 | 97 | snippet ei "elif" 98 | elif ${1}: 99 | ${2} 100 | endsnippet 101 | 102 | snippet while "while" 103 | while ${1:expression}: 104 | ${0:# TODO} 105 | endsnippet 106 | 107 | ############# 108 | 109 | snippet defs "defs" 110 | def ${1:fname}(self, ${2:**kwargs}): 111 | """${3:docstring for $1}""" 112 | ${3:pass} 113 | endsnippet 114 | 115 | snippet pro "property" 116 | def ${1}(): 117 | doc = "${2: The $1 property.}" 118 | def fget(self): 119 | ${3:return self._$1} 120 | def fset(self, value): 121 | ${4:self._$1 = value} 122 | def fdel(self): 123 | ${5:del self._$1} 124 | return locals() 125 | $1 = property(**$1()) 126 | endsnippet 127 | 128 | snippet init "init" 129 | def __init__(self, ${1:args}): 130 | ${2} 131 | endsnippet 132 | 133 | snippet doc "docstring" 134 | """ 135 | @Author: ${1:`wklken`} 136 | @Email: ${2:`wklken@yeah.net`} 137 | @Date: ${3} 138 | @Desc: ${4} 139 | """ 140 | endsnippet 141 | 142 | snippet rai "raise" 143 | raise ${1} 144 | endsnippet 145 | 146 | snippet tr "traceback" 147 | import traceback; traceback.print_exc() 148 | endsnippet 149 | ############# 150 | 151 | snippet fin "[i for i in l]" 152 | [${1:item} for ${2:$1} in ${3}] 153 | endsnippet 154 | 155 | snippet finif "[i for i in l if i]" 156 | [${1:item} for ${2:$1} in ${3} if ${4:$1}] 157 | endsnippet 158 | 159 | snippet td "TODO:" 160 | TODO: ${1} 161 | endsnippet 162 | 163 | snippet dk "api doc" 164 | :url: ${1} 165 | :method: POST GET 166 | :params: 167 | 168 | None 169 | 170 | :return:(json/jsonp) 171 | 172 | code: 173 | code: 174 | code: 175 | 176 | endsnippet 177 | -------------------------------------------------------------------------------- /UltiSnips/snippets.snippets: -------------------------------------------------------------------------------- 1 | snippet "snip(pet)?" "Snippet to create snippets" r 2 | snippet ${1:name}${2: ${3:"${4:$1 description}"}${5: ${6:}}} 3 | $0 4 | `!v "endsnippet"` 5 | endsnippet 6 | 7 | 8 | 9 | snippet ext 10 | extends ${0:what?} 11 | endsnippet 12 | -------------------------------------------------------------------------------- /autoload/plug.vim: -------------------------------------------------------------------------------- 1 | " vim-plug: Vim plugin manager 2 | " ============================ 3 | " 4 | " Download plug.vim and put it in ~/.vim/autoload 5 | " 6 | " curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ 7 | " https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 8 | " 9 | " Edit your .vimrc 10 | " 11 | " call plug#begin('~/.vim/plugged') 12 | " 13 | " " Make sure you use single quotes 14 | " 15 | " " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align 16 | " Plug 'junegunn/vim-easy-align' 17 | " 18 | " " Any valid git URL is allowed 19 | " Plug 'https://github.com/junegunn/vim-github-dashboard.git' 20 | " 21 | " " Multiple Plug commands can be written in a single line using | separators 22 | " Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' 23 | " 24 | " " On-demand loading 25 | " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } 26 | " Plug 'tpope/vim-fireplace', { 'for': 'clojure' } 27 | " 28 | " " Using a non-master branch 29 | " Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } 30 | " 31 | " " Using a tagged release; wildcard allowed (requires git 1.9.2 or above) 32 | " Plug 'fatih/vim-go', { 'tag': '*' } 33 | " 34 | " " Plugin options 35 | " Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' } 36 | " 37 | " " Plugin outside ~/.vim/plugged with post-update hook 38 | " Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } 39 | " 40 | " " Unmanaged plugin (manually installed and updated) 41 | " Plug '~/my-prototype-plugin' 42 | " 43 | " " Initialize plugin system 44 | " call plug#end() 45 | " 46 | " Then reload .vimrc and :PlugInstall to install plugins. 47 | " 48 | " Plug options: 49 | " 50 | "| Option | Description | 51 | "| ----------------------- | ------------------------------------------------ | 52 | "| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use | 53 | "| `rtp` | Subdirectory that contains Vim plugin | 54 | "| `dir` | Custom directory for the plugin | 55 | "| `as` | Use different name for the plugin | 56 | "| `do` | Post-update hook (string or funcref) | 57 | "| `on` | On-demand loading: Commands or ``-mappings | 58 | "| `for` | On-demand loading: File types | 59 | "| `frozen` | Do not update unless explicitly specified | 60 | " 61 | " More information: https://github.com/junegunn/vim-plug 62 | " 63 | " 64 | " Copyright (c) 2017 Junegunn Choi 65 | " 66 | " MIT License 67 | " 68 | " Permission is hereby granted, free of charge, to any person obtaining 69 | " a copy of this software and associated documentation files (the 70 | " "Software"), to deal in the Software without restriction, including 71 | " without limitation the rights to use, copy, modify, merge, publish, 72 | " distribute, sublicense, and/or sell copies of the Software, and to 73 | " permit persons to whom the Software is furnished to do so, subject to 74 | " the following conditions: 75 | " 76 | " The above copyright notice and this permission notice shall be 77 | " included in all copies or substantial portions of the Software. 78 | " 79 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 80 | " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 81 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 82 | " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 83 | " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 84 | " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 85 | " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 86 | 87 | if exists('g:loaded_plug') 88 | finish 89 | endif 90 | let g:loaded_plug = 1 91 | 92 | let s:cpo_save = &cpo 93 | set cpo&vim 94 | 95 | let s:plug_src = 'https://github.com/junegunn/vim-plug.git' 96 | let s:plug_tab = get(s:, 'plug_tab', -1) 97 | let s:plug_buf = get(s:, 'plug_buf', -1) 98 | let s:mac_gui = has('gui_macvim') && has('gui_running') 99 | let s:is_win = has('win32') || has('win64') 100 | let s:nvim = has('nvim') && exists('*jobwait') && !s:is_win 101 | let s:vim8 = has('patch-8.0.0039') && exists('*job_start') 102 | let s:me = resolve(expand(':p')) 103 | let s:base_spec = { 'branch': 'master', 'frozen': 0 } 104 | let s:TYPE = { 105 | \ 'string': type(''), 106 | \ 'list': type([]), 107 | \ 'dict': type({}), 108 | \ 'funcref': type(function('call')) 109 | \ } 110 | let s:loaded = get(s:, 'loaded', {}) 111 | let s:triggers = get(s:, 'triggers', {}) 112 | 113 | function! plug#begin(...) 114 | if a:0 > 0 115 | let s:plug_home_org = a:1 116 | let home = s:path(fnamemodify(expand(a:1), ':p')) 117 | elseif exists('g:plug_home') 118 | let home = s:path(g:plug_home) 119 | elseif !empty(&rtp) 120 | let home = s:path(split(&rtp, ',')[0]) . '/plugged' 121 | else 122 | return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.') 123 | endif 124 | 125 | let g:plug_home = home 126 | let g:plugs = {} 127 | let g:plugs_order = [] 128 | let s:triggers = {} 129 | 130 | call s:define_commands() 131 | return 1 132 | endfunction 133 | 134 | function! s:define_commands() 135 | command! -nargs=+ -bar Plug call plug#() 136 | if !executable('git') 137 | return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.') 138 | endif 139 | command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(0, []) 140 | command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(0, []) 141 | command! -nargs=0 -bar -bang PlugClean call s:clean(0) 142 | command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif 143 | command! -nargs=0 -bar PlugStatus call s:status() 144 | command! -nargs=0 -bar PlugDiff call s:diff() 145 | command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(0, ) 146 | endfunction 147 | 148 | function! s:to_a(v) 149 | return type(a:v) == s:TYPE.list ? a:v : [a:v] 150 | endfunction 151 | 152 | function! s:to_s(v) 153 | return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" 154 | endfunction 155 | 156 | function! s:glob(from, pattern) 157 | return s:lines(globpath(a:from, a:pattern)) 158 | endfunction 159 | 160 | function! s:source(from, ...) 161 | let found = 0 162 | for pattern in a:000 163 | for vim in s:glob(a:from, pattern) 164 | execute 'source' s:esc(vim) 165 | let found = 1 166 | endfor 167 | endfor 168 | return found 169 | endfunction 170 | 171 | function! s:assoc(dict, key, val) 172 | let a:dict[a:key] = add(get(a:dict, a:key, []), a:val) 173 | endfunction 174 | 175 | function! s:ask(message, ...) 176 | call inputsave() 177 | echohl WarningMsg 178 | let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) ')) 179 | echohl None 180 | call inputrestore() 181 | echo "\r" 182 | return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0 183 | endfunction 184 | 185 | function! s:ask_no_interrupt(...) 186 | try 187 | return call('s:ask', a:000) 188 | catch 189 | return 0 190 | endtry 191 | endfunction 192 | 193 | function! plug#end() 194 | if !exists('g:plugs') 195 | return s:err('Call plug#begin() first') 196 | endif 197 | 198 | if exists('#PlugLOD') 199 | augroup PlugLOD 200 | autocmd! 201 | augroup END 202 | augroup! PlugLOD 203 | endif 204 | let lod = { 'ft': {}, 'map': {}, 'cmd': {} } 205 | 206 | if exists('g:did_load_filetypes') 207 | filetype off 208 | endif 209 | for name in g:plugs_order 210 | if !has_key(g:plugs, name) 211 | continue 212 | endif 213 | let plug = g:plugs[name] 214 | if get(s:loaded, name, 0) || !has_key(plug, 'on') && !has_key(plug, 'for') 215 | let s:loaded[name] = 1 216 | continue 217 | endif 218 | 219 | if has_key(plug, 'on') 220 | let s:triggers[name] = { 'map': [], 'cmd': [] } 221 | for cmd in s:to_a(plug.on) 222 | if cmd =~? '^.\+' 223 | if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) 224 | call s:assoc(lod.map, cmd, name) 225 | endif 226 | call add(s:triggers[name].map, cmd) 227 | elseif cmd =~# '^[A-Z]' 228 | let cmd = substitute(cmd, '!*$', '', '') 229 | if exists(':'.cmd) != 2 230 | call s:assoc(lod.cmd, cmd, name) 231 | endif 232 | call add(s:triggers[name].cmd, cmd) 233 | else 234 | call s:err('Invalid `on` option: '.cmd. 235 | \ '. Should start with an uppercase letter or ``.') 236 | endif 237 | endfor 238 | endif 239 | 240 | if has_key(plug, 'for') 241 | let types = s:to_a(plug.for) 242 | if !empty(types) 243 | augroup filetypedetect 244 | call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') 245 | augroup END 246 | endif 247 | for type in types 248 | call s:assoc(lod.ft, type, name) 249 | endfor 250 | endif 251 | endfor 252 | 253 | for [cmd, names] in items(lod.cmd) 254 | execute printf( 255 | \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , %s)', 256 | \ cmd, string(cmd), string(names)) 257 | endfor 258 | 259 | for [map, names] in items(lod.map) 260 | for [mode, map_prefix, key_prefix] in 261 | \ [['i', '', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] 262 | execute printf( 263 | \ '%snoremap %s %s:call lod_map(%s, %s, %s, "%s")', 264 | \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix) 265 | endfor 266 | endfor 267 | 268 | for [ft, names] in items(lod.ft) 269 | augroup PlugLOD 270 | execute printf('autocmd FileType %s call lod_ft(%s, %s)', 271 | \ ft, string(ft), string(names)) 272 | augroup END 273 | endfor 274 | 275 | call s:reorg_rtp() 276 | filetype plugin indent on 277 | if has('vim_starting') 278 | if has('syntax') && !exists('g:syntax_on') 279 | syntax enable 280 | end 281 | else 282 | call s:reload_plugins() 283 | endif 284 | endfunction 285 | 286 | function! s:loaded_names() 287 | return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)') 288 | endfunction 289 | 290 | function! s:load_plugin(spec) 291 | call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim') 292 | endfunction 293 | 294 | function! s:reload_plugins() 295 | for name in s:loaded_names() 296 | call s:load_plugin(g:plugs[name]) 297 | endfor 298 | endfunction 299 | 300 | function! s:trim(str) 301 | return substitute(a:str, '[\/]\+$', '', '') 302 | endfunction 303 | 304 | function! s:version_requirement(val, min) 305 | for idx in range(0, len(a:min) - 1) 306 | let v = get(a:val, idx, 0) 307 | if v < a:min[idx] | return 0 308 | elseif v > a:min[idx] | return 1 309 | endif 310 | endfor 311 | return 1 312 | endfunction 313 | 314 | function! s:git_version_requirement(...) 315 | if !exists('s:git_version') 316 | let s:git_version = map(split(split(s:system('git --version'))[2], '\.'), 'str2nr(v:val)') 317 | endif 318 | return s:version_requirement(s:git_version, a:000) 319 | endfunction 320 | 321 | function! s:progress_opt(base) 322 | return a:base && !s:is_win && 323 | \ s:git_version_requirement(1, 7, 1) ? '--progress' : '' 324 | endfunction 325 | 326 | if s:is_win 327 | function! s:rtp(spec) 328 | return s:path(a:spec.dir . get(a:spec, 'rtp', '')) 329 | endfunction 330 | 331 | function! s:path(path) 332 | return s:trim(substitute(a:path, '/', '\', 'g')) 333 | endfunction 334 | 335 | function! s:dirpath(path) 336 | return s:path(a:path) . '\' 337 | endfunction 338 | 339 | function! s:is_local_plug(repo) 340 | return a:repo =~? '^[a-z]:\|^[%~]' 341 | endfunction 342 | else 343 | function! s:rtp(spec) 344 | return s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) 345 | endfunction 346 | 347 | function! s:path(path) 348 | return s:trim(a:path) 349 | endfunction 350 | 351 | function! s:dirpath(path) 352 | return substitute(a:path, '[/\\]*$', '/', '') 353 | endfunction 354 | 355 | function! s:is_local_plug(repo) 356 | return a:repo[0] =~ '[/$~]' 357 | endfunction 358 | endif 359 | 360 | function! s:err(msg) 361 | echohl ErrorMsg 362 | echom '[vim-plug] '.a:msg 363 | echohl None 364 | endfunction 365 | 366 | function! s:warn(cmd, msg) 367 | echohl WarningMsg 368 | execute a:cmd 'a:msg' 369 | echohl None 370 | endfunction 371 | 372 | function! s:esc(path) 373 | return escape(a:path, ' ') 374 | endfunction 375 | 376 | function! s:escrtp(path) 377 | return escape(a:path, ' ,') 378 | endfunction 379 | 380 | function! s:remove_rtp() 381 | for name in s:loaded_names() 382 | let rtp = s:rtp(g:plugs[name]) 383 | execute 'set rtp-='.s:escrtp(rtp) 384 | let after = globpath(rtp, 'after') 385 | if isdirectory(after) 386 | execute 'set rtp-='.s:escrtp(after) 387 | endif 388 | endfor 389 | endfunction 390 | 391 | function! s:reorg_rtp() 392 | if !empty(s:first_rtp) 393 | execute 'set rtp-='.s:first_rtp 394 | execute 'set rtp-='.s:last_rtp 395 | endif 396 | 397 | " &rtp is modified from outside 398 | if exists('s:prtp') && s:prtp !=# &rtp 399 | call s:remove_rtp() 400 | unlet! s:middle 401 | endif 402 | 403 | let s:middle = get(s:, 'middle', &rtp) 404 | let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') 405 | let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)') 406 | let rtp = join(map(rtps, 'escape(v:val, ",")'), ',') 407 | \ . ','.s:middle.',' 408 | \ . join(map(afters, 'escape(v:val, ",")'), ',') 409 | let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') 410 | let s:prtp = &rtp 411 | 412 | if !empty(s:first_rtp) 413 | execute 'set rtp^='.s:first_rtp 414 | execute 'set rtp+='.s:last_rtp 415 | endif 416 | endfunction 417 | 418 | function! s:doautocmd(...) 419 | if exists('#'.join(a:000, '#')) 420 | execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '' : '') join(a:000) 421 | endif 422 | endfunction 423 | 424 | function! s:dobufread(names) 425 | for name in a:names 426 | let path = s:rtp(g:plugs[name]).'/**' 427 | for dir in ['ftdetect', 'ftplugin'] 428 | if len(finddir(dir, path)) 429 | if exists('#BufRead') 430 | doautocmd BufRead 431 | endif 432 | return 433 | endif 434 | endfor 435 | endfor 436 | endfunction 437 | 438 | function! plug#load(...) 439 | if a:0 == 0 440 | return s:err('Argument missing: plugin name(s) required') 441 | endif 442 | if !exists('g:plugs') 443 | return s:err('plug#begin was not called') 444 | endif 445 | let unknowns = filter(copy(a:000), '!has_key(g:plugs, v:val)') 446 | if !empty(unknowns) 447 | let s = len(unknowns) > 1 ? 's' : '' 448 | return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) 449 | end 450 | for name in a:000 451 | call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) 452 | endfor 453 | call s:dobufread(a:000) 454 | return 1 455 | endfunction 456 | 457 | function! s:remove_triggers(name) 458 | if !has_key(s:triggers, a:name) 459 | return 460 | endif 461 | for cmd in s:triggers[a:name].cmd 462 | execute 'silent! delc' cmd 463 | endfor 464 | for map in s:triggers[a:name].map 465 | execute 'silent! unmap' map 466 | execute 'silent! iunmap' map 467 | endfor 468 | call remove(s:triggers, a:name) 469 | endfunction 470 | 471 | function! s:lod(names, types, ...) 472 | for name in a:names 473 | call s:remove_triggers(name) 474 | let s:loaded[name] = 1 475 | endfor 476 | call s:reorg_rtp() 477 | 478 | for name in a:names 479 | let rtp = s:rtp(g:plugs[name]) 480 | for dir in a:types 481 | call s:source(rtp, dir.'/**/*.vim') 482 | endfor 483 | if a:0 484 | if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2)) 485 | execute 'runtime' a:1 486 | endif 487 | call s:source(rtp, a:2) 488 | endif 489 | call s:doautocmd('User', name) 490 | endfor 491 | endfunction 492 | 493 | function! s:lod_ft(pat, names) 494 | let syn = 'syntax/'.a:pat.'.vim' 495 | call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn) 496 | execute 'autocmd! PlugLOD FileType' a:pat 497 | call s:doautocmd('filetypeplugin', 'FileType') 498 | call s:doautocmd('filetypeindent', 'FileType') 499 | endfunction 500 | 501 | function! s:lod_cmd(cmd, bang, l1, l2, args, names) 502 | call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) 503 | call s:dobufread(a:names) 504 | execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) 505 | endfunction 506 | 507 | function! s:lod_map(map, names, with_prefix, prefix) 508 | call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) 509 | call s:dobufread(a:names) 510 | let extra = '' 511 | while 1 512 | let c = getchar(0) 513 | if c == 0 514 | break 515 | endif 516 | let extra .= nr2char(c) 517 | endwhile 518 | 519 | if a:with_prefix 520 | let prefix = v:count ? v:count : '' 521 | let prefix .= '"'.v:register.a:prefix 522 | if mode(1) == 'no' 523 | if v:operator == 'c' 524 | let prefix = "\" . prefix 525 | endif 526 | let prefix .= v:operator 527 | endif 528 | call feedkeys(prefix, 'n') 529 | endif 530 | call feedkeys(substitute(a:map, '^', "\", '') . extra) 531 | endfunction 532 | 533 | function! plug#(repo, ...) 534 | if a:0 > 1 535 | return s:err('Invalid number of arguments (1..2)') 536 | endif 537 | 538 | try 539 | let repo = s:trim(a:repo) 540 | let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec 541 | let name = get(opts, 'as', fnamemodify(repo, ':t:s?\.git$??')) 542 | let spec = extend(s:infer_properties(name, repo), opts) 543 | if !has_key(g:plugs, name) 544 | call add(g:plugs_order, name) 545 | endif 546 | let g:plugs[name] = spec 547 | let s:loaded[name] = get(s:loaded, name, 0) 548 | catch 549 | return s:err(v:exception) 550 | endtry 551 | endfunction 552 | 553 | function! s:parse_options(arg) 554 | let opts = copy(s:base_spec) 555 | let type = type(a:arg) 556 | if type == s:TYPE.string 557 | let opts.tag = a:arg 558 | elseif type == s:TYPE.dict 559 | call extend(opts, a:arg) 560 | if has_key(opts, 'dir') 561 | let opts.dir = s:dirpath(expand(opts.dir)) 562 | endif 563 | else 564 | throw 'Invalid argument type (expected: string or dictionary)' 565 | endif 566 | return opts 567 | endfunction 568 | 569 | function! s:infer_properties(name, repo) 570 | let repo = a:repo 571 | if s:is_local_plug(repo) 572 | return { 'dir': s:dirpath(expand(repo)) } 573 | else 574 | if repo =~ ':' 575 | let uri = repo 576 | else 577 | if repo !~ '/' 578 | let repo = 'vim-scripts/'. repo 579 | endif 580 | let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git') 581 | let uri = printf(fmt, repo) 582 | endif 583 | return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri } 584 | endif 585 | endfunction 586 | 587 | function! s:install(force, names) 588 | call s:update_impl(0, a:force, a:names) 589 | endfunction 590 | 591 | function! s:update(force, names) 592 | call s:update_impl(1, a:force, a:names) 593 | endfunction 594 | 595 | function! plug#helptags() 596 | if !exists('g:plugs') 597 | return s:err('plug#begin was not called') 598 | endif 599 | for spec in values(g:plugs) 600 | let docd = join([spec.dir, 'doc'], '/') 601 | if isdirectory(docd) 602 | silent! execute 'helptags' s:esc(docd) 603 | endif 604 | endfor 605 | return 1 606 | endfunction 607 | 608 | function! s:syntax() 609 | syntax clear 610 | syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber 611 | syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX 612 | syn match plugNumber /[0-9]\+[0-9.]*/ contained 613 | syn match plugBracket /[[\]]/ contained 614 | syn match plugX /x/ contained 615 | syn match plugDash /^-/ 616 | syn match plugPlus /^+/ 617 | syn match plugStar /^*/ 618 | syn match plugMessage /\(^- \)\@<=.*/ 619 | syn match plugName /\(^- \)\@<=[^ ]*:/ 620 | syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/ 621 | syn match plugTag /(tag: [^)]\+)/ 622 | syn match plugInstall /\(^+ \)\@<=[^:]*/ 623 | syn match plugUpdate /\(^* \)\@<=[^:]*/ 624 | syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag 625 | syn match plugEdge /^ \X\+$/ 626 | syn match plugEdge /^ \X*/ contained nextgroup=plugSha 627 | syn match plugSha /[0-9a-f]\{7,9}/ contained 628 | syn match plugRelDate /([^)]*)$/ contained 629 | syn match plugNotLoaded /(not loaded)$/ 630 | syn match plugError /^x.*/ 631 | syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ 632 | syn match plugH2 /^.*:\n-\+$/ 633 | syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean 634 | hi def link plug1 Title 635 | hi def link plug2 Repeat 636 | hi def link plugH2 Type 637 | hi def link plugX Exception 638 | hi def link plugBracket Structure 639 | hi def link plugNumber Number 640 | 641 | hi def link plugDash Special 642 | hi def link plugPlus Constant 643 | hi def link plugStar Boolean 644 | 645 | hi def link plugMessage Function 646 | hi def link plugName Label 647 | hi def link plugInstall Function 648 | hi def link plugUpdate Type 649 | 650 | hi def link plugError Error 651 | hi def link plugDeleted Ignore 652 | hi def link plugRelDate Comment 653 | hi def link plugEdge PreProc 654 | hi def link plugSha Identifier 655 | hi def link plugTag Constant 656 | 657 | hi def link plugNotLoaded Comment 658 | endfunction 659 | 660 | function! s:lpad(str, len) 661 | return a:str . repeat(' ', a:len - len(a:str)) 662 | endfunction 663 | 664 | function! s:lines(msg) 665 | return split(a:msg, "[\r\n]") 666 | endfunction 667 | 668 | function! s:lastline(msg) 669 | return get(s:lines(a:msg), -1, '') 670 | endfunction 671 | 672 | function! s:new_window() 673 | execute get(g:, 'plug_window', 'vertical topleft new') 674 | endfunction 675 | 676 | function! s:plug_window_exists() 677 | let buflist = tabpagebuflist(s:plug_tab) 678 | return !empty(buflist) && index(buflist, s:plug_buf) >= 0 679 | endfunction 680 | 681 | function! s:switch_in() 682 | if !s:plug_window_exists() 683 | return 0 684 | endif 685 | 686 | if winbufnr(0) != s:plug_buf 687 | let s:pos = [tabpagenr(), winnr(), winsaveview()] 688 | execute 'normal!' s:plug_tab.'gt' 689 | let winnr = bufwinnr(s:plug_buf) 690 | execute winnr.'wincmd w' 691 | call add(s:pos, winsaveview()) 692 | else 693 | let s:pos = [winsaveview()] 694 | endif 695 | 696 | setlocal modifiable 697 | return 1 698 | endfunction 699 | 700 | function! s:switch_out(...) 701 | call winrestview(s:pos[-1]) 702 | setlocal nomodifiable 703 | if a:0 > 0 704 | execute a:1 705 | endif 706 | 707 | if len(s:pos) > 1 708 | execute 'normal!' s:pos[0].'gt' 709 | execute s:pos[1] 'wincmd w' 710 | call winrestview(s:pos[2]) 711 | endif 712 | endfunction 713 | 714 | function! s:finish_bindings() 715 | nnoremap R :call retry() 716 | nnoremap D :PlugDiff 717 | nnoremap S :PlugStatus 718 | nnoremap U :call status_update() 719 | xnoremap U :call status_update() 720 | nnoremap ]] :silent! call section('') 721 | nnoremap [[ :silent! call section('b') 722 | endfunction 723 | 724 | function! s:prepare(...) 725 | if empty(getcwd()) 726 | throw 'Invalid current working directory. Cannot proceed.' 727 | endif 728 | 729 | for evar in ['$GIT_DIR', '$GIT_WORK_TREE'] 730 | if exists(evar) 731 | throw evar.' detected. Cannot proceed.' 732 | endif 733 | endfor 734 | 735 | call s:job_abort() 736 | if s:switch_in() 737 | if b:plug_preview == 1 738 | pc 739 | endif 740 | enew 741 | else 742 | call s:new_window() 743 | endif 744 | 745 | nnoremap q :if b:plug_preview==1pcendifbd 746 | if a:0 == 0 747 | call s:finish_bindings() 748 | endif 749 | let b:plug_preview = -1 750 | let s:plug_tab = tabpagenr() 751 | let s:plug_buf = winbufnr(0) 752 | call s:assign_name() 753 | 754 | for k in ['', 'L', 'o', 'X', 'd', 'dd'] 755 | execute 'silent! unmap ' k 756 | endfor 757 | setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell 758 | setf vim-plug 759 | if exists('g:syntax_on') 760 | call s:syntax() 761 | endif 762 | endfunction 763 | 764 | function! s:assign_name() 765 | " Assign buffer name 766 | let prefix = '[Plugins]' 767 | let name = prefix 768 | let idx = 2 769 | while bufexists(name) 770 | let name = printf('%s (%s)', prefix, idx) 771 | let idx = idx + 1 772 | endwhile 773 | silent! execute 'f' fnameescape(name) 774 | endfunction 775 | 776 | function! s:chsh(swap) 777 | let prev = [&shell, &shellredir] 778 | if !s:is_win && a:swap 779 | set shell=sh shellredir=>%s\ 2>&1 780 | endif 781 | return prev 782 | endfunction 783 | 784 | function! s:bang(cmd, ...) 785 | try 786 | let [sh, shrd] = s:chsh(a:0) 787 | " FIXME: Escaping is incomplete. We could use shellescape with eval, 788 | " but it won't work on Windows. 789 | let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd 790 | let g:_plug_bang = '!'.escape(cmd, '#!%') 791 | execute "normal! :execute g:_plug_bang\\" 792 | finally 793 | unlet g:_plug_bang 794 | let [&shell, &shellredir] = [sh, shrd] 795 | endtry 796 | return v:shell_error ? 'Exit status: ' . v:shell_error : '' 797 | endfunction 798 | 799 | function! s:regress_bar() 800 | let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '') 801 | call s:progress_bar(2, bar, len(bar)) 802 | endfunction 803 | 804 | function! s:is_updated(dir) 805 | return !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', a:dir)) 806 | endfunction 807 | 808 | function! s:do(pull, force, todo) 809 | for [name, spec] in items(a:todo) 810 | if !isdirectory(spec.dir) 811 | continue 812 | endif 813 | let installed = has_key(s:update.new, name) 814 | let updated = installed ? 0 : 815 | \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir)) 816 | if a:force || installed || updated 817 | execute 'cd' s:esc(spec.dir) 818 | call append(3, '- Post-update hook for '. name .' ... ') 819 | let error = '' 820 | let type = type(spec.do) 821 | if type == s:TYPE.string 822 | if spec.do[0] == ':' 823 | if !get(s:loaded, name, 0) 824 | let s:loaded[name] = 1 825 | call s:reorg_rtp() 826 | endif 827 | call s:load_plugin(spec) 828 | try 829 | execute spec.do[1:] 830 | catch 831 | let error = v:exception 832 | endtry 833 | if !s:plug_window_exists() 834 | cd - 835 | throw 'Warning: vim-plug was terminated by the post-update hook of '.name 836 | endif 837 | else 838 | let error = s:bang(spec.do) 839 | endif 840 | elseif type == s:TYPE.funcref 841 | try 842 | let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') 843 | call spec.do({ 'name': name, 'status': status, 'force': a:force }) 844 | catch 845 | let error = v:exception 846 | endtry 847 | else 848 | let error = 'Invalid hook type' 849 | endif 850 | call s:switch_in() 851 | call setline(4, empty(error) ? (getline(4) . 'OK') 852 | \ : ('x' . getline(4)[1:] . error)) 853 | if !empty(error) 854 | call add(s:update.errors, name) 855 | call s:regress_bar() 856 | endif 857 | cd - 858 | endif 859 | endfor 860 | endfunction 861 | 862 | function! s:hash_match(a, b) 863 | return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 864 | endfunction 865 | 866 | function! s:checkout(spec) 867 | let sha = a:spec.commit 868 | let output = s:system('git rev-parse HEAD', a:spec.dir) 869 | if !v:shell_error && !s:hash_match(sha, s:lines(output)[0]) 870 | let output = s:system( 871 | \ 'git fetch --depth 999999 && git checkout '.s:esc(sha).' --', a:spec.dir) 872 | endif 873 | return output 874 | endfunction 875 | 876 | function! s:finish(pull) 877 | let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen')) 878 | if new_frozen 879 | let s = new_frozen > 1 ? 's' : '' 880 | call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) 881 | endif 882 | call append(3, '- Finishing ... ') | 4 883 | redraw 884 | call plug#helptags() 885 | call plug#end() 886 | call setline(4, getline(4) . 'Done!') 887 | redraw 888 | let msgs = [] 889 | if !empty(s:update.errors) 890 | call add(msgs, "Press 'R' to retry.") 891 | endif 892 | if a:pull && len(s:update.new) < len(filter(getline(5, '$'), 893 | \ "v:val =~ '^- ' && stridx(v:val, 'Already up-to-date') < 0")) 894 | call add(msgs, "Press 'D' to see the updated changes.") 895 | endif 896 | echo join(msgs, ' ') 897 | call s:finish_bindings() 898 | endfunction 899 | 900 | function! s:retry() 901 | if empty(s:update.errors) 902 | return 903 | endif 904 | echo 905 | call s:update_impl(s:update.pull, s:update.force, 906 | \ extend(copy(s:update.errors), [s:update.threads])) 907 | endfunction 908 | 909 | function! s:is_managed(name) 910 | return has_key(g:plugs[a:name], 'uri') 911 | endfunction 912 | 913 | function! s:names(...) 914 | return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) 915 | endfunction 916 | 917 | function! s:check_ruby() 918 | silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'") 919 | if !exists('g:plug_ruby') 920 | redraw! 921 | return s:warn('echom', 'Warning: Ruby interface is broken') 922 | endif 923 | let ruby_version = split(g:plug_ruby, '\.') 924 | unlet g:plug_ruby 925 | return s:version_requirement(ruby_version, [1, 8, 7]) 926 | endfunction 927 | 928 | function! s:update_impl(pull, force, args) abort 929 | let sync = index(a:args, '--sync') >= 0 || has('vim_starting') 930 | let args = filter(copy(a:args), 'v:val != "--sync"') 931 | let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? 932 | \ remove(args, -1) : get(g:, 'plug_threads', 16) 933 | 934 | let managed = filter(copy(g:plugs), 's:is_managed(v:key)') 935 | let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') : 936 | \ filter(managed, 'index(args, v:key) >= 0') 937 | 938 | if empty(todo) 939 | return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install')) 940 | endif 941 | 942 | if !s:is_win && s:git_version_requirement(2, 3) 943 | let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : '' 944 | let $GIT_TERMINAL_PROMPT = 0 945 | for plug in values(todo) 946 | let plug.uri = substitute(plug.uri, 947 | \ '^https://git::@github\.com', 'https://github.com', '') 948 | endfor 949 | endif 950 | 951 | if !isdirectory(g:plug_home) 952 | try 953 | call mkdir(g:plug_home, 'p') 954 | catch 955 | return s:err(printf('Invalid plug directory: %s. '. 956 | \ 'Try to call plug#begin with a valid directory', g:plug_home)) 957 | endtry 958 | endif 959 | 960 | if has('nvim') && !exists('*jobwait') && threads > 1 961 | call s:warn('echom', '[vim-plug] Update Neovim for parallel installer') 962 | endif 963 | 964 | let use_job = s:nvim || s:vim8 965 | let python = (has('python') || has('python3')) && !use_job 966 | let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby() 967 | 968 | let s:update = { 969 | \ 'start': reltime(), 970 | \ 'all': todo, 971 | \ 'todo': copy(todo), 972 | \ 'errors': [], 973 | \ 'pull': a:pull, 974 | \ 'force': a:force, 975 | \ 'new': {}, 976 | \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1, 977 | \ 'bar': '', 978 | \ 'fin': 0 979 | \ } 980 | 981 | call s:prepare(1) 982 | call append(0, ['', '']) 983 | normal! 2G 984 | silent! redraw 985 | 986 | let s:clone_opt = get(g:, 'plug_shallow', 1) ? 987 | \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : '' 988 | 989 | " Python version requirement (>= 2.7) 990 | if python && !has('python3') && !ruby && !use_job && s:update.threads > 1 991 | redir => pyv 992 | silent python import platform; print platform.python_version() 993 | redir END 994 | let python = s:version_requirement( 995 | \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) 996 | endif 997 | 998 | if (python || ruby) && s:update.threads > 1 999 | try 1000 | let imd = &imd 1001 | if s:mac_gui 1002 | set noimd 1003 | endif 1004 | if ruby 1005 | call s:update_ruby() 1006 | else 1007 | call s:update_python() 1008 | endif 1009 | catch 1010 | let lines = getline(4, '$') 1011 | let printed = {} 1012 | silent! 4,$d _ 1013 | for line in lines 1014 | let name = s:extract_name(line, '.', '') 1015 | if empty(name) || !has_key(printed, name) 1016 | call append('$', line) 1017 | if !empty(name) 1018 | let printed[name] = 1 1019 | if line[0] == 'x' && index(s:update.errors, name) < 0 1020 | call add(s:update.errors, name) 1021 | end 1022 | endif 1023 | endif 1024 | endfor 1025 | finally 1026 | let &imd = imd 1027 | call s:update_finish() 1028 | endtry 1029 | else 1030 | call s:update_vim() 1031 | while use_job && sync 1032 | sleep 100m 1033 | if s:update.fin 1034 | break 1035 | endif 1036 | endwhile 1037 | endif 1038 | endfunction 1039 | 1040 | function! s:log4(name, msg) 1041 | call setline(4, printf('- %s (%s)', a:msg, a:name)) 1042 | redraw 1043 | endfunction 1044 | 1045 | function! s:update_finish() 1046 | if exists('s:git_terminal_prompt') 1047 | let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt 1048 | endif 1049 | if s:switch_in() 1050 | call append(3, '- Updating ...') | 4 1051 | for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))')) 1052 | let [pos, _] = s:logpos(name) 1053 | if !pos 1054 | continue 1055 | endif 1056 | if has_key(spec, 'commit') 1057 | call s:log4(name, 'Checking out '.spec.commit) 1058 | let out = s:checkout(spec) 1059 | elseif has_key(spec, 'tag') 1060 | let tag = spec.tag 1061 | if tag =~ '\*' 1062 | let tags = s:lines(s:system('git tag --list '.string(tag).' --sort -version:refname 2>&1', spec.dir)) 1063 | if !v:shell_error && !empty(tags) 1064 | let tag = tags[0] 1065 | call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) 1066 | call append(3, '') 1067 | endif 1068 | endif 1069 | call s:log4(name, 'Checking out '.tag) 1070 | let out = s:system('git checkout -q '.s:esc(tag).' -- 2>&1', spec.dir) 1071 | else 1072 | let branch = s:esc(get(spec, 'branch', 'master')) 1073 | call s:log4(name, 'Merging origin/'.branch) 1074 | let out = s:system('git checkout -q '.branch.' -- 2>&1' 1075 | \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only origin/'.branch.' 2>&1')), spec.dir) 1076 | endif 1077 | if !v:shell_error && filereadable(spec.dir.'/.gitmodules') && 1078 | \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) 1079 | call s:log4(name, 'Updating submodules. This may take a while.') 1080 | let out .= s:bang('git submodule update --init --recursive 2>&1', spec.dir) 1081 | endif 1082 | let msg = s:format_message(v:shell_error ? 'x': '-', name, out) 1083 | if v:shell_error 1084 | call add(s:update.errors, name) 1085 | call s:regress_bar() 1086 | silent execute pos 'd _' 1087 | call append(4, msg) | 4 1088 | elseif !empty(out) 1089 | call setline(pos, msg[0]) 1090 | endif 1091 | redraw 1092 | endfor 1093 | silent 4 d _ 1094 | try 1095 | call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")')) 1096 | catch 1097 | call s:warn('echom', v:exception) 1098 | call s:warn('echo', '') 1099 | return 1100 | endtry 1101 | call s:finish(s:update.pull) 1102 | call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') 1103 | call s:switch_out('normal! gg') 1104 | endif 1105 | endfunction 1106 | 1107 | function! s:job_abort() 1108 | if (!s:nvim && !s:vim8) || !exists('s:jobs') 1109 | return 1110 | endif 1111 | 1112 | for [name, j] in items(s:jobs) 1113 | if s:nvim 1114 | silent! call jobstop(j.jobid) 1115 | elseif s:vim8 1116 | silent! call job_stop(j.jobid) 1117 | endif 1118 | if j.new 1119 | call s:system('rm -rf ' . s:shellesc(g:plugs[name].dir)) 1120 | endif 1121 | endfor 1122 | let s:jobs = {} 1123 | endfunction 1124 | 1125 | function! s:last_non_empty_line(lines) 1126 | let len = len(a:lines) 1127 | for idx in range(len) 1128 | let line = a:lines[len-idx-1] 1129 | if !empty(line) 1130 | return line 1131 | endif 1132 | endfor 1133 | return '' 1134 | endfunction 1135 | 1136 | function! s:job_out_cb(self, data) abort 1137 | let self = a:self 1138 | let data = remove(self.lines, -1) . a:data 1139 | let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]') 1140 | call extend(self.lines, lines) 1141 | " To reduce the number of buffer updates 1142 | let self.tick = get(self, 'tick', -1) + 1 1143 | if !self.running || self.tick % len(s:jobs) == 0 1144 | let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-') 1145 | let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) 1146 | call s:log(bullet, self.name, result) 1147 | endif 1148 | endfunction 1149 | 1150 | function! s:job_exit_cb(self, data) abort 1151 | let a:self.running = 0 1152 | let a:self.error = a:data != 0 1153 | call s:reap(a:self.name) 1154 | call s:tick() 1155 | endfunction 1156 | 1157 | function! s:job_cb(fn, job, ch, data) 1158 | if !s:plug_window_exists() " plug window closed 1159 | return s:job_abort() 1160 | endif 1161 | call call(a:fn, [a:job, a:data]) 1162 | endfunction 1163 | 1164 | function! s:nvim_cb(job_id, data, event) dict abort 1165 | return a:event == 'stdout' ? 1166 | \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) : 1167 | \ s:job_cb('s:job_exit_cb', self, 0, a:data) 1168 | endfunction 1169 | 1170 | function! s:spawn(name, cmd, opts) 1171 | let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], 1172 | \ 'new': get(a:opts, 'new', 0) } 1173 | let s:jobs[a:name] = job 1174 | let argv = add(s:is_win ? ['cmd', '/c'] : ['sh', '-c'], 1175 | \ has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd) 1176 | 1177 | if s:nvim 1178 | call extend(job, { 1179 | \ 'on_stdout': function('s:nvim_cb'), 1180 | \ 'on_exit': function('s:nvim_cb'), 1181 | \ }) 1182 | let jid = jobstart(argv, job) 1183 | if jid > 0 1184 | let job.jobid = jid 1185 | else 1186 | let job.running = 0 1187 | let job.error = 1 1188 | let job.lines = [jid < 0 ? argv[0].' is not executable' : 1189 | \ 'Invalid arguments (or job table is full)'] 1190 | endif 1191 | elseif s:vim8 1192 | let jid = job_start(s:is_win ? join(argv, ' ') : argv, { 1193 | \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]), 1194 | \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]), 1195 | \ 'out_mode': 'raw' 1196 | \}) 1197 | if job_status(jid) == 'run' 1198 | let job.jobid = jid 1199 | else 1200 | let job.running = 0 1201 | let job.error = 1 1202 | let job.lines = ['Failed to start job'] 1203 | endif 1204 | else 1205 | let params = has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd] 1206 | let job.lines = s:lines(call('s:system', params)) 1207 | let job.error = v:shell_error != 0 1208 | let job.running = 0 1209 | endif 1210 | endfunction 1211 | 1212 | function! s:reap(name) 1213 | let job = s:jobs[a:name] 1214 | if job.error 1215 | call add(s:update.errors, a:name) 1216 | elseif get(job, 'new', 0) 1217 | let s:update.new[a:name] = 1 1218 | endif 1219 | let s:update.bar .= job.error ? 'x' : '=' 1220 | 1221 | let bullet = job.error ? 'x' : '-' 1222 | let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) 1223 | call s:log(bullet, a:name, empty(result) ? 'OK' : result) 1224 | call s:bar() 1225 | 1226 | call remove(s:jobs, a:name) 1227 | endfunction 1228 | 1229 | function! s:bar() 1230 | if s:switch_in() 1231 | let total = len(s:update.all) 1232 | call setline(1, (s:update.pull ? 'Updating' : 'Installing'). 1233 | \ ' plugins ('.len(s:update.bar).'/'.total.')') 1234 | call s:progress_bar(2, s:update.bar, total) 1235 | call s:switch_out() 1236 | endif 1237 | endfunction 1238 | 1239 | function! s:logpos(name) 1240 | for i in range(4, line('$')) 1241 | if getline(i) =~# '^[-+x*] '.a:name.':' 1242 | for j in range(i + 1, line('$')) 1243 | if getline(j) !~ '^ ' 1244 | return [i, j - 1] 1245 | endif 1246 | endfor 1247 | return [i, i] 1248 | endif 1249 | endfor 1250 | return [0, 0] 1251 | endfunction 1252 | 1253 | function! s:log(bullet, name, lines) 1254 | if s:switch_in() 1255 | let [b, e] = s:logpos(a:name) 1256 | if b > 0 1257 | silent execute printf('%d,%d d _', b, e) 1258 | if b > winheight('.') 1259 | let b = 4 1260 | endif 1261 | else 1262 | let b = 4 1263 | endif 1264 | " FIXME For some reason, nomodifiable is set after :d in vim8 1265 | setlocal modifiable 1266 | call append(b - 1, s:format_message(a:bullet, a:name, a:lines)) 1267 | call s:switch_out() 1268 | endif 1269 | endfunction 1270 | 1271 | function! s:update_vim() 1272 | let s:jobs = {} 1273 | 1274 | call s:bar() 1275 | call s:tick() 1276 | endfunction 1277 | 1278 | function! s:tick() 1279 | let pull = s:update.pull 1280 | let prog = s:progress_opt(s:nvim || s:vim8) 1281 | while 1 " Without TCO, Vim stack is bound to explode 1282 | if empty(s:update.todo) 1283 | if empty(s:jobs) && !s:update.fin 1284 | call s:update_finish() 1285 | let s:update.fin = 1 1286 | endif 1287 | return 1288 | endif 1289 | 1290 | let name = keys(s:update.todo)[0] 1291 | let spec = remove(s:update.todo, name) 1292 | let new = !isdirectory(spec.dir) 1293 | 1294 | call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') 1295 | redraw 1296 | 1297 | let has_tag = has_key(spec, 'tag') 1298 | if !new 1299 | let [error, _] = s:git_validate(spec, 0) 1300 | if empty(error) 1301 | if pull 1302 | let fetch_opt = (has_tag && !empty(globpath(spec.dir, '.git/shallow'))) ? '--depth 99999999' : '' 1303 | call s:spawn(name, printf('git fetch %s %s 2>&1', fetch_opt, prog), { 'dir': spec.dir }) 1304 | else 1305 | let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 } 1306 | endif 1307 | else 1308 | let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 } 1309 | endif 1310 | else 1311 | call s:spawn(name, 1312 | \ printf('git clone %s %s %s %s 2>&1', 1313 | \ has_tag ? '' : s:clone_opt, 1314 | \ prog, 1315 | \ s:shellesc(spec.uri), 1316 | \ s:shellesc(s:trim(spec.dir))), { 'new': 1 }) 1317 | endif 1318 | 1319 | if !s:jobs[name].running 1320 | call s:reap(name) 1321 | endif 1322 | if len(s:jobs) >= s:update.threads 1323 | break 1324 | endif 1325 | endwhile 1326 | endfunction 1327 | 1328 | function! s:update_python() 1329 | let py_exe = has('python') ? 'python' : 'python3' 1330 | execute py_exe "<< EOF" 1331 | import datetime 1332 | import functools 1333 | import os 1334 | try: 1335 | import queue 1336 | except ImportError: 1337 | import Queue as queue 1338 | import random 1339 | import re 1340 | import shutil 1341 | import signal 1342 | import subprocess 1343 | import tempfile 1344 | import threading as thr 1345 | import time 1346 | import traceback 1347 | import vim 1348 | 1349 | G_NVIM = vim.eval("has('nvim')") == '1' 1350 | G_PULL = vim.eval('s:update.pull') == '1' 1351 | G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 1352 | G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) 1353 | G_CLONE_OPT = vim.eval('s:clone_opt') 1354 | G_PROGRESS = vim.eval('s:progress_opt(1)') 1355 | G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) 1356 | G_STOP = thr.Event() 1357 | G_IS_WIN = vim.eval('s:is_win') == '1' 1358 | 1359 | class PlugError(Exception): 1360 | def __init__(self, msg): 1361 | self.msg = msg 1362 | class CmdTimedOut(PlugError): 1363 | pass 1364 | class CmdFailed(PlugError): 1365 | pass 1366 | class InvalidURI(PlugError): 1367 | pass 1368 | class Action(object): 1369 | INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] 1370 | 1371 | class Buffer(object): 1372 | def __init__(self, lock, num_plugs, is_pull): 1373 | self.bar = '' 1374 | self.event = 'Updating' if is_pull else 'Installing' 1375 | self.lock = lock 1376 | self.maxy = int(vim.eval('winheight(".")')) 1377 | self.num_plugs = num_plugs 1378 | 1379 | def __where(self, name): 1380 | """ Find first line with name in current buffer. Return line num. """ 1381 | found, lnum = False, 0 1382 | matcher = re.compile('^[-+x*] {0}:'.format(name)) 1383 | for line in vim.current.buffer: 1384 | if matcher.search(line) is not None: 1385 | found = True 1386 | break 1387 | lnum += 1 1388 | 1389 | if not found: 1390 | lnum = -1 1391 | return lnum 1392 | 1393 | def header(self): 1394 | curbuf = vim.current.buffer 1395 | curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs) 1396 | 1397 | num_spaces = self.num_plugs - len(self.bar) 1398 | curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') 1399 | 1400 | with self.lock: 1401 | vim.command('normal! 2G') 1402 | vim.command('redraw') 1403 | 1404 | def write(self, action, name, lines): 1405 | first, rest = lines[0], lines[1:] 1406 | msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] 1407 | msg.extend([' ' + line for line in rest]) 1408 | 1409 | try: 1410 | if action == Action.ERROR: 1411 | self.bar += 'x' 1412 | vim.command("call add(s:update.errors, '{0}')".format(name)) 1413 | elif action == Action.DONE: 1414 | self.bar += '=' 1415 | 1416 | curbuf = vim.current.buffer 1417 | lnum = self.__where(name) 1418 | if lnum != -1: # Found matching line num 1419 | del curbuf[lnum] 1420 | if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]): 1421 | lnum = 3 1422 | else: 1423 | lnum = 3 1424 | curbuf.append(msg, lnum) 1425 | 1426 | self.header() 1427 | except vim.error: 1428 | pass 1429 | 1430 | class Command(object): 1431 | CD = 'cd /d' if G_IS_WIN else 'cd' 1432 | 1433 | def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None): 1434 | self.cmd = cmd 1435 | if cmd_dir: 1436 | self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd) 1437 | self.timeout = timeout 1438 | self.callback = cb if cb else (lambda msg: None) 1439 | self.clean = clean if clean else (lambda: None) 1440 | self.proc = None 1441 | 1442 | @property 1443 | def alive(self): 1444 | """ Returns true only if command still running. """ 1445 | return self.proc and self.proc.poll() is None 1446 | 1447 | def execute(self, ntries=3): 1448 | """ Execute the command with ntries if CmdTimedOut. 1449 | Returns the output of the command if no Exception. 1450 | """ 1451 | attempt, finished, limit = 0, False, self.timeout 1452 | 1453 | while not finished: 1454 | try: 1455 | attempt += 1 1456 | result = self.try_command() 1457 | finished = True 1458 | return result 1459 | except CmdTimedOut: 1460 | if attempt != ntries: 1461 | self.notify_retry() 1462 | self.timeout += limit 1463 | else: 1464 | raise 1465 | 1466 | def notify_retry(self): 1467 | """ Retry required for command, notify user. """ 1468 | for count in range(3, 0, -1): 1469 | if G_STOP.is_set(): 1470 | raise KeyboardInterrupt 1471 | msg = 'Timeout. Will retry in {0} second{1} ...'.format( 1472 | count, 's' if count != 1 else '') 1473 | self.callback([msg]) 1474 | time.sleep(1) 1475 | self.callback(['Retrying ...']) 1476 | 1477 | def try_command(self): 1478 | """ Execute a cmd & poll for callback. Returns list of output. 1479 | Raises CmdFailed -> return code for Popen isn't 0 1480 | Raises CmdTimedOut -> command exceeded timeout without new output 1481 | """ 1482 | first_line = True 1483 | 1484 | try: 1485 | tfile = tempfile.NamedTemporaryFile(mode='w+b') 1486 | preexec_fn = not G_IS_WIN and os.setsid or None 1487 | self.proc = subprocess.Popen(self.cmd, stdout=tfile, 1488 | stderr=subprocess.STDOUT, 1489 | stdin=subprocess.PIPE, shell=True, 1490 | preexec_fn=preexec_fn) 1491 | thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,)) 1492 | thrd.start() 1493 | 1494 | thread_not_started = True 1495 | while thread_not_started: 1496 | try: 1497 | thrd.join(0.1) 1498 | thread_not_started = False 1499 | except RuntimeError: 1500 | pass 1501 | 1502 | while self.alive: 1503 | if G_STOP.is_set(): 1504 | raise KeyboardInterrupt 1505 | 1506 | if first_line or random.random() < G_LOG_PROB: 1507 | first_line = False 1508 | line = '' if G_IS_WIN else nonblock_read(tfile.name) 1509 | if line: 1510 | self.callback([line]) 1511 | 1512 | time_diff = time.time() - os.path.getmtime(tfile.name) 1513 | if time_diff > self.timeout: 1514 | raise CmdTimedOut(['Timeout!']) 1515 | 1516 | thrd.join(0.5) 1517 | 1518 | tfile.seek(0) 1519 | result = [line.decode('utf-8', 'replace').rstrip() for line in tfile] 1520 | 1521 | if self.proc.returncode != 0: 1522 | raise CmdFailed([''] + result) 1523 | 1524 | return result 1525 | except: 1526 | self.terminate() 1527 | raise 1528 | 1529 | def terminate(self): 1530 | """ Terminate process and cleanup. """ 1531 | if self.alive: 1532 | if G_IS_WIN: 1533 | os.kill(self.proc.pid, signal.SIGINT) 1534 | else: 1535 | os.killpg(self.proc.pid, signal.SIGTERM) 1536 | self.clean() 1537 | 1538 | class Plugin(object): 1539 | def __init__(self, name, args, buf_q, lock): 1540 | self.name = name 1541 | self.args = args 1542 | self.buf_q = buf_q 1543 | self.lock = lock 1544 | self.tag = args.get('tag', 0) 1545 | 1546 | def manage(self): 1547 | try: 1548 | if os.path.exists(self.args['dir']): 1549 | self.update() 1550 | else: 1551 | self.install() 1552 | with self.lock: 1553 | thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) 1554 | except PlugError as exc: 1555 | self.write(Action.ERROR, self.name, exc.msg) 1556 | except KeyboardInterrupt: 1557 | G_STOP.set() 1558 | self.write(Action.ERROR, self.name, ['Interrupted!']) 1559 | except: 1560 | # Any exception except those above print stack trace 1561 | msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip()) 1562 | self.write(Action.ERROR, self.name, msg.split('\n')) 1563 | raise 1564 | 1565 | def install(self): 1566 | target = self.args['dir'] 1567 | if target[-1] == '\\': 1568 | target = target[0:-1] 1569 | 1570 | def clean(target): 1571 | def _clean(): 1572 | try: 1573 | shutil.rmtree(target) 1574 | except OSError: 1575 | pass 1576 | return _clean 1577 | 1578 | self.write(Action.INSTALL, self.name, ['Installing ...']) 1579 | callback = functools.partial(self.write, Action.INSTALL, self.name) 1580 | cmd = 'git clone {0} {1} {2} {3} 2>&1'.format( 1581 | '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], 1582 | esc(target)) 1583 | com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) 1584 | result = com.execute(G_RETRIES) 1585 | self.write(Action.DONE, self.name, result[-1:]) 1586 | 1587 | def repo_uri(self): 1588 | cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url' 1589 | command = Command(cmd, self.args['dir'], G_TIMEOUT,) 1590 | result = command.execute(G_RETRIES) 1591 | return result[-1] 1592 | 1593 | def update(self): 1594 | actual_uri = self.repo_uri() 1595 | expect_uri = self.args['uri'] 1596 | regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$') 1597 | ma = regex.match(actual_uri) 1598 | mb = regex.match(expect_uri) 1599 | if ma is None or mb is None or ma.groups() != mb.groups(): 1600 | msg = ['', 1601 | 'Invalid URI: {0}'.format(actual_uri), 1602 | 'Expected {0}'.format(expect_uri), 1603 | 'PlugClean required.'] 1604 | raise InvalidURI(msg) 1605 | 1606 | if G_PULL: 1607 | self.write(Action.UPDATE, self.name, ['Updating ...']) 1608 | callback = functools.partial(self.write, Action.UPDATE, self.name) 1609 | fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' 1610 | cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS) 1611 | com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) 1612 | result = com.execute(G_RETRIES) 1613 | self.write(Action.DONE, self.name, result[-1:]) 1614 | else: 1615 | self.write(Action.DONE, self.name, ['Already installed']) 1616 | 1617 | def write(self, action, name, msg): 1618 | self.buf_q.put((action, name, msg)) 1619 | 1620 | class PlugThread(thr.Thread): 1621 | def __init__(self, tname, args): 1622 | super(PlugThread, self).__init__() 1623 | self.tname = tname 1624 | self.args = args 1625 | 1626 | def run(self): 1627 | thr.current_thread().name = self.tname 1628 | buf_q, work_q, lock = self.args 1629 | 1630 | try: 1631 | while not G_STOP.is_set(): 1632 | name, args = work_q.get_nowait() 1633 | plug = Plugin(name, args, buf_q, lock) 1634 | plug.manage() 1635 | work_q.task_done() 1636 | except queue.Empty: 1637 | pass 1638 | 1639 | class RefreshThread(thr.Thread): 1640 | def __init__(self, lock): 1641 | super(RefreshThread, self).__init__() 1642 | self.lock = lock 1643 | self.running = True 1644 | 1645 | def run(self): 1646 | while self.running: 1647 | with self.lock: 1648 | thread_vim_command('noautocmd normal! a') 1649 | time.sleep(0.33) 1650 | 1651 | def stop(self): 1652 | self.running = False 1653 | 1654 | if G_NVIM: 1655 | def thread_vim_command(cmd): 1656 | vim.session.threadsafe_call(lambda: vim.command(cmd)) 1657 | else: 1658 | def thread_vim_command(cmd): 1659 | vim.command(cmd) 1660 | 1661 | def esc(name): 1662 | return '"' + name.replace('"', '\"') + '"' 1663 | 1664 | def nonblock_read(fname): 1665 | """ Read a file with nonblock flag. Return the last line. """ 1666 | fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) 1667 | buf = os.read(fread, 100000).decode('utf-8', 'replace') 1668 | os.close(fread) 1669 | 1670 | line = buf.rstrip('\r\n') 1671 | left = max(line.rfind('\r'), line.rfind('\n')) 1672 | if left != -1: 1673 | left += 1 1674 | line = line[left:] 1675 | 1676 | return line 1677 | 1678 | def main(): 1679 | thr.current_thread().name = 'main' 1680 | nthreads = int(vim.eval('s:update.threads')) 1681 | plugs = vim.eval('s:update.todo') 1682 | mac_gui = vim.eval('s:mac_gui') == '1' 1683 | 1684 | lock = thr.Lock() 1685 | buf = Buffer(lock, len(plugs), G_PULL) 1686 | buf_q, work_q = queue.Queue(), queue.Queue() 1687 | for work in plugs.items(): 1688 | work_q.put(work) 1689 | 1690 | start_cnt = thr.active_count() 1691 | for num in range(nthreads): 1692 | tname = 'PlugT-{0:02}'.format(num) 1693 | thread = PlugThread(tname, (buf_q, work_q, lock)) 1694 | thread.start() 1695 | if mac_gui: 1696 | rthread = RefreshThread(lock) 1697 | rthread.start() 1698 | 1699 | while not buf_q.empty() or thr.active_count() != start_cnt: 1700 | try: 1701 | action, name, msg = buf_q.get(True, 0.25) 1702 | buf.write(action, name, ['OK'] if not msg else msg) 1703 | buf_q.task_done() 1704 | except queue.Empty: 1705 | pass 1706 | except KeyboardInterrupt: 1707 | G_STOP.set() 1708 | 1709 | if mac_gui: 1710 | rthread.stop() 1711 | rthread.join() 1712 | 1713 | main() 1714 | EOF 1715 | endfunction 1716 | 1717 | function! s:update_ruby() 1718 | ruby << EOF 1719 | module PlugStream 1720 | SEP = ["\r", "\n", nil] 1721 | def get_line 1722 | buffer = '' 1723 | loop do 1724 | char = readchar rescue return 1725 | if SEP.include? char.chr 1726 | buffer << $/ 1727 | break 1728 | else 1729 | buffer << char 1730 | end 1731 | end 1732 | buffer 1733 | end 1734 | end unless defined?(PlugStream) 1735 | 1736 | def esc arg 1737 | %["#{arg.gsub('"', '\"')}"] 1738 | end 1739 | 1740 | def killall pid 1741 | pids = [pid] 1742 | if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM 1743 | pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil } 1744 | else 1745 | unless `which pgrep 2> /dev/null`.empty? 1746 | children = pids 1747 | until children.empty? 1748 | children = children.map { |pid| 1749 | `pgrep -P #{pid}`.lines.map { |l| l.chomp } 1750 | }.flatten 1751 | pids += children 1752 | end 1753 | end 1754 | pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } 1755 | end 1756 | end 1757 | 1758 | def compare_git_uri a, b 1759 | regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$} 1760 | regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1) 1761 | end 1762 | 1763 | require 'thread' 1764 | require 'fileutils' 1765 | require 'timeout' 1766 | running = true 1767 | iswin = VIM::evaluate('s:is_win').to_i == 1 1768 | pull = VIM::evaluate('s:update.pull').to_i == 1 1769 | base = VIM::evaluate('g:plug_home') 1770 | all = VIM::evaluate('s:update.todo') 1771 | limit = VIM::evaluate('get(g:, "plug_timeout", 60)') 1772 | tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1 1773 | nthr = VIM::evaluate('s:update.threads').to_i 1774 | maxy = VIM::evaluate('winheight(".")').to_i 1775 | vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/ 1776 | cd = iswin ? 'cd /d' : 'cd' 1777 | tot = VIM::evaluate('len(s:update.todo)') || 0 1778 | bar = '' 1779 | skip = 'Already installed' 1780 | mtx = Mutex.new 1781 | take1 = proc { mtx.synchronize { running && all.shift } } 1782 | logh = proc { 1783 | cnt = bar.length 1784 | $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" 1785 | $curbuf[2] = '[' + bar.ljust(tot) + ']' 1786 | VIM::command('normal! 2G') 1787 | VIM::command('redraw') 1788 | } 1789 | where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } } 1790 | log = proc { |name, result, type| 1791 | mtx.synchronize do 1792 | ing = ![true, false].include?(type) 1793 | bar += type ? '=' : 'x' unless ing 1794 | b = case type 1795 | when :install then '+' when :update then '*' 1796 | when true, nil then '-' else 1797 | VIM::command("call add(s:update.errors, '#{name}')") 1798 | 'x' 1799 | end 1800 | result = 1801 | if type || type.nil? 1802 | ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"] 1803 | elsif result =~ /^Interrupted|^Timeout/ 1804 | ["#{b} #{name}: #{result}"] 1805 | else 1806 | ["#{b} #{name}"] + result.lines.map { |l| " " << l } 1807 | end 1808 | if lnum = where.call(name) 1809 | $curbuf.delete lnum 1810 | lnum = 4 if ing && lnum > maxy 1811 | end 1812 | result.each_with_index do |line, offset| 1813 | $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp) 1814 | end 1815 | logh.call 1816 | end 1817 | } 1818 | bt = proc { |cmd, name, type, cleanup| 1819 | tried = timeout = 0 1820 | begin 1821 | tried += 1 1822 | timeout += limit 1823 | fd = nil 1824 | data = '' 1825 | if iswin 1826 | Timeout::timeout(timeout) do 1827 | tmp = VIM::evaluate('tempname()') 1828 | system("(#{cmd}) > #{tmp}") 1829 | data = File.read(tmp).chomp 1830 | File.unlink tmp rescue nil 1831 | end 1832 | else 1833 | fd = IO.popen(cmd).extend(PlugStream) 1834 | first_line = true 1835 | log_prob = 1.0 / nthr 1836 | while line = Timeout::timeout(timeout) { fd.get_line } 1837 | data << line 1838 | log.call name, line.chomp, type if name && (first_line || rand < log_prob) 1839 | first_line = false 1840 | end 1841 | fd.close 1842 | end 1843 | [$? == 0, data.chomp] 1844 | rescue Timeout::Error, Interrupt => e 1845 | if fd && !fd.closed? 1846 | killall fd.pid 1847 | fd.close 1848 | end 1849 | cleanup.call if cleanup 1850 | if e.is_a?(Timeout::Error) && tried < tries 1851 | 3.downto(1) do |countdown| 1852 | s = countdown > 1 ? 's' : '' 1853 | log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type 1854 | sleep 1 1855 | end 1856 | log.call name, 'Retrying ...', type 1857 | retry 1858 | end 1859 | [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] 1860 | end 1861 | } 1862 | main = Thread.current 1863 | threads = [] 1864 | watcher = Thread.new { 1865 | if vim7 1866 | while VIM::evaluate('getchar(1)') 1867 | sleep 0.1 1868 | end 1869 | else 1870 | require 'io/console' # >= Ruby 1.9 1871 | nil until IO.console.getch == 3.chr 1872 | end 1873 | mtx.synchronize do 1874 | running = false 1875 | threads.each { |t| t.raise Interrupt } unless vim7 1876 | end 1877 | threads.each { |t| t.join rescue nil } 1878 | main.kill 1879 | } 1880 | refresh = Thread.new { 1881 | while true 1882 | mtx.synchronize do 1883 | break unless running 1884 | VIM::command('noautocmd normal! a') 1885 | end 1886 | sleep 0.2 1887 | end 1888 | } if VIM::evaluate('s:mac_gui') == 1 1889 | 1890 | clone_opt = VIM::evaluate('s:clone_opt') 1891 | progress = VIM::evaluate('s:progress_opt(1)') 1892 | nthr.times do 1893 | mtx.synchronize do 1894 | threads << Thread.new { 1895 | while pair = take1.call 1896 | name = pair.first 1897 | dir, uri, tag = pair.last.values_at *%w[dir uri tag] 1898 | exists = File.directory? dir 1899 | ok, result = 1900 | if exists 1901 | chdir = "#{cd} #{iswin ? dir : esc(dir)}" 1902 | ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil 1903 | current_uri = data.lines.to_a.last 1904 | if !ret 1905 | if data =~ /^Interrupted|^Timeout/ 1906 | [false, data] 1907 | else 1908 | [false, [data.chomp, "PlugClean required."].join($/)] 1909 | end 1910 | elsif !compare_git_uri(current_uri, uri) 1911 | [false, ["Invalid URI: #{current_uri}", 1912 | "Expected: #{uri}", 1913 | "PlugClean required."].join($/)] 1914 | else 1915 | if pull 1916 | log.call name, 'Updating ...', :update 1917 | fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' 1918 | bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil 1919 | else 1920 | [true, skip] 1921 | end 1922 | end 1923 | else 1924 | d = esc dir.sub(%r{[\\/]+$}, '') 1925 | log.call name, 'Installing ...', :install 1926 | bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc { 1927 | FileUtils.rm_rf dir 1928 | } 1929 | end 1930 | mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok 1931 | log.call name, result, ok 1932 | end 1933 | } if running 1934 | end 1935 | end 1936 | threads.each { |t| t.join rescue nil } 1937 | logh.call 1938 | refresh.kill if refresh 1939 | watcher.kill 1940 | EOF 1941 | endfunction 1942 | 1943 | function! s:shellesc(arg) 1944 | return '"'.escape(a:arg, '"').'"' 1945 | endfunction 1946 | 1947 | function! s:glob_dir(path) 1948 | return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)') 1949 | endfunction 1950 | 1951 | function! s:progress_bar(line, bar, total) 1952 | call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']') 1953 | endfunction 1954 | 1955 | function! s:compare_git_uri(a, b) 1956 | " See `git help clone' 1957 | " https:// [user@] github.com[:port] / junegunn/vim-plug [.git] 1958 | " [git@] github.com[:port] : junegunn/vim-plug [.git] 1959 | " file:// / junegunn/vim-plug [/] 1960 | " / junegunn/vim-plug [/] 1961 | let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$' 1962 | let ma = matchlist(a:a, pat) 1963 | let mb = matchlist(a:b, pat) 1964 | return ma[1:2] ==# mb[1:2] 1965 | endfunction 1966 | 1967 | function! s:format_message(bullet, name, message) 1968 | if a:bullet != 'x' 1969 | return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))] 1970 | else 1971 | let lines = map(s:lines(a:message), '" ".v:val') 1972 | return extend([printf('x %s:', a:name)], lines) 1973 | endif 1974 | endfunction 1975 | 1976 | function! s:with_cd(cmd, dir) 1977 | return printf('cd%s %s && %s', s:is_win ? ' /d' : '', s:shellesc(a:dir), a:cmd) 1978 | endfunction 1979 | 1980 | function! s:system(cmd, ...) 1981 | try 1982 | let [sh, shrd] = s:chsh(1) 1983 | let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd 1984 | return system(s:is_win ? '('.cmd.')' : cmd) 1985 | finally 1986 | let [&shell, &shellredir] = [sh, shrd] 1987 | endtry 1988 | endfunction 1989 | 1990 | function! s:system_chomp(...) 1991 | let ret = call('s:system', a:000) 1992 | return v:shell_error ? '' : substitute(ret, '\n$', '', '') 1993 | endfunction 1994 | 1995 | function! s:git_validate(spec, check_branch) 1996 | let err = '' 1997 | if isdirectory(a:spec.dir) 1998 | let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url', a:spec.dir)) 1999 | let remote = result[-1] 2000 | if v:shell_error 2001 | let err = join([remote, 'PlugClean required.'], "\n") 2002 | elseif !s:compare_git_uri(remote, a:spec.uri) 2003 | let err = join(['Invalid URI: '.remote, 2004 | \ 'Expected: '.a:spec.uri, 2005 | \ 'PlugClean required.'], "\n") 2006 | elseif a:check_branch && has_key(a:spec, 'commit') 2007 | let result = s:lines(s:system('git rev-parse HEAD 2>&1', a:spec.dir)) 2008 | let sha = result[-1] 2009 | if v:shell_error 2010 | let err = join(add(result, 'PlugClean required.'), "\n") 2011 | elseif !s:hash_match(sha, a:spec.commit) 2012 | let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', 2013 | \ a:spec.commit[:6], sha[:6]), 2014 | \ 'PlugUpdate required.'], "\n") 2015 | endif 2016 | elseif a:check_branch 2017 | let branch = result[0] 2018 | " Check tag 2019 | if has_key(a:spec, 'tag') 2020 | let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) 2021 | if a:spec.tag !=# tag 2022 | let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', 2023 | \ (empty(tag) ? 'N/A' : tag), a:spec.tag) 2024 | endif 2025 | " Check branch 2026 | elseif a:spec.branch !=# branch 2027 | let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', 2028 | \ branch, a:spec.branch) 2029 | endif 2030 | if empty(err) 2031 | let [ahead, behind] = split(s:lastline(s:system(printf( 2032 | \ 'git rev-list --count --left-right HEAD...origin/%s', 2033 | \ a:spec.branch), a:spec.dir)), '\t') 2034 | if !v:shell_error && ahead 2035 | if behind 2036 | " Only mention PlugClean if diverged, otherwise it's likely to be 2037 | " pushable (and probably not that messed up). 2038 | let err = printf( 2039 | \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" 2040 | \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', a:spec.branch, ahead, behind) 2041 | else 2042 | let err = printf("Ahead of origin/%s by %d commit(s).\n" 2043 | \ .'Cannot update until local changes are pushed.', 2044 | \ a:spec.branch, ahead) 2045 | endif 2046 | endif 2047 | endif 2048 | endif 2049 | else 2050 | let err = 'Not found' 2051 | endif 2052 | return [err, err =~# 'PlugClean'] 2053 | endfunction 2054 | 2055 | function! s:rm_rf(dir) 2056 | if isdirectory(a:dir) 2057 | call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . s:shellesc(a:dir)) 2058 | endif 2059 | endfunction 2060 | 2061 | function! s:clean(force) 2062 | call s:prepare() 2063 | call append(0, 'Searching for invalid plugins in '.g:plug_home) 2064 | call append(1, '') 2065 | 2066 | " List of valid directories 2067 | let dirs = [] 2068 | let errs = {} 2069 | let [cnt, total] = [0, len(g:plugs)] 2070 | for [name, spec] in items(g:plugs) 2071 | if !s:is_managed(name) 2072 | call add(dirs, spec.dir) 2073 | else 2074 | let [err, clean] = s:git_validate(spec, 1) 2075 | if clean 2076 | let errs[spec.dir] = s:lines(err)[0] 2077 | else 2078 | call add(dirs, spec.dir) 2079 | endif 2080 | endif 2081 | let cnt += 1 2082 | call s:progress_bar(2, repeat('=', cnt), total) 2083 | normal! 2G 2084 | redraw 2085 | endfor 2086 | 2087 | let allowed = {} 2088 | for dir in dirs 2089 | let allowed[s:dirpath(fnamemodify(dir, ':h:h'))] = 1 2090 | let allowed[dir] = 1 2091 | for child in s:glob_dir(dir) 2092 | let allowed[child] = 1 2093 | endfor 2094 | endfor 2095 | 2096 | let todo = [] 2097 | let found = sort(s:glob_dir(g:plug_home)) 2098 | while !empty(found) 2099 | let f = remove(found, 0) 2100 | if !has_key(allowed, f) && isdirectory(f) 2101 | call add(todo, f) 2102 | call append(line('$'), '- ' . f) 2103 | if has_key(errs, f) 2104 | call append(line('$'), ' ' . errs[f]) 2105 | endif 2106 | let found = filter(found, 'stridx(v:val, f) != 0') 2107 | end 2108 | endwhile 2109 | 2110 | 4 2111 | redraw 2112 | if empty(todo) 2113 | call append(line('$'), 'Already clean.') 2114 | else 2115 | let s:clean_count = 0 2116 | call append(3, ['Directories to delete:', '']) 2117 | redraw! 2118 | if a:force || s:ask_no_interrupt('Delete all directories?') 2119 | call s:delete([6, line('$')], 1) 2120 | else 2121 | call setline(4, 'Cancelled.') 2122 | nnoremap d :set opfunc=delete_opg@ 2123 | nmap dd d_ 2124 | xnoremap d :call delete_op(visualmode(), 1) 2125 | echo 'Delete the lines (d{motion}) to delete the corresponding directories' 2126 | endif 2127 | endif 2128 | 4 2129 | setlocal nomodifiable 2130 | endfunction 2131 | 2132 | function! s:delete_op(type, ...) 2133 | call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0) 2134 | endfunction 2135 | 2136 | function! s:delete(range, force) 2137 | let [l1, l2] = a:range 2138 | let force = a:force 2139 | while l1 <= l2 2140 | let line = getline(l1) 2141 | if line =~ '^- ' && isdirectory(line[2:]) 2142 | execute l1 2143 | redraw! 2144 | let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) 2145 | let force = force || answer > 1 2146 | if answer 2147 | call s:rm_rf(line[2:]) 2148 | setlocal modifiable 2149 | call setline(l1, '~'.line[1:]) 2150 | let s:clean_count += 1 2151 | call setline(4, printf('Removed %d directories.', s:clean_count)) 2152 | setlocal nomodifiable 2153 | endif 2154 | endif 2155 | let l1 += 1 2156 | endwhile 2157 | endfunction 2158 | 2159 | function! s:upgrade() 2160 | echo 'Downloading the latest version of vim-plug' 2161 | redraw 2162 | let tmp = tempname() 2163 | let new = tmp . '/plug.vim' 2164 | 2165 | try 2166 | let out = s:system(printf('git clone --depth 1 %s %s', s:plug_src, tmp)) 2167 | if v:shell_error 2168 | return s:err('Error upgrading vim-plug: '. out) 2169 | endif 2170 | 2171 | if readfile(s:me) ==# readfile(new) 2172 | echo 'vim-plug is already up-to-date' 2173 | return 0 2174 | else 2175 | call rename(s:me, s:me . '.old') 2176 | call rename(new, s:me) 2177 | unlet g:loaded_plug 2178 | echo 'vim-plug has been upgraded' 2179 | return 1 2180 | endif 2181 | finally 2182 | silent! call s:rm_rf(tmp) 2183 | endtry 2184 | endfunction 2185 | 2186 | function! s:upgrade_specs() 2187 | for spec in values(g:plugs) 2188 | let spec.frozen = get(spec, 'frozen', 0) 2189 | endfor 2190 | endfunction 2191 | 2192 | function! s:status() 2193 | call s:prepare() 2194 | call append(0, 'Checking plugins') 2195 | call append(1, '') 2196 | 2197 | let ecnt = 0 2198 | let unloaded = 0 2199 | let [cnt, total] = [0, len(g:plugs)] 2200 | for [name, spec] in items(g:plugs) 2201 | if has_key(spec, 'uri') 2202 | if isdirectory(spec.dir) 2203 | let [err, _] = s:git_validate(spec, 1) 2204 | let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] 2205 | else 2206 | let [valid, msg] = [0, 'Not found. Try PlugInstall.'] 2207 | endif 2208 | else 2209 | if isdirectory(spec.dir) 2210 | let [valid, msg] = [1, 'OK'] 2211 | else 2212 | let [valid, msg] = [0, 'Not found.'] 2213 | endif 2214 | endif 2215 | let cnt += 1 2216 | let ecnt += !valid 2217 | " `s:loaded` entry can be missing if PlugUpgraded 2218 | if valid && get(s:loaded, name, -1) == 0 2219 | let unloaded = 1 2220 | let msg .= ' (not loaded)' 2221 | endif 2222 | call s:progress_bar(2, repeat('=', cnt), total) 2223 | call append(3, s:format_message(valid ? '-' : 'x', name, msg)) 2224 | normal! 2G 2225 | redraw 2226 | endfor 2227 | call setline(1, 'Finished. '.ecnt.' error(s).') 2228 | normal! gg 2229 | setlocal nomodifiable 2230 | if unloaded 2231 | echo "Press 'L' on each line to load plugin, or 'U' to update" 2232 | nnoremap L :call status_load(line('.')) 2233 | xnoremap L :call status_load(line('.')) 2234 | end 2235 | endfunction 2236 | 2237 | function! s:extract_name(str, prefix, suffix) 2238 | return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$') 2239 | endfunction 2240 | 2241 | function! s:status_load(lnum) 2242 | let line = getline(a:lnum) 2243 | let name = s:extract_name(line, '-', '(not loaded)') 2244 | if !empty(name) 2245 | call plug#load(name) 2246 | setlocal modifiable 2247 | call setline(a:lnum, substitute(line, ' (not loaded)$', '', '')) 2248 | setlocal nomodifiable 2249 | endif 2250 | endfunction 2251 | 2252 | function! s:status_update() range 2253 | let lines = getline(a:firstline, a:lastline) 2254 | let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)') 2255 | if !empty(names) 2256 | echo 2257 | execute 'PlugUpdate' join(names) 2258 | endif 2259 | endfunction 2260 | 2261 | function! s:is_preview_window_open() 2262 | silent! wincmd P 2263 | if &previewwindow 2264 | wincmd p 2265 | return 1 2266 | endif 2267 | endfunction 2268 | 2269 | function! s:find_name(lnum) 2270 | for lnum in reverse(range(1, a:lnum)) 2271 | let line = getline(lnum) 2272 | if empty(line) 2273 | return '' 2274 | endif 2275 | let name = s:extract_name(line, '-', '') 2276 | if !empty(name) 2277 | return name 2278 | endif 2279 | endfor 2280 | return '' 2281 | endfunction 2282 | 2283 | function! s:preview_commit() 2284 | if b:plug_preview < 0 2285 | let b:plug_preview = !s:is_preview_window_open() 2286 | endif 2287 | 2288 | let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}') 2289 | if empty(sha) 2290 | return 2291 | endif 2292 | 2293 | let name = s:find_name(line('.')) 2294 | if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir) 2295 | return 2296 | endif 2297 | 2298 | if exists('g:plug_pwindow') && !s:is_preview_window_open() 2299 | execute g:plug_pwindow 2300 | execute 'e' sha 2301 | else 2302 | execute 'pedit' sha 2303 | wincmd P 2304 | endif 2305 | setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable 2306 | try 2307 | let [sh, shrd] = s:chsh(1) 2308 | execute 'silent %!cd' s:shellesc(g:plugs[name].dir) '&& git show --no-color --pretty=medium' sha 2309 | finally 2310 | let [&shell, &shellredir] = [sh, shrd] 2311 | endtry 2312 | setlocal nomodifiable 2313 | nnoremap q :q 2314 | wincmd p 2315 | endfunction 2316 | 2317 | function! s:section(flags) 2318 | call search('\(^[x-] \)\@<=[^:]\+:', a:flags) 2319 | endfunction 2320 | 2321 | function! s:format_git_log(line) 2322 | let indent = ' ' 2323 | let tokens = split(a:line, nr2char(1)) 2324 | if len(tokens) != 5 2325 | return indent.substitute(a:line, '\s*$', '', '') 2326 | endif 2327 | let [graph, sha, refs, subject, date] = tokens 2328 | let tag = matchstr(refs, 'tag: [^,)]\+') 2329 | let tag = empty(tag) ? ' ' : ' ('.tag.') ' 2330 | return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date) 2331 | endfunction 2332 | 2333 | function! s:append_ul(lnum, text) 2334 | call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) 2335 | endfunction 2336 | 2337 | function! s:diff() 2338 | call s:prepare() 2339 | call append(0, ['Collecting changes ...', '']) 2340 | let cnts = [0, 0] 2341 | let bar = '' 2342 | let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') 2343 | call s:progress_bar(2, bar, len(total)) 2344 | for origin in [1, 0] 2345 | let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) 2346 | if empty(plugs) 2347 | continue 2348 | endif 2349 | call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') 2350 | for [k, v] in plugs 2351 | let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' 2352 | let diff = s:system_chomp('git log --graph --color=never --pretty=format:"%x01%h%x01%d%x01%s%x01%cr" '.s:shellesc(range), v.dir) 2353 | if !empty(diff) 2354 | let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' 2355 | call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) 2356 | let cnts[origin] += 1 2357 | endif 2358 | let bar .= '=' 2359 | call s:progress_bar(2, bar, len(total)) 2360 | normal! 2G 2361 | redraw 2362 | endfor 2363 | if !cnts[origin] 2364 | call append(5, ['', 'N/A']) 2365 | endif 2366 | endfor 2367 | call setline(1, printf('%d plugin(s) updated.', cnts[0]) 2368 | \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) 2369 | 2370 | if cnts[0] || cnts[1] 2371 | nnoremap :silent! call preview_commit() 2372 | nnoremap o :silent! call preview_commit() 2373 | endif 2374 | if cnts[0] 2375 | nnoremap X :call revert() 2376 | echo "Press 'X' on each block to revert the update" 2377 | endif 2378 | normal! gg 2379 | setlocal nomodifiable 2380 | endfunction 2381 | 2382 | function! s:revert() 2383 | if search('^Pending updates', 'bnW') 2384 | return 2385 | endif 2386 | 2387 | let name = s:find_name(line('.')) 2388 | if empty(name) || !has_key(g:plugs, name) || 2389 | \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' 2390 | return 2391 | endif 2392 | 2393 | call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch).' --', g:plugs[name].dir) 2394 | setlocal modifiable 2395 | normal! "_dap 2396 | setlocal nomodifiable 2397 | echo 'Reverted' 2398 | endfunction 2399 | 2400 | function! s:snapshot(force, ...) abort 2401 | call s:prepare() 2402 | setf vim 2403 | call append(0, ['" Generated by vim-plug', 2404 | \ '" '.strftime("%c"), 2405 | \ '" :source this file in vim to restore the snapshot', 2406 | \ '" or execute: vim -S snapshot.vim', 2407 | \ '', '', 'PlugUpdate!']) 2408 | 1 2409 | let anchor = line('$') - 3 2410 | let names = sort(keys(filter(copy(g:plugs), 2411 | \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)'))) 2412 | for name in reverse(names) 2413 | let sha = s:system_chomp('git rev-parse --short HEAD', g:plugs[name].dir) 2414 | if !empty(sha) 2415 | call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) 2416 | redraw 2417 | endif 2418 | endfor 2419 | 2420 | if a:0 > 0 2421 | let fn = expand(a:1) 2422 | if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?')) 2423 | return 2424 | endif 2425 | call writefile(getline(1, '$'), fn) 2426 | echo 'Saved as '.a:1 2427 | silent execute 'e' s:esc(fn) 2428 | setf vim 2429 | endif 2430 | endfunction 2431 | 2432 | function! s:split_rtp() 2433 | return split(&rtp, '\\\@ 10 | 11 | NOTE: Only builds 480 (Jan 11 2011) and later support import of color schemes. 12 | If the stable release doesn't include this function, grab the nightly build 13 | from: 14 | 15 | Open iTerm 2, open Preferences, click on the "Profiles" (formerly Addresses, 16 | formerly Bookmarks) icon in the preferences toolbar, then select the "colors" 17 | tab. Click on the "load presets" and select "import...". Select the Solaris 18 | Light or Dark theme file. 19 | 20 | You have now loaded the Solarized color presets into iTerm 2, but haven't yet 21 | applied them. To apply them, simply select an existing profile from the profile 22 | list window on the left, or create a new profile. Then select the Solarized 23 | Dark or Solarized Light preset from the "Load Presets" drop down. 24 | 25 | Ok, I've gone crazy with iTerm2 color management but you are going to be ok. 26 | Just realize two things: 27 | 28 | 1. Like other apps (Chrome as of this writing) on the Mac, iTerm2 locks in 29 | a target color space when you create a new window. If you switch your 30 | monitor color space, relaunch iTerm2 and it will pick up the new target 31 | color space. 32 | 33 | 2. The colors in iTerm2 currently cannot be device colors. They are baked in as 34 | generic rgb (which, despite the name, is an actual, specific color space 35 | from Apple and is used as a default just like other systems use sRGB as 36 | a default). I've switch Solarized Apple Color Picker palettes to use tagged 37 | colors by default, so for the most part iTerm2 will match up with other apps 38 | where you use Color Picker swatches. 39 | 40 | The Values 41 | ---------- 42 | 43 | L\*a\*b values are canonical (White D65, Reference D50), other values are 44 | matched in sRGB space. 45 | 46 | SOLARIZED HEX 16/8 TERMCOL XTERM/HEX L*A*B RGB HSB 47 | --------- ------- ---- ------- ----------- ---------- ----------- ----------- 48 | base03 #002b36 8/4 brblack 234 #1c1c1c 15 -12 -12 0 43 54 193 100 21 49 | base02 #073642 0/4 black 235 #262626 20 -12 -12 7 54 66 192 90 26 50 | base01 #586e75 10/7 brgreen 240 #585858 45 -07 -07 88 110 117 194 25 46 51 | base00 #657b83 11/7 bryellow 241 #626262 50 -07 -07 101 123 131 195 23 51 52 | base0 #839496 12/6 brblue 244 #808080 60 -06 -03 131 148 150 186 13 59 53 | base1 #93a1a1 14/4 brcyan 245 #8a8a8a 65 -05 -02 147 161 161 180 9 63 54 | base2 #eee8d5 7/7 white 254 #e4e4e4 92 -00 10 238 232 213 44 11 93 55 | base3 #fdf6e3 15/7 brwhite 230 #ffffd7 97 00 10 253 246 227 44 10 99 56 | yellow #b58900 3/3 yellow 136 #af8700 60 10 65 181 137 0 45 100 71 57 | orange #cb4b16 9/3 brred 166 #d75f00 50 50 55 203 75 22 18 89 80 58 | red #d30102 1/1 red 124 #af0000 45 70 60 211 1 2 0 99 83 59 | magenta #d33682 5/5 magenta 125 #af005f 50 65 -05 211 54 130 331 74 83 60 | violet #6c71c4 13/5 brmagenta 61 #5f5faf 50 15 -45 108 113 196 237 45 77 61 | blue #268bd2 4/4 blue 33 #0087ff 55 -10 -45 38 139 210 205 82 82 62 | cyan #2aa198 6/6 cyan 37 #00afaf 60 -35 -05 42 161 152 175 74 63 63 | green #859900 2/2 green 64 #5f8700 60 -20 65 133 153 0 68 100 60 64 | -------------------------------------------------------------------------------- /others/iterm2-colors-solarized/Solarized Dark.itermcolors: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ansi 0 Color 6 | 7 | Blue Component 8 | 0.19370138645172119 9 | Green Component 10 | 0.15575926005840302 11 | Red Component 12 | 0.0 13 | 14 | Ansi 1 Color 15 | 16 | Blue Component 17 | 0.14145714044570923 18 | Green Component 19 | 0.10840655118227005 20 | Red Component 21 | 0.81926977634429932 22 | 23 | Ansi 10 Color 24 | 25 | Blue Component 26 | 0.38298487663269043 27 | Green Component 28 | 0.35665956139564514 29 | Red Component 30 | 0.27671992778778076 31 | 32 | Ansi 11 Color 33 | 34 | Blue Component 35 | 0.43850564956665039 36 | Green Component 37 | 0.40717673301696777 38 | Red Component 39 | 0.32436618208885193 40 | 41 | Ansi 12 Color 42 | 43 | Blue Component 44 | 0.51685798168182373 45 | Green Component 46 | 0.50962930917739868 47 | Red Component 48 | 0.44058024883270264 49 | 50 | Ansi 13 Color 51 | 52 | Blue Component 53 | 0.72908437252044678 54 | Green Component 55 | 0.33896297216415405 56 | Red Component 57 | 0.34798634052276611 58 | 59 | Ansi 14 Color 60 | 61 | Blue Component 62 | 0.56363654136657715 63 | Green Component 64 | 0.56485837697982788 65 | Red Component 66 | 0.50599193572998047 67 | 68 | Ansi 15 Color 69 | 70 | Blue Component 71 | 0.86405980587005615 72 | Green Component 73 | 0.95794391632080078 74 | Red Component 75 | 0.98943418264389038 76 | 77 | Ansi 2 Color 78 | 79 | Blue Component 80 | 0.020208755508065224 81 | Green Component 82 | 0.54115492105484009 83 | Red Component 84 | 0.44977453351020813 85 | 86 | Ansi 3 Color 87 | 88 | Blue Component 89 | 0.023484811186790466 90 | Green Component 91 | 0.46751424670219421 92 | Red Component 93 | 0.64746475219726562 94 | 95 | Ansi 4 Color 96 | 97 | Blue Component 98 | 0.78231418132781982 99 | Green Component 100 | 0.46265947818756104 101 | Red Component 102 | 0.12754884362220764 103 | 104 | Ansi 5 Color 105 | 106 | Blue Component 107 | 0.43516635894775391 108 | Green Component 109 | 0.10802463442087173 110 | Red Component 111 | 0.77738940715789795 112 | 113 | Ansi 6 Color 114 | 115 | Blue Component 116 | 0.52502274513244629 117 | Green Component 118 | 0.57082360982894897 119 | Red Component 120 | 0.14679534733295441 121 | 122 | Ansi 7 Color 123 | 124 | Blue Component 125 | 0.79781103134155273 126 | Green Component 127 | 0.89001238346099854 128 | Red Component 129 | 0.91611063480377197 130 | 131 | Ansi 8 Color 132 | 133 | Blue Component 134 | 0.15170273184776306 135 | Green Component 136 | 0.11783610284328461 137 | Red Component 138 | 0.0 139 | 140 | Ansi 9 Color 141 | 142 | Blue Component 143 | 0.073530435562133789 144 | Green Component 145 | 0.21325300633907318 146 | Red Component 147 | 0.74176257848739624 148 | 149 | Background Color 150 | 151 | Blue Component 152 | 0.15170273184776306 153 | Green Component 154 | 0.11783610284328461 155 | Red Component 156 | 0.0 157 | 158 | Bold Color 159 | 160 | Blue Component 161 | 0.56363654136657715 162 | Green Component 163 | 0.56485837697982788 164 | Red Component 165 | 0.50599193572998047 166 | 167 | Cursor Color 168 | 169 | Blue Component 170 | 0.51685798168182373 171 | Green Component 172 | 0.50962930917739868 173 | Red Component 174 | 0.44058024883270264 175 | 176 | Cursor Text Color 177 | 178 | Blue Component 179 | 0.19370138645172119 180 | Green Component 181 | 0.15575926005840302 182 | Red Component 183 | 0.0 184 | 185 | Foreground Color 186 | 187 | Blue Component 188 | 0.51685798168182373 189 | Green Component 190 | 0.50962930917739868 191 | Red Component 192 | 0.44058024883270264 193 | 194 | Selected Text Color 195 | 196 | Blue Component 197 | 0.56363654136657715 198 | Green Component 199 | 0.56485837697982788 200 | Red Component 201 | 0.50599193572998047 202 | 203 | Selection Color 204 | 205 | Blue Component 206 | 0.19370138645172119 207 | Green Component 208 | 0.15575926005840302 209 | Red Component 210 | 0.0 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /others/iterm2-colors-solarized/Solarized Light.itermcolors: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ansi 0 Color 6 | 7 | Blue Component 8 | 0.19370138645172119 9 | Green Component 10 | 0.15575926005840302 11 | Red Component 12 | 0.0 13 | 14 | Ansi 1 Color 15 | 16 | Blue Component 17 | 0.14145712554454803 18 | Green Component 19 | 0.10840645432472229 20 | Red Component 21 | 0.81926983594894409 22 | 23 | Ansi 10 Color 24 | 25 | Blue Component 26 | 0.38298487663269043 27 | Green Component 28 | 0.35665956139564514 29 | Red Component 30 | 0.27671992778778076 31 | 32 | Ansi 11 Color 33 | 34 | Blue Component 35 | 0.43850564956665039 36 | Green Component 37 | 0.40717673301696777 38 | Red Component 39 | 0.32436618208885193 40 | 41 | Ansi 12 Color 42 | 43 | Blue Component 44 | 0.51685798168182373 45 | Green Component 46 | 0.50962930917739868 47 | Red Component 48 | 0.44058024883270264 49 | 50 | Ansi 13 Color 51 | 52 | Blue Component 53 | 0.72908437252044678 54 | Green Component 55 | 0.33896297216415405 56 | Red Component 57 | 0.34798634052276611 58 | 59 | Ansi 14 Color 60 | 61 | Blue Component 62 | 0.56363654136657715 63 | Green Component 64 | 0.56485837697982788 65 | Red Component 66 | 0.50599193572998047 67 | 68 | Ansi 15 Color 69 | 70 | Blue Component 71 | 0.86405980587005615 72 | Green Component 73 | 0.95794391632080078 74 | Red Component 75 | 0.98943418264389038 76 | 77 | Ansi 2 Color 78 | 79 | Blue Component 80 | 0.020208755508065224 81 | Green Component 82 | 0.54115492105484009 83 | Red Component 84 | 0.44977453351020813 85 | 86 | Ansi 3 Color 87 | 88 | Blue Component 89 | 0.023484811186790466 90 | Green Component 91 | 0.46751424670219421 92 | Red Component 93 | 0.64746475219726562 94 | 95 | Ansi 4 Color 96 | 97 | Blue Component 98 | 0.78231418132781982 99 | Green Component 100 | 0.46265947818756104 101 | Red Component 102 | 0.12754884362220764 103 | 104 | Ansi 5 Color 105 | 106 | Blue Component 107 | 0.43516635894775391 108 | Green Component 109 | 0.10802463442087173 110 | Red Component 111 | 0.77738940715789795 112 | 113 | Ansi 6 Color 114 | 115 | Blue Component 116 | 0.52502274513244629 117 | Green Component 118 | 0.57082360982894897 119 | Red Component 120 | 0.14679534733295441 121 | 122 | Ansi 7 Color 123 | 124 | Blue Component 125 | 0.79781103134155273 126 | Green Component 127 | 0.89001238346099854 128 | Red Component 129 | 0.91611063480377197 130 | 131 | Ansi 8 Color 132 | 133 | Blue Component 134 | 0.15170273184776306 135 | Green Component 136 | 0.11783610284328461 137 | Red Component 138 | 0.0 139 | 140 | Ansi 9 Color 141 | 142 | Blue Component 143 | 0.073530435562133789 144 | Green Component 145 | 0.21325300633907318 146 | Red Component 147 | 0.74176257848739624 148 | 149 | Background Color 150 | 151 | Blue Component 152 | 0.86405980587005615 153 | Green Component 154 | 0.95794391632080078 155 | Red Component 156 | 0.98943418264389038 157 | 158 | Bold Color 159 | 160 | Blue Component 161 | 0.38298487663269043 162 | Green Component 163 | 0.35665956139564514 164 | Red Component 165 | 0.27671992778778076 166 | 167 | Cursor Color 168 | 169 | Blue Component 170 | 0.43850564956665039 171 | Green Component 172 | 0.40717673301696777 173 | Red Component 174 | 0.32436618208885193 175 | 176 | Cursor Text Color 177 | 178 | Blue Component 179 | 0.79781103134155273 180 | Green Component 181 | 0.89001238346099854 182 | Red Component 183 | 0.91611063480377197 184 | 185 | Foreground Color 186 | 187 | Blue Component 188 | 0.43850564956665039 189 | Green Component 190 | 0.40717673301696777 191 | Red Component 192 | 0.32436618208885193 193 | 194 | Selected Text Color 195 | 196 | Blue Component 197 | 0.38298487663269043 198 | Green Component 199 | 0.35665956139564514 200 | Red Component 201 | 0.27671992778778076 202 | 203 | Selection Color 204 | 205 | Blue Component 206 | 0.79781103134155273 207 | Green Component 208 | 0.89001238346099854 209 | Red Component 210 | 0.91611063480377197 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /others/tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs": [ 3 | "browser", 4 | "jquery" 5 | ], 6 | "loadEagerly": [ 7 | "importantfile.js" 8 | ], 9 | "plugins": { 10 | "requirejs": { 11 | "baseURL": "./", 12 | "paths": {} 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | "========================================== 2 | " Author: wklken 3 | " Version: 9.1 4 | " Email: wklken@yeah.net 5 | " BlogPost: http://www.wklken.me 6 | " ReadMe: README.md 7 | " Donation: http://www.wklken.me/pages/donation.html 8 | " Last_modify: 2015-12-15 9 | " Sections: 10 | " -> Initial Plugin 加载插件 11 | " -> General Settings 基础设置 12 | " -> Display Settings 展示/排版等界面格式设置 13 | " -> FileEncode Settings 文件编码设置 14 | " -> Others 其它配置 15 | " -> HotKey Settings 自定义快捷键 16 | " -> FileType Settings 针对文件类型的设置 17 | " -> Theme Settings 主题设置 18 | " 19 | " -> 插件配置和具体设置在vimrc.bundles中 20 | " Note: Don't put anything in your .vimrc you don't understand! 21 | "========================================== 22 | 23 | "========================================== 24 | " Initial Plugin 加载插件 25 | "========================================== 26 | 27 | " 修改leader键 28 | let mapleader = ',' 29 | let g:mapleader = ',' 30 | 31 | " 开启语法高亮 32 | syntax on 33 | 34 | " install bundles 35 | if filereadable(expand("~/.vimrc.bundles")) 36 | source ~/.vimrc.bundles 37 | elseif filereadable(expand("~/.config/nvim/vimrc.bundles")) " neovim 38 | source ~/.config/nvim/vimrc.bundles 39 | endif 40 | 41 | " ensure ftdetect et al work by including this after the bundle stuff 42 | filetype plugin indent on 43 | 44 | " NOTE: 以下配置有详细说明,一些特性不喜欢可以直接注解掉 45 | 46 | "========================================== 47 | " General Settings 基础设置 48 | "========================================== 49 | 50 | 51 | " history存储容量 52 | set history=2000 53 | 54 | " 检测文件类型 55 | filetype on 56 | " 针对不同的文件类型采用不同的缩进格式 57 | filetype indent on 58 | " 允许插件 59 | filetype plugin on 60 | " 启动自动补全 61 | filetype plugin indent on 62 | 63 | " 文件修改之后自动载入 64 | set autoread 65 | " 启动的时候不显示那个援助乌干达儿童的提示 66 | set shortmess=atI 67 | 68 | " 备份,到另一个位置. 防止误删, 目前是取消备份 69 | "set backup 70 | "set backupext=.bak 71 | "set backupdir=/tmp/vimbk/ 72 | 73 | " 取消备份。 视情况自己改 74 | set nobackup 75 | " 关闭交换文件 76 | set noswapfile 77 | 78 | 79 | " TODO: remove this, use gundo 80 | " create undo file 81 | " if has('persistent_undo') 82 | " " How many undos 83 | " set undolevels=1000 84 | " " number of lines to save for undo 85 | " set undoreload=10000 86 | " " So is persistent undo ... 87 | " "set undofile 88 | " set noundofile 89 | " " set undodir=/tmp/vimundo/ 90 | " endif 91 | 92 | set wildignore=*.swp,*.bak,*.pyc,*.class,.svn 93 | 94 | " 突出显示当前列 95 | set cursorcolumn 96 | " 突出显示当前行 97 | set cursorline 98 | 99 | 100 | " 设置 退出vim后,内容显示在终端屏幕, 可以用于查看和复制, 不需要可以去掉 101 | " 好处:误删什么的,如果以前屏幕打开,可以找回 102 | set t_ti= t_te= 103 | 104 | 105 | " 鼠标暂不启用, 键盘党.... 106 | set mouse-=a 107 | " 启用鼠标 108 | " set mouse=a 109 | " Hide the mouse cursor while typing 110 | " set mousehide 111 | 112 | 113 | " 修复ctrl+m 多光标操作选择的bug,但是改变了ctrl+v进行字符选中时将包含光标下的字符 114 | set selection=inclusive 115 | set selectmode=mouse,key 116 | 117 | " change the terminal's title 118 | set title 119 | " 去掉输入错误的提示声音 120 | set novisualbell 121 | set noerrorbells 122 | set t_vb= 123 | set tm=500 124 | 125 | " Remember info about open buffers on close 126 | set viminfo^=% 127 | 128 | " For regular expressions turn magic on 129 | set magic 130 | 131 | " Configure backspace so it acts as it should act 132 | set backspace=eol,start,indent 133 | set whichwrap+=<,>,h,l 134 | 135 | "========================================== 136 | " Display Settings 展示/排版等界面格式设置 137 | "========================================== 138 | 139 | " 显示当前的行号列号 140 | set ruler 141 | " 在状态栏显示正在输入的命令 142 | set showcmd 143 | " 左下角显示当前vim模式 144 | set showmode 145 | 146 | " 在上下移动光标时,光标的上方或下方至少会保留显示的行数 147 | set scrolloff=7 148 | 149 | " set winwidth=79 150 | 151 | " 命令行(在状态行下)的高度,默认为1,这里是2 152 | set statusline=%<%f\ %h%m%r%=%k[%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}]\ %-14.(%l,%c%V%)\ %P 153 | " Always show the status line - use 2 lines for the status bar 154 | set laststatus=2 155 | 156 | " 显示行号 157 | set number 158 | " 取消换行 159 | set nowrap 160 | 161 | " 括号配对情况, 跳转并高亮一下匹配的括号 162 | set showmatch 163 | " How many tenths of a second to blink when matching brackets 164 | set matchtime=2 165 | 166 | 167 | " 设置文内智能搜索提示 168 | " 高亮search命中的文本 169 | set hlsearch 170 | " 打开增量搜索模式,随着键入即时搜索 171 | set incsearch 172 | " 搜索时忽略大小写 173 | set ignorecase 174 | " 有一个或以上大写字母时仍大小写敏感 175 | set smartcase 176 | 177 | " 代码折叠 178 | set foldenable 179 | " 折叠方法 180 | " manual 手工折叠 181 | " indent 使用缩进表示折叠 182 | " expr 使用表达式定义折叠 183 | " syntax 使用语法定义折叠 184 | " diff 对没有更改的文本进行折叠 185 | " marker 使用标记进行折叠, 默认标记是 {{{ 和 }}} 186 | set foldmethod=indent 187 | set foldlevel=99 188 | " 代码折叠自定义快捷键 zz 189 | let g:FoldMethod = 0 190 | map zz :call ToggleFold() 191 | fun! ToggleFold() 192 | if g:FoldMethod == 0 193 | exe "normal! zM" 194 | let g:FoldMethod = 1 195 | else 196 | exe "normal! zR" 197 | let g:FoldMethod = 0 198 | endif 199 | endfun 200 | 201 | " 缩进配置 202 | " Smart indent 203 | set smartindent 204 | " 打开自动缩进 205 | " never add copyindent, case error " copy the previous indentation on autoindenting 206 | set autoindent 207 | 208 | " tab相关变更 209 | " 设置Tab键的宽度 [等同的空格个数] 210 | set tabstop=4 211 | " 每一次缩进对应的空格数 212 | set shiftwidth=4 213 | " 按退格键时可以一次删掉 4 个空格 214 | set softtabstop=4 215 | " insert tabs on the start of a line according to shiftwidth, not tabstop 按退格键时可以一次删掉 4 个空格 216 | set smarttab 217 | " 将Tab自动转化成空格[需要输入真正的Tab键时,使用 Ctrl+V + Tab] 218 | set expandtab 219 | " 缩进时,取整 use multiple of shiftwidth when indenting with '<' and '>' 220 | set shiftround 221 | 222 | " A buffer becomes hidden when it is abandoned 223 | set hidden 224 | set wildmode=list:longest 225 | set ttyfast 226 | 227 | " 00x增减数字时使用十进制 228 | set nrformats= 229 | 230 | " 相对行号: 行号变成相对,可以用 nj/nk 进行跳转 231 | set relativenumber number 232 | au FocusLost * :set norelativenumber number 233 | au FocusGained * :set relativenumber 234 | " 插入模式下用绝对行号, 普通模式下用相对 235 | autocmd InsertEnter * :set norelativenumber number 236 | autocmd InsertLeave * :set relativenumber 237 | function! NumberToggle() 238 | if(&relativenumber == 1) 239 | set norelativenumber number 240 | else 241 | set relativenumber 242 | endif 243 | endfunc 244 | nnoremap :call NumberToggle() 245 | 246 | " 防止tmux下vim的背景色显示异常 247 | " Refer: http://sunaku.github.io/vim-256color-bce.html 248 | if &term =~ '256color' 249 | " disable Background Color Erase (BCE) so that color schemes 250 | " render properly when inside 256-color tmux and GNU screen. 251 | " see also http://snk.tuxfamily.org/log/vim-256color-bce.html 252 | set t_ut= 253 | endif 254 | 255 | "========================================== 256 | " FileEncode Settings 文件编码,格式 257 | "========================================== 258 | " 设置新文件的编码为 UTF-8 259 | set encoding=utf-8 260 | " 自动判断编码时,依次尝试以下编码: 261 | set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1 262 | set helplang=cn 263 | "set langmenu=zh_CN.UTF-8 264 | "set enc=2byte-gb18030 265 | " 下面这句只影响普通模式 (非图形界面) 下的 Vim 266 | set termencoding=utf-8 267 | 268 | " Use Unix as the standard file type 269 | set ffs=unix,dos,mac 270 | 271 | " 如遇Unicode值大于255的文本,不必等到空格再折行 272 | set formatoptions+=m 273 | " 合并两行中文时,不在中间加空格 274 | set formatoptions+=B 275 | 276 | 277 | "========================================== 278 | " others 其它设置 279 | "========================================== 280 | " vimrc文件修改之后自动加载, windows 281 | autocmd! bufwritepost _vimrc source % 282 | " vimrc文件修改之后自动加载, linux 283 | autocmd! bufwritepost .vimrc source % 284 | 285 | " 自动补全配置 286 | " 让Vim的补全菜单行为与一般IDE一致(参考VimTip1228) 287 | set completeopt=longest,menu 288 | 289 | " 增强模式中的命令行自动完成操作 290 | set wildmenu 291 | " Ignore compiled files 292 | set wildignore=*.o,*~,*.pyc,*.class 293 | 294 | " 离开插入模式后自动关闭预览窗口 295 | autocmd InsertLeave * if pumvisible() == 0|pclose|endif 296 | 297 | " 回车即选中当前项 298 | inoremap pumvisible() ? "\" : "\" 299 | 300 | " In the quickfix window, is used to jump to the error under the 301 | " cursor, so undefine the mapping there. 302 | autocmd BufReadPost quickfix nnoremap 303 | " quickfix window s/v to open in split window, ,gd/,jd => quickfix window => open it 304 | autocmd BufReadPost quickfix nnoremap v L 305 | autocmd BufReadPost quickfix nnoremap s K 306 | 307 | " command-line window 308 | autocmd CmdwinEnter * nnoremap 309 | 310 | 311 | " 上下左右键的行为 会显示其他信息 312 | inoremap pumvisible() ? "\" : "\" 313 | inoremap pumvisible() ? "\" : "\" 314 | inoremap pumvisible() ? "\\\" : "\" 315 | inoremap pumvisible() ? "\\\" : "\" 316 | 317 | " 打开自动定位到最后编辑的位置, 需要确认 .viminfo 当前用户可写 318 | if has("autocmd") 319 | au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif 320 | endif 321 | 322 | "========================================== 323 | " HotKey Settings 自定义快捷键设置 324 | "========================================== 325 | 326 | " 主要按键重定义 327 | 328 | " 关闭方向键, 强迫自己用 hjkl 329 | map 330 | map 331 | map 332 | map 333 | 334 | "Treat long lines as break lines (useful when moving around in them) 335 | "se swap之后,同物理行上线直接跳 336 | nnoremap k gk 337 | nnoremap gk k 338 | nnoremap j gj 339 | nnoremap gj j 340 | 341 | " F1 - F6 设置 342 | 343 | " F1 废弃这个键,防止调出系统帮助 344 | " I can type :help on my own, thanks. Protect your fat fingers from the evils of 345 | noremap " 346 | 347 | " F2 行号开关,用于鼠标复制代码用 348 | " 为方便复制,用开启/关闭行号显示: 349 | function! HideNumber() 350 | if(&relativenumber == &number) 351 | set relativenumber! number! 352 | elseif(&number) 353 | set number! 354 | else 355 | set relativenumber! 356 | endif 357 | set number? 358 | endfunc 359 | nnoremap :call HideNumber() 360 | " F3 显示可打印字符开关 361 | nnoremap :set list! list? 362 | " F4 换行开关 363 | nnoremap :set wrap! wrap? 364 | 365 | " F6 语法开关,关闭语法可以加快大文件的展示 366 | nnoremap :exec exists('syntax_on') ? 'syn off' : 'syn on' 367 | 368 | set pastetoggle= " when in insert mode, press to go to 369 | " paste mode, where you can paste mass data 370 | " that won't be autoindented 371 | 372 | " disbale paste mode when leaving insert mode 373 | au InsertLeave * set nopaste 374 | 375 | " F5 set paste问题已解决, 粘贴代码前不需要按F5了 376 | " F5 粘贴模式paste_mode开关,用于有格式的代码粘贴 377 | " Automatically set paste mode in Vim when pasting in insert mode 378 | function! XTermPasteBegin() 379 | set pastetoggle=[201~ 380 | set paste 381 | return "" 382 | endfunction 383 | inoremap [200~ XTermPasteBegin() 384 | 385 | 386 | 387 | " 分屏窗口移动, Smart way to move between windows 388 | map j 389 | map k 390 | map h 391 | map l 392 | 393 | 394 | " http://stackoverflow.com/questions/13194428/is-better-way-to-zoom-windows-in-vim-than-zoomwin 395 | " Zoom / Restore window. 396 | function! s:ZoomToggle() abort 397 | if exists('t:zoomed') && t:zoomed 398 | execute t:zoom_winrestcmd 399 | let t:zoomed = 0 400 | else 401 | let t:zoom_winrestcmd = winrestcmd() 402 | resize 403 | vertical resize 404 | let t:zoomed = 1 405 | endif 406 | endfunction 407 | command! ZoomToggle call s:ZoomToggle() 408 | nnoremap z :ZoomToggle 409 | 410 | 411 | " Go to home and end using capitalized directions 412 | noremap H ^ 413 | noremap L $ 414 | 415 | 416 | " Map ; to : and save a million keystrokes 用于快速进入命令行 417 | nnoremap ; : 418 | 419 | 420 | " 命令行模式增强,ctrl - a到行首, -e 到行尾 421 | cnoremap 422 | cnoremap 423 | cnoremap 424 | cnoremap 425 | 426 | 427 | " 搜索相关 428 | " Map to / (search) and Ctrl- to ? (backwards search) 429 | map / 430 | " 进入搜索Use sane regexes" 431 | nnoremap / /\v 432 | vnoremap / /\v 433 | 434 | " Keep search pattern at the center of the screen. 435 | nnoremap n nzz 436 | nnoremap N Nzz 437 | nnoremap * *zz 438 | nnoremap # #zz 439 | nnoremap g* g*zz 440 | 441 | " 去掉搜索高亮 442 | noremap / :nohls 443 | 444 | " switch # * 445 | nnoremap # * 446 | nnoremap * # 447 | 448 | " for # indent, python文件中输入新行时#号注释不切回行首 449 | autocmd BufNewFile,BufRead *.py inoremap # X# 450 | 451 | 452 | " tab/buffer相关 453 | 454 | " 切换前后buffer 455 | nnoremap [b :bprevious 456 | nnoremap ]b :bnext 457 | " 使用方向键切换buffer 458 | noremap :bp 459 | noremap :bn 460 | 461 | 462 | " tab 操作 463 | " http://vim.wikia.com/wiki/Alternative_tab_navigation 464 | " http://stackoverflow.com/questions/2005214/switching-to-a-particular-tab-in-vim 465 | 466 | " tab切换 467 | map th :tabfirst 468 | map tl :tablast 469 | 470 | map tj :tabnext 471 | map tk :tabprev 472 | map tn :tabnext 473 | map tp :tabprev 474 | 475 | map te :tabedit 476 | map td :tabclose 477 | map tm :tabm 478 | 479 | " normal模式下切换到确切的tab 480 | noremap 1 1gt 481 | noremap 2 2gt 482 | noremap 3 3gt 483 | noremap 4 4gt 484 | noremap 5 5gt 485 | noremap 6 6gt 486 | noremap 7 7gt 487 | noremap 8 8gt 488 | noremap 9 9gt 489 | noremap 0 :tablast 490 | 491 | " Toggles between the active and last active tab " 492 | " The first tab is always 1 " 493 | let g:last_active_tab = 1 494 | " nnoremap gt :execute 'tabnext ' . g:last_active_tab 495 | " nnoremap :execute 'tabnext ' . g:last_active_tab 496 | " vnoremap :execute 'tabnext ' . g:last_active_tab 497 | nnoremap tt :execute 'tabnext ' . g:last_active_tab 498 | autocmd TabLeave * let g:last_active_tab = tabpagenr() 499 | 500 | " 新建tab Ctrl+t 501 | nnoremap :tabnew 502 | inoremap :tabnew 503 | 504 | 505 | " => 选中及操作改键 506 | 507 | " 调整缩进后自动选中,方便再次操作 508 | vnoremap < >gv 510 | 511 | " y$ -> Y Make Y behave like other capitals 512 | map Y y$ 513 | 514 | " 复制选中区到系统剪切板中 515 | vnoremap y "+y 516 | 517 | " auto jump to end of select 518 | " vnoremap y y`] 519 | " vnoremap p p`] 520 | " nnoremap p p`] 521 | 522 | " select all 523 | map sa ggVG 524 | 525 | " 选中并高亮最后一次插入的内容 526 | nnoremap gv `[v`] 527 | 528 | " select block 529 | nnoremap v V`} 530 | 531 | " w!! to sudo & write a file 532 | cmap w!! w !sudo tee >/dev/null % 533 | 534 | " kj 替换 Esc 535 | inoremap kj 536 | 537 | " 滚动Speed up scrolling of the viewport slightly 538 | nnoremap 2 539 | nnoremap 2 540 | 541 | 542 | " Jump to start and end of line using the home row keys 543 | " 增强tab操作, 导致这个会有问题, 考虑换键 544 | "nmap t ok 545 | "nmap T Oj 546 | 547 | " Quickly close the current window 548 | nnoremap q :q 549 | 550 | " Quickly save the current file 551 | nnoremap w :w 552 | 553 | " 交换 ' `, 使得可以快速使用'跳到marked位置 554 | nnoremap ' ` 555 | nnoremap ` ' 556 | 557 | " remap U to for easier redo 558 | nnoremap U 559 | 560 | " Quickly edit/reload the vimrc file 561 | " nmap ev :e $MYVIMRC 562 | " nmap sv :so $MYVIMRC 563 | " edit vimrc/zshrc and load vimrc bindings 564 | nnoremap ev :vsp $MYVIMRC 565 | nnoremap ez :vsp ~/.zshrc 566 | nnoremap sv :source $MYVIMRC 567 | 568 | "========================================== 569 | " FileType Settings 文件类型设置 570 | "========================================== 571 | 572 | " 具体编辑文件类型的一般设置,比如不要 tab 等 573 | autocmd FileType python set tabstop=4 shiftwidth=4 expandtab ai 574 | autocmd FileType ruby,javascript,html,css,xml set tabstop=2 shiftwidth=2 softtabstop=2 expandtab ai 575 | autocmd BufRead,BufNewFile *.md,*.mkd,*.markdown set filetype=markdown.mkd 576 | autocmd BufRead,BufNewFile *.part set filetype=html 577 | autocmd BufRead,BufNewFile *.vue setlocal filetype=vue.html.javascript tabstop=2 shiftwidth=2 softtabstop=2 expandtab ai 578 | 579 | " disable showmatch when use > in php 580 | au BufWinEnter *.php set mps-=<:> 581 | 582 | 583 | 584 | " 保存python文件时删除多余空格 585 | fun! StripTrailingWhitespaces() 586 | let l = line(".") 587 | let c = col(".") 588 | %s/\s\+$//e 589 | call cursor(l, c) 590 | endfun 591 | autocmd FileType c,cpp,java,go,php,javascript,puppet,python,rust,twig,xml,yml,perl autocmd BufWritePre :call StripTrailingWhitespaces() 592 | 593 | 594 | " 定义函数AutoSetFileHead,自动插入文件头 595 | autocmd BufNewFile *.sh,*.py exec ":call AutoSetFileHead()" 596 | function! AutoSetFileHead() 597 | "如果文件类型为.sh文件 598 | if &filetype == 'sh' 599 | call setline(1, "\#!/bin/bash") 600 | endif 601 | 602 | "如果文件类型为python 603 | if &filetype == 'python' 604 | " call setline(1, "\#!/usr/bin/env python") 605 | " call append(1, "\# encoding: utf-8") 606 | call setline(1, "\# -*- coding: utf-8 -*-") 607 | endif 608 | 609 | normal G 610 | normal o 611 | normal o 612 | endfunc 613 | 614 | 615 | " 设置可以高亮的关键字 616 | if has("autocmd") 617 | " Highlight TODO, FIXME, NOTE, etc. 618 | if v:version > 701 619 | autocmd Syntax * call matchadd('Todo', '\W\zs\(TODO\|FIXME\|CHANGED\|DONE\|XXX\|BUG\|HACK\)') 620 | autocmd Syntax * call matchadd('Debug', '\W\zs\(NOTE\|INFO\|IDEA\|NOTICE\)') 621 | endif 622 | endif 623 | 624 | "========================================== 625 | " TEMP 设置, 尚未确定要不要 626 | "========================================== 627 | 628 | " beta 629 | " https://dougblack.io/words/a-good-vimrc.html 630 | set lazyredraw " redraw only when we need to. 631 | 632 | 633 | "========================================== 634 | " Theme Settings 主题设置 635 | "========================================== 636 | 637 | " Set extra options when running in GUI mode 638 | if has("gui_running") 639 | set guifont=Monaco:h14 640 | if has("gui_gtk2") "GTK2 641 | set guifont=Monaco\ 12,Monospace\ 12 642 | endif 643 | set guioptions-=T 644 | set guioptions+=e 645 | set guioptions-=r 646 | set guioptions-=L 647 | set guitablabel=%M\ %t 648 | set showtabline=1 649 | set linespace=2 650 | set noimd 651 | set t_Co=256 652 | endif 653 | 654 | 655 | 656 | " theme主题 657 | set background=dark 658 | set t_Co=256 659 | 660 | colorscheme solarized 661 | " colorscheme molokai 662 | 663 | 664 | " 设置标记一列的背景颜色和数字一行颜色一致 665 | hi! link SignColumn LineNr 666 | hi! link ShowMarksHLl DiffAdd 667 | hi! link ShowMarksHLu DiffChange 668 | 669 | " for error highlight,防止错误整行标红导致看不清 670 | highlight clear SpellBad 671 | highlight SpellBad term=standout ctermfg=1 term=underline cterm=underline 672 | highlight clear SpellCap 673 | highlight SpellCap term=underline cterm=underline 674 | highlight clear SpellRare 675 | highlight SpellRare term=underline cterm=underline 676 | highlight clear SpellLocal 677 | highlight SpellLocal term=underline cterm=underline 678 | -------------------------------------------------------------------------------- /vimrc.bundles: -------------------------------------------------------------------------------- 1 | " ========================================== 2 | " bundle 插件管理和配置项 3 | " ========================================== 4 | 5 | "------------------------------------------- begin of configs -------------------------------------------- 6 | 7 | " ################### 包依赖 ##################### 8 | " package dependence: ctags, ag(he_silver_searcher) 9 | " python dependence: pep8, pyflake 10 | 11 | " 非兼容vi模式。去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限 12 | set nocompatible 13 | filetype off " required! turn off 14 | 15 | " ################### 插件管理 ################### 16 | 17 | " inspired by spf13, 自定义需要的插件集合 18 | if !exists('g:bundle_groups') 19 | " let g:bundle_groups=['python', 'javascript', 'golang', 'php', 'ruby', 'shell', 'markdown', 'html', 'css', 'less', 'coffeescript', 'tmux', 'json', 'beta'] 20 | let g:bundle_groups=['python', 'javascript', 'markdown', 'html', 'css', 'tmux', 'beta'] 21 | endif 22 | 23 | " ---------------------------------------------------------------------------- 24 | " 使用 vim-plug 管理插件 25 | " vim plugin bundle control, command model 26 | " ---------------------------------------------------------------------------- 27 | 28 | call plug#begin('~/.vim/bundle') 29 | 30 | " 移动光标到插件名上, 使用'#'快速跳转到每个插件的配置处 31 | 32 | " syntastic 33 | if v:version < 800 34 | Plug 'scrooloose/syntastic' 35 | else 36 | Plug 'w0rp/ale' 37 | endif 38 | 39 | " Group dependencies, vim-snippets depends on ultisnips 40 | " 代码片段快速插入 (snippets中,是代码片段资源,需要学习) 41 | " Snippets are separated from the engine. Add this if you want them: 42 | Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' 43 | 44 | " auto complete 45 | " 代码自动补全 46 | " 迄今为止用到的最好的自动VIM自动补全插件 47 | " 重启 :YcmRestartServer 48 | Plug 'Valloric/YouCompleteMe' 49 | " 自动补全单引号,双引号等 50 | Plug 'Raimondi/delimitMate' 51 | " 自动补全html/xml标签 52 | Plug 'docunext/closetag.vim', { 'for': ['html', 'xml'] } 53 | 54 | " quick edit 55 | " 快速注释 56 | Plug 'scrooloose/nerdcommenter' 57 | 58 | 59 | " 快速加入修改环绕字符 60 | " for repeat -> enhance surround.vim, . to repeat command 61 | Plug 'tpope/vim-repeat' | Plug 'tpope/vim-surround' 62 | " trailingwhitespace 63 | " 快速去行尾空格 [, + ] 64 | Plug 'bronson/vim-trailing-whitespace' 65 | " easyalign 66 | " 快速赋值语句对齐 67 | Plug 'junegunn/vim-easy-align' 68 | 69 | " quick movement 70 | " easymotion 71 | "更高效的移动 [,, + w/fx/h/j/k/l] 72 | Plug 'Lokaltog/vim-easymotion' 73 | 74 | " 更高效的行内移动, f/F/t/T, 才触发 75 | " quickscope 76 | Plug 'unblevable/quick-scope' 77 | 78 | Plug 'vim-scripts/matchit.zip' 79 | " signature 80 | " 显示marks - 方便自己进行标记和跳转 81 | " m[a-zA-Z] add mark 82 | " '[a-zA-Z] go to mark 83 | " m del all marks 84 | " m/ list all marks 85 | " m. add new mark just follow previous mark 86 | Plug 'kshenoy/vim-signature' 87 | 88 | " quick selection and edit 89 | " expandregion 90 | " 选中区块 91 | Plug 'terryma/vim-expand-region' 92 | " 多光标选中编辑 93 | " multiplecursors 94 | Plug 'terryma/vim-multiple-cursors' 95 | 96 | " quick locate file or function 97 | " 文件搜索 98 | " change to https://github.com/ctrlpvim/ctrlp.vim 99 | " ctrlp ctrlpfunky 100 | Plug 'ctrlpvim/ctrlp.vim' | Plug 'tacahiroy/ctrlp-funky' 101 | " ctrlsf 102 | " 类似sublimetext的搜索 103 | " In CtrlSF window: 104 | " 回车/o, 打开 105 | " t 在tab中打开(建议) 106 | " T - Lkie t but focus CtrlSF window instead of opened new tab. 107 | " q - Quit CtrlSF window. 108 | Plug 'dyng/ctrlsf.vim' 109 | " incsearch 110 | " Plug 'haya14busa/incsearch.vim' 111 | " map / (incsearch-forward) 112 | " map ? (incsearch-backward) 113 | " map g/ (incsearch-stay) 114 | 115 | " quick run 116 | " quickrun 117 | Plug 'thinca/vim-quickrun' 118 | 119 | " git 120 | " fugitive 121 | Plug 'tpope/vim-fugitive' 122 | " gitgutter 123 | Plug 'airblade/vim-gitgutter' 124 | 125 | " gundo 126 | " edit history, 可以查看回到某个历史状态 127 | Plug 'sjl/gundo.vim' 128 | 129 | " view 130 | " airline 131 | " 状态栏增强展示 132 | Plug 'vim-airline/vim-airline' 133 | Plug 'vim-airline/vim-airline-themes' 134 | " rainbow_parentheses 135 | " 括号显示增强 136 | Plug 'kien/rainbow_parentheses.vim' 137 | " 主题 solarized 138 | " solarized 139 | Plug 'altercation/vim-colors-solarized' 140 | " molokai 141 | " 主题 molokai 142 | Plug 'tomasr/molokai' 143 | 144 | 145 | " nav 146 | " nerdtree nerdtreetabs 147 | Plug 'scrooloose/nerdtree' | Plug 'jistr/vim-nerdtree-tabs' 148 | " ctrlspace 149 | Plug 'vim-ctrlspace/vim-ctrlspace' 150 | " tagbar 151 | Plug 'majutsushi/tagbar' 152 | 153 | " text object 154 | " 支持自定义文本对象 155 | Plug 'kana/vim-textobj-user' 156 | " 增加行文本对象: l dal yal cil 157 | Plug 'kana/vim-textobj-line' 158 | " 增加文件文本对象: e dae yae cie 159 | Plug 'kana/vim-textobj-entire' 160 | " 增加缩进文本对象: i dai yai cii - 相同缩进属于同一块 161 | Plug 'kana/vim-textobj-indent' 162 | 163 | if count(g:bundle_groups, 'tmux') 164 | " tmux 165 | " For tmux navigator Ctrl-hjkl 166 | Plug 'christoomey/vim-tmux-navigator' 167 | endif 168 | 169 | if count(g:bundle_groups, 'markdown') 170 | Plug 'plasticboy/vim-markdown', {'for': 'md'} 171 | " https://github.com/suan/vim-instant-markdown 172 | " npm -g install instant-markdown-d 173 | " Plug 'suan/vim-instant-markdown' 174 | " let g:instant_markdown_slow = 1 175 | " let g:instant_markdown_autostart = 0 176 | " map :InstantMarkdownPreview 177 | endif 178 | 179 | if count(g:bundle_groups, 'golang') 180 | " 1. vim a.go 181 | " 2. :GoInstallBinaries 182 | " vimgo https://github.com/fatih/vim-go 183 | Plug 'fatih/vim-go', {'for': 'go'} 184 | endif 185 | 186 | 187 | if count(g:bundle_groups, 'python') 188 | " for python.vim syntax highlight 189 | " pythonsyntax 190 | Plug 'hdima/python-syntax' 191 | Plug 'hynek/vim-python-pep8-indent' 192 | Plug 'Glench/Vim-Jinja2-Syntax' 193 | 194 | " isort https://github.com/timothycrosley/isort#readme + https://github.com/fisadev/vim-isort#installation 195 | " pip install isort 196 | Plug 'fisadev/vim-isort' 197 | " Shift-V 上下选中, ctrl + i 规范化 198 | let g:vim_isort_map = '' 199 | endif 200 | 201 | if count(g:bundle_groups, 'php') 202 | " piv 203 | " shift-v可以查看函数手册 / leader-pd生成注释 204 | Plug 'spf13/PIV' 205 | endif 206 | 207 | if count(g:bundle_groups, 'ruby') 208 | Plug 'vim-ruby/vim-ruby' 209 | Plug 'tpope/vim-rails' 210 | " dir / dar 211 | Plug 'nelstrom/vim-textobj-rubyblock' 212 | 213 | " 有bug, 和当前有冲突, 尚未解决, 不要打开 => TODO: solve this problem 214 | " Plug 'tpope/vim-endwise' 215 | endif 216 | 217 | if count(g:bundle_groups, 'javascript') 218 | " javascript 219 | " 注意: syntax这个插件要放前面 220 | Plug 'othree/yajs.vim' | Plug 'pangloss/vim-javascript' 221 | " Plug 'jelera/vim-javascript-syntax' | Plug 'pangloss/vim-javascript' 222 | 223 | " TODO: jquery? for, remove or keep 224 | Plug 'othree/javascript-libraries-syntax.vim' 225 | let g:used_javascript_libs = 'jquery,underscore,backbone' 226 | 227 | " for javascript 自动补全, 配合YCM, 需要安装全局环境的(非nvm中) node.js&npm 228 | " 安装完成后还需要在 bundle/tern_for_vim 下执行 npm install 安装依赖 `cd ~/.vim/bundle/tern_for_vim && npm install` 229 | " see https://github.com/marijnh/tern_for_vim 230 | " Plug 'marijnh/tern_for_vim', {'do': 'npm install'} 231 | endif 232 | 233 | 234 | if count(g:bundle_groups, 'coffeescript') 235 | Plug 'kchmck/vim-coffee-script' 236 | endif 237 | 238 | " if count(g:bundle_groups, 'shell') 239 | " Plug 'Shougo/vimshell.vim' 240 | " endif 241 | 242 | if count(g:bundle_groups, 'json') 243 | " json 244 | Plug 'elzr/vim-json', {'for': 'json'} 245 | endif 246 | 247 | if count(g:bundle_groups, 'css') 248 | " css 249 | " not work in iterm2 which termianl selection is not xterm-256, and it slow 250 | " Plug 'ap/vim-css-color' 251 | 252 | " 这个有坑, see issue https://github.com/wklken/k-vim/issues/49 253 | " Plug 'gorodinskiy/vim-coloresque' 254 | " Plug 'lilydjwg/colorizer' 255 | endif 256 | 257 | if count(g:bundle_groups, 'less') 258 | " ###### vim.less : less 自动更新########## 259 | Plug 'groenewege/vim-less' 260 | " autocmd BufWritePost *.less :!lessc % > %:p:r.css 261 | endif 262 | 263 | if count(g:bundle_groups, 'html') 264 | " ###### emmet HTML complete ######### 265 | " Plug 'mattn/emmet-vim' 266 | endif 267 | 268 | " this is just for beta version 269 | if count(g:bundle_groups, 'beta') 270 | " indent 271 | Plug 'nathanaelkane/vim-indent-guides' 272 | " ig to trigger 273 | let g:indent_guides_start_level = 2 274 | let g:indent_guides_guide_size = 1 275 | let g:indent_guides_auto_colors = 1 276 | " autocmd VimEnter,Colorscheme * :hi IndentGuidesOdd ctermbg=black 277 | " autocmd VimEnter,Colorscheme * :hi IndentGuidesEven ctermbg=black 278 | 279 | " Plug 'robbles/logstash.vim' 280 | " Plug 'ryanoasis/vim-devicons' 281 | " Plug 'ekalinin/dockerfile.vim' 282 | 283 | " Plug 'ConradIrwin/vim-bracketed-paste' 284 | " Plug 'roxma/vim-paste-easy' 285 | 286 | 287 | endif 288 | 289 | 290 | " Add plugins to &runtimepath 291 | call plug#end() 292 | 293 | 294 | " ################### 基础 ###################### 295 | 296 | " syntastic {{{ 297 | if has_key(g:plugs, 'syntastic') 298 | " dependence 299 | " 1. shellcheck `brew install shellcheck` https://github.com/koalaman/shellcheck 300 | 301 | let g:syntastic_error_symbol='>>' 302 | let g:syntastic_warning_symbol='>' 303 | let g:syntastic_check_on_open=1 304 | let g:syntastic_check_on_wq=0 305 | let g:syntastic_enable_highlighting=1 306 | 307 | " checkers 308 | " python 309 | " pip install flake8 310 | let g:syntastic_python_checkers=['flake8', ] " 使用pyflakes,速度比pylint快 311 | let g:syntastic_python_flake8_options='--ignore=E501,E225,E124,E712,E116,E131' 312 | 313 | " javascript 314 | " let g:syntastic_javascript_checkers = ['jsl', 'jshint'] 315 | " let g:syntastic_html_checkers=['tidy', 'jshint'] 316 | " npm install -g eslint eslint-plugin-standard eslint-plugin-promise eslint-config-standard 317 | " npm install -g eslint-plugin-import eslint-plugin-node eslint-plugin-html babel-eslint 318 | let g:syntastic_javascript_checkers = ['eslint'] 319 | 320 | " to see error location list 321 | let g:syntastic_always_populate_loc_list = 1 322 | let g:syntastic_enable_signs = 1 323 | let g:syntastic_auto_loc_list = 0 324 | let g:syntastic_auto_jump = 0 325 | let g:syntastic_loc_list_height = 5 326 | 327 | function! ToggleErrors() 328 | let old_last_winnr = winnr('$') 329 | lclose 330 | if old_last_winnr == winnr('$') 331 | " Nothing was closed, open syntastic_error location panel 332 | Errors 333 | endif 334 | endfunction 335 | nnoremap s :call ToggleErrors() 336 | 337 | " ,en ,ep to jump between errors 338 | function! LocationPrevious() 339 | try 340 | lprev 341 | catch /^Vim\%((\a\+)\)\=:E553/ 342 | llast 343 | endtry 344 | endfunction 345 | 346 | function! LocationNext() 347 | try 348 | lnext 349 | catch /^Vim\%((\a\+)\)\=:E553/ 350 | lfirst 351 | endtry 352 | endfunction 353 | 354 | nnoremap LocationPrevious :exe 'call LocationPrevious()' 355 | nnoremap LocationNext :exe 'call LocationNext()' 356 | nmap ep LocationPrevious 357 | nmap en LocationNext 358 | 359 | " 修改高亮的背景色, 适应主题 360 | highlight SyntasticErrorSign guifg=white guibg=black 361 | 362 | " 禁止插件检查java 363 | " thanks to @marsqing, see https://github.com/wklken/k-vim/issues/164 364 | let g:syntastic_mode_map = {'mode': 'active', 'passive_filetypes': ['java'] } 365 | 366 | " 关闭syntastic语法检查, 鼠标复制代码时用到, 防止把错误标志给复制了 367 | nnoremap ec :SyntasticToggleMode 368 | endif 369 | " }}} 370 | 371 | 372 | " ale {{{ 373 | if has_key(g:plugs, 'ale') 374 | " pip install flake8 375 | " npm install -g eslint eslint-plugin-standard eslint-plugin-promise eslint-config-standard 376 | " npm install -g eslint-plugin-import eslint-plugin-node eslint-plugin-html babel-eslint 377 | let g:ale_linters = { 378 | \ 'python': ['flake8'], 379 | \ 'javascript': ['eslint'], 380 | \} 381 | 382 | let g:ale_python_flake8_options="--ignore=E121,E123,E126,E226,E24,E704,W503 --max-line-length=120" 383 | 384 | let g:ale_sign_error = '>>' 385 | let g:ale_sign_warning = '>' 386 | 387 | let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok'] 388 | let g:ale_echo_msg_error_str = 'E' 389 | let g:ale_echo_msg_warning_str = 'W' 390 | let g:ale_echo_msg_format = '[%linter%] %s [%severity%]' 391 | 392 | nmap ep (ale_previous_wrap) 393 | nmap en (ale_next_wrap) 394 | 395 | nnoremap ec :ALEToggle 396 | 397 | " troggle quickfix list 398 | function! ToggleErrors() 399 | let old_last_winnr = winnr('$') 400 | lclose 401 | if old_last_winnr == winnr('$') 402 | " Nothing was closed, open syntastic_error location panel 403 | lopen 404 | endif 405 | endfunction 406 | nnoremap s :call ToggleErrors() 407 | 408 | let g:ale_set_highlights = 1 409 | highlight clear ALEErrorSign 410 | highlight clear ALEWarningSign 411 | endif 412 | 413 | " }}} 414 | 415 | " ################### 自动补全 ################### 416 | 417 | " YouCompleteMe {{{ 418 | "youcompleteme 默认tab s-tab 和自动补全冲突 419 | "let g:ycm_key_list_select_completion=[''] 420 | let g:ycm_key_list_select_completion = [''] 421 | "let g:ycm_key_list_previous_completion=[''] 422 | let g:ycm_key_list_previous_completion = [''] 423 | let g:ycm_complete_in_comments = 1 "在注释输入中也能补全 424 | let g:ycm_complete_in_strings = 1 "在字符串输入中也能补全 425 | let g:ycm_use_ultisnips_completer = 1 "提示UltiSnips 426 | let g:ycm_collect_identifiers_from_comments_and_strings = 1 "注释和字符串中的文字也会被收入补全 427 | let g:ycm_collect_identifiers_from_tags_files = 1 428 | " 开启语法关键字补全 429 | let g:ycm_seed_identifiers_with_syntax=1 430 | " 回车作为选中 431 | let g:ycm_key_list_stop_completion = [''] 432 | 433 | "let g:ycm_seed_identifiers_with_syntax=1 "语言关键字补全, 不过python关键字都很短,所以,需要的自己打开 434 | 435 | " 跳转到定义处, 分屏打开 436 | let g:ycm_goto_buffer_command = 'horizontal-split' 437 | let g:ycm_register_as_syntastic_checker = 0 438 | " nnoremap jd :YcmCompleter GoToDefinition 439 | nnoremap jd :YcmCompleter GoToDefinitionElseDeclaration 440 | nnoremap gd :YcmCompleter GoToDeclaration 441 | 442 | " 引入,可以补全系统,以及python的第三方包 针对新老版本YCM做了兼容 443 | " old version 444 | if !empty(glob("~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py")) 445 | let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py" 446 | endif 447 | " new version 448 | if !empty(glob("~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py")) 449 | let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py" 450 | endif 451 | " new version 452 | if !empty(glob("~/.vim/bundle/YouCompleteMe/third_party/ycmd/examples/.ycm_extra_conf.py")) 453 | let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/third_party/ycmd/examples/.ycm_extra_conf.py" 454 | endif 455 | 456 | " 直接触发自动补全 insert模式下 457 | " let g:ycm_key_invoke_completion = '' 458 | " 黑名单,不启用 459 | let g:ycm_filetype_blacklist = { 460 | \ 'tagbar' : 1, 461 | \ 'gitcommit' : 1, 462 | \} 463 | " }}} 464 | 465 | 466 | " ultisnips {{{ 467 | let g:UltiSnipsExpandTrigger = "" 468 | let g:UltiSnipsJumpForwardTrigger = "" 469 | let g:UltiSnipsJumpBackwardTrigger = "" 470 | let g:UltiSnipsSnippetDirectories = ['UltiSnips'] 471 | let g:UltiSnipsSnippetsDir = '~/.vim/UltiSnips' 472 | " 定义存放代码片段的文件夹 .vim/UltiSnips下,使用自定义和默认的,将会的到全局,有冲突的会提示 473 | " 进入对应filetype的snippets进行编辑 474 | map us :UltiSnipsEdit 475 | 476 | " ctrl+j/k 进行选择 477 | func! g:JInYCM() 478 | if pumvisible() 479 | return "\" 480 | else 481 | return "\" 482 | endif 483 | endfunction 484 | 485 | func! g:KInYCM() 486 | if pumvisible() 487 | return "\" 488 | else 489 | return "\" 490 | endif 491 | endfunction 492 | inoremap =g:JInYCM() 493 | au BufEnter,BufRead * exec "inoremap " . g:UltiSnipsJumpBackwordTrigger . " =g:KInYCM()" 494 | let g:UltiSnipsJumpBackwordTrigger = "" 495 | " }}} 496 | 497 | 498 | " delimitMate {{{ 499 | " for python docstring ",优化输入 500 | au FileType python let b:delimitMate_nesting_quotes = ['"'] 501 | au FileType php let delimitMate_matchpairs = "(:),[:],{:}" 502 | " 关闭某些类型文件的自动补全 503 | "au FileType mail let b:delimitMate_autoclose = 0 504 | " }}} 505 | 506 | 507 | " closetag {{{ 508 | let g:closetag_html_style=1 509 | " }}} 510 | 511 | " ################### 快速编码 ################### 512 | 513 | " nerdcommenter {{{ 514 | let g:NERDSpaceDelims=1 515 | let g:NERDAltDelims_python = 1 516 | " }}} 517 | 518 | " trailingwhitespace {{{ 519 | map :FixWhitespace 520 | " }}} 521 | 522 | " easyalign {{{ 523 | vmap a (EasyAlign) 524 | nmap a (EasyAlign) 525 | if !exists('g:easy_align_delimiters') 526 | let g:easy_align_delimiters = {} 527 | endif 528 | let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignore_groups': ['String'] } 529 | " Default: 530 | " If a delimiter is in a highlight group whose name matches any of the followings, it will be ignored. 531 | let g:easy_align_ignore_groups = ['Comment', 'String'] 532 | " }}} 533 | 534 | " ################### 快速移动 ################### 535 | 536 | " easymotion {{{ 537 | let g:EasyMotion_smartcase = 1 538 | "let g:EasyMotion_startofline = 0 " keep cursor colum when JK motion 539 | map h (easymotion-linebackward) 540 | map j (easymotion-j) 541 | map k (easymotion-k) 542 | map l (easymotion-lineforward) 543 | " 重复上一次操作, 类似repeat插件, 很强大 544 | map . (easymotion-repeat) 545 | " }}} 546 | 547 | 548 | " quickscope {{{ 549 | let g:qs_highlight_on_keys = ['f', 'F', 't', 'T'] 550 | " macvim/gvim会有问题, 暂时注解 551 | " let g:qs_first_occurrence_highlight_color = '#afff5f' " gui vim 552 | " let g:qs_first_occurrence_highlight_color = 155 " terminal vim 553 | " let g:qs_second_occurrence_highlight_color = '#5fffff' " gui vim 554 | " let g:qs_second_occurrence_highlight_color = 81 " terminal vim 555 | " }}} 556 | 557 | " ################### 快速选中 ################### 558 | 559 | " expandregion {{{ 560 | " map + (expand_region_expand) 561 | " map _ (expand_region_shrink) 562 | vmap v (expand_region_expand) 563 | vmap V (expand_region_shrink) 564 | " Extend the global default 565 | if exists("*expand_region#custom_text_objects") 566 | call expand_region#custom_text_objects({ 567 | \ 'a]' :1, 568 | \ 'ab' :1, 569 | \ 'aB' :1, 570 | \ 'ii' :0, 571 | \ 'ai' :0, 572 | \ }) 573 | endif 574 | 575 | " }}} 576 | 577 | " multiplecursors {{{ 578 | let g:multi_cursor_use_default_mapping=0 579 | " Default mapping 580 | let g:multi_cursor_next_key='' 581 | let g:multi_cursor_prev_key='' 582 | let g:multi_cursor_skip_key='' 583 | let g:multi_cursor_quit_key='' 584 | " }}} 585 | 586 | " ################### 功能相关 ################### 587 | 588 | " ctrlp ctrlpfunky{{{ 589 | let g:ctrlp_map = 'p' 590 | let g:ctrlp_cmd = 'CtrlP' 591 | map f :CtrlPMRU 592 | let g:ctrlp_custom_ignore = { 593 | \ 'dir': '\v[\/]\.(git|hg|svn|rvm)$', 594 | \ 'file': '\v\.(exe|so|dll|zip|tar|tar.gz|pyc)$', 595 | \ } 596 | let g:ctrlp_working_path_mode=0 597 | let g:ctrlp_match_window_bottom=1 598 | let g:ctrlp_max_height=15 599 | let g:ctrlp_match_window_reversed=0 600 | let g:ctrlp_mruf_max=500 601 | let g:ctrlp_follow_symlinks=1 602 | " 如果安装了ag, 使用ag 603 | " if executable('ag') 604 | " " Use ag in CtrlP for listing files. Lightning fast and respects .gitignore 605 | " let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""' 606 | " " ag is fast enough that CtrlP doesn't need to cache 607 | " let g:ctrlp_use_caching = 0 608 | " endif 609 | 610 | " ctrlpfunky 611 | " ctrlp插件1 - 不用ctag进行函数快速跳转 612 | nnoremap fu :CtrlPFunky 613 | " narrow the list down with a word under cursor 614 | nnoremap fU :execute 'CtrlPFunky ' . expand('') 615 | let g:ctrlp_funky_syntax_highlight = 1 616 | 617 | let g:ctrlp_extensions = ['funky'] 618 | " }}} 619 | 620 | 621 | " ctrlsf {{{ 622 | nmap \ CtrlSFCwordPath 623 | " let g:ctrlsf_position = 'below' 624 | " let g:ctrlsf_winsize = '30%' 625 | let g:ctrlsf_auto_close = 0 626 | let g:ctrlsf_confirm_save = 0 627 | " Note: cannot use or for open 628 | " Use : or 629 | let g:ctrlsf_mapping = { 630 | \ "open" : "", 631 | \ "openb" : "O", 632 | \ "tab" : "t", 633 | \ "tabb" : "T", 634 | \ "prevw" : "p", 635 | \ "quit" : "q", 636 | \ "next" : "", 637 | \ "prev" : "", 638 | \ "pquit" : "q", 639 | \ } 640 | " }}} 641 | 642 | " git. git操作还是习惯命令行,vim里面处理简单diff编辑操作 643 | 644 | " fugitive {{{ 645 | " :Gdiff :Gstatus :Gvsplit 646 | nnoremap ge :Gdiff 647 | " not ready to open 648 | " gb maps to :Gblame 649 | " gs maps to :Gstatus 650 | " gd maps to :Gdiff 和现有冲突 651 | " gl maps to :Glog 652 | " gc maps to :Gcommit 653 | " gp maps to :Git push 654 | " }}} 655 | 656 | " gitgutter {{{ 657 | " 同git diff,实时展示文件中修改的行 658 | " 只是不喜欢除了行号多一列, 默认关闭,gs时打开 659 | let g:gitgutter_map_keys = 0 660 | let g:gitgutter_enabled = 0 661 | let g:gitgutter_highlight_lines = 1 662 | nnoremap gs :GitGutterToggle 663 | " }}} 664 | 665 | " gundo {{{ 666 | noremap h :GundoToggle 667 | " }}} 668 | 669 | " ################### 显示增强 ################### 670 | 671 | " airline {{{ 672 | if !exists('g:airline_symbols') 673 | let g:airline_symbols = {} 674 | endif 675 | let g:airline_left_sep = '▶' 676 | let g:airline_left_alt_sep = '❯' 677 | let g:airline_right_sep = '◀' 678 | let g:airline_right_alt_sep = '❮' 679 | let g:airline_symbols.linenr = '¶' 680 | let g:airline_symbols.branch = '⎇' 681 | " 是否打开tabline 682 | " let g:airline#extensions#tabline#enabled = 1 683 | " }}} 684 | 685 | 686 | 687 | " rainbow_parentheses {{{ 688 | " 不加入这行, 防止黑色括号出现, 很难识别 689 | " \ ['black', 'SeaGreen3'], 690 | let g:rbpt_colorpairs = [ 691 | \ ['brown', 'RoyalBlue3'], 692 | \ ['Darkblue', 'SeaGreen3'], 693 | \ ['darkgray', 'DarkOrchid3'], 694 | \ ['darkgreen', 'firebrick3'], 695 | \ ['darkcyan', 'RoyalBlue3'], 696 | \ ['darkred', 'SeaGreen3'], 697 | \ ['darkmagenta', 'DarkOrchid3'], 698 | \ ['brown', 'firebrick3'], 699 | \ ['gray', 'RoyalBlue3'], 700 | \ ['darkmagenta', 'DarkOrchid3'], 701 | \ ['Darkblue', 'firebrick3'], 702 | \ ['darkgreen', 'RoyalBlue3'], 703 | \ ['darkcyan', 'SeaGreen3'], 704 | \ ['darkred', 'DarkOrchid3'], 705 | \ ['red', 'firebrick3'], 706 | \ ] 707 | 708 | let g:rbpt_max = 16 709 | let g:rbpt_loadcmd_toggle = 0 710 | au VimEnter * RainbowParenthesesToggle 711 | au Syntax * RainbowParenthesesLoadRound 712 | au Syntax * RainbowParenthesesLoadSquare 713 | au Syntax * RainbowParenthesesLoadBraces 714 | " }}} 715 | 716 | 717 | " ################### 显示增强-主题 ###################" 718 | 719 | " solarized {{{ 720 | let g:solarized_termtrans=1 721 | let g:solarized_contrast="normal" 722 | let g:solarized_visibility="normal" 723 | " let g:solarized_termcolors=256 724 | " }}} 725 | 726 | " molokai {{{ 727 | " monokai原始背景色 728 | let g:molokai_original = 1 729 | let g:rehash256 = 1 730 | " }}} 731 | 732 | " ################### 快速导航 ################### 733 | 734 | " nerdtree nerdtreetabs {{{ 735 | " map n :NERDTreeToggle 736 | let NERDTreeHighlightCursorline=1 737 | let NERDTreeIgnore=[ '\.pyc$', '\.pyo$', '\.obj$', '\.o$', '\.so$', '\.egg$', '^\.git$', '^\.svn$', '^\.hg$' ] 738 | "close vim if the only window left open is a NERDTree 739 | autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | end 740 | " s/v 分屏打开文件 741 | let g:NERDTreeMapOpenSplit = 's' 742 | let g:NERDTreeMapOpenVSplit = 'v' 743 | " fix Nerdtree ^G before folder and file names OSX terminal vim 744 | let g:NERDTreeNodeDelimiter = "\u00a0" 745 | 746 | 747 | " nerdtreetabs 748 | map n NERDTreeTabsToggle 749 | " 关闭同步 750 | " let g:nerdtree_tabs_synchronize_view=0 751 | " let g:nerdtree_tabs_synchronize_focus=0 752 | " 是否自动开启nerdtree 753 | " thank to @ListenerRi, see https://github.com/wklken/k-vim/issues/165 754 | let g:nerdtree_tabs_open_on_console_startup=0 755 | let g:nerdtree_tabs_open_on_gui_startup=0 756 | " }}} 757 | 758 | 759 | " Vim Workspace Controller 760 | " ctrlspace {{{ 761 | let g:airline_exclude_preview = 1 762 | hi CtrlSpaceSelected guifg=#586e75 guibg=#eee8d5 guisp=#839496 gui=reverse,bold ctermfg=10 ctermbg=7 cterm=reverse,bold 763 | hi CtrlSpaceNormal guifg=#839496 guibg=#021B25 guisp=#839496 gui=NONE ctermfg=12 ctermbg=0 cterm=NONE 764 | hi CtrlSpaceSearch guifg=#cb4b16 guibg=NONE gui=bold ctermfg=9 ctermbg=NONE term=bold cterm=bold 765 | hi CtrlSpaceStatus guifg=#839496 guibg=#002b36 gui=reverse term=reverse cterm=reverse ctermfg=12 ctermbg=8 766 | " }}} 767 | 768 | 769 | " 标签导航 770 | " tagbar {{{ 771 | nmap :TagbarToggle 772 | let g:tagbar_autofocus = 1 773 | " let g:tagbar_autoshowtag = 1 774 | " let g:tagbar_show_visibility = 1 775 | " for ruby 776 | let g:tagbar_type_ruby = { 777 | \ 'kinds' : [ 778 | \ 'm:modules', 779 | \ 'c:classes', 780 | \ 'd:describes', 781 | \ 'C:contexts', 782 | \ 'f:methods', 783 | \ 'F:singleton methods' 784 | \ ] 785 | \ } 786 | 787 | " go语言的tagbar配置 788 | " 1. install gotags 'go get -u github.com/jstemmer/gotags' 789 | " 2. make sure `gotags` in you shell PATH, you can call check it with `which gotags` 790 | " for gotags. work with tagbar 791 | let g:tagbar_type_go = { 792 | \ 'ctagstype' : 'go', 793 | \ 'kinds' : [ 794 | \ 'p:package', 795 | \ 'i:imports:1', 796 | \ 'c:constants', 797 | \ 'v:variables', 798 | \ 't:types', 799 | \ 'n:interfaces', 800 | \ 'w:fields', 801 | \ 'e:embedded', 802 | \ 'm:methods', 803 | \ 'r:constructor', 804 | \ 'f:functions' 805 | \ ], 806 | \ 'sro' : '.', 807 | \ 'kind2scope' : { 808 | \ 't' : 'ctype', 809 | \ 'n' : 'ntype' 810 | \ }, 811 | \ 'scope2kind' : { 812 | \ 'ctype' : 't', 813 | \ 'ntype' : 'n' 814 | \ }, 815 | \ 'ctagsbin' : 'gotags', 816 | \ 'ctagsargs' : '-sort -silent' 817 | \ } 818 | " }}} 819 | 820 | 821 | " ################### 语言相关 ################### 822 | 823 | " quickrun {{{ 824 | let g:quickrun_config = { 825 | \ "_" : { 826 | \ "outputter" : "message", 827 | \ }, 828 | \} 829 | 830 | let g:quickrun_no_default_key_mappings = 1 831 | nmap r (quickrun) 832 | map :QuickRun 833 | " }}} 834 | 835 | 836 | " pythonsyntax {{{ 837 | let python_highlight_all = 1 838 | " }}} 839 | 840 | " piv {{{ 841 | let g:DisableAutoPHPFolding = 1 842 | " }}} 843 | 844 | 845 | " vimgo {{{ 846 | let g:go_highlight_functions = 1 847 | let g:go_highlight_methods = 1 848 | let g:go_highlight_structs = 1 849 | let g:go_highlight_operators = 1 850 | let g:go_highlight_build_constraints = 1 851 | 852 | let g:go_fmt_fail_silently = 1 853 | " format with goimports instead of gofmt 854 | let g:go_fmt_command = "goimports" 855 | let g:syntastic_go_checkers = ['golint', 'govet', 'errcheck'] 856 | let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go', 'java'] } 857 | " }}} 858 | 859 | " markdown {{{ 860 | let g:vim_markdown_folding_disabled=1 861 | " }}} 862 | 863 | 864 | " javascript {{{ 865 | " pangloss/vim-javascript 866 | let g:html_indent_inctags = "html,body,head,tbody" 867 | let g:html_indent_script1 = "inc" 868 | let g:html_indent_style1 = "inc" 869 | " }}} 870 | 871 | " json {{{ 872 | let g:vim_json_syntax_conceal = 0 873 | " }}} 874 | 875 | " css {{{ 876 | " }}} 877 | 878 | 879 | " ####### temp ####### 880 | 881 | " beta {{{ 882 | " pip install yapf 883 | " python code format 884 | " format all file 885 | autocmd FileType python nnoremap y :0,$!yapf 886 | " format select block 887 | autocmd FileType python vnoremap y :!yapf 888 | 889 | " Plug 'posva/vim-vue' 890 | 891 | " Plug 'millermedeiros/vim-esformatter' 892 | " will run esformatter after pressing followed by the 'e' and 's' 893 | " keys 894 | " nnoremap es :Esformatter 895 | " vnoremap es :EsformatterVisual 896 | 897 | " }}} 898 | 899 | "------------------------------------------- end of configs -------------------------------------------- 900 | --------------------------------------------------------------------------------