summaryrefslogtreecommitdiffstats
path: root/powerline/renderers/vim.py
diff options
context:
space:
mode:
Diffstat (limited to 'powerline/renderers/vim.py')
-rw-r--r--powerline/renderers/vim.py188
1 files changed, 188 insertions, 0 deletions
diff --git a/powerline/renderers/vim.py b/powerline/renderers/vim.py
new file mode 100644
index 0000000..a92d51c
--- /dev/null
+++ b/powerline/renderers/vim.py
@@ -0,0 +1,188 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+
+import vim
+
+from powerline.bindings.vim import vim_get_func, vim_getoption, environ, current_tabpage, get_vim_encoding
+from powerline.renderer import Renderer
+from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
+from powerline.theme import Theme
+from powerline.lib.unicode import unichr, register_strwidth_error
+
+
+vim_mode = vim_get_func('mode', rettype='unicode')
+if int(vim.eval('v:version')) >= 702:
+ _vim_mode = vim_mode
+ vim_mode = lambda: _vim_mode(1)
+
+mode_translations = {
+ unichr(ord('V') - 0x40): '^V',
+ unichr(ord('S') - 0x40): '^S',
+}
+
+
+class VimRenderer(Renderer):
+ '''Powerline vim segment renderer.'''
+
+ character_translations = Renderer.character_translations.copy()
+ character_translations[ord('%')] = '%%'
+
+ segment_info = Renderer.segment_info.copy()
+ segment_info.update(environ=environ)
+
+ def __init__(self, *args, **kwargs):
+ if not hasattr(vim, 'strwidth'):
+ # Hope nobody want to change this at runtime
+ if vim.eval('&ambiwidth') == 'double':
+ kwargs = dict(**kwargs)
+ kwargs['ambigious'] = 2
+ super(VimRenderer, self).__init__(*args, **kwargs)
+ self.hl_groups = {}
+ self.prev_highlight = None
+ self.strwidth_error_name = register_strwidth_error(self.strwidth)
+ self.encoding = get_vim_encoding()
+
+ def shutdown(self):
+ self.theme.shutdown()
+ for match in self.local_themes.values():
+ if 'theme' in match:
+ match['theme'].shutdown()
+
+ def add_local_theme(self, matcher, theme):
+ if matcher in self.local_themes:
+ raise KeyError('There is already a local theme with given matcher')
+ self.local_themes[matcher] = theme
+
+ def get_matched_theme(self, match):
+ try:
+ return match['theme']
+ except KeyError:
+ match['theme'] = Theme(theme_config=match['config'], main_theme_config=self.theme_config, **self.theme_kwargs)
+ return match['theme']
+
+ def get_theme(self, matcher_info):
+ if matcher_info is None:
+ return self.get_matched_theme(self.local_themes[None])
+ for matcher in self.local_themes.keys():
+ if matcher and matcher(matcher_info):
+ return self.get_matched_theme(self.local_themes[matcher])
+ else:
+ return self.theme
+
+ if hasattr(vim, 'strwidth'):
+ if sys.version_info < (3,):
+ def strwidth(self, string):
+ # Does not work with tabs, but neither is strwidth from default
+ # renderer
+ return vim.strwidth(string.encode(self.encoding, 'replace'))
+ else:
+ @staticmethod
+ def strwidth(string):
+ return vim.strwidth(string)
+
+ def get_segment_info(self, segment_info, mode):
+ return segment_info or self.segment_info
+
+ def render(self, window=None, window_id=None, winnr=None, is_tabline=False):
+ '''Render all segments.'''
+ segment_info = self.segment_info.copy()
+
+ if window is vim.current.window:
+ mode = vim_mode()
+ mode = mode_translations.get(mode, mode)
+ else:
+ mode = 'nc'
+
+ segment_info.update(
+ window=window,
+ mode=mode,
+ window_id=window_id,
+ winnr=winnr,
+ buffer=window.buffer,
+ tabpage=current_tabpage(),
+ encoding=self.encoding,
+ )
+ segment_info['tabnr'] = segment_info['tabpage'].number
+ segment_info['bufnr'] = segment_info['buffer'].number
+ if is_tabline:
+ winwidth = int(vim_getoption('columns'))
+ else:
+ winwidth = segment_info['window'].width
+
+ statusline = super(VimRenderer, self).render(
+ mode=mode,
+ width=winwidth,
+ segment_info=segment_info,
+ matcher_info=(None if is_tabline else segment_info),
+ )
+ statusline = statusline.encode(self.encoding, self.strwidth_error_name)
+ return statusline
+
+ def reset_highlight(self):
+ self.hl_groups.clear()
+
+ def hlstyle(self, fg=None, bg=None, attrs=None, **kwargs):
+ '''Highlight a segment.
+
+ If an argument is None, the argument is ignored. If an argument is
+ False, the argument is reset to the terminal defaults. If an argument
+ is a valid color or attribute, it’s added to the vim highlight group.
+ '''
+ # In order not to hit E541 two consequent identical highlighting
+ # specifiers may be squashed into one.
+ attrs = attrs or 0 # Normalize `attrs`
+ if (fg, bg, attrs) == self.prev_highlight:
+ return ''
+ self.prev_highlight = (fg, bg, attrs)
+
+ # We don’t need to explicitly reset attributes in vim, so skip those
+ # calls
+ if not attrs and not bg and not fg:
+ return ''
+
+ if not (fg, bg, attrs) in self.hl_groups:
+ hl_group = {
+ 'ctermfg': 'NONE',
+ 'guifg': None,
+ 'ctermbg': 'NONE',
+ 'guibg': None,
+ 'attrs': ['NONE'],
+ 'name': '',
+ }
+ if fg is not None and fg is not False:
+ hl_group['ctermfg'] = fg[0]
+ hl_group['guifg'] = fg[1]
+ if bg is not None and bg is not False:
+ hl_group['ctermbg'] = bg[0]
+ hl_group['guibg'] = bg[1]
+ if attrs:
+ hl_group['attrs'] = []
+ if attrs & ATTR_BOLD:
+ hl_group['attrs'].append('bold')
+ if attrs & ATTR_ITALIC:
+ hl_group['attrs'].append('italic')
+ if attrs & ATTR_UNDERLINE:
+ hl_group['attrs'].append('underline')
+ hl_group['name'] = (
+ 'Pl_'
+ + str(hl_group['ctermfg']) + '_'
+ + str(hl_group['guifg']) + '_'
+ + str(hl_group['ctermbg']) + '_'
+ + str(hl_group['guibg']) + '_'
+ + ''.join(hl_group['attrs'])
+ )
+ self.hl_groups[(fg, bg, attrs)] = hl_group
+ vim.command('hi {group} ctermfg={ctermfg} guifg={guifg} guibg={guibg} ctermbg={ctermbg} cterm={attrs} gui={attrs}'.format(
+ group=hl_group['name'],
+ ctermfg=hl_group['ctermfg'],
+ guifg='#{0:06x}'.format(hl_group['guifg']) if hl_group['guifg'] is not None else 'NONE',
+ ctermbg=hl_group['ctermbg'],
+ guibg='#{0:06x}'.format(hl_group['guibg']) if hl_group['guibg'] is not None else 'NONE',
+ attrs=','.join(hl_group['attrs']),
+ ))
+ return '%#' + self.hl_groups[(fg, bg, attrs)]['name'] + '#'
+
+
+renderer = VimRenderer