Add ability to override configuration options
Related changes: - Moved all non-ASCII symbols into `segment_data` - Added --config_path, replaced nargs='*' with better action='append' - Added g:powerline_config_path vim option - Added ipython overrides (via additional arguments to setup() or c.Powerline) TODO: support for non-string scalars in vim overrides. Fixes #231
This commit is contained in:
parent
c86b047ed4
commit
f211bb6c74
|
@ -132,8 +132,8 @@ Common configuration is a subdictionary that is a value of ``common`` key in
|
|||
|
||||
``paths``
|
||||
Defines additional paths which will be searched for modules when using
|
||||
:ref:`module segment option <config-themes-seg-module>`. Paths defined
|
||||
here have priority when searching for modules.
|
||||
:ref:`module segment option <config-themes-seg-module>`. Paths defined here
|
||||
have priority when searching for modules.
|
||||
|
||||
Extension-specific configuration
|
||||
--------------------------------
|
||||
|
@ -236,7 +236,8 @@ Themes
|
|||
using :ref:`local themes <config-ext-local_themes>` values of these keys are
|
||||
first searched in the segment description, then in ``segment_data`` key of
|
||||
a local theme, then in ``segment_data`` key of a :ref:`default theme
|
||||
<config-ext-theme>`.
|
||||
<config-ext-theme>`. For the :ref:`default theme <config-ext-theme>` itself
|
||||
step 2 is obviously avoided.
|
||||
|
||||
``segments``
|
||||
A dict with a ``left`` and a ``right`` list, consisting of segment
|
||||
|
@ -354,3 +355,74 @@ A segment function must return one of the following values:
|
|||
* A list of dicts consisting of a ``contents`` string, and
|
||||
a ``highlight_group`` list. This is useful for providing a particular
|
||||
highlighting group depending on the segment contents.
|
||||
|
||||
Local configuration
|
||||
===================
|
||||
|
||||
Depending on the application used it is possible to override configuration. Here
|
||||
is the list:
|
||||
|
||||
Vim overrides
|
||||
-------------
|
||||
|
||||
Vim configuration can be overridden using the following options:
|
||||
|
||||
``g:powerline_config_overrides``
|
||||
Dictionary, recursively merged with contents of
|
||||
:file:`powerline/config.json`.
|
||||
|
||||
``g:powerline_theme_overrides__{theme_name}``
|
||||
Dictionary, recursively merged with contents of
|
||||
:file:`powerline/themes/vim/{theme_name}.json`. Note that this way you can’t
|
||||
redefine some value (e.g. segment) in list, only the whole list itself: only
|
||||
dictionaries are merged recursively.
|
||||
|
||||
``g:powerline_config_path``
|
||||
Path (must be expanded, ``~`` shortcut is not supported). Points to the
|
||||
directory which will be searched for configuration. When this option is
|
||||
present, none of the other locations are searched.
|
||||
|
||||
Powerline script overrides
|
||||
--------------------------
|
||||
|
||||
Powerline script has a number of options controlling powerline behavior. Here
|
||||
``VALUE`` always means “some JSON object”.
|
||||
|
||||
``-c KEY.NESTED_KEY=VALUE`` or ``--config=KEY.NESTED_KEY=VALUE``
|
||||
Overrides options from :file:`powerline/config.json`.
|
||||
``KEY.KEY2.KEY3=VALUE`` is a shortcut for ``KEY={"KEY2": {"KEY3": VALUE}}``.
|
||||
Multiple options (i.e. ``-c K1=V1 -c K2=V2``) are allowed, result (in the
|
||||
example: ``{"K1": V1, "K2": V2}``) is recursively merged with the contents
|
||||
of the file.
|
||||
|
||||
``-t THEME_NAME.KEY.NESTED_KEY=VALUE`` or ``--theme_option=THEME_NAME.KEY.NESTED_KEY=VALUE``
|
||||
Overrides options from :file:`powerline/themes/{ext}/{THEME_NAME}.json`.
|
||||
``KEY.NESTED_KEY=VALUE`` is processed like described above, ``{ext}`` is the
|
||||
first argument to powerline script. May be passed multiple times.
|
||||
|
||||
``-p PATH`` or ``--config_path=PATH``
|
||||
Sets directory where configuration should be read from. If present, no
|
||||
default locations are searched for configuration. No expansions are
|
||||
performed by powerline script itself, but ``-p ~/.powerline`` will likely be
|
||||
expanded by the shell to something like ``-p /home/user/.powerline``.
|
||||
|
||||
Ipython overrides
|
||||
-----------------
|
||||
|
||||
Ipython overrides depend on ipython version. Before ipython-0.11 you should pass
|
||||
additional keyword arguments to setup() function. After ipython-0.11 you should
|
||||
use ``c.Powerline.KEY``. Supported ``KEY`` strings or keyword argument names:
|
||||
|
||||
``config_overrides``
|
||||
Overrides options from :file:`powerline/config.json`. Should be a dictionary
|
||||
that will be recursively merged with the contents of the file.
|
||||
|
||||
``theme_overrides``
|
||||
Overrides options from :file:`powerline/themes/ipython/*.json`. Should be
|
||||
a dictionary where keys are theme names and values are dictionaries which
|
||||
will be recursively merged with the contents of the given theme.
|
||||
|
||||
``path``
|
||||
Sets directory where configuration should be read from. If present, no
|
||||
default locations are searched for configuration. No expansions are
|
||||
performed thus you cannot use paths starting with ``~/``.
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from powerline.colorscheme import Colorscheme
|
||||
from powerline.lib import underscore_to_camelcase
|
||||
|
||||
|
||||
def load_json_config(search_paths, config_file):
|
||||
config_file += '.json'
|
||||
for path in search_paths:
|
||||
config_file_path = os.path.join(path, config_file)
|
||||
if os.path.isfile(config_file_path):
|
||||
with open(config_file_path, 'r') as config_file_fp:
|
||||
return json.load(config_file_fp)
|
||||
raise IOError('Config file not found in search path: {0}'.format(config_file))
|
||||
|
||||
|
||||
class Powerline(object):
|
||||
def __init__(self, ext, renderer_module=None):
|
||||
self.config_paths = self.get_config_paths()
|
||||
|
||||
# Load main config file
|
||||
config = self.load_main_config()
|
||||
common_config = config['common']
|
||||
ext_config = config['ext'][ext]
|
||||
self.ext = ext
|
||||
|
||||
# Load and initialize colorscheme
|
||||
colorscheme_config = self.load_colorscheme_config(ext_config['colorscheme'])
|
||||
colorscheme = Colorscheme(colorscheme_config)
|
||||
|
||||
# Load and initialize extension theme
|
||||
theme_config = self.load_theme_config(ext_config.get('theme', 'default'))
|
||||
common_config['paths'] = [os.path.expanduser(path) for path in common_config.get('paths', [])]
|
||||
self.import_paths = common_config['paths']
|
||||
theme_kwargs = {
|
||||
'ext': ext,
|
||||
'colorscheme': colorscheme,
|
||||
'common_config': common_config,
|
||||
'segment_info': self.get_segment_info(),
|
||||
}
|
||||
local_themes = self.get_local_themes(ext_config.get('local_themes', {}))
|
||||
|
||||
# Load and initialize extension renderer
|
||||
renderer_module_name = renderer_module or ext
|
||||
renderer_module_import = 'powerline.renderers.{0}'.format(renderer_module_name)
|
||||
renderer_class_name = '{0}Renderer'.format(underscore_to_camelcase(renderer_module_name))
|
||||
try:
|
||||
Renderer = getattr(importlib.import_module(renderer_module_import), renderer_class_name)
|
||||
except ImportError as e:
|
||||
sys.stderr.write('Error while importing renderer module: {0}\n'.format(e))
|
||||
sys.exit(1)
|
||||
options = {'term_truecolor': common_config.get('term_24bit_colors', False)}
|
||||
self.renderer = Renderer(theme_config, local_themes, theme_kwargs, **options)
|
||||
|
||||
def get_config_paths(self):
|
||||
config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
|
||||
config_path = os.path.join(config_home, 'powerline')
|
||||
plugin_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'config_files')
|
||||
return [config_path, plugin_path]
|
||||
|
||||
def load_theme_config(self, name):
|
||||
return load_json_config(self.config_paths, os.path.join('themes', self.ext, name))
|
||||
|
||||
def load_main_config(self):
|
||||
return load_json_config(self.config_paths, 'config')
|
||||
|
||||
def load_colorscheme_config(self, name):
|
||||
return load_json_config(self.config_paths, os.path.join('colorschemes', self.ext, name))
|
||||
|
||||
@staticmethod
|
||||
def get_local_themes(local_themes):
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def get_segment_info():
|
||||
return None
|
|
@ -1,4 +1,4 @@
|
|||
from powerline.core import Powerline
|
||||
from powerline.ipython import IpythonPowerline
|
||||
|
||||
from IPython.core.prompts import PromptManager
|
||||
|
||||
|
@ -19,8 +19,23 @@ class PowerlinePromptManager(PromptManager):
|
|||
return res if color else res_nocolor
|
||||
|
||||
|
||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||
def __init__(self, ip):
|
||||
config = ip.config.Powerline
|
||||
self.config_overrides = config.get('config_overrides')
|
||||
self.theme_overrides = config.get('theme_overrides', {})
|
||||
self.path = config.get('path')
|
||||
super(ConfigurableIpythonPowerline, self).__init__()
|
||||
|
||||
|
||||
def load_ipython_extension(ip):
|
||||
powerline = Powerline('ipython')
|
||||
global old_prompt_manager
|
||||
|
||||
old_prompt_manager = ip.prompt_manager
|
||||
powerline = ConfigurableIpythonPowerline(ip)
|
||||
|
||||
ip.prompt_manager = PowerlinePromptManager(powerline=powerline,
|
||||
shell=ip.prompt_manager.shell, config=ip.prompt_manager.config)
|
||||
|
||||
def unload_ipython_extension(ip):
|
||||
ip.prompt_manager = old_prompt_manager
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from powerline.core import Powerline
|
||||
from powerline.ipython import IpythonPowerline
|
||||
from IPython.Prompts import BasePrompt
|
||||
from IPython.ipapi import get as get_ipython
|
||||
|
||||
|
@ -18,10 +18,18 @@ class PowerlinePrompt(BasePrompt):
|
|||
return '%s>%s' % ('-' * self.prompt_text_len, ' ' * self.nrspaces)
|
||||
|
||||
|
||||
def setup(prompt='1'):
|
||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||
def __init__(self, config_overrides=None, theme_overrides={}, path=None):
|
||||
self.config_overrides = config_overrides
|
||||
self.theme_overrides = theme_overrides
|
||||
self.path = path
|
||||
super(ConfigurableIpythonPowerline, self).__init__()
|
||||
|
||||
|
||||
def setup(prompt='1', **kwargs):
|
||||
ip = get_ipython()
|
||||
|
||||
powerline = Powerline('ipython')
|
||||
powerline = ConfigurableIpythonPowerline(**kwargs)
|
||||
|
||||
attr = 'prompt' + prompt
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from libqtile import bar
|
||||
from libqtile.widget import base
|
||||
|
||||
from powerline.core import Powerline as PowerlineCore
|
||||
from powerline import Powerline as PowerlineCore
|
||||
|
||||
|
||||
class Powerline(base._TextBox):
|
||||
|
|
|
@ -18,15 +18,16 @@ endif
|
|||
let s:powerline_pycmd = substitute(get(g:, 'powerline_pycmd', 'py'), '\v^(py)%[thon](3?)$', '\1\2', '')
|
||||
let s:powerline_pyeval = get(g:, 'powerline_pyeval', s:powerline_pycmd.'eval')
|
||||
|
||||
let s:import_cmd = 'from powerline.vim import VimPowerline'
|
||||
try
|
||||
exec s:powerline_pycmd 'from powerline.core import Powerline'
|
||||
exec s:powerline_pycmd s:import_cmd
|
||||
catch
|
||||
" An error occured while importing the module, it could be installed
|
||||
" outside of Python's module search paths. Update sys.path and try again.
|
||||
exec s:powerline_pycmd 'import sys, vim'
|
||||
exec s:powerline_pycmd 'sys.path.append(vim.eval(''expand("<sfile>:h:h:h:h:h")''))'
|
||||
try
|
||||
exec s:powerline_pycmd 'from powerline.core import Powerline'
|
||||
exec s:powerline_pycmd s:import_cmd
|
||||
catch
|
||||
call s:CriticalError('An error occured while importing the Powerline package.
|
||||
\ This could be caused by an invalid sys.path setting, or by an incompatible
|
||||
|
@ -35,7 +36,8 @@ catch
|
|||
finish
|
||||
endtry
|
||||
endtry
|
||||
exec s:powerline_pycmd 'powerline = Powerline("vim", segment_info={})'
|
||||
exec s:powerline_pycmd 'powerline = VimPowerline()'
|
||||
exec s:powerline_pycmd 'del VimPowerline'
|
||||
|
||||
if !get(g:, 'powerline_debugging_pyeval') && exists('*'. s:powerline_pyeval)
|
||||
let s:pyeval = function(s:powerline_pyeval)
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
import zsh
|
||||
from powerline.core import Powerline
|
||||
from powerline.shell import ShellPowerline
|
||||
|
||||
|
||||
def get_var_config(var):
|
||||
try:
|
||||
return dict(((k, json.loads(v)) for k, v in zsh.getvalue(var).items()))
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
class Args(object):
|
||||
ext = ['shell']
|
||||
renderer_module = 'zsh_prompt'
|
||||
|
||||
@property
|
||||
def last_exit_code(self):
|
||||
return zsh.last_exit_code()
|
||||
|
@ -11,6 +21,14 @@ class Args(object):
|
|||
def last_pipe_status(self):
|
||||
return zsh.pipestatus()
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
return get_var_config('POWERLINE_CONFIG')
|
||||
|
||||
@property
|
||||
def theme_option(self):
|
||||
return get_var_config('POWERLINE_THEME_CONFIG')
|
||||
|
||||
|
||||
class Prompt(object):
|
||||
__slots__ = ('render', 'side', 'savedpsvar', 'savedps')
|
||||
|
@ -38,6 +56,6 @@ def set_prompt(powerline, psvar, side):
|
|||
|
||||
|
||||
def setup():
|
||||
powerline = Powerline(ext='shell', renderer_module='zsh_prompt', segment_info=Args())
|
||||
powerline = ShellPowerline(Args())
|
||||
set_prompt(powerline, 'PS1', 'left')
|
||||
set_prompt(powerline, 'RPS1', 'right')
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "hostname",
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
"name": "hostname"
|
||||
},
|
||||
{
|
||||
"name": "user"
|
||||
},
|
||||
{
|
||||
"name": "virtualenv",
|
||||
"before": "ⓔ "
|
||||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
|
@ -31,8 +40,7 @@
|
|||
"highlight_group": "exit_fail"
|
||||
},
|
||||
{
|
||||
"name": "branch",
|
||||
"before": " "
|
||||
"name": "branch"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "hostname",
|
||||
"before": " "
|
||||
"name": "hostname"
|
||||
},
|
||||
{
|
||||
"name": "user"
|
||||
},
|
||||
{
|
||||
"name": "virtualenv",
|
||||
"before": "ⓔ "
|
||||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"name": "branch",
|
||||
"before": " "
|
||||
"name": "branch"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"uptime": {
|
||||
"before": "⇑ "
|
||||
},
|
||||
"external_ip": {
|
||||
"before": "ⓦ "
|
||||
},
|
||||
"date": {
|
||||
"before": "⌚ "
|
||||
},
|
||||
"email_imap_alert": {
|
||||
"before": "✉ ",
|
||||
"args": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"right": [
|
||||
{
|
||||
"name": "uptime",
|
||||
"before": "⇑ ",
|
||||
"priority": 50,
|
||||
"divider_highlight_group": "background:divider"
|
||||
},
|
||||
{
|
||||
"name": "external_ip",
|
||||
"before": "ⓦ ",
|
||||
"priority": 50,
|
||||
"divider_highlight_group": "background:divider"
|
||||
},
|
||||
|
@ -35,18 +51,12 @@
|
|||
{
|
||||
"name": "date",
|
||||
"args": {"format": "%H:%M"},
|
||||
"before": "⌚ ",
|
||||
"highlight_group": ["time", "date"],
|
||||
"divider_highlight_group": "time:divider"
|
||||
},
|
||||
{
|
||||
"name": "email_imap_alert",
|
||||
"before": "✉ ",
|
||||
"priority": 10,
|
||||
"args": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hostname"
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from powerline.colorscheme import Colorscheme
|
||||
from powerline.matcher import Matcher
|
||||
from powerline.lib import underscore_to_camelcase
|
||||
|
||||
|
||||
class Powerline(object):
|
||||
def __init__(self, ext, renderer_module=None, segment_info=None, renderer_options={}):
|
||||
config_home = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
|
||||
config_path = os.path.join(config_home, 'powerline')
|
||||
plugin_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'config_files')
|
||||
self.search_paths = [config_path, plugin_path]
|
||||
sys.path[:0] = self.search_paths
|
||||
|
||||
# Load main config file
|
||||
config = self._load_json_config('config')
|
||||
self.config = config['common']
|
||||
self.config_ext = config['ext'][ext]
|
||||
|
||||
# Load and initialize colorscheme
|
||||
colorscheme_config = self._load_json_config(os.path.join('colorschemes', ext, self.config_ext['colorscheme']))
|
||||
colorscheme = Colorscheme(colorscheme_config)
|
||||
|
||||
# Load and initialize extension theme
|
||||
theme_config = self._load_theme_config(ext, self.config_ext.get('theme', 'default'))
|
||||
self.config['paths'] = [os.path.expanduser(path) for path in self.config.get('paths', [])]
|
||||
self.get_matcher = Matcher(ext, self.config['paths']).get
|
||||
theme_kwargs = {
|
||||
'ext': ext,
|
||||
'colorscheme': colorscheme,
|
||||
'common_config': self.config,
|
||||
'segment_info': segment_info,
|
||||
}
|
||||
local_themes = {}
|
||||
for key, local_theme_name in self.config_ext.get('local_themes', {}).items():
|
||||
key = self.get_matcher(key)
|
||||
local_themes[key] = {'config': self._load_theme_config(ext, local_theme_name)}
|
||||
|
||||
# Load and initialize extension renderer
|
||||
renderer_module_name = renderer_module or ext
|
||||
renderer_module_import = 'powerline.renderers.{0}'.format(renderer_module_name)
|
||||
renderer_class_name = '{0}Renderer'.format(underscore_to_camelcase(renderer_module_name))
|
||||
try:
|
||||
Renderer = getattr(importlib.import_module(renderer_module_import), renderer_class_name)
|
||||
except ImportError as e:
|
||||
sys.stderr.write('Error while importing renderer module: {0}\n'.format(e))
|
||||
sys.exit(1)
|
||||
options = {'term_truecolor': self.config.get('term_24bit_colors', False)}
|
||||
options.update(renderer_options)
|
||||
self.renderer = Renderer(theme_config, local_themes, theme_kwargs, **options)
|
||||
|
||||
def add_local_theme(self, key, config):
|
||||
'''Add local themes at runtime (e.g. during vim session).
|
||||
|
||||
Accepts key as first argument (same as keys in config.json:
|
||||
ext/*/local_themes) and configuration dictionary as the second (has
|
||||
format identical to themes/*/*.json)
|
||||
|
||||
Returns True if theme was added successfully and False if theme with
|
||||
the same matcher already exists
|
||||
'''
|
||||
key = self.get_matcher(key)
|
||||
try:
|
||||
self.renderer.add_local_theme(key, {'config': config})
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _load_theme_config(self, ext, name):
|
||||
return self._load_json_config(os.path.join('themes', ext, name))
|
||||
|
||||
def _load_json_config(self, config_file):
|
||||
config_file += '.json'
|
||||
for path in self.search_paths:
|
||||
config_file_path = os.path.join(path, config_file)
|
||||
if os.path.isfile(config_file_path):
|
||||
with open(config_file_path, 'r') as config_file_fp:
|
||||
return json.load(config_file_fp)
|
||||
raise IOError('Config file not found in search path: {0}'.format(config_file))
|
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts
|
||||
|
||||
|
||||
class IpythonPowerline(Powerline):
|
||||
def __init__(self):
|
||||
super(IpythonPowerline, self).__init__('ipython')
|
||||
|
||||
def get_config_paths(self):
|
||||
if self.path:
|
||||
return [self.path]
|
||||
else:
|
||||
return super(IpythonPowerline, self).get_config_paths()
|
||||
|
||||
def load_main_config(self):
|
||||
r = super(IpythonPowerline, self).load_main_config()
|
||||
if self.config_overrides:
|
||||
mergedicts(r, self.config_overrides)
|
||||
return r
|
||||
|
||||
def load_theme_config(self, name):
|
||||
r = super(IpythonPowerline, self).load_theme_config(name)
|
||||
if name in self.theme_overrides:
|
||||
mergedicts(r, self.theme_overrides[name])
|
||||
return r
|
|
@ -6,3 +6,12 @@ from powerline.lib.url import urllib_read, urllib_urlencode # NOQA
|
|||
def underscore_to_camelcase(string):
|
||||
'''Return a underscore_separated_string as CamelCase.'''
|
||||
return ''.join(word.capitalize() or '_' for word in string.split('_'))
|
||||
|
||||
def mergedicts(d1, d2):
|
||||
'''Recursively merge two dictionaries. First dictionary is modified in-place.
|
||||
'''
|
||||
for k in d2:
|
||||
if k in d1 and type(d1[k]) is dict and type(d2[k]) is dict:
|
||||
mergedicts(d1[k], d2[k])
|
||||
else:
|
||||
d1[k] = d2[k]
|
||||
|
|
|
@ -4,19 +4,16 @@ from importlib import import_module
|
|||
import sys
|
||||
|
||||
|
||||
class Matcher(object):
|
||||
def __init__(self, ext, path):
|
||||
self.ext = ext
|
||||
self.path = path
|
||||
|
||||
def get(self, match_name):
|
||||
def gen_matcher_getter(ext, import_paths):
|
||||
def get(match_name):
|
||||
match_module, separator, match_function = match_name.rpartition('.')
|
||||
if not separator:
|
||||
match_module = 'powerline.matchers.{0}'.format(self.ext)
|
||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
||||
match_function = match_name
|
||||
oldpath = sys.path
|
||||
sys.path = self.path + sys.path
|
||||
sys.path = import_paths + sys.path
|
||||
try:
|
||||
return getattr(import_module(match_module), match_function)
|
||||
finally:
|
||||
sys.path = oldpath
|
||||
return get
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts
|
||||
|
||||
|
||||
def mergeargs(argvalue):
|
||||
if not argvalue:
|
||||
return None
|
||||
l = argvalue
|
||||
r = dict([argvalue[0]])
|
||||
for subval in argvalue[1:]:
|
||||
mergedicts(r, dict([subval]))
|
||||
return r
|
||||
|
||||
|
||||
class ShellPowerline(Powerline):
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
self.theme_option = mergeargs(args.theme_option) or {}
|
||||
super(ShellPowerline, self).__init__(args.ext[0], args.renderer_module)
|
||||
|
||||
def get_segment_info(self):
|
||||
return self.args
|
||||
|
||||
def load_main_config(self):
|
||||
r = super(ShellPowerline, self).load_main_config()
|
||||
if self.args.config:
|
||||
mergedicts(r, mergeargs(self.args.config))
|
||||
return r
|
||||
|
||||
def load_theme_config(self, name):
|
||||
r = super(ShellPowerline, self).load_theme_config(name)
|
||||
if name in self.theme_option:
|
||||
mergedicts(r, self.theme_option[name])
|
||||
return r
|
||||
|
||||
def get_config_paths(self):
|
||||
if self.args.config_path:
|
||||
return [self.args.config_path]
|
||||
else:
|
||||
return super(ShellPowerline, self).get_config_paths()
|
|
@ -0,0 +1,72 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.bindings.vim import vim_get_func
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts
|
||||
from powerline.matcher import gen_matcher_getter
|
||||
import vim
|
||||
|
||||
|
||||
vim_exists = vim_get_func('exists', rettype=int)
|
||||
|
||||
def _override_from(config, override_varname):
|
||||
if vim_exists(override_varname):
|
||||
# FIXME vim.eval has problem with numeric types, vim.bindeval may be
|
||||
# absent (and requires converting values to python built-in types),
|
||||
# vim.eval with typed call like the one I implemented in frawor is slow.
|
||||
# Maybe eval(vime.eval('string({0})'.format(override_varname)))?
|
||||
overrides = vim.eval(override_varname)
|
||||
mergedicts(config, overrides)
|
||||
return config
|
||||
|
||||
|
||||
class VimPowerline(Powerline):
|
||||
def __init__(self):
|
||||
super(VimPowerline, self).__init__('vim')
|
||||
|
||||
def add_local_theme(self, key, config):
|
||||
'''Add local themes at runtime (during vim session).
|
||||
|
||||
Accepts key as first argument (same as keys in config.json:
|
||||
ext/*/local_themes) and configuration dictionary as the second (has
|
||||
format identical to themes/*/*.json)
|
||||
|
||||
Returns True if theme was added successfully and False if theme with
|
||||
the same matcher already exists
|
||||
'''
|
||||
key = self.get_matcher(key)
|
||||
try:
|
||||
self.renderer.add_local_theme(key, {'config': config})
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def load_main_config(self):
|
||||
return _override_from(super(VimPowerline, self).load_main_config(), 'g:powerline_config_overrides')
|
||||
|
||||
def load_theme_config(self, name):
|
||||
# Note: themes with non-[a-zA-Z0-9_] names are impossible to override
|
||||
# (though as far as I know exists() won’t throw). Won’t fix, use proper
|
||||
# theme names.
|
||||
return _override_from(super(VimPowerline, self).load_theme_config(name), 'g:powerline_theme_overrides__'+name)
|
||||
|
||||
def get_local_themes(self, local_themes):
|
||||
self.get_matcher = gen_matcher_getter(self.ext, self.import_paths)
|
||||
r = {}
|
||||
for key, local_theme_name in local_themes.items():
|
||||
key = self.get_matcher(key)
|
||||
r[key] = {'config': self.load_theme_config(local_theme_name)}
|
||||
return r
|
||||
|
||||
def get_config_paths(self):
|
||||
if vim_exists('g:powerline_config_path'):
|
||||
return [vim.eval('g:powerline_config_path')]
|
||||
else:
|
||||
return super(VimPowerline, self).get_config_paths()
|
||||
|
||||
@staticmethod
|
||||
def get_segment_info():
|
||||
return {}
|
|
@ -6,11 +6,11 @@ import sys
|
|||
import json
|
||||
|
||||
try:
|
||||
from powerline.core import Powerline
|
||||
from powerline.shell import ShellPowerline
|
||||
except ImportError:
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from powerline.core import Powerline # NOQA
|
||||
from powerline.shell import ShellPowerline # NOQA
|
||||
|
||||
def oval(s):
|
||||
if '=' not in s:
|
||||
|
@ -22,6 +22,20 @@ def oval(s):
|
|||
val = json.loads(s[idx+1:])
|
||||
return (o, val)
|
||||
|
||||
def odotval(s):
|
||||
o, val = oval(s)
|
||||
keys = o.split('.')
|
||||
if len(keys) > 1:
|
||||
r = (keys[0], {})
|
||||
rcur = r[1]
|
||||
for key in keys[1:-1]:
|
||||
rcur[key] = {}
|
||||
rcur = rcur[key]
|
||||
rcur[keys[-1]] = val
|
||||
return r
|
||||
else:
|
||||
return (o, val)
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('ext', nargs=1)
|
||||
parser.add_argument('side', nargs='?', choices=('left', 'right'))
|
||||
|
@ -29,11 +43,13 @@ parser.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
|||
parser.add_argument('-w', '--width', type=int)
|
||||
parser.add_argument('--last_exit_code', metavar='INT', type=int)
|
||||
parser.add_argument('--last_pipe_status', metavar='LIST', default='', type=lambda s: [int(status) for status in s.split()])
|
||||
parser.add_argument('-o', '--renderer_option', nargs='*', metavar='OPTION=VALUE', type=oval)
|
||||
parser.add_argument('-c', '--config', metavar='KEY.KEY=VALUE', type=odotval, action='append')
|
||||
parser.add_argument('-t', '--theme_option', metavar='THEME.KEY.KEY=VALUE', type=odotval, action='append')
|
||||
parser.add_argument('-p', '--config_path', metavar='PATH')
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
powerline = Powerline(ext=args.ext[0], renderer_module=args.renderer_module, segment_info=args, renderer_options=dict(args.renderer_option or {}))
|
||||
powerline = ShellPowerline(args)
|
||||
rendered = powerline.renderer.render(width=args.width, side=args.side)
|
||||
try:
|
||||
sys.stdout.write(rendered)
|
||||
|
|
Loading…
Reference in New Issue