Split colorschemes and add better gradient support

- Splitted colorschemes into colors definitions file (TODO: remove non-colors
  definitions like weather_condition_hot and base00) and actual colorscheme.
- Removed dictionary containing groups definitions for all groups for all modes,
  now colorscheme is queried for this each time.
- Moved determination of colors from theme to renderer.
- Added gradients definitions (actually, only one) to new colors file.
- Made line_percent with gradient=True use new gradients.
This commit is contained in:
ZyX 2013-02-23 01:05:18 +04:00 committed by Kim Silkebækken
parent b8b0518e9b
commit 01b34a7893
16 changed files with 229 additions and 359 deletions

View File

@ -155,15 +155,12 @@ Common configuration is a subdictionary that is a value of ``ext`` key in
Defines themes used when certain conditions are met, e.g. for Defines themes used when certain conditions are met, e.g. for
buffer-specific statuslines in vim. Requires a custom matcher and theme. buffer-specific statuslines in vim. Requires a custom matcher and theme.
Colorschemes Color definitions
============ =================
:Location: :file:`powerline/colorschemes/{extension}/{name}.json` :Location: :file:`powerline/colors.json`
``name`` .. _config-colors-colors:
Name of the colorscheme.
.. _config-colorscheme-colors:
``colors`` ``colors``
Color definitions, consisting of a dict where the key is the name of the Color definitions, consisting of a dict where the key is the name of the
@ -174,6 +171,22 @@ Colorschemes
"aabbcc"]``). This is useful for colorschemes that use colors that "aabbcc"]``). This is useful for colorschemes that use colors that
aren't available in color terminals. aren't available in color terminals.
``gradients``
Gradient definitions, consisting of a dict where the key is the name of the
gradient, and the value is a list containing one or two items, second item
is optional:
* A list of cterm color indicies.
* A list of hex color strings.
Colorschemes
============
:Location: :file:`powerline/colorschemes/{extension}/{name}.json`
``name``
Name of the colorscheme.
.. _config-colorscheme-groups: .. _config-colorscheme-groups:
``groups`` ``groups``
@ -184,11 +197,11 @@ Colorschemes
``fg`` ``fg``
Foreground color. Must be defined in :ref:`colors Foreground color. Must be defined in :ref:`colors
<config-colorscheme-colors>`. <config-colors-colors>`.
``bg`` ``bg``
Background color. Must be defined in :ref:`colors Background color. Must be defined in :ref:`colors
<config-colorscheme-colors>`. <config-colors-colors>`.
``attr`` ``attr``
Optional list of attributes. Valid values are one or more of Optional list of attributes. Valid values are one or more of
@ -203,8 +216,8 @@ Colorschemes
``colors`` ``colors``
A dict where the key is the color to be translated in this mode, and A dict where the key is the color to be translated in this mode, and
the value is the new color. Both the key and the value must be the value is the new color. Both the key and the value must be defined
defined in :ref:`colors <config-colorscheme-colors>`. in :ref:`colors <config-colors-colors>`.
``groups`` ``groups``
Segment highlighting groups for this mode. Same syntax as the main Segment highlighting groups for this mode. Same syntax as the main

View File

