/usr/lib/python2.7/dist-packages/powerline/vim.py is in python-powerline 2.6-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | # vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
import json
import logging
from itertools import count
try:
import vim
except ImportError:
vim = object()
from powerline.bindings.vim import vim_get_func, vim_getvar, get_vim_encoding, python_to_vim
from powerline import Powerline, FailedUnicode, finish_common_config
from powerline.lib.dict import mergedicts
from powerline.lib.unicode import u
def _override_from(config, override_varname, key=None):
try:
overrides = vim_getvar(override_varname)
except KeyError:
return config
if key is not None:
try:
overrides = overrides[key]
except KeyError:
return config
mergedicts(config, overrides)
return config
class VimVarHandler(logging.Handler, object):
'''Vim-specific handler which emits messages to Vim global variables
:param str varname:
Variable where
'''
def __init__(self, varname):
super(VimVarHandler, self).__init__()
utf_varname = u(varname)
self.vim_varname = utf_varname.encode('ascii')
vim.command('unlet! g:' + utf_varname)
vim.command('let g:' + utf_varname + ' = []')
def emit(self, record):
message = u(record.message)
if record.exc_text:
message += '\n' + u(record.exc_text)
vim.eval(b'add(g:' + self.vim_varname + b', ' + python_to_vim(message) + b')')
class VimPowerline(Powerline):
def init(self, pyeval='PowerlinePyeval', **kwargs):
super(VimPowerline, self).init('vim', **kwargs)
self.last_window_id = 1
self.pyeval = pyeval
self.construct_window_statusline = self.create_window_statusline_constructor()
if all((hasattr(vim.current.window, attr) for attr in ('options', 'vars', 'number'))):
self.win_idx = self.new_win_idx
else:
self.win_idx = self.old_win_idx
self._vim_getwinvar = vim_get_func('getwinvar', 'bytes')
self._vim_setwinvar = vim_get_func('setwinvar')
if sys.version_info < (3,):
def create_window_statusline_constructor(self):
window_statusline = b'%!' + str(self.pyeval) + b'(\'powerline.statusline({0})\')'
return window_statusline.format
else:
def create_window_statusline_constructor(self):
startstr = b'%!' + self.pyeval.encode('ascii') + b'(\'powerline.statusline('
endstr = b')\')'
return lambda idx: (
startstr + str(idx).encode('ascii') + endstr
)
create_window_statusline_constructor.__doc__ = (
'''Create function which returns &l:stl value being given window index
Created function must return :py:class:`bytes` instance because this is
what ``window.options['statusline']`` returns (``window`` is
:py:class:`vim.Window` instance).
:return:
Function with type ``int → bytes``.
'''
)
default_log_stream = sys.stdout
def add_local_theme(self, key, config):
'''Add local themes at runtime (during vim session).
:param str key:
Matcher name (in format ``{matcher_module}.{module_attribute}`` or
``{module_attribute}`` if ``{matcher_module}`` is
``powerline.matchers.vim``). Function pointed by
``{module_attribute}`` should be hashable and accept a dictionary
with information about current buffer and return boolean value
indicating whether current window matched conditions. See also
:ref:`local_themes key description <config-ext-local_themes>`.
:param dict config:
:ref:`Theme <config-themes>` dictionary.
:return:
``True`` if theme was added successfully and ``False`` if theme with
the same matcher already exists.
'''
self.update_renderer()
matcher = self.get_matcher(key)
theme_config = {}
for cfg_path in self.theme_levels:
try:
lvl_config = self.load_config(cfg_path, 'theme')
except IOError:
pass
else:
mergedicts(theme_config, lvl_config)
mergedicts(theme_config, config)
try:
self.renderer.add_local_theme(matcher, {'config': theme_config})
except KeyError:
return False
else:
# Hack for local themes support: when reloading modules it is not
# guaranteed that .add_local_theme will be called once again, so
# this function arguments will be saved here for calling from
# .do_setup().
self.setup_kwargs.setdefault('_local_themes', []).append((key, config))
return True
get_encoding = staticmethod(get_vim_encoding)
def load_main_config(self):
main_config = _override_from(super(VimPowerline, self).load_main_config(), 'powerline_config_overrides')
try:
use_var_handler = bool(int(vim_getvar('powerline_use_var_handler')))
except KeyError:
use_var_handler = False
if use_var_handler:
main_config.setdefault('common', {})
main_config['common'] = finish_common_config(self.get_encoding(), main_config['common'])
main_config['common']['log_file'].append(['powerline.vim.VimVarHandler', [['powerline_log_messages']]])
return main_config
def load_theme_config(self, name):
return _override_from(
super(VimPowerline, self).load_theme_config(name),
'powerline_theme_overrides',
name
)
def get_local_themes(self, local_themes):
if not local_themes:
return {}
return dict((
(matcher, {'config': self.load_theme_config(val)})
for matcher, key, val in (
(
(None if k == '__tabline__' else self.get_matcher(k)),
k,
v
)
for k, v in local_themes.items()
) if (
matcher or
key == '__tabline__'
)
))
def get_matcher(self, match_name):
match_module, separator, match_function = match_name.rpartition('.')
if not separator:
match_module = 'powerline.matchers.{0}'.format(self.ext)
match_function = match_name
return self.get_module_attr(match_module, match_function, prefix='matcher_generator')
def get_config_paths(self):
try:
return vim_getvar('powerline_config_paths')
except KeyError:
return super(VimPowerline, self).get_config_paths()
def do_setup(self, pyeval=None, pycmd=None, can_replace_pyeval=True, _local_themes=()):
import __main__
if not pyeval:
pyeval = 'pyeval' if sys.version_info < (3,) else 'py3eval'
can_replace_pyeval = True
if not pycmd:
pycmd = get_default_pycmd()
set_pycmd(pycmd)
# pyeval() and vim.bindeval were both introduced in one patch
if (not hasattr(vim, 'bindeval') and can_replace_pyeval) or pyeval == 'PowerlinePyeval':
vim.command(('''
function! PowerlinePyeval(e)
{pycmd} powerline.do_pyeval()
endfunction
''').format(pycmd=pycmd))
pyeval = 'PowerlinePyeval'
self.pyeval = pyeval
self.construct_window_statusline = self.create_window_statusline_constructor()
self.update_renderer()
__main__.powerline = self
try:
if (
bool(int(vim.eval('has(\'gui_running\') && argc() == 0')))
and not vim.current.buffer.name
and len(vim.windows) == 1
):
# Hack to show startup screen. Problems in GUI:
# - Defining local value of &statusline option while computing
# global value purges startup screen.
# - Defining highlight group while computing statusline purges
# startup screen.
# This hack removes the “while computing statusline” part: both
# things are defined, but they are defined right now.
#
# The above condition disables this hack if no GUI is running,
# Vim did not open any files and there is only one window.
# Without GUI everything works, in other cases startup screen is
# not shown.
self.new_window()
except UnicodeDecodeError:
# vim.current.buffer.name may raise UnicodeDecodeError when using
# Python-3*. Fortunately, this means that current buffer is not
# empty buffer, so the above condition should be False.
pass
# Cannot have this in one line due to weird newline handling (in :execute
# context newline is considered part of the command in just the same cases
# when bar is considered part of the command (unless defining function
# inside :execute)). vim.command is :execute equivalent regarding this case.
vim.command('augroup Powerline')
vim.command(' autocmd! ColorScheme * :{pycmd} powerline.reset_highlight()'.format(pycmd=pycmd))
vim.command(' autocmd! VimLeavePre * :{pycmd} powerline.shutdown()'.format(pycmd=pycmd))
vim.command('augroup END')
# Hack for local themes support after reloading.
for args in _local_themes:
self.add_local_theme(*args)
def reset_highlight(self):
try:
self.renderer.reset_highlight()
except AttributeError:
# Renderer object appears only after first `.render()` call. Thus if
# ColorScheme event happens before statusline is drawn for the first
# time AttributeError will be thrown for the self.renderer. It is
# fine to ignore it: no renderer == no colors to reset == no need to
# do anything.
pass
def new_win_idx(self, window_id):
r = None
for window in vim.windows:
try:
curwindow_id = window.vars['powerline_window_id']
if r is not None and curwindow_id == window_id:
raise KeyError
except KeyError:
curwindow_id = self.last_window_id
self.last_window_id += 1
window.vars['powerline_window_id'] = curwindow_id
statusline = self.construct_window_statusline(curwindow_id)
if window.options['statusline'] != statusline:
window.options['statusline'] = statusline
if curwindow_id == window_id if window_id else window is vim.current.window:
r = (window, curwindow_id, window.number)
return r
def old_win_idx(self, window_id):
r = None
for winnr, window in zip(count(1), vim.windows):
curwindow_id = self._vim_getwinvar(winnr, 'powerline_window_id')
if curwindow_id and not (r is not None and curwindow_id == window_id):
curwindow_id = int(curwindow_id)
else:
curwindow_id = self.last_window_id
self.last_window_id += 1
self._vim_setwinvar(winnr, 'powerline_window_id', curwindow_id)
statusline = self.construct_window_statusline(curwindow_id)
if self._vim_getwinvar(winnr, '&statusline') != statusline:
self._vim_setwinvar(winnr, '&statusline', statusline)
if curwindow_id == window_id if window_id else window is vim.current.window:
r = (window, curwindow_id, winnr)
return r
def statusline(self, window_id):
window, window_id, winnr = self.win_idx(window_id) or (None, None, None)
if not window:
return FailedUnicode('No window {0}'.format(window_id))
return self.render(window, window_id, winnr)
def tabline(self):
return self.render(*self.win_idx(None), is_tabline=True)
def new_window(self):
return self.render(*self.win_idx(None))
@staticmethod
def do_pyeval():
'''Evaluate python string passed to PowerlinePyeval
Is here to reduce the number of requirements to __main__ globals to just
one powerline object (previously it required as well vim and json).
'''
import __main__
vim.command('return ' + json.dumps(eval(vim.eval('a:e'), __main__.__dict__)))
def setup_components(self, components):
if components is None:
components = ('statusline', 'tabline')
if 'statusline' in components:
# Is immediately changed after new_window function is run. Good for
# global value.
vim.command('set statusline=%!{pyeval}(\'powerline.new_window()\')'.format(
pyeval=self.pyeval))
if 'tabline' in components:
vim.command('set tabline=%!{pyeval}(\'powerline.tabline()\')'.format(
pyeval=self.pyeval))
pycmd = None
def set_pycmd(new_pycmd):
global pycmd
pycmd = new_pycmd
def get_default_pycmd():
return 'python' if sys.version_info < (3,) else 'python3'
def setup(*args, **kwargs):
powerline = VimPowerline()
return powerline.setup(*args, **kwargs)
|