aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Hanus <hanus.michal@divelit.cz>2024-03-02 18:49:55 +0100
committerMichal Hanus <hanus.michal@divelit.cz>2024-03-02 18:49:55 +0100
commitaab38f32e0a02e43565a554d0a76ff65636499b8 (patch)
treef3f00df05c63228c69a338e80fd0e7d02986e8cf
parent99353a355321d68ef4fb3c26291084b23e8f4978 (diff)
crazyshitHEADmaster
-rw-r--r--_config.yml1
-rw-r--r--after/ftplugin/cpp.vim39
-rw-r--r--after/ftplugin/gitconfig.vim1
-rw-r--r--after/ftplugin/javascript.vim3
-rw-r--r--after/ftplugin/json.vim6
-rw-r--r--after/ftplugin/lua.vim8
-rw-r--r--after/ftplugin/markdown.vim69
-rw-r--r--after/ftplugin/python.vim17
-rw-r--r--after/ftplugin/qf.vim6
-rw-r--r--after/ftplugin/sql.vim1
-rw-r--r--after/ftplugin/tex.lua2
-rw-r--r--after/ftplugin/text.vim1
-rw-r--r--after/ftplugin/toml.vim0
-rw-r--r--after/ftplugin/vim.vim15
-rw-r--r--after/ftplugin/yaml.vim4
-rw-r--r--autoload/buf_utils.vim30
-rw-r--r--autoload/plug.vim2812
-rw-r--r--autoload/text_obj.vim86
-rw-r--r--docs/README.md218
-rw-r--r--docs/nvim_install_mac.sh20
-rw-r--r--docs/nvim_resources.md18
-rwxr-xr-xdocs/nvim_setup_linux.sh258
-rw-r--r--docs/nvim_setup_windows.ps155
-rw-r--r--ftdetect/pdc.vim4
-rw-r--r--ftdetect/snippets.vim4
-rw-r--r--ginit.vim74
-rw-r--r--init.lua48
-rw-r--r--init.vim166
-rw-r--r--lua/config/bqf.lua6
-rw-r--r--lua/config/bufferline.lua46
-rw-r--r--lua/config/dashboard-nvim.lua75
-rw-r--r--lua/config/fidget-nvim.lua1
-rw-r--r--lua/config/fugitive.lua11
-rw-r--r--lua/config/git-linker.lua37
-rw-r--r--lua/config/gitsigns.lua57
-rw-r--r--lua/config/hlslens.lua49
-rw-r--r--lua/config/iron.lua7
-rw-r--r--lua/config/lsp.lua273
-rw-r--r--lua/config/nvim-cmp.lua91
-rw-r--r--lua/config/nvim-notify.lua10
-rw-r--r--lua/config/nvim_hop.lua27
-rw-r--r--lua/config/treesitter.lua8
-rw-r--r--lua/config/which-key.lua60
-rw-r--r--lua/config/yanky.lua13
-rw-r--r--lua/config/zen-mode.lua15
-rw-r--r--lua/globals.lua75
-rw-r--r--lua/utils.lua59
-rw-r--r--my_snippets/all.snippets7
-rw-r--r--my_snippets/cpp.snippets187
-rw-r--r--my_snippets/markdown.snippets168
-rw-r--r--my_snippets/python.snippets30
-rw-r--r--my_snippets/snippets.snippets6
-rw-r--r--my_snippets/tex.snippets9
-rw-r--r--my_snippets/vim.snippets14
m---------plugged/goyo.vim0
m---------plugged/nerdtree0
m---------plugged/vim-airline0
m---------plugged/vim-commentary0
m---------plugged/vim-css-color0
m---------plugged/vim-surround0
m---------plugged/vimagit0
m---------plugged/vimwiki0
-rw-r--r--plugin/abbrev.vim3
-rw-r--r--plugin/command.vim50
-rw-r--r--plugin/log-autocmds.vim119
-rw-r--r--resources/head.tex78
-rw-r--r--spell/en.utf-8.add497
67 files changed, 3006 insertions, 3048 deletions
diff --git a/_config.yml b/_config.yml
deleted file mode 100644
index 9da9a02..0000000
--- a/_config.yml
+++ /dev/null
@@ -1 +0,0 @@
-theme: jekyll-theme-dinky \ No newline at end of file
diff --git a/after/ftplugin/cpp.vim b/after/ftplugin/cpp.vim
deleted file mode 100644
index a8f76f3..0000000
--- a/after/ftplugin/cpp.vim
+++ /dev/null
@@ -1,39 +0,0 @@
-set commentstring=//\ %s
-
-" Disable inserting comment leader after hitting o or O or <Enter>
-set formatoptions-=o
-set formatoptions-=r
-
-nnoremap <silent> <buffer> <F9> :call <SID>compile_run_cpp()<CR>
-
-function! s:compile_run_cpp() abort
- let src_path = expand('%:p:~')
- let src_noext = expand('%:p:~:r')
- " The building flags
- let _flag = '-Wall -Wextra -std=c++11 -O2'
-
- if executable('clang++')
- let prog = 'clang++'
- elseif executable('g++')
- let prog = 'g++'
- else
- echoerr 'No C++ compiler found on the system!'
- endif
- call s:create_term_buf('h', 20)
- execute printf('term %s %s %s -o %s && %s', prog, _flag, src_path, src_noext, src_noext)
- startinsert
-endfunction
-
-function s:create_term_buf(_type, size) abort
- set splitbelow
- set splitright
- if a:_type ==# 'v'
- vnew
- else
- new
- endif
- execute 'resize ' . a:size
-endfunction
-
-" For delimitMate
-let b:delimitMate_matchpairs = "(:),[:],{:}"
diff --git a/after/ftplugin/gitconfig.vim b/after/ftplugin/gitconfig.vim
deleted file mode 100644
index 9c2e80a..0000000
--- a/after/ftplugin/gitconfig.vim
+++ /dev/null
@@ -1 +0,0 @@
-set commentstring=#\ %s
diff --git a/after/ftplugin/javascript.vim b/after/ftplugin/javascript.vim
deleted file mode 100644
index 3e27ee8..0000000
--- a/after/ftplugin/javascript.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-" Disable inserting comment leader after hitting o or O or <Enter>
-set formatoptions-=o
-set formatoptions-=r
diff --git a/after/ftplugin/json.vim b/after/ftplugin/json.vim
deleted file mode 100644
index 90db3ec..0000000
--- a/after/ftplugin/json.vim
+++ /dev/null
@@ -1,6 +0,0 @@
-" let the initial folding state be that all folds are closed.
-set foldlevel=0
-
-" Use nvim-treesitter for folding
-set foldmethod=expr
-set foldexpr=nvim_treesitter#foldexpr()
diff --git a/after/ftplugin/lua.vim b/after/ftplugin/lua.vim
deleted file mode 100644
index 73b1a8f..0000000
--- a/after/ftplugin/lua.vim
+++ /dev/null
@@ -1,8 +0,0 @@
-" Disable inserting comment leader after hitting o or O or <Enter>
-set formatoptions-=o
-set formatoptions-=r
-
-nnoremap <buffer><silent> <F9> :luafile %<CR>
-
-" For delimitMate
-let b:delimitMate_matchpairs = "(:),[:],{:}"
diff --git a/after/ftplugin/markdown.vim b/after/ftplugin/markdown.vim
deleted file mode 100644
index efea5e5..0000000
--- a/after/ftplugin/markdown.vim
+++ /dev/null
@@ -1,69 +0,0 @@
-set concealcursor=c
-set synmaxcol=3000 " For long Chinese paragraphs
-
-set wrap
-
-" Fix minor issue with footnote, see https://github.com/vim-pandoc/vim-markdownfootnotes/issues/22
-if exists(':FootnoteNumber')
- nnoremap <buffer><silent> ^^ :<C-U>call markdownfootnotes#VimFootnotes('i')<CR>
- inoremap <buffer><silent> ^^ <C-O>:<C-U>call markdownfootnotes#VimFootnotes('i')<CR>
- imap <buffer> <silent> @@ <Plug>ReturnFromFootnote
- nmap <buffer> <silent> @@ <Plug>ReturnFromFootnote
-endif
-
-" Text objects for Markdown code blocks.
-xnoremap <buffer><silent> ic :<C-U>call text_obj#MdCodeBlock('i')<CR>
-xnoremap <buffer><silent> ac :<C-U>call text_obj#MdCodeBlock('a')<CR>
-onoremap <buffer><silent> ic :<C-U>call text_obj#MdCodeBlock('i')<CR>
-onoremap <buffer><silent> ac :<C-U>call text_obj#MdCodeBlock('a')<CR>
-
-" Use + to turn several lines to an unordered list.
-" Ref: https://vi.stackexchange.com/q/5495/15292 and https://stackoverflow.com/q/42438795/6064933.
-nnoremap <buffer><silent> + :set operatorfunc=AddListSymbol<CR>g@
-xnoremap <buffer><silent> + :<C-U> call AddListSymbol(visualmode(), 1)<CR>
-
-function! AddListSymbol(type, ...) abort
- if a:0
- let line_start = line("'<")
- let line_end = line("'>")
- else
- let line_start = line("'[")
- let line_end = line("']")
- endif
-
- " add list symbol to each line
- for line in range(line_start, line_end)
- let text = getline(line)
-
- let l:end = matchend(text, '^\s*')
- if l:end == 0
- let new_text = '+ ' . text
- else
- let new_text = text[0 : l:end-1] . ' + ' . text[l:end :]
- endif
-
- call setline(line, new_text)
- endfor
-endfunction
-
-" Add hard line breaks for Markdown
-nnoremap <buffer><silent> \ :set operatorfunc=AddLineBreak<CR>g@
-xnoremap <buffer><silent> \ :<C-U> call AddLineBreak(visualmode(), 1)<CR>
-
-function! AddLineBreak(type, ...) abort
- if a:0
- let line_start = line("'<")
- let line_end = line("'>")
- else
- let line_start = line("'[")
- let line_end = line("']")
- endif
-
- for line in range(line_start, line_end)
- let text = getline(line)
- " add backslash to each line
- let new_text = text . "\\"
-
- call setline(line, new_text)
- endfor
-endfunction
diff --git a/after/ftplugin/python.vim b/after/ftplugin/python.vim
deleted file mode 100644
index 185aa6e..0000000
--- a/after/ftplugin/python.vim
+++ /dev/null
@@ -1,17 +0,0 @@
-if exists(':AsyncRun')
- nnoremap <buffer><silent> <F9> :<C-U>AsyncRun python -u "%"<CR>
-endif
-
-" Do not wrap Python source code.
-set nowrap
-set sidescroll=5
-set sidescrolloff=2
-set colorcolumn=100
-
-set tabstop=4 " number of visual spaces per TAB
-set softtabstop=4 " number of spaces in tab when editing
-set shiftwidth=4 " number of spaces to use for autoindent
-set expandtab " expand tab to spaces so that tabs are spaces
-
-" For delimitMate
-let b:delimitMate_matchpairs = "(:),[:],{:}"
diff --git a/after/ftplugin/qf.vim b/after/ftplugin/qf.vim
deleted file mode 100644
index 89b4c1f..0000000
--- a/after/ftplugin/qf.vim
+++ /dev/null
@@ -1,6 +0,0 @@
-" Set quickfix window height, see also https://github.com/lervag/vimtex/issues/1127
-function! AdjustWindowHeight(minheight, maxheight)
- execute max([a:minheight, min([line('$'), a:maxheight])]) . 'wincmd _'
-endfunction
-
-call AdjustWindowHeight(5, 15)
diff --git a/after/ftplugin/sql.vim b/after/ftplugin/sql.vim
deleted file mode 100644
index 8c0d563..0000000
--- a/after/ftplugin/sql.vim
+++ /dev/null
@@ -1 +0,0 @@
-set commentstring=--\ %s
diff --git a/after/ftplugin/tex.lua b/after/ftplugin/tex.lua
deleted file mode 100644
index a11226a..0000000
--- a/after/ftplugin/tex.lua
+++ /dev/null
@@ -1,2 +0,0 @@
-vim.o.textwidth = 120
-vim.o.wrap = true
diff --git a/after/ftplugin/text.vim b/after/ftplugin/text.vim
deleted file mode 100644
index 0dfe4de..0000000
--- a/after/ftplugin/text.vim
+++ /dev/null
@@ -1 +0,0 @@
-set colorcolumn=
diff --git a/after/ftplugin/toml.vim b/after/ftplugin/toml.vim
deleted file mode 100644
index e69de29..0000000
--- a/after/ftplugin/toml.vim
+++ /dev/null
diff --git a/after/ftplugin/vim.vim b/after/ftplugin/vim.vim
deleted file mode 100644
index 17dcedb..0000000
--- a/after/ftplugin/vim.vim
+++ /dev/null
@@ -1,15 +0,0 @@
-" Disable inserting comment leader after hitting o or O or <Enter>
-set formatoptions-=o
-set formatoptions-=r
-
-" Set the folding related options for vim script. Setting folding option in
-" modeline is annoying in that the modeline get executed each time the window
-" focus is lost (see
-" https://github.com/tmux-plugins/vim-tmux-focus-events/issues/14)
-set foldmethod=expr foldexpr=utils#VimFolds(v:lnum) foldtext=utils#MyFoldText()
-
-" Use :help command for keyword when pressing `K` in vim file,
-" see `:h K` and https://stackoverflow.com/q/15867323/6064933
-set keywordprg=:help
-
-nnoremap <buffer><silent> <F9> :source %<CR>
diff --git a/after/ftplugin/yaml.vim b/after/ftplugin/yaml.vim
deleted file mode 100644
index ad695d7..0000000
--- a/after/ftplugin/yaml.vim
+++ /dev/null
@@ -1,4 +0,0 @@
-" Turn off syntax highlighting for large YAML files.
-if line('$') > 500
- setlocal syntax=OFF
-endif
diff --git a/autoload/buf_utils.vim b/autoload/buf_utils.vim
deleted file mode 100644
index 4af0ba6..0000000
--- a/autoload/buf_utils.vim
+++ /dev/null
@@ -1,30 +0,0 @@
-function! buf_utils#GoToBuffer(count, direction) abort
- if a:count == 0
- if a:direction ==# 'forward'
- bnext
- elseif a:direction ==# 'backward'
- bprevious
- else
- echoerr 'Bad argument ' a:direction
- endif
- return
- endif
- " Check the validity of buffer number.
- if index(s:GetBufNums(), a:count) == -1
- " Using `lua vim.notify('invalid bufnr: ' .. a:count)` won't work, because
- " we are essentially mixing Lua and vim script. We need to make sure that
- " args inside vim.notify() are valid vim values. The conversion from vim
- " value to lua value will be done by Nvim. See also https://github.com/neovim/neovim/pull/11338.
- call v:lua.vim.notify('Invalid bufnr: ' . a:count, 4, {'title': 'nvim-config'})
- return
- endif
-
- " Do not use {count} for gB (it is less useful)
- if a:direction ==# 'forward'
- silent execute('buffer' . a:count)
- endif
-endfunction
-
-function! s:GetBufNums() abort
- return map(copy(getbufinfo({'buflisted':1})), 'v:val.bufnr')
-endfunction
diff --git a/autoload/plug.vim b/autoload/plug.vim
new file mode 100644
index 0000000..9c3011f
--- /dev/null
+++ b/autoload/plug.vim
@@ -0,0 +1,2812 @@
+" vim-plug: Vim plugin manager
+" ============================
+"
+" Download plug.vim and put it in ~/.vim/autoload
+"
+" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
+" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+"
+" Edit your .vimrc
+"
+" call plug#begin('~/.vim/plugged')
+"
+" " Make sure you use single quotes
+"
+" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
+" Plug 'junegunn/vim-easy-align'
+"
+" " Any valid git URL is allowed
+" Plug 'https://github.com/junegunn/vim-github-dashboard.git'
+"
+" " Multiple Plug commands can be written in a single line using | separators
+" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
+"
+" " On-demand loading
+" Plug 'preservim/nerdtree', { 'on': 'NERDTreeToggle' }
+" Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
+"
+" " Using a non-default branch
+" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
+"
+" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
+" Plug 'fatih/vim-go', { 'tag': '*' }
+"
+" " Plugin options
+" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }
+"
+" " Plugin outside ~/.vim/plugged with post-update hook
+" Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
+"
+" " Unmanaged plugin (manually installed and updated)
+" Plug '~/my-prototype-plugin'
+"
+" " Initialize plugin system
+" call plug#end()
+"
+" Then reload .vimrc and :PlugInstall to install plugins.
+"
+" Plug options:
+"
+"| Option | Description |
+"| ----------------------- | ------------------------------------------------ |
+"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use |
+"| `rtp` | Subdirectory that contains Vim plugin |
+"| `dir` | Custom directory for the plugin |
+"| `as` | Use different name for the plugin |
+"| `do` | Post-update hook (string or funcref) |
+"| `on` | On-demand loading: Commands or `<Plug>`-mappings |
+"| `for` | On-demand loading: File types |
+"| `frozen` | Do not update unless explicitly specified |
+"
+" More information: https://github.com/junegunn/vim-plug
+"
+"
+" Copyright (c) 2017 Junegunn Choi
+"
+" MIT License
+"
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be
+" included in all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if exists('g:loaded_plug')
+ finish
+endif
+let g:loaded_plug = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let s:plug_src = 'https://github.com/junegunn/vim-plug.git'
+let s:plug_tab = get(s:, 'plug_tab', -1)
+let s:plug_buf = get(s:, 'plug_buf', -1)
+let s:mac_gui = has('gui_macvim') && has('gui_running')
+let s:is_win = has('win32')
+let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
+let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
+if s:is_win && &shellslash
+ set noshellslash
+ let s:me = resolve(expand('<sfile>:p'))
+ set shellslash
+else
+ let s:me = resolve(expand('<sfile>:p'))
+endif
+let s:base_spec = { 'branch': '', 'frozen': 0 }
+let s:TYPE = {
+\ 'string': type(''),
+\ 'list': type([]),
+\ 'dict': type({}),
+\ 'funcref': type(function('call'))
+\ }
+let s:loaded = get(s:, 'loaded', {})
+let s:triggers = get(s:, 'triggers', {})
+
+function! s:is_powershell(shell)
+ return a:shell =~# 'powershell\(\.exe\)\?$' || a:shell =~# 'pwsh\(\.exe\)\?$'
+endfunction
+
+function! s:isabsolute(dir) abort
+ return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
+endfunction
+
+function! s:git_dir(dir) abort
+ let gitdir = s:trim(a:dir) . '/.git'
+ if isdirectory(gitdir)
+ return gitdir
+ endif
+ if !filereadable(gitdir)
+ return ''
+ endif
+ let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
+ if len(gitdir) && !s:isabsolute(gitdir)
+ let gitdir = a:dir . '/' . gitdir
+ endif
+ return isdirectory(gitdir) ? gitdir : ''
+endfunction
+
+function! s:git_origin_url(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let config = gitdir . '/config'
+ if empty(gitdir) || !filereadable(config)
+ return ''
+ endif
+ return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
+endfunction
+
+function! s:git_revision(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+
+ let line = get(readfile(head), 0, '')
+ let ref = matchstr(line, '^ref: \zs.*')
+ if empty(ref)
+ return line
+ endif
+
+ if filereadable(gitdir . '/' . ref)
+ return get(readfile(gitdir . '/' . ref), 0, '')
+ endif
+
+ if filereadable(gitdir . '/packed-refs')
+ for line in readfile(gitdir . '/packed-refs')
+ if line =~# ' ' . ref
+ return matchstr(line, '^[0-9a-f]*')
+ endif
+ endfor
+ endif
+
+ return ''
+endfunction
+
+function! s:git_local_branch(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+ let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
+ return len(branch) ? branch : 'HEAD'
+endfunction
+
+function! s:git_origin_branch(spec)
+ if len(a:spec.branch)
+ return a:spec.branch
+ endif
+
+ " The file may not be present if this is a local repository
+ let gitdir = s:git_dir(a:spec.dir)
+ let origin_head = gitdir.'/refs/remotes/origin/HEAD'
+ if len(gitdir) && filereadable(origin_head)
+ return matchstr(get(readfile(origin_head), 0, ''),
+ \ '^ref: refs/remotes/origin/\zs.*')
+ endif
+
+ " The command may not return the name of a branch in detached HEAD state
+ let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
+ return v:shell_error ? '' : result[-1]
+endfunction
+
+if s:is_win
+ function! s:plug_call(fn, ...)
+ let shellslash = &shellslash
+ try
+ set noshellslash
+ return call(a:fn, a:000)
+ finally
+ let &shellslash = shellslash
+ endtry
+ endfunction
+else
+ function! s:plug_call(fn, ...)
+ return call(a:fn, a:000)
+ endfunction
+endif
+
+function! s:plug_getcwd()
+ return s:plug_call('getcwd')
+endfunction
+
+function! s:plug_fnamemodify(fname, mods)
+ return s:plug_call('fnamemodify', a:fname, a:mods)
+endfunction
+
+function! s:plug_expand(fmt)
+ return s:plug_call('expand', a:fmt, 1)
+endfunction
+
+function! s:plug_tempname()
+ return s:plug_call('tempname')
+endfunction
+
+function! plug#begin(...)
+ if a:0 > 0
+ let s:plug_home_org = a:1
+ let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p'))
+ elseif exists('g:plug_home')
+ let home = s:path(g:plug_home)
+ elseif has('nvim')
+ let home = stdpath('data') . '/plugged'
+ elseif !empty(&rtp)
+ let home = s:path(split(&rtp, ',')[0]) . '/plugged'
+ else
+ return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
+ endif
+ if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp
+ return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')
+ endif
+
+ let g:plug_home = home
+ let g:plugs = {}
+ let g:plugs_order = []
+ let s:triggers = {}
+
+ call s:define_commands()
+ return 1
+endfunction
+
+function! s:define_commands()
+ command! -nargs=+ -bar Plug call plug#(<args>)
+ if !executable('git')
+ return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')
+ endif
+ if has('win32')
+ \ && &shellslash
+ \ && (&shell =~# 'cmd\(\.exe\)\?$' || s:is_powershell(&shell))
+ return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')
+ endif
+ if !has('nvim')
+ \ && (has('win32') || has('win32unix'))
+ \ && !has('multi_byte')
+ return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.')
+ endif
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>])
+ command! -nargs=0 -bar -bang PlugClean call s:clean(<bang>0)
+ command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif
+ command! -nargs=0 -bar PlugStatus call s:status()
+ command! -nargs=0 -bar PlugDiff call s:diff()
+ command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(<bang>0, <f-args>)
+endfunction
+
+function! s:to_a(v)
+ return type(a:v) == s:TYPE.list ? a:v : [a:v]
+endfunction
+
+function! s:to_s(v)
+ return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
+endfunction
+
+function! s:glob(from, pattern)
+ return s:lines(globpath(a:from, a:pattern))
+endfunction
+
+function! s:source(from, ...)
+ let found = 0
+ for pattern in a:000
+ for vim in s:glob(a:from, pattern)
+ execute 'source' s:esc(vim)
+ let found = 1
+ endfor
+ endfor
+ return found
+endfunction
+
+function! s:assoc(dict, key, val)
+ let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)
+endfunction
+
+function! s:ask(message, ...)
+ call inputsave()
+ echohl WarningMsg
+ let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) '))
+ echohl None
+ call inputrestore()
+ echo "\r"
+ return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0
+endfunction
+
+function! s:ask_no_interrupt(...)
+ try
+ return call('s:ask', a:000)
+ catch
+ return 0
+ endtry
+endfunction
+
+function! s:lazy(plug, opt)
+ return has_key(a:plug, a:opt) &&
+ \ (empty(s:to_a(a:plug[a:opt])) ||
+ \ !isdirectory(a:plug.dir) ||
+ \ len(s:glob(s:rtp(a:plug), 'plugin')) ||
+ \ len(s:glob(s:rtp(a:plug), 'after/plugin')))
+endfunction
+
+function! plug#end()
+ if !exists('g:plugs')
+ return s:err('plug#end() called without calling plug#begin() first')
+ endif
+
+ if exists('#PlugLOD')
+ augroup PlugLOD
+ autocmd!
+ augroup END
+ augroup! PlugLOD
+ endif
+ let lod = { 'ft': {}, 'map': {}, 'cmd': {} }
+
+ if get(g:, 'did_load_filetypes', 0)
+ filetype off
+ endif
+ for name in g:plugs_order
+ if !has_key(g:plugs, name)
+ continue
+ endif
+ let plug = g:plugs[name]
+ if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for')
+ let s:loaded[name] = 1
+ continue
+ endif
+
+ if has_key(plug, 'on')
+ let s:triggers[name] = { 'map': [], 'cmd': [] }
+ for cmd in s:to_a(plug.on)
+ if cmd =~? '^<Plug>.\+'
+ if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
+ call s:assoc(lod.map, cmd, name)
+ endif
+ call add(s:triggers[name].map, cmd)
+ elseif cmd =~# '^[A-Z]'
+ let cmd = substitute(cmd, '!*$', '', '')
+ if exists(':'.cmd) != 2
+ call s:assoc(lod.cmd, cmd, name)
+ endif
+ call add(s:triggers[name].cmd, cmd)
+ else
+ call s:err('Invalid `on` option: '.cmd.
+ \ '. Should start with an uppercase letter or `<Plug>`.')
+ endif
+ endfor
+ endif
+
+ if has_key(plug, 'for')
+ let types = s:to_a(plug.for)
+ if !empty(types)
+ augroup filetypedetect
+ call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
+ augroup END
+ endif
+ for type in types
+ call s:assoc(lod.ft, type, name)
+ endfor
+ endif
+ endfor
+
+ for [cmd, names] in items(lod.cmd)
+ execute printf(
+ \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
+ \ cmd, string(cmd), string(names))
+ endfor
+
+ for [map, names] in items(lod.map)
+ for [mode, map_prefix, key_prefix] in
+ \ [['i', '<C-\><C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
+ execute printf(
+ \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, %s, "%s")<CR>',
+ \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix)
+ endfor
+ endfor
+
+ for [ft, names] in items(lod.ft)
+ augroup PlugLOD
+ execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
+ \ ft, string(ft), string(names))
+ augroup END
+ endfor
+
+ call s:reorg_rtp()
+ filetype plugin indent on
+ if has('vim_starting')
+ if has('syntax') && !exists('g:syntax_on')
+ syntax enable
+ end
+ else
+ call s:reload_plugins()
+ endif
+endfunction
+
+function! s:loaded_names()
+ return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')
+endfunction
+
+function! s:load_plugin(spec)
+ call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim')
+endfunction
+
+function! s:reload_plugins()
+ for name in s:loaded_names()
+ call s:load_plugin(g:plugs[name])
+ endfor
+endfunction
+
+function! s:trim(str)
+ return substitute(a:str, '[\/]\+$', '', '')
+endfunction
+
+function! s:version_requirement(val, min)
+ for idx in range(0, len(a:min) - 1)
+ let v = get(a:val, idx, 0)
+ if v < a:min[idx] | return 0
+ elseif v > a:min[idx] | return 1
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:git_version_requirement(...)
+ if !exists('s:git_version')
+ let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')
+ endif
+ return s:version_requirement(s:git_version, a:000)
+endfunction
+
+function! s:progress_opt(base)
+ return a:base && !s:is_win &&
+ \ s:git_version_requirement(1, 7, 1) ? '--progress' : ''
+endfunction
+
+function! s:rtp(spec)
+ return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
+endfunction
+
+if s:is_win
+ function! s:path(path)
+ return s:trim(substitute(a:path, '/', '\', 'g'))
+ endfunction
+
+ function! s:dirpath(path)
+ return s:path(a:path) . '\'
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo =~? '^[a-z]:\|^[%~]'
+ endfunction
+
+ " Copied from fzf
+ function! s:wrap_cmds(cmds)
+ let cmds = [
+ \ '@echo off',
+ \ 'setlocal enabledelayedexpansion']
+ \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds])
+ \ + ['endlocal']
+ if has('iconv')
+ if !exists('s:codepage')
+ let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0)
+ endif
+ return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage))
+ endif
+ return map(cmds, 'v:val."\r"')
+ endfunction
+
+ function! s:batchfile(cmd)
+ let batchfile = s:plug_tempname().'.bat'
+ call writefile(s:wrap_cmds(a:cmd), batchfile)
+ let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ return [batchfile, cmd]
+ endfunction
+else
+ function! s:path(path)
+ return s:trim(a:path)
+ endfunction
+
+ function! s:dirpath(path)
+ return substitute(a:path, '[/\\]*$', '/', '')
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo[0] =~ '[/$~]'
+ endfunction
+endif
+
+function! s:err(msg)
+ echohl ErrorMsg
+ echom '[vim-plug] '.a:msg
+ echohl None
+endfunction
+
+function! s:warn(cmd, msg)
+ echohl WarningMsg
+ execute a:cmd 'a:msg'
+ echohl None
+endfunction
+
+function! s:esc(path)
+ return escape(a:path, ' ')
+endfunction
+
+function! s:escrtp(path)
+ return escape(a:path, ' ,')
+endfunction
+
+function! s:remove_rtp()
+ for name in s:loaded_names()
+ let rtp = s:rtp(g:plugs[name])
+ execute 'set rtp-='.s:escrtp(rtp)
+ let after = globpath(rtp, 'after')
+ if isdirectory(after)
+ execute 'set rtp-='.s:escrtp(after)
+ endif
+ endfor
+endfunction
+
+function! s:reorg_rtp()
+ if !empty(s:first_rtp)
+ execute 'set rtp-='.s:first_rtp
+ execute 'set rtp-='.s:last_rtp
+ endif
+
+ " &rtp is modified from outside
+ if exists('s:prtp') && s:prtp !=# &rtp
+ call s:remove_rtp()
+ unlet! s:middle
+ endif
+
+ let s:middle = get(s:, 'middle', &rtp)
+ let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
+ let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)')
+ let rtp = join(map(rtps, 'escape(v:val, ",")'), ',')
+ \ . ','.s:middle.','
+ \ . join(map(afters, 'escape(v:val, ",")'), ',')
+ let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
+ let s:prtp = &rtp
+
+ if !empty(s:first_rtp)
+ execute 'set rtp^='.s:first_rtp
+ execute 'set rtp+='.s:last_rtp
+ endif
+endfunction
+
+function! s:doautocmd(...)
+ if exists('#'.join(a:000, '#'))
+ execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
+ endif
+endfunction
+
+function! s:dobufread(names)
+ for name in a:names
+ let path = s:rtp(g:plugs[name])
+ for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin']
+ if len(finddir(dir, path))
+ if exists('#BufRead')
+ doautocmd BufRead
+ endif
+ return
+ endif
+ endfor
+ endfor
+endfunction
+
+function! plug#load(...)
+ if a:0 == 0
+ return s:err('Argument missing: plugin name(s) required')
+ endif
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000
+ let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')
+ if !empty(unknowns)
+ let s = len(unknowns) > 1 ? 's' : ''
+ return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
+ end
+ let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')
+ if !empty(unloaded)
+ for name in unloaded
+ call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ endfor
+ call s:dobufread(unloaded)
+ return 1
+ end
+ return 0
+endfunction
+
+function! s:remove_triggers(name)
+ if !has_key(s:triggers, a:name)
+ return
+ endif
+ for cmd in s:triggers[a:name].cmd
+ execute 'silent! delc' cmd
+ endfor
+ for map in s:triggers[a:name].map
+ execute 'silent! unmap' map
+ execute 'silent! iunmap' map
+ endfor
+ call remove(s:triggers, a:name)
+endfunction
+
+function! s:lod(names, types, ...)
+ for name in a:names
+ call s:remove_triggers(name)
+ let s:loaded[name] = 1
+ endfor
+ call s:reorg_rtp()
+
+ for name in a:names
+ let rtp = s:rtp(g:plugs[name])
+ for dir in a:types
+ call s:source(rtp, dir.'/**/*.vim')
+ endfor
+ if a:0
+ if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))
+ execute 'runtime' a:1
+ endif
+ call s:source(rtp, a:2)
+ endif
+ call s:doautocmd('User', name)
+ endfor
+endfunction
+
+function! s:lod_ft(pat, names)
+ let syn = 'syntax/'.a:pat.'.vim'
+ call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
+ execute 'autocmd! PlugLOD FileType' a:pat
+ call s:doautocmd('filetypeplugin', 'FileType')
+ call s:doautocmd('filetypeindent', 'FileType')
+endfunction
+
+function! s:lod_cmd(cmd, bang, l1, l2, args, names)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
+endfunction
+
+function! s:lod_map(map, names, with_prefix, prefix)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ let extra = ''
+ while 1
+ let c = getchar(0)
+ if c == 0
+ break
+ endif
+ let extra .= nr2char(c)
+ endwhile
+
+ if a:with_prefix
+ let prefix = v:count ? v:count : ''
+ let prefix .= '"'.v:register.a:prefix
+ if mode(1) == 'no'
+ if v:operator == 'c'
+ let prefix = "\<esc>" . prefix
+ endif
+ let prefix .= v:operator
+ endif
+ call feedkeys(prefix, 'n')
+ endif
+ call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
+endfunction
+
+function! plug#(repo, ...)
+ if a:0 > 1
+ return s:err('Invalid number of arguments (1..2)')
+ endif
+
+ try
+ let repo = s:trim(a:repo)
+ let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec
+ let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??'))
+ let spec = extend(s:infer_properties(name, repo), opts)
+ if !has_key(g:plugs, name)
+ call add(g:plugs_order, name)
+ endif
+ let g:plugs[name] = spec
+ let s:loaded[name] = get(s:loaded, name, 0)
+ catch
+ return s:err(repo . ' ' . v:exception)
+ endtry
+endfunction
+
+function! s:parse_options(arg)
+ let opts = copy(s:base_spec)
+ let type = type(a:arg)
+ let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)'
+ if type == s:TYPE.string
+ if empty(a:arg)
+ throw printf(opt_errfmt, 'tag', 'string')
+ endif
+ let opts.tag = a:arg
+ elseif type == s:TYPE.dict
+ for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
+ if has_key(a:arg, opt)
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string')
+ endif
+ endfor
+ for opt in ['on', 'for']
+ if has_key(a:arg, opt)
+ \ && type(a:arg[opt]) != s:TYPE.list
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string or list')
+ endif
+ endfor
+ if has_key(a:arg, 'do')
+ \ && type(a:arg.do) != s:TYPE.funcref
+ \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
+ throw printf(opt_errfmt, 'do', 'string or funcref')
+ endif
+ call extend(opts, a:arg)
+ if has_key(opts, 'dir')
+ let opts.dir = s:dirpath(s:plug_expand(opts.dir))
+ endif
+ else
+ throw 'Invalid argument type (expected: string or dictionary)'
+ endif
+ return opts
+endfunction
+
+function! s:infer_properties(name, repo)
+ let repo = a:repo
+ if s:is_local_plug(repo)
+ return { 'dir': s:dirpath(s:plug_expand(repo)) }
+ else
+ if repo =~ ':'
+ let uri = repo
+ else
+ if repo !~ '/'
+ throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)
+ endif
+ let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
+ let uri = printf(fmt, repo)
+ endif
+ return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri }
+ endif
+endfunction
+
+function! s:install(force, names)
+ call s:update_impl(0, a:force, a:names)
+endfunction
+
+function! s:update(force, names)
+ call s:update_impl(1, a:force, a:names)
+endfunction
+
+function! plug#helptags()
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ for spec in values(g:plugs)
+ let docd = join([s:rtp(spec), 'doc'], '/')
+ if isdirectory(docd)
+ silent! execute 'helptags' s:esc(docd)
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:syntax()
+ syntax clear
+ syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber
+ syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX
+ syn match plugNumber /[0-9]\+[0-9.]*/ contained
+ syn match plugBracket /[[\]]/ contained
+ syn match plugX /x/ contained
+ syn match plugDash /^-\{1}\ /
+ syn match plugPlus /^+/
+ syn match plugStar /^*/
+ syn match plugMessage /\(^- \)\@<=.*/
+ syn match plugName /\(^- \)\@<=[^ ]*:/
+ syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/
+ syn match plugTag /(tag: [^)]\+)/
+ syn match plugInstall /\(^+ \)\@<=[^:]*/
+ syn match plugUpdate /\(^* \)\@<=[^:]*/
+ syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag
+ syn match plugEdge /^ \X\+$/
+ syn match plugEdge /^ \X*/ contained nextgroup=plugSha
+ syn match plugSha /[0-9a-f]\{7,9}/ contained
+ syn match plugRelDate /([^)]*)$/ contained
+ syn match plugNotLoaded /(not loaded)$/
+ syn match plugError /^x.*/
+ syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/
+ syn match plugH2 /^.*:\n-\+$/
+ syn match plugH2 /^-\{2,}/
+ syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
+ hi def link plug1 Title
+ hi def link plug2 Repeat
+ hi def link plugH2 Type
+ hi def link plugX Exception
+ hi def link plugBracket Structure
+ hi def link plugNumber Number
+
+ hi def link plugDash Special
+ hi def link plugPlus Constant
+ hi def link plugStar Boolean
+
+ hi def link plugMessage Function
+ hi def link plugName Label
+ hi def link plugInstall Function
+ hi def link plugUpdate Type
+
+ hi def link plugError Error
+ hi def link plugDeleted Ignore
+ hi def link plugRelDate Comment
+ hi def link plugEdge PreProc
+ hi def link plugSha Identifier
+ hi def link plugTag Constant
+
+ hi def link plugNotLoaded Comment
+endfunction
+
+function! s:lpad(str, len)
+ return a:str . repeat(' ', a:len - len(a:str))
+endfunction
+
+function! s:lines(msg)
+ return split(a:msg, "[\r\n]")
+endfunction
+
+function! s:lastline(msg)
+ return get(s:lines(a:msg), -1, '')
+endfunction
+
+function! s:new_window()
+ execute get(g:, 'plug_window', 'vertical topleft new')
+endfunction
+
+function! s:plug_window_exists()
+ let buflist = tabpagebuflist(s:plug_tab)
+ return !empty(buflist) && index(buflist, s:plug_buf) >= 0
+endfunction
+
+function! s:switch_in()
+ if !s:plug_window_exists()
+ return 0
+ endif
+
+ if winbufnr(0) != s:plug_buf
+ let s:pos = [tabpagenr(), winnr(), winsaveview()]
+ execute 'normal!' s:plug_tab.'gt'
+ let winnr = bufwinnr(s:plug_buf)
+ execute winnr.'wincmd w'
+ call add(s:pos, winsaveview())
+ else
+ let s:pos = [winsaveview()]
+ endif
+
+ setlocal modifiable
+ return 1
+endfunction
+
+function! s:switch_out(...)
+ call winrestview(s:pos[-1])
+ setlocal nomodifiable
+ if a:0 > 0
+ execute a:1
+ endif
+
+ if len(s:pos) > 1
+ execute 'normal!' s:pos[0].'gt'
+ execute s:pos[1] 'wincmd w'
+ call winrestview(s:pos[2])
+ endif
+endfunction
+
+function! s:finish_bindings()
+ nnoremap <silent> <buffer> R :call <SID>retry()<cr>
+ nnoremap <silent> <buffer> D :PlugDiff<cr>
+ nnoremap <silent> <buffer> S :PlugStatus<cr>
+ nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
+ nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
+endfunction
+
+function! s:prepare(...)
+ if empty(s:plug_getcwd())
+ throw 'Invalid current working directory. Cannot proceed.'
+ endif
+
+ for evar in ['$GIT_DIR', '$GIT_WORK_TREE']
+ if exists(evar)
+ throw evar.' detected. Cannot proceed.'
+ endif
+ endfor
+
+ call s:job_abort()
+ if s:switch_in()
+ if b:plug_preview == 1
+ pc
+ endif
+ enew
+ else
+ call s:new_window()
+ endif
+
+ nnoremap <silent> <buffer> q :call <SID>close_pane()<cr>
+ if a:0 == 0
+ call s:finish_bindings()
+ endif
+ let b:plug_preview = -1
+ let s:plug_tab = tabpagenr()
+ let s:plug_buf = winbufnr(0)
+ call s:assign_name()
+
+ for k in ['<cr>', 'L', 'o', 'X', 'd', 'dd']
+ execute 'silent! unmap <buffer>' k
+ endfor
+ setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell
+ if exists('+colorcolumn')
+ setlocal colorcolumn=
+ endif
+ setf vim-plug
+ if exists('g:syntax_on')
+ call s:syntax()
+ endif
+endfunction
+
+function! s:close_pane()
+ if b:plug_preview == 1
+ pc
+ let b:plug_preview = -1
+ else
+ bd
+ endif
+endfunction
+
+function! s:assign_name()
+ " Assign buffer name
+ let prefix = '[Plugins]'
+ let name = prefix
+ let idx = 2
+ while bufexists(name)
+ let name = printf('%s (%s)', prefix, idx)
+ let idx = idx + 1
+ endwhile
+ silent! execute 'f' fnameescape(name)
+endfunction
+
+function! s:chsh(swap)
+ let prev = [&shell, &shellcmdflag, &shellredir]
+ if !s:is_win
+ set shell=sh
+ endif
+ if a:swap
+ if s:is_powershell(&shell)
+ let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'
+ elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$'
+ set shellredir=>%s\ 2>&1
+ endif
+ endif
+ return prev
+endfunction
+
+function! s:bang(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(a:0)
+ " FIXME: Escaping is incomplete. We could use shellescape with eval,
+ " but it won't work on Windows.
+ let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')
+ execute "normal! :execute g:_plug_bang\<cr>\<cr>"
+ finally
+ unlet g:_plug_bang
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ return v:shell_error ? 'Exit status: ' . v:shell_error : ''
+endfunction
+
+function! s:regress_bar()
+ let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')
+ call s:progress_bar(2, bar, len(bar))
+endfunction
+
+function! s:is_updated(dir)
+ return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))
+endfunction
+
+function! s:do(pull, force, todo)
+ for [name, spec] in items(a:todo)
+ if !isdirectory(spec.dir)
+ continue
+ endif
+ let installed = has_key(s:update.new, name)
+ let updated = installed ? 0 :
+ \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))
+ if a:force || installed || updated
+ execute 'cd' s:esc(spec.dir)
+ call append(3, '- Post-update hook for '. name .' ... ')
+ let error = ''
+ let type = type(spec.do)
+ if type == s:TYPE.string
+ if spec.do[0] == ':'
+ if !get(s:loaded, name, 0)
+ let s:loaded[name] = 1
+ call s:reorg_rtp()
+ endif
+ call s:load_plugin(spec)
+ try
+ execute spec.do[1:]
+ catch
+ let error = v:exception
+ endtry
+ if !s:plug_window_exists()
+ cd -
+ throw 'Warning: vim-plug was terminated by the post-update hook of '.name
+ endif
+ else
+ let error = s:bang(spec.do)
+ endif
+ elseif type == s:TYPE.funcref
+ try
+ call s:load_plugin(spec)
+ let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')
+ call spec.do({ 'name': name, 'status': status, 'force': a:force })
+ catch
+ let error = v:exception
+ endtry
+ else
+ let error = 'Invalid hook type'
+ endif
+ call s:switch_in()
+ call setline(4, empty(error) ? (getline(4) . 'OK')
+ \ : ('x' . getline(4)[1:] . error))
+ if !empty(error)
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ endif
+ cd -
+ endif
+ endfor
+endfunction
+
+function! s:hash_match(a, b)
+ return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
+endfunction
+
+function! s:checkout(spec)
+ let sha = a:spec.commit
+ let output = s:git_revision(a:spec.dir)
+ if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
+ let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : ''
+ let output = s:system(
+ \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
+ endif
+ return output
+endfunction
+
+function! s:finish(pull)
+ let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
+ if new_frozen
+ let s = new_frozen > 1 ? 's' : ''
+ call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
+ endif
+ call append(3, '- Finishing ... ') | 4
+ redraw
+ call plug#helptags()
+ call plug#end()
+ call setline(4, getline(4) . 'Done!')
+ redraw
+ let msgs = []
+ if !empty(s:update.errors)
+ call add(msgs, "Press 'R' to retry.")
+ endif
+ if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
+ \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'"))
+ call add(msgs, "Press 'D' to see the updated changes.")
+ endif
+ echo join(msgs, ' ')
+ call s:finish_bindings()
+endfunction
+
+function! s:retry()
+ if empty(s:update.errors)
+ return
+ endif
+ echo
+ call s:update_impl(s:update.pull, s:update.force,
+ \ extend(copy(s:update.errors), [s:update.threads]))
+endfunction
+
+function! s:is_managed(name)
+ return has_key(g:plugs[a:name], 'uri')
+endfunction
+
+function! s:names(...)
+ return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
+endfunction
+
+function! s:check_ruby()
+ silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'")
+ if !exists('g:plug_ruby')
+ redraw!
+ return s:warn('echom', 'Warning: Ruby interface is broken')
+ endif
+ let ruby_version = split(g:plug_ruby, '\.')
+ unlet g:plug_ruby
+ return s:version_requirement(ruby_version, [1, 8, 7])
+endfunction
+
+function! s:update_impl(pull, force, args) abort
+ let sync = index(a:args, '--sync') >= 0 || has('vim_starting')
+ let args = filter(copy(a:args), 'v:val != "--sync"')
+ let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
+ \ remove(args, -1) : get(g:, 'plug_threads', 16)
+
+ let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
+ let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
+ \ filter(managed, 'index(args, v:key) >= 0')
+
+ if empty(todo)
+ return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))
+ endif
+
+ if !s:is_win && s:git_version_requirement(2, 3)
+ let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''
+ let $GIT_TERMINAL_PROMPT = 0
+ for plug in values(todo)
+ let plug.uri = substitute(plug.uri,
+ \ '^https://git::@github\.com', 'https://github.com', '')
+ endfor
+ endif
+
+ if !isdirectory(g:plug_home)
+ try
+ call mkdir(g:plug_home, 'p')
+ catch
+ return s:err(printf('Invalid plug directory: %s. '.
+ \ 'Try to call plug#begin with a valid directory', g:plug_home))
+ endtry
+ endif
+
+ if has('nvim') && !exists('*jobwait') && threads > 1
+ call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')
+ endif
+
+ let use_job = s:nvim || s:vim8
+ let python = (has('python') || has('python3')) && !use_job
+ 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()
+
+ let s:update = {
+ \ 'start': reltime(),
+ \ 'all': todo,
+ \ 'todo': copy(todo),
+ \ 'errors': [],
+ \ 'pull': a:pull,
+ \ 'force': a:force,
+ \ 'new': {},
+ \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1,
+ \ 'bar': '',
+ \ 'fin': 0
+ \ }
+
+ call s:prepare(1)
+ call append(0, ['', ''])
+ normal! 2G
+ silent! redraw
+
+ " Set remote name, overriding a possible user git config's clone.defaultRemoteName
+ let s:clone_opt = ['--origin', 'origin']
+ if get(g:, 'plug_shallow', 1)
+ call extend(s:clone_opt, ['--depth', '1'])
+ if s:git_version_requirement(1, 7, 10)
+ call add(s:clone_opt, '--no-single-branch')
+ endif
+ endif
+
+ if has('win32unix') || has('wsl')
+ call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input'])
+ endif
+
+ let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : ''
+
+ " Python version requirement (>= 2.7)
+ if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
+ redir => pyv
+ silent python import platform; print platform.python_version()
+ redir END
+ let python = s:version_requirement(
+ \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
+ endif
+
+ if (python || ruby) && s:update.threads > 1
+ try
+ let imd = &imd
+ if s:mac_gui
+ set noimd
+ endif
+ if ruby
+ call s:update_ruby()
+ else
+ call s:update_python()
+ endif
+ catch
+ let lines = getline(4, '$')
+ let printed = {}
+ silent! 4,$d _
+ for line in lines
+ let name = s:extract_name(line, '.', '')
+ if empty(name) || !has_key(printed, name)
+ call append('$', line)
+ if !empty(name)
+ let printed[name] = 1
+ if line[0] == 'x' && index(s:update.errors, name) < 0
+ call add(s:update.errors, name)
+ end
+ endif
+ endif
+ endfor
+ finally
+ let &imd = imd
+ call s:update_finish()
+ endtry
+ else
+ call s:update_vim()
+ while use_job && sync
+ sleep 100m
+ if s:update.fin
+ break
+ endif
+ endwhile
+ endif
+endfunction
+
+function! s:log4(name, msg)
+ call setline(4, printf('- %s (%s)', a:msg, a:name))
+ redraw
+endfunction
+
+function! s:update_finish()
+ if exists('s:git_terminal_prompt')
+ let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
+ endif
+ if s:switch_in()
+ call append(3, '- Updating ...') | 4
+ 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))'))
+ let [pos, _] = s:logpos(name)
+ if !pos
+ continue
+ endif
+ if has_key(spec, 'commit')
+ call s:log4(name, 'Checking out '.spec.commit)
+ let out = s:checkout(spec)
+ elseif has_key(spec, 'tag')
+ let tag = spec.tag
+ if tag =~ '\*'
+ let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))
+ if !v:shell_error && !empty(tags)
+ let tag = tags[0]
+ call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
+ call append(3, '')
+ endif
+ endif
+ call s:log4(name, 'Checking out '.tag)
+ let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
+ else
+ let branch = s:git_origin_branch(spec)
+ call s:log4(name, 'Merging origin/'.s:esc(branch))
+ let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'
+ \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)
+ endif
+ if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
+ \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
+ call s:log4(name, 'Updating submodules. This may take a while.')
+ let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)
+ endif
+ let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
+ if v:shell_error
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ silent execute pos 'd _'
+ call append(4, msg) | 4
+ elseif !empty(out)
+ call setline(pos, msg[0])
+ endif
+ redraw
+ endfor
+ silent 4 d _
+ try
+ 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")'))
+ catch
+ call s:warn('echom', v:exception)
+ call s:warn('echo', '')
+ return
+ endtry
+ call s:finish(s:update.pull)
+ call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
+ call s:switch_out('normal! gg')
+ endif
+endfunction
+
+function! s:job_abort()
+ if (!s:nvim && !s:vim8) || !exists('s:jobs')
+ return
+ endif
+
+ for [name, j] in items(s:jobs)
+ if s:nvim
+ silent! call jobstop(j.jobid)
+ elseif s:vim8
+ silent! call job_stop(j.jobid)
+ endif
+ if j.new
+ call s:rm_rf(g:plugs[name].dir)
+ endif
+ endfor
+ let s:jobs = {}
+endfunction
+
+function! s:last_non_empty_line(lines)
+ let len = len(a:lines)
+ for idx in range(len)
+ let line = a:lines[len-idx-1]
+ if !empty(line)
+ return line
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:job_out_cb(self, data) abort
+ let self = a:self
+ let data = remove(self.lines, -1) . a:data
+ let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]')
+ call extend(self.lines, lines)
+ " To reduce the number of buffer updates
+ let self.tick = get(self, 'tick', -1) + 1
+ if !self.running || self.tick % len(s:jobs) == 0
+ let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-')
+ let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines)
+ call s:log(bullet, self.name, result)
+ endif
+endfunction
+
+function! s:job_exit_cb(self, data) abort
+ let a:self.running = 0
+ let a:self.error = a:data != 0
+ call s:reap(a:self.name)
+ call s:tick()
+endfunction
+
+function! s:job_cb(fn, job, ch, data)
+ if !s:plug_window_exists() " plug window closed
+ return s:job_abort()
+ endif
+ call call(a:fn, [a:job, a:data])
+endfunction
+
+function! s:nvim_cb(job_id, data, event) dict abort
+ return (a:event == 'stdout' || a:event == 'stderr') ?
+ \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) :
+ \ s:job_cb('s:job_exit_cb', self, 0, a:data)
+endfunction
+
+function! s:spawn(name, cmd, opts)
+ let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],
+ \ 'new': get(a:opts, 'new', 0) }
+ let s:jobs[a:name] = job
+
+ if s:nvim
+ if has_key(a:opts, 'dir')
+ let job.cwd = a:opts.dir
+ endif
+ let argv = a:cmd
+ call extend(job, {
+ \ 'on_stdout': function('s:nvim_cb'),
+ \ 'on_stderr': function('s:nvim_cb'),
+ \ 'on_exit': function('s:nvim_cb'),
+ \ })
+ let jid = s:plug_call('jobstart', argv, job)
+ if jid > 0
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = [jid < 0 ? argv[0].' is not executable' :
+ \ 'Invalid arguments (or job table is full)']
+ endif
+ elseif s:vim8
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})'))
+ if has_key(a:opts, 'dir')
+ let cmd = s:with_cd(cmd, a:opts.dir, 0)
+ endif
+ let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]
+ let jid = job_start(s:is_win ? join(argv, ' ') : argv, {
+ \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]),
+ \ 'err_mode': 'raw',
+ \ 'out_mode': 'raw'
+ \})
+ if job_status(jid) == 'run'
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = ['Failed to start job']
+ endif
+ else
+ let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]))
+ let job.error = v:shell_error != 0
+ let job.running = 0
+ endif
+endfunction
+
+function! s:reap(name)
+ let job = s:jobs[a:name]
+ if job.error
+ call add(s:update.errors, a:name)
+ elseif get(job, 'new', 0)
+ let s:update.new[a:name] = 1
+ endif
+ let s:update.bar .= job.error ? 'x' : '='
+
+ let bullet = job.error ? 'x' : '-'
+ let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines)
+ call s:log(bullet, a:name, empty(result) ? 'OK' : result)
+ call s:bar()
+
+ call remove(s:jobs, a:name)
+endfunction
+
+function! s:bar()
+ if s:switch_in()
+ let total = len(s:update.all)
+ call setline(1, (s:update.pull ? 'Updating' : 'Installing').
+ \ ' plugins ('.len(s:update.bar).'/'.total.')')
+ call s:progress_bar(2, s:update.bar, total)
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:logpos(name)
+ let max = line('$')
+ for i in range(4, max > 4 ? max : 4)
+ if getline(i) =~# '^[-+x*] '.a:name.':'
+ for j in range(i + 1, max > 5 ? max : 5)
+ if getline(j) !~ '^ '
+ return [i, j - 1]
+ endif
+ endfor
+ return [i, i]
+ endif
+ endfor
+ return [0, 0]
+endfunction
+
+function! s:log(bullet, name, lines)
+ if s:switch_in()
+ let [b, e] = s:logpos(a:name)
+ if b > 0
+ silent execute printf('%d,%d d _', b, e)
+ if b > winheight('.')
+ let b = 4
+ endif
+ else
+ let b = 4
+ endif
+ " FIXME For some reason, nomodifiable is set after :d in vim8
+ setlocal modifiable
+ call append(b - 1, s:format_message(a:bullet, a:name, a:lines))
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:update_vim()
+ let s:jobs = {}
+
+ call s:bar()
+ call s:tick()
+endfunction
+
+function! s:tick()
+ let pull = s:update.pull
+ let prog = s:progress_opt(s:nvim || s:vim8)
+while 1 " Without TCO, Vim stack is bound to explode
+ if empty(s:update.todo)
+ if empty(s:jobs) && !s:update.fin
+ call s:update_finish()
+ let s:update.fin = 1
+ endif
+ return
+ endif
+
+ let name = keys(s:update.todo)[0]
+ let spec = remove(s:update.todo, name)
+ let new = empty(globpath(spec.dir, '.git', 1))
+
+ call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
+ redraw
+
+ let has_tag = has_key(spec, 'tag')
+ if !new
+ let [error, _] = s:git_validate(spec, 0)
+ if empty(error)
+ if pull
+ let cmd = s:git_version_requirement(2) ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch']
+ if has_tag && !empty(globpath(spec.dir, '.git/shallow'))
+ call extend(cmd, ['--depth', '99999999'])
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, cmd, { 'dir': spec.dir })
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 }
+ endif
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 }
+ endif
+ else
+ let cmd = ['git', 'clone']
+ if !has_tag
+ call extend(cmd, s:clone_opt)
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 })
+ endif
+
+ if !s:jobs[name].running
+ call s:reap(name)
+ endif
+ if len(s:jobs) >= s:update.threads
+ break
+ endif
+endwhile
+endfunction
+
+function! s:update_python()
+let py_exe = has('python') ? 'python' : 'python3'
+execute py_exe "<< EOF"
+import datetime
+import functools
+import os
+try:
+ import queue
+except ImportError:
+ import Queue as queue
+import random
+import re
+import shutil
+import signal
+import subprocess
+import tempfile
+import threading as thr
+import time
+import traceback
+import vim
+
+G_NVIM = vim.eval("has('nvim')") == '1'
+G_PULL = vim.eval('s:update.pull') == '1'
+G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
+G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
+G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt'))
+G_PROGRESS = vim.eval('s:progress_opt(1)')
+G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
+G_STOP = thr.Event()
+G_IS_WIN = vim.eval('s:is_win') == '1'
+
+class PlugError(Exception):
+ def __init__(self, msg):
+ self.msg = msg
+class CmdTimedOut(PlugError):
+ pass
+class CmdFailed(PlugError):
+ pass
+class InvalidURI(PlugError):
+ pass
+class Action(object):
+ INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']
+
+class Buffer(object):
+ def __init__(self, lock, num_plugs, is_pull):
+ self.bar = ''
+ self.event = 'Updating' if is_pull else 'Installing'
+ self.lock = lock
+ self.maxy = int(vim.eval('winheight(".")'))
+ self.num_plugs = num_plugs
+
+ def __where(self, name):
+ """ Find first line with name in current buffer. Return line num. """
+ found, lnum = False, 0
+ matcher = re.compile('^[-+x*] {0}:'.format(name))
+ for line in vim.current.buffer:
+ if matcher.search(line) is not None:
+ found = True
+ break
+ lnum += 1
+
+ if not found:
+ lnum = -1
+ return lnum
+
+ def header(self):
+ curbuf = vim.current.buffer
+ curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)
+
+ num_spaces = self.num_plugs - len(self.bar)
+ curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
+
+ with self.lock:
+ vim.command('normal! 2G')
+ vim.command('redraw')
+
+ def write(self, action, name, lines):
+ first, rest = lines[0], lines[1:]
+ msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
+ msg.extend([' ' + line for line in rest])
+
+ try:
+ if action == Action.ERROR:
+ self.bar += 'x'
+ vim.command("call add(s:update.errors, '{0}')".format(name))
+ elif action == Action.DONE:
+ self.bar += '='
+
+ curbuf = vim.current.buffer
+ lnum = self.__where(name)
+ if lnum != -1: # Found matching line num
+ del curbuf[lnum]
+ if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):
+ lnum = 3
+ else:
+ lnum = 3
+ curbuf.append(msg, lnum)
+
+ self.header()
+ except vim.error:
+ pass
+
+class Command(object):
+ CD = 'cd /d' if G_IS_WIN else 'cd'
+
+ def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None):
+ self.cmd = cmd
+ if cmd_dir:
+ self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd)
+ self.timeout = timeout
+ self.callback = cb if cb else (lambda msg: None)
+ self.clean = clean if clean else (lambda: None)
+ self.proc = None
+
+ @property
+ def alive(self):
+ """ Returns true only if command still running. """
+ return self.proc and self.proc.poll() is None
+
+ def execute(self, ntries=3):
+ """ Execute the command with ntries if CmdTimedOut.
+ Returns the output of the command if no Exception.
+ """
+ attempt, finished, limit = 0, False, self.timeout
+
+ while not finished:
+ try:
+ attempt += 1
+ result = self.try_command()
+ finished = True
+ return result
+ except CmdTimedOut:
+ if attempt != ntries:
+ self.notify_retry()
+ self.timeout += limit
+ else:
+ raise
+
+ def notify_retry(self):
+ """ Retry required for command, notify user. """
+ for count in range(3, 0, -1):
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+ msg = 'Timeout. Will retry in {0} second{1} ...'.format(
+ count, 's' if count != 1 else '')
+ self.callback([msg])
+ time.sleep(1)
+ self.callback(['Retrying ...'])
+
+ def try_command(self):
+ """ Execute a cmd & poll for callback. Returns list of output.
+ Raises CmdFailed -> return code for Popen isn't 0
+ Raises CmdTimedOut -> command exceeded timeout without new output
+ """
+ first_line = True
+
+ try:
+ tfile = tempfile.NamedTemporaryFile(mode='w+b')
+ preexec_fn = not G_IS_WIN and os.setsid or None
+ self.proc = subprocess.Popen(self.cmd, stdout=tfile,
+ stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE, shell=True,
+ preexec_fn=preexec_fn)
+ thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,))
+ thrd.start()
+
+ thread_not_started = True
+ while thread_not_started:
+ try:
+ thrd.join(0.1)
+ thread_not_started = False
+ except RuntimeError:
+ pass
+
+ while self.alive:
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+
+ if first_line or random.random() < G_LOG_PROB:
+ first_line = False
+ line = '' if G_IS_WIN else nonblock_read(tfile.name)
+ if line:
+ self.callback([line])
+
+ time_diff = time.time() - os.path.getmtime(tfile.name)
+ if time_diff > self.timeout:
+ raise CmdTimedOut(['Timeout!'])
+
+ thrd.join(0.5)
+
+ tfile.seek(0)
+ result = [line.decode('utf-8', 'replace').rstrip() for line in tfile]
+
+ if self.proc.returncode != 0:
+ raise CmdFailed([''] + result)
+
+ return result
+ except:
+ self.terminate()
+ raise
+
+ def terminate(self):
+ """ Terminate process and cleanup. """
+ if self.alive:
+ if G_IS_WIN:
+ os.kill(self.proc.pid, signal.SIGINT)
+ else:
+ os.killpg(self.proc.pid, signal.SIGTERM)
+ self.clean()
+
+class Plugin(object):
+ def __init__(self, name, args, buf_q, lock):
+ self.name = name
+ self.args = args
+ self.buf_q = buf_q
+ self.lock = lock
+ self.tag = args.get('tag', 0)
+
+ def manage(self):
+ try:
+ if os.path.exists(self.args['dir']):
+ self.update()
+ else:
+ self.install()
+ with self.lock:
+ thread_vim_command("let s:update.new['{0}'] = 1".format(self.name))
+ except PlugError as exc:
+ self.write(Action.ERROR, self.name, exc.msg)
+ except KeyboardInterrupt:
+ G_STOP.set()
+ self.write(Action.ERROR, self.name, ['Interrupted!'])
+ except:
+ # Any exception except those above print stack trace
+ msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())
+ self.write(Action.ERROR, self.name, msg.split('\n'))
+ raise
+
+ def install(self):
+ target = self.args['dir']
+ if target[-1] == '\\':
+ target = target[0:-1]
+
+ def clean(target):
+ def _clean():
+ try:
+ shutil.rmtree(target)
+ except OSError:
+ pass
+ return _clean
+
+ self.write(Action.INSTALL, self.name, ['Installing ...'])
+ callback = functools.partial(self.write, Action.INSTALL, self.name)
+ cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(
+ '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],
+ esc(target))
+ com = Command(cmd, None, G_TIMEOUT, callback, clean(target))
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+
+ def repo_uri(self):
+ cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'
+ command = Command(cmd, self.args['dir'], G_TIMEOUT,)
+ result = command.execute(G_RETRIES)
+ return result[-1]
+
+ def update(self):
+ actual_uri = self.repo_uri()
+ expect_uri = self.args['uri']
+ regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$')
+ ma = regex.match(actual_uri)
+ mb = regex.match(expect_uri)
+ if ma is None or mb is None or ma.groups() != mb.groups():
+ msg = ['',
+ 'Invalid URI: {0}'.format(actual_uri),
+ 'Expected {0}'.format(expect_uri),
+ 'PlugClean required.']
+ raise InvalidURI(msg)
+
+ if G_PULL:
+ self.write(Action.UPDATE, self.name, ['Updating ...'])
+ callback = functools.partial(self.write, Action.UPDATE, self.name)
+ fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''
+ cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)
+ com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+ else:
+ self.write(Action.DONE, self.name, ['Already installed'])
+
+ def write(self, action, name, msg):
+ self.buf_q.put((action, name, msg))
+
+class PlugThread(thr.Thread):
+ def __init__(self, tname, args):
+ super(PlugThread, self).__init__()
+ self.tname = tname
+ self.args = args
+
+ def run(self):
+ thr.current_thread().name = self.tname
+ buf_q, work_q, lock = self.args
+
+ try:
+ while not G_STOP.is_set():
+ name, args = work_q.get_nowait()
+ plug = Plugin(name, args, buf_q, lock)
+ plug.manage()
+ work_q.task_done()
+ except queue.Empty:
+ pass
+
+class RefreshThread(thr.Thread):
+ def __init__(self, lock):
+ super(RefreshThread, self).__init__()
+ self.lock = lock
+ self.running = True
+
+ def run(self):
+ while self.running:
+ with self.lock:
+ thread_vim_command('noautocmd normal! a')
+ time.sleep(0.33)
+
+ def stop(self):
+ self.running = False
+
+if G_NVIM:
+ def thread_vim_command(cmd):
+ vim.session.threadsafe_call(lambda: vim.command(cmd))
+else:
+ def thread_vim_command(cmd):
+ vim.command(cmd)
+
+def esc(name):
+ return '"' + name.replace('"', '\"') + '"'
+
+def nonblock_read(fname):
+ """ Read a file with nonblock flag. Return the last line. """
+ fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)
+ buf = os.read(fread, 100000).decode('utf-8', 'replace')
+ os.close(fread)
+
+ line = buf.rstrip('\r\n')
+ left = max(line.rfind('\r'), line.rfind('\n'))
+ if left != -1:
+ left += 1
+ line = line[left:]
+
+ return line
+
+def main():
+ thr.current_thread().name = 'main'
+ nthreads = int(vim.eval('s:update.threads'))
+ plugs = vim.eval('s:update.todo')
+ mac_gui = vim.eval('s:mac_gui') == '1'
+
+ lock = thr.Lock()
+ buf = Buffer(lock, len(plugs), G_PULL)
+ buf_q, work_q = queue.Queue(), queue.Queue()
+ for work in plugs.items():
+ work_q.put(work)
+
+ start_cnt = thr.active_count()
+ for num in range(nthreads):
+ tname = 'PlugT-{0:02}'.format(num)
+ thread = PlugThread(tname, (buf_q, work_q, lock))
+ thread.start()
+ if mac_gui:
+ rthread = RefreshThread(lock)
+ rthread.start()
+
+ while not buf_q.empty() or thr.active_count() != start_cnt:
+ try:
+ action, name, msg = buf_q.get(True, 0.25)
+ buf.write(action, name, ['OK'] if not msg else msg)
+ buf_q.task_done()
+ except queue.Empty:
+ pass
+ except KeyboardInterrupt:
+ G_STOP.set()
+
+ if mac_gui:
+ rthread.stop()
+ rthread.join()
+
+main()
+EOF
+endfunction
+
+function! s:update_ruby()
+ ruby << EOF
+ module PlugStream
+ SEP = ["\r", "\n", nil]
+ def get_line
+ buffer = ''
+ loop do
+ char = readchar rescue return
+ if SEP.include? char.chr
+ buffer << $/
+ break
+ else
+ buffer << char
+ end
+ end
+ buffer
+ end
+ end unless defined?(PlugStream)
+
+ def esc arg
+ %["#{arg.gsub('"', '\"')}"]
+ end
+
+ def killall pid
+ pids = [pid]
+ if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil }
+ else
+ unless `which pgrep 2> /dev/null`.empty?
+ children = pids
+ until children.empty?
+ children = children.map { |pid|
+ `pgrep -P #{pid}`.lines.map { |l| l.chomp }
+ }.flatten
+ pids += children
+ end
+ end
+ pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
+ end
+ end
+
+ def compare_git_uri a, b
+ regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$}
+ regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1)
+ end
+
+ require 'thread'
+ require 'fileutils'
+ require 'timeout'
+ running = true
+ iswin = VIM::evaluate('s:is_win').to_i == 1
+ pull = VIM::evaluate('s:update.pull').to_i == 1
+ base = VIM::evaluate('g:plug_home')
+ all = VIM::evaluate('s:update.todo')
+ limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
+ tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
+ nthr = VIM::evaluate('s:update.threads').to_i
+ maxy = VIM::evaluate('winheight(".")').to_i
+ vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/
+ cd = iswin ? 'cd /d' : 'cd'
+ tot = VIM::evaluate('len(s:update.todo)') || 0
+ bar = ''
+ skip = 'Already installed'
+ mtx = Mutex.new
+ take1 = proc { mtx.synchronize { running && all.shift } }
+ logh = proc {
+ cnt = bar.length
+ $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
+ $curbuf[2] = '[' + bar.ljust(tot) + ']'
+ VIM::command('normal! 2G')
+ VIM::command('redraw')
+ }
+ where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }
+ log = proc { |name, result, type|
+ mtx.synchronize do
+ ing = ![true, false].include?(type)
+ bar += type ? '=' : 'x' unless ing
+ b = case type
+ when :install then '+' when :update then '*'
+ when true, nil then '-' else
+ VIM::command("call add(s:update.errors, '#{name}')")
+ 'x'
+ end
+ result =
+ if type || type.nil?
+ ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]
+ elsif result =~ /^Interrupted|^Timeout/
+ ["#{b} #{name}: #{result}"]
+ else
+ ["#{b} #{name}"] + result.lines.map { |l| " " << l }
+ end
+ if lnum = where.call(name)
+ $curbuf.delete lnum
+ lnum = 4 if ing && lnum > maxy
+ end
+ result.each_with_index do |line, offset|
+ $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)
+ end
+ logh.call
+ end
+ }
+ bt = proc { |cmd, name, type, cleanup|
+ tried = timeout = 0
+ begin
+ tried += 1
+ timeout += limit
+ fd = nil
+ data = ''
+ if iswin
+ Timeout::timeout(timeout) do
+ tmp = VIM::evaluate('tempname()')
+ system("(#{cmd}) > #{tmp}")
+ data = File.read(tmp).chomp
+ File.unlink tmp rescue nil
+ end
+ else
+ fd = IO.popen(cmd).extend(PlugStream)
+ first_line = true
+ log_prob = 1.0 / nthr
+ while line = Timeout::timeout(timeout) { fd.get_line }
+ data << line
+ log.call name, line.chomp, type if name && (first_line || rand < log_prob)
+ first_line = false
+ end
+ fd.close
+ end
+ [$? == 0, data.chomp]
+ rescue Timeout::Error, Interrupt => e
+ if fd && !fd.closed?
+ killall fd.pid
+ fd.close
+ end
+ cleanup.call if cleanup
+ if e.is_a?(Timeout::Error) && tried < tries
+ 3.downto(1) do |countdown|
+ s = countdown > 1 ? 's' : ''
+ log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type
+ sleep 1
+ end
+ log.call name, 'Retrying ...', type
+ retry
+ end
+ [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
+ end
+ }
+ main = Thread.current
+ threads = []
+ watcher = Thread.new {
+ if vim7
+ while VIM::evaluate('getchar(1)')
+ sleep 0.1
+ end
+ else
+ require 'io/console' # >= Ruby 1.9
+ nil until IO.console.getch == 3.chr
+ end
+ mtx.synchronize do
+ running = false
+ threads.each { |t| t.raise Interrupt } unless vim7
+ end
+ threads.each { |t| t.join rescue nil }
+ main.kill
+ }
+ refresh = Thread.new {
+ while true
+ mtx.synchronize do
+ break unless running
+ VIM::command('noautocmd normal! a')
+ end
+ sleep 0.2
+ end
+ } if VIM::evaluate('s:mac_gui') == 1
+
+ clone_opt = VIM::evaluate('s:clone_opt').join(' ')
+ progress = VIM::evaluate('s:progress_opt(1)')
+ nthr.times do
+ mtx.synchronize do
+ threads << Thread.new {
+ while pair = take1.call
+ name = pair.first
+ dir, uri, tag = pair.last.values_at *%w[dir uri tag]
+ exists = File.directory? dir
+ ok, result =
+ if exists
+ chdir = "#{cd} #{iswin ? dir : esc(dir)}"
+ ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil
+ current_uri = data.lines.to_a.last
+ if !ret
+ if data =~ /^Interrupted|^Timeout/
+ [false, data]
+ else
+ [false, [data.chomp, "PlugClean required."].join($/)]
+ end
+ elsif !compare_git_uri(current_uri, uri)
+ [false, ["Invalid URI: #{current_uri}",
+ "Expected: #{uri}",
+ "PlugClean required."].join($/)]
+ else
+ if pull
+ log.call name, 'Updating ...', :update
+ fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''
+ bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil
+ else
+ [true, skip]
+ end
+ end
+ else
+ d = esc dir.sub(%r{[\\/]+$}, '')
+ log.call name, 'Installing ...', :install
+ bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {
+ FileUtils.rm_rf dir
+ }
+ end
+ mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
+ log.call name, result, ok
+ end
+ } if running
+ end
+ end
+ threads.each { |t| t.join rescue nil }
+ logh.call
+ refresh.kill if refresh
+ watcher.kill
+EOF
+endfunction
+
+function! s:shellesc_cmd(arg, script)
+ let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g')
+ return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g')
+endfunction
+
+function! s:shellesc_ps1(arg)
+ return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'"
+endfunction
+
+function! s:shellesc_sh(arg)
+ return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
+endfunction
+
+" Escape the shell argument based on the shell.
+" Vim and Neovim's shellescape() are insufficient.
+" 1. shellslash determines whether to use single/double quotes.
+" Double-quote escaping is fragile for cmd.exe.
+" 2. It does not work for powershell.
+" 3. It does not work for *sh shells if the command is executed
+" via cmd.exe (ie. cmd.exe /c sh -c command command_args)
+" 4. It does not support batchfile syntax.
+"
+" Accepts an optional dictionary with the following keys:
+" - shell: same as Vim/Neovim 'shell' option.
+" If unset, fallback to 'cmd.exe' on Windows or 'sh'.
+" - script: If truthy and shell is cmd.exe, escape for batchfile syntax.
+function! plug#shellescape(arg, ...)
+ if a:arg =~# '^[A-Za-z0-9_/:.-]\+$'
+ return a:arg
+ endif
+ let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
+ let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
+ let script = get(opts, 'script', 1)
+ if shell =~# 'cmd\(\.exe\)\?$'
+ return s:shellesc_cmd(a:arg, script)
+ elseif s:is_powershell(shell)
+ return s:shellesc_ps1(a:arg)
+ endif
+ return s:shellesc_sh(a:arg)
+endfunction
+
+function! s:glob_dir(path)
+ return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
+endfunction
+
+function! s:progress_bar(line, bar, total)
+ call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')
+endfunction
+
+function! s:compare_git_uri(a, b)
+ " See `git help clone'
+ " https:// [user@] github.com[:port] / junegunn/vim-plug [.git]
+ " [git@] github.com[:port] : junegunn/vim-plug [.git]
+ " file:// / junegunn/vim-plug [/]
+ " / junegunn/vim-plug [/]
+ let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$'
+ let ma = matchlist(a:a, pat)
+ let mb = matchlist(a:b, pat)
+ return ma[1:2] ==# mb[1:2]
+endfunction
+
+function! s:format_message(bullet, name, message)
+ if a:bullet != 'x'
+ return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
+ else
+ let lines = map(s:lines(a:message), '" ".v:val')
+ return extend([printf('x %s:', a:name)], lines)
+ endif
+endfunction
+
+function! s:with_cd(cmd, dir, ...)
+ let script = a:0 > 0 ? a:1 : 1
+ return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd)
+endfunction
+
+function! s:system(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ if type(a:cmd) == s:TYPE.list
+ " Neovim's system() supports list argument to bypass the shell
+ " but it cannot set the working directory for the command.
+ " Assume that the command does not rely on the shell.
+ if has('nvim') && a:0 == 0
+ return system(a:cmd)
+ endif
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ else
+ let cmd = a:cmd
+ endif
+ if a:0 > 0
+ let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
+ endif
+ if s:is_win && type(a:cmd) != s:TYPE.list
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ return system(cmd)
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+endfunction
+
+function! s:system_chomp(...)
+ let ret = call('s:system', a:000)
+ return v:shell_error ? '' : substitute(ret, '\n$', '', '')
+endfunction
+
+function! s:git_validate(spec, check_branch)
+ let err = ''
+ if isdirectory(a:spec.dir)
+ let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
+ let remote = result[-1]
+ if empty(remote)
+ let err = join([remote, 'PlugClean required.'], "\n")
+ elseif !s:compare_git_uri(remote, a:spec.uri)
+ let err = join(['Invalid URI: '.remote,
+ \ 'Expected: '.a:spec.uri,
+ \ 'PlugClean required.'], "\n")
+ elseif a:check_branch && has_key(a:spec, 'commit')
+ let sha = s:git_revision(a:spec.dir)
+ if empty(sha)
+ let err = join(add(result, 'PlugClean required.'), "\n")
+ elseif !s:hash_match(sha, a:spec.commit)
+ let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
+ \ a:spec.commit[:6], sha[:6]),
+ \ 'PlugUpdate required.'], "\n")
+ endif
+ elseif a:check_branch
+ let current_branch = result[0]
+ " Check tag
+ let origin_branch = s:git_origin_branch(a:spec)
+ if has_key(a:spec, 'tag')
+ let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
+ if a:spec.tag !=# tag && a:spec.tag !~ '\*'
+ let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
+ \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
+ endif
+ " Check branch
+ elseif origin_branch !=# current_branch
+ let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
+ \ current_branch, origin_branch)
+ endif
+ if empty(err)
+ let [ahead, behind] = split(s:lastline(s:system([
+ \ 'git', 'rev-list', '--count', '--left-right',
+ \ printf('HEAD...origin/%s', origin_branch)
+ \ ], a:spec.dir)), '\t')
+ if !v:shell_error && ahead
+ if behind
+ " Only mention PlugClean if diverged, otherwise it's likely to be
+ " pushable (and probably not that messed up).
+ let err = printf(
+ \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
+ \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
+ else
+ let err = printf("Ahead of origin/%s by %d commit(s).\n"
+ \ .'Cannot update until local changes are pushed.',
+ \ origin_branch, ahead)
+ endif
+ endif
+ endif
+ endif
+ else
+ let err = 'Not found'
+ endif
+ return [err, err =~# 'PlugClean']
+endfunction
+
+function! s:rm_rf(dir)
+ if isdirectory(a:dir)
+ return s:system(s:is_win
+ \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
+ \ : ['rm', '-rf', a:dir])
+ endif
+endfunction
+
+function! s:clean(force)
+ call s:prepare()
+ call append(0, 'Searching for invalid plugins in '.g:plug_home)
+ call append(1, '')
+
+ " List of valid directories
+ let dirs = []
+ let errs = {}
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ if !s:is_managed(name)
+ call add(dirs, spec.dir)
+ else
+ let [err, clean] = s:git_validate(spec, 1)
+ if clean
+ let errs[spec.dir] = s:lines(err)[0]
+ else
+ call add(dirs, spec.dir)
+ endif
+ endif
+ let cnt += 1
+ call s:progress_bar(2, repeat('=', cnt), total)
+ normal! 2G
+ redraw
+ endfor
+
+ let allowed = {}
+ for dir in dirs
+ let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1
+ let allowed[dir] = 1
+ for child in s:glob_dir(dir)
+ let allowed[child] = 1
+ endfor
+ endfor
+
+ let todo = []
+ let found = sort(s:glob_dir(g:plug_home))
+ while !empty(found)
+ let f = remove(found, 0)
+ if !has_key(allowed, f) && isdirectory(f)
+ call add(todo, f)
+ call append(line('$'), '- ' . f)
+ if has_key(errs, f)
+ call append(line('$'), ' ' . errs[f])
+ endif
+ let found = filter(found, 'stridx(v:val, f) != 0')
+ end
+ endwhile
+
+ 4
+ redraw
+ if empty(todo)
+ call append(line('$'), 'Already clean.')
+ else
+ let s:clean_count = 0
+ call append(3, ['Directories to delete:', ''])
+ redraw!
+ if a:force || s:ask_no_interrupt('Delete all directories?')
+ call s:delete([6, line('$')], 1)
+ else
+ call setline(4, 'Cancelled.')
+ nnoremap <silent> <buffer> d :set opfunc=<sid>delete_op<cr>g@
+ nmap <silent> <buffer> dd d_
+ xnoremap <silent> <buffer> d :<c-u>call <sid>delete_op(visualmode(), 1)<cr>
+ echo 'Delete the lines (d{motion}) to delete the corresponding directories'
+ endif
+ endif
+ 4
+ setlocal nomodifiable
+endfunction
+
+function! s:delete_op(type, ...)
+ call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0)
+endfunction
+
+function! s:delete(range, force)
+ let [l1, l2] = a:range
+ let force = a:force
+ let err_count = 0
+ while l1 <= l2
+ let line = getline(l1)
+ if line =~ '^- ' && isdirectory(line[2:])
+ execute l1
+ redraw!
+ let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)
+ let force = force || answer > 1
+ if answer
+ let err = s:rm_rf(line[2:])
+ setlocal modifiable
+ if empty(err)
+ call setline(l1, '~'.line[1:])
+ let s:clean_count += 1
+ else
+ delete _
+ call append(l1 - 1, s:format_message('x', line[1:], err))
+ let l2 += len(s:lines(err))
+ let err_count += 1
+ endif
+ let msg = printf('Removed %d directories.', s:clean_count)
+ if err_count > 0
+ let msg .= printf(' Failed to remove %d directories.', err_count)
+ endif
+ call setline(4, msg)
+ setlocal nomodifiable
+ endif
+ endif
+ let l1 += 1
+ endwhile
+endfunction
+
+function! s:upgrade()
+ echo 'Downloading the latest version of vim-plug'
+ redraw
+ let tmp = s:plug_tempname()
+ let new = tmp . '/plug.vim'
+
+ try
+ let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
+ if v:shell_error
+ return s:err('Error upgrading vim-plug: '. out)
+ endif
+
+ if readfile(s:me) ==# readfile(new)
+ echo 'vim-plug is already up-to-date'
+ return 0
+ else
+ call rename(s:me, s:me . '.old')
+ call rename(new, s:me)
+ unlet g:loaded_plug
+ echo 'vim-plug has been upgraded'
+ return 1
+ endif
+ finally
+ silent! call s:rm_rf(tmp)
+ endtry
+endfunction
+
+function! s:upgrade_specs()
+ for spec in values(g:plugs)
+ let spec.frozen = get(spec, 'frozen', 0)
+ endfor
+endfunction
+
+function! s:status()
+ call s:prepare()
+ call append(0, 'Checking plugins')
+ call append(1, '')
+
+ let ecnt = 0
+ let unloaded = 0
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ let is_dir = isdirectory(spec.dir)
+ if has_key(spec, 'uri')
+ if is_dir
+ let [err, _] = s:git_validate(spec, 1)
+ let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
+ else
+ let [valid, msg] = [0, 'Not found. Try PlugInstall.']
+ endif
+ else
+ if is_dir
+ let [valid, msg] = [1, 'OK']
+ else
+ let [valid, msg] = [0, 'Not found.']
+ endif
+ endif
+ let cnt += 1
+ let ecnt += !valid
+ " `s:loaded` entry can be missing if PlugUpgraded
+ if is_dir && get(s:loaded, name, -1) == 0
+ let unloaded = 1
+ let msg .= ' (not loaded)'
+ endif
+ call s:progress_bar(2, repeat('=', cnt), total)
+ call append(3, s:format_message(valid ? '-' : 'x', name, msg))
+ normal! 2G
+ redraw
+ endfor
+ call setline(1, 'Finished. '.ecnt.' error(s).')
+ normal! gg
+ setlocal nomodifiable
+ if unloaded
+ echo "Press 'L' on each line to load plugin, or 'U' to update"
+ nnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ xnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ end
+endfunction
+
+function! s:extract_name(str, prefix, suffix)
+ return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$')
+endfunction
+
+function! s:status_load(lnum)
+ let line = getline(a:lnum)
+ let name = s:extract_name(line, '-', '(not loaded)')
+ if !empty(name)
+ call plug#load(name)
+ setlocal modifiable
+ call setline(a:lnum, substitute(line, ' (not loaded)$', '', ''))
+ setlocal nomodifiable
+ endif
+endfunction
+
+function! s:status_update() range
+ let lines = getline(a:firstline, a:lastline)
+ let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)')
+ if !empty(names)
+ echo
+ execute 'PlugUpdate' join(names)
+ endif
+endfunction
+
+function! s:is_preview_window_open()
+ silent! wincmd P
+ if &previewwindow
+ wincmd p
+ return 1
+ endif
+endfunction
+
+function! s:find_name(lnum)
+ for lnum in reverse(range(1, a:lnum))
+ let line = getline(lnum)
+ if empty(line)
+ return ''
+ endif
+ let name = s:extract_name(line, '-', '')
+ if !empty(name)
+ return name
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:preview_commit()
+ if b:plug_preview < 0
+ let b:plug_preview = !s:is_preview_window_open()
+ endif
+
+ let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}')
+ if empty(sha)
+ let name = matchstr(getline('.'), '^- \zs[^:]*\ze:$')
+ if empty(name)
+ return
+ endif
+ let title = 'HEAD@{1}..'
+ let command = 'git diff --no-color HEAD@{1}'
+ else
+ let title = sha
+ let command = 'git show --no-color --pretty=medium '.sha
+ let name = s:find_name(line('.'))
+ endif
+
+ if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir)
+ return
+ endif
+
+ if exists('g:plug_pwindow') && !s:is_preview_window_open()
+ execute g:plug_pwindow
+ execute 'e' title
+ else
+ execute 'pedit' title
+ wincmd P
+ endif
+ setlocal previewwindow filetype=git buftype=nofile bufhidden=wipe nobuflisted modifiable
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && '.command
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ execute 'silent %!' cmd
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ setlocal nomodifiable
+ nnoremap <silent> <buffer> q :q<cr>
+ wincmd p
+endfunction
+
+function! s:section(flags)
+ call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
+endfunction
+
+function! s:format_git_log(line)
+ let indent = ' '
+ let tokens = split(a:line, nr2char(1))
+ if len(tokens) != 5
+ return indent.substitute(a:line, '\s*$', '', '')
+ endif
+ let [graph, sha, refs, subject, date] = tokens
+ let tag = matchstr(refs, 'tag: [^,)]\+')
+ let tag = empty(tag) ? ' ' : ' ('.tag.') '
+ return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)
+endfunction
+
+function! s:append_ul(lnum, text)
+ call append(a:lnum, ['', a:text, repeat('-', len(a:text))])
+endfunction
+
+function! s:diff()
+ call s:prepare()
+ call append(0, ['Collecting changes ...', ''])
+ let cnts = [0, 0]
+ let bar = ''
+ let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')
+ call s:progress_bar(2, bar, len(total))
+ for origin in [1, 0]
+ let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))
+ if empty(plugs)
+ continue
+ endif
+ call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
+ for [k, v] in plugs
+ let branch = s:git_origin_branch(v)
+ if len(branch)
+ let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
+ let cmd = ['git', 'log', '--graph', '--color=never']
+ if s:git_version_requirement(2, 10, 0)
+ call add(cmd, '--no-show-signature')
+ endif
+ call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
+ if has_key(v, 'rtp')
+ call extend(cmd, ['--', v.rtp])
+ endif
+ let diff = s:system_chomp(cmd, v.dir)
+ if !empty(diff)
+ let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
+ call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
+ let cnts[origin] += 1
+ endif
+ endif
+ let bar .= '='
+ call s:progress_bar(2, bar, len(total))
+ normal! 2G
+ redraw
+ endfor
+ if !cnts[origin]
+ call append(5, ['', 'N/A'])
+ endif
+ endfor
+ call setline(1, printf('%d plugin(s) updated.', cnts[0])
+ \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : ''))
+
+ if cnts[0] || cnts[1]
+ nnoremap <silent> <buffer> <plug>(plug-preview) :silent! call <SID>preview_commit()<cr>
+ if empty(maparg("\<cr>", 'n'))
+ nmap <buffer> <cr> <plug>(plug-preview)
+ endif
+ if empty(maparg('o', 'n'))
+ nmap <buffer> o <plug>(plug-preview)
+ endif
+ endif
+ if cnts[0]
+ nnoremap <silent> <buffer> X :call <SID>revert()<cr>
+ echo "Press 'X' on each block to revert the update"
+ endif
+ normal! gg
+ setlocal nomodifiable
+endfunction
+
+function! s:revert()
+ if search('^Pending updates', 'bnW')
+ return
+ endif
+
+ let name = s:find_name(line('.'))
+ if empty(name) || !has_key(g:plugs, name) ||
+ \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
+ return
+ endif
+
+ call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir)
+ setlocal modifiable
+ normal! "_dap
+ setlocal nomodifiable
+ echo 'Reverted'
+endfunction
+
+function! s:snapshot(force, ...) abort
+ call s:prepare()
+ setf vim
+ call append(0, ['" Generated by vim-plug',
+ \ '" '.strftime("%c"),
+ \ '" :source this file in vim to restore the snapshot',
+ \ '" or execute: vim -S snapshot.vim',
+ \ '', '', 'PlugUpdate!'])
+ 1
+ let anchor = line('$') - 3
+ let names = sort(keys(filter(copy(g:plugs),
+ \'has_key(v:val, "uri") && isdirectory(v:val.dir)')))
+ for name in reverse(names)
+ let sha = has_key(g:plugs[name], 'commit') ? g:plugs[name].commit : s:git_revision(g:plugs[name].dir)
+ if !empty(sha)
+ call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
+ redraw
+ endif
+ endfor
+
+ if a:0 > 0
+ let fn = s:plug_expand(a:1)
+ if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?'))
+ return
+ endif
+ call writefile(getline(1, '$'), fn)
+ echo 'Saved as '.a:1
+ silent execute 'e' s:esc(fn)
+ setf vim
+ endif
+endfunction
+
+function! s:split_rtp()
+ return split(&rtp, '\\\@<!,')
+endfunction
+
+let s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))
+let s:last_rtp = s:escrtp(get(s:split_rtp(), -1, ''))
+
+if exists('g:plugs')
+ let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))
+ call s:upgrade_specs()
+ call s:define_commands()
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/autoload/text_obj.vim b/autoload/text_obj.vim
deleted file mode 100644
index caba645..0000000
--- a/autoload/text_obj.vim
+++ /dev/null
@@ -1,86 +0,0 @@
-function! text_obj#URL() abort
- if match(&runtimepath, 'vim-highlighturl') != -1
- " Note that we use https://github.com/itchyny/vim-highlighturl to get the URL pattern.
- let url_pattern = highlighturl#default_pattern()
- else
- let url_pattern = expand('<cfile>')
- " Since expand('<cfile>') also works for normal words, we need to check if
- " this is really URL using heuristics, e.g., URL length.
- if len(url_pattern) <= 10
- return
- endif
- endif
-
- " We need to find all possible URL on this line and their start, end index.
- " Then find where current cursor is, and decide if cursor is on one of the
- " URLs.
- let line_text = getline('.')
- let url_infos = []
-
- let [_url, _idx_start, _idx_end] = matchstrpos(line_text, url_pattern)
- while _url !=# ''
- let url_infos += [[_url, _idx_start+1, _idx_end]]
- let [_url, _idx_start, _idx_end] = matchstrpos(line_text, url_pattern, _idx_end)
- endwhile
-
- " echo url_infos
- " If no URL is found, do nothing.
- if len(url_infos) == 0
- return
- endif
-
- let [start_col, end_col] = [-1, -1]
- " If URL is found, find if cursor is on it.
- let [buf_num, cur_row, cur_col] = getcurpos()[0:2]
- for url_info in url_infos
- " echo url_info
- let [_url, _idx_start, _idx_end] = url_info
- if cur_col >= _idx_start && cur_col <= _idx_end
- let start_col = _idx_start
- let end_col = _idx_end
- break
- endif
- endfor
-
- " Cursor is not on a URL, do nothing.
- if start_col == -1
- return
- endif
-
- " Now set the '< and '> mark
- call setpos("'<", [buf_num, cur_row, start_col, 0])
- call setpos("'>", [buf_num, cur_row, end_col, 0])
- normal! gv
-endfunction
-
-function! text_obj#MdCodeBlock(type) abort
- " the parameter type specify whether it is inner text objects or around
- " text objects.
-
- " Move the cursor to the end of line in case that cursor is on the opening
- " of a code block. Actually, there are still issues if the cursor is on the
- " closing of a code block. In this case, the start row of code blocks would
- " be wrong. Unless we can match code blocks, it not easy to fix this.
- normal! $
- let start_row = searchpos('\s*```', 'bnW')[0]
- let end_row = searchpos('\s*```', 'nW')[0]
-
- let buf_num = bufnr()
- if a:type ==# 'i'
- let start_row += 1
- let end_row -= 1
- endif
- " echo a:type start_row end_row
-
- call setpos("'<", [buf_num, start_row, 1, 0])
- call setpos("'>", [buf_num, end_row, 1, 0])
- execute 'normal! `<V`>'
-endfunction
-
-function! text_obj#Buffer() abort
- let buf_num = bufnr()
-
- call setpos("'<", [buf_num, 1, 1, 0])
- call setpos("'>", [buf_num, line('$'), 1, 0])
- execute 'normal! `<V`>'
-endfunction
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 774d919..0000000
--- a/docs/README.md
+++ /dev/null
@@ -1,218 +0,0 @@
-This doc summarizes how to install and use this configuration in detail.
-
-# Pre-requisite
-
-## Terminal emulators
-
-Which [terminal emulator](https://en.wikipedia.org/wiki/Terminal_emulator) we choose to use greatly affects the appearance and features of Nvim.
-Since Nvim supports true colors, terminals that support true colors are preferred.
-For a list of terminals that support true colors, see [here](https://github.com/termstandard/colors).
-
-For macOS, we can use [kitty](https://sw.kovidgoyal.net/kitty/), [iterm2](https://www.iterm2.com/), [wezterm](https://wezfurlong.org/wezterm/) or [Alacritty](https://github.com/jwilm/alacritty).
-
-If you ssh to Linux server on Windows, I recommend [wsltty](https://github.com/mintty/wsltty) and [Cygwin](https://www.cygwin.com/),
-both of them use [mintty](https://github.com/mintty/mintty) as the terminal emulator.
-For the latest version of Windows 10, you can also try [Windows Terminal](https://github.com/microsoft/terminal).
-
-## Patched Fonts
-
-Since statusline or file explorer plugins often use Unicode symbols not available in normal font,
-we need to install a patched font from the [nerd-fonts](https://github.com/ryanoasis/nerd-fonts) project.
-
-# Automatic installation
-
-## Automatic Installation for Linux
-
-To set up a workable Nvim environment on Linux,
-I use [a bash script](nvim_setup_linux.sh) to automatically install necessary dependencies, Nvim itself and configs.
-
-Note that the variable `PYTHON_INSTALLED`, `SYSTEM_PYTHON` and `ADD_TO_SYSTEM_PATH` in the script
-should be set properly based on your environment.
-
-## Automatic installation for Windows
-
-Run the script [nvim_setup_windows.ps1](nvim_setup_windows.ps1) in PowerShell **with Administrator rights**:
-
-```
-.\docs\nvim_setup_windows.ps1
-```
-
-# Manual install
-
-There are a few dependencies if we want to use Nvim for efficient editing and development work.
-
-## Dependencies
-
-### Python
-
-A lot of Nvim plugins are mainly written in Python, so we must install Python 3.
-The easiest way to install is via [Anaconda](https://docs.anaconda.com/anaconda/install/index.html) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html).
-
-After installation, make sure that you can run `python --version`,
-and that the output should be Python 3.x.
-
-### Pynvim
-
-Nvim relies on [pynvim](https://github.com/neovim/pynvim) to communicate with plugins that utilize its Python binding.
-Pynvim is required by plugins such as [wilder.nvim](https://github.com/gelguy/wilder.nvim).
-
-```
-pip install -U pynvim
-```
-
-### python-lsp-server
-
-[python-lsp-server (pylsp)](https://github.com/python-lsp/python-lsp-server) is a Python [Language Server](https://microsoft.github.io/language-server-protocol/) for completion, linting, go to definition, etc.
-
-```
-pip install 'python-lsp-server[all]' pylsp-mypy python-lsp-isort python-lsp-black
-```
-
-Note the executable for pylsp is also named `pylsp`. You need to set its PATH correctly.
-If you use pip from Anaconda, the executable path may be something like `$CONDA_ROOT/bin/pylsp`.
-For native python, the path for pylsp may be like `$HOME/.local/bin/pylsp`
-
-### Node
-
-We need to install node.js from [here](https://nodejs.org/en/download/).
-For Linux, you can use the following script:
-
-```bash
-# Ref: https://johnpapa.net/node-and-npm-without-sudo/
-wget https://nodejs.org/dist/v14.15.4/node-v14.15.4-linux-x64.tar.xz
-
-mkdir -p $HOME/tools
-# extract node to a custom directory, the directory should exist.
-tar xvf node-v14.15.4-linux-x64.tar.xz --directory=$HOME/tools
-```
-
-Then add the following config to `.bash_profile` or `.zshrc`
-
-```bash
-export PATH="$HOME/tools/node-v14.15.4-linux-x64/bin:$PATH"
-```
-
-Source the file:
-
-```bash
-source ~/.bash_profile
-# source ~/.zshrc
-```
-
-### vim-language-server
-
-[vim-language-server](https://github.com/iamcco/vim-language-server) provides completion for vim script. We can install vim-language-server globally:
-
-```bash
-npm install -g vim-language-server
-```
-
-vim-language-server is installed in the same directory as the node executable.
-
-### Git
-
-Git is required by plugin manager [lazy.nvim](https://github.com/folke/lazy.nvim) and other git-related plugins.
-
-For Linux and macOS, Git is usually pre-installed.
-The version of Git on the Linux system may be too old so that plugins may break.
-Check [here](https://jdhao.github.io/2021/03/27/upgrade_git_on_linux/) on how to install and set up the latest version of Git.
-For Windows, install [Git for Windows](https://git-scm.com/download/win) and make sure you can run `git` from command line.
-
-### ctags
-
-In order to use tags related plugins such as [vista.vim](https://github.com/liuchengxu/vista.vim), we need to install a ctags distribution.
-Universal-ctags is preferred.
-
-To install it on Linux, we need to build it from source. See [here](https://askubuntu.com/a/836521/768311) for the details.
-To install ctags on macOS, use [Homebrew](https://github.com/universal-ctags/homebrew-universal-ctags):
-
-```bash
-brew install ctags
-```
-
-To install it Windows, use [chocolatey](https://chocolatey.org/) or [scoop](https://scoop.sh/)
-
-```
-choco install universal-ctags
-
-# scoop bucket add extras
-# scoop install universal-ctags
-```
-
-Set its PATH properly and make sure you can run `ctags` from command line.
-
-### Ripgrep
-
-[Ripgrep](https://github.com/BurntSushi/ripgrep), aka, `rg`, is a fast grepping tool available for both Linux, Windows and macOS.
-It is used by several searching plugins.
-
-For Windows and macOS, we can install it via chocolatey and homebrew respectively.
-For Linux, we can download the [binary release](https://github.com/BurntSushi/ripgrep/releases) and install it.
-
-Set its PATH properly and make sure you can run `rg` from command line.
-
-### Linters
-
-A linter is a tool to check the source code for possible style and syntax issues.
-Based on the programming languages we use, we may need to install various linters.
-
-+ Python: [pylint](https://github.com/PyCQA/pylint) and [flake8](https://github.com/PyCQA/flake8).
-+ Vim script: [vint](https://github.com/Kuniwak/vint).
-
-Set their PATH properly and make sure you can run `pylint`, `flake8` and `vint` from command line.
-
-## Install Nvim
-
-There are various ways to install Nvim depending on your system.
-This config is only maintained for [the latest nvim stable release](https://github.com/neovim/neovim/releases/tag/stable).
-
-### Linux
-
-You can directly download the binary release from [here](https://github.com/neovim/neovim/releases/download/stable/nvim-linux64.tar.gz).
-You can also use the system package manager to install nvim,
-but that is not reliable since the latest version may not be available.
-
-### Windows
-
-You may download from [nvim release](https://github.com/neovim/neovim/releases/download/stable/nvim-win64.zip) from GitHub and manually extract it.
-
-Another way to install Nvim on Windows is via chocolatey or scoop:
-
-```
-choco install neovim
-
-# via scoop
-# scoop bucket add versions
-# scoop install neovim
-```
-
-### macOS
-
-It is recommended to install neovim via [Homebrew](https://brew.sh/) on macOS. Simply run the following command:
-
-```bash
-brew install neovim
-```
-
-After installing Nvim, we need to set the path to nvim correctly.
-**Make sure that you can run `nvim` from the command line after all these setups**.
-
-## Setting up Nvim
-
-After installing nvim and all the dependencies, we will install plugin managers and set up this config.
-
-### How to install this configuration
-
-On Linux and macOS, the directory is `~/.config/nvim`.
-On Windows, the config directory is `$HOME/AppData/Local/nvim`[^1].
-First, we need to remove all the files under the config directory (including dot files),
-then go to this directory, and run the following command:
-
-```
-git clone --depth=1 https://github.com/jdhao/nvim-config.git .
-```
-
-After that, when we first open nvim, all the plugins will be installed automatically.
-Since I use quite a lot of plugins (more than 60), it may take some time to install all of them.
-
-[^1]: Use `echo %userprofile%` to see where your `$HOME` is.
diff --git a/docs/nvim_install_mac.sh b/docs/nvim_install_mac.sh
deleted file mode 100644
index ef698c8..0000000
--- a/docs/nvim_install_mac.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-# This script is used to update Nvim on macOS
-#!/bin/bash
-set -eux
-
-wget https://github.com/neovim/neovim/releases/download/stable/nvim-macos.tar.gz
-
-if [[ ! -d "$HOME/tools/" ]]; then
- mkdir -p "$HOME/tools"
-fi
-
-# Delete existing nvim installation.
-# For newer release, the directory name is nvim-macos
-if [[ -d "$HOME/tools/nvim-macos" ]]; then
- rm -rf "$HOME/tools/nvim-macos"
-fi
-
-# Extract the tar ball
-tar zxvf nvim-macos.tar.gz -C "$HOME/tools"
-
-rm nvim-macos.tar.gz
diff --git a/docs/nvim_resources.md b/docs/nvim_resources.md
deleted file mode 100644
index 47c9156..0000000
--- a/docs/nvim_resources.md
+++ /dev/null
@@ -1,18 +0,0 @@
-Below are a list of resources that inspire me. This list is non-exhaustive as I
-can not remember the source of many settings.
-
-- [From .vimrc to .vim](https://vimways.org/2018/from-vimrc-to-vim/)
-- http://stevelosh.com/blog/2010/09/coming-home-to-vim/
-- https://github.com/tamlok/tvim/blob/master/.vimrc
-- https://nvie.com/posts/how-i-boosted-my-vim/
-- https://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/
-- https://sanctum.geek.nz/arabesque/vim-anti-patterns/
-- https://github.com/gkapfham/dotfiles/blob/master/.vimrc
-- https://google.github.io/styleguide/vimscriptguide.xml
-- https://github.com/romainl/idiomatic-vimrc
-- https://github.com/mhinz/vim-galore
-- https://learnvimscriptthehardway.stevelosh.com/
-- https://vimways.org/2018/from-vimrc-to-vim/
-- [vim script for Python developers](https://github.com/yegappan/VimScriptForPythonDevelopers)
-- [Awesome neovim](https://github.com/rockerBOO/awesome-neovim): extensive list of neovim resources (plugins, mostly).
-- [What is your favorite plugins for Nvim 0.5](https://www.reddit.com/r/neovim/comments/o20w3z/what_are_your_favorite_neovim_plugins_exclusive/)
diff --git a/docs/nvim_setup_linux.sh b/docs/nvim_setup_linux.sh
deleted file mode 100755
index f5dca87..0000000
--- a/docs/nvim_setup_linux.sh
+++ /dev/null
@@ -1,258 +0,0 @@
-#!/bin/bash
-set -exu
-set -o pipefail
-
-# Whether python3 has been installed on the system
-PYTHON_INSTALLED=true
-
-# If Python has been installed, then we need to know whether Python is provided
-# by the system, or you have already installed Python under your HOME.
-SYSTEM_PYTHON=true
-
-# If SYSTEM_PYTHON is false, we need to decide whether to install
-# Anaconda (INSTALL_ANACONDA=true) or Miniconda (INSTALL_ANACONDA=false)
-INSTALL_ANACONDA=false
-
-# Whether to add the path of the installed executables to system PATH
-ADD_TO_SYSTEM_PATH=true
-
-# select which shell we are using
-USE_ZSH_SHELL=true
-USE_BASH_SHELL=false
-
-if [[ ! -d "$HOME/packages/" ]]; then
- mkdir -p "$HOME/packages/"
-fi
-
-if [[ ! -d "$HOME/tools/" ]]; then
- mkdir -p "$HOME/tools/"
-fi
-
-#######################################################################
-# Anaconda or miniconda install #
-#######################################################################
-if [[ "$INSTALL_ANACONDA" = true ]]; then
- CONDA_DIR=$HOME/tools/anaconda
- CONDA_NAME=Anaconda.sh
- CONDA_LINK="https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.11-Linux-x86_64.sh"
-else
- CONDA_DIR=$HOME/tools/miniconda
- CONDA_NAME=Miniconda.sh
- CONDA_LINK="https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_4.10.3-Linux-x86_64.sh"
-fi
-
-if [[ ! "$PYTHON_INSTALLED" = true ]]; then
- echo "Installing Python in user HOME"
-
- SYSTEM_PYTHON=false
-
- echo "Downloading and installing conda"
-
- if [[ ! -f "$HOME/packages/$CONDA_NAME" ]]; then
- curl -Lo "$HOME/packages/$CONDA_NAME" $CONDA_LINK
- fi
-
- # Install conda silently
- if [[ -d $CONDA_DIR ]]; then
- rm -rf "$CONDA_DIR"
- fi
- bash "$HOME/packages/$CONDA_NAME" -b -p "$CONDA_DIR"
-
- # Setting up environment variables
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$CONDA_DIR/bin:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-else
- echo "Python is already installed. Skip installing it."
-fi
-
-# Install some Python packages used by Nvim plugins.
-echo "Installing Python packages"
-declare -a PY_PACKAGES=("pynvim" 'python-lsp-server[all]' "vim-vint" "python-lsp-isort" "pylsp-mypy" "python-lsp-black")
-
-if [[ "$SYSTEM_PYTHON" = true ]]; then
- echo "Using system Python to install $(PY_PACKAGES)"
-
- # If we use system Python, we need to install these Python packages under
- # user HOME, since we do not have permissions to install them under system
- # directories.
- for p in "${PY_PACKAGES[@]}"; do
- pip install --user "$p"
- done
-else
- echo "Using custom Python to install $(PY_PACKAGES)"
- for p in "${PY_PACKAGES[@]}"; do
- "$CONDA_DIR/bin/pip" install "$p"
- done
-fi
-
-#######################################################################
-# Install node and js-based language server #
-#######################################################################
-NODE_DIR=$HOME/tools/nodejs
-NODE_SRC_NAME=$HOME/packages/nodejs.tar.gz
-# when download speed is slow, we can also use its mirror site: https://mirrors.ustc.edu.cn/node/v15.0.0/
-NODE_LINK="https://mirrors.ustc.edu.cn/node/v15.0.0/node-v15.0.0-linux-x64.tar.xz"
-if [[ -z "$(command -v node)" ]]; then
- echo "Install Node.js"
- if [[ ! -f $NODE_SRC_NAME ]]; then
- echo "Downloading Node.js and renaming"
- wget $NODE_LINK -O "$NODE_SRC_NAME"
- fi
-
- if [[ ! -d "$NODE_DIR" ]]; then
- echo "Creating Node.js directory under tools directory"
- mkdir -p "$NODE_DIR"
- echo "Extracting to $HOME/tools/nodejs directory"
- tar xvf "$NODE_SRC_NAME" -C "$NODE_DIR" --strip-components 1
- fi
-
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$NODE_DIR/bin:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-else
- echo "Node.js is already installed. Skip installing it."
- NODE_DIR="$(realpath $(dirname $(which node))/..)"
-fi
-
-# Install vim-language-server
-"$NODE_DIR/bin/npm" install -g vim-language-server
-
-# Install bash-language-server
-"$NODE_DIR/bin/npm" install -g bash-language-server
-
-#######################################################################
-# lua-language-server #
-#######################################################################
-LUA_LS_DIR=$HOME/tools/lua-language-server
-LUA_LS_SRC=$HOME/packages/lua-language-server.tar.gz
-LUA_LS_LINK="https://github.com/LuaLS/lua-language-server/releases/download/3.6.11/lua-language-server-3.6.11-linux-x64.tar.gz"
-
-if [[ -z "$(command -v lua-language-server)" ]] && [[ ! -f "$LUA_LS_DIR/bin/lua-language-server" ]]; then
- echo 'Install lua-language-server'
- if [[ ! -f $LUA_LS_SRC ]]; then
- echo "Downloading lua-language-server and renaming"
- wget $LUA_LS_LINK -O "$LUA_LS_SRC"
- fi
-
- if [[ ! -d "$LUA_LS_DIR" ]]; then
- echo "Creating lua-language-server directory under tools directory"
- mkdir -p "$LUA_LS_DIR"
- echo "Extracting to directory $LUA_LS_DIR"
-
- tar zxvf "$LUA_LS_SRC" -C "$LUA_LS_DIR"
- fi
-
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$LUA_LS_DIR/bin:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-else
- echo "lua-language-server is already installed. Skip installing it."
-fi
-
-#######################################################################
-# Ripgrep part #
-#######################################################################
-RIPGREP_DIR=$HOME/tools/ripgrep
-RIPGREP_SRC_NAME=$HOME/packages/ripgrep.tar.gz
-RIPGREP_LINK="https://github.com/BurntSushi/ripgrep/releases/download/12.0.0/ripgrep-12.0.0-x86_64-unknown-linux-musl.tar.gz"
-if [[ -z "$(command -v rg)" ]] && [[ ! -f "$RIPGREP_DIR/rg" ]]; then
- echo "Install ripgrep"
- if [[ ! -f $RIPGREP_SRC_NAME ]]; then
- echo "Downloading ripgrep and renaming"
- wget $RIPGREP_LINK -O "$RIPGREP_SRC_NAME"
- fi
-
- if [[ ! -d "$RIPGREP_DIR" ]]; then
- echo "Creating ripgrep directory under tools directory"
- mkdir -p "$RIPGREP_DIR"
- echo "Extracting to $HOME/tools/ripgrep directory"
- tar zxvf "$RIPGREP_SRC_NAME" -C "$RIPGREP_DIR" --strip-components 1
- fi
-
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$RIPGREP_DIR:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-
- # set up manpath and zsh completion for ripgrep
- mkdir -p "$HOME/tools/ripgrep/doc/man/man1"
- mv "$HOME/tools/ripgrep/doc/rg.1" "$HOME/tools/ripgrep/doc/man/man1"
-
- if [[ "$USE_BASH_SHELL" = true ]]; then
- echo 'export MANPATH=$HOME/tools/ripgrep/doc/man:$MANPATH' >> "$HOME/.bash_profile"
- else
- echo 'export MANPATH=$HOME/tools/ripgrep/doc/man:$MANPATH' >> "$HOME/.zshrc"
- echo 'export FPATH=$HOME/tools/ripgrep/complete:$FPATH' >> "$HOME/.zshrc"
- fi
-else
- echo "ripgrep is already installed. Skip installing it."
-fi
-
-#######################################################################
-# Ctags install #
-#######################################################################
-CTAGS_SRC_DIR=$HOME/packages/ctags
-CTAGS_DIR=$HOME/tools/ctags
-CTAGS_LINK="https://github.com/universal-ctags/ctags.git"
-if [[ ! -f "$CTAGS_DIR/bin/ctags" ]]; then
- echo "Install ctags"
-
- if [[ ! -d $CTAGS_SRC_DIR ]]; then
- mkdir -p "$CTAGS_SRC_DIR"
- else
- # Prevent an incomplete download.
- rm -rf "$CTAGS_SRC_DIR"
- fi
-
- git clone --depth=1 "$CTAGS_LINK" "$CTAGS_SRC_DIR" && cd "$CTAGS_SRC_DIR"
- ./autogen.sh && ./configure --prefix="$CTAGS_DIR"
- make -j && make install
-
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$CTAGS_DIR/bin:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-else
- echo "ctags is already installed. Skip installing it."
-fi
-
-#######################################################################
-# Nvim install #
-#######################################################################
-NVIM_DIR=$HOME/tools/nvim
-NVIM_SRC_NAME=$HOME/packages/nvim-linux64.tar.gz
-NVIM_CONFIG_DIR=$HOME/.config/nvim
-NVIM_LINK="https://github.com/neovim/neovim/releases/download/stable/nvim-linux64.tar.gz"
-if [[ ! -f "$NVIM_DIR/bin/nvim" ]]; then
- echo "Installing Nvim"
- echo "Creating nvim directory under tools directory"
-
- if [[ ! -d "$NVIM_DIR" ]]; then
- mkdir -p "$NVIM_DIR"
- fi
-
- if [[ ! -f $NVIM_SRC_NAME ]]; then
- echo "Downloading Nvim"
- wget "$NVIM_LINK" -O "$NVIM_SRC_NAME"
- fi
- echo "Extracting neovim"
- tar zxvf "$NVIM_SRC_NAME" --strip-components 1 -C "$NVIM_DIR"
-
- if [[ "$ADD_TO_SYSTEM_PATH" = true ]] && [[ "$USE_BASH_SHELL" = true ]]; then
- echo "export PATH=\"$NVIM_DIR/bin:\$PATH\"" >> "$HOME/.bash_profile"
- fi
-else
- echo "Nvim is already installed. Skip installing it."
-fi
-
-echo "Setting up config and installing plugins"
-if [[ -d "$NVIM_CONFIG_DIR" ]]; then
- rm -rf "$NVIM_CONFIG_DIR.backup"
- mv "$NVIM_CONFIG_DIR" "$NVIM_CONFIG_DIR.backup"
-fi
-
-git clone --depth=1 https://github.com/jdhao/nvim-config.git "$NVIM_CONFIG_DIR"
-
-echo "Installing nvim plugins, please wait"
-"$NVIM_DIR/bin/nvim" -c "autocmd User LazyInstall quitall" -c "lua require('lazy').install()"
-
-echo "Finished installing Nvim and its dependencies!"
diff --git a/docs/nvim_setup_windows.ps1 b/docs/nvim_setup_windows.ps1
deleted file mode 100644
index 9148a22..0000000
--- a/docs/nvim_setup_windows.ps1
+++ /dev/null
@@ -1,55 +0,0 @@
-# Set policy to avoid errors
-Set-ExecutionPolicy RemoteSigned -scope CurrentUser
-
-# Install scoop
-Invoke-WebRequest -UseBasicParsing get.scoop.sh | Invoke-Expression
-
-# Install node
-scoop install nodejs
-
-# Install ripgrep
-scoop install ripgrep
-
-# Install universal-ctags
-scoop bucket add extras
-scoop install universal-ctags
-
-# Install vim-language-server
-npm install -g vim-language-server
-
-# Install bash-language-server
-npm install -g bash-language-server
-
-# Install miniconda3 (for Python)
-scoop install miniconda3
-
-# Install pynvim
-pip install -U pynvim
-
-# Install python-language-server
-pip install 'python-lsp-server[all]' pylsp-mypy python-lsp-isort
-
-# Install visual c++ redistribution
-scoop install vcredist2022
-
-# Install 7zip
-scoop install 7zip
-
-# Install lua-language-server
-$lua_ls_link = "https://github.com/LuaLS/lua-language-server/releases/download/3.6.11/lua-language-server-3.6.11-win32-x64.zip"
-$lua_ls_install_dir = "D:\portable_tools"
-$lua_ls_src_path = "$lua_ls_install_dir\lua-language-server.zip"
-$lua_ls_dir = "$lua_ls_install_dir\lua-language-server"
-
-# Download file, ref: https://stackoverflow.com/a/51225744/6064933
-Invoke-WebRequest $lua_ls_link -OutFile "$lua_ls_src_path"
-
-# Extract the zip file using 7zip, ref: https://stackoverflow.com/a/41933215/6064933
-7z x "$lua_ls_src_path" -o"$lua_ls_dir"
-
-# Setup PATH env variable, ref: https://stackoverflow.com/q/714877/6064933
-[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$lua_ls_dir\bin", "Machine")
-
-# Install neovim nightly
-scoop bucket add versions
-scoop install neovim
diff --git a/ftdetect/pdc.vim b/ftdetect/pdc.vim
deleted file mode 100644
index 20f96cf..0000000
--- a/ftdetect/pdc.vim
+++ /dev/null
@@ -1,4 +0,0 @@
-augroup det_md
- autocmd!
- autocmd BufRead,BufNewFile *.pdc set filetype=markdown
-augroup END
diff --git a/ftdetect/snippets.vim b/ftdetect/snippets.vim
deleted file mode 100644
index 3b81a36..0000000
--- a/ftdetect/snippets.vim
+++ /dev/null
@@ -1,4 +0,0 @@
-augroup det_snippet
- autocmd!
- autocmd BufRead,BufNewFile *.snippets set filetype=snippets
-augroup END
diff --git a/ginit.vim b/ginit.vim
deleted file mode 100644
index 5c3d0ff..0000000
--- a/ginit.vim
+++ /dev/null
@@ -1,74 +0,0 @@
-" Fix key mapping issues for GUI
-inoremap <silent> <S-Insert> <C-R>+
-cnoremap <S-Insert> <C-R>+
-nnoremap <silent> <C-6> <C-^>
-
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-" config for nvim-qt "
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-" To check if neovim-qt is running, use `exists('g:GuiLoaded')`,
-" see https://github.com/equalsraf/neovim-qt/issues/219
-if exists('g:GuiLoaded')
- " call GuiWindowMaximized(1)
- GuiTabline 0
- GuiPopupmenu 0
- GuiLinespace 2
- GuiFont! Hack\ NF:h10:l
-endif
-
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-" config for fvim "
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-if exists('g:fvim_loaded')
- set termguicolors
- colorscheme gruvbox8_hard
- set guifont=Hack\ NF:h13
- " Cursor tweaks
- FVimCursorSmoothMove v:true
- FVimCursorSmoothBlink v:true
-
- " Background composition, can be 'none', 'blur' or 'acrylic'
- FVimBackgroundComposition 'none'
- FVimBackgroundOpacity 1.0
- FVimBackgroundAltOpacity 1.0
-
- " Title bar tweaks (themed with colorscheme)
- FVimCustomTitleBar v:true
-
- " Debug UI overlay
- FVimDrawFPS v:false
- " Font debugging -- draw bounds around each glyph
- FVimFontDrawBounds v:false
-
- " Font tweaks
- FVimFontAntialias v:true
- FVimFontAutohint v:true
- FVimFontHintLevel 'full'
- FVimFontSubpixel v:true
- FVimFontLigature v:true
- " can be 'default', '14.0', '-1.0' etc.
- FVimFontLineHeight '+1'
-
- " Try to snap the fonts to the pixels, reduces blur
- " in some situations (e.g. 100% DPI).
- FVimFontAutoSnap v:true
-
- " Font weight tuning, possible values are 100..900
- FVimFontNormalWeight 100
- FVimFontBoldWeight 700
-
- FVimUIPopupMenu v:false
-endif
-
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-" config for neovide "
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-if exists("g:neovide")
- set guifont=Hack\ NF:h10
- let g:neovide_transparency = 1.0
- let g:neovide_cursor_animation_length = 0.1
- let g:neovide_cursor_trail_size=0.3
- let g:neovide_cursor_vfx_mode = ""
- let g:neovide_cursor_vfx_particle_density=10.0
- let g:neovide_cursor_vfx_opacity=150.0
-endif
diff --git a/init.lua b/init.lua
deleted file mode 100644
index 633f887..0000000
--- a/init.lua
+++ /dev/null
@@ -1,48 +0,0 @@
--- This is my personal Nvim configuration supporting Mac, Linux and Windows, with various plugins configured.
--- This configuration evolves as I learn more about Nvim and become more proficient in using Nvim.
--- Since it is very long (more than 1000 lines!), you should read it carefully and take only the settings that suit you.
--- I would not recommend cloning this repo and replace your own config. Good configurations are personal,
--- built over time with a lot of polish.
---
--- Author: Jiedong Hao
--- Email: jdhao@hotmail.com
--- Blog: https://jdhao.github.io/
--- GitHub: https://github.com/jdhao
--- StackOverflow: https://stackoverflow.com/users/6064933/jdhao
-vim.loader.enable()
-
-local version = vim.version
-
--- check if we have the latest stable version of nvim
-local expected_ver = "0.9.5"
-local ev = version.parse(expected_ver)
-local actual_ver = version()
-
-if version.cmp(ev, actual_ver) ~= 0 then
- local _ver = string.format("%s.%s.%s", actual_ver.major, actual_ver.minor, actual_ver.patch)
- local msg = string.format("Expect nvim %s, but got %s instead. Use at your own risk!", expected_ver, _ver)
- vim.api.nvim_err_writeln(msg)
-end
-
-local core_conf_files = {
- "globals.lua", -- some global settings
- "options.vim", -- setting options in nvim
- "autocommands.vim", -- various autocommands
- "mappings.lua", -- all the user-defined mappings
- "plugins.vim", -- all the plugins installed and their configurations
- "colorschemes.lua", -- colorscheme settings
-}
-
-local viml_conf_dir = vim.fn.stdpath("config") .. "/viml_conf"
--- source all the core config files
-for _, file_name in ipairs(core_conf_files) do
- if vim.endswith(file_name, 'vim') then
- local path = string.format("%s/%s", viml_conf_dir, file_name)
- local source_cmd = "source " .. path
- vim.cmd(source_cmd)
- else
- local module_name, _ = string.gsub(file_name, "%.lua", "")
- package.loaded[module_name] = nil
- require(module_name)
- end
-end
diff --git a/init.vim b/init.vim
new file mode 100644
index 0000000..6bd8f73
--- /dev/null
+++ b/init.vim
@@ -0,0 +1,166 @@
+let mapleader =","
+
+if ! filereadable(system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim"'))
+ echo "Downloading junegunn/vim-plug to manage plugins..."
+ silent !mkdir -p ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/
+ silent !curl "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" > ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/autoload/plug.vim
+ autocmd VimEnter * PlugInstall
+endif
+
+map ,, :keepp /<++><CR>ca<
+imap ,, <esc>:keepp /<++><CR>ca<
+
+call plug#begin(system('echo -n "${XDG_CONFIG_HOME:-$HOME/.config}/nvim/plugged"'))
+Plug 'tpope/vim-surround'
+Plug 'preservim/nerdtree'
+Plug 'junegunn/goyo.vim'
+Plug 'jreybert/vimagit'
+Plug 'vimwiki/vimwiki'
+Plug 'vim-airline/vim-airline'
+Plug 'tpope/vim-commentary'
+Plug 'ap/vim-css-color'
+call plug#end()
+
+set title
+set bg=light
+set go=a
+set mouse=a
+set nohlsearch
+set clipboard+=unnamedplus
+set noshowmode
+set noruler
+set laststatus=0
+set noshowcmd
+
+" Some basics:
+ nnoremap c "_c
+ set nocompatible
+ filetype plugin on
+ syntax on
+ set encoding=utf-8
+ set number relativenumber
+" Enable autocompletion:
+ set wildmode=longest,list,full
+" Disables automatic commenting on newline:
+ autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o
+" Perform dot commands over visual blocks:
+ vnoremap . :normal .<CR>
+" Goyo plugin makes text more readable when writing prose:
+ map <leader>f :Goyo \| set bg=light \| set linebreak<CR>
+" Spell-check set to <leader>o, 'o' for 'orthography':
+ map <leader>o :setlocal spell! spelllang=en_us<CR>
+" Splits open at the bottom and right, which is non-retarded, unlike vim defaults.
+ set splitbelow splitright
+
+" Nerd tree
+ map <leader>n :NERDTreeToggle<CR>
+ autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
+ if has('nvim')
+ let NERDTreeBookmarksFile = stdpath('data') . '/NERDTreeBookmarks'
+ else
+ let NERDTreeBookmarksFile = '~/.vim' . '/NERDTreeBookmarks'
+ endif
+
+" vimling:
+ nm <leader>d :call ToggleDeadKeys()<CR>
+ imap <leader>d <esc>:call ToggleDeadKeys()<CR>a
+ nm <leader>i :call ToggleIPA()<CR>
+ imap <leader>i <esc>:call ToggleIPA()<CR>a
+ nm <leader>q :call ToggleProse()<CR>
+
+" Shortcutting split navigation, saving a keypress:
+ map <C-h> <C-w>h
+ map <C-j> <C-w>j
+ map <C-k> <C-w>k
+ map <C-l> <C-w>l
+
+" Replace ex mode with gq
+ map Q gq
+
+" Check file in shellcheck:
+ map <leader>s :!clear && shellcheck -x %<CR>
+
+" Open my bibliography file in split
+ map <leader>b :vsp<space>$BIB<CR>
+ map <leader>r :vsp<space>$REFER<CR>
+
+" Replace all is aliased to S.
+ nnoremap S :%s//g<Left><Left>
+
+" Compile document, be it groff/LaTeX/markdown/etc.
+ map <leader>c :w! \| !compiler "%:p"<CR>
+
+" Open corresponding .pdf/.html or preview
+ map <leader>p :!opout "%:p"<CR>
+
+" Runs a script that cleans out tex build files whenever I close out of a .tex file.
+ autocmd VimLeave *.tex !texclear %
+
+" Ensure files are read as what I want:
+ let g:vimwiki_ext2syntax = {'.Rmd': 'markdown', '.rmd': 'markdown','.md': 'markdown', '.markdown': 'markdown', '.mdown': 'markdown'}
+ map <leader>v :VimwikiIndex<CR>
+ let g:vimwiki_list = [{'path': '~/.local/share/nvim/vimwiki', 'syntax': 'markdown', 'ext': '.md'}]
+ autocmd BufRead,BufNewFile /tmp/calcurse*,~/.calcurse/notes/* set filetype=markdown
+ autocmd BufRead,BufNewFile *.ms,*.me,*.mom,*.man set filetype=groff
+ autocmd BufRead,BufNewFile *.tex set filetype=tex
+
+" Save file as sudo on files that require root permission
+ cabbrev w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
+
+" Enable Goyo by default for mutt writing
+ autocmd BufRead,BufNewFile /tmp/neomutt* let g:goyo_width=80
+ autocmd BufRead,BufNewFile /tmp/neomutt* :Goyo | set bg=light
+ autocmd BufRead,BufNewFile /tmp/neomutt* map ZZ :Goyo\|x!<CR>
+ autocmd BufRead,BufNewFile /tmp/neomutt* map ZQ :Goyo\|q!<CR>
+
+" Automatically deletes all trailing whitespace and newlines at end of file on save. & reset cursor position
+ autocmd BufWritePre * let currPos = getpos(".")
+ autocmd BufWritePre * %s/\s\+$//e
+ autocmd BufWritePre * %s/\n\+\%$//e
+ autocmd BufWritePre *.[ch] %s/\%$/\r/e " add trailing newline for ANSI C standard
+ autocmd BufWritePre *neomutt* %s/^--$/-- /e " dash-dash-space signature delimiter in emails
+ autocmd BufWritePre * cal cursor(currPos[1], currPos[2])
+
+" When shortcut files are updated, renew bash and ranger configs with new material:
+ autocmd BufWritePost bm-files,bm-dirs !shortcuts
+" Run xrdb whenever Xdefaults or Xresources are updated.
+ autocmd BufRead,BufNewFile Xresources,Xdefaults,xresources,xdefaults set filetype=xdefaults
+ autocmd BufWritePost Xresources,Xdefaults,xresources,xdefaults !xrdb %
+" Recompile dwmblocks on config edit.
+ autocmd BufWritePost ~/.local/src/dwmblocks/config.h !cd ~/.local/src/dwmblocks/; sudo make install && { killall -q dwmblocks;setsid -f dwmblocks }
+
+" Turns off highlighting on the bits of code that are changed, so the line that is changed is highlighted but the actual text that has changed stands out on the line and is readable.
+if &diff
+ highlight! link DiffText MatchParen
+endif
+
+" Function for toggling the bottom statusbar:
+let s:hidden_all = 0
+function! ToggleHiddenAll()
+ if s:hidden_all == 0
+ let s:hidden_all = 1
+ set noshowmode
+ set noruler
+ set laststatus=0
+ set noshowcmd
+ else
+ let s:hidden_all = 0
+ set showmode
+ set ruler
+ set laststatus=2
+ set showcmd
+ endif
+endfunction
+nnoremap <leader>h :call ToggleHiddenAll()<CR>
+" Load command shortcuts generated from bm-dirs and bm-files via shortcuts script.
+" Here leader is ";".
+" So ":vs ;cfz" will expand into ":vs /home/<user>/.config/zsh/.zshrc"
+" if typed fast without the timeout.
+silent! source ~/.config/nvim/shortcuts.vim
+
+colorscheme default
+set tabstop=4
+set shiftwidth=4
+set softtabstop=4
+set autoindent
+set backspace=indent,eol,start
diff --git a/lua/config/bqf.lua b/lua/config/bqf.lua
deleted file mode 100644
index c62a513..0000000
--- a/lua/config/bqf.lua
+++ /dev/null
@@ -1,6 +0,0 @@
-require("bqf").setup {
- auto_resize_height = false,
- preview = {
- auto_preview = false,
- },
-}
diff --git a/lua/config/bufferline.lua b/lua/config/bufferline.lua
deleted file mode 100644
index 6fa27ce..0000000
--- a/lua/config/bufferline.lua
+++ /dev/null
@@ -1,46 +0,0 @@
-require("bufferline").setup {
- options = {
- numbers = "buffer_id",
- close_command = "bdelete! %d",
- right_mouse_command = nil,
- left_mouse_command = "buffer %d",
- middle_mouse_command = nil,
- indicator = {
- icon = "▎", -- this should be omitted if indicator style is not 'icon'
- style = "icon",
- },
- buffer_close_icon = "",
- modified_icon = "●",
- close_icon = "",
- left_trunc_marker = "",
- right_trunc_marker = "",
- max_name_length = 18,
- max_prefix_length = 15,
- tab_size = 10,
- diagnostics = false,
- custom_filter = function(bufnr)
- -- if the result is false, this buffer will be shown, otherwise, this
- -- buffer will be hidden.
-
- -- filter out filetypes you don't want to see
- local exclude_ft = { "qf", "fugitive", "git" }
- local cur_ft = vim.bo[bufnr].filetype
- local should_filter = vim.tbl_contains(exclude_ft, cur_ft)
-
- if should_filter then
- return false
- end
-
- return true
- end,
- show_buffer_icons = false,
- show_buffer_close_icons = true,
- show_close_icon = true,
- show_tab_indicators = true,
- persist_buffer_sort = true, -- whether or not custom sorted buffers should persist
- separator_style = "bar",
- enforce_regular_tabs = false,
- always_show_bufferline = true,
- sort_by = "id",
- },
-}
diff --git a/lua/config/dashboard-nvim.lua b/lua/config/dashboard-nvim.lua
deleted file mode 100644
index 9017d96..0000000
--- a/lua/config/dashboard-nvim.lua
+++ /dev/null
@@ -1,75 +0,0 @@
-local api = vim.api
-local keymap = vim.keymap
-local dashboard = require("dashboard")
-
-local conf = {}
-conf.header = {
- " ",
- " ",
- " ",
- " ███╗ ██╗ ███████╗ ██████╗ ██╗ ██╗ ██╗ ███╗ ███╗",
- " ████╗ ██║ ██╔════╝██╔═══██╗ ██║ ██║ ██║ ████╗ ████║",
- " ██╔██╗ ██║ █████╗ ██║ ██║ ██║ ██║ ██║ ██╔████╔██║",
- " ██║╚██╗██║ ██╔══╝ ██║ ██║ ╚██╗ ██╔╝ ██║ ██║╚██╔╝██║",
- " ██║ ╚████║ ███████╗╚██████╔╝ ╚████╔╝ ██║ ██║ ╚═╝ ██║",
- " ╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝",
- " ",
- " ",
- " ",
- " ",
-}
-
-conf.center = {
- {
- icon = "󰈞 ",
- desc = "Find File ",
- action = "Leaderf file --popup",
- key = "<Leader> f f",
- },
- {
- icon = "󰈢 ",
- desc = "Recently opened files ",
- action = "Leaderf mru --popup",
- key = "<Leader> f r",
- },
- {
- icon = "󰈬 ",
- desc = "Project grep ",
- action = "Leaderf rg --popup",
- key = "<Leader> f g",
- },
- {
- icon = " ",
- desc = "Open Nvim config ",
- action = "tabnew $MYVIMRC | tcd %:p:h",
- key = "<Leader> e v",
- },
- {
- icon = " ",
- desc = "New file ",
- action = "enew",
- key = "e",
- },
- {
- icon = "󰗼 ",
- desc = "Quit Nvim ",
- -- desc = "Quit Nvim ",
- action = "qa",
- key = "q",
- },
-}
-
-dashboard.setup({
- theme = 'doom',
- shortcut_type = 'number',
- config = conf
-})
-
-api.nvim_create_autocmd("FileType", {
- pattern = "dashboard",
- group = api.nvim_create_augroup("dashboard_enter", { clear = true }),
- callback = function ()
- keymap.set("n", "q", ":qa<CR>", { buffer = true, silent = true })
- keymap.set("n", "e", ":enew<CR>", { buffer = true, silent = true })
- end
-})
diff --git a/lua/config/fidget-nvim.lua b/lua/config/fidget-nvim.lua
deleted file mode 100644
index 945f564..0000000
--- a/lua/config/fidget-nvim.lua
+++ /dev/null
@@ -1 +0,0 @@
-require("fidget").setup {}
diff --git a/lua/config/fugitive.lua b/lua/config/fugitive.lua
deleted file mode 100644
index b9c45e2..0000000
--- a/lua/config/fugitive.lua
+++ /dev/null
@@ -1,11 +0,0 @@
-local keymap = vim.keymap
-
-keymap.set("n", "<leader>gs", "<cmd>Git<cr>", { desc = "Git status" })
-keymap.set("n", "<leader>gw", "<cmd>Gwrite<cr>", { desc = "Git add" })
-keymap.set("n", "<leader>gc", "<cmd>Git commit<cr>", { desc = "Git commit" })
-keymap.set("n", "<leader>gd", "<cmd>Gdiffsplit<cr>", { desc = "Git diff" })
-keymap.set("n", "<leader>gpl", "<cmd>Git pull<cr>", { desc = "Git pull" })
-keymap.set("n", "<leader>gpu", "<cmd>15 split|term git push<cr>", { desc = "Git push" })
-
--- convert git to Git in command line mode
-vim.fn['utils#Cabbrev']('git', 'Git')
diff --git a/lua/config/git-linker.lua b/lua/config/git-linker.lua
deleted file mode 100644
index 39f5ba2..0000000
--- a/lua/config/git-linker.lua
+++ /dev/null
@@ -1,37 +0,0 @@
-local keymap = vim.keymap
-local gitlinker = require("gitlinker")
-
-gitlinker.setup {
- callbacks = {
- ["dev.azure.com"] = function(url_data)
- vim.print(url_data)
- local url = require"gitlinker.hosts".get_base_https_url(url_data)
-
- if url_data.lstart then
- if url_data.lend == nil then
- url_data.lend = url_data.lstart
- end
- url = url .. "?path=/" .. url_data.file .. "&version=GC" .. url_data.rev .. "&line=" .. url_data.lstart .. "&lineEnd=" .. url_data.lend .. "&lineStartColumn=1" .. "&lineEndColumn=120"
- end
- return url
- end
- },
- mappings = nil,
-}
-
-keymap.set({ "n", "v" }, "<leader>gl", function()
- local mode = string.lower(vim.fn.mode())
- gitlinker.get_buf_range_url(mode)
-end, {
- silent = true,
- desc = "get git permlink",
-})
-
-keymap.set("n", "<leader>gb", function()
- gitlinker.get_repo_url({
- action_callback = gitlinker.actions.open_in_browser
- })
-end, {
- silent = true,
- desc = "browse repo in browser",
-})
diff --git a/lua/config/gitsigns.lua b/lua/config/gitsigns.lua
deleted file mode 100644
index 0a7294c..0000000
--- a/lua/config/gitsigns.lua
+++ /dev/null
@@ -1,57 +0,0 @@
-local gs = require("gitsigns")
-
-gs.setup {
- signs = {
- add = { hl = "GitSignsAdd", text = "+", numhl = "GitSignsAddNr", linehl = "GitSignsAddLn" },
- change = { hl = "GitSignsChange", text = "~", numhl = "GitSignsChangeNr", linehl = "GitSignsChangeLn" },
- delete = { hl = "GitSignsDelete", text = "_", numhl = "GitSignsDeleteNr", linehl = "GitSignsDeleteLn" },
- topdelete = { hl = "GitSignsDelete", text = "‾", numhl = "GitSignsDeleteNr", linehl = "GitSignsDeleteLn" },
- changedelete = { hl = "GitSignsChange", text = "│", numhl = "GitSignsChangeNr", linehl = "GitSignsChangeLn" },
- },
- word_diff = true,
- on_attach = function(bufnr)
- local function map(mode, l, r, opts)
- opts = opts or {}
- opts.buffer = bufnr
- vim.keymap.set(mode, l, r, opts)
- end
-
- -- Navigation
- map("n", "]c", function()
- if vim.wo.diff then
- return "]c"
- end
- vim.schedule(function()
- gs.next_hunk()
- end)
- return "<Ignore>"
- end, { expr = true, desc = "next hunk" })
-
- map("n", "[c", function()
- if vim.wo.diff then
- return "[c"
- end
- vim.schedule(function()
- gs.prev_hunk()
- end)
- return "<Ignore>"
- end, { expr = true, desc = "previous hunk" })
-
- -- Actions
- map("n", "<leader>hp", gs.preview_hunk)
- map("n", "<leader>hb", function()
- gs.blame_line { full = true }
- end)
- end,
-}
-
-vim.api.nvim_create_autocmd('ColorScheme', {
- pattern = "*",
- callback = function()
- vim.cmd [[
- hi GitSignsChangeInline gui=reverse
- hi GitSignsAddInline gui=reverse
- hi GitSignsDeleteInline gui=reverse
- ]]
- end
-})
diff --git a/lua/config/hlslens.lua b/lua/config/hlslens.lua
deleted file mode 100644
index 430bd23..0000000
--- a/lua/config/hlslens.lua
+++ /dev/null
@@ -1,49 +0,0 @@
-local api = vim.api
-local keymap = vim.keymap
-
-local hlslens = require("hlslens")
-
-hlslens.setup {
- calm_down = true,
- nearest_only = true,
-}
-
-local activate_hlslens = function(direction)
- local cmd = string.format("normal! %s%szzzv", vim.v.count1, direction)
- local status, msg = pcall(vim.cmd, cmd)
-
- -- Deal with the case that there is no such pattern in current buffer.
- if not status then
- local start_idx, _ = string.find(msg, 'E486', 1, true)
- local msg_part = string.sub(msg, start_idx)
- api.nvim_err_writeln(msg_part)
- return
- end
-
- hlslens.start()
-end
-
-keymap.set("n", "n", "", {
- callback = function()
- activate_hlslens("n")
- end,
-})
-
-keymap.set("n", "N", "", {
- callback = function()
- activate_hlslens("N")
- end,
-})
-
-keymap.set("n", "*", "", {
- callback = function()
- vim.fn.execute("normal! *N")
- hlslens.start()
- end,
-})
-keymap.set("n", "#", "", {
- callback = function()
- vim.fn.execute("normal! #N")
- hlslens.start()
- end,
-})
diff --git a/lua/config/iron.lua b/lua/config/iron.lua
deleted file mode 100644
index 67f5d81..0000000
--- a/lua/config/iron.lua
+++ /dev/null
@@ -1,7 +0,0 @@
-local iron = require("iron")
-iron.core.set_config {
- preferred = {
- python = "ipython",
- },
- repl_open_cmd = "vertical 120 split",
-}
diff --git a/lua/config/lsp.lua b/lua/config/lsp.lua
deleted file mode 100644
index 7c6fb79..0000000
--- a/lua/config/lsp.lua
+++ /dev/null
@@ -1,273 +0,0 @@
-local fn = vim.fn
-local api = vim.api
-local keymap = vim.keymap
-local lsp = vim.lsp
-local diagnostic = vim.diagnostic
-
-local utils = require("utils")
-
--- set quickfix list from diagnostics in a certain buffer, not the whole workspace
-local set_qflist = function(buf_num, severity)
- local diagnostics = nil
- diagnostics = diagnostic.get(buf_num, { severity = severity })
-
- local qf_items = diagnostic.toqflist(diagnostics)
- vim.fn.setqflist({}, ' ', { title = 'Diagnostics', items = qf_items })
-
- -- open quickfix by default
- vim.cmd[[copen]]
-end
-
-local custom_attach = function(client, bufnr)
- -- Mappings.
- local map = function(mode, l, r, opts)
- opts = opts or {}
- opts.silent = true
- opts.buffer = bufnr
- keymap.set(mode, l, r, opts)
- end
-
- map("n", "gd", vim.lsp.buf.definition, { desc = "go to definition" })
- map("n", "<C-]>", vim.lsp.buf.definition)
- map("n", "K", vim.lsp.buf.hover)
- map("n", "<C-k>", vim.lsp.buf.signature_help)
- map("n", "<space>rn", vim.lsp.buf.rename, { desc = "varialbe rename" })
- map("n", "gr", vim.lsp.buf.references, { desc = "show references" })
- map("n", "[d", diagnostic.goto_prev, { desc = "previous diagnostic" })
- map("n", "]d", diagnostic.goto_next, { desc = "next diagnostic" })
- -- this puts diagnostics from opened files to quickfix
- map("n", "<space>qw", diagnostic.setqflist, { desc = "put window diagnostics to qf" })
- -- this puts diagnostics from current buffer to quickfix
- map("n", "<space>qb", function() set_qflist(bufnr) end, { desc = "put buffer diagnostics to qf" })
- map("n", "<space>ca", vim.lsp.buf.code_action, { desc = "LSP code action" })
- map("n", "<space>wa", vim.lsp.buf.add_workspace_folder, { desc = "add workspace folder" })
- map("n", "<space>wr", vim.lsp.buf.remove_workspace_folder, { desc = "remove workspace folder" })
- map("n", "<space>wl", function()
- inspect(vim.lsp.buf.list_workspace_folders())
- end, { desc = "list workspace folder" })
-
- -- Set some key bindings conditional on server capabilities
- if client.server_capabilities.documentFormattingProvider then
- map("n", "<space>f", vim.lsp.buf.format, { desc = "format code" })
- end
-
- api.nvim_create_autocmd("CursorHold", {
- buffer = bufnr,
- callback = function()
- local float_opts = {
- focusable = false,
- close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
- border = "rounded",
- source = "always", -- show source in diagnostic popup window
- prefix = " ",
- }
-
- if not vim.b.diagnostics_pos then
- vim.b.diagnostics_pos = { nil, nil }
- end
-
- local cursor_pos = api.nvim_win_get_cursor(0)
- if (cursor_pos[1] ~= vim.b.diagnostics_pos[1] or cursor_pos[2] ~= vim.b.diagnostics_pos[2])
- and #diagnostic.get() > 0
- then
- diagnostic.open_float(nil, float_opts)
- end
-
- vim.b.diagnostics_pos = cursor_pos
- end,
- })
-
- -- The blow command will highlight the current variable and its usages in the buffer.
- if client.server_capabilities.documentHighlightProvider then
- vim.cmd([[
- hi! link LspReferenceRead Visual
- hi! link LspReferenceText Visual
- hi! link LspReferenceWrite Visual
- ]])
-
- local gid = api.nvim_create_augroup("lsp_document_highlight", { clear = true })
- api.nvim_create_autocmd("CursorHold" , {
- group = gid,
- buffer = bufnr,
- callback = function ()
- lsp.buf.document_highlight()
- end
- })
-
- api.nvim_create_autocmd("CursorMoved" , {
- group = gid,
- buffer = bufnr,
- callback = function ()
- lsp.buf.clear_references()
- end
- })
- end
-
- if vim.g.logging_level == "debug" then
- local msg = string.format("Language server %s started!", client.name)
- vim.notify(msg, vim.log.levels.DEBUG, { title = "Nvim-config" })
- end
-end
-
-local capabilities = require('cmp_nvim_lsp').default_capabilities()
-
-local lspconfig = require("lspconfig")
-
-if utils.executable("pylsp") then
- local venv_path = os.getenv('VIRTUAL_ENV')
- local py_path = nil
- -- decide which python executable to use for mypy
- if venv_path ~= nil then
- py_path = venv_path .. "/bin/python3"
- else
- py_path = vim.g.python3_host_prog
- end
-
- lspconfig.pylsp.setup {
- on_attach = custom_attach,
- settings = {
- pylsp = {
- plugins = {
- -- formatter options
- black = { enabled = true },
- autopep8 = { enabled = false },
- yapf = { enabled = false },
- -- linter options
- pylint = { enabled = true, executable = "pylint" },
- ruff = { enabled = false },
- pyflakes = { enabled = false },
- pycodestyle = { enabled = false },
- -- type checker
- pylsp_mypy = {
- enabled = true,
- overrides = { "--python-executable", py_path, true },
- report_progress = true,
- live_mode = false
- },
- -- auto-completion options
- jedi_completion = { fuzzy = true },
- -- import sorting
- isort = { enabled = true },
- },
- },
- },
- flags = {
- debounce_text_changes = 200,
- },
- capabilities = capabilities,
- }
-else
- vim.notify("pylsp not found!", vim.log.levels.WARN, { title = "Nvim-config" })
-end
-
--- if utils.executable('pyright') then
--- lspconfig.pyright.setup{
--- on_attach = custom_attach,
--- capabilities = capabilities
--- }
--- else
--- vim.notify("pyright not found!", vim.log.levels.WARN, {title = 'Nvim-config'})
--- end
-
-if utils.executable("ltex-ls") then
- lspconfig.ltex.setup {
- on_attach = custom_attach,
- cmd = { "ltex-ls" },
- filetypes = { "text", "plaintex", "tex", "markdown" },
- settings = {
- ltex = {
- language = "en"
- },
- },
- flags = { debounce_text_changes = 300 },
-}
-end
-
-if utils.executable("clangd") then
- lspconfig.clangd.setup {
- on_attach = custom_attach,
- capabilities = capabilities,
- filetypes = { "c", "cpp", "cc" },
- flags = {
- debounce_text_changes = 500,
- },
- }
-end
-
--- set up vim-language-server
-if utils.executable("vim-language-server") then
- lspconfig.vimls.setup {
- on_attach = custom_attach,
- flags = {
- debounce_text_changes = 500,
- },
- capabilities = capabilities,
- }
-else
- vim.notify("vim-language-server not found!", vim.log.levels.WARN, { title = "Nvim-config" })
-end
-
--- set up bash-language-server
-if utils.executable("bash-language-server") then
- lspconfig.bashls.setup {
- on_attach = custom_attach,
- capabilities = capabilities,
- }
-end
-
-if utils.executable("lua-language-server") then
- -- settings for lua-language-server can be found on https://github.com/LuaLS/lua-language-server/wiki/Settings .
- lspconfig.lua_ls.setup {
- on_attach = custom_attach,
- settings = {
- Lua = {
- runtime = {
- -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
- version = "LuaJIT",
- },
- diagnostics = {
- -- Get the language server to recognize the `vim` global
- globals = { "vim" },
- },
- workspace = {
- -- Make the server aware of Neovim runtime files,
- -- see also https://github.com/LuaLS/lua-language-server/wiki/Libraries#link-to-workspace .
- -- Lua-dev.nvim also has similar settings for lua ls, https://github.com/folke/neodev.nvim/blob/main/lua/neodev/luals.lua .
- library = {
- fn.stdpath("data") .. "/lazy/emmylua-nvim",
- fn.stdpath("config"),
- },
- maxPreload = 2000,
- preloadFileSize = 50000,
- },
- },
- },
- capabilities = capabilities,
- }
-end
-
--- Change diagnostic signs.
-fn.sign_define("DiagnosticSignError", { text = '🆇', texthl = "DiagnosticSignError" })
-fn.sign_define("DiagnosticSignWarn", { text = '⚠️', texthl = "DiagnosticSignWarn" })
-fn.sign_define("DiagnosticSignInfo", { text = 'ℹ️', texthl = "DiagnosticSignInfo" })
-fn.sign_define("DiagnosticSignHint", { text = '', texthl = "DiagnosticSignHint" })
-
--- global config for diagnostic
-diagnostic.config {
- underline = false,
- virtual_text = false,
- signs = true,
- severity_sort = true,
-}
-
--- lsp.handlers["textDocument/publishDiagnostics"] = lsp.with(lsp.diagnostic.on_publish_diagnostics, {
--- underline = false,
--- virtual_text = false,
--- signs = true,
--- update_in_insert = false,
--- })
-
--- Change border of documentation hover window, See https://github.com/neovim/neovim/pull/13998.
-lsp.handlers["textDocument/hover"] = lsp.with(vim.lsp.handlers.hover, {
- border = "rounded",
-})
diff --git a/lua/config/nvim-cmp.lua b/lua/config/nvim-cmp.lua
deleted file mode 100644
index a402f1c..0000000
--- a/lua/config/nvim-cmp.lua
+++ /dev/null
@@ -1,91 +0,0 @@
--- Setup nvim-cmp.
-local cmp = require("cmp")
-local lspkind = require("lspkind")
-
-cmp.setup {
- snippet = {
- expand = function(args)
- -- For `ultisnips` user.
- vim.fn["UltiSnips#Anon"](args.body)
- end,
- },
- mapping = cmp.mapping.preset.insert {
- ["<Tab>"] = function(fallback)
- if cmp.visible() then
- cmp.select_next_item()
- else
- fallback()
- end
- end,
- ["<S-Tab>"] = function(fallback)
- if cmp.visible() then
- cmp.select_prev_item()
- else
- fallback()
- end
- end,
- ["<CR>"] = cmp.mapping.confirm { select = true },
- ["<C-e>"] = cmp.mapping.abort(),
- ["<Esc>"] = cmp.mapping.close(),
- ["<C-d>"] = cmp.mapping.scroll_docs(-4),
- ["<C-f>"] = cmp.mapping.scroll_docs(4),
- },
- sources = {
- { name = "nvim_lsp" }, -- For nvim-lsp
- { name = "ultisnips" }, -- For ultisnips user.
- { name = "path" }, -- for path completion
- { name = "buffer", keyword_length = 2 }, -- for buffer word completion
- { name = "emoji", insert = true }, -- emoji completion
- },
- completion = {
- keyword_length = 1,
- completeopt = "menu,noselect",
- },
- view = {
- entries = "custom",
- },
- formatting = {
- format = lspkind.cmp_format {
- mode = "symbol_text",
- menu = {
- nvim_lsp = "[LSP]",
- ultisnips = "[US]",
- nvim_lua = "[Lua]",
- path = "[Path]",
- buffer = "[Buffer]",
- emoji = "[Emoji]",
- omni = "[Omni]",
- },
- },
- },
-}
-
-cmp.setup.filetype("tex", {
- sources = {
- { name = "omni" },
- { name = "ultisnips" }, -- For ultisnips user.
- { name = "buffer", keyword_length = 2 }, -- for buffer word completion
- { name = "path" }, -- for path completion
- },
-})
-
--- see https://github.com/hrsh7th/nvim-cmp/wiki/Menu-Appearance#how-to-add-visual-studio-code-dark-theme-colors-to-the-menu
-vim.cmd([[
- highlight! link CmpItemMenu Comment
- " gray
- highlight! CmpItemAbbrDeprecated guibg=NONE gui=strikethrough guifg=#808080
- " blue
- highlight! CmpItemAbbrMatch guibg=NONE guifg=#569CD6
- highlight! CmpItemAbbrMatchFuzzy guibg=NONE guifg=#569CD6
- " light blue
- highlight! CmpItemKindVariable guibg=NONE guifg=#9CDCFE
- highlight! CmpItemKindInterface guibg=NONE guifg=#9CDCFE
- highlight! CmpItemKindText guibg=NONE guifg=#9CDCFE
- " pink
- highlight! CmpItemKindFunction guibg=NONE guifg=#C586C0
- highlight! CmpItemKindMethod guibg=NONE guifg=#C586C0
- " front
- highlight! CmpItemKindKeyword guibg=NONE guifg=#D4D4D4
- highlight! CmpItemKindProperty guibg=NONE guifg=#D4D4D4
- highlight! CmpItemKindUnit guibg=NONE guifg=#D4D4D4
-]])
diff --git a/lua/config/nvim-notify.lua b/lua/config/nvim-notify.lua
deleted file mode 100644
index 4fcd02e..0000000
--- a/lua/config/nvim-notify.lua
+++ /dev/null
@@ -1,10 +0,0 @@
-local nvim_notify = require("notify")
-nvim_notify.setup {
- -- Animation style
- stages = "fade_in_slide_out",
- -- Default timeout for notifications
- timeout = 1500,
- background_colour = "#2E3440",
-}
-
-vim.notify = nvim_notify
diff --git a/lua/config/nvim_hop.lua b/lua/config/nvim_hop.lua
deleted file mode 100644
index 4530edf..0000000
--- a/lua/config/nvim_hop.lua
+++ /dev/null
@@ -1,27 +0,0 @@
-local keymap = vim.keymap
-local hop = require("hop")
-hop.setup {
- case_insensitive = true,
- char2_fallback_key = "<CR>",
- quit_key = "<Esc>",
-}
-
-keymap.set({ "n", "v", "o" }, "f", "", {
- silent = true,
- noremap = true,
- callback = function()
- hop.hint_char2()
- end,
- desc = "nvim-hop char2",
-})
-
-vim.api.nvim_create_autocmd("ColorScheme", {
- pattern = "*",
- callback = function ()
- vim.cmd([[
- hi HopNextKey cterm=bold ctermfg=176 gui=bold guibg=#ff00ff guifg=#ffffff
- hi HopNextKey1 cterm=bold ctermfg=176 gui=bold guibg=#ff00ff guifg=#ffffff
- hi HopNextKey2 cterm=bold ctermfg=176 gui=bold guibg=#ff00ff guifg=#ffffff
- ]])
- end
-})
diff --git a/lua/config/treesitter.lua b/lua/config/treesitter.lua
deleted file mode 100644
index 4111859..0000000
--- a/lua/config/treesitter.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-require("nvim-treesitter.configs").setup {
- ensure_installed = { "python", "cpp", "lua", "vim", "json", "toml" },
- ignore_install = {}, -- List of parsers to ignore installing
- highlight = {
- enable = true, -- false will disable the whole extension
- disable = { 'help' }, -- list of language that will be disabled
- },
-}
diff --git a/lua/config/which-key.lua b/lua/config/which-key.lua
deleted file mode 100644
index 10c0c41..0000000
--- a/lua/config/which-key.lua
+++ /dev/null
@@ -1,60 +0,0 @@
-require("which-key").setup {
- plugins = {
- marks = true, -- shows a list of your marks on ' and `
- registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
- spelling = {
- enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions
- suggestions = 9, -- how many suggestions should be shown in the list?
- },
- -- the presets plugin, adds help for a bunch of default keybindings in Neovim
- -- No actual key bindings are created
- presets = {
- operators = true, -- adds help for operators like d, y, ... and registers them for motion / text object completion
- motions = true, -- adds help for motions
- text_objects = true, -- help for text objects triggered after entering an operator
- windows = true, -- default bindings on <c-w>
- nav = true, -- misc bindings to work with windows
- z = true, -- bindings for folds, spelling and others prefixed with z
- g = true, -- bindings for prefixed with g
- },
- },
- -- add operators that will trigger motion and text object completion
- -- to enable all native operators, set the preset / operators plugin above
- operators = { gc = "Comments" },
- key_labels = {
- -- override the label used to display some keys. It doesn't effect WK in any other way.
- -- For example:
- -- ["<space>"] = "SPC",
- -- ["<cr>"] = "RET",
- -- ["<tab>"] = "TAB",
- },
- icons = {
- breadcrumb = "»", -- symbol used in the command line area that shows your active key combo
- separator = "➜", -- symbol used between a key and it's label
- group = "+", -- symbol prepended to a group
- },
- window = {
- border = "none", -- none, single, double, shadow
- position = "bottom", -- bottom, top
- margin = { 0, 0, 0, 0 }, -- extra window margin [top, right, bottom, left]
- padding = { 1, 0, 1, 0 }, -- extra window padding [top, right, bottom, left]
- },
- layout = {
- height = { min = 1, max = 25 }, -- min and max height of the columns
- width = { min = 20, max = 50 }, -- min and max width of the columns
- spacing = 1, -- spacing between columns
- align = "center", -- align columns left, center or right
- },
- ignore_missing = false, -- enable this to hide mappings for which you didn't specify a label
- hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate
- show_help = true, -- show help message on the command line when the popup is visible
- triggers = "auto", -- automatically setup triggers
- -- triggers = {"<leader>"} -- or specify a list manually
-
- triggers_blacklist = {
- -- list of mode / prefixes that should never be hooked by WhichKey
- -- this is mostly relevant for key maps that start with a native binding
- -- most people should not need to change this
- n = { "o", "O" },
- },
-}
diff --git a/lua/config/yanky.lua b/lua/config/yanky.lua
deleted file mode 100644
index 0f8eceb..0000000
--- a/lua/config/yanky.lua
+++ /dev/null
@@ -1,13 +0,0 @@
-require("yanky").setup({
- ring = {
- history_length = 50,
- storage = "memory",
- },
- preserve_cursor_position = {
- enabled = false,
- },
-})
-
--- cycle through the yank history, only work after paste
-vim.keymap.set("n", "[y", "<Plug>(YankyCycleForward)")
-vim.keymap.set("n", "]y", "<Plug>(YankyCycleBackward)")
diff --git a/lua/config/zen-mode.lua b/lua/config/zen-mode.lua
deleted file mode 100644
index b6d52ce..0000000
--- a/lua/config/zen-mode.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-require("zen-mode").setup {
- window = {
- backdrop = 0.8, -- shade the backdrop of the Zen window. Set to 1 to keep the same as Normal
- width = 120,
- options = {
- -- signcolumn = "no", -- disable signcolumn
- -- number = false, -- disable number column
- -- relativenumber = false, -- disable relative numbers
- cursorline = false, -- disable cursorline
- cursorcolumn = false, -- disable cursor column
- foldcolumn = "0", -- disable fold column
- list = false, -- disable whitespace characters
- },
- },
-}
diff --git a/lua/globals.lua b/lua/globals.lua
deleted file mode 100644
index b0af26e..0000000
--- a/lua/globals.lua
+++ /dev/null
@@ -1,75 +0,0 @@
-local fn = vim.fn
-local api = vim.api
-
-local utils = require('utils')
-
--- Inspect something
-function _G.inspect(item)
- vim.print(item)
-end
-
-------------------------------------------------------------------------
--- custom variables --
-------------------------------------------------------------------------
-vim.g.is_win = (utils.has("win32") or utils.has("win64")) and true or false
-vim.g.is_linux = (utils.has("unix") and (not utils.has("macunix"))) and true or false
-vim.g.is_mac = utils.has("macunix") and true or false
-
-vim.g.logging_level = "info"
-
-------------------------------------------------------------------------
--- builtin variables --
-------------------------------------------------------------------------
-vim.g.loaded_perl_provider = 0 -- Disable perl provider
-vim.g.loaded_ruby_provider = 0 -- Disable ruby provider
-vim.g.loaded_node_provider = 0 -- Disable node provider
-vim.g.did_install_default_menus = 1 -- do not load menu
-
-if utils.executable('python3') then
- if vim.g.is_win then
- vim.g.python3_host_prog = fn.substitute(fn.exepath("python3"), ".exe$", '', 'g')
- else
- vim.g.python3_host_prog = fn.exepath("python3")
- end
-else
- api.nvim_err_writeln("Python3 executable not found! You must install Python3 and set its PATH correctly!")
- return
-end
-
--- Custom mapping <leader> (see `:h mapleader` for more info)
-vim.g.mapleader = ','
-
--- Enable highlighting for lua HERE doc inside vim script
-vim.g.vimsyn_embed = 'l'
-
--- Use English as main language
-vim.cmd [[language en_US.UTF-8]]
-
--- Disable loading certain plugins
-
--- Whether to load netrw by default, see https://github.com/bling/dotvim/issues/4
-vim.g.loaded_netrw = 1
-vim.g.loaded_netrwPlugin = 1
-vim.g.netrw_liststyle = 3
-if vim.g.is_win then
- vim.g.netrw_http_cmd = "curl --ssl-no-revoke -Lo"
-end
-
--- Do not load tohtml.vim
-vim.g.loaded_2html_plugin = 1
-
--- Do not load zipPlugin.vim, gzip.vim and tarPlugin.vim (all these plugins are
--- related to checking files inside compressed files)
-vim.g.loaded_zipPlugin = 1
-vim.g.loaded_gzip = 1
-vim.g.loaded_tarPlugin = 1
-
--- Do not load the tutor plugin
-vim.g.loaded_tutor_mode_plugin = 1
-
--- Do not use builtin matchit.vim and matchparen.vim since we use vim-matchup
-vim.g.loaded_matchit = 1
-vim.g.loaded_matchparen = 1
-
--- Disable sql omni completion, it is broken.
-vim.g.loaded_sql_completion = 1
diff --git a/lua/utils.lua b/lua/utils.lua
deleted file mode 100644
index fef4178..0000000
--- a/lua/utils.lua
+++ /dev/null
@@ -1,59 +0,0 @@
-local fn = vim.fn
-
-local M = {}
-
-function M.executable(name)
- if fn.executable(name) > 0 then
- return true
- end
-
- return false
-end
-
---- check whether a feature exists in Nvim
---- @feat: string
---- the feature name, like `nvim-0.7` or `unix`.
---- return: bool
-M.has = function(feat)
- if fn.has(feat) == 1 then
- return true
- end
-
- return false
-end
-
---- Create a dir if it does not exist
-function M.may_create_dir(dir)
- local res = fn.isdirectory(dir)
-
- if res == 0 then
- fn.mkdir(dir, "p")
- end
-end
-
---- Generate random integers in the range [Low, High], inclusive,
---- adapted from https://stackoverflow.com/a/12739441/6064933
---- @low: the lower value for this range
---- @high: the upper value for this range
-function M.rand_int(low, high)
- -- Use lua to generate random int, see also: https://stackoverflow.com/a/20157671/6064933
- math.randomseed(os.time())
-
- return math.random(low, high)
-end
-
---- Select a random element from a sequence/list.
---- @seq: the sequence to choose an element
-function M.rand_element(seq)
- local idx = M.rand_int(1, #seq)
-
- return seq[idx]
-end
-
-function M.add_pack(name)
- local status, error = pcall(vim.cmd, "packadd " .. name)
-
- return status
-end
-
-return M
diff --git a/my_snippets/all.snippets b/my_snippets/all.snippets
deleted file mode 100644
index efe5ada..0000000
--- a/my_snippets/all.snippets
+++ /dev/null
@@ -1,7 +0,0 @@
-snippet "(?<!\w)ltx" "LaTeX symbol" r
-LaTeX
-endsnippet
-
-snippet arw "Right-pointed arrow"
---> $1
-endsnippet
diff --git a/my_snippets/cpp.snippets b/my_snippets/cpp.snippets
deleted file mode 100644
index 148c8d0..0000000
--- a/my_snippets/cpp.snippets
+++ /dev/null
@@ -1,187 +0,0 @@
-snippet bare "barebone code template"
-#include <iostream>
-#include <vector>
-#include <string>
-#include <map>
-#include <unordered_map>
-#include <set>
-#include <unordered_set>
-#include <stack>
-#include <queue>
-#include <numeric>
-
-using std::cout;
-using std::endl;
-using std::vector;
-using std::string;
-using std::map;
-using std::unordered_map;
-using std::set;
-using std::unordered_set;
-using std::stack;
-using std::queue;
-using std::pair;
-using std::make_pair;
-
-
-
-int main()
-{
-
- return 0;
-}
-endsnippet
-
-snippet icd "#include directive" b
-#include <$1>
-$0
-endsnippet
-
-snippet plist "print vector" w
-template <class T>
-void printList(const T& arr, const string& desc){
- std::cout << desc << ": [";
-
- for (auto it = arr.begin(); it != arr.end(); it++){
- std::cout << *it << ((std::next(it) != arr.end()) ? ", " : "");
- }
- std::cout << "]\n";
-}
-endsnippet
-
-snippet pmat "print list of list" w
-template <class T>
-void printMat(const vector<vector<T>>& mat, const string& desc){
- cout << desc << ": " << endl;
-
- for (auto it1 = mat.begin(); it1 != mat.end(); it1++){
- auto cur_vec = *it1;
- cout << "[";
- for (auto it2 = cur_vec.begin(); it2 != cur_vec.end(); it2++){
- cout << *it2 << ((std::next(it2) != cur_vec.end()) ? ", " : "]\n");
- }
- }
-}
-endsnippet
-
-snippet pqueue "print queue"
-template <class T>
-void printQueue(T q){
- while(!q.empty()){
- std::cout << q.top() << " ";
- q.pop();
- }
- std::cout << '\n';
-}
-endsnippet
-
-snippet cout "print a variable" w
-cout << "$1: " << $2 << endl;
-endsnippet
-
-snippet random "Generate a random list" b
-// Generate a random sequence of length len, in range(low, high) (inclusive).
-// need to #include<random>
-vector<int> genRandom(int low, int high, int len){
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<int> distribution(low, high);
-
- vector<int> arr(len, 0);
- for (int i = 0; i != len; ++i){
- arr[i] = distribution(gen);
- }
-
- return arr;
-}
-endsnippet
-
-snippet incset "Use set" b
-#include <set>
-
-using std::set;
-endsnippet
-
-snippet incmap "Use map" b
-#include <map>
-
-using std::map;
-endsnippet
-
-snippet incqueue "Use queue" b
-#include <queue>
-
-using std::queue;
-endsnippet
-
-snippet incstr "Use string" b
-#include <string>
-
-using std::string;
-endsnippet
-
-snippet incvec "Use vector" b
-#include <vector>
-
-using std::vector;
-endsnippet
-
-snippet incstack "Use stack" b
-#include <stack>
-
-using std::stack;
-endsnippet
-
-snippet vec "std::vector" w
-vector<$1> ${2:vec}
-endsnippet
-
-snippet map "std::map" w
-map<$1, $2> ${3:mymap}
-endsnippet
-
-snippet umap "std::unordered_map"
-unordered_map<$1, $2> ${3:mymap}
-endsnippet
-
-snippet set "std::set" w
-set<$1> ${2:myset}
-endsnippet
-
-snippet uset "std::unordered_set" w
-unordered_set<$1> ${2:myset}
-endsnippet
-
-snippet queue "std::queue" w
-queue<$1> ${2:q}
-endsnippet
-
-snippet stack "std::stack" w
-stack<$1> ${2:mystack}
-endsnippet
-
-snippet sol "solution" w
-auto solution = Solution();
-$0
-endsnippet
-
-snippet for "for loop" w
-for ($1; $2; $3){
- $4
-}
-endsnippet
-
-snippet if "if condition" w
-if ($1){
- $2
-}
-$0
-endsnippet
-
-snippet ifelse "if else condition"
-if ($1){
- $2
-}else{
-
-}
-endsnippet
diff --git a/my_snippets/markdown.snippets b/my_snippets/markdown.snippets
deleted file mode 100644
index e00f538..0000000
--- a/my_snippets/markdown.snippets
+++ /dev/null
@@ -1,168 +0,0 @@
-global !p
-def gen_header(snip):
- placeholders_string = snip.buffer[snip.line].strip()
- level = int(placeholders_string[0])
-
- # erase current line
- snip.buffer[snip.line] = ""
- line_content = "#"*level + " ${1:Section Name}"
- line_content += '\n$0'
-
- snip.expand_anon(line_content)
-endglobal
-
-snippet "(k1|kbd)" "HTML kbd tag" rw
-<kbd>${1:KEY}</kbd>$0
-endsnippet
-
-snippet k2 "Two key strokes shortcut"
-<kbd>${1:KEY}</kbd> + <kbd>${2:KEY}</kbd>
-endsnippet
-
-snippet k3 "Three key strokes shortcut"
-<kbd>${1:KEY}</kbd> + <kbd>${2:KEY}</kbd> + <kbd>${3:KEY}</kbd>
-endsnippet
-
-snippet meta "Markdown front matter (YAML format)" b
----
-title: "$1"
-date: `!p from datetime import datetime
-if not snip.c:
- snip.rv=datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S%z")`
-tags: [$2]
-categories: [$3]
----
-$0
-endsnippet
-
-snippet more "HTML more tag"
-<!--more-->
-endsnippet
-
-snippet img "Aligned image using HTML tag"
-<p align="center">
-<img src="${1:URL}" width="${2:800}">
-</p>
-$0
-endsnippet
-
-snippet font "HTML font tag"
-<font color="${1:blue}">${2:TEXT}</font>
-endsnippet
-
-snippet link "Markdown links"
-[$1]($2)$0
-endsnippet
-
-post_jump "gen_header(snip)"
-snippet "h([1-6])" "Markdown header" br
-`!p snip.rv = match.group(1)`
-endsnippet
-
-snippet detail "Clickable details" b
-<details>
-<summary><font size="2" color="red">${1:Click to show the code.}</font></summary>
-
-$2
-</details>
-endsnippet
-
-snippet yh "直角引号" w
-「$1」
-endsnippet
-
-snippet info "info box"
-<style type="text/css">
-@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css');
-
-.info-msg {
- color: #059;
- background-color: #BEF;
- margin: 5px 0;
- margin-bottom: 20px;
- padding: 10px;
- border-radius: 5px 5px 5px 5px;
- border: 2px solid transparent;
- border-color: transparent;
-}
-</style>
-
-<div class="info-msg">
- <i class="fa fa-info-circle"> Info</i></br>
- ${1:info text}
-</div>
-$0
-endsnippet
-
-snippet warn "warning box"
-<style type="text/css">
-@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css');
-
-.warning-msg {
- color: #9F6000;
- background-color: #FEEFB3;
- margin: 5px 0;
- margin-bottom: 20px;
- padding: 10px;
- border-radius: 5px 5px 5px 5px;
- border: 2px solid transparent;
- border-color: transparent;
-}
-</style>
-
-<div class="warning-msg">
- <i class="fa fa-warning"> Warning</i></br>
- ${1:warning text}
-</div>
-$0
-endsnippet
-
-snippet error "error box"
-<style type="text/css">
-@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css');
-
-.error-msg {
- color: #D8000C;
- background-color: #FFBABA;
- margin: 5px 0;
- margin-bottom: 20px;
- padding: 10px;
- border-radius: 5px 5px 5px 5px;
- border: 2px solid transparent;
- border-color: transparent;
-}
-</style>
-
-<div class="error-msg">
- <i class="fa fa-times-circle"> Error</i></br>
- ${1:error text}
-</div>
-$0
-endsnippet
-
-snippet success "success box"
-<style type="text/css">
-@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css');
-
-.success-msg {
- color: #270;
- background-color: #DFF2BF;
- margin: 5px 0;
- margin-bottom: 20px;
- padding: 10px;
- border-radius: 5px 5px 5px 5px;
- border: 2px solid transparent;
- border-color: transparent;
-}
-</style>
-
-<div class="success-msg">
- <i class="fa fa-check"></i>
- ${1:success text}
-</div>
-$0
-endsnippet
-
-snippet td "too long do not read" bw
-tl;dr: $1
-endsnippet
diff --git a/my_snippets/python.snippets b/my_snippets/python.snippets
deleted file mode 100644
index fc3f355..0000000
--- a/my_snippets/python.snippets
+++ /dev/null
@@ -1,30 +0,0 @@
-snippet head "Python source file header" b
-"""
-Description: $1
-Author: Jie-dong Hao (jdhao@hotmail.com)
-Created: `!v strftime("%Y-%m-%d %H:%M:%S%z")`
-"""
-$0
-endsnippet
-
-snippet print "Print value of some variable"
-print("$1".format($2))
-$0
-endsnippet
-
-snippet impa "import FOO as BAR" b
-import ${1:FOO} as ${2:BAR}
-endsnippet
-
-snippet main "Main function boilerplate" b
-def main():
- $0
-
-
-if __name__ == "__main__":
- main()
-endsnippet
-
-snippet sol "solution" b
-solution = Solution()
-endsnippet
diff --git a/my_snippets/snippets.snippets b/my_snippets/snippets.snippets
deleted file mode 100644
index 5473902..0000000
--- a/my_snippets/snippets.snippets
+++ /dev/null
@@ -1,6 +0,0 @@
-# copied from https://github.com/honza/vim-snippets/blob/master/UltiSnips/snippets.snippets
-snippet snip "Ultisnips snippet definition" b
-`!p snip.rv = "snippet"` ${1:Tab_trigger} "${2:Description}" ${3:b}
-${0:${VISUAL}}
-`!p snip.rv = "endsnippet"`
-endsnippet
diff --git a/my_snippets/tex.snippets b/my_snippets/tex.snippets
deleted file mode 100644
index 3b979f3..0000000
--- a/my_snippets/tex.snippets
+++ /dev/null
@@ -1,9 +0,0 @@
-snippet use "usepackage" b
-\usepackage{${1:package}}
-endsnippet
-
-snippet eqa "equation environment" b
-\begin{equation}\label{$1}
- $2
-\end{equation}
-endsnippet
diff --git a/my_snippets/vim.snippets b/my_snippets/vim.snippets
deleted file mode 100644
index a2e0d3c..0000000
--- a/my_snippets/vim.snippets
+++ /dev/null
@@ -1,14 +0,0 @@
-snippet fun "vim function"
-function! ${1:MyFunc}(${2}) abort
- $3
-endfunction
-$0
-endsnippet
-
-snippet aug "vim augroup" b
-augroup ${1:GROUP_NAME}
- autocmd!
- autocmd ${2:EVENT} ${3:PATTERN} $4
-augroup END
-$0
-endsnippet
diff --git a/plugged/goyo.vim b/plugged/goyo.vim
new file mode 160000
+Subproject fa0263d456dd43f5926484d1c4c7022dfcb21ba
diff --git a/plugged/nerdtree b/plugged/nerdtree
new file mode 160000
+Subproject 32168889bdbc1e7d1d313e3e41c1cc794b38eac
diff --git a/plugged/vim-airline b/plugged/vim-airline
new file mode 160000
+Subproject e6bb8427dc2d2dc3583ed1bf5ff6a9682c854d3
diff --git a/plugged/vim-commentary b/plugged/vim-commentary
new file mode 160000
+Subproject e87cd90dc09c2a203e13af9704bd0ef79303d75
diff --git a/plugged/vim-css-color b/plugged/vim-css-color
new file mode 160000
+Subproject 6cc65734bc7105d9677ca54e2255fcbc953ba6b
diff --git a/plugged/vim-surround b/plugged/vim-surround
new file mode 160000
+Subproject 3d188ed2113431cf8dac77be61b842acb64433d
diff --git a/plugged/vimagit b/plugged/vimagit
new file mode 160000
+Subproject 308650ddc1e9a94e49fae0ea04bbc1c45f23d4c
diff --git a/plugged/vimwiki b/plugged/vimwiki
new file mode 160000
+Subproject f0fe154ede6b11e3db9b058b930005a056a3d1c
diff --git a/plugin/abbrev.vim b/plugin/abbrev.vim
deleted file mode 100644
index 034a7c0..0000000
--- a/plugin/abbrev.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-" some abbreviations
-iabbrev reqire require
-iabbrev serveral several
diff --git a/plugin/command.vim b/plugin/command.vim
deleted file mode 100644
index 68b11f4..0000000
--- a/plugin/command.vim
+++ /dev/null
@@ -1,50 +0,0 @@
-" Capture output from a command to register @m, to paste, press "mp
-command! -nargs=1 -complete=command Redir call utils#CaptureCommandOutput(<q-args>)
-
-command! -bar -bang -nargs=+ -complete=file Edit call utils#MultiEdit([<f-args>])
-call utils#Cabbrev('edit', 'Edit')
-
-call utils#Cabbrev('man', 'Man')
-
-" show current date and time in human readable format
-command! -nargs=? Datetime echo utils#iso_time(<q-args>)
-
-" Convert Markdown file to PDF
-command! ToPDF call s:md_to_pdf()
-
-function! s:md_to_pdf() abort
- " check if pandoc is installed
- if executable('pandoc') != 1
- echoerr "pandoc not found"
- return
- endif
-
- let l:md_path = expand("%:p")
- let l:pdf_path = fnamemodify(l:md_path, ":r") .. ".pdf"
-
- let l:header_path = stdpath('config') . '/resources/head.tex'
-
- let l:cmd = "pandoc --pdf-engine=xelatex --highlight-style=zenburn --table-of-content " .
- \ "--include-in-header=" . l:header_path . " -V fontsize=10pt -V colorlinks -V toccolor=NavyBlue " .
- \ "-V linkcolor=red -V urlcolor=teal -V filecolor=magenta -s " .
- \ l:md_path . " -o " . l:pdf_path
-
- if g:is_mac
- let l:cmd = l:cmd . '&& open ' . l:pdf_path
- endif
-
- if g:is_win
- let l:cmd = l:cmd . '&& start ' . l:pdf_path
- endif
-
- " echomsg l:cmd
-
- let l:id = jobstart(l:cmd)
-
- if l:id == 0 || l:id == -1
- echoerr "Error running command"
- endif
-endfunction
-
-" json format
-command! -range JSONFormat <line1>,<line2>!python -m json.tool
diff --git a/plugin/log-autocmds.vim b/plugin/log-autocmds.vim
deleted file mode 100644
index 0b2b489..0000000
--- a/plugin/log-autocmds.vim
+++ /dev/null
@@ -1,119 +0,0 @@
-command! LogAutocmds call s:log_autocmds_toggle()
-
-function! s:log_autocmds_toggle()
- augroup LogAutocmd
- autocmd!
- augroup END
-
- let l:date = strftime('%F', localtime())
- let s:activate = get(s:, 'activate', 0) ? 0 : 1
- if !s:activate
- call s:log('Stopped autocmd log (' . l:date . ')')
- return
- endif
-
- call s:log('Started autocmd log (' . l:date . ')')
- augroup LogAutocmd
- for l:au in s:aulist
- silent execute 'autocmd' l:au '* call s:log(''' . l:au . ''')'
- endfor
- augroup END
-endfunction
-
-function! s:log(message)
- silent execute '!echo "'
- \ . strftime('%T', localtime()) . ' - ' . a:message . '"'
- \ '>> /tmp/vim_log_autocommands'
-endfunction
-
-" These are deliberately left out due to side effects
-" - SourceCmd
-" - FileAppendCmd
-" - FileWriteCmd
-" - BufWriteCmd
-" - FileReadCmd
-" - BufReadCmd
-" - FuncUndefined
-
-let s:aulist = [
- \ 'BufNewFile',
- \ 'BufReadPre',
- \ 'BufRead',
- \ 'BufReadPost',
- \ 'FileReadPre',
- \ 'FileReadPost',
- \ 'FilterReadPre',
- \ 'FilterReadPost',
- \ 'StdinReadPre',
- \ 'StdinReadPost',
- \ 'BufWrite',
- \ 'BufWritePre',
- \ 'BufWritePost',
- \ 'FileWritePre',
- \ 'FileWritePost',
- \ 'FileAppendPre',
- \ 'FileAppendPost',
- \ 'FilterWritePre',
- \ 'FilterWritePost',
- \ 'BufAdd',
- \ 'BufCreate',
- \ 'BufDelete',
- \ 'BufWipeout',
- \ 'BufFilePre',
- \ 'BufFilePost',
- \ 'BufEnter',
- \ 'BufLeave',
- \ 'BufWinEnter',
- \ 'BufWinLeave',
- \ 'BufUnload',
- \ 'BufHidden',
- \ 'BufNew',
- \ 'SwapExists',
- \ 'FileType',
- \ 'Syntax',
- \ 'EncodingChanged',
- \ 'TermChanged',
- \ 'VimEnter',
- \ 'GUIEnter',
- \ 'GUIFailed',
- \ 'TermResponse',
- \ 'QuitPre',
- \ 'VimLeavePre',
- \ 'VimLeave',
- \ 'FileChangedShell',
- \ 'FileChangedShellPost',
- \ 'FileChangedRO',
- \ 'ShellCmdPost',
- \ 'ShellFilterPost',
- \ 'CmdUndefined',
- \ 'SpellFileMissing',
- \ 'SourcePre',
- \ 'VimResized',
- \ 'FocusGained',
- \ 'FocusLost',
- \ 'CursorHold',
- \ 'CursorHoldI',
- \ 'CursorMoved',
- \ 'CursorMovedI',
- \ 'WinEnter',
- \ 'WinLeave',
- \ 'TabEnter',
- \ 'TabLeave',
- \ 'CmdwinEnter',
- \ 'CmdwinLeave',
- \ 'InsertEnter',
- \ 'InsertChange',
- \ 'InsertLeave',
- \ 'InsertCharPre',
- \ 'TextChanged',
- \ 'TextChangedI',
- \ 'ColorScheme',
- \ 'RemoteReply',
- \ 'QuickFixCmdPre',
- \ 'QuickFixCmdPost',
- \ 'SessionLoadPost',
- \ 'MenuPopup',
- \ 'CompleteDone',
- \ 'User',
- \ ]
-
diff --git a/resources/head.tex b/resources/head.tex
deleted file mode 100644
index 3086798..0000000
--- a/resources/head.tex
+++ /dev/null
@@ -1,78 +0,0 @@
-\usepackage{fancyvrb,newverbs}
-\usepackage[top=2cm, bottom=1.5cm, left=2cm, right=2cm]{geometry}
-
-\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}
-\usepackage{hyperref}
-
-% begin a new page for each section (first level header),
-% we need to combine this with `-V subparagraph` when invoking pandc
-% \usepackage{titlesec}
-% \newcommand{\sectionbreak}{\clearpage}
-
-% change background color for inline code in markdown files.
-% The following code does not work well for long text, because the text will exceed the page boundary.
-\definecolor{bgcolor}{HTML}{DADADA}
-\let\oldtexttt\texttt
-
-\renewcommand{\texttt}[1]{
- \colorbox{bgcolor}{\oldtexttt{#1}}
-}
-
-% change style of quote, see also https://tex.stackexchange.com/a/436253/114857
-\usepackage[most]{tcolorbox}
-
-\definecolor{linequote}{RGB}{224,215,188}
-\definecolor{backquote}{RGB}{249,245,233}
-\definecolor{bordercolor}{RGB}{221,221,221}
-
-% change left border: https://tex.stackexchange.com/a/475716/114857
-% change left margin: https://tex.stackexchange.com/a/457936/114857
-\newtcolorbox{myquote}[1][]{%
- enhanced,
- breakable,
- size=minimal,
- left=10pt,
- top=5pt,
- bottom=5pt,
- frame hidden,
- boxrule=0pt,
- sharp corners=all,
- colback=backquote,
- borderline west={2pt}{0pt}{bordercolor},
- #1
-}
-
-% redefine quote environment to use the myquote environment, see https://tex.stackexchange.com/a/337587/114857
-\renewenvironment{quote}{\begin{myquote}}{\end{myquote}}
-
-% start a new page after toc, we need to save the old command before defining
-% new one to avoid recursive command calls,
-% see https://tex.stackexchange.com/questions/47351/can-i-redefine-a-command-to-contain-itself
-\let\oldtoc\tableofcontents
-\renewcommand{\tableofcontents}{\oldtoc\newpage}
-
-% fix header level issue
-\usepackage{enumitem}
-\setlistdepth{9}
-
-\setlist[itemize,1]{label=$\bullet$}
-\setlist[itemize,2]{label=$\bullet$}
-\setlist[itemize,3]{label=$\bullet$}
-\setlist[itemize,4]{label=$\bullet$}
-\setlist[itemize,5]{label=$\bullet$}
-\setlist[itemize,6]{label=$\bullet$}
-\setlist[itemize,7]{label=$\bullet$}
-\setlist[itemize,8]{label=$\bullet$}
-\setlist[itemize,9]{label=$\bullet$}
-\renewlist{itemize}{itemize}{9}
-
-\setlist[enumerate,1]{label=$\arabic*.$}
-\setlist[enumerate,2]{label=$\alph*.$}
-\setlist[enumerate,3]{label=$\roman*.$}
-\setlist[enumerate,4]{label=$\arabic*.$}
-\setlist[enumerate,5]{label=$\alpha*$}
-\setlist[enumerate,6]{label=$\roman*.$}
-\setlist[enumerate,7]{label=$\arabic*.$}
-\setlist[enumerate,8]{label=$\alph*.$}
-\setlist[enumerate,9]{label=$\roman*.$}
-\renewlist{enumerate}{enumerate}{9}
diff --git a/spell/en.utf-8.add b/spell/en.utf-8.add
index 9767d50..69c8c1c 100644
--- a/spell/en.utf-8.add
+++ b/spell/en.utf-8.add
@@ -1,469 +1,28 @@
-AED
-API
-Autocommands
-BufRead
-Builtin
-Bézier
-CER
-CMD
-CentOS
-Cmder
-Ctrl
-DLL
-DT
-Deoplete
-Deteval
-Esc
-Exif
-Firefox
-Foxmail
-GPU
-GPUs
-GUIs
-GhostText
-GitHub
-HomeBrew
-ICCF
-ICDAR
-IDE
-IoU
-Iterm2
-JPEG
-JSON
-LSP
-Linters
-Listary
-MPI
-MXNet
-MacOS
-Matplotlib
-Neomake
-Nvim
-Numpy
-OpenCV
-PIL
-PNG
-POSIX
-Pandoc
-Plugin
-Plugins
-PowerShell
-PyTorch
-Pynvim
-RCTW
-Ripgrep
-TOC
-TensorFlow
-UI
-URLs
-Uber
-Ubuntu
-UltiSnips
-Ultisnips
-Unindent
-VOC
-VimConf
-WSL
-X11
-YouCompleteMe
-Zsh
-ack
-ag
-appimage
-autocommand
-autocommands
-autocompletion
-autoload
-backend
-backtick
-base64
-bashrc
-blog
-bruteforce
-builtin
-cmder
-colorscheme
-conda
-config
-configs
-css
-css_intro/!
-ctags
-deoplete
-dict
-diff
-dir
-docstrings
-emoji
-env
-epub
-favicon
-favicons
-filetype
-filetypes
-filetypes/!
-firenvim
-fontconfig
-fzf
-gcc
-grep
-gutentags
-homebrew
-horovod
-inline
-iterm2
-jedi
-jpg
-keras
-linters
-linting
-lookaround
-lookbehind
-lua
-macOS
-maskrcnn
-mergetools
-metadata
-mobi
-modeline
-modelines
-mouseless
-namespace
-ndarray
-neovim
-nerdtree
-nvim
-opentype
-pdflatex
-perl
-plugin
-plugins
-png
-popup
-pylint
-quickfix
-refractor
-regex
-repo
-rg
-ripgrep
-runtimepath
-smartphone
-solarized
-specicial/!
-statusline
-statuslines
-tabline
-tabstops
-tagbar
-terminfo
-tex
-textline
-tmux
-truetype
-uWSGI
-ultisnips
-uninstall
-usepackage
-uwsgi
-vimrc
-vimscript
-vimtex
-warmup
-wildmenu
-workflow
-wsltty
-zplug
-zsh
-zinit
-pycodestyle
-pep8
-pyflakes
-pyls
-flake8
-sbcl
-quicklisp
-REPL
-vlime
-Matplotlib's
-MiKTeX
-FontManager
-ttc
-xnoremap
-wiki
-backticks
-Reddit
-LeaderF
-tabpage
-ccls
-cmake
-LLVM
-llvm
-subsampling
-refactor
-colorschemes
-gruvbox8
-gruvbox
-Gruvbox
-monokai
-NeoSolarized
-FiraCode
-libc
-printf
-CMake
-lsp
-PPTX
-libreoffice
-PPT
-pptx
-pdf
-unoconv
-python3
-imagemagick
-ghostscript
-poppler
-Tqdm
-tqdm
-cmd
-ThreadPoolExecutor
-Cygwin
-mintty
-iTerm
-stdin
-unicode
-ClashX
-Qv2ray
-socks5
-v2ray
-V2Ray
-Dockerfile
-pip3
-dein
-pynvim
-iTerm2
-neoformat
-documentation/!
-documentation
-WSGI
-ncurses
-powerline
-repos
-hugo
-ZOC
-stackexchange
-https
-username
-url
-dev
-Miniconda
-Semshi
-Alacritty
-vim/!
-Vim/!
-Vim
-vim
-RPC
-SumatraPDF/!
-api
-YAML
-TOML
-pandoc
-textwidth
-bytecode
-CPython
-nohup
-stdout
-stderr
-UTC
-CJK
-numpy
-LibreOffice
-rebase
-rebasing
-glibc
-Clangd
-clangd
-cheatsheet
-redis
-Disqus
-submodules
-stackoverflow
-hostname
-strftime
-shiftwidth
-whitespace
-treesitter
-linter
-MySQL
-advocator
-Hexo
-pybind11
-OSC
-minpac
-ctrl
-IME
-emacs
-Elisp
-conf
-MELPA
-smartparens
-Tpope
-extmarks
-extmark
-CTAN
-MikTex/!
-MikTeX
-softwares/!
-Zong
-cjk
-backupcopy
-nowritebackup
-nvim's
-linux
-zshrc
-pdftoppm
-pdf2image
-pdffonts
-myers
-difftool
-vimdiff
-softmax
-lib64
-toolset
-sym
-ffmpeg
-PyAV
-mp4
-vint
-npm
-js
-sudo
-ps1
-tpm
-hacky
-PCRE
-teardown
-github
-fastgit
-EOL
-PyCharm
-deduplication
-STL
-delimitMate
-lspconfig
-lualine
-Keymap
-iCloud
-keyframe
-maskRCNN
-vundle
-ycm
-ftplugin
-vim9
-dotfile
-magit
-xelatex
-subarray
-fvim
-CUDA
-cuda
-cpu
-jdhao
-whitelisted
-BST
-autocmd
-init
-miniconda
-tsinghua
-pylsp
-mypy
-isort
-ustc
-PyTorch
-maxcdn
-torchvision
-FFmpeg
-pyav
-wezterm
-frac
-argmax
-NeruIPS
-InfoNCE
-LSTM
-linkedin
-hotmail
-datetime
-csv
-iterable
-dataframe
-CRNN
-ICPR
-matplotlib
-scikit
-NumPy
-cudnn
-SGD
-ImageNet
-ReLU
-CIFAR
-ResNet
-XGBoost
-Shenzhen
-Tanh
-Kaggle
-minist
-src
-RGBA
-yapf
-Vimming
-overfitting
-PCA
-SVM
-KNN
-leetcode
-Logitech
-WTF
-tensorboard
-Nvidia
-GPG
-manpage
-metatable
-open3d
-pyntcloud
-param
-reddit
-viml
-PostgreSQL
-CNY
-wechat
-ziroom
-Postgres
-plpgsql
-postgres
-PySpark
-winbar
-cmdline
-shada
-async
-localhost
-JetBrains
-localhost
-MariaDB
-SQLite
-Pgadmin
-Datagrip
-mysql
-cwd
-pyright
-stubgen
-pylance
-variadic
-Vimium
-Databricks
-Jira
-databricks
-FastAPI
-pylintrc
-PYTHONPATH
-Uvicorn
-qpdf
+DL
+E2E
+eMBB
+eSIM
+GNSS
+GPIO
+HRLLC
+I2C
+IoT
+LPWAN
+LTE
+mMTC
+MQTT
+PDM
+PIR
+PWM
+RTC
+SiP
+SMA
+SPI
+URLLC
+WDT
+FSPL
+Czechia
+Silesian
+GSM
+3GPP
+nRF9160