Restructure segment rendering methods

Theme.get_segments() is now a generator which returns segment copies,
and it no longer handles segment content replacement.

Renderer.render() accepts a theme and a segments parameter in order to
override the default actions (calling self.get_theme() and
self.get_segments()). This is necessary to be able to cache themes and
segment contents somewhere else and provide the cached data to the
render method. The render method now also handles removing excluded
segments, which was previously handled in Theme.get_segments().

Finally, VimRenderer.render() caches all theme and segment data and
provides this data to the renderer for non-current windows.

Closes #12.
This commit is contained in:
Kim Silkebækken 2012-12-17 13:18:40 +01:00
parent 3a8e64b767
commit ccd6b4c28a
3 changed files with 23 additions and 30 deletions

View File

@ -33,17 +33,16 @@ class VimRenderer(Renderer):
if current:
mode = vim_mode()
contents_override = None
theme = self.get_theme()
segments = [segment for segment in theme.get_segments()]
self.window_cache[window_id] = (theme, segments)
else:
mode = 'nc'
contents_override = self.window_cache.get(window_id)
theme, segments = self.window_cache.get(window_id, (None, None))
statusline = super(VimRenderer, self).render(mode, width=winwidth, contents_override=contents_override)
statusline = super(VimRenderer, self).render(mode, winwidth, theme, segments)
statusline = statusline.replace(self.PERCENT_PLACEHOLDER, '%%')
if current:
self.window_cache[window_id] = {segment['key']: segment['contents'] for segment in self.segments if segment['type'] == 'function'}
return statusline
def hl(self, fg=None, bg=None, attr=None):

View File

@ -13,7 +13,6 @@ class Renderer(object):
self.theme = Theme(theme_config=theme_config, **theme_kwargs)
self.local_themes = local_themes
self.theme_kwargs = theme_kwargs
self.segments = []
def get_theme(self):
for matcher in self.local_themes.iterkeys():
@ -25,7 +24,7 @@ class Renderer(object):
else:
return self.theme
def render(self, mode, width=None, contents_override=None):
def render(self, mode, width=None, theme=None, segments=None):
'''Render all segments.
When a width is provided, low-priority segments are dropped one at
@ -34,10 +33,13 @@ class Renderer(object):
provided they will fill the remaining space until the desired width is
reached.
'''
theme = self.get_theme()
theme = theme or self.get_theme()
segments = segments or theme.get_segments()
# Handle excluded/included segments for the current mode
segments = [segment for segment in segments\
if mode not in segment['exclude_modes'] or (segment['include_modes'] and segment in segment['include_modes'])]
segments = theme.get_segments(mode, contents_override)
self.segments = segments
rendered_highlighted = self._render_segments(mode, theme, segments)
if not width:

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
import copy
class Theme(object):
def __init__(self, ext, colorscheme, theme_config, common_config, get_segment):
@ -20,23 +22,14 @@ class Theme(object):
'''
return self.dividers[side][type]
def get_segments(self, mode, contents_override=None):
def get_segments(self):
'''Return all segments.
Function segments are called, and all segments get their before/after
and ljust/rjust properties applied.
'''
contents_override = contents_override or {}
return_segments = []
for segment in self.segments:
if mode in segment['exclude_modes'] or (segment['include_modes'] and segment not in segment['include_modes']):
continue
if segment['type'] == 'function':
contents = contents_override.get(segment['key'])
if contents is None:
if contents_override:
continue
contents = segment['contents_func'](**segment['args'])
if contents is None:
@ -52,12 +45,11 @@ class Theme(object):
else:
continue
if segment['key'] not in contents_override:
# Only apply before/after/just to non-overridden segments
segment['contents'] = unicode(segment['before'] + unicode(segment['contents']) + segment['after'])\
.ljust(segment['ljust'])\
.rjust(segment['rjust'])
return_segments.append(segment)
return return_segments
# We need to yield a copy of the segment, or else mode-dependent
# segment contents can't be cached correctly e.g. when caching
# non-current window contents for vim statuslines
yield copy.copy(segment)