Kaynağa Gözat

Merge pull request #227 from starcraftman/starting

Use Python installer on Neovim during `vim_starting` (#104)
Junegunn Choi 10 yıl önce
ebeveyn
işleme
9e0a082a3d
2 değiştirilmiş dosya ile 61 ekleme ve 44 silme
  1. 1 3
      .travis.yml
  2. 60 41
      plug.vim

+ 1 - 3
.travis.yml

@@ -7,19 +7,17 @@ rvm:
   - 2.1.0 # Test against python3 installer
   - 2.1.0 # Test against python3 installer
 
 
 before_script: |
 before_script: |
+  sudo apt-get update -y
   if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.2 ]; then
   if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.2 ]; then
-    sudo apt-get update -y
     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

+ 60 - 41
plug.vim

@@ -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.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.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 * ' ')
 
 
-    vim.command('normal! 2G')
-    if not self.is_win:
-      vim.command('redraw')
-
-  def write(self, *args, **kwargs):
     with self.lock:
     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:]
     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))
-  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():
   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')
-  for thread in threads:
-    thread.join()
+  GLog.write('Buffer Writing Loop')
+  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:
   if mac_gui:
     rthread.stop()
     rthread.stop()
     rthread.join()
     rthread.join()