Merge pull request #921 from ZyX-I/colorschemes-hierarchy

Implement colorschemes hierarchy

Fixes #770.
This commit is contained in:
Nikolai Aleksandrovich Pavlov 2014-07-12 14:35:49 +04:00
commit 12a93c57ad
21 changed files with 733 additions and 356 deletions

View File

@ -16,7 +16,9 @@ Powerline provides default configurations in the following locations:
`Main configuration`_
:file:`powerline/config.json`
`Colorschemes`_
:file:`powerline/colorschemes/{extension}/default.json`
:file:`powerline/colorschemes/{name}.json`,
:file:`powerline/colorscheme/__main__.json`,
:file:`powerline/colorschemes/{extension}/{name}.json`
`Themes`_
:file:`powerline/themes/{extension}/default.json`
@ -248,7 +250,14 @@ Color definitions
Colorschemes
============
:Location: :file:`powerline/colorschemes/{extension}/{name}.json`
:Location: :file:`powerline/colorschemes/{name}.json`,
:file:`powerline/colorscheme/__main__.json`,
:file:`powerline/colorschemes/{extension}/{name}.json`
Colorscheme files are processed in order given: definitions from each next file
override those from each previous file. It is required that either
:file:`powerline/colorschemes/{name}.json`, or
:file:`powerline/colorschemes/{extension}/{name}.json` exists.
``name``
Name of the colorscheme.
@ -258,21 +267,27 @@ Colorschemes
``groups``
Segment highlighting groups, consisting of a dict where the key is the
name of the highlighting group (usually the function name for function
segments), and the value is a dict that defines the foreground color,
background color and optional attributes:
segments), and the value is either
``fg``
Foreground color. Must be defined in :ref:`colors
<config-colors-colors>`.
#) a dict that defines the foreground color, background color and
attributes:
``bg``
Background color. Must be defined in :ref:`colors
<config-colors-colors>`.
``fg``
Foreground color. Must be defined in :ref:`colors
<config-colors-colors>`.
``attr``
Optional list of attributes. Valid values are one or more of
``bold``, ``italic`` and ``underline``. Note that some attributes
may be unavailable in some applications or terminal emulators.
``bg``
Background color. Must be defined in :ref:`colors
<config-colors-colors>`.
``attr``
List of attributes. Valid values are one or more of ``bold``,
``italic`` and ``underline``. Note that some attributes may be
unavailable in some applications or terminal emulators. If you do not
need any attributes leave this empty.
#) a string (an alias): a name of existing group. This groups definition
will be used when this color is requested.
``mode_translations``
Mode-specific highlighting for extensions that support it (e.g. the vim

View File

@ -9,6 +9,7 @@ from powerline.colorscheme import Colorscheme
from powerline.lib.config import ConfigLoader
from powerline.lib.unicode import safe_unicode, FailedUnicode
from powerline.config import DEFAULT_SYSTEM_CONFIG_DIR
from powerline.lib import mergedicts
from threading import Lock, Event
@ -220,6 +221,22 @@ def finish_common_config(common_config):
return common_config
if sys.version_info < (3,):
# `raise exception[0], None, exception[1]` is a SyntaxError in python-3*
# Not using ('''…''') because this syntax does not work in python-2.6
exec(('def reraise(exception):\n'
' if type(exception) is tuple:\n'
' raise exception[0], None, exception[1]\n'
' else:\n'
' raise exception\n'))
else:
def reraise(exception):
if type(exception) is tuple:
raise exception[0].with_traceback(exception[1])
else:
raise exception
class Powerline(object):
'''Main powerline class, entrance point for all powerline uses. Sets
powerline up and loads the configuration.
@ -455,7 +472,40 @@ class Powerline(object):
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
'''
return self._load_config(os.path.join('colorschemes', self.ext, name), 'colorscheme')
# TODO Make sure no colorscheme name ends with __ (do it in
# powerline-lint)
levels = (
os.path.join('colorschemes', name),
os.path.join('colorschemes', self.ext, '__main__'),
os.path.join('colorschemes', self.ext, name),
)
config = {}
loaded = 0
exceptions = []
for cfg_path in levels:
try:
lvl_config = self._load_config(cfg_path, 'colorscheme')
except IOError as e:
if sys.version_info < (3,):
tb = sys.exc_info()[2]
exceptions.append((e, tb))
else:
exceptions.append(e)
else:
if not cfg_path.endswith('__'):
loaded += 1
# TODO Either make sure `attr` list is always present or make
# mergedicts not merge group definitions.
mergedicts(config, lvl_config)
if not loaded:
for exception in exceptions:
if type(exception) is tuple:
e = exception[0]
else:
e = exception
self.exception('Failed to load colorscheme: {0}', e, exception=exception)
raise e
return config
def load_colors_config(self):
'''Get colorscheme.
@ -562,5 +612,11 @@ class Powerline(object):
def exception(self, msg, *args, **kwargs):
if 'prefix' not in kwargs:
kwargs['prefix'] = 'powerline'
exception = kwargs.pop('exception', None)
pl = getattr(self, 'pl', None) or get_fallback_logger()
if exception:
try:
reraise(exception)
except Exception:
return pl.exception(msg, *args, **kwargs)
return pl.exception(msg, *args, **kwargs)

View File

@ -1,6 +1,10 @@
# vim:fileencoding=utf-8:noet
from copy import copy
try:
from __builtin__ import unicode
except ImportError:
unicode = str
DEFAULT_MODE_KEY = None
@ -70,32 +74,41 @@ class Colorscheme(object):
else:
return self.colors[gradient]
def get_highlighting(self, groups, mode, gradient_level=None):
trans = self.translations.get(mode, {})
for group in hl_iter(groups):
if 'groups' in trans and group in trans['groups']:
def get_group_props(self, mode, trans, group, translate_colors=True):
if isinstance(group, (str, unicode)):
try:
group_props = trans['groups'][group]
except KeyError:
try:
group_props = trans['groups'][group]
group_props = self.groups[group]
except KeyError:
continue
break
return None
else:
return self.get_group_props(mode, trans, group_props, True)
else:
try:
group_props = copy(self.groups[group])
except KeyError:
continue
return self.get_group_props(mode, trans, group_props, False)
else:
if translate_colors:
group_props = copy(group)
try:
ctrans = trans['colors']
except KeyError:
pass
else:
for key in ('fg', 'bg'):
try:
group_props[key] = ctrans[group_props[key]]
except KeyError:
pass
except KeyError:
pass
return group_props
else:
return group
def get_highlighting(self, groups, mode, gradient_level=None):
trans = self.translations.get(mode, {})
for group in hl_iter(groups):
group_props = self.get_group_props(mode, trans, group)
if group_props:
break
else:
raise KeyError('Highlighting groups not found in colorscheme: ' + ', '.join(hl_iter(groups)))

View File

@ -0,0 +1,42 @@
{
"name": "Default",
"groups": {
"background:divider": { "fg": "gray5", "bg": "gray0", "attr": [] },
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2", "attr": [] },
"time": { "fg": "gray10", "bg": "gray2", "attr": ["bold"] },
"time:divider": { "fg": "gray5", "bg": "gray2", "attr": [] },
"email_alert": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attr": ["bold"] },
"hostname": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0", "attr": [] },
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0", "attr": [] },
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0", "attr": [] },
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0", "attr": [] },
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0", "attr": [] },
"uptime": { "fg": "gray8", "bg": "gray0", "attr": [] },
"external_ip": { "fg": "gray8", "bg": "gray0", "attr": [] },
"network_load": { "fg": "gray8", "bg": "gray0", "attr": [] },
"network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attr": [] },
"system_load": { "fg": "gray8", "bg": "gray0", "attr": [] },
"system_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attr": [] },
"environment": { "fg": "gray8", "bg": "gray0", "attr": [] },
"cpu_load_percent": { "fg": "gray8", "bg": "gray0", "attr": [] },
"cpu_load_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attr": [] },
"battery": { "fg": "gray8", "bg": "gray0", "attr": [] },
"battery_gradient": { "fg": "white_red", "bg": "gray0", "attr": [] },
"battery_full": { "fg": "red", "bg": "gray0", "attr": [] },
"battery_empty": { "fg": "white", "bg": "gray0", "attr": [] },
"now_playing": { "fg": "gray10", "bg": "black", "attr": [] },
"user": { "fg": "white", "bg": "darkblue", "attr": ["bold"] },
"superuser": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
"branch": { "fg": "gray9", "bg": "gray2", "attr": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attr": [] },
"branch_clean": { "fg": "gray9", "bg": "gray2", "attr": [] },
"branch:divider": { "fg": "gray7", "bg": "gray2", "attr": [] },
"cwd": { "fg": "gray9", "bg": "gray4", "attr": [] },
"cwd:current_folder": { "fg": "gray10", "bg": "gray4", "attr": ["bold"] },
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attr": [] },
"virtualenv": { "fg": "white", "bg": "darkcyan", "attr": [] }
}
}

View File

@ -1,8 +1,7 @@
{
"name": "Default color scheme for IPython prompt",
"groups": {
"virtualenv": { "fg": "white", "bg": "darkcyan" },
"prompt": { "fg": "gray9", "bg": "gray4" },
"prompt_count": { "fg": "white", "bg": "gray4" }
"prompt": { "fg": "gray9", "bg": "gray4", "attr": [] },
"prompt_count": { "fg": "white", "bg": "gray4", "attr": [] }
}
}

View File

@ -0,0 +1,6 @@
{
"groups": {
"continuation": "cwd",
"continuation:current": "cwd:current_folder"
}
}

View File

@ -1,23 +1,12 @@
{
"name": "Default color scheme for shell prompts",
"groups": {
"jobnum": { "fg": "brightyellow", "bg": "mediumorange" },
"user": { "fg": "white", "bg": "darkblue", "attr": ["bold"] },
"superuser": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
"virtualenv": { "fg": "white", "bg": "darkcyan" },
"branch": { "fg": "gray9", "bg": "gray2" },
"branch_dirty": { "fg": "brightyellow", "bg": "gray2" },
"branch_clean": { "fg": "gray9", "bg": "gray2" },
"continuation": { "fg": "gray9", "bg": "gray4" },
"continuation:current": { "fg": "gray10", "bg": "gray4", "attr": ["bold"] },
"cwd": { "fg": "gray9", "bg": "gray4" },
"cwd:current_folder": { "fg": "gray10", "bg": "gray4", "attr": ["bold"] },
"cwd:divider": { "fg": "gray7", "bg": "gray4" },
"hostname": { "fg": "brightyellow", "bg": "mediumorange" },
"exit_fail": { "fg": "white", "bg": "darkestred" },
"exit_success": { "fg": "white", "bg": "darkestgreen" },
"environment": { "fg": "white", "bg": "darkestgreen" },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attr": ["bold"] }
"hostname": { "fg": "brightyellow", "bg": "mediumorange", "attr": [] },
"jobnum": { "fg": "brightyellow", "bg": "mediumorange", "attr": [] },
"exit_fail": { "fg": "white", "bg": "darkestred", "attr": [] },
"exit_success": { "fg": "white", "bg": "darkestgreen", "attr": [] },
"environment": { "fg": "white", "bg": "darkestgreen", "attr": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attr": ["bold"] }
},
"mode_translations": {
"vicmd": {

View File

@ -1,23 +1,10 @@
{
"name": "Solarized Dark",
"name": "Solarized dark for shell",
"groups": {
"jobnum": { "fg": "oldlace", "bg": "darkgreencopper" },
"user": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
"superuser": { "fg": "oldlace", "bg": "red", "attr": ["bold"] },
"virtualenv": { "fg": "oldlace", "bg": "green" },
"branch": { "fg": "gray61", "bg": "royalblue5" },
"branch_dirty": { "fg": "yellow", "bg": "royalblue5" },
"branch_clean": { "fg": "gray61", "bg": "royalblue5" },
"continuation": { "fg": "lightyellow", "bg": "darkgreencopper" },
"continuation:current": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
"cwd": { "fg": "lightyellow", "bg": "darkgreencopper" },
"cwd:current_folder": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
"cwd:divider": { "fg": "gray61", "bg": "darkgreencopper" },
"hostname": { "fg": "oldlace", "bg": "darkgreencopper" },
"exit_fail": { "fg": "oldlace", "bg": "red" },
"exit_success": { "fg": "oldlace", "bg": "green" },
"environment": { "fg": "oldlace", "bg": "green" },
"mode": { "fg": "oldlace", "bg": "green", "attr": ["bold"] }
"jobnum": { "fg": "oldlace", "bg": "darkgreencopper", "attr": [] },
"exit_fail": { "fg": "oldlace", "bg": "red", "attr": [] },
"exit_success": { "fg": "oldlace", "bg": "green", "attr": [] },
"mode": { "fg": "oldlace", "bg": "green", "attr": ["bold"] }
},
"mode_translations": {
"vicmd": {

View File

@ -0,0 +1,17 @@
{
"name": "Solarized dark",
"groups": {
"background": { "fg": "oldlace", "bg": "royalblue5", "attr": [] },
"user": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
"superuser": { "fg": "oldlace", "bg": "red", "attr": ["bold"] },
"virtualenv": { "fg": "oldlace", "bg": "green", "attr": [] },
"branch": { "fg": "gray61", "bg": "royalblue5", "attr": [] },
"branch_dirty": { "fg": "yellow", "bg": "royalblue5", "attr": [] },
"branch_clean": { "fg": "gray61", "bg": "royalblue5", "attr": [] },
"cwd": { "fg": "lightyellow", "bg": "darkgreencopper", "attr": [] },
"cwd:current_folder": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
"cwd:divider": { "fg": "gray61", "bg": "darkgreencopper", "attr": [] },
"hostname": { "fg": "oldlace", "bg": "darkgreencopper", "attr": [] },
"environment": { "fg": "oldlace", "bg": "green", "attr": [] }
}
}

View File

@ -1,32 +0,0 @@
{
"name": "Default color scheme for terminal prompts",
"groups": {
"background:divider": { "fg": "gray5", "bg": "gray0" },
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2" },
"time": { "fg": "gray10", "bg": "gray2", "attr": ["bold"] },
"time:divider": { "fg": "gray5", "bg": "gray2" },
"email_alert": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attr": ["bold"] },
"hostname": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0" },
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0" },
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0" },
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0" },
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0" },
"uptime": { "fg": "gray8", "bg": "gray0" },
"external_ip": { "fg": "gray8", "bg": "gray0" },
"network_load": { "fg": "gray8", "bg": "gray0" },
"network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" },
"system_load": { "fg": "gray8", "bg": "gray0" },
"system_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" },
"cpu_load_percent": { "fg": "gray8", "bg": "gray0" },
"cpu_load_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" },
"environment": { "fg": "gray8", "bg": "gray0" },
"battery": { "fg": "gray8", "bg": "gray0" },
"battery_gradient": { "fg": "white_red", "bg": "gray0" },
"battery_full": { "fg": "red", "bg": "gray0" },
"battery_empty": { "fg": "white", "bg": "gray0" },
"now_playing": { "fg": "gray10", "bg": "black" }
}
}

View File

@ -0,0 +1,15 @@
{
"groups": {
"branch_clean": "branch",
"environment": "information:unimportant",
"file_size": "information:unimportant",
"file_format": "information:unimportant",
"file_encoding": "file_format",
"file_type": "file_format",
"branch": "information:additional",
"file_directory": "information:additional",
"file_name_empty": "file_directory",
"line_percent": "information:additional",
"position": "information:additional"
}
}

View File

@ -1,42 +1,35 @@
{
"name": "Default color scheme",
"groups": {
"background": { "fg": "white", "bg": "gray2" },
"background:divider": { "fg": "gray6", "bg": "gray2" },
"information:unimportant": { "fg": "gray8", "bg": "gray2", "attr": [] },
"information:additional": { "fg": "gray9", "bg": "gray4", "attr": [] },
"background": { "fg": "white", "bg": "gray2", "attr": [] },
"background:divider": { "fg": "gray6", "bg": "gray2", "attr": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attr": ["bold"] },
"visual_range": { "fg": "brightestorange", "bg": "darkorange", "attr": ["bold"] },
"modified_indicator": { "fg": "brightyellow", "bg": "gray4", "attr": ["bold"] },
"paste_indicator": { "fg": "white", "bg": "mediumorange", "attr": ["bold"] },
"readonly_indicator": { "fg": "brightestred", "bg": "gray4" },
"branch": { "fg": "gray9", "bg": "gray4" },
"branch_dirty": { "fg": "brightyellow", "bg": "gray4" },
"branch_clean": { "fg": "gray9", "bg": "gray4" },
"branch:divider": { "fg": "gray7", "bg": "gray4" },
"file_directory": { "fg": "gray9", "bg": "gray4" },
"readonly_indicator": { "fg": "brightestred", "bg": "gray4", "attr": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray4", "attr": [] },
"branch:divider": { "fg": "gray7", "bg": "gray4", "attr": [] },
"file_name": { "fg": "white", "bg": "gray4", "attr": ["bold"] },
"window_title": { "fg": "white", "bg": "gray4" },
"file_size": { "fg": "gray8", "bg": "gray2" },
"window_title": { "fg": "white", "bg": "gray4", "attr": [] },
"file_name_no_file": { "fg": "gray9", "bg": "gray4", "attr": ["bold"] },
"file_name_empty": { "fg": "gray9", "bg": "gray4" },
"file_format": { "fg": "gray8", "bg": "gray2" },
"file_encoding": { "fg": "gray8", "bg": "gray2" },
"file_type": { "fg": "gray8", "bg": "gray2" },
"file_vcs_status": { "fg": "brightestred", "bg": "gray4" },
"file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4" },
"file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4" },
"line_percent": { "fg": "gray9", "bg": "gray4" },
"line_percent_gradient": { "fg": "dark_green_gray", "bg": "gray4" },
"position": { "fg": "gray9", "bg": "gray4" },
"position_gradient": { "fg": "green_yellow_red", "bg": "gray4" },
"file_vcs_status": { "fg": "brightestred", "bg": "gray4", "attr": [] },
"file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4", "attr": [] },
"file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4", "attr": [] },
"line_percent": { "fg": "gray9", "bg": "gray4", "attr": [] },
"line_percent_gradient": { "fg": "dark_green_gray", "bg": "gray4", "attr": [] },
"position": { "fg": "gray9", "bg": "gray4", "attr": [] },
"position_gradient": { "fg": "green_yellow_red", "bg": "gray4", "attr": [] },
"line_current": { "fg": "gray1", "bg": "gray10", "attr": ["bold"] },
"line_current_symbol": { "fg": "gray1", "bg": "gray10" },
"virtcol_current_gradient": { "fg": "dark_GREEN_Orange_red", "bg": "gray10" },
"col_current": { "fg": "gray6", "bg": "gray10" },
"modified_buffers": { "fg": "brightyellow", "bg": "gray2" },
"environment": { "fg": "gray8", "bg": "gray2" },
"line_current_symbol": { "fg": "gray1", "bg": "gray10", "attr": [] },
"virtcol_current_gradient": { "fg": "dark_GREEN_Orange_red", "bg": "gray10", "attr": [] },
"col_current": { "fg": "gray6", "bg": "gray10", "attr": [] },
"modified_buffers": { "fg": "brightyellow", "bg": "gray2", "attr": [] },
"error": { "fg": "brightestred", "bg": "darkred", "attr": ["bold"] },
"warning": { "fg": "brightyellow", "bg": "darkorange", "attr": ["bold"] },
"current_tag": { "fg": "gray9", "bg": "gray2" }
"current_tag": { "fg": "gray9", "bg": "gray2", "attr": [] }
},
"mode_translations": {
"nc": {
@ -76,8 +69,8 @@
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attr": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue" },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue" }
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attr": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attr": [] }
}
},
"v": {

View File

@ -1,38 +1,33 @@
{
"name": "Solarized Dark",
"name": "Solarized dark for vim",
"groups": {
"background": { "fg": "oldlace", "bg": "royalblue5" },
"background:divider": { "fg": "lightskyblue4", "bg": "royalblue5" },
"information:additional": { "fg": "lightyellow", "bg": "darkgreencopper", "attr": [] },
"information:unimportant": { "fg": "oldlace", "bg": "darkgreencopper", "attr": [] },
"background": { "fg": "oldlace", "bg": "royalblue5", "attr": [] },
"background:divider": { "fg": "lightskyblue4", "bg": "royalblue5", "attr": [] },
"mode": { "fg": "oldlace", "bg": "green", "attr": ["bold"] },
"visual_range": { "fg": "green", "bg": "oldlace", "attr": ["bold"] },
"modified_indicator": { "fg": "yellow", "bg": "darkgreencopper", "attr": ["bold"] },
"paste_indicator": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
"readonly_indicator": { "fg": "red", "bg": "darkgreencopper" },
"branch": { "fg": "lightyellow", "bg": "darkgreencopper" },
"branch_dirty": { "fg": "yellow", "bg": "darkgreencopper" },
"branch_clean": { "fg": "lightyellow", "bg": "darkgreencopper" },
"branch:divider": { "fg": "gray61", "bg": "darkgreencopper" },
"file_directory": { "fg": "lightyellow", "bg": "darkgreencopper" },
"readonly_indicator": { "fg": "red", "bg": "darkgreencopper", "attr": [] },
"branch_dirty": { "fg": "yellow", "bg": "darkgreencopper", "attr": [] },
"branch:divider": { "fg": "gray61", "bg": "darkgreencopper", "attr": [] },
"file_name": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
"window_title": { "fg": "oldlace", "bg": "darkgreencopper" },
"file_size": { "fg": "oldlace", "bg": "darkgreencopper" },
"window_title": { "fg": "oldlace", "bg": "darkgreencopper", "attr": [] },
"file_name_no_file": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
"file_name_empty": { "fg": "oldlace", "bg": "darkgreencopper" },
"file_format": { "fg": "gray61", "bg": "royalblue5" },
"file_encoding": { "fg": "gray61", "bg": "royalblue5" },
"file_type": { "fg": "gray61", "bg": "royalblue5" },
"file_vcs_status": { "fg": "red", "bg": "darkgreencopper" },
"file_vcs_status_M": { "fg": "yellow", "bg": "darkgreencopper" },
"file_vcs_status_A": { "fg": "green", "bg": "darkgreencopper" },
"line_percent": { "fg": "oldlace", "bg": "lightskyblue4" },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "lightskyblue4" },
"position": { "fg": "oldlace", "bg": "lightskyblue4" },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "lightskyblue4" },
"file_format": { "fg": "gray61", "bg": "royalblue5", "attr": [] },
"file_vcs_status": { "fg": "red", "bg": "darkgreencopper", "attr": [] },
"file_vcs_status_M": { "fg": "yellow", "bg": "darkgreencopper", "attr": [] },
"file_vcs_status_A": { "fg": "green", "bg": "darkgreencopper", "attr": [] },
"line_percent": { "fg": "oldlace", "bg": "lightskyblue4", "attr": [] },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "lightskyblue4", "attr": [] },
"position": { "fg": "oldlace", "bg": "lightskyblue4", "attr": [] },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "lightskyblue4", "attr": [] },
"line_current": { "fg": "gray13", "bg": "lightyellow", "attr": ["bold"] },
"line_current_symbol": { "fg": "gray13", "bg": "lightyellow" },
"virtcol_current_gradient": { "fg": "GREEN_Orange_red", "bg": "lightyellow" },
"col_current": { "fg": "azure4", "bg": "lightyellow" },
"environment": { "fg": "gray61", "bg": "royalblue5" },
"line_current_symbol": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"virtcol_current_gradient": { "fg": "GREEN_Orange_red", "bg": "lightyellow", "attr": [] },
"col_current": { "fg": "azure4", "bg": "lightyellow", "attr": [] },
"environment": { "fg": "gray61", "bg": "royalblue5", "attr": [] },
"error": { "fg": "oldlace", "bg": "red", "attr": ["bold"] },
"warning": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
"current_tag": { "fg": "oldlace", "bg": "royalblue5", "attr": ["bold"] }
@ -50,32 +45,30 @@
},
"i": {
"groups": {
"background": { "fg": "oldlace", "bg": "darkgreencopper" },
"background:divider": { "fg": "lightyellow", "bg": "darkgreencopper" },
"background": { "fg": "oldlace", "bg": "darkgreencopper", "attr": [] },
"background:divider": { "fg": "lightyellow", "bg": "darkgreencopper", "attr": [] },
"mode": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
"modified_indicator": { "fg": "yellow", "bg": "lightyellow", "attr": ["bold"] },
"paste_indicator": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
"readonly_indicator": { "fg": "red", "bg": "lightyellow" },
"branch": { "fg": "darkgreencopper", "bg": "lightyellow" },
"branch:divider": { "fg": "lightskyblue4", "bg": "lightyellow" },
"file_directory": { "fg": "darkgreencopper", "bg": "lightyellow" },
"readonly_indicator": { "fg": "red", "bg": "lightyellow", "attr": [] },
"branch": { "fg": "darkgreencopper", "bg": "lightyellow", "attr": [] },
"branch:divider": { "fg": "lightskyblue4", "bg": "lightyellow", "attr": [] },
"file_directory": { "fg": "darkgreencopper", "bg": "lightyellow", "attr": [] },
"file_name": { "fg": "royalblue5", "bg": "lightyellow", "attr": ["bold"] },
"file_size": { "fg": "royalblue5", "bg": "lightyellow" },
"file_size": { "fg": "royalblue5", "bg": "lightyellow", "attr": [] },
"file_name_no_file": { "fg": "royalblue5", "bg": "lightyellow", "attr": ["bold"] },
"file_name_empty": { "fg": "royalblue5", "bg": "lightyellow" },
"file_format": { "fg": "lightyellow", "bg": "darkgreencopper" },
"file_encoding": { "fg": "lightyellow", "bg": "darkgreencopper" },
"file_type": { "fg": "lightyellow", "bg": "darkgreencopper" },
"file_vcs_status": { "fg": "red", "bg": "lightyellow" },
"file_vcs_status_M": { "fg": "yellow", "bg": "lightyellow" },
"file_vcs_status_A": { "fg": "green", "bg": "lightyellow" },
"line_percent": { "fg": "oldlace", "bg": "gray61" },
"line_percent_gradient": { "fg": "oldlace", "bg": "gray61" },
"position": { "fg": "oldlace", "bg": "gray61" },
"position_gradient": { "fg": "oldlace", "bg": "gray61" },
"file_name_empty": { "fg": "royalblue5", "bg": "lightyellow", "attr": [] },
"file_format": { "fg": "lightyellow", "bg": "darkgreencopper", "attr": [] },
"file_vcs_status": { "fg": "red", "bg": "lightyellow", "attr": [] },
"file_vcs_status_M": { "fg": "yellow", "bg": "lightyellow", "attr": [] },
"file_vcs_status_A": { "fg": "green", "bg": "lightyellow", "attr": [] },
"line_percent": { "fg": "oldlace", "bg": "gray61", "attr": [] },
"line_percent_gradient": { "fg": "oldlace", "bg": "gray61", "attr": [] },
"position": { "fg": "oldlace", "bg": "gray61", "attr": [] },
"position_gradient": { "fg": "oldlace", "bg": "gray61", "attr": [] },
"line_current": { "fg": "gray13", "bg": "oldlace", "attr": ["bold"] },
"line_current_symbol": { "fg": "gray13", "bg": "oldlace" },
"col_current": { "fg": "azure4", "bg": "oldlace" }
"line_current_symbol": { "fg": "gray13", "bg": "oldlace", "attr": [] },
"col_current": { "fg": "azure4", "bg": "oldlace", "attr": [] }
}
},
"v": {

View File

@ -1,38 +1,33 @@
{
"name": "Solarized Light",
"name": "Solarized light for vim",
"groups": {
"background": { "fg": "gray13", "bg": "darkgreencopper" },
"background:divider": { "fg": "azure4", "bg": "darkgreencopper" },
"information:additional": { "fg": "royalblue5", "bg": "lightyellow", "attr": [] },
"information:unimportant": { "fg": "gray61", "bg": "darkgreencopper", "attr": [] },
"background": { "fg": "gray13", "bg": "darkgreencopper", "attr": [] },
"background:divider": { "fg": "azure4", "bg": "darkgreencopper", "attr": [] },
"mode": { "fg": "oldlace", "bg": "green", "attr": ["bold"] },
"visual_range": { "fg": "green", "bg": "oldlace", "attr": ["bold"] },
"modified_indicator": { "fg": "yellow", "bg": "lightyellow", "attr": ["bold"] },
"paste_indicator": { "fg": "red", "bg": "lightyellow", "attr": ["bold"] },
"readonly_indicator": { "fg": "red", "bg": "lightyellow" },
"branch": { "fg": "royalblue5", "bg": "lightyellow" },
"branch_dirty": { "fg": "yellow", "bg": "lightyellow" },
"branch_clean": { "fg": "royalblue5", "bg": "lightyellow" },
"branch:divider": { "fg": "gray61", "bg": "lightyellow" },
"file_directory": { "fg": "royalblue5", "bg": "lightyellow" },
"readonly_indicator": { "fg": "red", "bg": "lightyellow", "attr": [] },
"branch_dirty": { "fg": "yellow", "bg": "lightyellow", "attr": [] },
"branch:divider": { "fg": "gray61", "bg": "lightyellow", "attr": [] },
"file_name": { "fg": "gray13", "bg": "lightyellow", "attr": ["bold"] },
"window_title": { "fg": "gray13", "bg": "lightyellow" },
"file_size": { "fg": "gray13", "bg": "lightyellow" },
"window_title": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"file_size": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"file_name_no_file": { "fg": "gray13", "bg": "lightyellow", "attr": ["bold"] },
"file_name_empty": { "fg": "gray13", "bg": "lightyellow" },
"file_format": { "fg": "gray61", "bg": "darkgreencopper" },
"file_encoding": { "fg": "gray61", "bg": "darkgreencopper" },
"file_type": { "fg": "gray61", "bg": "darkgreencopper" },
"file_vcs_status": { "fg": "red", "bg": "lightyellow" },
"file_vcs_status_M": { "fg": "yellow", "bg": "lightyellow" },
"file_vcs_status_A": { "fg": "green", "bg": "lightyellow" },
"line_percent": { "fg": "gray13", "bg": "lightyellow" },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "lightyellow" },
"position": { "fg": "gray13", "bg": "lightyellow" },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "lightyellow" },
"file_name_empty": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"file_vcs_status": { "fg": "red", "bg": "lightyellow", "attr": [] },
"file_vcs_status_M": { "fg": "yellow", "bg": "lightyellow", "attr": [] },
"file_vcs_status_A": { "fg": "green", "bg": "lightyellow", "attr": [] },
"line_percent": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "lightyellow", "attr": [] },
"position": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "lightyellow", "attr": [] },
"line_current": { "fg": "oldlace", "bg": "royalblue5", "attr": ["bold"] },
"line_current_symbol": { "fg": "oldlace", "bg": "royalblue5" },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "royalblue5" },
"col_current": { "fg": "lightskyblue4", "bg": "royalblue5" },
"environment": { "fg": "gray61", "bg": "darkgreencopper" },
"line_current_symbol": { "fg": "oldlace", "bg": "royalblue5", "attr": [] },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "royalblue5", "attr": [] },
"col_current": { "fg": "lightskyblue4", "bg": "royalblue5", "attr": [] },
"error": { "fg": "gray13", "bg": "red", "attr": ["bold"] },
"warning": { "fg": "gray13", "bg": "lightyellow", "attr": ["bold"] },
"current_tag": { "fg": "gray13", "bg": "darkgreencopper", "attr": ["bold"] }
@ -50,33 +45,31 @@
},
"i": {
"groups": {
"background": { "fg": "gray13", "bg": "lightyellow" },
"background:divider": { "fg": "royalblue5", "bg": "lightyellow" },
"background": { "fg": "gray13", "bg": "lightyellow", "attr": [] },
"background:divider": { "fg": "royalblue5", "bg": "lightyellow", "attr": [] },
"mode": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
"modified_indicator": { "fg": "yellow", "bg": "royalblue5", "attr": ["bold"] },
"paste_indicator": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
"readonly_indicator": { "fg": "red", "bg": "royalblue5" },
"branch": { "fg": "lightyellow", "bg": "royalblue5" },
"branch:divider": { "fg": "azure4", "bg": "royalblue5" },
"file_directory": { "fg": "lightyellow", "bg": "royalblue5" },
"readonly_indicator": { "fg": "red", "bg": "royalblue5", "attr": [] },
"branch": { "fg": "lightyellow", "bg": "royalblue5", "attr": [] },
"branch:divider": { "fg": "azure4", "bg": "royalblue5", "attr": [] },
"file_directory": { "fg": "lightyellow", "bg": "royalblue5", "attr": [] },
"file_name": { "fg": "darkgreencopper", "bg": "royalblue5", "attr": ["bold"] },
"file_size": { "fg": "darkgreencopper", "bg": "royalblue5" },
"file_size": { "fg": "darkgreencopper", "bg": "royalblue5", "attr": [] },
"file_name_no_file": { "fg": "darkgreencopper", "bg": "royalblue5", "attr": ["bold"] },
"file_name_empty": { "fg": "darkgreencopper", "bg": "royalblue5" },
"file_format": { "fg": "royalblue5", "bg": "lightyellow" },
"file_encoding": { "fg": "royalblue5", "bg": "lightyellow" },
"file_type": { "fg": "royalblue5", "bg": "lightyellow" },
"file_vcs_status": { "fg": "red", "bg": "royalblue5" },
"file_vcs_status_M": { "fg": "yellow", "bg": "royalblue5" },
"file_vcs_status_A": { "fg": "green", "bg": "royalblue5" },
"line_percent": { "fg": "gray13", "bg": "gray61" },
"line_percent_gradient": { "fg": "gray13", "bg": "gray61" },
"position": { "fg": "gray13", "bg": "gray61" },
"position_gradient": { "fg": "gray13", "bg": "gray61" },
"file_name_empty": { "fg": "darkgreencopper", "bg": "royalblue5", "attr": [] },
"file_format": { "fg": "royalblue5", "bg": "lightyellow", "attr": [] },
"file_vcs_status": { "fg": "red", "bg": "royalblue5", "attr": [] },
"file_vcs_status_M": { "fg": "yellow", "bg": "royalblue5", "attr": [] },
"file_vcs_status_A": { "fg": "green", "bg": "royalblue5", "attr": [] },
"line_percent": { "fg": "gray13", "bg": "gray61", "attr": [] },
"line_percent_gradient": { "fg": "gray13", "bg": "gray61", "attr": [] },
"position": { "fg": "gray13", "bg": "gray61", "attr": [] },
"position_gradient": { "fg": "gray13", "bg": "gray61", "attr": [] },
"line_current": { "fg": "oldlace", "bg": "gray13", "attr": ["bold"] },
"line_current_symbol": { "fg": "oldlace", "bg": "gray13" },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "gray13" },
"col_current": { "fg": "lightskyblue4", "bg": "gray13" }
"line_current_symbol": { "fg": "oldlace", "bg": "gray13", "attr": [] },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "gray13", "attr": [] },
"col_current": { "fg": "lightskyblue4", "bg": "gray13", "attr": [] }
}
},
"v": {

View File

@ -1,26 +0,0 @@
{
"name": "Default color scheme for window managers",
"groups": {
"background:divider": { "fg": "gray5", "bg": "gray0" },
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2" },
"time": { "fg": "gray10", "bg": "gray2", "attr": ["bold"] },
"time:divider": { "fg": "gray5", "bg": "gray2" },
"email_alert": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attr": ["bold"] },
"hostname": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0" },
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0" },
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0" },
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0" },
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0" },
"uptime": { "fg": "gray8", "bg": "gray0" },
"external_ip": { "fg": "gray8", "bg": "gray0" },
"network_load": { "fg": "gray8", "bg": "gray0" },
"system_load": { "fg": "gray8", "bg": "gray0" },
"system_load_good": { "fg": "lightyellowgreen", "bg": "gray0" },
"system_load_bad": { "fg": "gold3", "bg": "gray0" },
"system_load_ugly": { "fg": "orangered", "bg": "gray0" },
"environment": { "fg": "gray8", "bg": "gray0" }
}
}

View File

@ -18,7 +18,7 @@ def mergedicts(d1, d2):
'''Recursively merge two dictionaries. First dictionary is modified in-place.
'''
for k in d2:
if k in d1 and type(d1[k]) is dict and type(d2[k]) is dict:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
mergedicts(d1[k], d2[k])
elif d2[k] is REMOVE_THIS_KEY:
d1.pop(k, None)
@ -26,6 +26,21 @@ def mergedicts(d1, d2):
d1[k] = d2[k]
def mergedicts_copy(d1, d2):
'''Recursively merge two dictionaries.
Dictionaries are not modified. Copying happens only if necessary. Assumes
that first dictionary support .copy() method.
'''
ret = d1.copy()
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
ret[k] = mergedicts_copy(d1[k], d2[k])
else:
ret[k] = d2[k]
return ret
def add_divider_highlight_group(highlight_group):
def dec(func):
@wraps_saveargs(func)

View File

@ -7,6 +7,7 @@ from powerline.lint.markedjson.error import echoerr, MarkedError
from powerline.segments.vim import vim_modes
from powerline.lint.inspect import getconfigargspec
from powerline.lib.threaded import ThreadedSegment
from powerline.lib import mergedicts_copy
import itertools
import sys
import os
@ -414,14 +415,20 @@ def check_matcher_func(ext, match_name, data, context, echoerr):
def check_ext(ext, data, context, echoerr):
hadsomedirs = False
hadproblem = False
for subdir in ('themes', 'colorschemes'):
if ext not in data['configs'][subdir]:
hadproblem = True
echoerr(context='Error while loading {0} extension configuration'.format(ext),
context_mark=ext.mark,
problem='{0} configuration does not exist'.format(subdir))
else:
hadsomedirs = True
if ext not in data['lists']['exts']:
hadproblem = True
echoerr(context='Error while loading {0} extension configuration'.format(ext),
context_mark=ext.mark,
problem='extension configuration does not exist')
else:
for typ in ('themes', 'colorschemes'):
if ext not in data['configs'][typ] and not data['configs']['top_' + typ]:
hadproblem = True
echoerr(context='Error while loading {0} extension configuration'.format(ext),
context_mark=ext.mark,
problem='{0} configuration does not exist'.format(typ))
else:
hadsomedirs = True
return hadsomedirs, hadproblem
@ -431,7 +438,13 @@ def check_config(d, theme, data, context, echoerr):
else:
# local_themes
ext = context[-3][0]
if ext not in data['configs'][d] or theme not in data['configs'][d][ext]:
if ext not in data['lists']['exts']:
echoerr(context='Error while loading {0} extension configuration'.format(ext),
context_mark=ext.mark,
problem='extension configuration does not exist')
return True, False, True
if ((ext not in data['configs'][d] or theme not in data['configs'][d][ext])
and theme not in data['configs']['top_' + d]):
echoerr(context='Error while loading {0} from {1} extension configuration'.format(d[:-1], ext),
problem='failed to find configuration file {0}/{1}/{2}.json'.format(d, ext, theme),
problem_mark=theme.mark)
@ -531,22 +544,84 @@ def check_color(color, data, context, echoerr):
def check_translated_group_name(group, data, context, echoerr):
if group not in context[0][1].get('groups', {}):
echoerr(context='Error while checking translated group in colorscheme (key {key})'.format(key=context_key(context)),
problem='translated group {0} is not in main groups dictionary'.format(group),
problem_mark=group.mark)
return True, False, True
return True, False, False
return check_group(group, data, context, echoerr)
def check_group(group, data, context, echoerr):
if not isinstance(group, unicode):
return True, False, False
colorscheme = data['colorscheme']
ext = data['ext']
configs = []
if ext:
if colorscheme == '__main__':
configs.append([config for config in data['ext_colorscheme_configs'][ext].items()])
configs.append([config for config in data['top_colorscheme_configs'].items()])
else:
try:
configs.append([data['ext_colorscheme_configs'][ext][colorscheme]])
except KeyError:
pass
try:
configs.append([data['ext_colorscheme_configs'][ext]['__main__']])
except KeyError:
pass
try:
configs.append([data['top_colorscheme_configs'][colorscheme]])
except KeyError:
pass
else:
try:
configs.append([data['top_colorscheme_configs'][colorscheme]])
except KeyError:
pass
new_echoerr = DelayedEchoErr(echoerr)
hadproblem = False
for config_lst in configs:
tofind = len(config_lst)
not_found = []
for config in config_lst:
if isinstance(config, tuple):
new_colorscheme, config = config
new_data = data.copy()
new_data['colorscheme'] = new_colorscheme
else:
new_data = data
try:
group_data = config['groups'][group]
except KeyError:
not_found.append(config.mark.name)
else:
proceed, echo, chadproblem = check_group(
group_data,
new_data,
context,
echoerr,
)
if chadproblem:
hadproblem = True
else:
tofind -= 1
if not tofind:
return proceed, echo, hadproblem
if not proceed:
break
if not_found:
new_echoerr(context='Error while checking group definition in colorscheme (key {key})'.format(key=context_key(context)),
problem='name {0} is not present in {1} {2} colorschemes: {3}'.format(group, tofind, ext, ', '.join(not_found)),
problem_mark=group.mark)
new_echoerr.echo_all()
return True, False, hadproblem
color_spec = Spec().type(unicode).func(check_color).copy
name_spec = Spec().type(unicode).len('gt', 0).optional().copy
group_spec = Spec(
group_name_spec = Spec().re('^\w+(?::\w+)?$').copy
group_spec = Spec().either(Spec(
fg=color_spec(),
bg=color_spec(),
attr=Spec().list(Spec().type(unicode).oneof(set(('bold', 'italic', 'underline')))).optional(),
).copy
group_name_spec = Spec().re('^\w+(?::\w+)?$').copy
attr=Spec().list(Spec().type(unicode).oneof(set(('bold', 'italic', 'underline')))),
), group_name_spec().func(check_group)).copy
groups_spec = Spec().unknown_spec(
group_name_spec(),
group_spec(),
@ -555,23 +630,32 @@ colorscheme_spec = (Spec(
name=name_spec(),
groups=groups_spec(),
).context_message('Error while loading coloscheme'))
mode_translations_value_spec = Spec(
colors=Spec().unknown_spec(
color_spec(),
color_spec(),
).optional(),
groups=Spec().unknown_spec(
group_name_spec().func(check_translated_group_name),
group_spec(),
).optional(),
).copy
top_colorscheme_spec = (Spec(
name=name_spec(),
groups=groups_spec(),
mode_translations=Spec().unknown_spec(
Spec().type(unicode),
mode_translations_value_spec(),
).optional().context_message('Error while loading mode translations (key {key})').optional(),
).context_message('Error while loading top-level coloscheme'))
vim_mode_spec = Spec().oneof(set(list(vim_modes) + ['nc'])).copy
vim_colorscheme_spec = (Spec(
name=name_spec(),
groups=groups_spec(),
mode_translations=Spec().unknown_spec(
vim_mode_spec(),
Spec(
colors=Spec().unknown_spec(
color_spec(),
color_spec(),
).optional(),
groups=Spec().unknown_spec(
group_name_spec().func(check_translated_group_name),
group_spec(),
).optional(),
),
).context_message('Error while loading mode translations (key {key})'),
mode_translations_value_spec(),
).optional().context_message('Error while loading mode translations (key {key})'),
).context_message('Error while loading vim colorscheme'))
shell_mode_spec = Spec().re('^(?:[\w\-]+|\.safe)$').copy
shell_colorscheme_spec = (Spec(
@ -579,17 +663,8 @@ shell_colorscheme_spec = (Spec(
groups=groups_spec(),
mode_translations=Spec().unknown_spec(
shell_mode_spec(),
Spec(
colors=Spec().unknown_spec(
color_spec(),
color_spec(),
).optional(),
groups=Spec().unknown_spec(
group_name_spec().func(check_translated_group_name),
group_spec(),
).optional(),
),
).context_message('Error while loading mode translations (key {key})'),
mode_translations_value_spec(),
).optional().context_message('Error while loading mode translations (key {key})'),
).context_message('Error while loading shell colorscheme'))
@ -1044,44 +1119,60 @@ def check(path=None, debug=False):
ee = EchoErr(echoerr, logger)
dirs = {
paths = {
'themes': defaultdict(lambda: []),
'colorschemes': defaultdict(lambda: [])
'colorschemes': defaultdict(lambda: []),
'top_colorschemes': [],
'top_themes': [],
}
lists = {
'colorschemes': set(),
'themes': set(),
'exts': set(),
}
for path in reversed(search_paths):
for subdir in ('themes', 'colorschemes'):
d = os.path.join(path, subdir)
for typ in ('themes', 'colorschemes'):
d = os.path.join(path, typ)
if os.path.isdir(d):
for ext in os.listdir(d):
extd = os.path.join(d, ext)
if os.path.isdir(extd):
dirs[subdir][ext].append(extd)
elif os.path.exists(d):
for subp in os.listdir(d):
extpath = os.path.join(d, subp)
if os.path.isdir(extpath):
lists['exts'].add(subp)
paths[typ][subp].append(extpath)
elif extpath.endswith('.json'):
name = subp[:-5]
if name != '__main__':
lists[typ].add(name)
paths['top_' + typ].append(extpath)
else:
hadproblem = True
sys.stderr.write('Path {0} is supposed to be a directory, but it is not\n'.format(d))
configs = {
'themes': defaultdict(lambda: {}),
'colorschemes': defaultdict(lambda: {})
}
for subdir in ('themes', 'colorschemes'):
for ext in dirs[subdir]:
for d in dirs[subdir][ext]:
for config in os.listdir(d):
if os.path.isdir(os.path.join(d, config)):
dirs[subdir][ext].append(os.path.join(d, config))
elif config.endswith('.json'):
configs[subdir][ext][config[:-5]] = os.path.join(d, config)
configs = defaultdict(lambda: defaultdict(lambda: {}))
for typ in ('themes', 'colorschemes'):
for ext in paths[typ]:
for d in paths[typ][ext]:
for subp in os.listdir(d):
if subp.endswith('.json'):
name = subp[:-5]
if name != '__main__':
lists[typ].add(name)
configs[typ][ext][name] = os.path.join(d, subp)
for path in paths['top_' + typ]:
name = os.path.basename(path)[:-5]
configs['top_' + typ][name] = path
diff = set(configs['themes']) ^ set(configs['colorschemes'])
if diff:
hadproblem = True
for ext in diff:
sys.stderr.write('{0} extension {1} present only in {2}\n'.format(
ext,
'configuration' if (ext in dirs['themes'] and ext in dirs['colorschemes']) else 'directory',
'themes' if ext in configs['themes'] else 'colorschemes',
))
typ = 'colorschemes' if ext in configs['themes'] else 'themes'
if not configs['top_' + typ] or typ == 'themes':
sys.stderr.write('{0} extension {1} not present in {2}\n'.format(
ext,
'configuration' if (ext in paths['themes'] and ext in paths['colorschemes']) else 'directory',
typ,
))
lhadproblem = [False]
@ -1103,7 +1194,7 @@ def check(path=None, debug=False):
sys.stderr.write(str(e) + '\n')
hadproblem = True
else:
if main_spec.match(main_config, data={'configs': configs}, context=(('', main_config),), echoerr=ee)[1]:
if main_spec.match(main_config, data={'configs': configs, 'lists': lists}, context=(('', main_config),), echoerr=ee)[1]:
hadproblem = True
import_paths = [os.path.expanduser(path) for path in main_config.get('common', {}).get('paths', [])]
@ -1125,9 +1216,30 @@ def check(path=None, debug=False):
if lhadproblem[0]:
hadproblem = True
colorscheme_configs = defaultdict(lambda: {})
top_colorscheme_configs = {}
data = {
'ext': None,
'top_colorscheme_configs': top_colorscheme_configs,
'ext_colorscheme_configs': {},
'colors_config': colors_config
}
for colorscheme, cfile in configs['top_colorschemes'].items():
with open_file(cfile) as config_file_fp:
try:
config, lhadproblem = load(config_file_fp)
except MarkedError as e:
sys.stderr.write(str(e) + '\n')
hadproblem = True
continue
if lhadproblem:
hadproblem = True
top_colorscheme_configs[colorscheme] = config
data['colorscheme'] = colorscheme
if top_colorscheme_spec.match(config, context=(('', config),), data=data, echoerr=ee)[1]:
hadproblem = True
ext_colorscheme_configs = defaultdict(lambda: {})
for ext in configs['colorschemes']:
data = {'ext': ext, 'colors_config': colors_config}
for colorscheme, cfile in configs['colorschemes'][ext].items():
with open_file(cfile) as config_file_fp:
try:
@ -1138,7 +1250,17 @@ def check(path=None, debug=False):
continue
if lhadproblem:
hadproblem = True
colorscheme_configs[ext][colorscheme] = config
ext_colorscheme_configs[ext][colorscheme] = config
for ext, econfigs in ext_colorscheme_configs.items():
data = {
'ext': ext,
'top_colorscheme_configs': top_colorscheme_configs,
'ext_colorscheme_configs': ext_colorscheme_configs,
'colors_config': colors_config,
}
for colorscheme, config in econfigs.items():
data['colorscheme'] = colorscheme
if ext == 'vim':
spec = vim_colorscheme_spec
elif ext == 'shell':
@ -1148,6 +1270,27 @@ def check(path=None, debug=False):
if spec.match(config, context=(('', config),), data=data, echoerr=ee)[1]:
hadproblem = True
colorscheme_configs = {}
for ext in lists['exts']:
colorscheme_configs[ext] = {}
for colorscheme in lists['colorschemes']:
econfigs = ext_colorscheme_configs[ext]
ecconfigs = econfigs.get(colorscheme)
mconfigs = (
top_colorscheme_configs.get(colorscheme),
econfigs.get('__main__'),
ecconfigs,
)
config = None
for mconfig in mconfigs:
if not mconfig:
continue
if config:
config = mergedicts_copy(config, mconfig)
else:
config = mconfig
colorscheme_configs[colorscheme] = config
theme_configs = defaultdict(lambda: {})
for ext in configs['themes']:
for theme, sfile in configs['themes'][ext].items():
@ -1161,6 +1304,7 @@ def check(path=None, debug=False):
if lhadproblem:
hadproblem = True
theme_configs[ext][theme] = config
for ext, configs in theme_configs.items():
data = {'ext': ext, 'colorscheme_configs': colorscheme_configs, 'import_paths': import_paths,
'main_config': main_config, 'ext_theme_configs': configs, 'colors_config': colors_config}

View File

@ -47,6 +47,16 @@ class MarkedFloat(float):
__new__ = gen_new(float)
class MarkedDict(dict):
__new__ = gen_new(dict)
def __init__(self, value, mark):
super(MarkedDict, self).__init__(value)
def copy(self):
return MarkedDict(super(MarkedDict, self).copy(), self.mark)
class MarkedValue:
def __init__(self, value, mark):
self.mark = mark
@ -57,6 +67,7 @@ specialclasses = {
unicode: MarkedUnicode,
int: MarkedInt,
float: MarkedFloat,
dict: MarkedDict,
}
classcache = {}
@ -70,7 +81,10 @@ def gen_marked_value(value, mark, use_special_classes=True):
else:
class Marked(MarkedValue):
for func in value.__class__.__dict__:
if func not in set(('__init__', '__new__', '__getattribute__')):
if func == 'copy':
def copy(self):
return self.__class__(self.value.copy(), self.mark)
elif func not in set(('__init__', '__new__', '__getattribute__')):
if func in set(('__eq__',)):
# HACK to make marked dictionaries always work
exec (('def {0}(self, *args):\n'

View File

@ -22,6 +22,8 @@ for script in tests/*.vim ; do
done
if ! sh tests/test_shells/test.sh ; then
echo "Failed shells"
FAILED=1
if ${PYTHON} -c 'import platform, sys; sys.exit(1 * (platform.python_implementation() == "PyPy"))' ; then
FAILED=1
fi
fi
exit $FAILED

View File

@ -101,7 +101,7 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=True) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config', wait=False, interval=0.05)
# When running once thread should not start
@ -117,7 +117,7 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['common']['spaces'] = 1
add_watcher_events(p, 'config')
@ -141,14 +141,19 @@ class TestConfigReload(TestCase):
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'colorschemes/test/nonexistent')
self.assertAccessEvents('config', 'colorschemes/nonexistent', 'colorschemes/test/__main__', 'colorschemes/test/nonexistent')
# It should normally handle file missing error
self.assertEqual(p.logger._pop_msgs(), ['exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'])
self.assertEqual(p.logger._pop_msgs(), [
'exception:test:powerline:Failed to load colorscheme: colorschemes/nonexistent',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/__main__',
'exception:test:powerline:Failed to load colorscheme: colorschemes/test/nonexistent',
'exception:test:powerline:Failed to create renderer: colorschemes/test/nonexistent'
])
config['config']['ext']['test']['colorscheme'] = '2'
add_watcher_events(p, 'config')
self.assertEqual(p.render(), '<2 3 1> s <3 4 False>>><1 4 4>g <4 False False>>><None None None>')
self.assertAccessEvents('config', 'colorschemes/test/2')
self.assertAccessEvents('config', 'colorschemes/2', 'colorschemes/test/__main__', 'colorschemes/test/2')
self.assertEqual(p.logger._pop_msgs(), [])
config['config']['ext']['test']['theme'] = '2'
@ -170,7 +175,7 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
add_watcher_events(p, 'config')
@ -182,9 +187,14 @@ class TestConfigReload(TestCase):
# fcf:colorschemes/test/nonexistentraise”).
# sleep(0.1)
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config')
# For colorschemes/{test/,}*raise find_config_file raises
# IOError, but it does not do so for colorschemes/test/__main__,
# so powerline is trying to load this, but not other
# colorschemes/*
self.assertAccessEvents('config', 'colorschemes/test/__main__')
self.assertIn('exception:test:powerline:Failed to create renderer: fcf:colorschemes/test/nonexistentraise', p.logger._pop_msgs())
config['colorschemes/nonexistentraise'] = {}
config['colorschemes/test/nonexistentraise'] = {
'groups': {
"str1": {"fg": "col1", "bg": "col3", "attr": ["bold"]},
@ -192,9 +202,10 @@ class TestConfigReload(TestCase):
},
}
while not p._will_create_renderer():
sleep(0.000001)
sleep(0.1)
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><2 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('colorschemes/test/nonexistentraise')
# Same as above
self.assertAccessEvents('colorschemes/nonexistentraise', 'colorschemes/test/nonexistentraise', 'colorschemes/test/__main__')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
@ -202,7 +213,7 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['colors']['colors']['col1'] = 5
add_watcher_events(p, 'colors')
@ -215,12 +226,12 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
add_watcher_events(p, 'colorschemes/test/default')
self.assertEqual(p.render(), '<1 3 1> s<3 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('colorschemes/test/default')
self.assertAccessEvents('colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default')
self.assertEqual(p.logger._pop_msgs(), [])
pop_events()
@ -228,7 +239,7 @@ class TestConfigReload(TestCase):
with get_powerline(run_once=False) as p:
with replace_item(globals(), 'config', deepcopy(config)):
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default')
@ -242,7 +253,7 @@ class TestConfigReload(TestCase):
config['config']['common']['interval'] = None
with get_powerline(run_once=False) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)
@ -257,7 +268,7 @@ class TestConfigReload(TestCase):
config['config']['common']['interval'] = None
with get_powerline(run_once=True) as p:
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
self.assertAccessEvents('config', 'colors', 'colorschemes/test/default', 'themes/test/default')
self.assertAccessEvents('config', 'colors', 'colorschemes/default', 'colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
add_watcher_events(p, 'themes/test/default', wait=False)

View File

@ -12,6 +12,16 @@ import sys
import os
def highlighted_string(s, group, **kwargs):
ret = {
'type': 'string',
'contents': s,
'highlight_group': [group],
}
ret.update(kwargs)
return ret
config = {
'config': {
'common': {
@ -46,14 +56,39 @@ config = {
'col2': 2,
'col3': 3,
'col4': 4,
'col5': 5,
'col6': 6,
'col7': 7,
'col8': 8,
'col9': 9,
'col10': 10,
'col11': 11,
'col12': 12,
},
'gradients': {
},
},
'colorschemes/test/__main__': {
'groups': {
'm1': 'g1',
'm2': 'g3',
'm3': {'fg': 'col11', 'bg': 'col12', 'attr': []},
}
},
'colorschemes/default': {
'groups': {
'g1': {'fg': 'col5', 'bg': 'col6', 'attr': []},
'g2': {'fg': 'col7', 'bg': 'col8', 'attr': []},
'g3': {'fg': 'col9', 'bg': 'col10', 'attr': []},
}
},
'colorschemes/test/default': {
'groups': {
'str1': {'fg': 'col1', 'bg': 'col2', 'attr': ['bold']},
'str2': {'fg': 'col3', 'bg': 'col4', 'attr': ['underline']},
'd1': 'g2',
'd2': 'm2',
'd3': 'm3',
},
},
'colorschemes/vim/default': {
@ -64,26 +99,11 @@ config = {
'themes/test/default': {
'segments': {
'left': [
{
'type': 'string',
'contents': 's',
'width': 'auto',
'highlight_group': ['str1'],
},
{
'type': 'string',
'contents': 'g',
'highlight_group': ['str2'],
},
highlighted_string('s', 'str1', width='auto'),
highlighted_string('g', 'str2'),
],
'right': [
{
'type': 'string',
'contents': 'f',
'width': 'auto',
'align': 'right',
'highlight_group': ['str2'],
},
highlighted_string('f', 'str2', width='auto', align='right'),
],
},
},
@ -111,13 +131,15 @@ def add_p_arg(func):
return f
class TestSingleLine(TestCase):
class TestRender(TestCase):
def assertRenderEqual(self, p, output, **kwargs):
self.assertEqual(p.render(**kwargs).replace(' ', ' '), output)
def assertRenderLinesEqual(self, p, output, **kwargs):
self.assertEqual([l.replace(' ', ' ') for l in p.render_above_lines(**kwargs)], output)
class TestLines(TestRender):
@add_p_arg
def test_without_above(self, p):
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}<{344}f {--}')
@ -149,6 +171,115 @@ class TestSingleLine(TestCase):
], width=10)
class TestColorschemesHierarchy(TestRender):
@add_p_arg
def test_group_redirects(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('b', 'd2', draw_hard_divider=False),
highlighted_string('c', 'd3', draw_hard_divider=False),
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{910}b{1112}c{56}A{910}B{1112}C{56}1{78}2{910}3{--}')
@add_p_arg
def test_group_redirects_no_main(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('a', 'd1', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{78} a{56}1{78}2{910}3{--}')
@add_p_arg
def test_group_redirects_no_top_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('c', 'd3', draw_soft_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{1112} c{1112}C{--}')
@add_p_arg
def test_group_redirects_no_test_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('A', 'm1', draw_hard_divider=False),
highlighted_string('B', 'm2', draw_hard_divider=False),
highlighted_string('C', 'm3', draw_hard_divider=False),
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} A{910}B{1112}C{56}1{78}2{910}3{--}')
@add_p_arg
def test_group_redirects_only_main(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('C', 'm3', draw_hard_divider=False),
],
'right': [],
}
# Powerline is not able to work without default colorscheme
# somewhere, thus it will output error string
self.assertRenderEqual(p, 'colorschemes/test/default')
@add_p_arg
def test_group_redirects_only_top_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/test/__main__']
del config['colorschemes/test/default']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('1', 'g1', draw_hard_divider=False),
highlighted_string('2', 'g2', draw_hard_divider=False),
highlighted_string('3', 'g3', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{56} 1{78}2{910}3{--}')
@add_p_arg
def test_group_redirects_only_test_default(self, p):
with replace_item(globals(), 'config', deepcopy(config)):
del config['colorschemes/default']
del config['colorschemes/test/__main__']
config['themes/test/default']['segments'] = {
'left': [
highlighted_string('s', 'str1', draw_hard_divider=False),
],
'right': [],
}
self.assertRenderEqual(p, '{121} s{--}')
class TestVim(TestCase):
def test_environ_update(self):
# Regression test: test that segment obtains environment from vim, not