mirror of
https://github.com/powerline/powerline.git
synced 2025-07-24 06:15:41 +02:00
Merge pull request #893 from ZyX-I/multiline-prompt
Multiline prompt support Fixes #462
This commit is contained in:
commit
35522b1511
@ -305,8 +305,22 @@ Themes
|
|||||||
step 2 is obviously avoided.
|
step 2 is obviously avoided.
|
||||||
|
|
||||||
``segments``
|
``segments``
|
||||||
A dict with a ``left`` and a ``right`` list, consisting of segment
|
A dict with a ``left`` and a ``right`` lists, consisting of segment
|
||||||
dicts. Each segment has the following options:
|
dictionaries. Shell themes may also contain ``above`` list of dictionaries.
|
||||||
|
Each item in ``above`` list may have ``left`` and ``right`` keys like this
|
||||||
|
dictionary, but no ``above`` key.
|
||||||
|
|
||||||
|
.. _config-themes-above:
|
||||||
|
|
||||||
|
``above`` list is used for multiline shell configurations.
|
||||||
|
|
||||||
|
``left`` and ``right`` lists are used for segments that should be put on the
|
||||||
|
left or right side in the output. Actual mechanizm of putting segments on
|
||||||
|
the left or the right depends on used renderer, but most renderers require
|
||||||
|
one to specify segment with :ref:`width <config-themes-seg-width>` ``auto``
|
||||||
|
on either side to make generated line fill all of the available width.
|
||||||
|
|
||||||
|
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``
|
||||||
@ -368,6 +382,8 @@ Themes
|
|||||||
right (``r``).
|
right (``r``).
|
||||||
|
|
||||||
``width``
|
``width``
|
||||||
|
.. _config-themes-seg-width:
|
||||||
|
|
||||||
Enforces a specific width for this segment.
|
Enforces a specific width for this segment.
|
||||||
|
|
||||||
This segment will work as a spacer if the width is set to ``auto``.
|
This segment will work as a spacer if the width is set to ``auto``.
|
||||||
@ -566,6 +582,15 @@ configuration script was sourced (in fish case: after ``powerline-setup``
|
|||||||
function was run). To disable specific feature support set one of these
|
function was run). To disable specific feature support set one of these
|
||||||
variables to some non-empty value.
|
variables to some non-empty value.
|
||||||
|
|
||||||
|
If you do not want to disable prompt in shell, but yet do not want to launch
|
||||||
|
python twice to get :ref:`above <config-themes-above>` lines you do not use in
|
||||||
|
tcsh you should set ``$POWERLINE_NO_TCSH_ABOVE`` or
|
||||||
|
``$POWERLINE_NO_SHELL_ABOVE`` variable.
|
||||||
|
|
||||||
|
If you do not want to see additional space which is added to the right prompt in
|
||||||
|
fish in order to support multiline prompt you should set
|
||||||
|
``$POWERLINE_NO_FISH_ABOVE`` or ``$POWERLINE_NO_SHELL_ABOVE`` variables.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Most supported shells’ configuration scripts check for additional
|
Most supported shells’ configuration scripts check for additional
|
||||||
|
@ -413,6 +413,25 @@ class Powerline(object):
|
|||||||
pass
|
pass
|
||||||
return FailedUnicode(safe_unicode(e))
|
return FailedUnicode(safe_unicode(e))
|
||||||
|
|
||||||
|
def render_above_lines(self, *args, **kwargs):
|
||||||
|
'''Like .render(), but for ``self.renderer.render_above_lines()``
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
self.update_renderer()
|
||||||
|
for line in self.renderer.render_above_lines(*args, **kwargs):
|
||||||
|
yield line
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
self.exception('Failed to render: {0}', str(e))
|
||||||
|
except Exception as e:
|
||||||
|
# Updates e variable to new value, masking previous one.
|
||||||
|
# Normally it is the same exception (due to raise in case pl is
|
||||||
|
# unset), but it may also show error in logger. Note that latter
|
||||||
|
# is not logged by logger for obvious reasons, thus this also
|
||||||
|
# prevents us from seeing logger traceback.
|
||||||
|
pass
|
||||||
|
yield FailedUnicode(safe_unicode(e))
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
'''Shut down all background threads. Must be run only prior to exiting
|
'''Shut down all background threads. Must be run only prior to exiting
|
||||||
current application.
|
current application.
|
||||||
|
@ -28,9 +28,15 @@ _powerline_init_tmux_support() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_run_powerline() {
|
||||||
|
# Arguments: side, last_exit_code, jobnum
|
||||||
|
$POWERLINE_COMMAND shell $1 -w $COLUMNS -r bash_prompt --last_exit_code=$2 --jobnum=$3
|
||||||
|
}
|
||||||
|
|
||||||
_powerline_prompt() {
|
_powerline_prompt() {
|
||||||
local last_exit_code=$?
|
local last_exit_code=$?
|
||||||
PS1="$($POWERLINE_COMMAND shell left -r bash_prompt --last_exit_code=$last_exit_code --jobnum="$(jobs -p|wc -l)")"
|
local jobnum="$(jobs -p|wc -l)"
|
||||||
|
PS1="$(_run_powerline aboveleft $last_exit_code $jobnum)"
|
||||||
_powerline_tmux_set_pwd
|
_powerline_tmux_set_pwd
|
||||||
return $last_exit_code
|
return $last_exit_code
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,35 @@ function powerline-setup
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
function --on-variable POWERLINE_COMMAND _powerline_update
|
function --on-variable POWERLINE_COMMAND _powerline_update
|
||||||
set -l addargs "--last_exit_code=\$status --last_pipe_status=\$status --jobnum=(jobs -p | wc -l)"
|
set -l addargs "--last_exit_code=\$status"
|
||||||
|
set -l addargs "$addargs --last_pipe_status=\$status"
|
||||||
|
set -l addargs "$addargs --jobnum=(jobs -p | wc -l)"
|
||||||
|
set -l addargs "$addargs --width=\$_POWERLINE_COLUMNS"
|
||||||
|
set -l promptside
|
||||||
|
set -l rpromptpast
|
||||||
|
set -l columnsexpr
|
||||||
|
if test -z "$POWERLINE_NO_FISH_ABOVE$POWERLINE_NO_SHELL_ABOVE"
|
||||||
|
set promptside aboveleft
|
||||||
|
set rpromptpast 'echo -n " "'
|
||||||
|
set columnsexpr '(math $COLUMNS - 1)'
|
||||||
|
else
|
||||||
|
set promptside left
|
||||||
|
set rpromptpast
|
||||||
|
set columnsexpr '$COLUMNS'
|
||||||
|
end
|
||||||
eval "
|
eval "
|
||||||
function fish_prompt
|
function fish_prompt
|
||||||
$POWERLINE_COMMAND shell left $addargs
|
$POWERLINE_COMMAND shell $promptside $addargs
|
||||||
end
|
end
|
||||||
function fish_right_prompt
|
function fish_right_prompt
|
||||||
$POWERLINE_COMMAND shell right $addargs
|
$POWERLINE_COMMAND shell right $addargs
|
||||||
|
$rpromptpast
|
||||||
|
end
|
||||||
|
function --on-signal WINCH _powerline_set_columns
|
||||||
|
set -g _POWERLINE_COLUMNS $columnsexpr
|
||||||
end
|
end
|
||||||
"
|
"
|
||||||
|
_powerline_set_columns
|
||||||
end
|
end
|
||||||
_powerline_update
|
_powerline_update
|
||||||
end
|
end
|
||||||
|
@ -19,7 +19,13 @@ if ! ( $?POWERLINE_NO_TCSH_TMUX_SUPPORT || $?POWERLINE_NO_SHELL_TMUX_SUPPORT ) t
|
|||||||
alias cwdcmd "`alias cwdcmd` ; _powerline_tmux_set_pwd"
|
alias cwdcmd "`alias cwdcmd` ; _powerline_tmux_set_pwd"
|
||||||
endif
|
endif
|
||||||
if ! ( $?POWERLINE_NO_TCSH_PROMPT || $?POWERLINE_NO_SHELL_PROMPT ) then
|
if ! ( $?POWERLINE_NO_TCSH_PROMPT || $?POWERLINE_NO_SHELL_PROMPT ) then
|
||||||
alias _powerline_set_prompt 'set prompt="`$POWERLINE_COMMAND shell left -r tcsh_prompt --last_exit_code=$?`"'
|
if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then
|
||||||
alias _powerline_set_rprompt 'set rprompt="`$POWERLINE_COMMAND shell right -r tcsh_prompt --last_exit_code=$?` "'
|
alias _powerline_above true
|
||||||
alias precmd "`alias precmd` ; _powerline_set_prompt ; _powerline_set_rprompt"
|
else
|
||||||
|
alias _powerline_above '$POWERLINE_COMMAND shell above --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS'
|
||||||
|
endif
|
||||||
|
alias _powerline_set_prompt 'set prompt="`$POWERLINE_COMMAND shell left -r tcsh_prompt --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS`"'
|
||||||
|
alias _powerline_set_rprompt 'set rprompt="`$POWERLINE_COMMAND shell right -r tcsh_prompt --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS` "'
|
||||||
|
alias _powerline_set_columns 'set POWERLINE_COLUMNS=`stty size|cut -d" " -f2` ; set POWERLINE_COLUMNS=`expr $POWERLINE_COLUMNS - 2`'
|
||||||
|
alias precmd 'set POWERLINE_STATUS=$? ; '"`alias precmd`"' ; _powerline_set_columns ; _powerline_above ; _powerline_set_prompt ; _powerline_set_rprompt'
|
||||||
endif
|
endif
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||||
|
|
||||||
import zsh
|
import zsh
|
||||||
import atexit
|
import atexit
|
||||||
from powerline.shell import ShellPowerline
|
from powerline.shell import ShellPowerline
|
||||||
@ -89,21 +91,22 @@ class ZshPowerline(ShellPowerline):
|
|||||||
def precmd(self):
|
def precmd(self):
|
||||||
self.args.last_pipe_status = zsh.pipestatus()
|
self.args.last_pipe_status = zsh.pipestatus()
|
||||||
self.args.last_exit_code = zsh.last_exit_code()
|
self.args.last_exit_code = zsh.last_exit_code()
|
||||||
zsh.eval('_POWERLINE_PARSER_STATE="${(%):-%_}"')
|
|
||||||
|
|
||||||
|
|
||||||
class Prompt(object):
|
class Prompt(object):
|
||||||
__slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme')
|
__slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme', 'above')
|
||||||
|
|
||||||
def __init__(self, powerline, side, theme, savedpsvar=None, savedps=None):
|
def __init__(self, powerline, side, theme, savedpsvar=None, savedps=None, above=False):
|
||||||
self.powerline = powerline
|
self.powerline = powerline
|
||||||
self.side = side
|
self.side = side
|
||||||
|
self.above = above
|
||||||
self.savedpsvar = savedpsvar
|
self.savedpsvar = savedpsvar
|
||||||
self.savedps = savedps
|
self.savedps = savedps
|
||||||
self.args = powerline.args
|
self.args = powerline.args
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
zsh.eval('_POWERLINE_PARSER_STATE="${(%):-%_}"')
|
||||||
segment_info = {
|
segment_info = {
|
||||||
'args': self.args,
|
'args': self.args,
|
||||||
'environ': environ,
|
'environ': environ,
|
||||||
@ -111,7 +114,14 @@ class Prompt(object):
|
|||||||
'local_theme': self.theme,
|
'local_theme': self.theme,
|
||||||
'parser_state': zsh.getvalue('_POWERLINE_PARSER_STATE'),
|
'parser_state': zsh.getvalue('_POWERLINE_PARSER_STATE'),
|
||||||
}
|
}
|
||||||
r = self.powerline.render(
|
r = ''
|
||||||
|
if self.above:
|
||||||
|
for line in self.powerline.render_above_lines(
|
||||||
|
width=zsh.columns() - 1,
|
||||||
|
segment_info=segment_info,
|
||||||
|
):
|
||||||
|
r += line + '\n'
|
||||||
|
r += self.powerline.render(
|
||||||
width=zsh.columns(),
|
width=zsh.columns(),
|
||||||
side=self.side,
|
side=self.side,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
@ -131,13 +141,13 @@ class Prompt(object):
|
|||||||
self.powerline.shutdown()
|
self.powerline.shutdown()
|
||||||
|
|
||||||
|
|
||||||
def set_prompt(powerline, psvar, side, theme):
|
def set_prompt(powerline, psvar, side, theme, above=False):
|
||||||
try:
|
try:
|
||||||
savedps = zsh.getvalue(psvar)
|
savedps = zsh.getvalue(psvar)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
savedps = None
|
savedps = None
|
||||||
zpyvar = 'ZPYTHON_POWERLINE_' + psvar
|
zpyvar = 'ZPYTHON_POWERLINE_' + psvar
|
||||||
prompt = Prompt(powerline, side, theme, psvar, savedps)
|
prompt = Prompt(powerline, side, theme, psvar, savedps, above)
|
||||||
zsh.set_special_string(zpyvar, prompt)
|
zsh.set_special_string(zpyvar, prompt)
|
||||||
zsh.setvalue(psvar, '${' + zpyvar + '}')
|
zsh.setvalue(psvar, '${' + zpyvar + '}')
|
||||||
|
|
||||||
@ -146,7 +156,7 @@ def setup():
|
|||||||
powerline = ZshPowerline(Args())
|
powerline = ZshPowerline(Args())
|
||||||
used_powerlines.append(powerline)
|
used_powerlines.append(powerline)
|
||||||
used_powerlines.append(powerline)
|
used_powerlines.append(powerline)
|
||||||
set_prompt(powerline, 'PS1', 'left', None)
|
set_prompt(powerline, 'PS1', 'left', None, above=True)
|
||||||
set_prompt(powerline, 'RPS1', 'right', None)
|
set_prompt(powerline, 'RPS1', 'right', None)
|
||||||
set_prompt(powerline, 'PS2', 'left', 'continuation')
|
set_prompt(powerline, 'PS2', 'left', 'continuation')
|
||||||
set_prompt(powerline, 'RPS2', 'right', 'continuation')
|
set_prompt(powerline, 'RPS2', 'right', 'continuation')
|
||||||
|
@ -111,21 +111,27 @@ _powerline_setup_prompt() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
precmd_functions+=( _powerline_set_jobnum )
|
precmd_functions+=( _powerline_set_jobnum )
|
||||||
if zmodload libzpython &>/dev/null || zmodload zsh/zpython &>/dev/null ; then
|
if test -z "${POWERLINE_NO_ZSH_ZPYTHON}" && { zmodload libzpython || zmodload zsh/zpython } &>/dev/null ; then
|
||||||
precmd_functions+=( _powerline_update_counter )
|
precmd_functions+=( _powerline_update_counter )
|
||||||
zpython 'from powerline.bindings.zsh import setup as _powerline_setup'
|
zpython 'from powerline.bindings.zsh import setup as _powerline_setup'
|
||||||
zpython '_powerline = _powerline_setup()'
|
zpython '_powerline = _powerline_setup()'
|
||||||
zpython 'del _powerline_setup'
|
zpython 'del _powerline_setup'
|
||||||
else
|
else
|
||||||
local add_args='--last_exit_code=$? --last_pipe_status="$pipestatus"'
|
local add_args='--last_exit_code=$?'
|
||||||
|
add_args+=' --last_pipe_status="$pipestatus"'
|
||||||
add_args+=' --renderer_arg="client_id=$$"'
|
add_args+=' --renderer_arg="client_id=$$"'
|
||||||
add_args+=' --jobnum=$_POWERLINE_JOBNUM'
|
add_args+=' --jobnum=$_POWERLINE_JOBNUM'
|
||||||
local add_args_2=$add_args' -R parser_state=${(%%):-%_} -R local_theme=continuation'
|
local new_args_2=' -R parser_state=${(%%):-%_}'
|
||||||
PS1='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args')'
|
new_args_2+=' -R local_theme=continuation'
|
||||||
|
local add_args_3=$add_args' -R local_theme=select'
|
||||||
|
local add_args_2=$add_args$new_args_2
|
||||||
|
add_args+=' --width=$(( COLUMNS - 1 ))'
|
||||||
|
local add_args_r2=$add_args$new_args_2
|
||||||
|
PS1='$($POWERLINE_COMMAND shell aboveleft -r zsh_prompt '$add_args')'
|
||||||
RPS1='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args')'
|
RPS1='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args')'
|
||||||
PS2='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args_2')'
|
PS2='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args_2')'
|
||||||
RPS2='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args_2')'
|
RPS2='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args_r2')'
|
||||||
PS3='$($POWERLINE_COMMAND shell left -r zsh_prompt -R local_theme=select '$add_args')'
|
PS3='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args_3')'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,25 +73,31 @@ class DelayedEchoErr(EchoErr):
|
|||||||
|
|
||||||
class Spec(object):
|
class Spec(object):
|
||||||
def __init__(self, **keys):
|
def __init__(self, **keys):
|
||||||
new_keys = {}
|
self.specs = []
|
||||||
self.specs = list(keys.values())
|
self.keys = {}
|
||||||
for k, v in keys.items():
|
|
||||||
new_keys[k] = len(self.specs)
|
|
||||||
self.specs.append(v)
|
|
||||||
self.keys = new_keys
|
|
||||||
self.checks = []
|
self.checks = []
|
||||||
self.cmsg = ''
|
self.cmsg = ''
|
||||||
self.isoptional = False
|
self.isoptional = False
|
||||||
self.uspecs = []
|
self.uspecs = []
|
||||||
self.ufailmsg = lambda key: 'found unknown key: {0}'.format(key)
|
self.ufailmsg = lambda key: 'found unknown key: {0}'.format(key)
|
||||||
if keys:
|
self.did_type = False
|
||||||
|
self.update(**keys)
|
||||||
|
|
||||||
|
def update(self, **keys):
|
||||||
|
for k, v in keys.items():
|
||||||
|
self.keys[k] = len(self.specs)
|
||||||
|
self.specs.append(v)
|
||||||
|
if self.keys and not self.did_type:
|
||||||
self.type(dict)
|
self.type(dict)
|
||||||
|
self.did_type = True
|
||||||
|
return self
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return self.__class__().update(self.__dict__)
|
return self.__class__()._update(self.__dict__)
|
||||||
|
|
||||||
def update(self, d):
|
def _update(self, d):
|
||||||
self.__dict__.update(d)
|
self.__dict__.update(d)
|
||||||
|
self.keys = copy(self.keys)
|
||||||
self.checks = copy(self.checks)
|
self.checks = copy(self.checks)
|
||||||
self.uspecs = copy(self.uspecs)
|
self.uspecs = copy(self.uspecs)
|
||||||
self.specs = [spec.copy() for spec in self.specs]
|
self.specs = [spec.copy() for spec in self.specs]
|
||||||
@ -1005,6 +1011,13 @@ segments_spec = Spec().optional().list(
|
|||||||
lambda value: 'it is recommended that divider highlight group names end with ":divider"').optional(),
|
lambda value: 'it is recommended that divider highlight group names end with ":divider"').optional(),
|
||||||
).func(check_full_segment_data),
|
).func(check_full_segment_data),
|
||||||
).copy
|
).copy
|
||||||
|
segdict_spec=Spec(
|
||||||
|
left=segments_spec().context_message('Error while loading segments from left side (key {key})'),
|
||||||
|
right=segments_spec().context_message('Error while loading segments from right side (key {key})'),
|
||||||
|
).func(
|
||||||
|
lambda value, *args: (True, True, not (('left' in value) or ('right' in value))),
|
||||||
|
lambda value: 'segments dictionary must contain either left, right or both keys'
|
||||||
|
).context_message('Error while loading segments (key {key})').copy
|
||||||
theme_spec = (Spec(
|
theme_spec = (Spec(
|
||||||
default_module=segment_module_spec(),
|
default_module=segment_module_spec(),
|
||||||
segment_data=Spec().unknown_spec(
|
segment_data=Spec().unknown_spec(
|
||||||
@ -1016,13 +1029,7 @@ theme_spec = (Spec(
|
|||||||
contents=Spec().type(unicode).optional(),
|
contents=Spec().type(unicode).optional(),
|
||||||
),
|
),
|
||||||
).optional().context_message('Error while loading segment data (key {key})'),
|
).optional().context_message('Error while loading segment data (key {key})'),
|
||||||
segments=Spec(
|
segments=segdict_spec().update(above=Spec().list(segdict_spec()).optional()),
|
||||||
left=segments_spec().context_message('Error while loading segments from left side (key {key})'),
|
|
||||||
right=segments_spec().context_message('Error while loading segments from right side (key {key})'),
|
|
||||||
).func(
|
|
||||||
lambda value, *args: (True, True, not (('left' in value) or ('right' in value))),
|
|
||||||
lambda value: 'segments dictionary must contain either left, right or both keys'
|
|
||||||
).context_message('Error while loading segments (key {key})'),
|
|
||||||
).context_message('Error while loading theme'))
|
).context_message('Error while loading theme'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +175,20 @@ class Renderer(object):
|
|||||||
r['getcwd'] = lambda: r['environ']['PWD']
|
r['getcwd'] = lambda: r['environ']['PWD']
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def render(self, mode=None, width=None, side=None, output_raw=False, segment_info=None, matcher_info=None):
|
def render_above_lines(self, **kwargs):
|
||||||
|
'''Render all segments in the {theme}/segments/above list
|
||||||
|
|
||||||
|
Rendering happens in the reversed order. Parameters are the same as in
|
||||||
|
.render() method.
|
||||||
|
|
||||||
|
:yield: rendered line.
|
||||||
|
'''
|
||||||
|
|
||||||
|
theme = self.get_theme(kwargs.get('matcher_info', None))
|
||||||
|
for line in range(theme.get_line_number() - 1, 0, -1):
|
||||||
|
yield self.render(side=None, line=line, **kwargs)
|
||||||
|
|
||||||
|
def render(self, mode=None, width=None, side=None, line=0, output_raw=False, segment_info=None, matcher_info=None):
|
||||||
'''Render all segments.
|
'''Render all segments.
|
||||||
|
|
||||||
When a width is provided, low-priority segments are dropped one at
|
When a width is provided, low-priority segments are dropped one at
|
||||||
@ -193,6 +206,9 @@ class Renderer(object):
|
|||||||
:param str side:
|
:param str side:
|
||||||
One of ``left``, ``right``. Determines which side will be rendered.
|
One of ``left``, ``right``. Determines which side will be rendered.
|
||||||
If not present all sides are rendered.
|
If not present all sides are rendered.
|
||||||
|
:param int line:
|
||||||
|
Line number for which segments should be obtained. Is counted from
|
||||||
|
zero (botmost line).
|
||||||
:param bool output_raw:
|
:param bool output_raw:
|
||||||
Changes the output: if this parameter is ``True`` then in place of
|
Changes the output: if this parameter is ``True`` then in place of
|
||||||
one string this method outputs a pair ``(colored_string,
|
one string this method outputs a pair ``(colored_string,
|
||||||
@ -203,7 +219,7 @@ class Renderer(object):
|
|||||||
Matcher information. Is processed in ``.get_theme()`` method.
|
Matcher information. Is processed in ``.get_theme()`` method.
|
||||||
'''
|
'''
|
||||||
theme = self.get_theme(matcher_info)
|
theme = self.get_theme(matcher_info)
|
||||||
segments = theme.get_segments(side, self.get_segment_info(segment_info, mode))
|
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
||||||
|
|
||||||
# Handle excluded/included segments for the current mode
|
# Handle excluded/included segments for the current mode
|
||||||
segments = [self._get_highlighting(segment, mode) for segment in segments
|
segments = [self._get_highlighting(segment, mode) for segment in segments
|
||||||
|
@ -51,7 +51,7 @@ def get_argparser(parser=None, *args, **kwargs):
|
|||||||
parser = argparse.ArgumentParser
|
parser = argparse.ArgumentParser
|
||||||
p = parser(*args, **kwargs)
|
p = parser(*args, **kwargs)
|
||||||
p.add_argument('ext', nargs=1)
|
p.add_argument('ext', nargs=1)
|
||||||
p.add_argument('side', nargs='?', choices=('left', 'right'))
|
p.add_argument('side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'))
|
||||||
p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
||||||
p.add_argument('-w', '--width', type=int)
|
p.add_argument('-w', '--width', type=int)
|
||||||
p.add_argument('--last_exit_code', metavar='INT', type=int)
|
p.add_argument('--last_exit_code', metavar='INT', type=int)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from powerline.segment import gen_segment_getter
|
from powerline.segment import gen_segment_getter
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
def requires_segment_info(func):
|
def requires_segment_info(func):
|
||||||
@ -9,6 +10,13 @@ def requires_segment_info(func):
|
|||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
def new_empty_segment_line():
|
||||||
|
return {
|
||||||
|
'left': [],
|
||||||
|
'right': []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Theme(object):
|
class Theme(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
ext,
|
ext,
|
||||||
@ -20,10 +28,7 @@ class Theme(object):
|
|||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
||||||
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
||||||
self.segments = {
|
self.segments = []
|
||||||
'left': [],
|
|
||||||
'right': [],
|
|
||||||
}
|
|
||||||
self.EMPTY_SEGMENT = {
|
self.EMPTY_SEGMENT = {
|
||||||
'contents': None,
|
'contents': None,
|
||||||
'highlight': {'fg': False, 'bg': False, 'attr': 0}
|
'highlight': {'fg': False, 'bg': False, 'attr': 0}
|
||||||
@ -33,25 +38,29 @@ class Theme(object):
|
|||||||
if top_theme_config:
|
if top_theme_config:
|
||||||
theme_configs.append(top_theme_config)
|
theme_configs.append(top_theme_config)
|
||||||
get_segment = gen_segment_getter(pl, ext, common_config['paths'], theme_configs, theme_config.get('default_module'))
|
get_segment = gen_segment_getter(pl, ext, common_config['paths'], theme_configs, theme_config.get('default_module'))
|
||||||
for side in ['left', 'right']:
|
for segdict in itertools.chain((theme_config['segments'],),
|
||||||
for segment in theme_config['segments'].get(side, []):
|
theme_config['segments'].get('above', ())):
|
||||||
segment = get_segment(segment, side)
|
self.segments.append(new_empty_segment_line())
|
||||||
if not run_once:
|
for side in ['left', 'right']:
|
||||||
if segment['startup']:
|
for segment in segdict.get(side, []):
|
||||||
try:
|
segment = get_segment(segment, side)
|
||||||
segment['startup'](pl, shutdown_event)
|
if not run_once:
|
||||||
except Exception as e:
|
if segment['startup']:
|
||||||
pl.error('Exception during {0} startup: {1}', segment['name'], str(e))
|
try:
|
||||||
continue
|
segment['startup'](pl, shutdown_event)
|
||||||
self.segments[side].append(segment)
|
except Exception as e:
|
||||||
|
pl.error('Exception during {0} startup: {1}', segment['name'], str(e))
|
||||||
|
continue
|
||||||
|
self.segments[-1][side].append(segment)
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
for segments in self.segments.values():
|
for line in self.segments:
|
||||||
for segment in segments:
|
for segments in line.values():
|
||||||
try:
|
for segment in segments:
|
||||||
segment['shutdown']()
|
try:
|
||||||
except TypeError:
|
segment['shutdown']()
|
||||||
pass
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def get_divider(self, side='left', type='soft'):
|
def get_divider(self, side='left', type='soft'):
|
||||||
'''Return segment divider.'''
|
'''Return segment divider.'''
|
||||||
@ -60,15 +69,22 @@ class Theme(object):
|
|||||||
def get_spaces(self):
|
def get_spaces(self):
|
||||||
return self.spaces
|
return self.spaces
|
||||||
|
|
||||||
def get_segments(self, side=None, segment_info=None):
|
def get_line_number(self):
|
||||||
|
return len(self.segments)
|
||||||
|
|
||||||
|
def get_segments(self, side=None, line=0, segment_info=None):
|
||||||
'''Return all segments.
|
'''Return all segments.
|
||||||
|
|
||||||
Function segments are called, and all segments get their before/after
|
Function segments are called, and all segments get their before/after
|
||||||
and ljust/rjust properties applied.
|
and ljust/rjust properties applied.
|
||||||
|
|
||||||
|
:param int line:
|
||||||
|
Line number for which segments should be obtained. Is counted from
|
||||||
|
zero (botmost line).
|
||||||
'''
|
'''
|
||||||
for side in [side] if side else ['left', 'right']:
|
for side in [side] if side else ['left', 'right']:
|
||||||
parsed_segments = []
|
parsed_segments = []
|
||||||
for segment in self.segments[side]:
|
for segment in self.segments[line][side]:
|
||||||
if segment['type'] == 'function':
|
if segment['type'] == 'function':
|
||||||
self.pl.prefix = segment['name']
|
self.pl.prefix = segment['name']
|
||||||
try:
|
try:
|
||||||
|
@ -10,6 +10,12 @@ except ImportError:
|
|||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
|
||||||
from powerline.shell import ShellPowerline, get_argparser, finish_args # NOQA
|
from powerline.shell import ShellPowerline, get_argparser, finish_args # NOQA
|
||||||
|
|
||||||
|
def write(output):
|
||||||
|
try:
|
||||||
|
sys.stdout.write(output)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
sys.stdout.write(output.encode('utf-8'))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = get_argparser(description=__doc__).parse_args()
|
args = get_argparser(description=__doc__).parse_args()
|
||||||
finish_args(args)
|
finish_args(args)
|
||||||
@ -17,13 +23,21 @@ if __name__ == '__main__':
|
|||||||
segment_info = {'args': args, 'environ': os.environ}
|
segment_info = {'args': args, 'environ': os.environ}
|
||||||
if args.renderer_arg:
|
if args.renderer_arg:
|
||||||
segment_info.update(args.renderer_arg)
|
segment_info.update(args.renderer_arg)
|
||||||
rendered = powerline.render(
|
if args.side.startswith('above'):
|
||||||
width=args.width,
|
for line in powerline.render_above_lines(
|
||||||
side=args.side,
|
width=args.width,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
mode=os.environ.get('_POWERLINE_MODE'),
|
mode=os.environ.get('_POWERLINE_MODE'),
|
||||||
)
|
):
|
||||||
try:
|
write(line)
|
||||||
sys.stdout.write(rendered)
|
sys.stdout.write('\n')
|
||||||
except UnicodeEncodeError:
|
args.side = args.side[len('above'):]
|
||||||
sys.stdout.write(rendered.encode('utf-8'))
|
|
||||||
|
if args.side:
|
||||||
|
rendered = powerline.render(
|
||||||
|
width=args.width,
|
||||||
|
side=args.side,
|
||||||
|
segment_info=segment_info,
|
||||||
|
mode=os.environ.get('_POWERLINE_MODE'),
|
||||||
|
)
|
||||||
|
write(rendered)
|
||||||
|
@ -4,6 +4,7 @@ from powerline.renderer import Renderer
|
|||||||
from powerline.lib.config import ConfigLoader
|
from powerline.lib.config import ConfigLoader
|
||||||
from powerline import Powerline
|
from powerline import Powerline
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from time import sleep
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
@ -96,6 +97,15 @@ class SimpleRenderer(Renderer):
|
|||||||
return '<{fg} {bg} {attr}>'.format(fg=fg and fg[0], bg=bg and bg[0], attr=attr)
|
return '<{fg} {bg} {attr}>'.format(fg=fg and fg[0], bg=bg and bg[0], attr=attr)
|
||||||
|
|
||||||
|
|
||||||
|
class EvenSimplerRenderer(Renderer):
|
||||||
|
def hlstyle(self, fg=None, bg=None, attr=None):
|
||||||
|
return '{{{fg}{bg}{attr}}}'.format(
|
||||||
|
fg=fg and fg[0] or '-',
|
||||||
|
bg=bg and bg[0] or '-',
|
||||||
|
attr=attr if attr else '',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPowerline(Powerline):
|
class TestPowerline(Powerline):
|
||||||
_created = False
|
_created = False
|
||||||
|
|
||||||
@ -111,7 +121,12 @@ renderer = SimpleRenderer
|
|||||||
|
|
||||||
|
|
||||||
def get_powerline(**kwargs):
|
def get_powerline(**kwargs):
|
||||||
|
global renderer
|
||||||
watcher = Watcher()
|
watcher = Watcher()
|
||||||
|
if kwargs.pop('simpler_renderer', False):
|
||||||
|
renderer = EvenSimplerRenderer
|
||||||
|
else:
|
||||||
|
renderer = SimpleRenderer
|
||||||
pl = TestPowerline(
|
pl = TestPowerline(
|
||||||
ext='test',
|
ext='test',
|
||||||
renderer_module='tests.lib.config_mock',
|
renderer_module='tests.lib.config_mock',
|
||||||
@ -138,3 +153,11 @@ def swap_attributes(cfg_container, powerline_module, replaces):
|
|||||||
setattr(powerline_module, attr, val)
|
setattr(powerline_module, attr, val)
|
||||||
replaces[attr] = old_val
|
replaces[attr] = old_val
|
||||||
return replaces
|
return replaces
|
||||||
|
|
||||||
|
|
||||||
|
def add_watcher_events(p, *args, **kwargs):
|
||||||
|
p._watcher._reset(args)
|
||||||
|
while not p._will_create_renderer():
|
||||||
|
sleep(kwargs.get('interval', 0.1))
|
||||||
|
if not kwargs.get('wait', True):
|
||||||
|
return
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import powerline as powerline_module
|
import powerline as powerline_module
|
||||||
import time
|
from time import sleep
|
||||||
from tests import TestCase
|
from tests import TestCase
|
||||||
from tests.lib import replace_item
|
from tests.lib import replace_item
|
||||||
from tests.lib.config_mock import swap_attributes, get_powerline, pop_events
|
from tests.lib.config_mock import swap_attributes, get_powerline, pop_events, add_watcher_events
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
@ -92,18 +92,6 @@ config = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def sleep(interval):
|
|
||||||
time.sleep(interval)
|
|
||||||
|
|
||||||
|
|
||||||
def add_watcher_events(p, *args, **kwargs):
|
|
||||||
p._watcher._reset(args)
|
|
||||||
while not p._will_create_renderer():
|
|
||||||
sleep(kwargs.get('interval', 0.1))
|
|
||||||
if not kwargs.get('wait', True):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class TestConfigReload(TestCase):
|
class TestConfigReload(TestCase):
|
||||||
def assertAccessEvents(self, *args):
|
def assertAccessEvents(self, *args):
|
||||||
self.assertEqual(set(pop_events()), set(args))
|
self.assertEqual(set(pop_events()), set(args))
|
||||||
|
@ -1,151 +1,136 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import unicode_literals, absolute_import, division
|
||||||
'''Dynamic configuration files tests.'''
|
import powerline as powerline_module
|
||||||
|
|
||||||
|
|
||||||
import tests.vim as vim_module
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
from tests.lib import Args, urllib_read, replace_attr
|
|
||||||
from tests import TestCase
|
from tests import TestCase
|
||||||
|
from tests.lib import replace_item
|
||||||
|
from tests.lib.config_mock import swap_attributes, get_powerline, pop_events
|
||||||
|
from functools import wraps
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
VBLOCK = chr(ord('V') - 0x40)
|
config = {
|
||||||
SBLOCK = chr(ord('S') - 0x40)
|
'config': {
|
||||||
|
'common': {
|
||||||
|
'dividers': {
|
||||||
|
'left': {
|
||||||
|
'hard': '>>',
|
||||||
|
'soft': '>',
|
||||||
|
},
|
||||||
|
'right': {
|
||||||
|
'hard': '<<',
|
||||||
|
'soft': '<',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'spaces': 0,
|
||||||
|
'interval': 0,
|
||||||
|
},
|
||||||
|
'ext': {
|
||||||
|
'test': {
|
||||||
|
'theme': 'default',
|
||||||
|
'colorscheme': 'default',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'colors': {
|
||||||
|
'colors': {
|
||||||
|
'col1': 1,
|
||||||
|
'col2': 2,
|
||||||
|
'col3': 3,
|
||||||
|
'col4': 4,
|
||||||
|
},
|
||||||
|
'gradients': {
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'colorschemes/test/default': {
|
||||||
|
'groups': {
|
||||||
|
'str1': {'fg': 'col1', 'bg': 'col2', 'attr': ['bold']},
|
||||||
|
'str2': {'fg': 'col3', 'bg': 'col4', 'attr': ['underline']},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'themes/test/default': {
|
||||||
|
'segments': {
|
||||||
|
'left': [
|
||||||
|
{
|
||||||
|
'type': 'string',
|
||||||
|
'contents': 's',
|
||||||
|
'width': 'auto',
|
||||||
|
'highlight_group': ['str1'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'string',
|
||||||
|
'contents': 'g',
|
||||||
|
'highlight_group': ['str2'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'right': [
|
||||||
|
{
|
||||||
|
'type': 'string',
|
||||||
|
'contents': 'f',
|
||||||
|
'width': 'auto',
|
||||||
|
'align': 'right',
|
||||||
|
'highlight_group': ['str2'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestConfig(TestCase):
|
def add_p_arg(func):
|
||||||
def test_vim(self):
|
@wraps(func)
|
||||||
from powerline.vim import VimPowerline
|
def f(self):
|
||||||
cfg_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'powerline', 'config_files')
|
with get_powerline(run_once=True, simpler_renderer=True) as p:
|
||||||
buffers = (
|
func(self, p)
|
||||||
(('bufoptions',), {'buftype': 'help'}),
|
return f
|
||||||
(('bufname', '[Command Line]'), {}),
|
|
||||||
(('bufoptions',), {'buftype': 'quickfix'}),
|
|
||||||
(('bufname', 'NERD_tree_1'), {}),
|
|
||||||
(('bufname', '__Gundo__'), {}),
|
|
||||||
(('bufname', '__Gundo_Preview__'), {}),
|
|
||||||
(('bufname', 'ControlP'), {}),
|
|
||||||
)
|
|
||||||
with open(os.path.join(cfg_path, 'config.json'), 'r') as f:
|
|
||||||
local_themes_raw = json.load(f)['ext']['vim']['local_themes']
|
|
||||||
# Don't run tests on external/plugin segments
|
|
||||||
local_themes = dict((k, v) for (k, v) in local_themes_raw.items())
|
|
||||||
self.assertEqual(len(buffers), len(local_themes))
|
|
||||||
outputs = {}
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
with vim_module._with('split'):
|
|
||||||
with VimPowerline() as powerline:
|
|
||||||
def check_output(mode, args, kwargs):
|
|
||||||
if mode == 'nc':
|
|
||||||
window = vim_module.windows[0]
|
|
||||||
window_id = 2
|
|
||||||
else:
|
|
||||||
vim_module._start_mode(mode)
|
|
||||||
window = vim_module.current.window
|
|
||||||
window_id = 1
|
|
||||||
winnr = window.number
|
|
||||||
out = powerline.render(window, window_id, winnr)
|
|
||||||
if out in outputs:
|
|
||||||
self.fail('Duplicate in set #{0} ({1}) for mode {2!r} (previously defined in set #{3} ({4!r}) for mode {5!r})'.format(i, (args, kwargs), mode, *outputs[out]))
|
|
||||||
outputs[out] = (i, (args, kwargs), mode)
|
|
||||||
|
|
||||||
with vim_module._with('bufname', '/tmp/foo.txt'):
|
|
||||||
with vim_module._with('globals', powerline_config_path=cfg_path):
|
|
||||||
exclude = set(('no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!'))
|
|
||||||
try:
|
|
||||||
for mode in ['n', 'nc', 'no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'i', 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!']:
|
|
||||||
check_output(mode, None, None)
|
|
||||||
for args, kwargs in buffers:
|
|
||||||
i += 1
|
|
||||||
if mode in exclude:
|
|
||||||
continue
|
|
||||||
if mode == 'nc' and args == ('bufname', 'ControlP'):
|
|
||||||
# ControlP window is not supposed to not
|
|
||||||
# be in the focus
|
|
||||||
continue
|
|
||||||
with vim_module._with(*args, **kwargs):
|
|
||||||
check_output(mode, args, kwargs)
|
|
||||||
finally:
|
|
||||||
vim_module._start_mode('n')
|
|
||||||
|
|
||||||
def test_tmux(self):
|
|
||||||
from powerline.segments import common
|
|
||||||
from imp import reload
|
|
||||||
reload(common)
|
|
||||||
from powerline.shell import ShellPowerline
|
|
||||||
with replace_attr(common, 'urllib_read', urllib_read):
|
|
||||||
with ShellPowerline(Args(ext=['tmux']), run_once=False) as powerline:
|
|
||||||
powerline.render()
|
|
||||||
with ShellPowerline(Args(ext=['tmux']), run_once=False) as powerline:
|
|
||||||
powerline.render()
|
|
||||||
|
|
||||||
def test_zsh(self):
|
|
||||||
from powerline.shell import ShellPowerline
|
|
||||||
args = Args(last_pipe_status=[1, 0], jobnum=0, ext=['shell'], renderer_module='zsh_prompt')
|
|
||||||
segment_info = {'args': args}
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info=segment_info)
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info=segment_info)
|
|
||||||
segment_info['local_theme'] = 'select'
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info=segment_info)
|
|
||||||
segment_info['local_theme'] = 'continuation'
|
|
||||||
segment_info['parser_state'] = 'if cmdsubst'
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info=segment_info)
|
|
||||||
|
|
||||||
def test_bash(self):
|
|
||||||
from powerline.shell import ShellPowerline
|
|
||||||
args = Args(last_exit_code=1, jobnum=0, ext=['shell'], renderer_module='bash_prompt', config={'ext': {'shell': {'theme': 'default_leftonly'}}})
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info={'args': args})
|
|
||||||
with ShellPowerline(args, run_once=False) as powerline:
|
|
||||||
powerline.render(segment_info={'args': args})
|
|
||||||
|
|
||||||
def test_ipython(self):
|
|
||||||
from powerline.ipython import IpythonPowerline
|
|
||||||
|
|
||||||
class IpyPowerline(IpythonPowerline):
|
|
||||||
path = None
|
|
||||||
config_overrides = None
|
|
||||||
theme_overrides = {}
|
|
||||||
|
|
||||||
with IpyPowerline() as powerline:
|
|
||||||
segment_info = Args(prompt_count=1)
|
|
||||||
for prompt_type in ['in', 'in2', 'out', 'rewrite']:
|
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
|
||||||
|
|
||||||
def test_wm(self):
|
|
||||||
from powerline.segments import common
|
|
||||||
from imp import reload
|
|
||||||
reload(common)
|
|
||||||
from powerline import Powerline
|
|
||||||
with replace_attr(common, 'urllib_read', urllib_read):
|
|
||||||
Powerline(ext='wm', renderer_module='pango_markup', run_once=True).render()
|
|
||||||
reload(common)
|
|
||||||
|
|
||||||
|
|
||||||
old_cwd = None
|
class TestSingleLine(TestCase):
|
||||||
|
def assertRenderEqual(self, p, output, **kwargs):
|
||||||
|
self.assertEqual(p.render(**kwargs).replace(' ', ' '), output)
|
||||||
|
|
||||||
|
def assertRenderLinesEqual(self, p, output, **kwargs):
|
||||||
|
self.assertEqual([l.replace(' ', ' ') for l in p.render_above_lines(**kwargs)], output)
|
||||||
|
|
||||||
|
@add_p_arg
|
||||||
|
def test_without_above(self, p):
|
||||||
|
self.assertRenderEqual(p, '{121} s{24}>>{344}g{34}>{34}<{344}f {--}')
|
||||||
|
self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344}f {--}', width=10)
|
||||||
|
# self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}<{344} f {--}', width=11)
|
||||||
|
self.assertEqual(list(p.render_above_lines()), [])
|
||||||
|
|
||||||
|
def test_with_above(self):
|
||||||
|
with replace_item(globals(), 'config', deepcopy(config)):
|
||||||
|
old_segments = deepcopy(config['themes/test/default']['segments'])
|
||||||
|
config['themes/test/default']['segments']['above'] = [old_segments]
|
||||||
|
with get_powerline(run_once=True, simpler_renderer=True) as p:
|
||||||
|
self.assertRenderLinesEqual(p, [
|
||||||
|
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
])
|
||||||
|
self.assertRenderLinesEqual(p, [
|
||||||
|
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
], width=10)
|
||||||
|
|
||||||
|
config['themes/test/default']['segments']['above'] = [old_segments] * 2
|
||||||
|
with get_powerline(run_once=True, simpler_renderer=True) as p:
|
||||||
|
self.assertRenderLinesEqual(p, [
|
||||||
|
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
'{121} s{24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
])
|
||||||
|
self.assertRenderLinesEqual(p, [
|
||||||
|
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
'{121} s {24}>>{344}g{34}>{34}<{344}f {--}',
|
||||||
|
], width=10)
|
||||||
|
|
||||||
|
|
||||||
|
replaces = {}
|
||||||
|
|
||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
global old_cwd
|
global replaces
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
|
replaces = swap_attributes(globals(), powerline_module, replaces)
|
||||||
old_cwd = os.getcwd()
|
|
||||||
from powerline.segments import vim
|
|
||||||
globals()['vim'] = vim
|
|
||||||
|
|
||||||
|
|
||||||
def tearDownModule():
|
tearDownModule = setUpModule
|
||||||
global old_cwd
|
|
||||||
os.chdir(old_cwd)
|
|
||||||
old_cwd = None
|
|
||||||
sys.path.pop(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
153
tests/test_provided_config_files.py
Normal file
153
tests/test_provided_config_files.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# vim:fileencoding=utf-8:noet
|
||||||
|
|
||||||
|
'''Dynamic configuration files tests.'''
|
||||||
|
|
||||||
|
|
||||||
|
import tests.vim as vim_module
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from tests.lib import Args, urllib_read, replace_attr
|
||||||
|
from tests import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
VBLOCK = chr(ord('V') - 0x40)
|
||||||
|
SBLOCK = chr(ord('S') - 0x40)
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfig(TestCase):
|
||||||
|
def test_vim(self):
|
||||||
|
from powerline.vim import VimPowerline
|
||||||
|
cfg_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'powerline', 'config_files')
|
||||||
|
buffers = (
|
||||||
|
(('bufoptions',), {'buftype': 'help'}),
|
||||||
|
(('bufname', '[Command Line]'), {}),
|
||||||
|
(('bufoptions',), {'buftype': 'quickfix'}),
|
||||||
|
(('bufname', 'NERD_tree_1'), {}),
|
||||||
|
(('bufname', '__Gundo__'), {}),
|
||||||
|
(('bufname', '__Gundo_Preview__'), {}),
|
||||||
|
(('bufname', 'ControlP'), {}),
|
||||||
|
)
|
||||||
|
with open(os.path.join(cfg_path, 'config.json'), 'r') as f:
|
||||||
|
local_themes_raw = json.load(f)['ext']['vim']['local_themes']
|
||||||
|
# Don't run tests on external/plugin segments
|
||||||
|
local_themes = dict((k, v) for (k, v) in local_themes_raw.items())
|
||||||
|
self.assertEqual(len(buffers), len(local_themes))
|
||||||
|
outputs = {}
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
with vim_module._with('split'):
|
||||||
|
with VimPowerline() as powerline:
|
||||||
|
def check_output(mode, args, kwargs):
|
||||||
|
if mode == 'nc':
|
||||||
|
window = vim_module.windows[0]
|
||||||
|
window_id = 2
|
||||||
|
else:
|
||||||
|
vim_module._start_mode(mode)
|
||||||
|
window = vim_module.current.window
|
||||||
|
window_id = 1
|
||||||
|
winnr = window.number
|
||||||
|
out = powerline.render(window, window_id, winnr)
|
||||||
|
if out in outputs:
|
||||||
|
self.fail('Duplicate in set #{0} ({1}) for mode {2!r} (previously defined in set #{3} ({4!r}) for mode {5!r})'.format(i, (args, kwargs), mode, *outputs[out]))
|
||||||
|
outputs[out] = (i, (args, kwargs), mode)
|
||||||
|
|
||||||
|
with vim_module._with('bufname', '/tmp/foo.txt'):
|
||||||
|
with vim_module._with('globals', powerline_config_path=cfg_path):
|
||||||
|
exclude = set(('no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!'))
|
||||||
|
try:
|
||||||
|
for mode in ['n', 'nc', 'no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'i', 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!']:
|
||||||
|
check_output(mode, None, None)
|
||||||
|
for args, kwargs in buffers:
|
||||||
|
i += 1
|
||||||
|
if mode in exclude:
|
||||||
|
continue
|
||||||
|
if mode == 'nc' and args == ('bufname', 'ControlP'):
|
||||||
|
# ControlP window is not supposed to not
|
||||||
|
# be in the focus
|
||||||
|
continue
|
||||||
|
with vim_module._with(*args, **kwargs):
|
||||||
|
check_output(mode, args, kwargs)
|
||||||
|
finally:
|
||||||
|
vim_module._start_mode('n')
|
||||||
|
|
||||||
|
def test_tmux(self):
|
||||||
|
from powerline.segments import common
|
||||||
|
from imp import reload
|
||||||
|
reload(common)
|
||||||
|
from powerline.shell import ShellPowerline
|
||||||
|
with replace_attr(common, 'urllib_read', urllib_read):
|
||||||
|
with ShellPowerline(Args(ext=['tmux']), run_once=False) as powerline:
|
||||||
|
powerline.render()
|
||||||
|
with ShellPowerline(Args(ext=['tmux']), run_once=False) as powerline:
|
||||||
|
powerline.render()
|
||||||
|
|
||||||
|
def test_zsh(self):
|
||||||
|
from powerline.shell import ShellPowerline
|
||||||
|
args = Args(last_pipe_status=[1, 0], jobnum=0, ext=['shell'], renderer_module='zsh_prompt')
|
||||||
|
segment_info = {'args': args}
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info=segment_info)
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info=segment_info)
|
||||||
|
segment_info['local_theme'] = 'select'
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info=segment_info)
|
||||||
|
segment_info['local_theme'] = 'continuation'
|
||||||
|
segment_info['parser_state'] = 'if cmdsubst'
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info=segment_info)
|
||||||
|
|
||||||
|
def test_bash(self):
|
||||||
|
from powerline.shell import ShellPowerline
|
||||||
|
args = Args(last_exit_code=1, jobnum=0, ext=['shell'], renderer_module='bash_prompt', config={'ext': {'shell': {'theme': 'default_leftonly'}}})
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info={'args': args})
|
||||||
|
with ShellPowerline(args, run_once=False) as powerline:
|
||||||
|
powerline.render(segment_info={'args': args})
|
||||||
|
|
||||||
|
def test_ipython(self):
|
||||||
|
from powerline.ipython import IpythonPowerline
|
||||||
|
|
||||||
|
class IpyPowerline(IpythonPowerline):
|
||||||
|
path = None
|
||||||
|
config_overrides = None
|
||||||
|
theme_overrides = {}
|
||||||
|
|
||||||
|
with IpyPowerline() as powerline:
|
||||||
|
segment_info = Args(prompt_count=1)
|
||||||
|
for prompt_type in ['in', 'in2', 'out', 'rewrite']:
|
||||||
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
|
|
||||||
|
def test_wm(self):
|
||||||
|
from powerline.segments import common
|
||||||
|
from imp import reload
|
||||||
|
reload(common)
|
||||||
|
from powerline import Powerline
|
||||||
|
with replace_attr(common, 'urllib_read', urllib_read):
|
||||||
|
Powerline(ext='wm', renderer_module='pango_markup', run_once=True).render()
|
||||||
|
reload(common)
|
||||||
|
|
||||||
|
|
||||||
|
old_cwd = None
|
||||||
|
|
||||||
|
|
||||||
|
def setUpModule():
|
||||||
|
global old_cwd
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
|
||||||
|
old_cwd = os.getcwd()
|
||||||
|
from powerline.segments import vim
|
||||||
|
globals()['vim'] = vim
|
||||||
|
|
||||||
|
|
||||||
|
def tearDownModule():
|
||||||
|
global old_cwd
|
||||||
|
os.chdir(old_cwd)
|
||||||
|
old_cwd = None
|
||||||
|
sys.path.pop(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from tests import main
|
||||||
|
main()
|
Loading…
x
Reference in New Issue
Block a user