summaryrefslogtreecommitdiffstats
path: root/powerline/bindings/zsh/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'powerline/bindings/zsh/__init__.py')
-rw-r--r--powerline/bindings/zsh/__init__.py225
1 files changed, 225 insertions, 0 deletions
diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py
new file mode 100644
index 0000000..44f5c69
--- /dev/null
+++ b/powerline/bindings/zsh/__init__.py
@@ -0,0 +1,225 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import atexit
+
+from weakref import WeakValueDictionary, ref
+
+import zsh
+
+from powerline.shell import ShellPowerline
+from powerline.lib.overrides import parsedotval, parse_override_var
+from powerline.lib.unicode import unicode, u
+from powerline.lib.encoding import (get_preferred_output_encoding,
+ get_preferred_environment_encoding)
+from powerline.lib.dict import mergeargs
+
+
+used_powerlines = WeakValueDictionary()
+
+
+def shutdown():
+ for powerline in tuple(used_powerlines.values()):
+ powerline.shutdown()
+
+
+def get_var_config(var):
+ try:
+ val = zsh.getvalue(var)
+ if isinstance(val, dict):
+ return mergeargs([parsedotval((u(k), u(v))) for k, v in val.items()])
+ elif isinstance(val, (unicode, str, bytes)):
+ return mergeargs(parse_override_var(u(val)))
+ else:
+ return None
+ except:
+ return None
+
+
+class Args(object):
+ __slots__ = ('last_pipe_status', 'last_exit_code')
+ ext = ['shell']
+ renderer_module = '.zsh'
+
+ @property
+ def config_override(self):
+ return get_var_config('POWERLINE_CONFIG_OVERRIDES')
+
+ @property
+ def theme_override(self):
+ return get_var_config('POWERLINE_THEME_OVERRIDES')
+
+ @property
+ def config_path(self):
+ try:
+ ret = zsh.getvalue('POWERLINE_CONFIG_PATHS')
+ except IndexError:
+ return None
+ else:
+ if isinstance(ret, (unicode, str, bytes)):
+ return [
+ path
+ for path in ret.split((b':' if isinstance(ret, bytes) else ':'))
+ if path
+ ]
+ else:
+ return ret
+
+ @property
+ def jobnum(self):
+ return zsh.getvalue('_POWERLINE_JOBNUM')
+
+
+def string(s):
+ if type(s) is bytes:
+ return s.decode(get_preferred_environment_encoding(), 'replace')
+ else:
+ return str(s)
+
+
+class Environment(object):
+ @staticmethod
+ def __getitem__(key):
+ try:
+ return string(zsh.getvalue(key))
+ except IndexError as e:
+ raise KeyError(*e.args)
+
+ @staticmethod
+ def get(key, default=None):
+ try:
+ return string(zsh.getvalue(key))
+ except IndexError:
+ return default
+
+ @staticmethod
+ def __contains__(key):
+ try:
+ zsh.getvalue(key)
+ return True
+ except IndexError:
+ return False
+
+
+environ = Environment()
+
+
+if hasattr(zsh, 'expand') and zsh.expand('${:-}') == '':
+ zsh_expand = zsh.expand
+else:
+ def zsh_expand(s):
+ zsh.eval('local _POWERLINE_REPLY="' + s + '"')
+ ret = zsh.getvalue('_POWERLINE_REPLY')
+ zsh.setvalue('_POWERLINE_REPLY', None)
+ return ret
+
+
+class ZshPowerline(ShellPowerline):
+ def init(self, **kwargs):
+ super(ZshPowerline, self).init(Args(), **kwargs)
+
+ def precmd(self):
+ self.args.last_pipe_status = zsh.pipestatus()
+ self.args.last_exit_code = zsh.last_exit_code()
+
+ def do_setup(self, zsh_globals):
+ set_prompt(self, 'PS1', 'left', None, above=True)
+ set_prompt(self, 'RPS1', 'right', None)
+ set_prompt(self, 'PS2', 'left', 'continuation')
+ set_prompt(self, 'RPS2', 'right', 'continuation')
+ set_prompt(self, 'PS3', 'left', 'select')
+ used_powerlines[id(self)] = self
+ zsh_globals['_powerline'] = self
+
+
+class Prompt(object):
+ __slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme', 'above', '__weakref__')
+
+ def __init__(self, powerline, side, theme, savedpsvar=None, savedps=None, above=False):
+ self.powerline = powerline
+ self.side = side
+ self.above = above
+ self.savedpsvar = savedpsvar
+ self.savedps = savedps
+ self.args = powerline.args
+ self.theme = theme
+
+ def __str__(self):
+ parser_state = u(zsh_expand('${(%):-%_}'))
+ shortened_path = u(zsh_expand('${(%):-%~}'))
+ try:
+ mode = u(zsh.getvalue('_POWERLINE_MODE'))
+ except IndexError:
+ mode = None
+ try:
+ default_mode = u(zsh.getvalue('_POWERLINE_DEFAULT_MODE'))
+ except IndexError:
+ default_mode = None
+ segment_info = {
+ 'args': self.args,
+ 'environ': environ,
+ 'client_id': 1,
+ 'local_theme': self.theme,
+ 'parser_state': parser_state,
+ 'shortened_path': shortened_path,
+ 'mode': mode,
+ 'default_mode': default_mode,
+ }
+ try:
+ zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT')
+ except IndexError:
+ zle_rprompt_indent = 1
+ r = ''
+ if self.above:
+ for line in self.powerline.render_above_lines(
+ width=zsh.columns() - zle_rprompt_indent,
+ segment_info=segment_info,
+ ):
+ if line:
+ r += line + '\n'
+ r += self.powerline.render(
+ width=zsh.columns(),
+ side=self.side,
+ segment_info=segment_info,
+ mode=mode,
+ )
+ if type(r) is not str:
+ if type(r) is bytes:
+ return r.decode(get_preferred_output_encoding(), 'replace')
+ else:
+ return r.encode(get_preferred_output_encoding(), 'replace')
+ return r
+
+ def __del__(self):
+ if self.savedps:
+ zsh.setvalue(self.savedpsvar, self.savedps)
+ self.powerline.shutdown()
+
+
+def set_prompt(powerline, psvar, side, theme, above=False):
+ try:
+ savedps = zsh.getvalue(psvar)
+ except IndexError:
+ savedps = None
+ zpyvar = 'ZPYTHON_POWERLINE_' + psvar
+ prompt = Prompt(powerline, side, theme, psvar, savedps, above)
+ zsh.setvalue(zpyvar, None)
+ zsh.set_special_string(zpyvar, prompt)
+ zsh.setvalue(psvar, '${' + zpyvar + '}')
+ return ref(prompt)
+
+
+def reload():
+ for powerline in tuple(used_powerlines.values()):
+ powerline.reload()
+
+
+def reload_config():
+ for powerline in used_powerlines.values():
+ powerline.create_renderer(load_main=True, load_colors=True, load_colorscheme=True, load_theme=True)
+
+
+def setup(zsh_globals):
+ powerline = ZshPowerline()
+ powerline.setup(zsh_globals)
+ atexit.register(shutdown)