mirror of
https://github.com/powerline/powerline.git
synced 2025-07-27 07:44:36 +02:00
Merge pull request #975 from ZyX-I/min_cursor_columns
Add cursor_space and cursor_columns options
This commit is contained in:
commit
1abe0ac194
@ -283,6 +283,16 @@ ascii Theme without any unicode characters at all
|
|||||||
background colors, while the ``soft`` dividers are used to divide
|
background colors, while the ``soft`` dividers are used to divide
|
||||||
segments with the same background color.
|
segments with the same background color.
|
||||||
|
|
||||||
|
.. _config-themes-cursor_space:
|
||||||
|
|
||||||
|
``cursor_space``
|
||||||
|
Space reserved for user input in shell bindings. It is measured in per
|
||||||
|
cents.
|
||||||
|
|
||||||
|
``cursor_columns``
|
||||||
|
Space reserved for user input in shell bindings. Unlike :ref:`cursor_space
|
||||||
|
<config-themes-cursor_space>` it is measured in absolute amout of columns.
|
||||||
|
|
||||||
.. _config-themes-segment_data:
|
.. _config-themes-segment_data:
|
||||||
|
|
||||||
``segment_data``
|
``segment_data``
|
||||||
|
@ -41,7 +41,12 @@ _powerline_init_tmux_support() {
|
|||||||
|
|
||||||
_powerline_prompt() {
|
_powerline_prompt() {
|
||||||
# Arguments: side, last_exit_code, jobnum
|
# Arguments: side, last_exit_code, jobnum
|
||||||
$POWERLINE_COMMAND shell $1 -w "${COLUMNS:-$(_powerline_columns_fallback)}" -r bash_prompt --last_exit_code=$2 --jobnum=$3
|
$POWERLINE_COMMAND shell $1 \
|
||||||
|
--width="${COLUMNS:-$(_powerline_columns_fallback)}" \
|
||||||
|
-r bash_prompt \
|
||||||
|
--last_exit_code=$2 \
|
||||||
|
--jobnum=$3 \
|
||||||
|
--renderer_arg="client_id=$$"
|
||||||
}
|
}
|
||||||
|
|
||||||
_powerline_set_prompt() {
|
_powerline_set_prompt() {
|
||||||
|
@ -34,6 +34,9 @@ function powerline-setup
|
|||||||
set -l addargs "--last_exit_code=\$status"
|
set -l addargs "--last_exit_code=\$status"
|
||||||
set -l addargs "$addargs --last_pipe_status=\$status"
|
set -l addargs "$addargs --last_pipe_status=\$status"
|
||||||
set -l addargs "$addargs --jobnum=(jobs -p | wc -l)"
|
set -l addargs "$addargs --jobnum=(jobs -p | wc -l)"
|
||||||
|
# One random value has an 1/32767 = 0.0031% probability of having
|
||||||
|
# the same value in two shells
|
||||||
|
set -l addargs "$addargs --renderer_arg=client_id="(random)
|
||||||
set -l addargs "$addargs --width=\$_POWERLINE_COLUMNS"
|
set -l addargs "$addargs --width=\$_POWERLINE_COLUMNS"
|
||||||
set -l promptside
|
set -l promptside
|
||||||
set -l rpromptpast
|
set -l rpromptpast
|
||||||
|
@ -22,20 +22,20 @@ class PowerlinePromptManager(PromptManager):
|
|||||||
self.shell = shell
|
self.shell = shell
|
||||||
|
|
||||||
def render(self, name, color=True, *args, **kwargs):
|
def render(self, name, color=True, *args, **kwargs):
|
||||||
width = None if name == 'in' else self.width
|
|
||||||
if name == 'out' or name == 'rewrite':
|
if name == 'out' or name == 'rewrite':
|
||||||
powerline = self.non_prompt_powerline
|
powerline = self.non_prompt_powerline
|
||||||
else:
|
else:
|
||||||
powerline = self.prompt_powerline
|
powerline = self.prompt_powerline
|
||||||
res, res_nocolor = powerline.render(
|
res = powerline.render(
|
||||||
output_raw=True,
|
side='left',
|
||||||
width=width,
|
output_width=True,
|
||||||
|
output_raw=not color,
|
||||||
matcher_info=name,
|
matcher_info=name,
|
||||||
segment_info=self.powerline_segment_info,
|
segment_info=self.powerline_segment_info,
|
||||||
)
|
)
|
||||||
self.txtwidth = len(res_nocolor)
|
self.txtwidth = res[-1]
|
||||||
self.width = self.txtwidth
|
self.width = res[-1]
|
||||||
ret = res if color else res_nocolor
|
ret = res[0] if color else res[1]
|
||||||
if name == 'rewrite':
|
if name == 'rewrite':
|
||||||
return RewriteResult(ret)
|
return RewriteResult(ret)
|
||||||
else:
|
else:
|
||||||
@ -43,12 +43,12 @@ class PowerlinePromptManager(PromptManager):
|
|||||||
|
|
||||||
|
|
||||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||||
def __init__(self, ip, is_prompt):
|
def __init__(self, ip, is_prompt, old_widths):
|
||||||
config = ip.config.Powerline
|
config = ip.config.Powerline
|
||||||
self.config_overrides = config.get('config_overrides')
|
self.config_overrides = config.get('config_overrides')
|
||||||
self.theme_overrides = config.get('theme_overrides', {})
|
self.theme_overrides = config.get('theme_overrides', {})
|
||||||
self.paths = config.get('paths')
|
self.paths = config.get('paths')
|
||||||
super(ConfigurableIpythonPowerline, self).__init__(is_prompt)
|
super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths)
|
||||||
|
|
||||||
|
|
||||||
old_prompt_manager = None
|
old_prompt_manager = None
|
||||||
@ -58,8 +58,9 @@ def load_ipython_extension(ip):
|
|||||||
global old_prompt_manager
|
global old_prompt_manager
|
||||||
|
|
||||||
old_prompt_manager = ip.prompt_manager
|
old_prompt_manager = ip.prompt_manager
|
||||||
prompt_powerline = ConfigurableIpythonPowerline(ip, True)
|
old_widths = {}
|
||||||
non_prompt_powerline = ConfigurableIpythonPowerline(ip, False)
|
prompt_powerline = ConfigurableIpythonPowerline(ip, True, old_widths)
|
||||||
|
non_prompt_powerline = ConfigurableIpythonPowerline(ip, False, old_widths)
|
||||||
|
|
||||||
ip.prompt_manager = PowerlinePromptManager(
|
ip.prompt_manager = PowerlinePromptManager(
|
||||||
prompt_powerline=prompt_powerline,
|
prompt_powerline=prompt_powerline,
|
||||||
|
@ -32,12 +32,15 @@ class PowerlinePrompt(BasePrompt):
|
|||||||
self.set_p_str()
|
self.set_p_str()
|
||||||
return string(self.p_str)
|
return string(self.p_str)
|
||||||
|
|
||||||
def set_p_str(self, width=None):
|
def set_p_str(self):
|
||||||
self.p_str, self.p_str_nocolor = (
|
self.p_str, self.p_str_nocolor, self.powerline_prompt_width = (
|
||||||
self.powerline.render(output_raw=True,
|
self.powerline.render(
|
||||||
segment_info=self.powerline_segment_info,
|
side='left',
|
||||||
matcher_info=self.powerline_prompt_type,
|
output_raw=True,
|
||||||
width=width)
|
output_width=True,
|
||||||
|
segment_info=self.powerline_segment_info,
|
||||||
|
matcher_info=self.powerline_prompt_type,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -58,20 +61,21 @@ class PowerlinePrompt1(PowerlinePrompt):
|
|||||||
def set_p_str(self):
|
def set_p_str(self):
|
||||||
super(PowerlinePrompt1, self).set_p_str()
|
super(PowerlinePrompt1, self).set_p_str()
|
||||||
self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
|
self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
|
||||||
self.prompt_text_len = len(self.p_str_nocolor) - self.nrspaces
|
|
||||||
self.powerline_last_in['nrspaces'] = self.nrspaces
|
self.powerline_last_in['nrspaces'] = self.nrspaces
|
||||||
self.powerline_last_in['prompt_text_len'] = self.prompt_text_len
|
|
||||||
|
|
||||||
def auto_rewrite(self):
|
def auto_rewrite(self):
|
||||||
return RewriteResult(self.other_powerline.render(matcher_info='rewrite', width=self.prompt_text_len, segment_info=self.powerline_segment_info)
|
return RewriteResult(self.other_powerline.render(
|
||||||
+ (' ' * self.nrspaces))
|
side='left',
|
||||||
|
matcher_info='rewrite',
|
||||||
|
segment_info=self.powerline_segment_info) + (' ' * self.nrspaces)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PowerlinePromptOut(PowerlinePrompt):
|
class PowerlinePromptOut(PowerlinePrompt):
|
||||||
powerline_prompt_type = 'out'
|
powerline_prompt_type = 'out'
|
||||||
|
|
||||||
def set_p_str(self):
|
def set_p_str(self):
|
||||||
super(PowerlinePromptOut, self).set_p_str(width=self.powerline_last_in['prompt_text_len'])
|
super(PowerlinePromptOut, self).set_p_str()
|
||||||
spaces = ' ' * self.powerline_last_in['nrspaces']
|
spaces = ' ' * self.powerline_last_in['nrspaces']
|
||||||
self.p_str += spaces
|
self.p_str += spaces
|
||||||
self.p_str_nocolor += spaces
|
self.p_str_nocolor += spaces
|
||||||
@ -82,21 +86,22 @@ class PowerlinePrompt2(PowerlinePromptOut):
|
|||||||
|
|
||||||
|
|
||||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||||
def __init__(self, is_prompt, config_overrides=None, theme_overrides={}, paths=None):
|
def __init__(self, is_prompt, old_widths, config_overrides=None, theme_overrides={}, paths=None):
|
||||||
self.config_overrides = config_overrides
|
self.config_overrides = config_overrides
|
||||||
self.theme_overrides = theme_overrides
|
self.theme_overrides = theme_overrides
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
super(ConfigurableIpythonPowerline, self).__init__(is_prompt)
|
super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths)
|
||||||
|
|
||||||
|
|
||||||
def setup(**kwargs):
|
def setup(**kwargs):
|
||||||
ip = get_ipython()
|
ip = get_ipython()
|
||||||
|
|
||||||
prompt_powerline = ConfigurableIpythonPowerline(True, **kwargs)
|
old_widths = {}
|
||||||
non_prompt_powerline = ConfigurableIpythonPowerline(False, **kwargs)
|
prompt_powerline = ConfigurableIpythonPowerline(True, old_widths, **kwargs)
|
||||||
|
non_prompt_powerline = ConfigurableIpythonPowerline(False, old_widths, **kwargs)
|
||||||
|
|
||||||
def late_startup_hook():
|
def late_startup_hook():
|
||||||
last_in = {'nrspaces': 0, 'prompt_text_len': None}
|
last_in = {'nrspaces': 0}
|
||||||
for attr, prompt_class, powerline, other_powerline in (
|
for attr, prompt_class, powerline, other_powerline in (
|
||||||
('prompt1', PowerlinePrompt1, prompt_powerline, non_prompt_powerline),
|
('prompt1', PowerlinePrompt1, prompt_powerline, non_prompt_powerline),
|
||||||
('prompt2', PowerlinePrompt2, prompt_powerline, None),
|
('prompt2', PowerlinePrompt2, prompt_powerline, None),
|
||||||
|
@ -134,7 +134,12 @@ _powerline_set_jobs() {
|
|||||||
_powerline_prompt() {
|
_powerline_prompt() {
|
||||||
# Arguments: side, exit_code
|
# Arguments: side, exit_code
|
||||||
_powerline_set_jobs
|
_powerline_set_jobs
|
||||||
$POWERLINE_COMMAND shell $1 -w "${COLUMNS:-$(_powerline_columns_fallback)}" $_POWERLINE_RENDERER_ARG --last_exit_code=$2 --jobnum=$_POWERLINE_JOBS
|
$POWERLINE_COMMAND shell $1 \
|
||||||
|
--width="${COLUMNS:-$(_powerline_columns_fallback)}" \
|
||||||
|
$_POWERLINE_RENDERER_ARG \
|
||||||
|
--renderer_arg="client_id=$$" \
|
||||||
|
--last_exit_code=$2 \
|
||||||
|
--jobnum=$_POWERLINE_JOBS
|
||||||
}
|
}
|
||||||
|
|
||||||
_powerline_setup_prompt() {
|
_powerline_setup_prompt() {
|
||||||
|
@ -24,11 +24,11 @@ if ( { $POWERLINE_CONFIG shell --shell=tcsh uses prompt } ) then
|
|||||||
if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then
|
if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then
|
||||||
alias _powerline_above true
|
alias _powerline_above true
|
||||||
else
|
else
|
||||||
alias _powerline_above '$POWERLINE_COMMAND shell above --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS'
|
alias _powerline_above '$POWERLINE_COMMAND shell above --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS'
|
||||||
endif
|
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_prompt 'set prompt="`$POWERLINE_COMMAND shell left -r tcsh_prompt --renderer_arg=client_id=$$ --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_rprompt 'set rprompt="`$POWERLINE_COMMAND shell right -r tcsh_prompt --renderer_arg=client_id=$$ --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 _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'
|
alias precmd 'set POWERLINE_STATUS=$? ; '"`alias precmd`"' ; _powerline_set_columns ; _powerline_above ; _powerline_set_prompt ; _powerline_set_rprompt'
|
||||||
|
@ -129,21 +129,22 @@ _powerline_setup_prompt() {
|
|||||||
POWERLINE_COMMAND=( "$($POWERLINE_CONFIG shell command)" )
|
POWERLINE_COMMAND=( "$($POWERLINE_CONFIG shell command)" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local add_args='--last_exit_code=$?'
|
local add_args='-r zsh_prompt'
|
||||||
|
add_args+=' --last_exit_code=$?'
|
||||||
add_args+=' --last_pipe_status="$pipestatus"'
|
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 new_args_2=' -R parser_state=${(%%):-%_}'
|
local new_args_2=' --renderer_arg="parser_state=${(%%):-%_}"'
|
||||||
new_args_2+=' -R local_theme=continuation'
|
new_args_2+=' --renderer_arg="local_theme=continuation"'
|
||||||
local add_args_3=$add_args' -R local_theme=select'
|
local add_args_3=$add_args' --renderer_arg="local_theme=select"'
|
||||||
local add_args_2=$add_args$new_args_2
|
local add_args_2=$add_args$new_args_2
|
||||||
add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - 1 ))'
|
add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - 1 ))'
|
||||||
local add_args_r2=$add_args$new_args_2
|
local add_args_r2=$add_args$new_args_2
|
||||||
PS1='$($POWERLINE_COMMAND shell aboveleft -r zsh_prompt '$add_args')'
|
PS1='$($POWERLINE_COMMAND shell aboveleft '$add_args')'
|
||||||
RPS1='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args')'
|
RPS1='$($POWERLINE_COMMAND shell right '$add_args')'
|
||||||
PS2='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args_2')'
|
PS2='$($POWERLINE_COMMAND shell left '$add_args_2')'
|
||||||
RPS2='$($POWERLINE_COMMAND shell right -r zsh_prompt '$add_args_r2')'
|
RPS2='$($POWERLINE_COMMAND shell right '$add_args_r2')'
|
||||||
PS3='$($POWERLINE_COMMAND shell left -r zsh_prompt '$add_args_3')'
|
PS3='$($POWERLINE_COMMAND shell left '$add_args_3')'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
"segments": {
|
"segments": {
|
||||||
"left": [
|
"left": [
|
||||||
{
|
{
|
||||||
"name": "virtualenv"
|
"name": "virtualenv",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -7,29 +7,36 @@
|
|||||||
"name": "mode"
|
"name": "mode"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hostname"
|
"name": "hostname",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "user"
|
"name": "user",
|
||||||
|
"priority": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "virtualenv"
|
"name": "virtualenv",
|
||||||
|
"priority": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cwd"
|
"name": "cwd",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"module": "powerline.segments.shell",
|
"module": "powerline.segments.shell",
|
||||||
"name": "jobnum"
|
"name": "jobnum",
|
||||||
|
"priority": 20
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"right": [
|
"right": [
|
||||||
{
|
{
|
||||||
"module": "powerline.segments.shell",
|
"module": "powerline.segments.shell",
|
||||||
"name": "last_pipe_status"
|
"name": "last_pipe_status",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "branch"
|
"name": "branch",
|
||||||
|
"priority": 40
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -3,27 +3,34 @@
|
|||||||
"segments": {
|
"segments": {
|
||||||
"left": [
|
"left": [
|
||||||
{
|
{
|
||||||
"name": "hostname"
|
"name": "hostname",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "user"
|
"name": "user",
|
||||||
|
"priority": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "virtualenv"
|
"name": "virtualenv",
|
||||||
|
"priority": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "branch"
|
"name": "branch",
|
||||||
|
"priority": 40
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cwd"
|
"name": "cwd",
|
||||||
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"module": "powerline.segments.shell",
|
"module": "powerline.segments.shell",
|
||||||
"name": "jobnum"
|
"name": "jobnum",
|
||||||
|
"priority": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"module": "powerline.segments.shell",
|
||||||
"name": "last_status",
|
"name": "last_status",
|
||||||
"module": "powerline.segments.shell"
|
"priority": 10
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,17 @@ class RewriteResult(object):
|
|||||||
|
|
||||||
|
|
||||||
class IpythonPowerline(Powerline):
|
class IpythonPowerline(Powerline):
|
||||||
def __init__(self, is_prompt):
|
def __init__(self, is_prompt, old_widths):
|
||||||
super(IpythonPowerline, self).__init__(
|
super(IpythonPowerline, self).__init__(
|
||||||
'ipython',
|
'ipython',
|
||||||
renderer_module=('ipython_prompt' if is_prompt else 'ipython'),
|
renderer_module=('ipython_prompt' if is_prompt else 'ipython'),
|
||||||
use_daemon_threads=True
|
use_daemon_threads=True
|
||||||
)
|
)
|
||||||
|
self.old_widths = old_widths
|
||||||
|
|
||||||
|
def create_renderer(self, *args, **kwargs):
|
||||||
|
super(IpythonPowerline, self).create_renderer(*args, **kwargs)
|
||||||
|
self.renderer.old_widths = self.old_widths
|
||||||
|
|
||||||
def get_config_paths(self):
|
def get_config_paths(self):
|
||||||
if self.paths:
|
if self.paths:
|
||||||
|
@ -1279,6 +1279,8 @@ spaces_spec = Spec().unsigned().cmp(
|
|||||||
).copy
|
).copy
|
||||||
common_theme_spec = Spec(
|
common_theme_spec = Spec(
|
||||||
default_module=segment_module_spec().optional(),
|
default_module=segment_module_spec().optional(),
|
||||||
|
cursor_space=Spec().type(int, float).cmp('le', 100).cmp('gt', 0).optional(),
|
||||||
|
cursor_columns=Spec().type(int).cmp('gt', 0).optional(),
|
||||||
).context_message('Error while loading theme').copy
|
).context_message('Error while loading theme').copy
|
||||||
top_theme_spec = common_theme_spec().update(
|
top_theme_spec = common_theme_spec().update(
|
||||||
dividers=dividers_spec(),
|
dividers=dividers_spec(),
|
||||||
|
@ -15,11 +15,15 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def construct_returned_value(rendered_highlighted, segments, output_raw):
|
def construct_returned_value(rendered_highlighted, segments, width, output_raw, output_width):
|
||||||
if output_raw:
|
if not (output_raw or output_width):
|
||||||
return rendered_highlighted, ''.join((segment['_rendered_raw'] for segment in segments))
|
|
||||||
else:
|
|
||||||
return rendered_highlighted
|
return rendered_highlighted
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
(rendered_highlighted,)
|
||||||
|
+ ((''.join((segment['_rendered_raw'] for segment in segments)),) if output_raw else ())
|
||||||
|
+ ((width,) if output_width else ())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Renderer(object):
|
class Renderer(object):
|
||||||
@ -188,7 +192,7 @@ class Renderer(object):
|
|||||||
for line in range(theme.get_line_number() - 1, 0, -1):
|
for line in range(theme.get_line_number() - 1, 0, -1):
|
||||||
yield self.render(side=None, line=line, **kwargs)
|
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):
|
def render(self, mode=None, width=None, side=None, line=0, output_raw=False, output_width=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
|
||||||
@ -213,14 +217,44 @@ class Renderer(object):
|
|||||||
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,
|
||||||
colorless_string)``.
|
colorless_string)``.
|
||||||
|
:param bool output_width:
|
||||||
|
Changes the output: if this parameter is ``True`` then in place of
|
||||||
|
one string this method outputs a pair ``(colored_string,
|
||||||
|
string_width)``. Returns a three-tuple if ``output_raw`` is also
|
||||||
|
``True``: ``(colored_string, colorless_string, string_width)``.
|
||||||
:param dict segment_info:
|
:param dict segment_info:
|
||||||
Segment information. See also ``.get_segment_info()`` method.
|
Segment information. See also ``.get_segment_info()`` method.
|
||||||
:param matcher_info:
|
:param matcher_info:
|
||||||
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, line, self.get_segment_info(segment_info, mode))
|
return self.do_render(
|
||||||
|
mode=mode,
|
||||||
|
width=width,
|
||||||
|
side=side,
|
||||||
|
line=line,
|
||||||
|
output_raw=output_raw,
|
||||||
|
output_width=output_width,
|
||||||
|
segment_info=segment_info,
|
||||||
|
theme=theme,
|
||||||
|
)
|
||||||
|
|
||||||
|
def compute_divider_widths(self, theme):
|
||||||
|
return {
|
||||||
|
'left': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('left', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('left', 'soft')),
|
||||||
|
},
|
||||||
|
'right': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('right', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('right', 'soft')),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_render(self, mode, width, side, line, output_raw, output_width, segment_info, theme):
|
||||||
|
'''Like Renderer.render(), but accept theme in place of matcher_info
|
||||||
|
'''
|
||||||
|
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 = [
|
segments = [
|
||||||
self._get_highlighting(segment, segment['mode'] or mode)
|
self._get_highlighting(segment, segment['mode'] or mode)
|
||||||
@ -234,37 +268,36 @@ class Renderer(object):
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
current_width = 0
|
||||||
|
|
||||||
if not width:
|
if not width:
|
||||||
# No width specified, so we don't need to crop or pad anything
|
# No width specified, so we don't need to crop or pad anything
|
||||||
|
if output_width:
|
||||||
|
current_width = self._render_length(theme, segments, self.compute_divider_widths(theme))
|
||||||
return construct_returned_value(''.join([
|
return construct_returned_value(''.join([
|
||||||
segment['_rendered_hl']
|
segment['_rendered_hl']
|
||||||
for segment in self._render_segments(theme, segments)
|
for segment in self._render_segments(theme, segments)
|
||||||
]) + self.hlstyle(), segments, output_raw)
|
]) + self.hlstyle(), segments, current_width, output_raw, output_width)
|
||||||
|
|
||||||
divider_lengths = {
|
divider_widths = self.compute_divider_widths(theme)
|
||||||
'left': {
|
|
||||||
'hard': self.strwidth(theme.get_divider('left', 'hard')),
|
|
||||||
'soft': self.strwidth(theme.get_divider('left', 'soft')),
|
|
||||||
},
|
|
||||||
'right': {
|
|
||||||
'hard': self.strwidth(theme.get_divider('right', 'hard')),
|
|
||||||
'soft': self.strwidth(theme.get_divider('right', 'soft')),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
length = self._render_length(theme, segments, divider_lengths)
|
|
||||||
|
|
||||||
# Create an ordered list of segments that can be dropped
|
# Create an ordered list of segments that can be dropped
|
||||||
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
|
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
|
||||||
for segment in segments_priority:
|
for segment in segments_priority:
|
||||||
if self._render_length(theme, segments, divider_lengths) <= width:
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
if current_width <= width:
|
||||||
break
|
break
|
||||||
segments.remove(segment)
|
segments.remove(segment)
|
||||||
|
|
||||||
# Distribute the remaining space on spacer segments
|
# Distribute the remaining space on spacer segments
|
||||||
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
||||||
if segments_spacers:
|
if segments_spacers:
|
||||||
distribute_len, distribute_len_remainder = divmod(width - sum([segment['_len'] for segment in segments]), len(segments_spacers))
|
if not segments_priority:
|
||||||
|
# Update segment['_len'] and current_width if not already done
|
||||||
|
# (is not done in shells where there is nothing to remove
|
||||||
|
# because “priority” key is not specified)
|
||||||
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
distribute_len, distribute_len_remainder = divmod(width - current_width, len(segments_spacers))
|
||||||
for segment in segments_spacers:
|
for segment in segments_spacers:
|
||||||
if segment['align'] == 'l':
|
if segment['align'] == 'l':
|
||||||
segment['_space_right'] += distribute_len
|
segment['_space_right'] += distribute_len
|
||||||
@ -275,12 +308,17 @@ class Renderer(object):
|
|||||||
segment['_space_left'] += space_side + space_side_remainder
|
segment['_space_left'] += space_side + space_side_remainder
|
||||||
segment['_space_right'] += space_side
|
segment['_space_right'] += space_side
|
||||||
segments_spacers[0]['_space_right'] += distribute_len_remainder
|
segments_spacers[0]['_space_right'] += distribute_len_remainder
|
||||||
|
# `_len` key is not needed anymore, but current_width should have an
|
||||||
|
# actual value for various bindings.
|
||||||
|
current_width = width
|
||||||
|
elif output_width:
|
||||||
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
|
||||||
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
||||||
|
|
||||||
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
return construct_returned_value(rendered_highlighted, segments, current_width, output_raw, output_width)
|
||||||
|
|
||||||
def _render_length(self, theme, segments, divider_lengths):
|
def _render_length(self, theme, segments, divider_widths):
|
||||||
'''Update segments lengths and return them
|
'''Update segments lengths and return them
|
||||||
'''
|
'''
|
||||||
segments_len = len(segments)
|
segments_len = len(segments)
|
||||||
@ -306,7 +344,7 @@ class Renderer(object):
|
|||||||
draw_divider = segment['draw_' + divider_type + '_divider']
|
draw_divider = segment['draw_' + divider_type + '_divider']
|
||||||
segment_len += segment['_space_left'] + segment['_space_right'] + outer_padding
|
segment_len += segment['_space_left'] + segment['_space_right'] + outer_padding
|
||||||
if draw_divider:
|
if draw_divider:
|
||||||
segment_len += divider_lengths[side][divider_type] + divider_spaces
|
segment_len += divider_widths[side][divider_type] + divider_spaces
|
||||||
|
|
||||||
segment['_len'] = segment_len
|
segment['_len'] = segment_len
|
||||||
ret += segment_len
|
ret += segment_len
|
||||||
|
@ -21,7 +21,7 @@ class IpythonRenderer(ShellRenderer):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
match['theme'] = Theme(
|
match['theme'] = Theme(
|
||||||
theme_config=match['config'],
|
theme_config=match['config'],
|
||||||
top_theme_config=self.theme_config,
|
main_theme_config=self.theme_config,
|
||||||
**self.theme_kwargs
|
**self.theme_kwargs
|
||||||
)
|
)
|
||||||
return match['theme']
|
return match['theme']
|
||||||
@ -32,5 +32,9 @@ class IpythonRenderer(ShellRenderer):
|
|||||||
if 'theme' in match:
|
if 'theme' in match:
|
||||||
match['theme'].shutdown()
|
match['theme'].shutdown()
|
||||||
|
|
||||||
|
def render(self, *args, **kwargs):
|
||||||
|
# XXX super(ShellRenderer), *not* super(IpythonRenderer)
|
||||||
|
return super(ShellRenderer, self).render(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
renderer = IpythonRenderer
|
renderer = IpythonRenderer
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||||
|
|
||||||
from powerline.renderer import Renderer
|
from powerline.renderer import Renderer
|
||||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||||
@ -23,6 +23,60 @@ class ShellRenderer(Renderer):
|
|||||||
|
|
||||||
character_translations = Renderer.character_translations.copy()
|
character_translations = Renderer.character_translations.copy()
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ShellRenderer, self).__init__(*args, **kwargs)
|
||||||
|
self.old_widths = {}
|
||||||
|
|
||||||
|
def render(self, segment_info, **kwargs):
|
||||||
|
local_theme = segment_info.get('local_theme')
|
||||||
|
return super(ShellRenderer, self).render(
|
||||||
|
matcher_info=local_theme,
|
||||||
|
segment_info=segment_info,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def do_render(self, output_width, segment_info, side, theme, width=None, **kwargs):
|
||||||
|
if isinstance(segment_info, dict):
|
||||||
|
client_id = segment_info.get('client_id')
|
||||||
|
else:
|
||||||
|
client_id = None
|
||||||
|
local_key = (client_id, side, None if theme is self.theme else id(theme))
|
||||||
|
key = (client_id, side, None)
|
||||||
|
did_width = False
|
||||||
|
if local_key[-1] != key[-1] and side == 'left':
|
||||||
|
try:
|
||||||
|
width = self.old_widths[key]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
did_width = True
|
||||||
|
if not did_width:
|
||||||
|
if width is not None:
|
||||||
|
if theme.cursor_space_multiplier is not None:
|
||||||
|
width = int(width * theme.cursor_space_multiplier)
|
||||||
|
elif theme.cursor_columns:
|
||||||
|
width -= theme.cursor_columns
|
||||||
|
|
||||||
|
if side == 'right':
|
||||||
|
try:
|
||||||
|
width -= self.old_widths[(client_id, 'left', local_key[-1])]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
res = super(ShellRenderer, self).do_render(
|
||||||
|
output_width=True,
|
||||||
|
width=width,
|
||||||
|
theme=theme,
|
||||||
|
segment_info=segment_info,
|
||||||
|
side=side,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
self.old_widths[local_key] = res[-1]
|
||||||
|
ret = res if output_width else res[:-1]
|
||||||
|
if len(ret) == 1:
|
||||||
|
return ret[0]
|
||||||
|
else:
|
||||||
|
return ret
|
||||||
|
|
||||||
def hlstyle(self, fg=None, bg=None, attr=None):
|
def hlstyle(self, fg=None, bg=None, attr=None):
|
||||||
'''Highlight a segment.
|
'''Highlight a segment.
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ class VimRenderer(Renderer):
|
|||||||
try:
|
try:
|
||||||
return match['theme']
|
return match['theme']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
match['theme'] = Theme(theme_config=match['config'], top_theme_config=self.theme_config, **self.theme_kwargs)
|
match['theme'] = Theme(theme_config=match['config'], main_theme_config=self.theme_config, **self.theme_kwargs)
|
||||||
return match['theme']
|
return match['theme']
|
||||||
|
|
||||||
def get_theme(self, matcher_info):
|
def get_theme(self, matcher_info):
|
||||||
|
@ -14,34 +14,6 @@ class ZshPromptRenderer(ShellRenderer):
|
|||||||
character_translations = ShellRenderer.character_translations.copy()
|
character_translations = ShellRenderer.character_translations.copy()
|
||||||
character_translations[ord('%')] = '%%'
|
character_translations[ord('%')] = '%%'
|
||||||
|
|
||||||
old_widths = {}
|
|
||||||
|
|
||||||
def render(self, segment_info, *args, **kwargs):
|
|
||||||
client_id = segment_info.get('client_id')
|
|
||||||
key = (client_id, kwargs.get('side'))
|
|
||||||
kwargs = kwargs.copy()
|
|
||||||
width = kwargs.pop('width', None)
|
|
||||||
local_theme = segment_info.get('local_theme')
|
|
||||||
if client_id and local_theme:
|
|
||||||
output_raw = False
|
|
||||||
try:
|
|
||||||
width = self.old_widths[key]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
output_raw = True
|
|
||||||
ret = super(ShellRenderer, self).render(
|
|
||||||
output_raw=output_raw,
|
|
||||||
width=width,
|
|
||||||
matcher_info=local_theme,
|
|
||||||
segment_info=segment_info,
|
|
||||||
*args, **kwargs
|
|
||||||
)
|
|
||||||
if output_raw:
|
|
||||||
self.old_widths[key] = len(ret[1])
|
|
||||||
ret = ret[0]
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def get_theme(self, matcher_info):
|
def get_theme(self, matcher_info):
|
||||||
if not matcher_info:
|
if not matcher_info:
|
||||||
return self.theme
|
return self.theme
|
||||||
@ -51,7 +23,7 @@ class ZshPromptRenderer(ShellRenderer):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
match['theme'] = Theme(
|
match['theme'] = Theme(
|
||||||
theme_config=match['config'],
|
theme_config=match['config'],
|
||||||
top_theme_config=self.theme_config,
|
main_theme_config=self.theme_config,
|
||||||
**self.theme_kwargs
|
**self.theme_kwargs
|
||||||
)
|
)
|
||||||
return match['theme']
|
return match['theme']
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
from powerline.segment import gen_segment_getter, process_segment
|
from powerline.segment import gen_segment_getter, process_segment
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
@ -28,7 +29,7 @@ class Theme(object):
|
|||||||
theme_config,
|
theme_config,
|
||||||
common_config,
|
common_config,
|
||||||
pl,
|
pl,
|
||||||
top_theme_config=None,
|
main_theme_config=None,
|
||||||
run_once=False,
|
run_once=False,
|
||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
self.dividers = theme_config['dividers']
|
self.dividers = theme_config['dividers']
|
||||||
@ -37,6 +38,11 @@ class Theme(object):
|
|||||||
for k, v in val.items()))
|
for k, v in val.items()))
|
||||||
for key, val in self.dividers.items()
|
for key, val in self.dividers.items()
|
||||||
))
|
))
|
||||||
|
try:
|
||||||
|
self.cursor_space_multiplier = 1 - (theme_config['cursor_space'] / 100)
|
||||||
|
except KeyError:
|
||||||
|
self.cursor_space_multiplier = None
|
||||||
|
self.cursor_columns = theme_config.get('cursor_columns')
|
||||||
self.spaces = theme_config['spaces']
|
self.spaces = theme_config['spaces']
|
||||||
self.segments = []
|
self.segments = []
|
||||||
self.EMPTY_SEGMENT = {
|
self.EMPTY_SEGMENT = {
|
||||||
@ -45,8 +51,8 @@ class Theme(object):
|
|||||||
}
|
}
|
||||||
self.pl = pl
|
self.pl = pl
|
||||||
theme_configs = [theme_config]
|
theme_configs = [theme_config]
|
||||||
if top_theme_config:
|
if main_theme_config:
|
||||||
theme_configs.append(top_theme_config)
|
theme_configs.append(main_theme_config)
|
||||||
get_segment = gen_segment_getter(pl, ext, common_config, theme_configs, theme_config.get('default_module'))
|
get_segment = gen_segment_getter(pl, ext, common_config, theme_configs, theme_config.get('default_module'))
|
||||||
for segdict in itertools.chain((theme_config['segments'],),
|
for segdict in itertools.chain((theme_config['segments'],),
|
||||||
theme_config['segments'].get('above', ())):
|
theme_config['segments'].get('above', ())):
|
||||||
|
@ -118,11 +118,11 @@ class TestConfig(TestCase):
|
|||||||
|
|
||||||
segment_info = Args(prompt_count=1)
|
segment_info = Args(prompt_count=1)
|
||||||
|
|
||||||
with IpyPowerline(True) as powerline:
|
with IpyPowerline(True, {}) as powerline:
|
||||||
for prompt_type in ['in', 'in2']:
|
for prompt_type in ['in', 'in2']:
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
with IpyPowerline(False) as powerline:
|
with IpyPowerline(False, {}) as powerline:
|
||||||
for prompt_type in ['out', 'rewrite']:
|
for prompt_type in ['out', 'rewrite']:
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
powerline.render(matcher_info=prompt_type, segment_info=segment_info)
|
||||||
|
@ -54,10 +54,14 @@ run_test() {
|
|||||||
|
|
||||||
run screen -L -c tests/test_shells/screenrc -d -m -S "$SESNAME" \
|
run screen -L -c tests/test_shells/screenrc -d -m -S "$SESNAME" \
|
||||||
env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "${ARGS[@]}"
|
env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "${ARGS[@]}"
|
||||||
screen -S "$SESNAME" -X readreg a tests/test_shells/input.$SH
|
while ! screen -S "$SESNAME" -X readreg a tests/test_shells/input.$SH ; do
|
||||||
|
sleep 0.1s
|
||||||
|
done
|
||||||
# Wait for screen to initialize
|
# Wait for screen to initialize
|
||||||
sleep 1
|
sleep 1
|
||||||
screen -S "$SESNAME" -p 0 -X width 300 1
|
while ! screen -S "$SESNAME" -p 0 -X width 300 1 ; do
|
||||||
|
sleep 0.1s
|
||||||
|
done
|
||||||
if test "x${SH}" = "xdash" ; then
|
if test "x${SH}" = "xdash" ; then
|
||||||
# If I do not use this hack for dash then output will look like
|
# If I do not use this hack for dash then output will look like
|
||||||
#
|
#
|
||||||
|
Loading…
x
Reference in New Issue
Block a user