parent
145e1c2050
commit
bdde4ae99f
|
@ -17,9 +17,11 @@ Powerline provides default configurations in the following locations:
|
|||
:file:`powerline/config.json`
|
||||
:ref:`Colorschemes <config-colors>`
|
||||
:file:`powerline/colorschemes/{name}.json`,
|
||||
:file:`powerline/colorscheme/__main__.json`,
|
||||
:file:`powerline/colorscheme/{extension}/__main__.json`,
|
||||
:file:`powerline/colorschemes/{extension}/{name}.json`
|
||||
:ref:`Themes <config-themes>`
|
||||
:file:`powerline/themes/{top_theme}.json`,
|
||||
:file:`powerline/themes/{extension}/__main__.json`,
|
||||
:file:`powerline/themes/{extension}/default.json`
|
||||
|
||||
The default configuration files are stored in the main package. User
|
||||
|
@ -48,6 +50,10 @@ overrides <local-configuration-overrides>`.
|
|||
corresponding values are both dictionaries in which case these dictionaries
|
||||
are merged and key is assigned the result of the merge.
|
||||
|
||||
.. note:: Some configuration files (i.e. themes and colorschemes) have two level
|
||||
of merging: first happens merging described above, second theme- or
|
||||
colorscheme-specific merging happens.
|
||||
|
||||
.. _quick-guide:
|
||||
|
||||
Quick setup guide
|
||||
|
|
|
@ -58,15 +58,6 @@ Common configuration is a subdictionary that is a value of ``common`` key in
|
|||
codes thus rendering powerline prompt colorless. Valid values: ``"tmux"``,
|
||||
``"screen"``, ``null`` (default).
|
||||
|
||||
``dividers``
|
||||
Defines the dividers used in all Powerline extensions. This option
|
||||
should usually only be changed if you don't have a patched font, or if
|
||||
you use a font patched with the legacy font patcher.
|
||||
|
||||
The ``hard`` dividers are used to divide segments with different
|
||||
background colors, while the ``soft`` dividers are used to divide
|
||||
segments with the same background color.
|
||||
|
||||
.. _config-common-paths:
|
||||
|
||||
``paths``
|
||||
|
@ -95,6 +86,12 @@ Common configuration is a subdictionary that is a value of ``common`` key in
|
|||
Boolean, determines whether configuration should be reloaded at all.
|
||||
Defaults to ``True``.
|
||||
|
||||
.. _config-common-default_top_theme:
|
||||
|
||||
``default_top_theme``
|
||||
String, determines which top-level theme will be used as the default.
|
||||
Defaults to ``powerline``. See `Themes`_ section for more details.
|
||||
|
||||
Extension-specific configuration
|
||||
--------------------------------
|
||||
|
||||
|
@ -109,6 +106,12 @@ Common configuration is a subdictionary that is a value of ``ext`` key in
|
|||
|
||||
Defines the theme used for this extension.
|
||||
|
||||
``top_theme``
|
||||
.. _config-ext-top_theme:
|
||||
|
||||
Defines the top-level theme used for this extension. See `Themes`_ section
|
||||
for more details.
|
||||
|
||||
``local_themes``
|
||||
.. _config-ext-local_themes:
|
||||
|
||||
|
@ -155,7 +158,7 @@ Colorschemes
|
|||
============
|
||||
|
||||
:Location: :file:`powerline/colorschemes/{name}.json`,
|
||||
:file:`powerline/colorscheme/__main__.json`,
|
||||
:file:`powerline/colorschemes/__main__.json`,
|
||||
:file:`powerline/colorschemes/{extension}/{name}.json`
|
||||
|
||||
Colorscheme files are processed in order given: definitions from each next file
|
||||
|
@ -213,7 +216,17 @@ override those from each previous file. It is required that either
|
|||
Themes
|
||||
======
|
||||
|
||||
:Location: :file:`powerline/themes/{extension}/{name}.json`
|
||||
:Location: :file:`powerline/themes/{top_theme}.json`,
|
||||
:file:`powerline/themes/__main__.json`,
|
||||
:file:`powerline/themes/{extension}/{name}.json`
|
||||
|
||||
Theme files are processed in order given: definitions from each next file
|
||||
override those from each previous file. It is required that file
|
||||
:file:`powerline/themes/{extension}/{name}.json` exists.
|
||||
|
||||
`{top_theme}` component of the file name is obtained either from :ref:`top_theme
|
||||
extension-specific key <config-ext-top_theme>` or from :ref:`default_top_theme
|
||||
common configuration key <config-common-default_top_theme>`.
|
||||
|
||||
``name``
|
||||
Name of the theme.
|
||||
|
@ -223,6 +236,20 @@ Themes
|
|||
``default_module``
|
||||
Python module where segments will be looked by default.
|
||||
|
||||
``spaces``
|
||||
Defines number of spaces just before the divider (on the right side) or just
|
||||
after it (on the left side). These spaces will not be added if divider is
|
||||
not drawn.
|
||||
|
||||
``dividers``
|
||||
Defines the dividers used in all Powerline extensions. This option
|
||||
should usually only be changed if you don't have a patched font, or if
|
||||
you use a font patched with the legacy font patcher.
|
||||
|
||||
The ``hard`` dividers are used to divide segments with different
|
||||
background colors, while the ``soft`` dividers are used to divide
|
||||
segments with the same background color.
|
||||
|
||||
.. _config-themes-segment_data:
|
||||
|
||||
``segment_data``
|
||||
|
@ -240,6 +267,9 @@ Themes
|
|||
<config-ext-theme>`. For the :ref:`default theme <config-ext-theme>` itself
|
||||
step 2 is obviously avoided.
|
||||
|
||||
.. note:: Top-level themes are out of equation here: they are merged
|
||||
before the above merging process happens.
|
||||
|
||||
``segments``
|
||||
A dict with a ``left`` and a ``right`` lists, consisting of segment
|
||||
dictionaries. Shell themes may also contain ``above`` list of dictionaries.
|
||||
|
|
|
@ -215,6 +215,7 @@ def finish_common_config(common_config):
|
|||
paths.
|
||||
'''
|
||||
common_config = common_config.copy()
|
||||
common_config.setdefault('default_top_theme', 'powerline')
|
||||
common_config.setdefault('paths', [])
|
||||
common_config.setdefault('watcher', 'auto')
|
||||
common_config.setdefault('log_level', 'WARNING')
|
||||
|
@ -345,13 +346,15 @@ class Powerline(object):
|
|||
if load_main:
|
||||
self._purge_configs('main')
|
||||
config = self.load_main_config()
|
||||
self.common_config = config['common']
|
||||
self.common_config = finish_common_config(config['common'])
|
||||
if self.common_config != self.prev_common_config:
|
||||
common_config_differs = True
|
||||
|
||||
self.prev_common_config = self.common_config
|
||||
load_theme = (load_theme
|
||||
or not self.prev_common_config
|
||||
or self.prev_common_config['default_top_theme'] != self.common_config['default_top_theme'])
|
||||
|
||||
self.common_config = finish_common_config(self.common_config)
|
||||
self.prev_common_config = self.common_config
|
||||
|
||||
self.import_paths = self.common_config['paths']
|
||||
|
||||
|
@ -386,6 +389,8 @@ class Powerline(object):
|
|||
if interval is not None and not self.config_loader.is_alive():
|
||||
self.config_loader.start()
|
||||
|
||||
self.default_top_theme = self.common_config['default_top_theme']
|
||||
|
||||
self.ext_config = config['ext'][self.ext]
|
||||
if self.ext_config != self.prev_ext_config:
|
||||
ext_config_differs = True
|
||||
|
@ -445,30 +450,20 @@ class Powerline(object):
|
|||
'''
|
||||
return get_config_paths()
|
||||
|
||||
def _load_config(self, cfg_path, type):
|
||||
def _load_config(self, cfg_path, cfg_type):
|
||||
'''Load configuration and setup watches.'''
|
||||
return load_config(
|
||||
cfg_path,
|
||||
self.find_config_files,
|
||||
self.config_loader,
|
||||
self.cr_callbacks[type]
|
||||
self.cr_callbacks[cfg_type]
|
||||
)
|
||||
|
||||
def _purge_configs(self, type):
|
||||
function = self.cr_callbacks[type]
|
||||
def _purge_configs(self, cfg_type):
|
||||
function = self.cr_callbacks[cfg_type]
|
||||
self.config_loader.unregister_functions(set((function,)))
|
||||
self.config_loader.unregister_missing(set(((self.find_config_files, function),)))
|
||||
|
||||
def load_theme_config(self, name):
|
||||
'''Get theme configuration.
|
||||
|
||||
:param str name:
|
||||
Name of the theme to load.
|
||||
|
||||
:return: dictionary with :ref:`theme configuration <config-themes>`
|
||||
'''
|
||||
return self._load_config(os.path.join('themes', self.ext, name), 'theme')
|
||||
|
||||
def load_main_config(self):
|
||||
'''Get top-level configuration.
|
||||
|
||||
|
@ -476,6 +471,47 @@ class Powerline(object):
|
|||
'''
|
||||
return self._load_config('config', 'main')
|
||||
|
||||
def _load_hierarhical_config(self, cfg_type, levels, ignore_levels):
|
||||
'''Load and merge multiple configuration files
|
||||
|
||||
:param str cfg_type:
|
||||
Type of the loaded configuration files (e.g. ``colorscheme``,
|
||||
``theme``).
|
||||
:param list levels:
|
||||
Configuration names resembling levels in hierarchy, sorted by
|
||||
priority. Configuration file names with higher priority should go
|
||||
last.
|
||||
:param set ignore_levels:
|
||||
If only files listed in this variable are present then configuration
|
||||
file is considered not loaded: at least one file on the level not
|
||||
listed in this variable must be present.
|
||||
'''
|
||||
config = {}
|
||||
loaded = 0
|
||||
exceptions = []
|
||||
for i, cfg_path in enumerate(levels):
|
||||
try:
|
||||
lvl_config = self._load_config(cfg_path, cfg_type)
|
||||
except IOError as e:
|
||||
if sys.version_info < (3,):
|
||||
tb = sys.exc_info()[2]
|
||||
exceptions.append((e, tb))
|
||||
else:
|
||||
exceptions.append(e)
|
||||
else:
|
||||
if i not in ignore_levels:
|
||||
loaded += 1
|
||||
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 %s: {0}' % cfg_type, e, exception=exception)
|
||||
raise e
|
||||
return config
|
||||
|
||||
def load_colorscheme_config(self, name):
|
||||
'''Get colorscheme.
|
||||
|
||||
|
@ -484,40 +520,27 @@ class Powerline(object):
|
|||
|
||||
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
|
||||
'''
|
||||
# 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
|
||||
return self._load_hierarhical_config('colorscheme', levels, (1,))
|
||||
|
||||
def load_theme_config(self, name):
|
||||
'''Get theme configuration.
|
||||
|
||||
:param str name:
|
||||
Name of the theme to load.
|
||||
|
||||
:return: dictionary with :ref:`theme configuration <config-themes>`
|
||||
'''
|
||||
levels = (
|
||||
os.path.join('themes', self.ext_config.get('top_theme') or self.default_top_theme),
|
||||
os.path.join('themes', self.ext, '__main__'),
|
||||
os.path.join('themes', self.ext, name),
|
||||
)
|
||||
return self._load_hierarhical_config('theme', levels, (0, 1,))
|
||||
|
||||
def load_colors_config(self):
|
||||
'''Get colorscheme.
|
||||
|
|
|
@ -1,17 +1,6 @@
|
|||
{
|
||||
"common": {
|
||||
"term_truecolor": false,
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
}
|
||||
},
|
||||
"spaces": 1
|
||||
"term_truecolor": false
|
||||
},
|
||||
"ext": {
|
||||
"ipython": {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
}
|
||||
},
|
||||
"spaces": 1
|
||||
}
|
|
@ -431,9 +431,6 @@ class WithPath(object):
|
|||
def check_matcher_func(ext, match_name, data, context, echoerr):
|
||||
import_paths = [os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', [])]
|
||||
|
||||
if match_name == '__tabline__':
|
||||
return True, False
|
||||
|
||||
match_module, separator, match_function = match_name.rpartition('.')
|
||||
if not separator:
|
||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
||||
|
@ -512,23 +509,30 @@ def check_config(d, theme, data, context, echoerr):
|
|||
return True, False, False
|
||||
|
||||
|
||||
def check_top_theme(theme, data, context, echoerr):
|
||||
if theme not in data['configs']['top_themes']:
|
||||
echoerr(context='Error while checking extension configuration (key {key})'.format(key=context_key(context)),
|
||||
context_mark=context[-2][0].mark,
|
||||
problem='failed to find top theme {0}'.format(theme),
|
||||
problem_mark=theme.mark)
|
||||
return True, False, True
|
||||
return True, False, False
|
||||
|
||||
|
||||
divider_spec = Spec().type(unicode).len('le', 3,
|
||||
lambda value: 'Divider {0!r} is too large!'.format(value)).copy
|
||||
divside_spec = Spec(
|
||||
hard=divider_spec(),
|
||||
soft=divider_spec(),
|
||||
ext_theme_spec = Spec().type(unicode).func(lambda *args: check_config('themes', *args)).copy
|
||||
top_theme_spec = Spec().type(unicode).func(check_top_theme).copy
|
||||
ext_spec = Spec(
|
||||
colorscheme=Spec().type(unicode).func(
|
||||
(lambda *args: check_config('colorschemes', *args))
|
||||
),
|
||||
theme=ext_theme_spec(),
|
||||
top_theme=top_theme_spec().optional(),
|
||||
).copy
|
||||
colorscheme_spec = Spec().type(unicode).func(lambda *args: check_config('colorschemes', *args)).copy
|
||||
theme_spec = Spec().type(unicode).func(lambda *args: check_config('themes', *args)).copy
|
||||
main_spec = (Spec(
|
||||
common=Spec(
|
||||
dividers=Spec(
|
||||
left=divside_spec(),
|
||||
right=divside_spec(),
|
||||
),
|
||||
spaces=Spec().unsigned().cmp(
|
||||
'le', 2, lambda value: 'Are you sure you need such a big ({0}) number of spaces?'.format(value)
|
||||
),
|
||||
default_top_theme=top_theme_spec().optional(),
|
||||
term_truecolor=Spec().type(bool).optional(),
|
||||
# Python is capable of loading from zip archives. Thus checking path
|
||||
# only for existence of the path, not for it being a directory
|
||||
|
@ -556,36 +560,29 @@ main_spec = (Spec(
|
|||
watcher=Spec().type(unicode).oneof(set(('auto', 'inotify', 'stat'))).optional(),
|
||||
).context_message('Error while loading common configuration (key {key})'),
|
||||
ext=Spec(
|
||||
vim=Spec(
|
||||
colorscheme=colorscheme_spec(),
|
||||
theme=theme_spec(),
|
||||
local_themes=Spec().unknown_spec(
|
||||
lambda *args: check_matcher_func('vim', *args), theme_spec()
|
||||
vim=ext_spec().update(
|
||||
local_themes=Spec(
|
||||
__tabline__=ext_theme_spec(),
|
||||
).unknown_spec(
|
||||
lambda *args: check_matcher_func('vim', *args), ext_theme_spec()
|
||||
),
|
||||
).optional(),
|
||||
ipython=Spec(
|
||||
colorscheme=colorscheme_spec(),
|
||||
theme=theme_spec(),
|
||||
ipython=ext_spec().update(
|
||||
local_themes=Spec(
|
||||
in2=theme_spec(),
|
||||
out=theme_spec(),
|
||||
rewrite=theme_spec(),
|
||||
in2=ext_theme_spec(),
|
||||
out=ext_theme_spec(),
|
||||
rewrite=ext_theme_spec(),
|
||||
),
|
||||
).optional(),
|
||||
shell=Spec(
|
||||
colorscheme=colorscheme_spec(),
|
||||
theme=theme_spec(),
|
||||
shell=ext_spec().update(
|
||||
local_themes=Spec(
|
||||
continuation=theme_spec(),
|
||||
select=theme_spec(),
|
||||
continuation=ext_theme_spec(),
|
||||
select=ext_theme_spec(),
|
||||
),
|
||||
).optional(),
|
||||
).unknown_spec(
|
||||
check_ext,
|
||||
Spec(
|
||||
colorscheme=colorscheme_spec(),
|
||||
theme=theme_spec(),
|
||||
)
|
||||
ext_spec(),
|
||||
).context_message('Error while loading extensions configuration (key {key})'),
|
||||
).context_message('Error while loading main configuration'))
|
||||
|
||||
|
@ -771,7 +768,7 @@ type_keys = {
|
|||
}
|
||||
required_keys = {
|
||||
'function': set(('name',)),
|
||||
'string': set(('contents',)),
|
||||
'string': set(()),
|
||||
'filler': set(),
|
||||
'segment_list': set(('name', 'segments',)),
|
||||
}
|
||||
|
@ -845,11 +842,11 @@ def check_full_segment_data(segment, data, context, echoerr):
|
|||
|
||||
ext = data['ext']
|
||||
theme_segment_data = context[0][1].get('segment_data', {})
|
||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
if not top_theme_name or data['theme'] == top_theme_name:
|
||||
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
if not main_theme_name or data['theme'] == main_theme_name:
|
||||
top_segment_data = {}
|
||||
else:
|
||||
top_segment_data = data['ext_theme_configs'].get(top_theme_name, {}).get('segment_data', {})
|
||||
top_segment_data = data['ext_theme_configs'].get(main_theme_name, {}).get('segment_data', {})
|
||||
|
||||
names = [segment['name']]
|
||||
if segment.get('type', 'function') == 'function':
|
||||
|
@ -977,12 +974,16 @@ def check_segment_name(name, data, context, echoerr):
|
|||
return True, False, hadproblem
|
||||
elif context[-2][1].get('type') != 'segment_list':
|
||||
if name not in context[0][1].get('segment_data', {}):
|
||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
if data['theme'] == top_theme_name:
|
||||
top_theme = {}
|
||||
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
if data['theme'] == main_theme_name:
|
||||
main_theme = {}
|
||||
else:
|
||||
top_theme = data['ext_theme_configs'].get(top_theme_name, {})
|
||||
if name not in top_theme.get('segment_data', {}):
|
||||
main_theme = data['ext_theme_configs'].get(main_theme_name, {})
|
||||
if (
|
||||
name not in main_theme.get('segment_data', {})
|
||||
and name not in data['ext_theme_configs'].get('__main__', {}).get('segment_data', {})
|
||||
and not any(((name in theme.get('segment_data', {})) for theme in data['top_themes'].values()))
|
||||
):
|
||||
echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)),
|
||||
problem='found useless use of name key (such name is not present in theme/segment_data)',
|
||||
problem_mark=name.mark)
|
||||
|
@ -1070,34 +1071,49 @@ def check_highlight_groups(hl_groups, data, context, echoerr):
|
|||
return True, False, False
|
||||
|
||||
|
||||
def check_segment_data_key(key, data, context, echoerr):
|
||||
def list_themes(data, context):
|
||||
theme_type = data['theme_type']
|
||||
ext = data['ext']
|
||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
is_top_theme = (data['theme'] == top_theme_name)
|
||||
if is_top_theme:
|
||||
themes = data['ext_theme_configs'].values()
|
||||
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||
is_main_theme = (data['theme'] == main_theme_name)
|
||||
if theme_type == 'top':
|
||||
return list(itertools.chain(*[
|
||||
[(ext, theme) for theme in theme_configs.values()]
|
||||
for ext, theme_configs in data['theme_configs'].items()
|
||||
]))
|
||||
elif theme_type == 'main' or is_main_theme:
|
||||
return [(ext, theme) for theme in data['ext_theme_configs'].values()]
|
||||
else:
|
||||
themes = [context[0][1]]
|
||||
return [(ext, context[0][1])]
|
||||
|
||||
for theme in themes:
|
||||
|
||||
def check_segment_data_key(key, data, context, echoerr):
|
||||
has_module_name = '.' in key
|
||||
found = False
|
||||
for ext, theme in list_themes(data, context):
|
||||
for segments in theme.get('segments', {}).values():
|
||||
found = False
|
||||
for segment in segments:
|
||||
if 'name' in segment:
|
||||
if key == segment['name']:
|
||||
found = True
|
||||
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext))
|
||||
if key == unicode(module) + '.' + unicode(segment['name']):
|
||||
found = True
|
||||
if has_module_name:
|
||||
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext))
|
||||
full_name = unicode(module) + '.' + unicode(segment['name'])
|
||||
if key == full_name:
|
||||
found = True
|
||||
break
|
||||
else:
|
||||
if key == segment['name']:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
break
|
||||
if found:
|
||||
break
|
||||
else:
|
||||
echoerr(context='Error while checking segment data',
|
||||
problem='found key {0} that cannot be associated with any segment'.format(key),
|
||||
problem_mark=key.mark)
|
||||
return True, False, True
|
||||
if data['theme_type'] != 'top':
|
||||
echoerr(context='Error while checking segment data',
|
||||
problem='found key {0} that cannot be associated with any segment'.format(key),
|
||||
problem_mark=key.mark)
|
||||
return True, False, True
|
||||
|
||||
return True, False, False
|
||||
|
||||
|
@ -1109,8 +1125,8 @@ threaded_args_specs = {
|
|||
}
|
||||
|
||||
|
||||
def check_args_variant(segment, args, data, context, echoerr):
|
||||
argspec = getconfigargspec(segment)
|
||||
def check_args_variant(func, args, data, context, echoerr):
|
||||
argspec = getconfigargspec(func)
|
||||
present_args = set(args)
|
||||
all_args = set(argspec.args)
|
||||
required_args = set(argspec.args[:-len(argspec.defaults)])
|
||||
|
@ -1132,7 +1148,7 @@ def check_args_variant(segment, args, data, context, echoerr):
|
|||
problem_mark=next(iter(present_args - all_args)).mark)
|
||||
hadproblem = True
|
||||
|
||||
if isinstance(segment, ThreadedSegment):
|
||||
if isinstance(func, ThreadedSegment):
|
||||
for key in set(threaded_args_specs) & present_args:
|
||||
proceed, khadproblem = threaded_args_specs[key].match(
|
||||
args[key],
|
||||
|
@ -1149,13 +1165,13 @@ def check_args_variant(segment, args, data, context, echoerr):
|
|||
return hadproblem
|
||||
|
||||
|
||||
def check_args(get_segment_variants, args, data, context, echoerr):
|
||||
def check_args(get_functions, args, data, context, echoerr):
|
||||
new_echoerr = DelayedEchoErr(echoerr)
|
||||
count = 0
|
||||
hadproblem = False
|
||||
for segment in get_segment_variants(data, context, new_echoerr):
|
||||
for func in get_functions(data, context, new_echoerr):
|
||||
count += 1
|
||||
shadproblem = check_args_variant(segment, args, data, context, echoerr)
|
||||
shadproblem = check_args_variant(func, args, data, context, echoerr)
|
||||
if shadproblem:
|
||||
hadproblem = True
|
||||
|
||||
|
@ -1171,7 +1187,7 @@ def check_args(get_segment_variants, args, data, context, echoerr):
|
|||
return True, False, hadproblem
|
||||
|
||||
|
||||
def get_one_segment_variant(data, context, echoerr):
|
||||
def get_one_segment_function(data, context, echoerr):
|
||||
name = context[-2][1].get('name')
|
||||
if name:
|
||||
func = import_segment(name, data, context, echoerr)
|
||||
|
@ -1179,7 +1195,7 @@ def get_one_segment_variant(data, context, echoerr):
|
|||
yield func
|
||||
|
||||
|
||||
def get_all_possible_segments(data, context, echoerr):
|
||||
def get_all_possible_functions(data, context, echoerr):
|
||||
name = context[-2][0]
|
||||
module, name = name.rpartition('.')[::2]
|
||||
if module:
|
||||
|
@ -1187,13 +1203,13 @@ def get_all_possible_segments(data, context, echoerr):
|
|||
if func:
|
||||
yield func
|
||||
else:
|
||||
for theme_config in data['ext_theme_configs'].values():
|
||||
for ext, theme_config in list_themes(data, context):
|
||||
for segments in theme_config.get('segments', {}).values():
|
||||
for segment in segments:
|
||||
if segment.get('type', 'function') == 'function':
|
||||
module = segment.get(
|
||||
'module',
|
||||
context[0][1].get('default_module', 'powerline.segments.' + data['ext'])
|
||||
theme_config.get('default_module', 'powerline.segments.' + data['ext'])
|
||||
)
|
||||
func = import_segment(name, data, context, echoerr, module=module)
|
||||
if func:
|
||||
|
@ -1222,7 +1238,7 @@ segment_spec = Spec(
|
|||
before=Spec().type(unicode).optional(),
|
||||
width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(),
|
||||
align=Spec().oneof(set('lr')).optional(),
|
||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_one_segment_variant, *args, **kwargs)),
|
||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_one_segment_function, *args, **kwargs)),
|
||||
contents=Spec().type(unicode).optional(),
|
||||
highlight_group=Spec().list(
|
||||
highlight_group_spec().re(
|
||||
|
@ -1245,20 +1261,52 @@ segdict_spec=Spec(
|
|||
(lambda value, *args: (True, True, not (('left' in value) or ('right' in value)))),
|
||||
(lambda value: 'segments dictionary must contain either left, right or both keys')
|
||||
).context_message('Error while loading segments (key {key})').copy
|
||||
theme_spec = (Spec(
|
||||
default_module=segment_module_spec(),
|
||||
divside_spec = Spec(
|
||||
hard=divider_spec(),
|
||||
soft=divider_spec(),
|
||||
).copy
|
||||
segment_data_value_spec = Spec(
|
||||
after=Spec().type(unicode).optional(),
|
||||
before=Spec().type(unicode).optional(),
|
||||
display=Spec().type(bool).optional(),
|
||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_all_possible_functions, *args, **kwargs)),
|
||||
contents=Spec().type(unicode).optional(),
|
||||
).copy
|
||||
dividers_spec = Spec(
|
||||
left=divside_spec(),
|
||||
right=divside_spec(),
|
||||
).copy
|
||||
spaces_spec = Spec().unsigned().cmp(
|
||||
'le', 2, (lambda value: 'Are you sure you need such a big ({0}) number of spaces?'.format(value))
|
||||
).copy
|
||||
common_theme_spec = Spec(
|
||||
default_module=segment_module_spec().optional(),
|
||||
).context_message('Error while loading theme').copy
|
||||
top_theme_spec = common_theme_spec().update(
|
||||
dividers=dividers_spec(),
|
||||
spaces=spaces_spec(),
|
||||
segment_data=Spec().unknown_spec(
|
||||
Spec().func(check_segment_data_key),
|
||||
Spec(
|
||||
after=Spec().type(unicode).optional(),
|
||||
before=Spec().type(unicode).optional(),
|
||||
display=Spec().type(bool).optional(),
|
||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_all_possible_segments, *args, **kwargs)),
|
||||
contents=Spec().type(unicode).optional(),
|
||||
),
|
||||
segment_data_value_spec(),
|
||||
).optional().context_message('Error while loading segment data (key {key})'),
|
||||
)
|
||||
main_theme_spec = common_theme_spec().update(
|
||||
dividers=dividers_spec().optional(),
|
||||
spaces=spaces_spec().optional(),
|
||||
segment_data=Spec().unknown_spec(
|
||||
Spec().func(check_segment_data_key),
|
||||
segment_data_value_spec(),
|
||||
).optional().context_message('Error while loading segment data (key {key})'),
|
||||
)
|
||||
theme_spec = common_theme_spec().update(
|
||||
dividers=dividers_spec().optional(),
|
||||
spaces=spaces_spec().optional(),
|
||||
segment_data=Spec().unknown_spec(
|
||||
Spec().func(check_segment_data_key),
|
||||
segment_data_value_spec(),
|
||||
).optional().context_message('Error while loading segment data (key {key})'),
|
||||
segments=segdict_spec().update(above=Spec().list(segdict_spec()).optional()),
|
||||
).context_message('Error while loading theme'))
|
||||
)
|
||||
|
||||
|
||||
def generate_json_config_loader(lhadproblem):
|
||||
|
@ -1315,6 +1363,8 @@ def check(paths=None, debug=False):
|
|||
hadproblem = True
|
||||
sys.stderr.write('Path {0} is supposed to be a directory, but it is not\n'.format(d))
|
||||
|
||||
hadproblem = False
|
||||
|
||||
configs = defaultdict(lambda: defaultdict(lambda: {}))
|
||||
for typ in ('themes', 'colorschemes'):
|
||||
for ext in paths[typ]:
|
||||
|
@ -1324,6 +1374,11 @@ def check(paths=None, debug=False):
|
|||
name = subp[:-5]
|
||||
if name != '__main__':
|
||||
lists[typ].add(name)
|
||||
if name.startswith('__') or name.endswith('__'):
|
||||
hadproblem = True
|
||||
sys.stderr.write('File name is not supposed to start or end with “__”: {0}'.format(
|
||||
os.path.join(d, subp)
|
||||
))
|
||||
configs[typ][ext][name] = os.path.join(d, subp)
|
||||
for path in paths['top_' + typ]:
|
||||
name = os.path.basename(path)[:-5]
|
||||
|
@ -1341,7 +1396,6 @@ def check(paths=None, debug=False):
|
|||
typ,
|
||||
))
|
||||
|
||||
hadproblem = False
|
||||
try:
|
||||
main_config = load_config('config', find_config_files, config_loader)
|
||||
except IOError:
|
||||
|
@ -1469,17 +1523,53 @@ def check(paths=None, debug=False):
|
|||
hadproblem = True
|
||||
theme_configs[ext][theme] = config
|
||||
|
||||
top_theme_configs = {}
|
||||
for top_theme, top_theme_file in configs['top_themes'].items():
|
||||
with open_file(top_theme_file) 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_theme_configs[top_theme] = config
|
||||
|
||||
for ext, configs in theme_configs.items():
|
||||
data = {
|
||||
'ext': ext,
|
||||
'colorscheme_configs': colorscheme_configs,
|
||||
'import_paths': import_paths,
|
||||
'main_config': main_config,
|
||||
'top_themes': top_theme_configs,
|
||||
'ext_theme_configs': configs,
|
||||
'colors_config': colors_config
|
||||
}
|
||||
for theme, config in configs.items():
|
||||
data['theme'] = theme
|
||||
if theme_spec.match(config, context=(('', config),), data=data, echoerr=ee)[1]:
|
||||
if theme == '__main__':
|
||||
data['theme_type'] = 'main'
|
||||
spec = main_theme_spec
|
||||
else:
|
||||
data['theme_type'] = 'regular'
|
||||
spec = theme_spec
|
||||
if spec.match(config, context=(('', config),), data=data, echoerr=ee)[1]:
|
||||
hadproblem = True
|
||||
|
||||
for top_theme, config in top_theme_configs.items():
|
||||
data = {
|
||||
'ext': ext,
|
||||
'colorscheme_configs': colorscheme_configs,
|
||||
'import_paths': import_paths,
|
||||
'main_config': main_config,
|
||||
'theme_configs': theme_configs,
|
||||
'ext_theme_configs': configs,
|
||||
'colors_config': colors_config
|
||||
}
|
||||
data['theme_type'] = 'top'
|
||||
data['theme'] = top_theme
|
||||
if top_theme_spec.match(config, context=(('', config),), data=data, echoerr=ee)[1]:
|
||||
hadproblem = True
|
||||
|
||||
return hadproblem
|
||||
|
|
|
@ -31,13 +31,13 @@ class Theme(object):
|
|||
top_theme_config=None,
|
||||
run_once=False,
|
||||
shutdown_event=None):
|
||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
||||
self.dividers = theme_config['dividers']
|
||||
self.dividers = dict((
|
||||
(key, dict((k, u(v))
|
||||
for k, v in val.items()))
|
||||
for key, val in self.dividers.items()
|
||||
))
|
||||
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
||||
self.spaces = theme_config['spaces']
|
||||
self.segments = []
|
||||
self.EMPTY_SEGMENT = {
|
||||
'contents': None,
|
||||
|
|
|
@ -17,17 +17,6 @@ CONFIG_DIR = 'tests/config'
|
|||
|
||||
root_config = lambda: {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '#>',
|
||||
'soft': '|>',
|
||||
},
|
||||
'right': {
|
||||
'hard': '<#',
|
||||
'soft': '<|',
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
'interval': None,
|
||||
'watcher': 'auto',
|
||||
},
|
||||
|
@ -76,12 +65,41 @@ theme_config = lambda: {
|
|||
}
|
||||
}
|
||||
|
||||
top_theme_config = lambda: {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '#>',
|
||||
'soft': '|>',
|
||||
},
|
||||
'right': {
|
||||
'hard': '<#',
|
||||
'soft': '<|',
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
}
|
||||
|
||||
|
||||
main_tree = lambda: {
|
||||
'1/config': root_config(),
|
||||
'1/colors': colors_config(),
|
||||
'1/colorschemes/default': colorscheme_config(),
|
||||
'1/themes/test/default': theme_config(),
|
||||
'1/themes/powerline': top_theme_config(),
|
||||
'1/themes/other1': mdc(top_theme_config(), {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '!>',
|
||||
}
|
||||
}
|
||||
}),
|
||||
'1/themes/other2': mdc(top_theme_config(), {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
}
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
|
@ -151,11 +169,7 @@ class TestMerging(TestCase):
|
|||
with WithConfigTree(mdc(main_tree(), {
|
||||
'2/config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '!>',
|
||||
}
|
||||
}
|
||||
'default_top_theme': 'other1',
|
||||
}
|
||||
},
|
||||
})) as p:
|
||||
|
@ -163,36 +177,26 @@ class TestMerging(TestCase):
|
|||
with WithConfigTree(mdc(main_tree(), {
|
||||
'2/config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '!>',
|
||||
}
|
||||
}
|
||||
'default_top_theme': 'other1',
|
||||
}
|
||||
},
|
||||
'3/config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
}
|
||||
}
|
||||
'default_top_theme': 'other2',
|
||||
}
|
||||
},
|
||||
})) as p:
|
||||
self.assertRenderEqual(p, '{12} bt{2-}>>{--}')
|
||||
|
||||
def test_top_theme_merging(self):
|
||||
with WithConfigTree(mdc(main_tree(), {
|
||||
'2/config': {
|
||||
'common': {
|
||||
'spaces': 1,
|
||||
}
|
||||
'2/themes/powerline': {
|
||||
'spaces': 1,
|
||||
},
|
||||
'3/config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
}
|
||||
'3/themes/powerline': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,17 +12,6 @@ from tests.lib.config_mock import get_powerline, add_watcher_events
|
|||
config = {
|
||||
'config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
"left": {
|
||||
"hard": ">>",
|
||||
"soft": ">",
|
||||
},
|
||||
"right": {
|
||||
"hard": "<<",
|
||||
"soft": "<",
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
'interval': 0,
|
||||
'watcher': 'test',
|
||||
},
|
||||
|
@ -73,6 +62,32 @@ config = {
|
|||
],
|
||||
},
|
||||
},
|
||||
'themes/powerline': {
|
||||
'dividers': {
|
||||
"left": {
|
||||
"hard": ">>",
|
||||
"soft": ">",
|
||||
},
|
||||
"right": {
|
||||
"hard": "<<",
|
||||
"soft": "<",
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
},
|
||||
'themes/other': {
|
||||
'dividers': {
|
||||
"left": {
|
||||
"hard": ">>",
|
||||
"soft": ">",
|
||||
},
|
||||
"right": {
|
||||
"hard": "<<",
|
||||
"soft": "<",
|
||||
},
|
||||
},
|
||||
'spaces': 1,
|
||||
},
|
||||
'themes/test/2': {
|
||||
'segments': {
|
||||
"left": [
|
||||
|
@ -116,7 +131,7 @@ class TestConfigReload(TestCase):
|
|||
def test_noreload(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
config['config']['common']['spaces'] = 1
|
||||
add_watcher_events(p, 'config', wait=False, interval=0.05)
|
||||
# When running once thread should not start
|
||||
|
@ -128,25 +143,30 @@ class TestConfigReload(TestCase):
|
|||
def test_reload_main(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['config']['common']['spaces'] = 1
|
||||
config['config']['common']['default_top_theme'] = 'other'
|
||||
add_watcher_events(p, 'config')
|
||||
p.render()
|
||||
self.assertEqual(p.render(), '<1 2 1> s <2 4 False>>><3 4 4>g <4 False False>>><None None None>')
|
||||
self.assertAccessEvents(p, 'config')
|
||||
self.assertAccessEvents(p, 'config', 'themes/other', 'check:themes/test/__main__', 'themes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
config['config']['ext']['test']['theme'] = '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(p, 'config', 'check:themes/test/nonexistent')
|
||||
self.assertAccessEvents(p, 'config', 'check:themes/test/nonexistent', 'themes/other', 'check:themes/test/__main__')
|
||||
# It should normally handle file missing error
|
||||
self.assertEqual(p.logger._pop_msgs(), ['exception:test:powerline:Failed to create renderer: themes/test/nonexistent'])
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load theme: themes/test/__main__',
|
||||
'exception:test:powerline:Failed to load theme: themes/test/nonexistent',
|
||||
'exception:test:powerline:Failed to create renderer: themes/test/nonexistent'
|
||||
])
|
||||
|
||||
config['config']['ext']['test']['theme'] = 'default'
|
||||
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(p, 'config', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'themes/test/default', 'themes/other', 'check:themes/test/__main__')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
|
||||
|
@ -170,7 +190,7 @@ class TestConfigReload(TestCase):
|
|||
config['config']['ext']['test']['theme'] = '2'
|
||||
add_watcher_events(p, 'config')
|
||||
self.assertEqual(p.render(), '<2 3 1> t <3 4 False>>><1 4 4>b <4 False False>>><None None None>')
|
||||
self.assertAccessEvents(p, 'config', 'themes/test/2')
|
||||
self.assertAccessEvents(p, 'config', 'themes/test/2', 'themes/other', 'check:themes/test/__main__')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
self.assertEqual(p.renderer.local_themes, None)
|
||||
|
@ -185,7 +205,7 @@ class TestConfigReload(TestCase):
|
|||
def test_reload_unexistent(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
|
||||
add_watcher_events(p, 'config')
|
||||
|
@ -222,7 +242,7 @@ class TestConfigReload(TestCase):
|
|||
def test_reload_colors(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['colors']['colors']['col1'] = 5
|
||||
add_watcher_events(p, 'colors')
|
||||
|
@ -234,7 +254,7 @@ class TestConfigReload(TestCase):
|
|||
def test_reload_colorscheme(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
|
||||
add_watcher_events(p, 'colorschemes/test/default')
|
||||
|
@ -246,12 +266,24 @@ class TestConfigReload(TestCase):
|
|||
def test_reload_theme(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default')
|
||||
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents(p, 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
@with_new_config
|
||||
def test_reload_top_theme(self, config):
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['themes/powerline']['dividers']['left']['hard'] = '|>'
|
||||
add_watcher_events(p, 'themes/powerline')
|
||||
self.assertEqual(p.render(), '<1 2 1> s<2 4 False>|><3 4 4>g<4 False False>|><None None None>')
|
||||
self.assertAccessEvents(p, 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
@with_new_config
|
||||
|
@ -259,12 +291,12 @@ class TestConfigReload(TestCase):
|
|||
config['config']['common']['interval'] = None
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
||||
self.assertEqual(p.render(), '<1 2 1> col3<2 4 False>>><3 4 4>g<4 False False>>><None None None>')
|
||||
self.assertAccessEvents(p, 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
self.assertTrue(p._watcher._calls)
|
||||
|
||||
|
@ -273,7 +305,7 @@ class TestConfigReload(TestCase):
|
|||
config['config']['common']['interval'] = None
|
||||
with get_powerline(config, 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(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default')
|
||||
self.assertAccessEvents(p, 'config', 'colors', 'check:colorschemes/default', 'check:colorschemes/test/__main__', 'colorschemes/test/default', 'themes/test/default', 'themes/powerline', 'check:themes/test/__main__')
|
||||
|
||||
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
||||
|
|
|
@ -22,17 +22,6 @@ def highlighted_string(s, group, **kwargs):
|
|||
config = {
|
||||
'config': {
|
||||
'common': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
'soft': '>',
|
||||
},
|
||||
'right': {
|
||||
'hard': '<<',
|
||||
'soft': '<',
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
'interval': 0,
|
||||
'watcher': 'test',
|
||||
},
|
||||
|
@ -104,6 +93,26 @@ config = {
|
|||
],
|
||||
},
|
||||
},
|
||||
'themes/powerline': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
'soft': '>',
|
||||
},
|
||||
'right': {
|
||||
'hard': '<<',
|
||||
'soft': '<',
|
||||
},
|
||||
},
|
||||
'spaces': 0,
|
||||
},
|
||||
'themes/test/__main__': {
|
||||
'dividers': {
|
||||
'right': {
|
||||
'soft': '|',
|
||||
},
|
||||
},
|
||||
},
|
||||
'themes/vim/default': {
|
||||
'default_module': 'powerline.segments.common',
|
||||
'segments': {
|
||||
|
@ -147,9 +156,9 @@ class TestRender(TestCase):
|
|||
class TestLines(TestRender):
|
||||
@add_args
|
||||
def test_without_above(self, p, config):
|
||||
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}<{344}f {--}')
|
||||
self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344}f {--}', width=10)
|
||||
# self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344} f {--}', width=11)
|
||||
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}|{344}f {--}')
|
||||
self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}|{344}f {--}', width=10)
|
||||
# self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}|{344} f {--}', width=11)
|
||||
self.assertEqual(list(p.render_above_lines()), [])
|
||||
|
||||
@with_new_config
|
||||
|
@ -158,21 +167,21 @@ class TestLines(TestRender):
|
|||
config['themes/test/default']['segments']['above'] = [old_segments]
|
||||
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
||||
self.assertRenderLinesEqual(p, [
|
||||
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s{24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
])
|
||||
self.assertRenderLinesEqual(p, [
|
||||
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s {24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
], width=10)
|
||||
|
||||
config['themes/test/default']['segments']['above'] = [old_segments] * 2
|
||||
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
||||
self.assertRenderLinesEqual(p, [
|
||||
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s{24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
'{121} s{24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
])
|
||||
self.assertRenderLinesEqual(p, [
|
||||
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||
'{121} s {24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
'{121} s {24}>>{344}g{34}>{34}|{344}f {--}',
|
||||
], width=10)
|
||||
|
||||
|
||||
|
@ -299,6 +308,82 @@ class TestColorschemesHierarchy(TestRender):
|
|||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
|
||||
class TestThemeHierarchy(TestRender):
|
||||
@add_args
|
||||
def test_hierarchy(self, p, config):
|
||||
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}|{344}f {--}')
|
||||
|
||||
@add_args
|
||||
def test_no_main(self, p, config):
|
||||
del config['themes/test/__main__']
|
||||
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}<{344}f {--}')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
@add_args
|
||||
def test_no_powerline(self, p, config):
|
||||
config['themes/test/__main__']['dividers'] = config['themes/powerline']['dividers']
|
||||
config['themes/test/__main__']['spaces'] = 1
|
||||
del config['themes/powerline']
|
||||
self.assertRenderEqual(p, '{121} s {24}>>{344}g {34}>{34}<{344} f {--}')
|
||||
self.assertEqual(p.logger._pop_msgs(), [])
|
||||
|
||||
@add_args
|
||||
def test_no_default(self, p, config):
|
||||
del config['themes/test/default']
|
||||
self.assertRenderEqual(p, 'themes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load theme: themes/test/default',
|
||||
'exception:test:powerline:Failed to create renderer: themes/test/default',
|
||||
'exception:test:powerline:Failed to render: themes/test/default',
|
||||
])
|
||||
|
||||
@add_args
|
||||
def test_only_default(self, p, config):
|
||||
config['themes/test/default']['dividers'] = config['themes/powerline']['dividers']
|
||||
config['themes/test/default']['spaces'] = 1
|
||||
del config['themes/test/__main__']
|
||||
del config['themes/powerline']
|
||||
self.assertRenderEqual(p, '{121} s {24}>>{344}g {34}>{34}<{344} f {--}')
|
||||
|
||||
@add_args
|
||||
def test_only_main(self, p, config):
|
||||
del config['themes/test/default']
|
||||
del config['themes/powerline']
|
||||
self.assertRenderEqual(p, 'themes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load theme: themes/powerline',
|
||||
'exception:test:powerline:Failed to load theme: themes/test/default',
|
||||
'exception:test:powerline:Failed to create renderer: themes/test/default',
|
||||
'exception:test:powerline:Failed to render: themes/test/default',
|
||||
])
|
||||
|
||||
@add_args
|
||||
def test_only_powerline(self, p, config):
|
||||
del config['themes/test/default']
|
||||
del config['themes/test/__main__']
|
||||
self.assertRenderEqual(p, 'themes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load theme: themes/test/__main__',
|
||||
'exception:test:powerline:Failed to load theme: themes/test/default',
|
||||
'exception:test:powerline:Failed to create renderer: themes/test/default',
|
||||
'exception:test:powerline:Failed to render: themes/test/default',
|
||||
])
|
||||
|
||||
@add_args
|
||||
def test_nothing(self, p, config):
|
||||
del config['themes/test/default']
|
||||
del config['themes/powerline']
|
||||
del config['themes/test/__main__']
|
||||
self.assertRenderEqual(p, 'themes/test/default')
|
||||
self.assertEqual(p.logger._pop_msgs(), [
|
||||
'exception:test:powerline:Failed to load theme: themes/powerline',
|
||||
'exception:test:powerline:Failed to load theme: themes/test/__main__',
|
||||
'exception:test:powerline:Failed to load theme: themes/test/default',
|
||||
'exception:test:powerline:Failed to create renderer: themes/test/default',
|
||||
'exception:test:powerline:Failed to render: themes/test/default',
|
||||
])
|
||||
|
||||
|
||||
class TestVim(TestCase):
|
||||
def test_environ_update(self):
|
||||
# Regression test: test that segment obtains environment from vim, not
|
||||
|
|
Loading…
Reference in New Issue