Merge pull request #958 from ZyX-I/theme-hierarchy
Implement theme hierarchy
This commit is contained in:
commit
22fdc10534
|
@ -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,28 @@ 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>`. Powerline ships
|
||||
with the following top themes:
|
||||
|
||||
========================== ====================================================
|
||||
Theme Description
|
||||
========================== ====================================================
|
||||
powerline Default powerline theme with fancy powerline symbols
|
||||
unicode Theme without any symbols from private use area
|
||||
unicode_terminus Theme containing only symbols from terminus PCF font
|
||||
unicode_terminus_condensed Like above, but occupies as less space as possible
|
||||
ascii Theme without any unicode characters at all
|
||||
========================== ====================================================
|
||||
|
||||
``name``
|
||||
Name of the theme.
|
||||
|
@ -223,23 +247,45 @@ 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``
|
||||
A dict where keys are segment names or strings ``{module}.{name}``. Used to
|
||||
specify default values for various keys:
|
||||
:ref:`after <config-themes-seg-after>`,
|
||||
:ref:`args <config-themes-seg-args>` (only for function segments),
|
||||
:ref:`before <config-themes-seg-before>`,
|
||||
:ref:`contents <config-themes-seg-contents>` (only for string segments
|
||||
if :ref:`name <config-themes-seg-name>` is defined),
|
||||
:ref:`display <config-themes-seg-display>`.
|
||||
|
||||
Key :ref:`args <config-themes-seg-args>` (only for function and
|
||||
segments_list segments) is handled specially: unlike other values it is
|
||||
merged with all other values, except that a single ``{module}.{name}`` key
|
||||
if found prevents merging all ``{name}`` values.
|
||||
|
||||
When using :ref:`local themes <config-ext-local_themes>` values of these
|
||||
keys are first searched in the segment description, then in ``segment_data``
|
||||
key of a local theme, then in ``segment_data`` key of a :ref:`default theme
|
||||
<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.
|
||||
|
@ -259,8 +305,8 @@ Themes
|
|||
Each segment dictionary has the following options:
|
||||
|
||||
``type``
|
||||
The segment type. Can be one of ``function`` (default), ``string``
|
||||
or ``filler``:
|
||||
The segment type. Can be one of ``function`` (default), ``string``,
|
||||
``filler`` or ``segments_list``:
|
||||
|
||||
``function``
|
||||
The segment contents is the return value of the function defined
|
||||
|
@ -367,11 +413,12 @@ Themes
|
|||
*not* included in any modes, *except* for the modes in this list.
|
||||
|
||||
``display``
|
||||
|
||||
.. _config-themes-seg-display:
|
||||
|
||||
Boolean. If false disables displaying of the segment.
|
||||
Defaults to ``True``.
|
||||
|
||||
``segments``
|
||||
.. _config-themes-seg-segments:
|
||||
|
||||
A list of subsegments.
|
||||
|
|
|
@ -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,108 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": " ",
|
||||
"soft": "| "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ",
|
||||
"soft": " |"
|
||||
}
|
||||
},
|
||||
"spaces": 1,
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": "BR "
|
||||
},
|
||||
|
||||
"line_current_symbol": {
|
||||
"contents": "LN "
|
||||
},
|
||||
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"ellipsis": "..."
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.network_load": {
|
||||
"args": {
|
||||
"recv_format": "DL {value:>8}",
|
||||
"sent_format": "UL {value:>8}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.now_playing": {
|
||||
"args": {
|
||||
"state_symbols": {
|
||||
"fallback": "",
|
||||
"play": ">",
|
||||
"pause": "~",
|
||||
"stop": "X"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.battery": {
|
||||
"args": {
|
||||
"full_heart": "O",
|
||||
"empty_heart": "O"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.uptime": {
|
||||
"before": "UP "
|
||||
},
|
||||
"powerline.segments.common.date": {
|
||||
"before": ""
|
||||
},
|
||||
"powerline.segments.common.email_imap_alert": {
|
||||
"before": "MAIL "
|
||||
},
|
||||
"powerline.segments.common.virtualenv": {
|
||||
"before": "(e) "
|
||||
},
|
||||
"powerline.segments.common.hostname": {
|
||||
"before": "H "
|
||||
},
|
||||
|
||||
"powerline.segments.vim.mode": {
|
||||
"args": {
|
||||
"override": {
|
||||
"n": "NORMAL",
|
||||
"no": "N-OPER",
|
||||
"v": "VISUAL",
|
||||
"V": "V-LINE",
|
||||
"^V": "V-BLCK",
|
||||
"s": "SELECT",
|
||||
"S": "S-LINE",
|
||||
"^S": "S-BLCK",
|
||||
"i": "INSERT",
|
||||
"R": "REPLACE",
|
||||
"Rv": "V-RPLCE",
|
||||
"c": "COMMND",
|
||||
"cv": "VIM EX",
|
||||
"ce": "EX",
|
||||
"r": "PROMPT",
|
||||
"rm": "MORE",
|
||||
"r?": "CONFIRM",
|
||||
"!": "SHELL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.visual_range": {
|
||||
"args": {
|
||||
"CTRL_V_text": "{rows} x {vcols}",
|
||||
"v_text_oneline": "C:{vcols}",
|
||||
"v_text_multiline": "L:{rows}",
|
||||
"V_text": "L:{rows}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.readonly_indicator": {
|
||||
"args": {
|
||||
"text": "RO"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.modified_indicator": {
|
||||
"args": {
|
||||
"text": "+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
}
|
||||
},
|
||||
"spaces": 1,
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": " "
|
||||
},
|
||||
|
||||
"line_current_symbol": {
|
||||
"contents": " "
|
||||
},
|
||||
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"ellipsis": "⋯"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.network_load": {
|
||||
"args": {
|
||||
"recv_format": "⬇ {value:>8}",
|
||||
"sent_format": "⬆ {value:>8}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.now_playing": {
|
||||
"args": {
|
||||
"state_symbols": {
|
||||
"fallback": "♫",
|
||||
"play": "▶",
|
||||
"pause": "▮▮",
|
||||
"stop": "■"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.battery": {
|
||||
"args": {
|
||||
"full_heart": "♥",
|
||||
"empty_heart": "♥"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.uptime": {
|
||||
"before": "⇑ "
|
||||
},
|
||||
"powerline.segments.common.date": {
|
||||
"before": "⌚ "
|
||||
},
|
||||
"powerline.segments.common.email_imap_alert": {
|
||||
"before": "✉ "
|
||||
},
|
||||
"powerline.segments.common.virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"powerline.segments.common.hostname": {
|
||||
"before": " "
|
||||
},
|
||||
|
||||
"powerline.segments.vim.mode": {
|
||||
"args": {
|
||||
"override": {
|
||||
"n": "NORMAL",
|
||||
"no": "N·OPER",
|
||||
"v": "VISUAL",
|
||||
"V": "V·LINE",
|
||||
"^V": "V·BLCK",
|
||||
"s": "SELECT",
|
||||
"S": "S·LINE",
|
||||
"^S": "S·BLCK",
|
||||
"i": "INSERT",
|
||||
"R": "REPLACE",
|
||||
"Rv": "V·RPLCE",
|
||||
"c": "COMMND",
|
||||
"cv": "VIM EX",
|
||||
"ce": "EX",
|
||||
"r": "PROMPT",
|
||||
"rm": "MORE",
|
||||
"r?": "CONFIRM",
|
||||
"!": "SHELL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.visual_range": {
|
||||
"args": {
|
||||
"CTRL_V_text": "{rows} × {vcols}",
|
||||
"v_text_oneline": "C:{vcols}",
|
||||
"v_text_multiline": "L:{rows}",
|
||||
"V_text": "L:{rows}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.readonly_indicator": {
|
||||
"args": {
|
||||
"text": ""
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.modified_indicator": {
|
||||
"args": {
|
||||
"text": "+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"dir_limit_depth": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,5 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
|
@ -30,10 +16,7 @@
|
|||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"args": {
|
||||
"dir_limit_depth": 3
|
||||
}
|
||||
"name": "cwd"
|
||||
},
|
||||
{
|
||||
"module": "powerline.segments.shell",
|
||||
|
|
|
@ -1,19 +1,5 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
|
@ -29,10 +15,7 @@
|
|||
"name": "branch"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"args": {
|
||||
"dir_limit_depth": 3
|
||||
}
|
||||
"name": "cwd"
|
||||
},
|
||||
{
|
||||
"module": "powerline.segments.shell",
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"uptime": {
|
||||
"before": "⇑ "
|
||||
},
|
||||
"date": {
|
||||
"before": "⌚ "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"right": [
|
||||
{
|
||||
|
@ -19,7 +11,8 @@
|
|||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "date"
|
||||
"name": "date",
|
||||
"before": ""
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": "▌ ",
|
||||
"soft": "│ "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ▐",
|
||||
"soft": " │"
|
||||
}
|
||||
},
|
||||
"spaces": 1,
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": "⎇ "
|
||||
},
|
||||
|
||||
"line_current_symbol": {
|
||||
"contents": " "
|
||||
},
|
||||
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"ellipsis": "⋯"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.network_load": {
|
||||
"args": {
|
||||
"recv_format": "⬇ {value:>8}",
|
||||
"sent_format": "⬆ {value:>8}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.now_playing": {
|
||||
"args": {
|
||||
"state_symbols": {
|
||||
"fallback": "♫",
|
||||
"play": "▶",
|
||||
"pause": "▮▮",
|
||||
"stop": "■"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.battery": {
|
||||
"args": {
|
||||
"full_heart": "♥",
|
||||
"empty_heart": "♥"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.uptime": {
|
||||
"before": "⇑ "
|
||||
},
|
||||
"powerline.segments.common.date": {
|
||||
"before": "⌚ "
|
||||
},
|
||||
"powerline.segments.common.email_imap_alert": {
|
||||
"before": "✉ "
|
||||
},
|
||||
"powerline.segments.common.virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"powerline.segments.common.hostname": {
|
||||
"before": "⌂ "
|
||||
},
|
||||
|
||||
"powerline.segments.vim.mode": {
|
||||
"args": {
|
||||
"override": {
|
||||
"n": "NORMAL",
|
||||
"no": "N·OPER",
|
||||
"v": "VISUAL",
|
||||
"V": "V·LINE",
|
||||
"^V": "V·BLCK",
|
||||
"s": "SELECT",
|
||||
"S": "S·LINE",
|
||||
"^S": "S·BLCK",
|
||||
"i": "INSERT",
|
||||
"R": "REPLACE",
|
||||
"Rv": "V·RPLCE",
|
||||
"c": "COMMND",
|
||||
"cv": "VIM EX",
|
||||
"ce": "EX",
|
||||
"r": "PROMPT",
|
||||
"rm": "MORE",
|
||||
"r?": "CONFIRM",
|
||||
"!": "SHELL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.visual_range": {
|
||||
"args": {
|
||||
"CTRL_V_text": "{rows} × {vcols}",
|
||||
"v_text_oneline": "C:{vcols}",
|
||||
"v_text_multiline": "L:{rows}",
|
||||
"V_text": "L:{rows}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.readonly_indicator": {
|
||||
"args": {
|
||||
"text": "⊗"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.modified_indicator": {
|
||||
"args": {
|
||||
"text": "+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": "▌ ",
|
||||
"soft": "│ "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ▐",
|
||||
"soft": " │"
|
||||
}
|
||||
},
|
||||
"spaces": 1,
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": "BR "
|
||||
},
|
||||
|
||||
"line_current_symbol": {
|
||||
"contents": " "
|
||||
},
|
||||
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"ellipsis": "…"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.network_load": {
|
||||
"args": {
|
||||
"recv_format": "⇓ {value:>8}",
|
||||
"sent_format": "⇑ {value:>8}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.now_playing": {
|
||||
"args": {
|
||||
"state_symbols": {
|
||||
"fallback": "♫",
|
||||
"play": "▶",
|
||||
"pause": "▮▮",
|
||||
"stop": "■"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.battery": {
|
||||
"args": {
|
||||
"full_heart": "♥",
|
||||
"empty_heart": "♥"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.uptime": {
|
||||
"before": "↑ "
|
||||
},
|
||||
"powerline.segments.common.date": {
|
||||
"before": ""
|
||||
},
|
||||
"powerline.segments.common.email_imap_alert": {
|
||||
"before": "MAIL "
|
||||
},
|
||||
"powerline.segments.common.virtualenv": {
|
||||
"before": "(e) "
|
||||
},
|
||||
"powerline.segments.common.hostname": {
|
||||
"before": "⌂ "
|
||||
},
|
||||
|
||||
"powerline.segments.vim.mode": {
|
||||
"args": {
|
||||
"override": {
|
||||
"n": "NORMAL",
|
||||
"no": "N·OPER",
|
||||
"v": "VISUAL",
|
||||
"V": "V·LINE",
|
||||
"^V": "V·BLCK",
|
||||
"s": "SELECT",
|
||||
"S": "S·LINE",
|
||||
"^S": "S·BLCK",
|
||||
"i": "INSERT",
|
||||
"R": "REPLACE",
|
||||
"Rv": "V·RPLCE",
|
||||
"c": "COMMND",
|
||||
"cv": "VIM EX",
|
||||
"ce": "EX",
|
||||
"r": "PROMPT",
|
||||
"rm": "MORE",
|
||||
"r?": "CONFIRM",
|
||||
"!": "SHELL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.visual_range": {
|
||||
"args": {
|
||||
"CTRL_V_text": "{rows} × {vcols}",
|
||||
"v_text_oneline": "C:{vcols}",
|
||||
"v_text_multiline": "L:{rows}",
|
||||
"V_text": "L:{rows}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.readonly_indicator": {
|
||||
"args": {
|
||||
"text": "RO"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.modified_indicator": {
|
||||
"args": {
|
||||
"text": "+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": "▌",
|
||||
"soft": "│"
|
||||
},
|
||||
"right": {
|
||||
"hard": "▐",
|
||||
"soft": "│"
|
||||
}
|
||||
},
|
||||
"spaces": 0,
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": "B "
|
||||
},
|
||||
|
||||
"line_current_symbol": {
|
||||
"contents": ""
|
||||
},
|
||||
|
||||
"powerline.segments.common.cwd": {
|
||||
"args": {
|
||||
"use_path_separator": true,
|
||||
"ellipsis": "…"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.network_load": {
|
||||
"args": {
|
||||
"recv_format": "⇓{value:>8}",
|
||||
"sent_format": "⇑{value:>8}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.now_playing": {
|
||||
"args": {
|
||||
"state_symbols": {
|
||||
"fallback": "♫",
|
||||
"play": "▶",
|
||||
"pause": "▮▮",
|
||||
"stop": "■"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.battery": {
|
||||
"args": {
|
||||
"full_heart": "♥",
|
||||
"empty_heart": "♥"
|
||||
}
|
||||
},
|
||||
"powerline.segments.common.uptime": {
|
||||
"before": "↑"
|
||||
},
|
||||
"powerline.segments.common.date": {
|
||||
"before": ""
|
||||
},
|
||||
"powerline.segments.common.email_imap_alert": {
|
||||
"before": "M "
|
||||
},
|
||||
"powerline.segments.common.virtualenv": {
|
||||
"before": "E "
|
||||
},
|
||||
"powerline.segments.common.hostname": {
|
||||
"before": "⌂"
|
||||
},
|
||||
|
||||
"powerline.segments.vim.mode": {
|
||||
"args": {
|
||||
"override": {
|
||||
"n": "NML",
|
||||
"no": "NOP",
|
||||
"v": "VIS",
|
||||
"V": "VLN",
|
||||
"^V": "VBL",
|
||||
"s": "SEL",
|
||||
"S": "SLN",
|
||||
"^S": "SBL",
|
||||
"i": "INS",
|
||||
"R": "REP",
|
||||
"Rv": "VRP",
|
||||
"c": "CMD",
|
||||
"cv": "VEX",
|
||||
"ce": " EX",
|
||||
"r": "PRT",
|
||||
"rm": "MOR",
|
||||
"r?": "CON",
|
||||
"!": " SH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.visual_range": {
|
||||
"args": {
|
||||
"CTRL_V_text": "{rows}×{vcols}",
|
||||
"v_text_oneline": "C:{vcols}",
|
||||
"v_text_multiline": "L:{rows}",
|
||||
"V_text": "L:{rows}"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.readonly_indicator": {
|
||||
"args": {
|
||||
"text": "RO"
|
||||
}
|
||||
},
|
||||
"powerline.segments.vim.modified_indicator": {
|
||||
"args": {
|
||||
"text": "+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"segment_data": {
|
||||
"line_percent": {
|
||||
"args": {
|
||||
"gradient": true
|
||||
},
|
||||
"after": "%"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,4 @@
|
|||
{
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": " "
|
||||
},
|
||||
"modified_indicator": {
|
||||
"args": { "text": "+" }
|
||||
},
|
||||
"line_percent": {
|
||||
"args": { "gradient": true },
|
||||
"after": "%"
|
||||
},
|
||||
"line_current_symbol": {
|
||||
"contents": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
|
|
|
@ -7,19 +7,18 @@
|
|||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "date"
|
||||
"name": "date",
|
||||
"before": ""
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
"args": {
|
||||
"format": "%H:%M",
|
||||
"istime": true
|
||||
},
|
||||
"before": "⌚ "
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "email_imap_alert",
|
||||
"before": "✉ ",
|
||||
"priority": 10,
|
||||
"args": {
|
||||
"username": "",
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
|
||||
from threading import Thread, Lock, Event
|
||||
from types import MethodType
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
from powerline.segments import Segment
|
||||
|
||||
|
||||
class MultiRunnedThread(object):
|
||||
|
@ -28,12 +30,14 @@ class MultiRunnedThread(object):
|
|||
return None
|
||||
|
||||
|
||||
class ThreadedSegment(MultiRunnedThread):
|
||||
class ThreadedSegment(Segment, MultiRunnedThread):
|
||||
min_sleep_time = 0.1
|
||||
update_first = True
|
||||
interval = 1
|
||||
daemon = False
|
||||
|
||||
argmethods = ('render', 'set_state')
|
||||
|
||||
def __init__(self):
|
||||
super(ThreadedSegment, self).__init__()
|
||||
self.run_once = True
|
||||
|
@ -145,10 +149,34 @@ class ThreadedSegment(MultiRunnedThread):
|
|||
def debug(self, *args, **kwargs):
|
||||
self.pl.debug(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def argspecobjs(self):
|
||||
for name in self.argmethods:
|
||||
try:
|
||||
yield name, getattr(self, name)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def additional_args(self):
|
||||
return (('interval', self.interval),)
|
||||
|
||||
def omitted_args(self, name, method):
|
||||
if isinstance(getattr(self, name, None), MethodType):
|
||||
omitted_indexes = (0,)
|
||||
else:
|
||||
omitted_indexes = ()
|
||||
if name.startswith('render'):
|
||||
if omitted_indexes:
|
||||
omitted_indexes += (1,)
|
||||
else:
|
||||
omitted_indexes = (0,)
|
||||
return omitted_indexes
|
||||
|
||||
|
||||
class KwThreadedSegment(ThreadedSegment):
|
||||
update_first = True
|
||||
|
||||
argmethods = ('render', 'set_state', 'key', 'render_one')
|
||||
|
||||
def __init__(self):
|
||||
super(KwThreadedSegment, self).__init__()
|
||||
self.updated = True
|
||||
|
|
|
@ -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,30 +1071,45 @@ 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:
|
||||
for segments in theme.get('segments', {}).values():
|
||||
|
||||
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():
|
||||
for segment in segments:
|
||||
if 'name' in segment:
|
||||
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
|
||||
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext))
|
||||
if key == unicode(module) + '.' + unicode(segment['name']):
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
break
|
||||
if found:
|
||||
break
|
||||
else:
|
||||
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)
|
||||
|
@ -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(),
|
||||
segment_data=Spec().unknown_spec(
|
||||
Spec().func(check_segment_data_key),
|
||||
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_segments, *args, **kwargs)),
|
||||
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),
|
||||
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,12 +1374,17 @@ 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]
|
||||
configs['top_' + typ][name] = path
|
||||
|
||||
diff = set(configs['themes']) ^ set(configs['colorschemes'])
|
||||
diff = set(configs['colorschemes']) - set(configs['themes'])
|
||||
if diff:
|
||||
hadproblem = True
|
||||
for ext in diff:
|
||||
|
@ -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
|
||||
|
|
|
@ -1,62 +1,63 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
|
||||
from inspect import ArgSpec, getargspec
|
||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||
from itertools import count
|
||||
|
||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||
from powerline.segments import Segment
|
||||
|
||||
|
||||
def getconfigargspec(obj):
|
||||
if isinstance(obj, ThreadedSegment):
|
||||
args = ['interval']
|
||||
defaults = [getattr(obj, 'interval', 1)]
|
||||
if obj.update_first:
|
||||
args.append('update_first')
|
||||
defaults.append(True)
|
||||
methods = ['render', 'set_state']
|
||||
if isinstance(obj, KwThreadedSegment):
|
||||
methods += ['key', 'render_one']
|
||||
|
||||
for method in methods:
|
||||
if hasattr(obj, method):
|
||||
# Note: on <python-2.6 it may return simple tuple, not
|
||||
# ArgSpec instance.
|
||||
argspec = getargspec(getattr(obj, method))
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
if (arg == 'self' or
|
||||
(arg == 'segment_info' and
|
||||
getattr(obj, 'powerline_requires_segment_info', None)) or
|
||||
(arg == 'create_watcher' and
|
||||
getattr(obj, 'powerline_requires_filesystem_watcher', None)) or
|
||||
(arg == 'pl') or
|
||||
(method.startswith('render') and (1 if argspec.args[0] == 'self' else 0) + i == len(argspec.args)) or
|
||||
arg in args):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||
else:
|
||||
if hasattr(obj, 'powerline_origin'):
|
||||
obj = obj.powerline_origin
|
||||
else:
|
||||
obj = obj
|
||||
|
||||
argspec = getargspec(obj)
|
||||
args = []
|
||||
defaults = []
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
if ((arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None)) or
|
||||
arg == 'pl'):
|
||||
|
||||
if isinstance(obj, Segment):
|
||||
additional_args = obj.additional_args()
|
||||
argspecobjs = obj.argspecobjs()
|
||||
get_omitted_args = obj.omitted_args
|
||||
else:
|
||||
additional_args = ()
|
||||
argspecobjs = ((None, obj),)
|
||||
get_omitted_args = lambda *args: ()
|
||||
|
||||
for arg in additional_args:
|
||||
args.append(arg[0])
|
||||
if len(arg) > 1:
|
||||
defaults.append(arg[1])
|
||||
|
||||
requires_segment_info = getattr(obj, 'powerline_requires_segment_info', False)
|
||||
requires_filesystem_watcher = getattr(obj, 'powerline_requires_filesystem_watcher', False)
|
||||
|
||||
for name, method in argspecobjs:
|
||||
argspec = getargspec(method)
|
||||
omitted_args = get_omitted_args(name, method)
|
||||
largs = len(argspec.args)
|
||||
for i, arg in enumerate(reversed(argspec.args)):
|
||||
if (
|
||||
largs - (i + 1) in omitted_args
|
||||
or arg == 'pl'
|
||||
or (arg == 'create_watcher' and requires_filesystem_watcher)
|
||||
or (arg == 'segment_info' and requires_segment_info)
|
||||
):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
if argspec.defaults and len(argspec.defaults) > i:
|
||||
if arg in args:
|
||||
idx = args.index(arg)
|
||||
if len(args) - idx > len(defaults):
|
||||
args.pop(idx)
|
||||
else:
|
||||
continue
|
||||
default = argspec.defaults[-(i + 1)]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
if arg not in args:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))
|
||||
|
||||
return argspec
|
||||
return ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||
|
|
|
@ -1,25 +1,57 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||
|
||||
from powerline.lib.file_watcher import create_file_watcher
|
||||
import sys
|
||||
|
||||
from powerline.lib.file_watcher import create_file_watcher
|
||||
|
||||
def get_segment_key(segment, theme_configs, key, module=None, default=None):
|
||||
|
||||
def list_segment_key_values(segment, theme_configs, key, module=None, default=None):
|
||||
try:
|
||||
return segment[key]
|
||||
except KeyError:
|
||||
if 'name' in segment:
|
||||
name = segment['name']
|
||||
for theme_config in theme_configs:
|
||||
if 'segment_data' in theme_config:
|
||||
for segment_key in ((module + '.' + name, name) if module else (name,)):
|
||||
try:
|
||||
return theme_config['segment_data'][segment_key][key]
|
||||
yield segment[key]
|
||||
except KeyError:
|
||||
pass
|
||||
return default
|
||||
try:
|
||||
name = segment['name']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
found_module_key = False
|
||||
for theme_config in theme_configs:
|
||||
try:
|
||||
segment_data = theme_config['segment_data']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if module:
|
||||
try:
|
||||
yield segment_data[module + '.' + name][key]
|
||||
found_module_key = True
|
||||
except KeyError:
|
||||
pass
|
||||
if not found_module_key:
|
||||
try:
|
||||
yield segment_data[name][key]
|
||||
except KeyError:
|
||||
pass
|
||||
yield default
|
||||
|
||||
|
||||
def get_segment_key(merge, *args, **kwargs):
|
||||
if merge:
|
||||
ret = None
|
||||
for value in list_segment_key_values(*args, **kwargs):
|
||||
if ret is None:
|
||||
ret = value
|
||||
elif isinstance(ret, dict) and isinstance(value, dict):
|
||||
old_ret = ret
|
||||
ret = value.copy()
|
||||
ret.update(old_ret)
|
||||
else:
|
||||
return ret
|
||||
return ret
|
||||
else:
|
||||
return next(list_segment_key_values(*args, **kwargs))
|
||||
|
||||
|
||||
def get_function(data, segment):
|
||||
|
@ -33,7 +65,7 @@ def get_function(data, segment):
|
|||
|
||||
|
||||
def get_string(data, segment):
|
||||
return data['get_key'](segment, None, 'contents'), None, None
|
||||
return data['get_key'](False, segment, None, 'contents'), None, None
|
||||
|
||||
|
||||
def get_filler(data, segment):
|
||||
|
@ -129,8 +161,8 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||
'path': common_config['paths'],
|
||||
}
|
||||
|
||||
def get_key(segment, module, key, default=None):
|
||||
return get_segment_key(segment, theme_configs, key, module, default)
|
||||
def get_key(merge, segment, module, key, default=None):
|
||||
return get_segment_key(merge, segment, theme_configs, key, module, default)
|
||||
data['get_key'] = get_key
|
||||
|
||||
def get(segment, side):
|
||||
|
@ -146,7 +178,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||
pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator')
|
||||
return None
|
||||
|
||||
if not get_key(segment, module, 'display', True):
|
||||
if not get_key(False, segment, module, 'display', True):
|
||||
return None
|
||||
|
||||
if segment_type == 'function':
|
||||
|
@ -155,7 +187,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||
highlight_group = segment.get('highlight_group') or segment.get('name')
|
||||
|
||||
if segment_type in ('function', 'segment_list'):
|
||||
args = dict(((str(k), v) for k, v in get_key(segment, module, 'args', {}).items()))
|
||||
args = dict(((str(k), v) for k, v in get_key(True, segment, module, 'args', {}).items()))
|
||||
|
||||
if segment_type == 'segment_list':
|
||||
# Handle startup and shutdown of _contents_func?
|
||||
|
@ -219,8 +251,8 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||
'type': segment_type,
|
||||
'highlight_group': highlight_group,
|
||||
'divider_highlight_group': None,
|
||||
'before': get_key(segment, module, 'before', ''),
|
||||
'after': get_key(segment, module, 'after', ''),
|
||||
'before': get_key(False, segment, module, 'before', ''),
|
||||
'after': get_key(False, segment, module, 'after', ''),
|
||||
'contents_func': contents_func,
|
||||
'contents': contents,
|
||||
'priority': segment.get('priority', None),
|
||||
|
|
|
@ -1,2 +1,51 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
|
||||
from pkgutil import extend_path
|
||||
from types import MethodType
|
||||
|
||||
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
|
||||
class Segment(object):
|
||||
'''Base class for any segment that is not a function
|
||||
|
||||
Required for powerline.lint.inspect to work properly.
|
||||
'''
|
||||
if sys.version_info < (3, 4):
|
||||
def argspecobjs(self):
|
||||
yield '__call__', self.__call__
|
||||
else:
|
||||
def argspecobjs(self): # NOQA
|
||||
yield '__call__', self
|
||||
|
||||
argspecobjs.__doc__ = (
|
||||
'''Return a list of valid arguments for inspect.getargspec
|
||||
|
||||
Used to determine function arguments.
|
||||
'''
|
||||
)
|
||||
|
||||
def omitted_args(self, name, method):
|
||||
'''List arguments which should be omitted
|
||||
|
||||
Returns a tuple with indexes of omitted arguments.
|
||||
|
||||
.. note::``segment_info``, ``create_watcher`` and ``pl`` will be omitted
|
||||
regardless of the below return (for ``segment_info`` and
|
||||
``create_watcher``: only if object was marked to require segment
|
||||
info or filesystem watcher).
|
||||
'''
|
||||
if isinstance(self.__call__, MethodType):
|
||||
return (0,)
|
||||
else:
|
||||
return ()
|
||||
|
||||
@staticmethod
|
||||
def additional_args():
|
||||
'''Returns a list of (additional argument name[, default value]) tuples.
|
||||
'''
|
||||
return ()
|
||||
|
|
|
@ -19,6 +19,7 @@ from powerline.lib.monotonic import monotonic
|
|||
from powerline.lib.humanize_bytes import humanize_bytes
|
||||
from powerline.lib.unicode import u
|
||||
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
||||
from powerline.segments import Segment
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
|
@ -896,7 +897,6 @@ Highlight groups used: ``email_alert_gradient`` (gradient), ``email_alert``.
|
|||
''')
|
||||
|
||||
|
||||
class NowPlayingSegment(object):
|
||||
STATE_SYMBOLS = {
|
||||
'fallback': '♫',
|
||||
'play': '▶',
|
||||
|
@ -904,21 +904,23 @@ class NowPlayingSegment(object):
|
|||
'stop': '■',
|
||||
}
|
||||
|
||||
def __call__(self, player='mpd', format='{state_symbol} {artist} - {title} ({total})', **kwargs):
|
||||
|
||||
class NowPlayingSegment(Segment):
|
||||
def __call__(self, player='mpd', format='{state_symbol} {artist} - {title} ({total})', state_symbols=STATE_SYMBOLS, **kwargs):
|
||||
player_func = getattr(self, 'player_{0}'.format(player))
|
||||
stats = {
|
||||
'state': None,
|
||||
'state_symbol': self.STATE_SYMBOLS['fallback'],
|
||||
'state': 'fallback',
|
||||
'album': None,
|
||||
'artist': None,
|
||||
'title': None,
|
||||
'elapsed': None,
|
||||
'total': None,
|
||||
}
|
||||
func_stats = player_func(**kwargs)
|
||||
func_stats = player_func(state_symbol=state_symbols, **kwargs)
|
||||
if not func_stats:
|
||||
return None
|
||||
stats.update(func_stats)
|
||||
stats['state_symbol'] = state_symbols.get(stats['state'])
|
||||
return format.format(**stats)
|
||||
|
||||
@staticmethod
|
||||
|
@ -965,7 +967,6 @@ class NowPlayingSegment(object):
|
|||
state = self._convert_state(now_playing.get('status'))
|
||||
return {
|
||||
'state': state,
|
||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
||||
'album': now_playing.get('album'),
|
||||
'artist': now_playing.get('artist'),
|
||||
'title': now_playing.get('title'),
|
||||
|
@ -998,7 +999,6 @@ class NowPlayingSegment(object):
|
|||
client.disconnect()
|
||||
return {
|
||||
'state': status.get('state'),
|
||||
'state_symbol': self.STATE_SYMBOLS.get(status.get('state')),
|
||||
'album': now_playing.get('album'),
|
||||
'artist': now_playing.get('artist'),
|
||||
'title': now_playing.get('title'),
|
||||
|
@ -1027,7 +1027,6 @@ class NowPlayingSegment(object):
|
|||
state = self._convert_state(status)
|
||||
return {
|
||||
'state': state,
|
||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
||||
'album': info.get('xesam:album'),
|
||||
'artist': info.get('xesam:artist')[0],
|
||||
'title': info.get('xesam:title'),
|
||||
|
@ -1074,7 +1073,6 @@ class NowPlayingSegment(object):
|
|||
return None
|
||||
return {
|
||||
'state': state,
|
||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
||||
'album': spotify_status[1],
|
||||
'artist': spotify_status[2],
|
||||
'title': spotify_status[3],
|
||||
|
|
|
@ -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,38 +177,28 @@ 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': {
|
||||
'2/themes/powerline': {
|
||||
'spaces': 1,
|
||||
}
|
||||
},
|
||||
'3/config': {
|
||||
'common': {
|
||||
'3/themes/powerline': {
|
||||
'dividers': {
|
||||
'left': {
|
||||
'hard': '>>',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
})) as p:
|
||||
self.assertRenderEqual(p, '{12} bt {2-}>>{--}')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/vim -S
|
||||
let g:powerline_config_path = expand('<sfile>:p:h:h') . '/powerline/config_files'
|
||||
let g:powerline_config_overrides = {'common': {'dividers': {'left': {'hard': ' ', 'soft': ' > '}, 'right': {'hard': ' ', 'soft': ' < '}}}}
|
||||
let g:powerline_config_overrides = {'common': {'default_top_theme': 'ascii'}}
|
||||
let g:powerline_theme_overrides__default = {'segment_data': {'line_current_symbol': {'contents': 'LN '}, 'branch': {'before': 'B '}}}
|
||||
try
|
||||
python import powerline.vim
|
||||
|
|
|
@ -13,7 +13,7 @@ catch
|
|||
endtry
|
||||
|
||||
if result isnot# '%#Pl_240_5789784_235_2500134_NONE# 1 %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#abc %#Pl_244_8421504_235_2500134_NONE# %#Pl_240_5789784_235_2500134_NONE#2 %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#def %#Pl_235_2500134_240_5789784_NONE# %#Pl_250_12369084_240_5789784_NONE#./%#Pl_231_16777215_240_5789784_bold#ghi %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE# %#Pl_252_13684944_236_3158064_NONE# %#Pl_235_2500134_252_13684944_bold# Tabs '
|
||||
call writefile(['Unexpected result', result], 'message.fail')
|
||||
call writefile(['Unexpected tabline', result], 'message.fail')
|
||||
cquit
|
||||
endif
|
||||
|
||||
|
@ -27,7 +27,7 @@ catch
|
|||
endtry
|
||||
|
||||
if result isnot# '%#Pl_240_5789784_235_2500134_NONE# ./%#Pl_244_8421504_235_2500134_bold#abc %#Pl_244_8421504_235_2500134_NONE# %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#def %#Pl_235_2500134_240_5789784_NONE# %#Pl_250_12369084_240_5789784_NONE#./%#Pl_231_16777215_240_5789784_bold#ghi %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE# %#Pl_252_13684944_236_3158064_NONE# %#Pl_235_2500134_252_13684944_bold# Bufs '
|
||||
call writefile(['Unexpected result (2)', result], 'message.fail')
|
||||
call writefile(['Unexpected tabline (2)', result], 'message.fail')
|
||||
cquit
|
||||
endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue