aboutsummaryrefslogtreecommitdiff
path: root/runtime/autoload
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/autoload')
-rw-r--r--runtime/autoload/man.vim44
-rw-r--r--runtime/autoload/msgpack.vim3
-rw-r--r--runtime/autoload/provider/python.vim4
-rw-r--r--runtime/autoload/provider/python3.vim4
-rw-r--r--runtime/autoload/provider/pythonx.vim26
-rw-r--r--runtime/autoload/provider/ruby.vim34
-rw-r--r--runtime/autoload/provider/script_host.py247
-rw-r--r--runtime/autoload/remote/host.vim69
8 files changed, 111 insertions, 320 deletions
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 49663d7e5a..0dfcc424e2 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -11,6 +11,8 @@ catch /E145:/
" Ignore the error in restricted mode
endtry
+" Load man page {page} from {section}
+" call man#get_page([{section}, ]{page})
function man#get_page(...) abort
let invoked_from_man = (&filetype ==# 'man')
@@ -20,21 +22,14 @@ function man#get_page(...) abort
elseif a:0 > 2
echoerr 'too many arguments'
return
- elseif a:0 == 2
- let [page, sect] = [a:2, 0 + a:1]
- elseif type(1) == type(a:1)
- let [page, sect] = ['<cword>', a:1]
- else
- let [page, sect] = [a:1, '']
endif
- if page == '<cword>'
- let page = expand('<cword>')
- endif
+ let sect = get(a:000, 0)
+ let page = get(a:000, 1, sect)
let [page, sect] = s:parse_page_and_section(sect, page)
- if 0 + sect > 0 && s:find_page(sect, page) == 0
+ if !empty(sect) && s:find_page(sect, page) == 0
let sect = ''
endif
@@ -54,9 +49,9 @@ function man#get_page(...) abort
let thiswin = winnr()
wincmd b
if winnr() > 1
- exe "norm! " . thiswin . "\<C-W>w"
+ exec thiswin . 'wincmd w'
while 1
- if &filetype == 'man'
+ if &filetype ==# 'man'
break
endif
wincmd w
@@ -80,11 +75,11 @@ function man#get_page(...) abort
endif
silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b'
" Remove blank lines from top and bottom.
- while getline(1) =~ '^\s*$'
- silent keepjumps norm! gg"_dd
+ while getline(1) =~# '^\s*$'
+ silent keepjumps 1delete _
endwhile
- while getline('$') =~ '^\s*$'
- silent keepjumps norm! G"_dd
+ while getline('$') =~# '^\s*$'
+ silent keepjumps $delete _
endwhile
setlocal nomodified
setlocal filetype=man
@@ -118,15 +113,11 @@ endfunction
" Expects a string like 'access' or 'access(2)'.
function s:parse_page_and_section(sect, str) abort
try
- let save_isk = &iskeyword
- setlocal iskeyword-=(,)
- let page = substitute(a:str, '(*\(\k\+\).*', '\1', '')
- let sect = substitute(a:str, '\(\k\+\)(\([^()]*\)).*', '\2', '')
- if sect == page || -1 == match(sect, '^[0-9 ]\+$')
+ let [page, sect] = matchlist(a:str, '\v\C([-.[:alnum:]_]+)%(\(([-.[:alnum:]_]+)\))?')[1:2]
+ if empty(sect)
let sect = a:sect
endif
catch
- let &l:iskeyword = save_isk
echoerr 'man.vim: failed to parse: "'.a:str.'"'
endtry
@@ -134,7 +125,7 @@ function s:parse_page_and_section(sect, str) abort
endfunction
function s:cmd(sect, page) abort
- if 0 + a:sect > 0
+ if !empty(a:sect)
return s:man_sect_arg.' '.a:sect.' '.a:page
endif
return a:page
@@ -142,10 +133,5 @@ endfunction
function s:find_page(sect, page) abort
let where = system('/usr/bin/man '.s:man_find_arg.' '.s:cmd(a:sect, a:page))
- if where !~ "^/"
- if matchstr(where, " [^ ]*$") !~ "^ /"
- return 0
- endif
- endif
- return 1
+ return (where =~# '^ */')
endfunction
diff --git a/runtime/autoload/msgpack.vim b/runtime/autoload/msgpack.vim
index e6022922fe..2bb7ec5b02 100644
--- a/runtime/autoload/msgpack.vim
+++ b/runtime/autoload/msgpack.vim
@@ -395,7 +395,8 @@ endfunction
""
" Dump floating-point value.
function s:msgpack_dump_float(v) abort
- return string(type(a:v) == type({}) ? a:v._VAL : a:v)
+ return substitute(string(type(a:v) == type({}) ? a:v._VAL : a:v),
+ \'\V\^\(-\)\?str2float(''\(inf\|nan\)'')\$', '\1\2', '')
endfunction
""
diff --git a/runtime/autoload/provider/python.vim b/runtime/autoload/provider/python.vim
index b769895357..cb9d5c5296 100644
--- a/runtime/autoload/provider/python.vim
+++ b/runtime/autoload/provider/python.vim
@@ -24,12 +24,10 @@ if s:prog == ''
finish
endif
-let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
-
" The Python provider plugin will run in a separate instance of the Python
" host.
call remote#host#RegisterClone('legacy-python-provider', 'python')
-call remote#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
+call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
function! provider#python#Call(method, args)
if s:err != ''
diff --git a/runtime/autoload/provider/python3.vim b/runtime/autoload/provider/python3.vim
index 2952f76b40..f4a751e7a2 100644
--- a/runtime/autoload/provider/python3.vim
+++ b/runtime/autoload/provider/python3.vim
@@ -24,12 +24,10 @@ if s:prog == ''
finish
endif
-let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
-
" The Python3 provider plugin will run in a separate instance of the Python3
" host.
call remote#host#RegisterClone('legacy-python3-provider', 'python3')
-call remote#host#RegisterPlugin('legacy-python3-provider', s:plugin_path, [])
+call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
function! provider#python3#Call(method, args)
if s:err != ''
diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim
index 022ef19914..05815a4896 100644
--- a/runtime/autoload/provider/pythonx.vim
+++ b/runtime/autoload/provider/pythonx.vim
@@ -5,6 +5,32 @@ endif
let s:loaded_pythonx_provider = 1
+function! provider#pythonx#Require(host) abort
+ let ver = (a:host.orig_name ==# 'python') ? 2 : 3
+
+ " Python host arguments
+ let args = ['-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
+
+ " Collect registered Python plugins into args
+ let python_plugins = remote#host#PluginsForHost(a:host.name)
+ for plugin in python_plugins
+ call add(args, plugin.path)
+ endfor
+
+ try
+ let channel_id = rpcstart((ver == '2' ?
+ \ provider#python#Prog() : provider#python3#Prog()), args)
+ if rpcrequest(channel_id, 'poll') == 'ok'
+ return channel_id
+ endif
+ catch
+ echomsg v:throwpoint
+ echomsg v:exception
+ endtry
+ throw remote#host#LoadErrorForHost(a:host.orig_name,
+ \ '$NVIM_PYTHON_LOG_FILE')
+endfunction
+
function! provider#pythonx#Detect(major_ver) abort
let host_var = (a:major_ver == 2) ?
\ 'g:python_host_prog' : 'g:python3_host_prog'
diff --git a/runtime/autoload/provider/ruby.vim b/runtime/autoload/provider/ruby.vim
new file mode 100644
index 0000000000..aad8c09d28
--- /dev/null
+++ b/runtime/autoload/provider/ruby.vim
@@ -0,0 +1,34 @@
+" The Ruby provider helper
+if exists('s:loaded_ruby_provider')
+ finish
+endif
+
+let s:loaded_ruby_provider = 1
+
+function! provider#ruby#Require(host) abort
+ " Collect registered Ruby plugins into args
+ let args = []
+ let ruby_plugins = remote#host#PluginsForHost(a:host.name)
+
+ for plugin in ruby_plugins
+ call add(args, plugin.path)
+ endfor
+
+ try
+ let channel_id = rpcstart(provider#ruby#Prog(), args)
+
+ if rpcrequest(channel_id, 'poll') == 'ok'
+ return channel_id
+ endif
+ catch
+ echomsg v:throwpoint
+ echomsg v:exception
+ endtry
+
+ throw remote#host#LoadErrorForHost(a:host.orig_name,
+ \ '$NVIM_RUBY_LOG_FILE')
+endfunction
+
+function! provider#ruby#Prog() abort
+ return 'neovim-ruby-host'
+endfunction
diff --git a/runtime/autoload/provider/script_host.py b/runtime/autoload/provider/script_host.py
deleted file mode 100644
index 416b4070bb..0000000000
--- a/runtime/autoload/provider/script_host.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""Legacy python/python3-vim emulation."""
-import imp
-import io
-import logging
-import os
-import sys
-
-import neovim
-
-__all__ = ('ScriptHost',)
-
-
-logger = logging.getLogger(__name__)
-debug, info, warn = (logger.debug, logger.info, logger.warn,)
-
-IS_PYTHON3 = sys.version_info >= (3, 0)
-
-if IS_PYTHON3:
- basestring = str
-
- if sys.version_info >= (3, 4):
- from importlib.machinery import PathFinder
-
-
-@neovim.plugin
-class ScriptHost(object):
-
- """Provides an environment for running python plugins created for Vim."""
-
- def __init__(self, nvim):
- """Initialize the legacy python-vim environment."""
- self.setup(nvim)
- # context where all code will run
- self.module = imp.new_module('__main__')
- nvim.script_context = self.module
- # it seems some plugins assume 'sys' is already imported, so do it now
- exec('import sys', self.module.__dict__)
- self.legacy_vim = nvim.with_hook(LegacyEvalHook())
- sys.modules['vim'] = self.legacy_vim
-
- def setup(self, nvim):
- """Setup import hooks and global streams.
-
- This will add import hooks for importing modules from runtime
- directories and patch the sys module so 'print' calls will be
- forwarded to Nvim.
- """
- self.nvim = nvim
- info('install import hook/path')
- self.hook = path_hook(nvim)
- sys.path_hooks.append(self.hook)
- nvim.VIM_SPECIAL_PATH = '_vim_path_'
- sys.path.append(nvim.VIM_SPECIAL_PATH)
- info('redirect sys.stdout and sys.stderr')
- self.saved_stdout = sys.stdout
- self.saved_stderr = sys.stderr
- sys.stdout = RedirectStream(lambda data: nvim.out_write(data))
- sys.stderr = RedirectStream(lambda data: nvim.err_write(data))
-
- def teardown(self):
- """Restore state modified from the `setup` call."""
- for plugin in self.installed_plugins:
- if hasattr(plugin, 'on_teardown'):
- plugin.teardown()
- nvim = self.nvim
- info('uninstall import hook/path')
- sys.path.remove(nvim.VIM_SPECIAL_PATH)
- sys.path_hooks.remove(self.hook)
- info('restore sys.stdout and sys.stderr')
- sys.stdout = self.saved_stdout
- sys.stderr = self.saved_stderr
-
- @neovim.rpc_export('python_execute', sync=True)
- def python_execute(self, script, range_start, range_stop):
- """Handle the `python` ex command."""
- self._set_current_range(range_start, range_stop)
- exec(script, self.module.__dict__)
-
- @neovim.rpc_export('python_execute_file', sync=True)
- def python_execute_file(self, file_path, range_start, range_stop):
- """Handle the `pyfile` ex command."""
- self._set_current_range(range_start, range_stop)
- with open(file_path) as f:
- script = compile(f.read(), file_path, 'exec')
- exec(script, self.module.__dict__)
-
- @neovim.rpc_export('python_do_range', sync=True)
- def python_do_range(self, start, stop, code):
- """Handle the `pydo` ex command."""
- self._set_current_range(start, stop)
- nvim = self.nvim
- start -= 1
- stop -= 1
- fname = '_vim_pydo'
-
- # define the function
- function_def = 'def %s(line, linenr):\n %s' % (fname, code,)
- exec(function_def, self.module.__dict__)
- # get the function
- function = self.module.__dict__[fname]
- while start <= stop:
- # Process batches of 5000 to avoid the overhead of making multiple
- # API calls for every line. Assuming an average line length of 100
- # bytes, approximately 488 kilobytes will be transferred per batch,
- # which can be done very quickly in a single API call.
- sstart = start
- sstop = min(start + 5000, stop)
- lines = nvim.current.buffer.get_line_slice(sstart, sstop, True,
- True)
-
- exception = None
- newlines = []
- linenr = sstart + 1
- for i, line in enumerate(lines):
- result = function(line, linenr)
- if result is None:
- # Update earlier lines, and skip to the next
- if newlines:
- end = sstart + len(newlines) - 1
- nvim.current.buffer.set_line_slice(sstart, end,
- True, True,
- newlines)
- sstart += len(newlines) + 1
- newlines = []
- pass
- elif isinstance(result, basestring):
- newlines.append(result)
- else:
- exception = TypeError('pydo should return a string ' +
- 'or None, found %s instead'
- % result.__class__.__name__)
- break
- linenr += 1
-
- start = sstop + 1
- if newlines:
- end = sstart + len(newlines) - 1
- nvim.current.buffer.set_line_slice(sstart, end, True, True,
- newlines)
- if exception:
- raise exception
- # delete the function
- del self.module.__dict__[fname]
-
- @neovim.rpc_export('python_eval', sync=True)
- def python_eval(self, expr):
- """Handle the `pyeval` vim function."""
- return eval(expr, self.module.__dict__)
-
- def _set_current_range(self, start, stop):
- current = self.legacy_vim.current
- current.range = current.buffer.range(start, stop)
-
-
-class RedirectStream(io.IOBase):
- def __init__(self, redirect_handler):
- self.redirect_handler = redirect_handler
-
- def write(self, data):
- self.redirect_handler(data)
-
- def writelines(self, seq):
- self.redirect_handler('\n'.join(seq))
-
-
-class LegacyEvalHook(neovim.SessionHook):
-
- """Injects legacy `vim.eval` behavior to a Nvim instance."""
-
- def __init__(self):
- super(LegacyEvalHook, self).__init__(from_nvim=self._string_eval)
-
- def _string_eval(self, obj, session, method, kind):
- if method == 'vim_eval':
- if IS_PYTHON3:
- if isinstance(obj, (int, float)):
- return str(obj)
- elif isinstance(obj, (int, long, float)):
- return str(obj)
- return obj
-
-
-# This was copied/adapted from nvim-python help
-def path_hook(nvim):
- def _get_paths():
- return discover_runtime_directories(nvim)
-
- def _find_module(fullname, oldtail, path):
- idx = oldtail.find('.')
- if idx > 0:
- name = oldtail[:idx]
- tail = oldtail[idx+1:]
- fmr = imp.find_module(name, path)
- module = imp.find_module(fullname[:-len(oldtail)] + name, *fmr)
- return _find_module(fullname, tail, module.__path__)
- else:
- return imp.find_module(fullname, path)
-
- class VimModuleLoader(object):
- def __init__(self, module):
- self.module = module
-
- def load_module(self, fullname, path=None):
- # Check sys.modules, required for reload (see PEP302).
- if fullname in sys.modules:
- return sys.modules[fullname]
- return imp.load_module(fullname, *self.module)
-
- class VimPathFinder(object):
- @staticmethod
- def find_module(fullname, path=None):
- "Method for Python 2.7 and 3.3."
- try:
- return VimModuleLoader(
- _find_module(fullname, fullname, path or _get_paths()))
- except ImportError:
- return None
-
- @staticmethod
- def find_spec(fullname, path=None, target=None):
- "Method for Python 3.4+."
- return PathFinder.find_spec(fullname, path or _get_paths(), target)
-
- def hook(path):
- if path == nvim.VIM_SPECIAL_PATH:
- return VimPathFinder
- else:
- raise ImportError
-
- return hook
-
-
-def discover_runtime_directories(nvim):
- rv = []
- for path in nvim.list_runtime_paths():
- if not os.path.exists(path):
- continue
- path1 = os.path.join(path, 'pythonx')
- if IS_PYTHON3:
- path2 = os.path.join(path, 'python3')
- else:
- path2 = os.path.join(path, 'python2')
- if os.path.exists(path1):
- rv.append(path1)
- if os.path.exists(path2):
- rv.append(path2)
- return rv
diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim
index 24497b10c2..1aead649a0 100644
--- a/runtime/autoload/remote/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -2,6 +2,7 @@ let s:hosts = {}
let s:plugin_patterns = {}
let s:remote_plugins_manifest = fnamemodify(expand($MYVIMRC, 1), ':h')
\.'/.'.fnamemodify($MYVIMRC, ':t').'-rplugin~'
+let s:plugins_for_host = {}
" Register a host by associating it with a factory(funcref)
@@ -35,6 +36,9 @@ endfunction
" Get a host channel, bootstrapping it if necessary
function! remote#host#Require(name) abort
+ if empty(s:plugins_for_host)
+ call remote#host#LoadRemotePlugins()
+ endif
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -123,6 +127,13 @@ function! remote#host#LoadRemotePlugins() abort
endfunction
+function! remote#host#LoadRemotePluginsEvent(event, pattern) abort
+ autocmd! nvim-rplugin
+ call remote#host#LoadRemotePlugins()
+ execute 'silent doautocmd' a:event a:pattern
+endfunction
+
+
function! s:RegistrationCommands(host) abort
" Register a temporary host clone for discovering specs
let host_id = a:host.'-registration-clone'
@@ -138,7 +149,9 @@ function! s:RegistrationCommands(host) abort
endfor
let channel = remote#host#Require(host_id)
let lines = []
+ let registered = []
for path in paths
+ unlet! specs
let specs = rpcrequest(channel, 'specs', path)
if type(specs) != type([])
" host didn't return a spec list, indicates a failure while loading a
@@ -151,9 +164,10 @@ function! s:RegistrationCommands(host) abort
call add(lines, " \\ ".string(spec).",")
endfor
call add(lines, " \\ ])")
+ call add(registered, path)
endfor
echomsg printf("remote/host: %s host registered plugins %s",
- \ a:host, string(map(copy(paths), "fnamemodify(v:val, ':t')")))
+ \ a:host, string(map(registered, "fnamemodify(v:val, ':t')")))
" Delete the temporary host clone
call rpcstop(s:hosts[host_id].channel)
@@ -163,7 +177,7 @@ function! s:RegistrationCommands(host) abort
endfunction
-function! s:UpdateRemotePlugins() abort
+function! remote#host#UpdateRemotePlugins() abort
let commands = []
let hosts = keys(s:hosts)
for host in hosts
@@ -185,10 +199,6 @@ function! s:UpdateRemotePlugins() abort
endfunction
-command! UpdateRemotePlugins call s:UpdateRemotePlugins()
-
-
-let s:plugins_for_host = {}
function! remote#host#PluginsForHost(host) abort
if !has_key(s:plugins_for_host, a:host)
let s:plugins_for_host[a:host] = []
@@ -197,40 +207,25 @@ function! remote#host#PluginsForHost(host) abort
endfunction
-" Registration of standard hosts
-
-" Python/Python3 {{{
-function! s:RequirePythonHost(host) abort
- let ver = (a:host.orig_name ==# 'python') ? 2 : 3
-
- " Python host arguments
- let args = ['-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
-
- " Collect registered Python plugins into args
- let python_plugins = remote#host#PluginsForHost(a:host.name)
- for plugin in python_plugins
- call add(args, plugin.path)
- endfor
-
- try
- let channel_id = rpcstart((ver == '2' ?
- \ provider#python#Prog() : provider#python3#Prog()), args)
- if rpcrequest(channel_id, 'poll') == 'ok'
- return channel_id
- endif
- catch
- echomsg v:throwpoint
- echomsg v:exception
- endtry
- throw 'Failed to load '. a:host.orig_name . ' host. '.
+function! remote#host#LoadErrorForHost(host, log) abort
+ return 'Failed to load '. a:host . ' host. '.
\ 'You can try to see what happened '.
\ 'by starting Neovim with the environment variable '.
- \ '$NVIM_PYTHON_LOG_FILE set to a file and opening '.
- \ 'the generated log file. Also, the host stderr will be available '.
+ \ a:log . ' set to a file and opening the generated '.
+ \ 'log file. Also, the host stderr will be available '.
\ 'in Neovim log, so it may contain useful information. '.
\ 'See also ~/.nvimlog.'
endfunction
-call remote#host#Register('python', '*.py', function('s:RequirePythonHost'))
-call remote#host#Register('python3', '*.py', function('s:RequirePythonHost'))
-" }}}
+
+" Registration of standard hosts
+
+" Python/Python3
+call remote#host#Register('python', '*',
+ \ function('provider#pythonx#Require'))
+call remote#host#Register('python3', '*',
+ \ function('provider#pythonx#Require'))
+
+" Ruby
+call remote#host#Register('ruby', '*.rb',
+ \ function('provider#ruby#Require'))