diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:40:16 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:40:16 +0000 |
commit | 3f25952c13d5847d510c0cae22a8ba876638d570 (patch) | |
tree | 02f505f016ed5a1029277dcae520d5e2a75906fb /powerline/bindings/zsh | |
parent | Initial commit. (diff) | |
download | powerline-3f25952c13d5847d510c0cae22a8ba876638d570.tar.xz powerline-3f25952c13d5847d510c0cae22a8ba876638d570.zip |
Adding upstream version 2.8.3.upstream/2.8.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'powerline/bindings/zsh')
-rw-r--r-- | powerline/bindings/zsh/__init__.py | 225 | ||||
-rw-r--r-- | powerline/bindings/zsh/powerline.zsh | 216 |
2 files changed, 441 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) diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh new file mode 100644 index 0000000..ff46cb0 --- /dev/null +++ b/powerline/bindings/zsh/powerline.zsh @@ -0,0 +1,216 @@ +local _POWERLINE_SOURCED="$0:A" + +_powerline_columns_fallback() { + if which stty &>/dev/null ; then + local cols="$(stty size 2>/dev/null)" + if ! test -z "$cols" ; then + echo "${cols#* }" + return 0 + fi + fi + echo 0 + return 0 +} + +_powerline_append_precmd_function() { + if test -z "${precmd_functions[(re)$1]}" ; then + precmd_functions+=( $1 ) + fi +} + +integer -g _POWERLINE_JOBNUM=0 + +_powerline_tmux_pane() { + local -x TMUX="$_POWERLINE_TMUX" + echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %' +} + +_powerline_tmux_pane() { + local -x TMUX="$_POWERLINE_TMUX" + echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %' +} + +_powerline_init_tmux_support() { + emulate -L zsh + if test -n "$TMUX" && tmux refresh -S &>/dev/null ; then + # TMUX variable may be unset to create new tmux session inside this one + typeset -g _POWERLINE_TMUX="$TMUX" + + function -g _powerline_tmux_setenv() { + emulate -L zsh + local -x TMUX="$_POWERLINE_TMUX" + tmux setenv -g TMUX_"$1"_$(_powerline_tmux_pane) "$2" + tmux refresh -S + } + + function -g _powerline_tmux_set_pwd() { + _powerline_tmux_setenv PWD "$PWD" + } + + function -g _powerline_tmux_set_columns() { + _powerline_tmux_setenv COLUMNS "${COLUMNS:-$(_powerline_columns_fallback)}" + } + + chpwd_functions+=( _powerline_tmux_set_pwd ) + trap '_powerline_tmux_set_columns' SIGWINCH + _powerline_tmux_set_columns + _powerline_tmux_set_pwd + fi +} + +_powerline_init_modes_support() { + emulate -L zsh + + test -z "$ZSH_VERSION" && return 0 + + local -a vs + vs=( ${(s:.:)ZSH_VERSION} ) + + # Mode support requires >=zsh-4.3.11 + if (( vs[1] < 4 || (vs[1] == 4 && (vs[2] < 3 || (vs[2] == 3 && vs[3] < 11))) )) ; then + return 0 + fi + + function -g _powerline_get_main_keymap_name() { + REPLY="${${(Q)${${(z)${"$(bindkey -lL main)"}}[3]}}:-.safe}" + } + + function -g _powerline_set_true_keymap_name() { + typeset -g _POWERLINE_MODE="${1}" + local plm_bk="$(bindkey -lL ${_POWERLINE_MODE})" + if [[ $plm_bk = 'bindkey -A'* ]] ; then + _powerline_set_true_keymap_name ${(Q)${${(z)plm_bk}[3]}} + fi + } + + function -g _powerline_zle_keymap_select() { + _powerline_set_true_keymap_name $KEYMAP + zle reset-prompt + test -z "$_POWERLINE_SAVE_WIDGET" || zle $_POWERLINE_SAVE_WIDGET + } + + function -g _powerline_set_main_keymap_name() { + local REPLY + _powerline_get_main_keymap_name + _powerline_set_true_keymap_name "$REPLY" + } + + _powerline_add_widget zle-keymap-select _powerline_zle_keymap_select + _powerline_set_main_keymap_name + + if [[ "$_POWERLINE_MODE" != vi* ]] ; then + typeset -g _POWERLINE_DEFAULT_MODE="$_POWERLINE_MODE" + fi + + _powerline_append_precmd_function _powerline_set_main_keymap_name +} + +_powerline_set_jobnum() { + # If you are wondering why I am not using the same code as I use for bash + # ($(jobs|wc -l)): consider the following test: + # echo abc | less + # <C-z> + # . This way jobs will print + # [1] + done echo abc | + # suspended less -M + # ([ is in first column). You see: any line counting thingie will return + # wrong number of jobs. You need to filter the lines first. Or not use + # jobs built-in at all. + integer -g _POWERLINE_JOBNUM=${(%):-%j} +} + +_powerline_update_counter() { + zpython '_powerline.precmd()' +} + +_powerline_setup_prompt() { + emulate -L zsh + + _powerline_append_precmd_function _powerline_set_jobnum + + typeset -g VIRTUAL_ENV_DISABLE_PROMPT=1 + + if test -z "${POWERLINE_NO_ZSH_ZPYTHON}" && { zmodload libzpython || zmodload zsh/zpython } &>/dev/null ; then + _powerline_append_precmd_function _powerline_update_counter + zpython 'from powerline.bindings.zsh import setup as _powerline_setup' + zpython '_powerline_setup(globals())' + zpython 'del _powerline_setup' + powerline-reload() { + zpython 'from powerline.bindings.zsh import reload as _powerline_reload' + zpython '_powerline_reload()' + zpython 'del _powerline_reload' + } + powerline-reload-config() { + zpython 'from powerline.bindings.zsh import reload_config as _powerline_reload_config' + zpython '_powerline_reload_config()' + zpython 'del _powerline_reload_config' + } + else + if test -z "${POWERLINE_COMMAND}" ; then + typeset -g POWERLINE_COMMAND="$($POWERLINE_CONFIG_COMMAND shell command)" + fi + + local add_args='-r .zsh' + add_args+=' --last-exit-code=$?' + add_args+=' --last-pipe-status="$pipestatus"' + add_args+=' --renderer-arg="client_id=$$"' + add_args+=' --renderer-arg="shortened_path=${(%):-%~}"' + add_args+=' --jobnum=$_POWERLINE_JOBNUM' + add_args+=' --renderer-arg="mode=$_POWERLINE_MODE"' + add_args+=' --renderer-arg="default_mode=$_POWERLINE_DEFAULT_MODE"' + local new_args_2=' --renderer-arg="parser_state=${(%%):-%_}"' + new_args_2+=' --renderer-arg="local_theme=continuation"' + local add_args_3=$add_args' --renderer-arg="local_theme=select"' + local add_args_2=$add_args$new_args_2 + add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - ${ZLE_RPROMPT_INDENT:-1} ))' + local add_args_r2=$add_args$new_args_2 + typeset -g PS1='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell aboveleft '$add_args')' + typeset -g RPS1='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell right '$add_args')' + typeset -g PS2='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell left '$add_args_2')' + typeset -g RPS2='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell right '$add_args_r2')' + typeset -g PS3='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell left '$add_args_3')' + fi +} + +_powerline_add_widget() { + local widget="$1" + local function="$2" + local old_widget_command="$(zle -l -L $widget)" + if [[ "$old_widget_command" = "zle -N $widget $function" ]] ; then + return 0 + elif [[ -z "$old_widget_command" ]] ; then + zle -N $widget $function + else + local save_widget="_powerline_save_$widget" + local -i i=0 + while ! test -z "$(zle -l -L $save_widget)" ; do + save_widget="${save_widget}_$i" + (( i++ )) + done + # If widget was defined with `zle -N widget` (without `function` + # argument) then this function will be handy. + eval "function $save_widget() { emulate -L zsh; $widget \$@ }" + eval "${old_widget_command/$widget/$save_widget}" + zle -N $widget $function + typeset -g _POWERLINE_SAVE_WIDGET="$save_widget" + fi +} + +if test -z "${POWERLINE_CONFIG_COMMAND}" ; then + if which powerline-config >/dev/null 2>/dev/null ; then + typeset -g POWERLINE_CONFIG_COMMAND=powerline-config + else + typeset -g POWERLINE_CONFIG_COMMAND="${_POWERLINE_SOURCED:h:h:h:h}/scripts/powerline-config" + fi +fi + +setopt promptpercent +setopt promptsubst + +if "${POWERLINE_CONFIG_COMMAND}" shell --shell=zsh uses prompt ; then + _powerline_setup_prompt + _powerline_init_modes_support +fi +if "${POWERLINE_CONFIG_COMMAND}" shell --shell=zsh uses tmux ; then + _powerline_init_tmux_support +fi |