diff --git a/.vim/autoload/plug.vim b/.vim/autoload/plug.vim index a2e057f..8be364c 100644 --- a/.vim/autoload/plug.vim +++ b/.vim/autoload/plug.vim @@ -14,6 +14,9 @@ " Plug 'junegunn/seoul256.vim' " Plug 'junegunn/vim-easy-align' " +" " Group dependencies, vim-snippets depends on ultisnips +" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' +" " " On-demand loading " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } " Plug 'tpope/vim-fireplace', { 'for': 'clojure' } @@ -22,7 +25,7 @@ " Plug 'https://github.com/junegunn/vim-github-dashboard.git' " " " Plugin options -" Plug 'nsf/gocode', { 'tag': 'go.weekly.2012-03-13', 'rtp': 'vim' } +" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' } " " " Plugin outside ~/.vim/plugged with post-update hook " Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' } @@ -72,8 +75,6 @@ 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') || has('win64') -let s:py2 = has('python') && !has('nvim') && !s:is_win && !has('win32unix') -let s:ruby = has('ruby') && !has('nvim') && (v:version >= 703 || v:version == 702 && has('patch374')) let s:nvim = has('nvim') && exists('*jobwait') && !s:is_win let s:me = resolve(expand(':p')) let s:base_spec = { 'branch': 'master', 'frozen': 0 } @@ -358,7 +359,9 @@ function! plug#load(...) for name in a:000 call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) endfor - doautocmd BufRead + if exists('#BufRead') + doautocmd BufRead + endif return 1 endfunction @@ -388,14 +391,21 @@ function! s:lod(names, types) for dir in a:types call s:source(rtp, dir.'/**/*.vim') endfor + if exists('#User#'.name) + execute 'doautocmd User' name + endif endfor endfunction function! s:lod_ft(pat, names) call s:lod(a:names, ['plugin', 'after/plugin']) execute 'autocmd! PlugLOD FileType' a:pat - doautocmd filetypeplugin FileType - doautocmd filetypeindent FileType + if exists('#filetypeplugin#FileType') + doautocmd filetypeplugin FileType + endif + if exists('#filetypeindent#FileType') + doautocmd filetypeindent FileType + endif endfunction function! s:lod_cmd(cmd, bang, l1, l2, args, names) @@ -430,7 +440,7 @@ function! s:add(repo, ...) call add(g:plugs_order, name) endif let g:plugs[name] = spec - let s:loaded[name] = 0 + let s:loaded[name] = get(s:loaded, name, 0) catch return s:err(v:exception) endtry @@ -746,6 +756,10 @@ function! s:update_impl(pull, force, args) abort echohl None endif + let python = (has('python') || has('python3')) && !s:is_win && !has('win32unix') + \ && (!s:nvim || has('vim_starting')) + let ruby = has('ruby') && !s:nvim && (v:version >= 703 || v:version == 702 && has('patch374')) + let s:update = { \ 'start': reltime(), \ 'all': todo, @@ -754,7 +768,7 @@ function! s:update_impl(pull, force, args) abort \ 'pull': a:pull, \ 'force': a:force, \ 'new': {}, - \ 'threads': (s:py2 || s:ruby || s:nvim) ? min([len(todo), threads]) : 1, + \ 'threads': (python || ruby || s:nvim) ? min([len(todo), threads]) : 1, \ 'bar': '', \ 'fin': 0 \ } @@ -762,22 +776,27 @@ function! s:update_impl(pull, force, args) abort call s:prepare() call append(0, ['', '']) normal! 2G + silent! redraw + + let s:clone_opt = get(g:, 'plug_shallow', 1) ? + \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : '' " Python version requirement (>= 2.7) - if s:py2 && !s:ruby && !s:nvim && s:update.threads > 1 + if python && !has('python3') && !ruby && !s:nvim && s:update.threads > 1 redir => pyv silent python import platform; print(platform.python_version()) redir END - let s:py2 = s:version_requirement( + let python = s:version_requirement( \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) endif - if (s:py2 || s:ruby) && !s:nvim && s:update.threads > 1 + + if (python || ruby) && s:update.threads > 1 try let imd = &imd if s:mac_gui set noimd endif - if s:ruby + if ruby call s:update_ruby() else call s:update_python() @@ -961,16 +980,18 @@ while 1 " Without TCO, Vim stack is bound to explode call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') redraw - let checkout = s:shellesc(has_key(spec, 'tag') ? spec.tag : spec.branch) - let merge = s:shellesc(has_key(spec, 'tag') ? spec.tag : 'origin/'.spec.branch) + let has_tag = has_key(spec, 'tag') + let checkout = s:shellesc(has_tag ? spec.tag : spec.branch) + let merge = s:shellesc(has_tag ? spec.tag : 'origin/'.spec.branch) if !new let [valid, msg] = s:git_valid(spec, 0) if valid if pull + let fetch_opt = (has_tag && !empty(globpath(spec.dir, '.git/shallow'))) ? '--depth 99999999' : '' call s:spawn(name, - \ printf('(git fetch %s 2>&1 && git checkout -q %s 2>&1 && git merge --ff-only %s 2>&1 && git submodule update --init --recursive 2>&1)', - \ prog, checkout, merge), { 'dir': spec.dir }) + \ printf('(git fetch %s %s 2>&1 && git checkout -q %s 2>&1 && git merge --ff-only %s 2>&1 && git submodule update --init --recursive 2>&1)', + \ fetch_opt, prog, checkout, merge), { 'dir': spec.dir }) else let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 } endif @@ -979,7 +1000,8 @@ while 1 " Without TCO, Vim stack is bound to explode endif else call s:spawn(name, - \ printf('git clone %s --recursive %s -b %s %s 2>&1', + \ printf('git clone %s %s --recursive %s -b %s %s 2>&1', + \ has_tag ? '' : s:clone_opt, \ prog, \ s:shellesc(spec.uri), \ checkout, @@ -996,12 +1018,16 @@ endwhile endfunction function! s:update_python() -python << EOF +let py_exe = has('python3') ? 'python3' : 'python' +execute py_exe "<< EOF" """ Due to use of signals this function is POSIX only. """ import datetime import functools import os -import Queue +try: + import queue +except ImportError: + import Queue as queue import random import re import shutil @@ -1013,48 +1039,36 @@ 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 = 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_THREADS = {} -class CmdTimedOut(Exception): +class BaseExc(Exception): + def __init__(self, msg): + self._msg = msg + @property + def msg(self): + return self._msg +class CmdTimedOut(BaseExc): pass -class CmdFailed(Exception): +class CmdFailed(BaseExc): pass -class InvalidURI(Exception): +class InvalidURI(BaseExc): pass class Action(object): INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] -class GLog(object): - ON = None - LOGDIR = None - @classmethod - def write(cls, msg): - if cls.ON is None: - cls.ON = int(vim.eval('get(g:, "plug_log_on", 0)')) - cls.LOGDIR = os.path.expanduser(vim.eval('get(g:, "plug_logs", "~/plug_logs")')) - if cls.ON: - if not os.path.exists(cls.LOGDIR): - os.makedirs(cls.LOGDIR) - cls._write(msg) - @classmethod - def _write(cls, msg): - name = thr.current_thread().name - fname = cls.LOGDIR + os.path.sep + name - with open(fname, 'ab') as flog: - ltime = datetime.datetime.now().strftime("%H:%M:%S.%f") - msg = '[{0},{1}] {2}{3}'.format(name, ltime, msg, '\n') - flog.write(msg) - class Buffer(object): - def __init__(self, lock, num_plugs): + def __init__(self, lock, num_plugs, is_pull, is_win): self.bar = '' - self.event = 'Updating' if vim.eval('s:update.pull') == '1' else 'Installing' - self.is_win = vim.eval('s:is_win') == '1' + self.event = 'Updating' if is_pull else 'Installing' + self.is_win = is_win self.lock = lock self.maxy = int(vim.eval('winheight(".")')) self.num_plugs = num_plugs @@ -1080,15 +1094,12 @@ class Buffer(object): num_spaces = self.num_plugs - len(self.bar) curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') - vim.command('normal! 2G') - if not self.is_win: - vim.command('redraw') - - def write(self, *args, **kwargs): with self.lock: - self._write(*args, **kwargs) + vim.command('normal! 2G') + if not self.is_win: + vim.command('redraw') - def _write(self, action, name, lines): + def write(self, action, name, lines): first, rest = lines[0], lines[1:] msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] padded_rest = [' ' + line for line in rest] @@ -1113,7 +1124,7 @@ class Buffer(object): self.header() except vim.error: - GLog.write('Buffer Update FAILED.') + pass class Command(object): def __init__(self, cmd, cmd_dir=None, timeout=60, ntries=3, cb=None, clean=None): @@ -1159,7 +1170,7 @@ class Command(object): proc = None first_line = True try: - tfile = tempfile.NamedTemporaryFile() + tfile = tempfile.NamedTemporaryFile(mode='w+b', delete=False) proc = subprocess.Popen(self.cmd, cwd=self.cmd_dir, stdout=tfile, stderr=subprocess.STDOUT, shell=True, preexec_fn=os.setsid) while proc.poll() is None: @@ -1180,7 +1191,7 @@ class Command(object): raise CmdTimedOut(['Timeout!']) tfile.seek(0) - result = [line.rstrip() for line in tfile] + result = [line.decode().rstrip() for line in tfile] if proc.returncode != 0: msg = [''] @@ -1192,18 +1203,21 @@ class Command(object): if self.clean: self.clean() raise + finally: + os.remove(tfile.name) return result class Plugin(object): - def __init__(self, name, args, buf, lock): + def __init__(self, name, args, buf_q, lock): self.name = name self.args = args - self.buf = buf + self.buf_q = buf_q self.lock = lock tag = args.get('tag', 0) self.checkout = esc(tag if tag else args['branch']) self.merge = esc(tag if tag else 'origin/' + args['branch']) + self.tag = tag def manage(self): try: @@ -1212,9 +1226,9 @@ class Plugin(object): else: self.install() with self.lock: - vim.command("let s:update.new['{0}'] = 1".format(self.name)) + thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) except (CmdTimedOut, CmdFailed, InvalidURI) as exc: - self.write(Action.ERROR, self.name, exc.message) + self.write(Action.ERROR, self.name, exc.msg) except KeyboardInterrupt: G_STOP.set() self.write(Action.ERROR, self.name, ['Interrupted!']) @@ -1236,9 +1250,9 @@ class Plugin(object): return _clean self.write(Action.INSTALL, self.name, ['Installing ...']) - callback = functools.partial(self.buf.write, Action.INSTALL, self.name) - cmd = 'git clone {0} --recursive {1} -b {2} {3} 2>&1'.format( - G_PROGRESS, self.args['uri'], self.checkout, esc(target)) + callback = functools.partial(self.write, Action.INSTALL, self.name) + cmd = 'git clone {0} {1} --recursive {2} -b {3} {4} 2>&1'.format( + '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], self.checkout, esc(target)) com = Command(cmd, None, G_TIMEOUT, G_RETRIES, callback, clean(target)) result = com.attempt_cmd() self.write(Action.DONE, self.name, result[-1:]) @@ -1256,16 +1270,15 @@ class Plugin(object): if G_PULL: self.write(Action.UPDATE, self.name, ['Updating ...']) - callback = functools.partial(self.buf.write, Action.UPDATE, self.name) - cmds = ['git fetch {0}'.format(G_PROGRESS), + 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 '' + cmds = ['git fetch {0} {1}'.format(fetch_opt, G_PROGRESS), 'git checkout -q {0}'.format(self.checkout), 'git merge --ff-only {0}'.format(self.merge), 'git submodule update --init --recursive'] cmd = ' 2>&1 && '.join(cmds) - GLog.write(cmd) com = Command(cmd, self.args['dir'], G_TIMEOUT, G_RETRIES, callback) result = com.attempt_cmd() - GLog.write(result) self.write(Action.DONE, self.name, result[-1:]) else: self.write(Action.DONE, self.name, ['Already installed']) @@ -1277,8 +1290,7 @@ class Plugin(object): return result[-1] def write(self, action, name, msg): - GLog.write('{0} {1}: {2}'.format(action, name, '\n'.join(msg))) - self.buf.write(action, name, msg) + self.buf_q.put((action, name, msg)) class PlugThread(thr.Thread): def __init__(self, tname, args): @@ -1288,17 +1300,20 @@ class PlugThread(thr.Thread): def run(self): thr.current_thread().name = self.tname - work_q, lock, buf = self.args + buf_q, work_q, lock = self.args try: while not G_STOP.is_set(): name, args = work_q.get_nowait() - GLog.write('{0}: Dir {1}'.format(name, args['dir'])) - plug = Plugin(name, args, buf, lock) + plug = Plugin(name, args, buf_q, lock) plug.manage() work_q.task_done() - except Queue.Empty: - GLog.write('Queue now empty.') + except queue.Empty: + pass + finally: + global G_THREADS + with lock: + del G_THREADS[thr.current_thread().name] class RefreshThread(thr.Thread): def __init__(self, lock): @@ -1309,19 +1324,26 @@ class RefreshThread(thr.Thread): def run(self): while self.running: with self.lock: - vim.command('noautocmd normal! a') + thread_vim_command('noautocmd normal! a') time.sleep(0.2) 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) + buf = os.read(fread, 100000).decode() os.close(fread) line = buf.rstrip('\r\n') @@ -1334,42 +1356,40 @@ def nonblock_read(fname): def main(): thr.current_thread().name = 'main' - GLog.write('') - if GLog.ON and os.path.exists(GLog.LOGDIR): - shutil.rmtree(GLog.LOGDIR) - - threads = [] nthreads = int(vim.eval('s:update.threads')) plugs = vim.eval('s:update.todo') mac_gui = vim.eval('s:mac_gui') == '1' is_win = vim.eval('s:is_win') == '1' - GLog.write('Plugs: {0}'.format(plugs)) - GLog.write('PULL: {0}, WIN: {1}, MAC: {2}'.format(G_PULL, is_win, mac_gui)) - GLog.write('Num Threads: {0}'.format(nthreads)) lock = thr.Lock() - buf = Buffer(lock, len(plugs)) - work_q = Queue.Queue() + buf = Buffer(lock, len(plugs), G_PULL, is_win) + buf_q, work_q = queue.Queue(), queue.Queue() for work in plugs.items(): work_q.put(work) - GLog.write('Starting Threads') + global G_THREADS for num in range(nthreads): tname = 'PlugT-{0:02}'.format(num) - thread = PlugThread(tname, (work_q, lock, buf)) + thread = PlugThread(tname, (buf_q, work_q, lock)) thread.start() - threads.append(thread) + G_THREADS[tname] = thread if mac_gui: rthread = RefreshThread(lock) rthread.start() - GLog.write('Joining Live Threads') - for thread in threads: - thread.join() + while not buf_q.empty() or len(G_THREADS) != 0: + try: + action, name, msg = buf_q.get(True, 0.25) + buf.write(action, name, msg) + buf_q.task_done() + except queue.Empty: + pass + except KeyboardInterrupt: + G_STOP.set() + if mac_gui: rthread.stop() rthread.join() - GLog.write('Cleanly Exited Main') main() EOF @@ -1533,6 +1553,7 @@ function! s:update_ruby() end } if VIM::evaluate('s:mac_gui') == 1 + clone_opt = VIM::evaluate('s:clone_opt') progress = VIM::evaluate('s:progress_opt(1)') nthr.times do mtx.synchronize do @@ -1562,7 +1583,8 @@ function! s:update_ruby() else if pull log.call name, 'Updating ...', :update - bt.call "#{cd} #{dir} && git fetch #{progress} 2>&1 && git checkout -q #{checkout} 2>&1 && git merge --ff-only #{merge} 2>&1 && #{subm}", name, :update, nil + fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' + bt.call "#{cd} #{dir} && git fetch #{fetch_opt} #{progress} 2>&1 && git checkout -q #{checkout} 2>&1 && git merge --ff-only #{merge} 2>&1 && #{subm}", name, :update, nil else [true, skip] end @@ -1570,7 +1592,7 @@ function! s:update_ruby() else d = esc dir.sub(%r{[\\/]+$}, '') log.call name, 'Installing ...', :install - bt.call "git clone #{progress} --recursive #{uri} -b #{checkout} #{d} 2>&1", name, :install, proc { + bt.call "git clone #{clone_opt unless tag} #{progress} --recursive #{uri} -b #{checkout} #{d} 2>&1", name, :install, proc { FileUtils.rm_rf dir } end @@ -1620,14 +1642,14 @@ endfunction function! s:system(cmd, ...) try - let sh = &shell + let [sh, shrd] = [&shell, &shellredir] if !s:is_win - set shell=sh + set shell=sh shellredir=>%s\ 2>&1 endif let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd return system(s:is_win ? '('.cmd.')' : cmd) finally - let &shell = sh + let [&shell, &shellredir] = [sh, shrd] endtry endfunction @@ -1880,7 +1902,7 @@ function! s:preview_commit() execute 'pedit' sha wincmd P setlocal filetype=git buftype=nofile nobuflisted - execute 'silent read !cd' s:shellesc(g:plugs[name].dir) '&& git show' sha + execute 'silent read !cd' s:shellesc(g:plugs[name].dir) '&& git show --pretty=medium' sha normal! gg"_dd wincmd p endfunction diff --git a/.vim/plugins.vim b/.vim/plugins.vim index d938771..6964dc9 100644 --- a/.vim/plugins.vim +++ b/.vim/plugins.vim @@ -53,6 +53,9 @@ let g:syntastic_always_populate_loc_list = 1 " vim-airline let g:airline#extensions#tabline#enabled = 1 +" vim-go +let g:go_fmt_command = 'goimports' + " vim-latex let g:Tex_DefaultTargetFormat = 'pdf' let g:Tex_MultipleCompileFormats = 'pdf, aux'