Merge pull request #227 from starcraftman/starting

Use Python installer on Neovim during `vim_starting` (#104)
This commit is contained in:
Junegunn Choi 2015-05-07 01:33:14 +09:00
commit 9e0a082a3d
2 changed files with 61 additions and 44 deletions

View File

@ -7,19 +7,17 @@ rvm:
- 2.1.0 # Test against python3 installer - 2.1.0 # Test against python3 installer
before_script: | before_script: |
if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.2 ]; then
sudo apt-get update -y sudo apt-get update -y
if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.2 ]; then
sudo apt-get install -y vim-nox sudo apt-get install -y vim-nox
sudo ln -s /usr/bin/vim /usr/local/bin/vim sudo ln -s /usr/bin/vim /usr/local/bin/vim
else else
git clone --depth 1 https://github.com/vim/vim git clone --depth 1 https://github.com/vim/vim
cd vim cd vim
if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.3 ]; then if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.3 ]; then
sudo apt-get update -y
sudo apt-get install -y python2.7-dev sudo apt-get install -y python2.7-dev
./configure --with-features=huge --enable-pythoninterp ./configure --with-features=huge --enable-pythoninterp
elif [ $(ruby -e 'puts RUBY_VERSION') = 2.1.0 ]; then elif [ $(ruby -e 'puts RUBY_VERSION') = 2.1.0 ]; then
sudo apt-get update -y
sudo apt-get install -y python3-dev sudo apt-get install -y python3-dev
./configure --with-features=huge --enable-python3interp ./configure --with-features=huge --enable-python3interp
else else

View File

