diff --git a/powerline/bindings/vim/__init__.py b/powerline/bindings/vim/__init__.py index 4210cc26..51e76263 100644 --- a/powerline/bindings/vim/__init__.py +++ b/powerline/bindings/vim/__init__.py @@ -9,8 +9,7 @@ try: except ImportError: vim = {} -if not hasattr(vim, 'bindeval'): - import json +from powerline.lib.unicode import unicode try: @@ -19,6 +18,22 @@ except AttributeError: vim_encoding = 'utf-8' +python_to_vim_types = { + unicode: ( + lambda o: b'\'' + (o.translate({ + ord('\''): '\'\'', + }).encode(vim_encoding)) + b'\'' + ), + bytes: (lambda o: b'\'' + o.replace(b'\'', b'\'\'') + b'\''), + int: (str if str is bytes else (lambda o: unicode(o).encode('ascii'))), +} +python_to_vim_types[float] = python_to_vim_types[int] + + +def python_to_vim(o): + return python_to_vim_types[type(o)](o) + + if hasattr(vim, 'bindeval'): def vim_get_func(f, rettype=None): '''Return a vim function binding.''' @@ -39,11 +54,25 @@ else: __slots__ = ('f', 'rettype') def __init__(self, f, rettype=None): - self.f = f + self.f = f.encode('utf-8') self.rettype = rettype def __call__(self, *args): - r = vim.eval(self.f + '(' + json.dumps(args)[1:-1] + ')') + expr = self.f + b'(' + (b','.join(( + python_to_vim(o) for o in args + ))) + b')' + try: + r = vim.eval(expr) + except UnicodeDecodeError: + r = bytes(bytearray(( + int(chunk) for chunk in ( + vim.eval( + b'substitute(' + expr + b', ' + + b'\'^.*$\', \'\\=join(map(range(len(submatch(0))), ' + + b'"char2nr(submatch(0)[v:val])"))\', "")' + ).split() + ) + ))) if self.rettype: return self.rettype(r) return r @@ -140,7 +169,7 @@ else: def vim_setoption(option, value): vim.command('let &g:{option} = {value}'.format( - option=option, value=json.encode(value))) + option=option, value=python_to_vim(value))) if hasattr(vim, 'tabpages'): diff --git a/tests/test_segments.py b/tests/test_segments.py index 2cc6545b..629b3759 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -8,6 +8,7 @@ from functools import partial from powerline.segments import shell, tmux, common from powerline.lib.vcs import get_fallback_create_watcher +from powerline.lib.unicode import out_u import tests.vim as vim_module @@ -18,10 +19,10 @@ from tests import TestCase, SkipTest def get_dummy_guess(**kwargs): if 'directory' in kwargs: def guess(path, create_watcher): - return Args(branch=lambda: os.path.basename(path), **kwargs) + return Args(branch=lambda: out_u(os.path.basename(path)), **kwargs) else: def guess(path, create_watcher): - return Args(branch=lambda: os.path.basename(path), directory=path, **kwargs) + return Args(branch=lambda: out_u(os.path.basename(path)), directory=path, **kwargs) return guess