mirror of
https://github.com/powerline/powerline.git
synced 2025-07-31 01:35:40 +02:00
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`
|
:file:`powerline/config.json`
|
||||||
:ref:`Colorschemes <config-colors>`
|
:ref:`Colorschemes <config-colors>`
|
||||||
:file:`powerline/colorschemes/{name}.json`,
|
:file:`powerline/colorschemes/{name}.json`,
|
||||||
:file:`powerline/colorscheme/__main__.json`,
|
:file:`powerline/colorscheme/{extension}/__main__.json`,
|
||||||
:file:`powerline/colorschemes/{extension}/{name}.json`
|
:file:`powerline/colorschemes/{extension}/{name}.json`
|
||||||
:ref:`Themes <config-themes>`
|
:ref:`Themes <config-themes>`
|
||||||
|
:file:`powerline/themes/{top_theme}.json`,
|
||||||
|
:file:`powerline/themes/{extension}/__main__.json`,
|
||||||
:file:`powerline/themes/{extension}/default.json`
|
:file:`powerline/themes/{extension}/default.json`
|
||||||
|
|
||||||
The default configuration files are stored in the main package. User
|
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
|
corresponding values are both dictionaries in which case these dictionaries
|
||||||
are merged and key is assigned the result of the merge.
|
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-guide:
|
||||||
|
|
||||||
Quick setup 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"``,
|
codes thus rendering powerline prompt colorless. Valid values: ``"tmux"``,
|
||||||
``"screen"``, ``null`` (default).
|
``"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:
|
.. _config-common-paths:
|
||||||
|
|
||||||
``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.
|
Boolean, determines whether configuration should be reloaded at all.
|
||||||
Defaults to ``True``.
|
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
|
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.
|
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``
|
``local_themes``
|
||||||
.. _config-ext-local_themes:
|
.. _config-ext-local_themes:
|
||||||
|
|
||||||
@ -155,7 +158,7 @@ Colorschemes
|
|||||||
============
|
============
|
||||||
|
|
||||||
:Location: :file:`powerline/colorschemes/{name}.json`,
|
:Location: :file:`powerline/colorschemes/{name}.json`,
|
||||||
:file:`powerline/colorscheme/__main__.json`,
|
:file:`powerline/colorschemes/__main__.json`,
|
||||||
:file:`powerline/colorschemes/{extension}/{name}.json`
|
:file:`powerline/colorschemes/{extension}/{name}.json`
|
||||||
|
|
||||||
Colorscheme files are processed in order given: definitions from each next file
|
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
|
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``
|
||||||
Name of the theme.
|
Name of the theme.
|
||||||
@ -223,23 +247,45 @@ Themes
|
|||||||
``default_module``
|
``default_module``
|
||||||
Python module where segments will be looked by default.
|
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:
|
.. _config-themes-segment_data:
|
||||||
|
|
||||||
``segment_data``
|
``segment_data``
|
||||||
A dict where keys are segment names or strings ``{module}.{name}``. Used to
|
A dict where keys are segment names or strings ``{module}.{name}``. Used to
|
||||||
specify default values for various keys:
|
specify default values for various keys:
|
||||||
:ref:`after <config-themes-seg-after>`,
|
:ref:`after <config-themes-seg-after>`,
|
||||||
:ref:`args <config-themes-seg-args>` (only for function segments),
|
|
||||||
:ref:`before <config-themes-seg-before>`,
|
:ref:`before <config-themes-seg-before>`,
|
||||||
:ref:`contents <config-themes-seg-contents>` (only for string segments
|
:ref:`contents <config-themes-seg-contents>` (only for string segments
|
||||||
if :ref:`name <config-themes-seg-name>` is defined),
|
if :ref:`name <config-themes-seg-name>` is defined),
|
||||||
:ref:`display <config-themes-seg-display>`.
|
: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
|
When using :ref:`local themes <config-ext-local_themes>` values of these
|
||||||
keys are first searched in the segment description, then in ``segment_data``
|
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
|
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
|
<config-ext-theme>`. For the :ref:`default theme <config-ext-theme>` itself
|
||||||
step 2 is obviously avoided.
|
step 2 is obviously avoided.
|
||||||
|
|
||||||
|
.. note:: Top-level themes are out of equation here: they are merged
|
||||||
|
before the above merging process happens.
|
||||||
|
|
||||||
``segments``
|
``segments``
|
||||||
A dict with a ``left`` and a ``right`` lists, consisting of segment
|
A dict with a ``left`` and a ``right`` lists, consisting of segment
|
||||||
dictionaries. Shell themes may also contain ``above`` list of dictionaries.
|
dictionaries. Shell themes may also contain ``above`` list of dictionaries.
|
||||||
@ -259,8 +305,8 @@ Themes
|
|||||||
Each segment dictionary has the following options:
|
Each segment dictionary has the following options:
|
||||||
|
|
||||||
``type``
|
``type``
|
||||||
The segment type. Can be one of ``function`` (default), ``string``
|
The segment type. Can be one of ``function`` (default), ``string``,
|
||||||
or ``filler``:
|
``filler`` or ``segments_list``:
|
||||||
|
|
||||||
``function``
|
``function``
|
||||||
The segment contents is the return value of the function defined
|
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.
|
*not* included in any modes, *except* for the modes in this list.
|
||||||
|
|
||||||
``display``
|
``display``
|
||||||
|
|
||||||
.. _config-themes-seg-display:
|
.. _config-themes-seg-display:
|
||||||
|
|
||||||
Boolean. If false disables displaying of the segment.
|
Boolean. If false disables displaying of the segment.
|
||||||
Defaults to ``True``.
|
Defaults to ``True``.
|
||||||
|
|
||||||
``segments``
|
``segments``
|
||||||
|
.. _config-themes-seg-segments:
|
||||||
|
|
||||||
A list of subsegments.
|
A list of subsegments.
|
||||||
|
@ -215,6 +215,7 @@ def finish_common_config(common_config):
|
|||||||
paths.
|
paths.
|
||||||
'''
|
'''
|
||||||
common_config = common_config.copy()
|
common_config = common_config.copy()
|
||||||
|
common_config.setdefault('default_top_theme', 'powerline')
|
||||||
common_config.setdefault('paths', [])
|
common_config.setdefault('paths', [])
|
||||||
common_config.setdefault('watcher', 'auto')
|
common_config.setdefault('watcher', 'auto')
|
||||||
common_config.setdefault('log_level', 'WARNING')
|
common_config.setdefault('log_level', 'WARNING')
|
||||||
@ -345,13 +346,15 @@ class Powerline(object):
|
|||||||
if load_main:
|
if load_main:
|
||||||
self._purge_configs('main')
|
self._purge_configs('main')
|
||||||
config = self.load_main_config()
|
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:
|
if self.common_config != self.prev_common_config:
|
||||||
common_config_differs = True
|
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']
|
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():
|
if interval is not None and not self.config_loader.is_alive():
|
||||||
self.config_loader.start()
|
self.config_loader.start()
|
||||||
|
|
||||||
|
self.default_top_theme = self.common_config['default_top_theme']
|
||||||
|
|
||||||
self.ext_config = config['ext'][self.ext]
|
self.ext_config = config['ext'][self.ext]
|
||||||
if self.ext_config != self.prev_ext_config:
|
if self.ext_config != self.prev_ext_config:
|
||||||
ext_config_differs = True
|
ext_config_differs = True
|
||||||
@ -445,30 +450,20 @@ class Powerline(object):
|
|||||||
'''
|
'''
|
||||||
return get_config_paths()
|
return get_config_paths()
|
||||||
|
|
||||||
def _load_config(self, cfg_path, type):
|
def _load_config(self, cfg_path, cfg_type):
|
||||||
'''Load configuration and setup watches.'''
|
'''Load configuration and setup watches.'''
|
||||||
return load_config(
|
return load_config(
|
||||||
cfg_path,
|
cfg_path,
|
||||||
self.find_config_files,
|
self.find_config_files,
|
||||||
self.config_loader,
|
self.config_loader,
|
||||||
self.cr_callbacks[type]
|
self.cr_callbacks[cfg_type]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _purge_configs(self, type):
|
def _purge_configs(self, cfg_type):
|
||||||
function = self.cr_callbacks[type]
|
function = self.cr_callbacks[cfg_type]
|
||||||
self.config_loader.unregister_functions(set((function,)))
|
self.config_loader.unregister_functions(set((function,)))
|
||||||
self.config_loader.unregister_missing(set(((self.find_config_files, 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):
|
def load_main_config(self):
|
||||||
'''Get top-level configuration.
|
'''Get top-level configuration.
|
||||||
|
|
||||||
@ -476,6 +471,47 @@ class Powerline(object):
|
|||||||
'''
|
'''
|
||||||
return self._load_config('config', 'main')
|
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):
|
def load_colorscheme_config(self, name):
|
||||||
'''Get colorscheme.
|
'''Get colorscheme.
|
||||||
|
|
||||||
@ -484,40 +520,27 @@ class Powerline(object):
|
|||||||
|
|
||||||
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
|
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
|
||||||
'''
|
'''
|
||||||
# TODO Make sure no colorscheme name ends with __ (do it in
|
|
||||||
# powerline-lint)
|
|
||||||
levels = (
|
levels = (
|
||||||
os.path.join('colorschemes', name),
|
os.path.join('colorschemes', name),
|
||||||
os.path.join('colorschemes', self.ext, '__main__'),
|
os.path.join('colorschemes', self.ext, '__main__'),
|
||||||
os.path.join('colorschemes', self.ext, name),
|
os.path.join('colorschemes', self.ext, name),
|
||||||
)
|
)
|
||||||
config = {}
|
return self._load_hierarhical_config('colorscheme', levels, (1,))
|
||||||
loaded = 0
|
|
||||||
exceptions = []
|
def load_theme_config(self, name):
|
||||||
for cfg_path in levels:
|
'''Get theme configuration.
|
||||||
try:
|
|
||||||
lvl_config = self._load_config(cfg_path, 'colorscheme')
|
:param str name:
|
||||||
except IOError as e:
|
Name of the theme to load.
|
||||||
if sys.version_info < (3,):
|
|
||||||
tb = sys.exc_info()[2]
|
:return: dictionary with :ref:`theme configuration <config-themes>`
|
||||||
exceptions.append((e, tb))
|
'''
|
||||||
else:
|
levels = (
|
||||||
exceptions.append(e)
|
os.path.join('themes', self.ext_config.get('top_theme') or self.default_top_theme),
|
||||||
else:
|
os.path.join('themes', self.ext, '__main__'),
|
||||||
if not cfg_path.endswith('__'):
|
os.path.join('themes', self.ext, name),
|
||||||
loaded += 1
|
)
|
||||||
# TODO Either make sure `attr` list is always present or make
|
return self._load_hierarhical_config('theme', levels, (0, 1,))
|
||||||
# mergedicts not merge group definitions.
|
|
||||||
mergedicts(config, lvl_config)
|
|
||||||
if not loaded:
|
|
||||||
for exception in exceptions:
|
|
||||||
if type(exception) is tuple:
|
|
||||||
e = exception[0]
|
|
||||||
else:
|
|
||||||
e = exception
|
|
||||||
self.exception('Failed to load colorscheme: {0}', e, exception=exception)
|
|
||||||
raise e
|
|
||||||
return config
|
|
||||||
|
|
||||||
def load_colors_config(self):
|
def load_colors_config(self):
|
||||||
'''Get colorscheme.
|
'''Get colorscheme.
|
||||||
|
@ -1,17 +1,6 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
"term_truecolor": false,
|
"term_truecolor": false
|
||||||
"dividers": {
|
|
||||||
"left": {
|
|
||||||
"hard": " ",
|
|
||||||
"soft": " "
|
|
||||||
},
|
|
||||||
"right": {
|
|
||||||
"hard": " ",
|
|
||||||
"soft": " "
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"spaces": 1
|
|
||||||
},
|
},
|
||||||
"ext": {
|
"ext": {
|
||||||
"ipython": {
|
"ipython": {
|
||||||
|
108
powerline/config_files/themes/ascii.json
Normal file
108
powerline/config_files/themes/ascii.json
Normal file
@ -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": "+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
powerline/config_files/themes/powerline.json
Normal file
108
powerline/config_files/themes/powerline.json
Normal file
@ -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": "+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
powerline/config_files/themes/shell/__main__.json
Normal file
14
powerline/config_files/themes/shell/__main__.json
Normal file
@ -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",
|
"default_module": "powerline.segments.common",
|
||||||
"segment_data": {
|
|
||||||
"hostname": {
|
|
||||||
"before": " ",
|
|
||||||
"args": {
|
|
||||||
"only_if_ssh": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"virtualenv": {
|
|
||||||
"before": "ⓔ "
|
|
||||||
},
|
|
||||||
"branch": {
|
|
||||||
"before": " "
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"segments": {
|
"segments": {
|
||||||
"left": [
|
"left": [
|
||||||
{
|
{
|
||||||
@ -30,10 +16,7 @@
|
|||||||
"name": "virtualenv"
|
"name": "virtualenv"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cwd",
|
"name": "cwd"
|
||||||
"args": {
|
|
||||||
"dir_limit_depth": 3
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"module": "powerline.segments.shell",
|
"module": "powerline.segments.shell",
|
||||||
|
@ -1,19 +1,5 @@
|
|||||||
{
|
{
|
||||||
"default_module": "powerline.segments.common",
|
"default_module": "powerline.segments.common",
|
||||||
"segment_data": {
|
|
||||||
"hostname": {
|
|
||||||
"before": " ",
|
|
||||||
"args": {
|
|
||||||
"only_if_ssh": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"virtualenv": {
|
|
||||||
"before": "ⓔ "
|
|
||||||
},
|
|
||||||
"branch": {
|
|
||||||
"before": " "
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"segments": {
|
"segments": {
|
||||||
"left": [
|
"left": [
|
||||||
{
|
{
|
||||||
@ -29,10 +15,7 @@
|
|||||||
"name": "branch"
|
"name": "branch"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cwd",
|
"name": "cwd"
|
||||||
"args": {
|
|
||||||
"dir_limit_depth": 3
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"module": "powerline.segments.shell",
|
"module": "powerline.segments.shell",
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
{
|
{
|
||||||
"default_module": "powerline.segments.common",
|
"default_module": "powerline.segments.common",
|
||||||
"segment_data": {
|
|
||||||
"uptime": {
|
|
||||||
"before": "⇑ "
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"before": "⌚ "
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"segments": {
|
"segments": {
|
||||||
"right": [
|
"right": [
|
||||||
{
|
{
|
||||||
@ -19,7 +11,8 @@
|
|||||||
"priority": 50
|
"priority": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "date"
|
"name": "date",
|
||||||
|
"before": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "date",
|
"name": "date",
|
||||||
|
108
powerline/config_files/themes/unicode.json
Normal file
108
powerline/config_files/themes/unicode.json
Normal file
@ -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": "+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
powerline/config_files/themes/unicode_terminus.json
Normal file
108
powerline/config_files/themes/unicode_terminus.json
Normal file
@ -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": "+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
powerline/config_files/themes/unicode_terminus_condensed.json
Normal file
109
powerline/config_files/themes/unicode_terminus_condensed.json
Normal file
@ -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": "+"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
powerline/config_files/themes/vim/__main__.json
Normal file
10
powerline/config_files/themes/vim/__main__.json
Normal file
@ -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": {
|
"segments": {
|
||||||
"left": [
|
"left": [
|
||||||
{
|
{
|
||||||
|
@ -7,19 +7,18 @@
|
|||||||
"priority": 50
|
"priority": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "date"
|
"name": "date",
|
||||||
|
"before": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "date",
|
"name": "date",
|
||||||
"args": {
|
"args": {
|
||||||
"format": "%H:%M",
|
"format": "%H:%M",
|
||||||
"istime": true
|
"istime": true
|
||||||
},
|
}
|
||||||
"before": "⌚ "
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "email_imap_alert",
|
"name": "email_imap_alert",
|
||||||
"before": "✉ ",
|
|
||||||
"priority": 10,
|
"priority": 10,
|
||||||
"args": {
|
"args": {
|
||||||
"username": "",
|
"username": "",
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from powerline.lib.monotonic import monotonic
|
|
||||||
|
|
||||||
from threading import Thread, Lock, Event
|
from threading import Thread, Lock, Event
|
||||||
|
from types import MethodType
|
||||||
|
|
||||||
|
from powerline.lib.monotonic import monotonic
|
||||||
|
from powerline.segments import Segment
|
||||||
|
|
||||||
|
|
||||||
class MultiRunnedThread(object):
|
class MultiRunnedThread(object):
|
||||||
@ -28,12 +30,14 @@ class MultiRunnedThread(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ThreadedSegment(MultiRunnedThread):
|
class ThreadedSegment(Segment, MultiRunnedThread):
|
||||||
min_sleep_time = 0.1
|
min_sleep_time = 0.1
|
||||||
update_first = True
|
update_first = True
|
||||||
interval = 1
|
interval = 1
|
||||||
daemon = False
|
daemon = False
|
||||||
|
|
||||||
|
argmethods = ('render', 'set_state')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ThreadedSegment, self).__init__()
|
super(ThreadedSegment, self).__init__()
|
||||||
self.run_once = True
|
self.run_once = True
|
||||||
@ -145,10 +149,34 @@ class ThreadedSegment(MultiRunnedThread):
|
|||||||
def debug(self, *args, **kwargs):
|
def debug(self, *args, **kwargs):
|
||||||
self.pl.debug(prefix=self.__class__.__name__, *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):
|
class KwThreadedSegment(ThreadedSegment):
|
||||||
update_first = True
|
update_first = True
|
||||||
|
|
||||||
|
argmethods = ('render', 'set_state', 'key', 'render_one')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(KwThreadedSegment, self).__init__()
|
super(KwThreadedSegment, self).__init__()
|
||||||
self.updated = True
|
self.updated = True
|
||||||
|
@ -431,9 +431,6 @@ class WithPath(object):
|
|||||||
def check_matcher_func(ext, match_name, data, context, echoerr):
|
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', [])]
|
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('.')
|
match_module, separator, match_function = match_name.rpartition('.')
|
||||||
if not separator:
|
if not separator:
|
||||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
match_module = 'powerline.matchers.{0}'.format(ext)
|
||||||
@ -512,23 +509,30 @@ def check_config(d, theme, data, context, echoerr):
|
|||||||
return True, False, False
|
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,
|
divider_spec = Spec().type(unicode).len('le', 3,
|
||||||
lambda value: 'Divider {0!r} is too large!'.format(value)).copy
|
lambda value: 'Divider {0!r} is too large!'.format(value)).copy
|
||||||
divside_spec = Spec(
|
ext_theme_spec = Spec().type(unicode).func(lambda *args: check_config('themes', *args)).copy
|
||||||
hard=divider_spec(),
|
top_theme_spec = Spec().type(unicode).func(check_top_theme).copy
|
||||||
soft=divider_spec(),
|
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
|
).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(
|
main_spec = (Spec(
|
||||||
common=Spec(
|
common=Spec(
|
||||||
dividers=Spec(
|
default_top_theme=top_theme_spec().optional(),
|
||||||
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)
|
|
||||||
),
|
|
||||||
term_truecolor=Spec().type(bool).optional(),
|
term_truecolor=Spec().type(bool).optional(),
|
||||||
# Python is capable of loading from zip archives. Thus checking path
|
# Python is capable of loading from zip archives. Thus checking path
|
||||||
# only for existence of the path, not for it being a directory
|
# 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(),
|
watcher=Spec().type(unicode).oneof(set(('auto', 'inotify', 'stat'))).optional(),
|
||||||
).context_message('Error while loading common configuration (key {key})'),
|
).context_message('Error while loading common configuration (key {key})'),
|
||||||
ext=Spec(
|
ext=Spec(
|
||||||
vim=Spec(
|
vim=ext_spec().update(
|
||||||
colorscheme=colorscheme_spec(),
|
local_themes=Spec(
|
||||||
theme=theme_spec(),
|
__tabline__=ext_theme_spec(),
|
||||||
local_themes=Spec().unknown_spec(
|
).unknown_spec(
|
||||||
lambda *args: check_matcher_func('vim', *args), theme_spec()
|
lambda *args: check_matcher_func('vim', *args), ext_theme_spec()
|
||||||
),
|
),
|
||||||
).optional(),
|
).optional(),
|
||||||
ipython=Spec(
|
ipython=ext_spec().update(
|
||||||
colorscheme=colorscheme_spec(),
|
|
||||||
theme=theme_spec(),
|
|
||||||
local_themes=Spec(
|
local_themes=Spec(
|
||||||
in2=theme_spec(),
|
in2=ext_theme_spec(),
|
||||||
out=theme_spec(),
|
out=ext_theme_spec(),
|
||||||
rewrite=theme_spec(),
|
rewrite=ext_theme_spec(),
|
||||||
),
|
),
|
||||||
).optional(),
|
).optional(),
|
||||||
shell=Spec(
|
shell=ext_spec().update(
|
||||||
colorscheme=colorscheme_spec(),
|
|
||||||
theme=theme_spec(),
|
|
||||||
local_themes=Spec(
|
local_themes=Spec(
|
||||||
continuation=theme_spec(),
|
continuation=ext_theme_spec(),
|
||||||
select=theme_spec(),
|
select=ext_theme_spec(),
|
||||||
),
|
),
|
||||||
).optional(),
|
).optional(),
|
||||||
).unknown_spec(
|
).unknown_spec(
|
||||||
check_ext,
|
check_ext,
|
||||||
Spec(
|
ext_spec(),
|
||||||
colorscheme=colorscheme_spec(),
|
|
||||||
theme=theme_spec(),
|
|
||||||
)
|
|
||||||
).context_message('Error while loading extensions configuration (key {key})'),
|
).context_message('Error while loading extensions configuration (key {key})'),
|
||||||
).context_message('Error while loading main configuration'))
|
).context_message('Error while loading main configuration'))
|
||||||
|
|
||||||
@ -771,7 +768,7 @@ type_keys = {
|
|||||||
}
|
}
|
||||||
required_keys = {
|
required_keys = {
|
||||||
'function': set(('name',)),
|
'function': set(('name',)),
|
||||||
'string': set(('contents',)),
|
'string': set(()),
|
||||||
'filler': set(),
|
'filler': set(),
|
||||||
'segment_list': set(('name', 'segments',)),
|
'segment_list': set(('name', 'segments',)),
|
||||||
}
|
}
|
||||||
@ -845,11 +842,11 @@ def check_full_segment_data(segment, data, context, echoerr):
|
|||||||
|
|
||||||
ext = data['ext']
|
ext = data['ext']
|
||||||
theme_segment_data = context[0][1].get('segment_data', {})
|
theme_segment_data = context[0][1].get('segment_data', {})
|
||||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||||
if not top_theme_name or data['theme'] == top_theme_name:
|
if not main_theme_name or data['theme'] == main_theme_name:
|
||||||
top_segment_data = {}
|
top_segment_data = {}
|
||||||
else:
|
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']]
|
names = [segment['name']]
|
||||||
if segment.get('type', 'function') == 'function':
|
if segment.get('type', 'function') == 'function':
|
||||||
@ -977,12 +974,16 @@ def check_segment_name(name, data, context, echoerr):
|
|||||||
return True, False, hadproblem
|
return True, False, hadproblem
|
||||||
elif context[-2][1].get('type') != 'segment_list':
|
elif context[-2][1].get('type') != 'segment_list':
|
||||||
if name not in context[0][1].get('segment_data', {}):
|
if name not in context[0][1].get('segment_data', {}):
|
||||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||||
if data['theme'] == top_theme_name:
|
if data['theme'] == main_theme_name:
|
||||||
top_theme = {}
|
main_theme = {}
|
||||||
else:
|
else:
|
||||||
top_theme = data['ext_theme_configs'].get(top_theme_name, {})
|
main_theme = data['ext_theme_configs'].get(main_theme_name, {})
|
||||||
if name not in top_theme.get('segment_data', {}):
|
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)),
|
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='found useless use of name key (such name is not present in theme/segment_data)',
|
||||||
problem_mark=name.mark)
|
problem_mark=name.mark)
|
||||||
@ -1070,34 +1071,49 @@ def check_highlight_groups(hl_groups, data, context, echoerr):
|
|||||||
return True, False, False
|
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']
|
ext = data['ext']
|
||||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
main_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||||
is_top_theme = (data['theme'] == top_theme_name)
|
is_main_theme = (data['theme'] == main_theme_name)
|
||||||
if is_top_theme:
|
if theme_type == 'top':
|
||||||
themes = data['ext_theme_configs'].values()
|
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:
|
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():
|
for segments in theme.get('segments', {}).values():
|
||||||
found = False
|
|
||||||
for segment in segments:
|
for segment in segments:
|
||||||
if 'name' in segment:
|
if 'name' in segment:
|
||||||
if key == segment['name']:
|
if has_module_name:
|
||||||
found = True
|
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext))
|
||||||
module = segment.get('module', theme.get('default_module', 'powerline.segments.' + ext))
|
full_name = unicode(module) + '.' + unicode(segment['name'])
|
||||||
if key == unicode(module) + '.' + unicode(segment['name']):
|
if key == full_name:
|
||||||
found = True
|
found = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if key == segment['name']:
|
||||||
|
found = True
|
||||||
|
break
|
||||||
if found:
|
if found:
|
||||||
break
|
break
|
||||||
if found:
|
if found:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
echoerr(context='Error while checking segment data',
|
if data['theme_type'] != 'top':
|
||||||
problem='found key {0} that cannot be associated with any segment'.format(key),
|
echoerr(context='Error while checking segment data',
|
||||||
problem_mark=key.mark)
|
problem='found key {0} that cannot be associated with any segment'.format(key),
|
||||||
return True, False, True
|
problem_mark=key.mark)
|
||||||
|
return True, False, True
|
||||||
|
|
||||||
return True, False, False
|
return True, False, False
|
||||||
|
|
||||||
@ -1109,8 +1125,8 @@ threaded_args_specs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_args_variant(segment, args, data, context, echoerr):
|
def check_args_variant(func, args, data, context, echoerr):
|
||||||
argspec = getconfigargspec(segment)
|
argspec = getconfigargspec(func)
|
||||||
present_args = set(args)
|
present_args = set(args)
|
||||||
all_args = set(argspec.args)
|
all_args = set(argspec.args)
|
||||||
required_args = set(argspec.args[:-len(argspec.defaults)])
|
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)
|
problem_mark=next(iter(present_args - all_args)).mark)
|
||||||
hadproblem = True
|
hadproblem = True
|
||||||
|
|
||||||
if isinstance(segment, ThreadedSegment):
|
if isinstance(func, ThreadedSegment):
|
||||||
for key in set(threaded_args_specs) & present_args:
|
for key in set(threaded_args_specs) & present_args:
|
||||||
proceed, khadproblem = threaded_args_specs[key].match(
|
proceed, khadproblem = threaded_args_specs[key].match(
|
||||||
args[key],
|
args[key],
|
||||||
@ -1149,13 +1165,13 @@ def check_args_variant(segment, args, data, context, echoerr):
|
|||||||
return hadproblem
|
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)
|
new_echoerr = DelayedEchoErr(echoerr)
|
||||||
count = 0
|
count = 0
|
||||||
hadproblem = False
|
hadproblem = False
|
||||||
for segment in get_segment_variants(data, context, new_echoerr):
|
for func in get_functions(data, context, new_echoerr):
|
||||||
count += 1
|
count += 1
|
||||||
shadproblem = check_args_variant(segment, args, data, context, echoerr)
|
shadproblem = check_args_variant(func, args, data, context, echoerr)
|
||||||
if shadproblem:
|
if shadproblem:
|
||||||
hadproblem = True
|
hadproblem = True
|
||||||
|
|
||||||
@ -1171,7 +1187,7 @@ def check_args(get_segment_variants, args, data, context, echoerr):
|
|||||||
return True, False, hadproblem
|
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')
|
name = context[-2][1].get('name')
|
||||||
if name:
|
if name:
|
||||||
func = import_segment(name, data, context, echoerr)
|
func = import_segment(name, data, context, echoerr)
|
||||||
@ -1179,7 +1195,7 @@ def get_one_segment_variant(data, context, echoerr):
|
|||||||
yield func
|
yield func
|
||||||
|
|
||||||
|
|
||||||
def get_all_possible_segments(data, context, echoerr):
|
def get_all_possible_functions(data, context, echoerr):
|
||||||
name = context[-2][0]
|
name = context[-2][0]
|
||||||
module, name = name.rpartition('.')[::2]
|
module, name = name.rpartition('.')[::2]
|
||||||
if module:
|
if module:
|
||||||
@ -1187,13 +1203,13 @@ def get_all_possible_segments(data, context, echoerr):
|
|||||||
if func:
|
if func:
|
||||||
yield func
|
yield func
|
||||||
else:
|
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 segments in theme_config.get('segments', {}).values():
|
||||||
for segment in segments:
|
for segment in segments:
|
||||||
if segment.get('type', 'function') == 'function':
|
if segment.get('type', 'function') == 'function':
|
||||||
module = segment.get(
|
module = segment.get(
|
||||||
'module',
|
'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)
|
func = import_segment(name, data, context, echoerr, module=module)
|
||||||
if func:
|
if func:
|
||||||
@ -1222,7 +1238,7 @@ segment_spec = Spec(
|
|||||||
before=Spec().type(unicode).optional(),
|
before=Spec().type(unicode).optional(),
|
||||||
width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(),
|
width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(),
|
||||||
align=Spec().oneof(set('lr')).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(),
|
contents=Spec().type(unicode).optional(),
|
||||||
highlight_group=Spec().list(
|
highlight_group=Spec().list(
|
||||||
highlight_group_spec().re(
|
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, *args: (True, True, not (('left' in value) or ('right' in value)))),
|
||||||
(lambda value: 'segments dictionary must contain either left, right or both keys')
|
(lambda value: 'segments dictionary must contain either left, right or both keys')
|
||||||
).context_message('Error while loading segments (key {key})').copy
|
).context_message('Error while loading segments (key {key})').copy
|
||||||
theme_spec = (Spec(
|
divside_spec = Spec(
|
||||||
default_module=segment_module_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(
|
segment_data=Spec().unknown_spec(
|
||||||
Spec().func(check_segment_data_key),
|
Spec().func(check_segment_data_key),
|
||||||
Spec(
|
segment_data_value_spec(),
|
||||||
after=Spec().type(unicode).optional(),
|
).optional().context_message('Error while loading segment data (key {key})'),
|
||||||
before=Spec().type(unicode).optional(),
|
)
|
||||||
display=Spec().type(bool).optional(),
|
main_theme_spec = common_theme_spec().update(
|
||||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_all_possible_segments, *args, **kwargs)),
|
dividers=dividers_spec().optional(),
|
||||||
contents=Spec().type(unicode).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})'),
|
).optional().context_message('Error while loading segment data (key {key})'),
|
||||||
segments=segdict_spec().update(above=Spec().list(segdict_spec()).optional()),
|
segments=segdict_spec().update(above=Spec().list(segdict_spec()).optional()),
|
||||||
).context_message('Error while loading theme'))
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate_json_config_loader(lhadproblem):
|
def generate_json_config_loader(lhadproblem):
|
||||||
@ -1315,6 +1363,8 @@ def check(paths=None, debug=False):
|
|||||||
hadproblem = True
|
hadproblem = True
|
||||||
sys.stderr.write('Path {0} is supposed to be a directory, but it is not\n'.format(d))
|
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: {}))
|
configs = defaultdict(lambda: defaultdict(lambda: {}))
|
||||||
for typ in ('themes', 'colorschemes'):
|
for typ in ('themes', 'colorschemes'):
|
||||||
for ext in paths[typ]:
|
for ext in paths[typ]:
|
||||||
@ -1324,12 +1374,17 @@ def check(paths=None, debug=False):
|
|||||||
name = subp[:-5]
|
name = subp[:-5]
|
||||||
if name != '__main__':
|
if name != '__main__':
|
||||||
lists[typ].add(name)
|
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)
|
configs[typ][ext][name] = os.path.join(d, subp)
|
||||||
for path in paths['top_' + typ]:
|
for path in paths['top_' + typ]:
|
||||||
name = os.path.basename(path)[:-5]
|
name = os.path.basename(path)[:-5]
|
||||||
configs['top_' + typ][name] = path
|
configs['top_' + typ][name] = path
|
||||||
|
|
||||||
diff = set(configs['themes']) ^ set(configs['colorschemes'])
|
diff = set(configs['colorschemes']) - set(configs['themes'])
|
||||||
if diff:
|
if diff:
|
||||||
hadproblem = True
|
hadproblem = True
|
||||||
for ext in diff:
|
for ext in diff:
|
||||||
@ -1341,7 +1396,6 @@ def check(paths=None, debug=False):
|
|||||||
typ,
|
typ,
|
||||||
))
|
))
|
||||||
|
|
||||||
hadproblem = False
|
|
||||||
try:
|
try:
|
||||||
main_config = load_config('config', find_config_files, config_loader)
|
main_config = load_config('config', find_config_files, config_loader)
|
||||||
except IOError:
|
except IOError:
|
||||||
@ -1469,17 +1523,53 @@ def check(paths=None, debug=False):
|
|||||||
hadproblem = True
|
hadproblem = True
|
||||||
theme_configs[ext][theme] = config
|
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():
|
for ext, configs in theme_configs.items():
|
||||||
data = {
|
data = {
|
||||||
'ext': ext,
|
'ext': ext,
|
||||||
'colorscheme_configs': colorscheme_configs,
|
'colorscheme_configs': colorscheme_configs,
|
||||||
'import_paths': import_paths,
|
'import_paths': import_paths,
|
||||||
'main_config': main_config,
|
'main_config': main_config,
|
||||||
|
'top_themes': top_theme_configs,
|
||||||
'ext_theme_configs': configs,
|
'ext_theme_configs': configs,
|
||||||
'colors_config': colors_config
|
'colors_config': colors_config
|
||||||
}
|
}
|
||||||
for theme, config in configs.items():
|
for theme, config in configs.items():
|
||||||
data['theme'] = theme
|
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
|
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
|
return hadproblem
|
||||||
|
@ -1,62 +1,63 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from inspect import ArgSpec, getargspec
|
from inspect import ArgSpec, getargspec
|
||||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
|
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||||
|
from powerline.segments import Segment
|
||||||
|
|
||||||
|
|
||||||
def getconfigargspec(obj):
|
def getconfigargspec(obj):
|
||||||
if isinstance(obj, ThreadedSegment):
|
if hasattr(obj, 'powerline_origin'):
|
||||||
args = ['interval']
|
obj = obj.powerline_origin
|
||||||
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:
|
else:
|
||||||
if hasattr(obj, 'powerline_origin'):
|
obj = obj
|
||||||
obj = obj.powerline_origin
|
|
||||||
else:
|
|
||||||
obj = obj
|
|
||||||
|
|
||||||
argspec = getargspec(obj)
|
args = []
|
||||||
args = []
|
defaults = []
|
||||||
defaults = []
|
|
||||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
if isinstance(obj, Segment):
|
||||||
if ((arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None)) or
|
additional_args = obj.additional_args()
|
||||||
arg == 'pl'):
|
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
|
continue
|
||||||
if argspec.defaults and len(argspec.defaults) >= i:
|
if argspec.defaults and len(argspec.defaults) > i:
|
||||||
default = 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)
|
defaults.append(default)
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
else:
|
else:
|
||||||
args.insert(0, arg)
|
if arg not in args:
|
||||||
argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))
|
args.insert(0, arg)
|
||||||
|
|
||||||
return argspec
|
return ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||||
|
@ -1,25 +1,57 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals, division, print_function
|
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||||
|
|
||||||
from powerline.lib.file_watcher import create_file_watcher
|
|
||||||
import sys
|
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:
|
try:
|
||||||
return segment[key]
|
yield segment[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if 'name' in segment:
|
pass
|
||||||
name = segment['name']
|
try:
|
||||||
for theme_config in theme_configs:
|
name = segment['name']
|
||||||
if 'segment_data' in theme_config:
|
except KeyError:
|
||||||
for segment_key in ((module + '.' + name, name) if module else (name,)):
|
pass
|
||||||
try:
|
else:
|
||||||
return theme_config['segment_data'][segment_key][key]
|
found_module_key = False
|
||||||
except KeyError:
|
for theme_config in theme_configs:
|
||||||
pass
|
try:
|
||||||
return default
|
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):
|
def get_function(data, segment):
|
||||||
@ -33,7 +65,7 @@ def get_function(data, segment):
|
|||||||
|
|
||||||
|
|
||||||
def get_string(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):
|
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'],
|
'path': common_config['paths'],
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_key(segment, module, key, default=None):
|
def get_key(merge, segment, module, key, default=None):
|
||||||
return get_segment_key(segment, theme_configs, key, module, default)
|
return get_segment_key(merge, segment, theme_configs, key, module, default)
|
||||||
data['get_key'] = get_key
|
data['get_key'] = get_key
|
||||||
|
|
||||||
def get(segment, side):
|
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')
|
pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not get_key(segment, module, 'display', True):
|
if not get_key(False, segment, module, 'display', True):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if segment_type == 'function':
|
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')
|
highlight_group = segment.get('highlight_group') or segment.get('name')
|
||||||
|
|
||||||
if segment_type in ('function', 'segment_list'):
|
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':
|
if segment_type == 'segment_list':
|
||||||
# Handle startup and shutdown of _contents_func?
|
# 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,
|
'type': segment_type,
|
||||||
'highlight_group': highlight_group,
|
'highlight_group': highlight_group,
|
||||||
'divider_highlight_group': None,
|
'divider_highlight_group': None,
|
||||||
'before': get_key(segment, module, 'before', ''),
|
'before': get_key(False, segment, module, 'before', ''),
|
||||||
'after': get_key(segment, module, 'after', ''),
|
'after': get_key(False, segment, module, 'after', ''),
|
||||||
'contents_func': contents_func,
|
'contents_func': contents_func,
|
||||||
'contents': contents,
|
'contents': contents,
|
||||||
'priority': segment.get('priority', None),
|
'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 pkgutil import extend_path
|
||||||
|
from types import MethodType
|
||||||
|
|
||||||
|
|
||||||
__path__ = extend_path(__path__, __name__)
|
__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.humanize_bytes import humanize_bytes
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
||||||
|
from powerline.segments import Segment
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
@ -896,29 +897,30 @@ Highlight groups used: ``email_alert_gradient`` (gradient), ``email_alert``.
|
|||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
||||||
class NowPlayingSegment(object):
|
STATE_SYMBOLS = {
|
||||||
STATE_SYMBOLS = {
|
'fallback': '♫',
|
||||||
'fallback': '♫',
|
'play': '▶',
|
||||||
'play': '▶',
|
'pause': '▮▮',
|
||||||
'pause': '▮▮',
|
'stop': '■',
|
||||||
'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))
|
player_func = getattr(self, 'player_{0}'.format(player))
|
||||||
stats = {
|
stats = {
|
||||||
'state': None,
|
'state': 'fallback',
|
||||||
'state_symbol': self.STATE_SYMBOLS['fallback'],
|
|
||||||
'album': None,
|
'album': None,
|
||||||
'artist': None,
|
'artist': None,
|
||||||
'title': None,
|
'title': None,
|
||||||
'elapsed': None,
|
'elapsed': None,
|
||||||
'total': None,
|
'total': None,
|
||||||
}
|
}
|
||||||
func_stats = player_func(**kwargs)
|
func_stats = player_func(state_symbol=state_symbols, **kwargs)
|
||||||
if not func_stats:
|
if not func_stats:
|
||||||
return None
|
return None
|
||||||
stats.update(func_stats)
|
stats.update(func_stats)
|
||||||
|
stats['state_symbol'] = state_symbols.get(stats['state'])
|
||||||
return format.format(**stats)
|
return format.format(**stats)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -965,7 +967,6 @@ class NowPlayingSegment(object):
|
|||||||
state = self._convert_state(now_playing.get('status'))
|
state = self._convert_state(now_playing.get('status'))
|
||||||
return {
|
return {
|
||||||
'state': state,
|
'state': state,
|
||||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
|
||||||
'album': now_playing.get('album'),
|
'album': now_playing.get('album'),
|
||||||
'artist': now_playing.get('artist'),
|
'artist': now_playing.get('artist'),
|
||||||
'title': now_playing.get('title'),
|
'title': now_playing.get('title'),
|
||||||
@ -998,7 +999,6 @@ class NowPlayingSegment(object):
|
|||||||
client.disconnect()
|
client.disconnect()
|
||||||
return {
|
return {
|
||||||
'state': status.get('state'),
|
'state': status.get('state'),
|
||||||
'state_symbol': self.STATE_SYMBOLS.get(status.get('state')),
|
|
||||||
'album': now_playing.get('album'),
|
'album': now_playing.get('album'),
|
||||||
'artist': now_playing.get('artist'),
|
'artist': now_playing.get('artist'),
|
||||||
'title': now_playing.get('title'),
|
'title': now_playing.get('title'),
|
||||||
@ -1027,7 +1027,6 @@ class NowPlayingSegment(object):
|
|||||||
state = self._convert_state(status)
|
state = self._convert_state(status)
|
||||||
return {
|
return {
|
||||||
'state': state,
|
'state': state,
|
||||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
|
||||||
'album': info.get('xesam:album'),
|
'album': info.get('xesam:album'),
|
||||||
'artist': info.get('xesam:artist')[0],
|
'artist': info.get('xesam:artist')[0],
|
||||||
'title': info.get('xesam:title'),
|
'title': info.get('xesam:title'),
|
||||||
@ -1074,7 +1073,6 @@ class NowPlayingSegment(object):
|
|||||||
return None
|
return None
|
||||||
return {
|
return {
|
||||||
'state': state,
|
'state': state,
|
||||||
'state_symbol': self.STATE_SYMBOLS.get(state),
|
|
||||||
'album': spotify_status[1],
|
'album': spotify_status[1],
|
||||||
'artist': spotify_status[2],
|
'artist': spotify_status[2],
|
||||||
'title': spotify_status[3],
|
'title': spotify_status[3],
|
||||||
|
@ -31,13 +31,13 @@ class Theme(object):
|
|||||||
top_theme_config=None,
|
top_theme_config=None,
|
||||||
run_once=False,
|
run_once=False,
|
||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
self.dividers = theme_config['dividers']
|
||||||
self.dividers = dict((
|
self.dividers = dict((
|
||||||
(key, dict((k, u(v))
|
(key, dict((k, u(v))
|
||||||
for k, v in val.items()))
|
for k, v in val.items()))
|
||||||
for key, val in self.dividers.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.segments = []
|
||||||
self.EMPTY_SEGMENT = {
|
self.EMPTY_SEGMENT = {
|
||||||
'contents': None,
|
'contents': None,
|
||||||
|
@ -17,17 +17,6 @@ CONFIG_DIR = 'tests/config'
|
|||||||
|
|
||||||
root_config = lambda: {
|
root_config = lambda: {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
|
||||||
'left': {
|
|
||||||
'hard': '#>',
|
|
||||||
'soft': '|>',
|
|
||||||
},
|
|
||||||
'right': {
|
|
||||||
'hard': '<#',
|
|
||||||
'soft': '<|',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'spaces': 0,
|
|
||||||
'interval': None,
|
'interval': None,
|
||||||
'watcher': 'auto',
|
'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: {
|
main_tree = lambda: {
|
||||||
'1/config': root_config(),
|
'1/config': root_config(),
|
||||||
'1/colors': colors_config(),
|
'1/colors': colors_config(),
|
||||||
'1/colorschemes/default': colorscheme_config(),
|
'1/colorschemes/default': colorscheme_config(),
|
||||||
'1/themes/test/default': theme_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(), {
|
with WithConfigTree(mdc(main_tree(), {
|
||||||
'2/config': {
|
'2/config': {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
'default_top_theme': 'other1',
|
||||||
'left': {
|
|
||||||
'hard': '!>',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})) as p:
|
})) as p:
|
||||||
@ -163,36 +177,26 @@ class TestMerging(TestCase):
|
|||||||
with WithConfigTree(mdc(main_tree(), {
|
with WithConfigTree(mdc(main_tree(), {
|
||||||
'2/config': {
|
'2/config': {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
'default_top_theme': 'other1',
|
||||||
'left': {
|
|
||||||
'hard': '!>',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'3/config': {
|
'3/config': {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
'default_top_theme': 'other2',
|
||||||
'left': {
|
|
||||||
'hard': '>>',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})) as p:
|
})) as p:
|
||||||
self.assertRenderEqual(p, '{12} bt{2-}>>{--}')
|
self.assertRenderEqual(p, '{12} bt{2-}>>{--}')
|
||||||
|
|
||||||
|
def test_top_theme_merging(self):
|
||||||
with WithConfigTree(mdc(main_tree(), {
|
with WithConfigTree(mdc(main_tree(), {
|
||||||
'2/config': {
|
'2/themes/powerline': {
|
||||||
'common': {
|
'spaces': 1,
|
||||||
'spaces': 1,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
'3/config': {
|
'3/themes/powerline': {
|
||||||
'common': {
|
'dividers': {
|
||||||
'dividers': {
|
'left': {
|
||||||
'left': {
|
'hard': '>>',
|
||||||
'hard': '>>',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -12,17 +12,6 @@ from tests.lib.config_mock import get_powerline, add_watcher_events
|
|||||||
config = {
|
config = {
|
||||||
'config': {
|
'config': {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
|
||||||
"left": {
|
|
||||||
"hard": ">>",
|
|
||||||
"soft": ">",
|
|
||||||
},
|
|
||||||
"right": {
|
|
||||||
"hard": "<<",
|
|
||||||
"soft": "<",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'spaces': 0,
|
|
||||||
'interval': 0,
|
'interval': 0,
|
||||||
'watcher': 'test',
|
'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': {
|
'themes/test/2': {
|
||||||
'segments': {
|
'segments': {
|
||||||
"left": [
|
"left": [
|
||||||
@ -116,7 +131,7 @@ class TestConfigReload(TestCase):
|
|||||||
def test_noreload(self, config):
|
def test_noreload(self, config):
|
||||||
with get_powerline(config, run_once=True) as p:
|
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.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']['spaces'] = 1
|
||||||
add_watcher_events(p, 'config', wait=False, interval=0.05)
|
add_watcher_events(p, 'config', wait=False, interval=0.05)
|
||||||
# When running once thread should not start
|
# When running once thread should not start
|
||||||
@ -128,25 +143,30 @@ class TestConfigReload(TestCase):
|
|||||||
def test_reload_main(self, config):
|
def test_reload_main(self, config):
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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')
|
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.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(), [])
|
self.assertEqual(p.logger._pop_msgs(), [])
|
||||||
|
|
||||||
config['config']['ext']['test']['theme'] = 'nonexistent'
|
config['config']['ext']['test']['theme'] = 'nonexistent'
|
||||||
add_watcher_events(p, 'config')
|
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.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
|
# 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'
|
config['config']['ext']['test']['theme'] = 'default'
|
||||||
add_watcher_events(p, 'config')
|
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.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(), [])
|
self.assertEqual(p.logger._pop_msgs(), [])
|
||||||
|
|
||||||
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
|
config['config']['ext']['test']['colorscheme'] = 'nonexistent'
|
||||||
@ -170,7 +190,7 @@ class TestConfigReload(TestCase):
|
|||||||
config['config']['ext']['test']['theme'] = '2'
|
config['config']['ext']['test']['theme'] = '2'
|
||||||
add_watcher_events(p, 'config')
|
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.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.logger._pop_msgs(), [])
|
||||||
|
|
||||||
self.assertEqual(p.renderer.local_themes, None)
|
self.assertEqual(p.renderer.local_themes, None)
|
||||||
@ -185,7 +205,7 @@ class TestConfigReload(TestCase):
|
|||||||
def test_reload_unexistent(self, config):
|
def test_reload_unexistent(self, config):
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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'
|
config['config']['ext']['test']['colorscheme'] = 'nonexistentraise'
|
||||||
add_watcher_events(p, 'config')
|
add_watcher_events(p, 'config')
|
||||||
@ -222,7 +242,7 @@ class TestConfigReload(TestCase):
|
|||||||
def test_reload_colors(self, config):
|
def test_reload_colors(self, config):
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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
|
config['colors']['colors']['col1'] = 5
|
||||||
add_watcher_events(p, 'colors')
|
add_watcher_events(p, 'colors')
|
||||||
@ -234,7 +254,7 @@ class TestConfigReload(TestCase):
|
|||||||
def test_reload_colorscheme(self, config):
|
def test_reload_colorscheme(self, config):
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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'
|
config['colorschemes/test/default']['groups']['str1']['bg'] = 'col3'
|
||||||
add_watcher_events(p, 'colorschemes/test/default')
|
add_watcher_events(p, 'colorschemes/test/default')
|
||||||
@ -246,12 +266,24 @@ class TestConfigReload(TestCase):
|
|||||||
def test_reload_theme(self, config):
|
def test_reload_theme(self, config):
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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'
|
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||||
add_watcher_events(p, 'themes/test/default')
|
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.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(), [])
|
self.assertEqual(p.logger._pop_msgs(), [])
|
||||||
|
|
||||||
@with_new_config
|
@with_new_config
|
||||||
@ -259,12 +291,12 @@ class TestConfigReload(TestCase):
|
|||||||
config['config']['common']['interval'] = None
|
config['config']['common']['interval'] = None
|
||||||
with get_powerline(config, run_once=False) as p:
|
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.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'
|
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
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.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.assertEqual(p.logger._pop_msgs(), [])
|
||||||
self.assertTrue(p._watcher._calls)
|
self.assertTrue(p._watcher._calls)
|
||||||
|
|
||||||
@ -273,7 +305,7 @@ class TestConfigReload(TestCase):
|
|||||||
config['config']['common']['interval'] = None
|
config['config']['common']['interval'] = None
|
||||||
with get_powerline(config, run_once=True) as p:
|
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.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'
|
config['themes/test/default']['segments']['left'][0]['contents'] = 'col3'
|
||||||
add_watcher_events(p, 'themes/test/default', wait=False)
|
add_watcher_events(p, 'themes/test/default', wait=False)
|
||||||
|
@ -22,17 +22,6 @@ def highlighted_string(s, group, **kwargs):
|
|||||||
config = {
|
config = {
|
||||||
'config': {
|
'config': {
|
||||||
'common': {
|
'common': {
|
||||||
'dividers': {
|
|
||||||
'left': {
|
|
||||||
'hard': '>>',
|
|
||||||
'soft': '>',
|
|
||||||
},
|
|
||||||
'right': {
|
|
||||||
'hard': '<<',
|
|
||||||
'soft': '<',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'spaces': 0,
|
|
||||||
'interval': 0,
|
'interval': 0,
|
||||||
'watcher': 'test',
|
'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': {
|
'themes/vim/default': {
|
||||||
'default_module': 'powerline.segments.common',
|
'default_module': 'powerline.segments.common',
|
||||||
'segments': {
|
'segments': {
|
||||||
@ -147,9 +156,9 @@ class TestRender(TestCase):
|
|||||||
class TestLines(TestRender):
|
class TestLines(TestRender):
|
||||||
@add_args
|
@add_args
|
||||||
def test_without_above(self, p, config):
|
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 {--}')
|
||||||
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=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 {--}', width=11)
|
||||||
self.assertEqual(list(p.render_above_lines()), [])
|
self.assertEqual(list(p.render_above_lines()), [])
|
||||||
|
|
||||||
@with_new_config
|
@with_new_config
|
||||||
@ -158,21 +167,21 @@ class TestLines(TestRender):
|
|||||||
config['themes/test/default']['segments']['above'] = [old_segments]
|
config['themes/test/default']['segments']['above'] = [old_segments]
|
||||||
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
||||||
self.assertRenderLinesEqual(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, [
|
self.assertRenderLinesEqual(p, [
|
||||||
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
'{121} s {24}>>{344}g{34}>{34}|{344}f {--}',
|
||||||
], width=10)
|
], width=10)
|
||||||
|
|
||||||
config['themes/test/default']['segments']['above'] = [old_segments] * 2
|
config['themes/test/default']['segments']['above'] = [old_segments] * 2
|
||||||
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
with get_powerline(config, run_once=True, simpler_renderer=True) as p:
|
||||||
self.assertRenderLinesEqual(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, [
|
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)
|
], width=10)
|
||||||
|
|
||||||
|
|
||||||
@ -299,6 +308,82 @@ class TestColorschemesHierarchy(TestRender):
|
|||||||
self.assertEqual(p.logger._pop_msgs(), [])
|
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):
|
class TestVim(TestCase):
|
||||||
def test_environ_update(self):
|
def test_environ_update(self):
|
||||||
# Regression test: test that segment obtains environment from vim, not
|
# Regression test: test that segment obtains environment from vim, not
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/vim -S
|
#!/usr/bin/vim -S
|
||||||
let g:powerline_config_path = expand('<sfile>:p:h:h') . '/powerline/config_files'
|
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 '}}}
|
let g:powerline_theme_overrides__default = {'segment_data': {'line_current_symbol': {'contents': 'LN '}, 'branch': {'before': 'B '}}}
|
||||||
try
|
try
|
||||||
python import powerline.vim
|
python import powerline.vim
|
||||||
|
@ -13,7 +13,7 @@ catch
|
|||||||
endtry
|
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 '
|
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
|
cquit
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ catch
|
|||||||
endtry
|
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 '
|
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
|
cquit
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user