@ -72,9 +72,6 @@ let s:plug_tab = get(s:, 'plug_tab', -1)
let s:plug_buf = get(s:, 'plug_buf', -1) let s:plug_buf = get(s:, 'plug_buf', -1)
let s:mac_gui = has('gui_macvim') && has('gui_running') let s:mac_gui = has('gui_macvim') && has('gui_running')
let s:is_win = has('win32') || has('win64') let s:is_win = has('win32') || has('win64')
let s:py = (has('python') || has('python3')) && !has('nvim') && !s:is_win && !has('win32unix')
let s:py_exe = has('python3') ? 'python3' : 'python'
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:nvim = has('nvim') && exists('*jobwait') && !s:is_win
let s:me = resolve(expand('<sfile>:p')) let s:me = resolve(expand('<sfile>:p'))
let s:base_spec = { 'branch': 'master', 'frozen': 0 } let s:base_spec = { 'branch': 'master', 'frozen': 0 }
@ -747,6 +744,10 @@ function! s:update_impl(pull, force, args) abort
echohl None echohl None
endif 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 = { let s:update = {
\ 'start': reltime(), \ 'start': reltime(),
\ 'all': todo, \ 'all': todo,
@ -755,7 +756,7 @@ function! s:update_impl(pull, force, args) abort
\ 'pull': a:pull, \ 'pull': a:pull,
\ 'force': a:force, \ 'force': a:force,
\ 'new': {}, \ 'new': {},
\ 'threads': (s:py || s:ruby || s:nvim) ? min([len(todo), threads]) : 1, \ 'threads': (python || ruby || s:nvim) ? min([len(todo), threads]) : 1,
\ 'bar': '', \ 'bar': '',
\ 'fin': 0 \ 'fin': 0
\ } \ }
@ -768,20 +769,21 @@ function! s:update_impl(pull, force, args) abort
\ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : '' \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : ''
" Python version requirement (>= 2.7) " Python version requirement (>= 2.7)
if s:py && !has('python3') && !s:ruby && !s:nvim && s:update.threads > 1 if python && !has('python3') && !ruby && !s:nvim && s:update.threads > 1
redir => pyv redir => pyv
silent python import platform; print(platform.python_version()) silent python import platform; print(platform.python_version())
redir END redir END
let s:py = s:version_requirement( let python = s:version_requirement(
\ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
endif endif
if (s:py || s:ruby) && !s:nvim && s:update.threads > 1
if (python || ruby) && s:update.threads > 1
try try
let imd = &imd let imd = &imd
if s:mac_gui if s:mac_gui
set noimd set noimd
endif endif
if s:ruby if ruby
call s:update_ruby() call s:update_ruby()
else else
call s:update_python() call s:update_python()
@ -1003,7 +1005,8 @@ endwhile
endfunction endfunction
function! s:update_python() function! s:update_python()
execute s:py_exe "<< EOF" let py_exe = has('python3') ? 'python3' : 'python'
execute py_exe "<< EOF"
""" Due to use of signals this function is POSIX only. """ """ Due to use of signals this function is POSIX only. """
import datetime import datetime
import functools import functools
@ -1023,6 +1026,7 @@ import time
import traceback import traceback
import vim import vim
G_NVIM = vim.eval("has('nvim')") == '1'
G_PULL = vim.eval('s:update.pull') == '1' G_PULL = vim.eval('s:update.pull') == '1'
G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
@ -1030,15 +1034,14 @@ G_CLONE_OPT = vim.eval('s:clone_opt')
G_PROGRESS = vim.eval('s:progress_opt(1)') G_PROGRESS = vim.eval('s:progress_opt(1)')
G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
G_STOP = thr.Event() G_STOP = thr.Event()
G_THREADS = {}
class BaseExc(Exception): class BaseExc(Exception):
def __init__(self, msg): def __init__(self, msg):
self.msg = msg
def _get_msg(self):
return self.msg
def _set_msg(self, msg):
self._msg = msg self._msg = msg
message = property(_get_msg, _set_msg) @property
def msg(self):
return self._msg
class CmdTimedOut(BaseExc): class CmdTimedOut(BaseExc):
pass pass
class CmdFailed(BaseExc): class CmdFailed(BaseExc):
@ -1070,10 +1073,10 @@ class GLog(object):
flog.write(msg.encode()) flog.write(msg.encode())
class Buffer(object): class Buffer(object):
def __init__(self, lock, num_plugs): def __init__(self, lock, num_plugs, is_pull, is_win):
self.bar = '' self.bar = ''
self.event = 'Updating' if vim.eval('s:update.pull') == '1' else 'Installing' self.event = 'Updating' if is_pull else 'Installing'
self.is_win = vim.eval('s:is_win') == '1' self.is_win = is_win
self.lock = lock self.lock = lock
self.maxy = int(vim.eval('winheight(".")')) self.maxy = int(vim.eval('winheight(".")'))
self.num_plugs = num_plugs self.num_plugs = num_plugs
@ -1099,15 +1102,12 @@ class Buffer(object):
num_spaces = self.num_plugs - len(self.bar) num_spaces = self.num_plugs - len(self.bar)
curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
with self.lock:
vim.command('normal! 2G') vim.command('normal! 2G')
if not self.is_win: if not self.is_win:
vim.command('redraw') vim.command('redraw')
def write(self, *args, **kwargs): def write(self, action, name, lines):
with self.lock:
self._write(*args, **kwargs)
def _write(self, action, name, lines):
first, rest = lines[0], lines[1:] first, rest = lines[0], lines[1:]
msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
padded_rest = [' ' + line for line in rest] padded_rest = [' ' + line for line in rest]
@ -1217,10 +1217,10 @@ class Command(object):
return result return result
class Plugin(object): class Plugin(object):
def __init__(self, name, args, buf, lock): def __init__(self, name, args, buf_q, lock):
self.name = name self.name = name
self.args = args self.args = args
self.buf = buf self.buf_q = buf_q
self.lock = lock self.lock = lock
tag = args.get('tag', 0) tag = args.get('tag', 0)
self.checkout = esc(tag if tag else args['branch']) self.checkout = esc(tag if tag else args['branch'])
@ -1234,7 +1234,7 @@ class Plugin(object):
else: else:
self.install() self.install()
with self.lock: 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: except (CmdTimedOut, CmdFailed, InvalidURI) as exc:
self.write(Action.ERROR, self.name, exc.msg) self.write(Action.ERROR, self.name, exc.msg)
except KeyboardInterrupt: except KeyboardInterrupt:
@ -1258,7 +1258,7 @@ class Plugin(object):
return _clean return _clean
self.write(Action.INSTALL, self.name, ['Installing ...']) self.write(Action.INSTALL, self.name, ['Installing ...'])
callback = functools.partial(self.buf.write, Action.INSTALL, self.name) callback = functools.partial(self.write, Action.INSTALL, self.name)
cmd = 'git clone {0} {1} --recursive {2} -b {3} {4} 2>&1'.format( 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)) '' 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)) com = Command(cmd, None, G_TIMEOUT, G_RETRIES, callback, clean(target))
@ -1278,7 +1278,7 @@ class Plugin(object):
if G_PULL: if G_PULL:
self.write(Action.UPDATE, self.name, ['Updating ...']) self.write(Action.UPDATE, self.name, ['Updating ...'])
callback = functools.partial(self.buf.write, Action.UPDATE, self.name) 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 '' 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), cmds = ['git fetch {0} {1}'.format(fetch_opt, G_PROGRESS),
'git checkout -q {0}'.format(self.checkout), 'git checkout -q {0}'.format(self.checkout),
@ -1301,7 +1301,7 @@ class Plugin(object):
def write(self, action, name, msg): def write(self, action, name, msg):
GLog.write('{0} {1}: {2}'.format(action, name, '\n'.join(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): class PlugThread(thr.Thread):
def __init__(self, tname, args): def __init__(self, tname, args):
@ -1311,17 +1311,21 @@ class PlugThread(thr.Thread):
def run(self): def run(self):
thr.current_thread().name = self.tname thr.current_thread().name = self.tname
work_q, lock, buf = self.args buf_q, work_q, lock = self.args
try: try:
while not G_STOP.is_set(): while not G_STOP.is_set():
name, args = work_q.get_nowait() name, args = work_q.get_nowait()
GLog.write('{0}: Dir {1}'.format(name, args['dir'])) GLog.write('{0}: Dir {1}'.format(name, args['dir']))
plug = Plugin(name, args, buf, lock) plug = Plugin(name, args, buf_q, lock)
plug.manage() plug.manage()
work_q.task_done() work_q.task_done()
except queue.Empty: except queue.Empty:
GLog.write('Queue now empty.') GLog.write('Queue now empty.')
finally:
global G_THREADS
with lock:
del G_THREADS[thr.current_thread().name]
class RefreshThread(thr.Thread): class RefreshThread(thr.Thread):
def __init__(self, lock): def __init__(self, lock):
@ -1332,12 +1336,19 @@ class RefreshThread(thr.Thread):
def run(self): def run(self):
while self.running: while self.running:
with self.lock: with self.lock:
vim.command('noautocmd normal! a') thread_vim_command('noautocmd normal! a')
time.sleep(0.2) time.sleep(0.2)
def stop(self): def stop(self):
self.running = False 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): def esc(name):
return '"' + name.replace('"', '\"') + '"' return '"' + name.replace('"', '\"') + '"'
@ -1361,7 +1372,6 @@ def main():
if GLog.ON and os.path.exists(GLog.LOGDIR): if GLog.ON and os.path.exists(GLog.LOGDIR):
shutil.rmtree(GLog.LOGDIR) shutil.rmtree(GLog.LOGDIR)
threads = []
nthreads = int(vim.eval('s:update.threads')) nthreads = int(vim.eval('s:update.threads'))
plugs = vim.eval('s:update.todo') plugs = vim.eval('s:update.todo')
mac_gui = vim.eval('s:mac_gui') == '1' mac_gui = vim.eval('s:mac_gui') == '1'
@ -1371,24 +1381,33 @@ def main():
GLog.write('Num Threads: {0}'.format(nthreads)) GLog.write('Num Threads: {0}'.format(nthreads))
lock = thr.Lock() lock = thr.Lock()
buf = Buffer(lock, len(plugs)) buf = Buffer(lock, len(plugs), G_PULL, is_win)
work_q = queue.Queue() buf_q, work_q = queue.Queue(), queue.Queue()
for work in plugs.items(): for work in plugs.items():
work_q.put(work) work_q.put(work)
GLog.write('Starting Threads') GLog.write('Starting Threads')
global G_THREADS
for num in range(nthreads): for num in range(nthreads):
tname = 'PlugT-{0:02}'.format(num) tname = 'PlugT-{0:02}'.format(num)
thread = PlugThread(tname, (work_q, lock, buf)) thread = PlugThread(tname, (buf_q, work_q, lock))
thread.start() thread.start()
threads.append(thread) G_THREADS[tname] = thread
if mac_gui: if mac_gui:
rthread = RefreshThread(lock) rthread = RefreshThread(lock)
rthread.start() rthread.start()
GLog.write('Joining Live Threads') GLog.write('Buffer Writing Loop')
for thread in threads: while not buf_q.empty() or len(G_THREADS) != 0:
thread.join() 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: if mac_gui:
rthread.stop() rthread.stop()
rthread.join() rthread.join()