@ -31,7 +31,8 @@ class Powerline(object):
# Load and initialize colorscheme # Load and initialize colorscheme
colorscheme_config = self.load_colorscheme_config(ext_config['colorscheme']) colorscheme_config = self.load_colorscheme_config(ext_config['colorscheme'])
colorscheme = Colorscheme(colorscheme_config) colors_config = self.load_colors_config()
colorscheme = Colorscheme(colorscheme_config, colors_config)
# Load and initialize extension theme # Load and initialize extension theme
theme_config = self.load_theme_config(ext_config.get('theme', 'default')) theme_config = self.load_theme_config(ext_config.get('theme', 'default'))
@ -39,7 +40,6 @@ class Powerline(object):
self.import_paths = common_config['paths'] self.import_paths = common_config['paths']
theme_kwargs = { theme_kwargs = {
'ext': ext, 'ext': ext,
'colorscheme': colorscheme,
'common_config': common_config, 'common_config': common_config,
'segment_info': self.get_segment_info(), 'segment_info': self.get_segment_info(),
} }
@ -55,7 +55,7 @@ class Powerline(object):
sys.stderr.write('Error while importing renderer module: {0}\n'.format(e)) sys.stderr.write('Error while importing renderer module: {0}\n'.format(e))
sys.exit(1) sys.exit(1)
options = {'term_truecolor': common_config.get('term_24bit_colors', False)} options = {'term_truecolor': common_config.get('term_24bit_colors', False)}
self.renderer = Renderer(theme_config, local_themes, theme_kwargs, **options) self.renderer = Renderer(theme_config, local_themes, theme_kwargs, colorscheme, **options)
def get_config_paths(self): def get_config_paths(self):
config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')) config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
@ -72,6 +72,9 @@ class Powerline(object):
def load_colorscheme_config(self, name): def load_colorscheme_config(self, name):
return load_json_config(self.config_paths, os.path.join('colorschemes', self.ext, name)) return load_json_config(self.config_paths, os.path.join('colorschemes', self.ext, name))
def load_colors_config(self):
return load_json_config(self.config_paths, 'colors')
@staticmethod @staticmethod
def get_local_themes(local_themes): def get_local_themes(local_themes):
return {} return {}

View File

@ -1,95 +1,108 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from copy import copy
DEFAULT_MODE_KEY = None DEFAULT_MODE_KEY = None
ATTR_BOLD = 1 ATTR_BOLD = 1
ATTR_ITALIC = 2 ATTR_ITALIC = 2
ATTR_UNDERLINE = 4 ATTR_UNDERLINE = 4
def get_attr_flag(attributes):
'''Convert an attribute array to a renderer flag.'''
attr_flag = 0
if 'bold' in attributes:
attr_flag |= ATTR_BOLD
if 'italic' in attributes:
attr_flag |= ATTR_ITALIC
if 'underline' in attributes:
attr_flag |= ATTR_UNDERLINE
return attr_flag
def pick_gradient_value(grad_list, gradient_level):
'''Given a list of colors and gradient percent, return a color that should be used.
Note: gradient level is not checked for being inside [0, 100] interval.
'''
return grad_list[int(round(gradient_level * (len(grad_list) - 1) / 100))]
class Colorscheme(object): class Colorscheme(object):
def __init__(self, colorscheme_config): def __init__(self, colorscheme_config, colors_config):
'''Initialize a colorscheme.''' '''Initialize a colorscheme.'''
self.colors = {} self.colors = {}
self.modes_groups = {DEFAULT_MODE_KEY: {}} self.gradients = {}
self.groups = colorscheme_config['groups']
self.translations = colorscheme_config.get('mode_translations', {})
# Create a dict of color tuples with both a cterm and hex value # Create a dict of color tuples with both a cterm and hex value
for color_name, color in colorscheme_config['colors'].items(): for color_name, color in colors_config['colors'].items():
try: try:
self.colors[color_name] = (color[0], int(color[1], 16)) self.colors[color_name] = (color[0], int(color[1], 16))
except TypeError: except TypeError:
self.colors[color_name] = (color, cterm_to_hex[color]) self.colors[color_name] = (color, cterm_to_hex[color])
# Create highlighting groups for all modes # Create a dict of gradient names with two lists: for cterm and hex
for group_name, group_props in colorscheme_config['groups'].items(): # values. Two lists in place of one list of pairs were chosen because
group_attr_flag = self._get_attr_flag(group_props.get('attr', [])) # true colors allow more precise gradients.
self.modes_groups[DEFAULT_MODE_KEY][group_name] = { for gradient_name, gradient in colors_config['gradients'].items():
'fg': self.colors[group_props['fg']], if len(gradient) == 2:
'bg': self.colors[group_props['bg']], self.gradients[gradient_name] = (
'attr': group_attr_flag, (gradient[0], [int(color, 16) for color in gradient[1]]))
} else:
self.gradients[gradient_name] = (
(gradient[0], [cterm_to_hex[color] for color in gradient[0]]))
# Create mode-specific highlighting for this group def get_gradient(self, gradient, gradient_level):
for mode, translations in colorscheme_config.get('mode_translations', {}).items(): if gradient in self.gradients:
if not mode in self.modes_groups: return tuple((pick_gradient_value(grad_list, gradient_level) for grad_list in self.gradients[gradient]))
self.modes_groups[mode] = {} else:
if group_name in translations.get('groups', {}): return self.colors[gradient]
# Override entire group if present in the translations group dict
self.modes_groups[mode][group_name] = {
'fg': self.colors[translations['groups'][group_name]['fg']],
'bg': self.colors[translations['groups'][group_name]['bg']],
'attr': self._get_attr_flag(translations['groups'][group_name].get('attr', [])),
}
else:
# Fallback to color translations from the translations colors dict
self.modes_groups[mode][group_name] = {
'fg': self.colors[translations.get('colors', {}).get(group_props['fg'], group_props['fg'])],
'bg': self.colors[translations.get('colors', {}).get(group_props['bg'], group_props['bg'])],
'attr': group_attr_flag,
}
def get_group_highlighting(self, group): def get_highlighting(self, groups, mode, gradient_level=None):
'''Return highlighting information for all modes of a highlighting group.''' trans = self.translations.get(mode, {})
group_highlighting = {} for group in groups:
for mode, mode_group in self.modes_groups.items(): if 'groups' in trans and group in trans['groups']:
try: try:
group_highlighting[mode] = mode_group[group] group_props = trans['groups'][group]
except TypeError: except KeyError:
for try_group in group: continue
if try_group in self.modes_groups[mode]: break
group_highlighting[mode] = mode_group[try_group]
break
finally:
if mode not in group_highlighting:
raise KeyError('Highlighting groups not found in colorscheme: {0}'.format(group))
return group_highlighting
def get_highlighting(self, group, mode=None): else:
'''Return highlighting information for a highlighting group and mode. try:
group_props = copy(self.groups[group])
except KeyError:
continue
If no mode is specified, or the mode doesn't exist, highlighting for try:
the default mode is returned. ctrans = trans['colors']
''' for key in ('fg', 'bg'):
if not mode or mode not in self.modes_groups: try:
mode = DEFAULT_MODE_KEY group_props[key] = ctrans[group_props[key]]
try: except KeyError:
return self.modes_groups[mode][group] pass
except TypeError: except KeyError:
for try_group in group: pass
if try_group in self.modes_groups[mode]:
return self.modes_groups[mode][try_group] break
raise KeyError('Highlighting groups not found in colorscheme: {0}'.format(group)) else:
return self.modes_groups[mode][group] raise KeyError('Highlighting groups not found in colorscheme: ' + ', '.join(groups))
if gradient_level is None:
pick_color = self.colors.__getitem__
else:
pick_color = lambda gradient : self.get_gradient(gradient, gradient_level)
return {
'fg': pick_color(group_props['fg']),
'bg': pick_color(group_props['bg']),
'attr': get_attr_flag(group_props.get('attr', [])),
}
def _get_attr_flag(self, attributes):
'''Convert an attribute array to a renderer flag.'''
attr_flag = 0
if 'bold' in attributes:
attr_flag |= ATTR_BOLD
if 'italic' in attributes:
attr_flag |= ATTR_ITALIC
if 'underline' in attributes:
attr_flag |= ATTR_UNDERLINE
return attr_flag
cterm_to_hex = { cterm_to_hex = {
16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff, 16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,

View File

@ -0,0 +1,82 @@
{
"colors": {
"black": 16,
"white": 231,
"green": [2, "719e07"],
"darkestgreen": 22,
"darkgreen": 28,
"mediumgreen": 70,
"brightgreen": 148,
"cyan": [6, "2aa198"],
"darkestcyan": 23,
"darkcyan": 74,
"mediumcyan": 117,
"brightcyan": 159,
"blue": [4, "268bd2"],
"darkestblue": 24,
"darkblue": 31,
"red": [1, "dc322f"],
"darkestred": 52,
"darkred": 88,
"mediumred": 124,
"brightred": 160,
"brightestred": 196,
"magenta": [5, "d33682"],
"darkestpurple": 55,
"mediumpurple": 98,
"brightpurple": 189,
"violet": [13, "6c71c4"],
"orange": [9, "cb4b16"],
"darkorange": 94,
"mediumorange": 166,
"brightorange": 208,
"brightestorange": 214,
"yellow": [3, "b58900"],
"brightyellow": 220,
"gray0": 233,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 252,
"base03": [8, "002b36"],
"base02": [0, "073642"],
"base01": [10, "586e75"],
"base00": [11, "657b83"],
"base0": [12, "839496"],
"base1": [14, "93a1a1"],
"base2": [7, "eee8d5"],
"base3": [15, "fdf6e3"],
"system_load_good": 106,
"system_load_bad": 178,
"system_load_ugly": 202,
"weather_temp_cold": 67,
"weather_temp_hot": 166,
"weather_condition_cold": 117,
"weather_condition_hot": 228
},
"gradients": {
"green_yellow_red": [
[190, 184, 178, 172, 166, 160],
["8ae71c", "c2e821", "e9d926", "eaa72b", "eb7830", "ec4b35"]
]
}
}

View File

@ -1,23 +1,5 @@
{ {
"name": "Default color scheme for IPython prompt", "name": "Default color scheme for IPython prompt",
"colors": {
"black": 16,
"white": 231,
"darkcyan": 74,
"gray0": 233,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 252
},
"groups": { "groups": {
"virtualenv": { "fg": "white", "bg": "darkcyan" }, "virtualenv": { "fg": "white", "bg": "darkcyan" },
"prompt": { "fg": "gray9", "bg": "gray4" } "prompt": { "fg": "gray9", "bg": "gray4" }

View File

@ -1,58 +1,5 @@
{ {
"name": "Default color scheme for shell prompts", "name": "Default color scheme for shell prompts",
"colors": {
"black": 16,
"white": 231,
"darkestgreen": 22,
"darkgreen": 28,
"mediumgreen": 70,
"brightgreen": 148,
"darkestcyan": 23,
"darkcyan": 74,
"mediumcyan": 117,
"brightcyan": 159,
"darkestblue": 24,
"darkblue": 31,
"darkestred": 52,
"darkred": 88,
"mediumred": 124,
"brightred": 160,
"brightestred": 196,
"darkestpurple": 55,
"mediumpurple": 98,
"brightpurple": 189,
"darkorange": 94,
"mediumorange": 166,
"brightorange": 208,
"brightestorange": 214,
"brightyellow": 220,
"gray0": 233,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 252,
"gradient1": 190,
"gradient2": 184,
"gradient3": 178,
"gradient4": 172,
"gradient5": 166,
"gradient6": 160
},
"groups": { "groups": {
"user": { "fg": "white", "bg": "darkblue", "attr": ["bold"] }, "user": { "fg": "white", "bg": "darkblue", "attr": ["bold"] },
"superuser": { "fg": "white", "bg": "brightred", "attr": ["bold"] }, "superuser": { "fg": "white", "bg": "brightred", "attr": ["bold"] },

View File

@ -1,23 +1,5 @@
{ {
"name": "Solarized Dark", "name": "Solarized Dark",
"colors": {
"base03": [8, "002b36"],
"base02": [0, "073642"],
"base01": [10, "586e75"],
"base00": [11, "657b83"],
"base0": [12, "839496"],
"base1": [14, "93a1a1"],
"base2": [7, "eee8d5"],
"base3": [15, "fdf6e3"],
"yellow": [3, "b58900"],
"orange": [9, "cb4b16"],
"red": [1, "dc322f"],
"magenta": [5, "d33682"],
"violet": [13, "6c71c4"],
"blue": [4, "268bd2"],
"cyan": [6, "2aa198"],
"green": [2, "719e07"]
},
"groups": { "groups": {
"user": { "fg": "base3", "bg": "blue", "attr": ["bold"] }, "user": { "fg": "base3", "bg": "blue", "attr": ["bold"] },
"superuser": { "fg": "base3", "bg": "red", "attr": ["bold"] }, "superuser": { "fg": "base3", "bg": "red", "attr": ["bold"] },

View File

@ -1,38 +1,5 @@
{ {
"name": "Default color scheme for terminal prompts", "name": "Default color scheme for terminal prompts",
"colors": {
"black": 16,
"white": 231,
"brightred": 160,
"darkestblue": 24,
"darkblue": 31,
"mediumblue": 38,
"brightblue": 117,
"brightestblue": 153,
"gray0": 234,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 254,
"system_load_good": 106,
"system_load_bad": 178,
"system_load_ugly": 202,
"weather_temp_cold": 67,
"weather_temp_hot": 166,
"weather_condition_cold": 117,
"weather_condition_hot": 228
},
"groups": { "groups": {
"background:divider": { "fg": "gray5", "bg": "gray0" }, "background:divider": { "fg": "gray5", "bg": "gray0" },
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] }, "session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },

View File

@ -1,58 +1,5 @@
{ {
"name": "Default color scheme", "name": "Default color scheme",
"colors": {
"black": 16,
"white": 231,
"darkestgreen": 22,
"darkgreen": 28,
"mediumgreen": 70,
"brightgreen": 148,
"darkestcyan": 23,
"darkcyan": 74,
"mediumcyan": 117,
"brightcyan": 159,
"darkestblue": 24,
"darkblue": 31,
"darkestred": 52,
"darkred": 88,
"mediumred": 124,
"brightred": 160,
"brightestred": 196,
"darkestpurple": 55,
"mediumpurple": 98,
"brightpurple": 189,
"darkorange": 94,
"mediumorange": 166,
"brightorange": 208,
"brightestorange": 214,
"brightyellow": 220,
"gray0": 233,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 252,
"gradient1": [190, "8ae71c"],
"gradient2": [184, "c2e821"],
"gradient3": [178, "e9d926"],
"gradient4": [172, "eaa72b"],
"gradient5": [166, "eb7830"],
"gradient6": [160, "ec4b35"]
},
"groups": { "groups": {
"background": { "fg": "white", "bg": "gray2" }, "background": { "fg": "white", "bg": "gray2" },
"background:divider": { "fg": "gray6", "bg": "gray2" }, "background:divider": { "fg": "gray6", "bg": "gray2" },
@ -74,12 +21,7 @@
"file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4" }, "file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4" },
"file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4" }, "file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4" },
"line_percent": { "fg": "gray9", "bg": "gray4" }, "line_percent": { "fg": "gray9", "bg": "gray4" },
"line_percent_gradient1": { "fg": "gradient1", "bg": "gray4" }, "line_percent_gradient": { "fg": "green_yellow_red", "bg": "gray4" },
"line_percent_gradient2": { "fg": "gradient2", "bg": "gray4" },
"line_percent_gradient3": { "fg": "gradient3", "bg": "gray4" },
"line_percent_gradient4": { "fg": "gradient4", "bg": "gray4" },
"line_percent_gradient5": { "fg": "gradient5", "bg": "gray4" },
"line_percent_gradient6": { "fg": "gradient6", "bg": "gray4" },
"line_current": { "fg": "gray1", "bg": "gray10", "attr": ["bold"] }, "line_current": { "fg": "gray1", "bg": "gray10", "attr": ["bold"] },
"line_current_symbol": { "fg": "gray1", "bg": "gray10" }, "line_current_symbol": { "fg": "gray1", "bg": "gray10" },
"col_current": { "fg": "gray6", "bg": "gray10" }, "col_current": { "fg": "gray6", "bg": "gray10" },
@ -102,12 +44,7 @@
"gray9": "gray4", "gray9": "gray4",
"gray10": "gray5", "gray10": "gray5",
"white": "gray6", "white": "gray6",
"gradient1": "gray5", "green_yellow_red": "gray5"
"gradient2": "gray5",
"gradient3": "gray5",
"gradient4": "gray5",
"gradient5": "gray5",
"gradient6": "gray5"
} }
}, },
"i": { "i": {
@ -123,12 +60,7 @@
"gray8": "mediumcyan", "gray8": "mediumcyan",
"gray9": "mediumcyan", "gray9": "mediumcyan",
"gray10": "mediumcyan", "gray10": "mediumcyan",
"gradient1": "mediumcyan", "green_yellow_red": "gray5"
"gradient2": "mediumcyan",
"gradient3": "mediumcyan",
"gradient4": "mediumcyan",
"gradient5": "mediumcyan",
"gradient6": "mediumcyan"
}, },
"groups": { "groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attr": ["bold"] }, "mode": { "fg": "darkestcyan", "bg": "white", "attr": ["bold"] },

View File

@ -1,23 +1,5 @@
{ {
"name": "Solarized Dark", "name": "Solarized Dark",
"colors": {
"base03": [8, "002b36"],
"base02": [0, "073642"],
"base01": [10, "586e75"],
"base00": [11, "657b83"],
"base0": [12, "839496"],
"base1": [14, "93a1a1"],
"base2": [7, "eee8d5"],
"base3": [15, "fdf6e3"],
"yellow": [3, "b58900"],
"orange": [9, "cb4b16"],
"red": [1, "dc322f"],
"magenta": [5, "d33682"],
"violet": [13, "6c71c4"],
"blue": [4, "268bd2"],
"cyan": [6, "2aa198"],
"green": [2, "719e07"]
},
"groups": { "groups": {
"background": { "fg": "base3", "bg": "base02" }, "background": { "fg": "base3", "bg": "base02" },
"background:divider": { "fg": "base00", "bg": "base02" }, "background:divider": { "fg": "base00", "bg": "base02" },

View File

@ -1,38 +1,5 @@
{ {
"name": "Default color scheme for window managers", "name": "Default color scheme for window managers",
"colors": {
"black": 16,
"white": 231,
"brightred": 160,
"darkestblue": 24,
"darkblue": 31,
"mediumblue": 38,
"brightblue": 117,
"brightestblue": 153,
"gray0": 234,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 254,
"system_load_good": 106,
"system_load_bad": 178,
"system_load_ugly": 202,
"weather_temp_cold": 67,
"weather_temp_hot": 166,
"weather_condition_cold": 117,
"weather_condition_hot": 228
},
"groups": { "groups": {
"background:divider": { "fg": "gray5", "bg": "gray0" }, "background:divider": { "fg": "gray5", "bg": "gray0" },
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] }, "session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },

View File

@ -11,7 +11,8 @@
"soft": " " "soft": " "
} }
}, },
"spaces": 1 "spaces": 1,
"colors": "default"
}, },
"ext": { "ext": {
"ipython": { "ipython": {

View File

@ -1,16 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from powerline.colorscheme import DEFAULT_MODE_KEY
from powerline.theme import Theme from powerline.theme import Theme
class Renderer(object): class Renderer(object):
def __init__(self, theme_config, local_themes, theme_kwargs, **options): def __init__(self, theme_config, local_themes, theme_kwargs, colorscheme, **options):
self.__dict__.update(options) self.__dict__.update(options)
self.theme_config = theme_config self.theme_config = theme_config
self.theme = Theme(theme_config=theme_config, **theme_kwargs) self.theme = Theme(theme_config=theme_config, **theme_kwargs)
self.local_themes = local_themes self.local_themes = local_themes
self.theme_kwargs = theme_kwargs self.theme_kwargs = theme_kwargs
self.colorscheme = colorscheme
def add_local_theme(self, matcher, theme): def add_local_theme(self, matcher, theme):
if matcher in self.local_themes: if matcher in self.local_themes:
@ -27,6 +27,14 @@ class Renderer(object):
else: else:
return self.theme return self.theme
def get_highlighting(self, segment, mode):
segment['highlight'] = self.colorscheme.get_highlighting(segment['highlight_group'], mode, segment.get('gradient_level'))
if segment['divider_highlight_group']:
segment['divider_highlight'] = self.colorscheme.get_highlighting(segment['divider_highlight_group'], mode)
else:
segment['divider_highlight'] = None
return segment
def render(self, mode=None, width=None, side=None, output_raw=False, segment_info=None, matcher_info=None): def render(self, mode=None, width=None, side=None, output_raw=False, segment_info=None, matcher_info=None):
'''Render all segments. '''Render all segments.
@ -43,10 +51,10 @@ class Renderer(object):
theme.segment_info.update(segment_info) theme.segment_info.update(segment_info)
# Handle excluded/included segments for the current mode # Handle excluded/included segments for the current mode
segments = [segment for segment in segments segments = [self.get_highlighting(segment, mode) for segment in segments
if mode not in segment['exclude_modes'] or (segment['include_modes'] and segment in segment['include_modes'])] if mode not in segment['exclude_modes'] or (segment['include_modes'] and segment in segment['include_modes'])]
segments = [segment for segment in self._render_segments(mode, theme, segments)] segments = [segment for segment in self._render_segments(theme, segments)]
if not width: if not width:
# No width specified, so we don't need to crop or pad anything # No width specified, so we don't need to crop or pad anything
@ -73,11 +81,11 @@ class Renderer(object):
segment['_space_right'] += space_side segment['_space_right'] += space_side
segments_spacers[0]['_space_right'] += distribute_len_remainder segments_spacers[0]['_space_right'] += distribute_len_remainder
rendered_highlighted = u''.join([segment['_rendered_hl'] for segment in self._render_segments(mode, theme, segments)]) + self.hlstyle() rendered_highlighted = u''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
return self._returned_value(rendered_highlighted, segments, output_raw) return self._returned_value(rendered_highlighted, segments, output_raw)
def _render_segments(self, mode, theme, segments, render_highlighted=True): def _render_segments(self, theme, segments, render_highlighted=True):
'''Internal segment rendering method. '''Internal segment rendering method.
This method loops through the segment array and compares the This method loops through the segment array and compares the
@ -89,10 +97,6 @@ class Renderer(object):
statusline if render_highlighted is True. statusline if render_highlighted is True.
''' '''
segments_len = len(segments) segments_len = len(segments)
try:
mode = mode if mode in segments[0]['highlight'] else DEFAULT_MODE_KEY
except IndexError:
pass
for index, segment in enumerate(segments): for index, segment in enumerate(segments):
segment['_rendered_raw'] = u'' segment['_rendered_raw'] = u''
@ -102,7 +106,7 @@ class Renderer(object):
next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT
compare_segment = next_segment if segment['side'] == 'left' else prev_segment compare_segment = next_segment if segment['side'] == 'left' else prev_segment
outer_padding = ' ' if (index == 0 and segment['side'] == 'left') or (index == segments_len - 1 and segment['side'] == 'right') else '' outer_padding = ' ' if (index == 0 and segment['side'] == 'left') or (index == segments_len - 1 and segment['side'] == 'right') else ''
divider_type = 'soft' if compare_segment['highlight'][mode]['bg'] == segment['highlight'][mode]['bg'] else 'hard' divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
divider_raw = theme.get_divider(segment['side'], divider_type) divider_raw = theme.get_divider(segment['side'], divider_type)
divider_spaces = theme.get_spaces() divider_spaces = theme.get_spaces()
@ -130,13 +134,13 @@ class Renderer(object):
if render_highlighted: if render_highlighted:
if divider_type == 'soft': if divider_type == 'soft':
divider_highlight_group_key = 'highlight' if segment['divider_highlight_group'] is None else 'divider_highlight' divider_highlight_group_key = 'highlight' if segment['divider_highlight_group'] is None else 'divider_highlight'
divider_fg = segment[divider_highlight_group_key][mode]['fg'] divider_fg = segment[divider_highlight_group_key]['fg']
divider_bg = segment[divider_highlight_group_key][mode]['bg'] divider_bg = segment[divider_highlight_group_key]['bg']
else: else:
divider_fg = segment['highlight'][mode]['bg'] divider_fg = segment['highlight']['bg']
divider_bg = compare_segment['highlight'][mode]['bg'] divider_bg = compare_segment['highlight']['bg']
divider_highlighted = self.hl(divider_raw, divider_fg, divider_bg, False) divider_highlighted = self.hl(divider_raw, divider_fg, divider_bg, False)
contents_highlighted = self.hl(self.escape(contents_raw), **segment['highlight'][mode]) contents_highlighted = self.hl(self.escape(contents_raw), **segment['highlight'])
# Append padded raw and highlighted segments to the rendered segment variables # Append padded raw and highlighted segments to the rendered segment variables
if segment['draw_divider'] or (divider_type == 'hard' and segment['width'] != 'auto'): if segment['draw_divider'] or (divider_type == 'hard' and segment['width'] != 'auto'):

View File

@ -45,6 +45,10 @@ segment_getters = {
} }
def scalar_to_list(value):
return value if type(value) is list else [value]
def gen_segment_getter(ext, path, theme_configs, default_module=None): def gen_segment_getter(ext, path, theme_configs, default_module=None):
data = { data = {
'default_module': default_module or 'powerline.segments.' + ext, 'default_module': default_module or 'powerline.segments.' + ext,
@ -66,8 +70,8 @@ def gen_segment_getter(ext, path, theme_configs, default_module=None):
divider_highlight_group = segment.get('divider_highlight_group') divider_highlight_group = segment.get('divider_highlight_group')
return { return {
'type': segment_type, 'type': segment_type,
'highlight_group': highlight_group, 'highlight_group': scalar_to_list(highlight_group),
'divider_highlight_group': divider_highlight_group, 'divider_highlight_group': scalar_to_list(divider_highlight_group) if divider_highlight_group else None,
'before': get_key(segment, module, 'before', ''), 'before': get_key(segment, module, 'before', ''),
'after': get_key(segment, module, 'after', ''), 'after': get_key(segment, module, 'after', ''),
'contents_func': contents_func, 'contents_func': contents_func,

View File

@ -241,7 +241,8 @@ def line_percent(segment_info, gradient=False):
return percentage return percentage
return [{ return [{
'contents': percentage, 'contents': percentage,
'highlight_group': ['line_percent_gradient' + str(int(5 * percentage // 100) + 1), 'line_percent'], 'highlight_group': ['line_percent_gradient', 'line_percent'],
'gradient_level': percentage,
}] }]

View File

@ -18,8 +18,7 @@ def requires_segment_info(func):
class Theme(object): class Theme(object):
def __init__(self, ext, colorscheme, theme_config, common_config, top_theme_config=None, segment_info=None): def __init__(self, ext, theme_config, common_config, top_theme_config=None, segment_info=None):
self.colorscheme = colorscheme
self.dividers = theme_config.get('dividers', common_config['dividers']) self.dividers = theme_config.get('dividers', common_config['dividers'])
self.spaces = theme_config.get('spaces', common_config['spaces']) self.spaces = theme_config.get('spaces', common_config['spaces'])
self.segments = { self.segments = {
@ -28,7 +27,7 @@ class Theme(object):
} }
self.EMPTY_SEGMENT = { self.EMPTY_SEGMENT = {
'contents': None, 'contents': None,
'highlight': defaultdict(lambda: {'fg': False, 'bg': False, 'attr': 0}) 'highlight': {'fg': False, 'bg': False, 'attr': 0}
} }
self.segment_info = segment_info self.segment_info = segment_info
theme_configs = [theme_config] theme_configs = [theme_config]
@ -45,14 +44,6 @@ class Theme(object):
def get_spaces(self): def get_spaces(self):
return self.spaces return self.spaces
def add_highlight(self, segment):
segment['highlight'] = self.colorscheme.get_group_highlighting(segment['highlight_group'])
if segment['divider_highlight_group']:
segment['divider_highlight'] = self.colorscheme.get_group_highlighting(segment['divider_highlight_group'])
else:
segment['divider_highlight'] = None
return segment
def get_segments(self, side=None): def get_segments(self, side=None):
'''Return all segments. '''Return all segments.
@ -92,7 +83,6 @@ class Theme(object):
else: else:
continue continue
for segment in parsed_segments: for segment in parsed_segments:
segment = self.add_highlight(segment)
segment['contents'] = segment['before'] + unicode(segment['contents'] if segment['contents'] is not None else '') + segment['after'] segment['contents'] = segment['before'] + unicode(segment['contents'] if segment['contents'] is not None else '') + segment['after']
# Align segment contents # Align segment contents
if segment['width'] and segment['width'] != 'auto': if segment['width'] and segment['width'] != 'auto':