Release 2.3

- Added ability to hide domain part of the user name to common.env.user segment.
- Added ability to show conda environment to virtualenv segment.
- Added systemd service file.
- Added ability to detect internal_ip interface using default gateway.
- Added support for password-protected connections in mpd player bindings.
- Added `output` option to i3wm.workspaces segment to filter workspaces based on
  their output.
- Added “charging” indicator to battery segment.
- Made tmux bindings show zoom indicator in window status.
- Fixed tmux bindings so that they support tmux-2.1.
- Fixed support for unicode characters in common.time.date segment.
This commit is contained in:
Foo 2015-10-20 12:54:26 +03:00
commit 7ed55bb25c
46 changed files with 658 additions and 360 deletions

View File

@ -8,11 +8,11 @@ addons:
packages:
- libssl1.0.0
- zsh
# - tcsh
# - mksh
# - busybox
- tcsh
- mksh
- busybox
# - rc
# - socat
- socat
- bc
language: python
install: tests/install.sh

View File

@ -7,7 +7,7 @@ Powerline
**Powerline is a statusline plugin for vim, and provides statuslines and
prompts for several other applications, including zsh, bash, tmux, IPython,
Awesome and Qtile.**
Awesome, i3 and Qtile.**
* `Support forum`_ (powerline-support@googlegroups.com)
* `Development discussion`_ (powerline-dev@googlegroups.com)

View File

@ -0,0 +1,6 @@
*************
i3wm segments
*************
.. automodule:: powerline.segments.i3wm
:members:

View File

@ -467,7 +467,8 @@ Shell
``client_id``
Identifier unique to one shell instance. Is used to record instance
state by powerline daemon.
state by powerline daemon. In tmux this is the same as :ref:`pane_id
<dev-seginfo-shell-renarg-pane_id>`.
It is not guaranteed that existing client ID will not be retaken
when old shell with this ID quit: usually process PID is used as
@ -481,6 +482,14 @@ Shell
Local theme that will be used by shell. One should not rely on the
existence of this key.
.. _dev-seginfo-shell-renarg-pane_id:
``pane_id``
Identifier unique to each tmux pane. Is always an integer, optional.
Obtained by using ``tmux display -p '#D'``, then all leading spaces
and per cent signs are stripped and the result is converted into an
integer.
Other keys, if any, are specific to segments.
Ipython

View File

@ -113,8 +113,7 @@ install a patched font.
Patched fonts
-------------
This method is the fallback method and works for every terminal, with the
exception of :ref:`rxvt-unicode <tips-and-tricks-urxvt>`.
This method is the fallback method and works for every terminal.
Download the font from `powerline-fonts`_. If preferred font cant be found in
the `powerline-fonts`_ repo, then patching the preferred font is needed instead.

View File

@ -22,7 +22,7 @@ Python package
to be installed. ``coreutils`` may be installed using ``brew install
coreutils``.
2. Install Powerline using one of the following commans:
2. Install Powerline using one of the following commands:
.. code-block:: sh

View File

@ -4,7 +4,7 @@ Overview
**Powerline is a statusline plugin for vim, and provides statuslines and
prompts for several other applications, including zsh, bash, tmux, IPython,
Awesome and Qtile.**
Awesome, i3 and Qtile.**
Features
--------

View File

@ -7,6 +7,8 @@ import codecs
from collections import namedtuple
from functools import reduce
from docutils.parsers.rst import Directive
from docutils.parsers.rst.directives import unchanged_required
from docutils import nodes

View File

@ -189,6 +189,25 @@ If your locale encoding is not unicode (any encoding that starts with “utf”
should set up your system to use unicode locale or forget about powerline fancy
characters.
Urxvt unicode3 and frills
-------------------------
Make sure that, whatever urxvt package you're installing, both the `unicode3`
and `frills` features are enabled at compile time. Run
``urxvt --help 2>&1 | grep options:`` to get a list of enabled options.
This should contain at least `frills`, `unicode3` and optionally `iso14755`
if you want to input Unicode characters as well.
Compiler flags example:
--enable-frills \
--enable-unicode3
As long as your terminal emulator is compiled without unicode rendering,
no amount of configuration will make it display unicode characters.
They're being considered 'unnecessary features', but they add negligible
overhead to the size of the installed package (~100KB).
Vim issues
==========
@ -244,8 +263,8 @@ highlighting groups are usually cleared, including those defined by powerline.
To workaround this issue powerline hooks ``Colorscheme`` event, but when you
source vimrc with ``BufWritePost`` (or any other) event, but without ``nested``
this event is not launched. See also `autocmd-nested
<http://vimpluginloader.sourceforge.net/doc/autocmd.txt.html#autocmd-nested>`_
Vim documentation.
<http://vimcommunity.bitbucket.org/doc/autocmd.txt.html#autocmd-nested>`_ Vim
documentation.
Powerline loses color after saving any file
-------------------------------------------

View File

@ -2,11 +2,11 @@ set -g status on
set -g status-utf8 on
set -g status-interval 2
set -g status-left-length 20
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=`tmux display -p "#D"`)'
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=\"`tmux display -p "#D"`\")'
set -g status-right-length 150
set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"
set -g window-status-current-format "#[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#[$_POWERLINE_WINDOW_CURRENT_COLOR]#I $_POWERLINE_LEFT_SOFT_DIVIDER#[$_POWERLINE_WINDOW_NAME_COLOR]#W #[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER"
set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I#F #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"
set -g window-status-current-format "#[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#[$_POWERLINE_WINDOW_CURRENT_COLOR]#I#F $_POWERLINE_LEFT_SOFT_DIVIDER#[$_POWERLINE_WINDOW_NAME_COLOR]#W #[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER"
# Legacy status-left definition to be overwritten for tmux Versions 1.8+
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left -R pane_id=`tmux display -p '#D'`)"
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left -R pane_id=\"`tmux display -p '#D'`\")"
# vim: ft=tmux

View File

@ -1,3 +1,3 @@
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=`tmux display -p "#D"` --width=`tmux display -p "#{client_width}"` -R width_adjust=`tmux show-options -g status-left-length | cut -d" " -f 2`)'
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=`tmux display -p '#D'`)"
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id="`tmux display -p "#D"`" --width=`tmux display -p "#{client_width}"` -R width_adjust=`tmux show-options -g status-left-length | cut -d" " -f 2`)'
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#D'`\")"
# vim: ft=tmux

View File

@ -1,5 +1,5 @@
# powerline_tmux_1.8_plus.conf
# tmux Version 1.8 introduces the 'client_prefix' format variable, applicable
# for versions 1.8+
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env \$POWERLINE_COMMAND \$POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=`tmux display -p '#D'`)"
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env \$POWERLINE_COMMAND \$POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#D'`\")"
# vim: ft=tmux

View File

@ -10,7 +10,7 @@ from itertools import chain
from powerline.lib.overrides import parsedotval, parse_override_var
from powerline.lib.dict import mergeargs
from powerline.lib.encoding import get_preferred_arguments_encoding
from powerline.lib.unicode import u
from powerline.lib.unicode import u, unicode
if sys.version_info < (3,):
@ -49,6 +49,14 @@ def finish_args(environ, args):
))
if args.renderer_arg:
args.renderer_arg = mergeargs((parsedotval(v) for v in args.renderer_arg), remove=True)
if 'pane_id' in args.renderer_arg:
if isinstance(args.renderer_arg['pane_id'], (bytes, unicode)):
try:
args.renderer_arg['pane_id'] = int(args.renderer_arg['pane_id'].lstrip(' %'))
except ValueError:
pass
if 'client_id' not in args.renderer_arg:
args.renderer_arg['client_id'] = args.renderer_arg['pane_id']
args.config_path = (
[path for path in environ.get('POWERLINE_CONFIG_PATHS', '').split(':') if path]
+ (args.config_path or [])

View File

@ -51,7 +51,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "O",
"empty_heart": "O"
"empty_heart": "O",
"online": "C",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -50,7 +50,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥"
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -50,7 +50,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "💙",
"empty_heart": "💛"
"empty_heart": "💛",
"online": "⚡️",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -50,7 +50,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥"
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -50,7 +50,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥"
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -51,7 +51,9 @@
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥"
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {

View File

@ -0,0 +1,10 @@
[Unit]
Description=powerline-daemon - Daemon that improves powerline performance
Documentation=man:powerline-daemon(1)
Documentation=https://powerline.readthedocs.org/en/latest/
[Service]
ExecStart=/usr/bin/powerline-daemon --foreground
[Install]
WantedBy=default.target

View File

@ -134,7 +134,7 @@ class INotify(object):
eno = ctypes.get_errno()
extra = ''
if eno == errno.ENOSPC:
extra = 'You may need to increase the inotify limits on your system, via /proc/sys/inotify/max_user_*'
extra = 'You may need to increase the inotify limits on your system, via /proc/sys/fs/inotify/max_user_*'
raise OSError(eno, self.os.strerror(eno) + str(extra))
def __del__(self):

View File

@ -63,7 +63,7 @@ class TmuxRenderer(Renderer):
if segment_info:
r.update(segment_info)
if 'pane_id' in r:
varname = 'TMUX_PWD_' + r['pane_id'].lstrip('%')
varname = 'TMUX_PWD_' + str(r['pane_id'])
if varname in r['environ']:
r['getcwd'] = lambda: r['environ'][varname]
r['mode'] = mode

View File

@ -8,11 +8,7 @@ import re
from powerline.lib.shell import run_cmd
# XXX Warning: module name must not be equal to the segment name as long as this
# segment is imported into powerline.segments.common module.
def _get_battery(pl):
def _fetch_battery_info(pl):
try:
import dbus
except ImportError:
@ -51,27 +47,37 @@ def _get_battery(pl):
pl.debug('Not using DBUS+UPower with {0}: not a power supply', devpath)
continue
pl.debug('Using DBUS+UPower with {0}', devpath)
return lambda pl: float(
return lambda pl: (
float(
dbus.Interface(dev, dbus_interface=devinterface).Get(
devtype_name,
'Percentage'
),
),
dbus.Interface(dev, dbus_interface=devinterface).Get(
devtype_name,
'Percentage'
)
'State'
) == 1
)
pl.debug('Not using DBUS+UPower as no batteries were found')
if os.path.isdir('/sys/class/power_supply'):
linux_bat_fmt = '/sys/class/power_supply/{0}/capacity'
linux_ac_fmt = '/sys/class/power_supply/{0}/online'
for linux_bat in os.listdir('/sys/class/power_supply'):
cap_path = linux_bat_fmt.format(linux_bat)
online_path = linux_ac_fmt.format(linux_bat)
if linux_bat.startswith('BAT') and os.path.exists(cap_path):
pl.debug('Using /sys/class/power_supply with battery {0}', linux_bat)
def _get_capacity(pl):
def _get_battery_status(pl):
with open(cap_path, 'r') as f:
return int(float(f.readline().split()[0]))
return _get_capacity
pl.debug('Not using /sys/class/power_supply as no batteries were found')
_capacity = int(float(f.readline().split()[0]))
with open(online_path, 'r') as f:
_ac_powered = f.readline() == 1
return _capacity, _ac_powered
return _get_battery_status
pl.debug('Not using /sys/class/power_supply as no batteries were found')
else:
pl.debug('Not using /sys/class/power_supply: no directory')
@ -86,12 +92,12 @@ def _get_battery(pl):
BATTERY_PERCENT_RE = re.compile(r'(\d+)%')
def _get_capacity(pl):
def _get_battery_status(pl):
battery_summary = run_cmd(pl, ['pmset', '-g', 'batt'])
battery_percent = BATTERY_PERCENT_RE.search(battery_summary).group(1)
return int(battery_percent)
return _get_capacity
ac_charging = 'AC' in battery_summary
return int(battery_percent), ac_charging
return _get_battery_status
else:
pl.debug('Not using pmset: executable not found')
@ -110,11 +116,11 @@ def _get_battery(pl):
for battery in wmi.InstancesOf('Win32_Battery'):
pl.debug('Using win32com.client with Win32_Battery')
def _get_capacity(pl):
def _get_battery_status(pl):
# http://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx
return battery.EstimatedChargeRemaining
return battery.EstimatedChargeRemaining, battery.BatteryStatus == 6
return _get_capacity
return _get_battery_status
pl.debug('Not using win32com.client as no batteries were found')
from ctypes import Structure, c_byte, c_ulong, byref
if sys.platform == 'cygwin':
@ -136,52 +142,57 @@ def _get_battery(pl):
('BatteryFullLifeTime', c_ulong)
]
def _get_capacity(pl):
def _get_battery_status(pl):
powerclass = PowerClass()
result = library_loader.kernel32.GetSystemPowerStatus(byref(powerclass))
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa372693(v=vs.85).aspx
if result:
return None
return powerclass.BatteryLifePercent
return powerclass.BatteryLifePercent, powerclass.ACLineStatus == 1
if _get_capacity() is None:
if _get_battery_status() is None:
pl.debug('Not using GetSystemPowerStatus because it failed')
else:
pl.debug('Using GetSystemPowerStatus')
return _get_capacity
return _get_battery_status
raise NotImplementedError
def _get_capacity(pl):
global _get_capacity
def _get_battery_status(pl):
global _get_battery_status
def _failing_get_capacity(pl):
def _failing_get_status(pl):
raise NotImplementedError
try:
_get_capacity = _get_battery(pl)
_get_battery_status = _fetch_battery_info(pl)
except NotImplementedError:
_get_capacity = _failing_get_capacity
_get_battery_status = _failing_get_status
except Exception as e:
pl.exception('Exception while obtaining battery capacity getter: {0}', str(e))
_get_capacity = _failing_get_capacity
return _get_capacity(pl)
pl.exception('Exception while obtaining battery status: {0}', str(e))
_get_battery_status = _failing_get_status
return _get_battery_status(pl)
def battery(pl, format='{capacity:3.0%}', steps=5, gamify=False, full_heart='O', empty_heart='O'):
def battery(pl, format='{ac_state} {capacity:3.0%}', steps=5, gamify=False, full_heart='O', empty_heart='O', online='C', offline=' '):
'''Return battery charge status.
:param str format:
Percent format in case gamify is False.
Percent format in case gamify is False. Format arguments: ``ac_state``
which is equal to either ``online`` or ``offline`` string arguments and
``capacity`` which is equal to current battery capacity in interval [0,
100].
:param int steps:
Number of discrete steps to show between 0% and 100% capacity if gamify
is True.
:param bool gamify:
Measure in hearts () instead of percentages. For full hearts
``battery_full`` highlighting group is preferred, for empty hearts there
is ``battery_empty``.
is ``battery_empty``. ``battery_online`` or ``battery_offline`` group
will be used for leading segment containing ``online`` or ``offline``
argument contents.
:param str full_heart:
Heart displayed for full part of battery.
:param str empty_heart:
@ -189,21 +200,32 @@ def battery(pl, format='{capacity:3.0%}', steps=5, gamify=False, full_heart='O',
another gradient level and highlighting group, so it is OK for it to be
the same as full_heart as long as necessary highlighting groups are
defined.
:param str online:
Symbol used if computer is connected to a power supply.
:param str offline:
Symbol used if computer is not connected to a power supply.
``battery_gradient`` and ``battery`` groups are used in any case, first is
preferred.
Highlight groups used: ``battery_full`` or ``battery_gradient`` (gradient) or ``battery``, ``battery_empty`` or ``battery_gradient`` (gradient) or ``battery``.
Highlight groups used: ``battery_full`` or ``battery_gradient`` (gradient) or ``battery``, ``battery_empty`` or ``battery_gradient`` (gradient) or ``battery``, ``battery_online`` or ``battery_ac_state`` or ``battery_gradient`` (gradient) or ``battery``, ``battery_offline`` or ``battery_ac_state`` or ``battery_gradient`` (gradient) or ``battery``.
'''
try:
capacity = _get_capacity(pl)
capacity, ac_powered = _get_battery_status(pl)
except NotImplementedError:
pl.info('Unable to get battery capacity.')
pl.info('Unable to get battery status.')
return None
ret = []
if gamify:
denom = int(steps)
numer = int(denom * capacity / 100)
ret.append({
'contents': online if ac_powered else offline,
'draw_inner_divider': False,
'highlight_groups': ['battery_online' if ac_powered else 'battery_offline', 'battery_ac_state', 'battery_gradient', 'battery'],
'gradient_level': 0,
})
ret.append({
'contents': full_heart * numer,
'draw_inner_divider': False,
@ -220,7 +242,7 @@ def battery(pl, format='{capacity:3.0%}', steps=5, gamify=False, full_heart='O',
})
else:
ret.append({
'contents': format.format(capacity=(capacity / 100.0)),
'contents': format.format(ac_state=(online if ac_powered else offline), capacity=(capacity / 100.0)),
'highlight_groups': ['battery_gradient', 'battery'],
# Gradients are “least alert most alert” by default, capacity has
# the opposite semantics.

View File

@ -19,9 +19,20 @@ def environment(pl, segment_info, variable=None):
@requires_segment_info
def virtualenv(pl, segment_info):
'''Return the name of the current Python virtualenv.'''
return os.path.basename(segment_info['environ'].get('VIRTUAL_ENV', '')) or None
def virtualenv(pl, segment_info, ignore_venv=False, ignore_conda=False):
'''Return the name of the current Python or conda virtualenv.
:param bool ignore_venv:
Whether to ignore virtual environments. Default is False.
:param bool ignore_conda:
Whether to ignore conda environments. Default is False.
'''
return (
(not ignore_venv and
os.path.basename(segment_info['environ'].get('VIRTUAL_ENV', ''))) or
(not ignore_conda and
segment_info['environ'].get('CONDA_DEFAULT_ENV', '')) or
None)
@requires_segment_info
@ -148,11 +159,13 @@ username = False
_geteuid = getattr(os, 'geteuid', lambda: 1)
def user(pl, hide_user=None):
def user(pl, hide_user=None, hide_domain=False):
'''Return the current user.
:param str hide_user:
Omit showing segment for users with names equal to this string.
:param bool hide_domain:
Drop domain component if it exists in a username (delimited by '@').
Highlights the user with the ``superuser`` if the effective user ID is 0.
@ -166,6 +179,11 @@ def user(pl, hide_user=None):
return None
if username == hide_user:
return None
if hide_domain:
try:
username = username[:username.index('@')]
except ValueError:
pass
euid = _geteuid()
return [{
'contents': username,

View File

@ -101,16 +101,24 @@ else:
return 0
def internal_ip(pl, interface='auto', ipv=4):
family = netifaces.AF_INET6 if ipv == 6 else netifaces.AF_INET
if interface == 'auto':
try:
interface = next(iter(sorted(netifaces.interfaces(), key=_interface_key, reverse=True)))
except StopIteration:
pl.info('No network interfaces found')
return None
elif interface == 'default_gateway':
try:
interface = netifaces.gateways()['default'][family][1]
except KeyError:
pl.info('No default gateway found for IPv{0}', ipv)
return None
addrs = netifaces.ifaddresses(interface)
try:
return addrs[netifaces.AF_INET6 if ipv == 6 else netifaces.AF_INET][0]['addr']
return addrs[family][0]['addr']
except (KeyError, IndexError):
pl.info("No IPv{0} address found for interface {1}", ipv, interface)
return None
@ -130,6 +138,11 @@ Requires ``netifaces`` module to work properly.
#. ``teredo`` followed by number or the end of string.
#. Any other interface that is not ``lo*``.
#. ``lo`` followed by number or the end of string.
Use ``default_gateway`` to detect the interface based on the machine's
`default gateway <https://en.wikipedia.org/wiki/Default_gateway>`_ (i.e.,
the router to which it is connected).
:param int ipv:
4 or 6 for ipv4 and ipv6 respectively, depending on which IP address you
need exactly.
@ -150,7 +163,10 @@ try:
return if_io.bytes_recv, if_io.bytes_sent
def _get_interfaces():
io_counters = psutil.network_io_counters(pernic=True)
try:
io_counters = psutil.net_io_counters(pernic=True)
except AttributeError:
io_counters = psutil.network_io_counters(pernic=True)
for interface, data in io_counters.items():
if data:
yield interface, data.bytes_recv, data.bytes_sent

View File

@ -167,14 +167,16 @@ Requires cmus-remote command be acessible from $PATH.
class MpdPlayerSegment(PlayerSegment):
def get_player_status(self, pl, host='localhost', port=6600):
def get_player_status(self, pl, host='localhost', password=None, port=6600):
try:
import mpd
except ImportError:
if password:
host = password + '@' + host
now_playing = run_cmd(pl, [
'mpc', 'current',
'-f', '%album%\n%artist%\n%title%\n%time%',
'-h', str(host),
'-h', host,
'-p', str(port)
], strip=False)
if not now_playing:
@ -189,6 +191,8 @@ class MpdPlayerSegment(PlayerSegment):
else:
client = mpd.MPDClient()
client.connect(host, port)
if password:
client.password(password)
now_playing = client.currentsong()
if not now_playing:
return
@ -220,6 +224,8 @@ package) or alternatively the ``mpc`` command to be acessible from $PATH.
{0}
:param str host:
Host on which mpd runs.
:param str password:
Password used for connecting to daemon.
:param int port:
Port which should be connected to.
''').format(_common_args.format('mpd')))

View File

@ -16,8 +16,13 @@ def date(pl, format='%Y-%m-%d', istime=False):
Highlight groups used: ``time`` or ``date``.
'''
try:
contents = datetime.now().strftime(format)
except UnicodeEncodeError:
contents = datetime.now().strftime(format.encode('utf-8')).decode('utf-8')
return [{
'contents': datetime.now().strftime(format),
'contents': contents,
'highlight_groups': (['time'] if istime else []) + ['date'],
'divider_highlight_group': 'time:divider' if istime else None,
}]

View File

@ -19,7 +19,7 @@ def calcgrp(w):
return group
def workspaces(pl, only_show=None, strip=0):
def workspaces(pl, only_show=None, output=None, strip=0):
'''Return list of used workspaces
:param list only_show:
@ -27,6 +27,9 @@ def workspaces(pl, only_show=None, strip=0):
``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces
are shown.
:param str output:
If specified, only workspaces on this output are shown.
:param int strip:
Specifies how many characters from the front of each workspace name
should be stripped (e.g. to remove workspace numbers). Defaults to zero.
@ -45,7 +48,10 @@ def workspaces(pl, only_show=None, strip=0):
return [{
'contents': w['name'][min(len(w['name']), strip):],
'highlight_groups': calcgrp(w)
} for w in conn.get_workspaces() if not only_show or any((w[typ] for typ in only_show))]
} for w in conn.get_workspaces()
if (not only_show or any(w[typ] for typ in only_show))
and (not output or w['output'] == output)
]
@requires_segment_info

View File

@ -147,38 +147,42 @@ def create_ebuilds(version_string, overlay, user, **kwargs):
live_ebuild = None
for ebuild in os.listdir(pdir):
if ebuild.endswith('.ebuild') and '9999' in ebuild:
live_ebuild_base = ebuild
live_ebuild = os.path.join(pdir, ebuild)
break
assert(live_ebuild)
vcur = os.path.join(pdir, '{0}-{1}.ebuild'.format(pn, version_string))
with open(live_ebuild) as LEF:
with open(vcur, 'w') as F:
dropnext = False
for line in LEF:
if line.startswith('EGIT'):
# Drop all EGIT_… and the next empty line
dropnext = True
next_re = re.compile('^$')
continue
if dropnext:
assert(next_re.match(line))
dropnext = False
continue
if line.startswith('# Note the lack of an assignment to ${S}'):
next_re = re.compile('^#')
dropnext = True
line = 'S="${WORKDIR}/${MY_P}"\n'
if line.startswith('inherit'):
line = line.replace(' git-r3', '')
line += '\n'
line += 'MY_PN="powerline-status"\n'
line += 'MY_P="${MY_PN}-${PV}"'
line += '\n'
elif line.startswith('HOMEPAGE'):
line += 'SRC_URI="mirror://pypi/p/${MY_PN}/${MY_P}.tar.gz"\n'
elif line.startswith('KEYWORDS'):
line = 'KEYWORDS="~amd64 ~ppc ~x86 ~x86-fbsd"\n'
F.write(line)
if pn == 'powerline-vim':
with open(live_ebuild) as LEF:
with open(vcur, 'w') as F:
dropnext = False
for line in LEF:
if line.startswith('EGIT'):
# Drop all EGIT_… and the next empty line
dropnext = True
next_re = re.compile('^$')
continue
if dropnext:
assert(next_re.match(line))
dropnext = False
continue
if line.startswith('# Note the lack of an assignment to ${S}'):
next_re = re.compile('^#')
dropnext = True
line = 'S="${WORKDIR}/${MY_P}"\n'
if line.startswith('inherit'):
line = line.replace(' git-r3', '')
line += '\n'
line += 'MY_PN="powerline-status"\n'
line += 'MY_P="${MY_PN}-${PV}"'
line += '\n'
elif line.startswith('HOMEPAGE'):
line += 'SRC_URI="mirror://pypi/p/${MY_PN}/${MY_P}.tar.gz"\n'
elif line.startswith('KEYWORDS'):
line = 'KEYWORDS="~amd64 ~ppc ~x86 ~x86-fbsd"\n'
F.write(line)
else:
os.symlink(live_ebuild_base, vcur)
new_files.append(vcur)
check_call(['ebuild', vcur, 'manifest'])
new_files.append(os.path.join(pdir, 'Manifest'))

View File

@ -59,7 +59,7 @@ else:
def get_version():
base_version = '2.2'
base_version = '2.3'
base_version += '.dev9999'
try:
return base_version + '+git.' + str(subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip())
@ -70,7 +70,7 @@ def get_version():
setup(
name='powerline-status',
version='2.2',
version='2.3',
description='The ultimate statusline/prompt utility.',
long_description=README,
classifiers=[

33
tests/common.sh Normal file
View File

@ -0,0 +1,33 @@
. tests/bot-ci/scripts/common/main.sh
set +x
: ${PYTHON:=python}
FAILED=0
FAIL_SUMMARY=""
enter_suite() {
local suite_name="$1"
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE}/$suite_name"
}
exit_suite() {
if test $FAILED -ne 0 ; then
echo "Suite ${POWERLINE_CURRENT_SUITE} failed, summary:"
echo "${FAIL_SUMMARY}"
fi
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE%/*}"
exit $FAILED
}
fail() {
local test_name="$1"
local fail_char="$2"
local message="$3"
local full_msg="$fail_char $POWERLINE_CURRENT_SUITE|$test_name :: $message"
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}"
echo "Failed: $full_msg"
echo "$full_msg" >> tests/failures
FAILED=1
}

View File

@ -29,7 +29,11 @@ checkout_cached_dir git://github.com/powerline/deps tests/bot-ci/deps
mkdir -p "$HOME/opt"
if test -n "$USE_UCS2_PYTHON" ; then
pip install virtualenvwrapper
if test "$UCS2_PYTHON_VARIANT" = "2.6" ; then
pip install 'virtualenvwrapper==4.6.0'
else
pip install virtualenvwrapper
fi
set +e
. virtualenvwrapper.sh
set -e

View File

@ -1,5 +1,8 @@
#!/bin/sh
FAILED=0
. tests/common.sh
enter_suite daemon
export ADDRESS="powerline-ipc-test-$$"
echo "Powerline address: $ADDRESS"
if $PYTHON scripts/powerline-daemon -s$ADDRESS ; then
@ -8,16 +11,14 @@ if $PYTHON scripts/powerline-daemon -s$ADDRESS ; then
$PYTHON client/powerline.py --socket $ADDRESS -p/dev/null shell left | \
grep 'file not found'
) ; then
echo "-p/dev/null argument ignored or not treated properly"
FAILED=1
fail "devnull" F "-p/dev/null argument ignored or not treated properly"
fi
if ( \
$PYTHON client/powerline.py --socket $ADDRESS \
-p$PWD/powerline/config_files shell left | \
grep 'file not found'
) ; then
echo "-p/dev/null argument remembered while it should not"
FAILED=1
fail "nodevnull" F "-p/dev/null argument remembered while it should not"
fi
if ! ( \
cd tests && \
@ -25,17 +26,15 @@ if $PYTHON scripts/powerline-daemon -s$ADDRESS ; then
-p$PWD/../powerline/config_files shell left | \
grep 'tests'
) ; then
echo "Output lacks string “tests”"
FAILED=1
fail "segment" F "Output lacks string “tests”"
fi
else
echo "Daemon exited with status $?"
FAILED=1
fail "exitcode" E "Daemon exited with status $?"
fi
if $PYTHON scripts/powerline-daemon -s$ADDRESS -k ; then
:
else
echo "powerline-daemon -k failed with exit code $?"
FAILED=1
fail "-k" F "powerline-daemon -k failed with exit code $?"
fi
exit $FAILED
exit_suite

View File

@ -1,7 +1,10 @@
#!/bin/sh
FAILED=0
. tests/common.sh
enter_suite lint
if ! ${PYTHON} scripts/powerline-lint -p powerline/config_files ; then
echo "Failed powerline-lint"
FAILED=1
fail "test" F "Running powerline-lint failed"
fi
exit $FAILED
exit_suite

View File

@ -1,9 +1,13 @@
#!/bin/sh
FAILED=0
. tests/common.sh
enter_suite python
for file in tests/test_*.py ; do
test_name="${file##*/test_}"
if ! ${PYTHON} $file --verbose --catch ; then
echo "Failed test(s) from $file"
FAILED=1
fail "${test_name%.py}" F "Failed test(s) from $file"
fi
done
exit $FAILED
exit_suite

View File

@ -1,11 +1,12 @@
#!/bin/sh
. tests/bot-ci/scripts/common/main.sh
FAILED=0
. tests/common.sh
enter_suite vim
if test -z "$VIM" ; then
if test -n "$USE_UCS2_PYTHON" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/tip-$UCS2_PYTHON_VARIANT-ucs2-double/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7-0-112-$UCS2_PYTHON_VARIANT-ucs2/vim"
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$UCS2_PYTHON_VARIANT-ucs2-double/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$UCS2_PYTHON_VARIANT-ucs2/vim"
opt_dir="$HOME/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT"
main_path="$opt_dir/lib/python$UCS2_PYTHON_VARIANT"
site_path="$main_path/site-packages"
@ -18,8 +19,8 @@ if test -z "$VIM" ; then
exit 0
fi
if test -d "$ROOT/tests/bot-ci/deps" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/tip-$PYTHON_MM/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7-0-112-$PYTHON_MM/vim"
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$PYTHON_MM/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$PYTHON_MM/vim"
else
NEW_VIM="vim"
fi
@ -42,28 +43,29 @@ export POWERLINE_THEME_OVERRIDES='default.segments.left=[]'
test_script() {
local vim="$1"
local script="$2"
local test_name_prefix="$3"
echo "Running script $script with $vim"
if ! test -e "$vim" ; then
return 0
fi
if ! "$vim" -u NONE -S $script || test -f message.fail ; then
echo "Failed script $script run with $VIM" >&2
local test_name="$test_name_prefix-${script##*/}"
fail "${test_name%.vim}" F "Failed script $script run with $VIM"
cat message.fail >&2
rm message.fail
FAILED=1
fi
}
for script in tests/test_*.vim ; do
if test "${script%.old.vim}" = "${script}" ; then
test_script "$NEW_VIM" "$script"
test_script "$NEW_VIM" "$script" new
fi
done
if test -e "$OLD_VIM" ; then
for script in tests/test_*.old.vim ; do
test_script "$OLD_VIM" "$script"
test_script "$OLD_VIM" "$script" old
done
fi
exit $FAILED
exit_suite

View File

@ -1,8 +1,13 @@
#!/bin/sh
set -e
FAILED=0
if ! sh tests/test_in_vterm/test.sh ; then
echo "Failed vterm"
FAILED=1
fi
exit $FAILED
. tests/common.sh
enter_suite vterm
for t in tests/test_in_vterm/test_*.sh ; do
test_name="${t##*/test_}"
if ! sh "$t" ; then
fail "${test_name%.sh}" F "Failed running $t"
fi
done
exit_suite

View File

@ -1,20 +1,16 @@
#!/bin/bash
. tests/bot-ci/scripts/common/main.sh
. tests/common.sh
enter_suite root
: ${USER:=`id -un`}
: ${HOME:=`getent passwd $USER | cut -d: -f6`}
export USER HOME
FAILED=0
if test "$TRAVIS" = true ; then
export PATH="$HOME/opt/fish/bin:${PATH}"
export PATH="$PWD/tests/bot-ci/deps/rc:$PATH"
export PATH="$PWD/tests/bot-ci/deps/mksh:$PATH"
export PATH="$PWD/tests/bot-ci/deps/busybox:$PATH"
export PATH="$PWD/tests/bot-ci/deps/tcsh:$PATH"
export PATH="$PWD/tests/bot-ci/deps/socat:$PATH"
if test "$PYTHON_IMPLEMENTATION" = "CPython" ; then
export PATH="$HOME/opt/zsh-${PYTHON_MM}${USE_UCS2_PYTHON:+-ucs2}/bin:${PATH}"
@ -38,9 +34,16 @@ fi
export PYTHON="${PYTHON:=python}"
export PYTHONPATH="${PYTHONPATH}${PYTHONPATH:+:}`realpath .`"
for script in tests/run_*_tests.sh ; do
test_name="${script##*/run_}"
if ! sh $script ; then
echo "Failed $script"
FAILED=1
fail "${test_name%_tests.sh}" F "Failed $script"
fi
done
exit $FAILED
if test -e tests/failures ; then
echo "Some tests failed. Summary:"
cat tests/failures
rm tests/failures
fi
exit_suite

View File

@ -1,55 +0,0 @@
#!/bin/sh
. tests/bot-ci/scripts/common/main.sh
set +x
FAILED=0
rm -rf tests/vterm
mkdir tests/vterm
mkdir tests/vterm/path
ln -s "$(which "${PYTHON}")" tests/vterm/path/python
ln -s "$(which bash)" tests/vterm/path
ln -s "$(which env)" tests/vterm/path
ln -s "$(which cut)" tests/vterm/path
ln -s "$PWD/scripts/powerline-render" tests/vterm/path
ln -s "$PWD/scripts/powerline-config" tests/vterm/path
cp -r tests/terminfo tests/vterm
FAIL_SUMMARY=""
test_tmux() {
if test "$PYTHON_IMPLEMENTATION" = PyPy; then
# FIXME PyPy3 segfaults for some reason, PyPy does it as well, but
# occasionally.
return 0
fi
if ! which "${POWERLINE_TMUX_EXE}" ; then
return 0
fi
ln -sf "$(which "${POWERLINE_TMUX_EXE}")" tests/vterm/path
f=tests/test_in_vterm/test_tmux.py
if ! "${PYTHON}" $f ; then
echo "Failed vterm test $f"
FAILED=1
FAIL_SUMMARY="$FAIL_SUMMARY${NL}F $POWERLINE_TMUX_EXE $f"
fi
}
if test -z "$POWERLINE_TMUX_EXE" && test -d tests/bot-ci/deps/tmux ; then
for tmux in tests/bot-ci/deps/tmux/tmux-*/tmux ; do
export POWERLINE_TMUX_EXE="$PWD/$tmux"
test_tmux || true
done
else
export POWERLINE_TMUX_EXE="${POWERLINE_TMUX_EXE:-tmux}"
test_tmux || true
fi
if test $FAILED -eq 0 ; then
echo "$FAIL_SUMMARY"
rm -rf tests/vterm
fi
exit $FAILED

View File

@ -18,7 +18,7 @@ from powerline import get_fallback_logger
from tests.lib.terminal import ExpectProcess
VTERM_TEST_DIR = os.path.abspath('tests/vterm')
VTERM_TEST_DIR = os.path.abspath('tests/vterm_tmux')
def cell_properties_key_to_shell_escape(cell_properties_key):
@ -193,57 +193,57 @@ def main(attempts=3):
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 127),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 124),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
), expected_result_new=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 127),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 124),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
), expected_result_2_0=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1 '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 128),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 125),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
))
@ -265,10 +265,10 @@ def main(attempts=3):
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' <'),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'sh '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'h '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
@ -278,10 +278,10 @@ def main(attempts=3):
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' <'),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'sh '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'h '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
@ -291,10 +291,10 @@ def main(attempts=3):
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), '<'),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'ash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),

View File

@ -0,0 +1,52 @@
#!/bin/sh
. tests/common.sh
enter_suite tmux
rm -rf tests/vterm_tmux
mkdir tests/vterm_tmux
mkdir tests/vterm_tmux/path
ln -s "$(which "${PYTHON}")" tests/vterm_tmux/path/python
ln -s "$(which bash)" tests/vterm_tmux/path
ln -s "$(which env)" tests/vterm_tmux/path
ln -s "$(which cut)" tests/vterm_tmux/path
ln -s "$PWD/scripts/powerline-render" tests/vterm_tmux/path
ln -s "$PWD/scripts/powerline-config" tests/vterm_tmux/path
cp -r tests/terminfo tests/vterm_tmux
test_tmux() {
if test "$PYTHON_IMPLEMENTATION" = PyPy; then
# FIXME PyPy3 segfaults for some reason, PyPy does it as well, but
# occasionally.
return 0
fi
if ! which "${POWERLINE_TMUX_EXE}" ; then
return 0
fi
ln -sf "$(which "${POWERLINE_TMUX_EXE}")" tests/vterm_tmux/path
f=tests/test_in_vterm/test_tmux.py
if ! "${PYTHON}" $f ; then
local test_name="$("$POWERLINE_TMUX_EXE" -V 2>&1 | cut -d' ' -f2)"
fail "$test_name" F "Failed vterm test $f"
fi
}
if test -z "$POWERLINE_TMUX_EXE" && test -d tests/bot-ci/deps/tmux ; then
for tmux in tests/bot-ci/deps/tmux/tmux-*/tmux ; do
export POWERLINE_TMUX_EXE="$PWD/$tmux"
test_tmux || true
done
else
export POWERLINE_TMUX_EXE="${POWERLINE_TMUX_EXE:-tmux}"
test_tmux || true
fi
if test $FAILED -eq 0 ; then
rm -rf tests/vterm_tmux
else
echo "$FAIL_SUMMARY"
fi
exit_suite

View File

@ -7,6 +7,7 @@ import os
from functools import partial
from collections import namedtuple
from time import sleep
from platform import python_implementation
from powerline.segments import shell, tmux, pdb, i3wm
from powerline.lib.vcs import get_fallback_create_watcher
@ -397,6 +398,29 @@ class TestNet(TestCommon):
interfaces[:] = ()
self.assertEqual(self.module.internal_ip(pl=pl, ipv=6), None)
gateways = {
'default': {
netifaces.AF_INET: ('192.168.100.1', 'enp2s0'),
netifaces.AF_INET6: ('feff::5446:5eff:fe5a:0001', 'enp2s0')
}
}
with replace_module_module(
self.module, 'netifaces',
interfaces=(lambda: interfaces),
ifaddresses=(lambda interface: addr[interface]),
gateways=(lambda: gateways),
AF_INET=netifaces.AF_INET,
AF_INET6=netifaces.AF_INET6,
):
# default gateway has specified address family
self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=4), '192.168.100.200')
self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=6), 'feff::5446:5eff:fe5a:7777%enp2s0')
# default gateway doesn't have specified address family
gateways['default'] = {}
self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=4), None)
self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=6), None)
def test_network_load(self):
def gb(interface):
return None
@ -472,15 +496,15 @@ class TestEnv(TestCommon):
pass
def username(self):
return 'def'
return 'def@DOMAIN.COM'
if hasattr(self.module, 'psutil') and not callable(self.module.psutil.Process.username):
username = property(username)
struct_passwd = namedtuple('struct_passwd', ('pw_name',))
new_psutil = new_module('psutil', Process=Process)
new_pwd = new_module('pwd', getpwuid=lambda uid: struct_passwd(pw_name='def'))
new_getpass = new_module('getpass', getuser=lambda: 'def')
new_pwd = new_module('pwd', getpwuid=lambda uid: struct_passwd(pw_name='def@DOMAIN.COM'))
new_getpass = new_module('getpass', getuser=lambda: 'def@DOMAIN.COM')
pl = Pl()
with replace_attr(self.module, 'pwd', new_pwd):
with replace_attr(self.module, 'getpass', new_getpass):
@ -488,12 +512,18 @@ class TestEnv(TestCommon):
with replace_attr(self.module, 'psutil', new_psutil):
with replace_attr(self.module, '_geteuid', lambda: 5):
self.assertEqual(self.module.user(pl=pl), [
{'contents': 'def', 'highlight_groups': ['user']}
{'contents': 'def@DOMAIN.COM', 'highlight_groups': ['user']}
])
self.assertEqual(self.module.user(pl=pl, hide_user='abc'), [
{'contents': 'def@DOMAIN.COM', 'highlight_groups': ['user']}
])
self.assertEqual(self.module.user(pl=pl, hide_domain=False), [
{'contents': 'def@DOMAIN.COM', 'highlight_groups': ['user']}
])
self.assertEqual(self.module.user(pl=pl, hide_user='def@DOMAIN.COM'), None)
self.assertEqual(self.module.user(pl=pl, hide_domain=True), [
{'contents': 'def', 'highlight_groups': ['user']}
])
self.assertEqual(self.module.user(pl=pl, hide_user='def'), None)
with replace_attr(self.module, '_geteuid', lambda: 0):
self.assertEqual(self.module.user(pl=pl), [
{'contents': 'def', 'highlight_groups': ['superuser', 'user']}
@ -602,8 +632,39 @@ class TestEnv(TestCommon):
pl = Pl()
with replace_env('VIRTUAL_ENV', '/abc/def/ghi') as segment_info:
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
segment_info['environ'].pop('VIRTUAL_ENV')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
with replace_env('CONDA_DEFAULT_ENV', 'foo') as segment_info:
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), 'foo')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), 'foo')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
segment_info['environ'].pop('CONDA_DEFAULT_ENV')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
with replace_env('CONDA_DEFAULT_ENV', 'foo', environ={'VIRTUAL_ENV': '/sbc/def/ghi'}) as segment_info:
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), 'foo')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
segment_info['environ'].pop('CONDA_DEFAULT_ENV')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_conda=True), 'ghi')
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True), None)
self.assertEqual(self.module.virtualenv(pl=pl, segment_info=segment_info, ignore_venv=True, ignore_conda=True), None)
def test_environment(self):
pl = Pl()
@ -686,6 +747,12 @@ class TestTime(TestCommon):
with replace_attr(self.module, 'datetime', Args(now=lambda: Args(strftime=lambda fmt: fmt))):
self.assertEqual(self.module.date(pl=pl), [{'contents': '%Y-%m-%d', 'highlight_groups': ['date'], 'divider_highlight_group': None}])
self.assertEqual(self.module.date(pl=pl, format='%H:%M', istime=True), [{'contents': '%H:%M', 'highlight_groups': ['time', 'date'], 'divider_highlight_group': 'time:divider'}])
unicode_date = self.module.date(pl=pl, format='\u231a', istime=True)
expected_unicode_date = [{'contents': '\u231a', 'highlight_groups': ['time', 'date'], 'divider_highlight_group': 'time:divider'}]
if python_implementation() == 'PyPy' and sys.version_info >= (3,):
if unicode_date != expected_unicode_date:
raise SkipTest('Dates do not match, see https://bitbucket.org/pypy/pypy/issues/2161/pypy3-strftime-does-not-accept-unicode')
self.assertEqual(unicode_date, expected_unicode_date)
def test_fuzzy_time(self):
time = Args(hour=0, minute=45)
@ -819,10 +886,10 @@ class TestI3WM(TestCase):
def test_workspaces(self):
pl = Pl()
with replace_attr(i3wm, 'conn', Args(get_workspaces=lambda: iter([
{'name': '1: w1', 'focused': False, 'urgent': False, 'visible': False},
{'name': '2: w2', 'focused': False, 'urgent': False, 'visible': True},
{'name': '3: w3', 'focused': False, 'urgent': True, 'visible': True},
{'name': '4: w4', 'focused': True, 'urgent': True, 'visible': True},
{'name': '1: w1', 'output': 'LVDS1', 'focused': False, 'urgent': False, 'visible': False},
{'name': '2: w2', 'output': 'LVDS1', 'focused': False, 'urgent': False, 'visible': True},
{'name': '3: w3', 'output': 'HDMI1', 'focused': False, 'urgent': True, 'visible': True},
{'name': '4: w4', 'output': 'DVI01', 'focused': True, 'urgent': True, 'visible': True},
]))):
self.assertEqual(i3wm.workspaces(pl=pl), [
{'contents': '1: w1', 'highlight_groups': ['workspace']},
@ -850,6 +917,15 @@ class TestI3WM(TestCase):
{'contents': 'w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
{'contents': 'w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
])
self.assertEqual(i3wm.workspaces(pl=pl, only_show=['focused', 'urgent'], output='DVI01'), [
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
])
self.assertEqual(i3wm.workspaces(pl=pl, only_show=['visible'], output='HDMI1'), [
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
])
self.assertEqual(i3wm.workspaces(pl=pl, only_show=['visible'], strip=3, output='LVDS1'), [
{'contents': 'w2', 'highlight_groups': ['w_visible', 'workspace']},
])
def test_mode(self):
pl = Pl()
@ -881,12 +957,12 @@ class TestBat(TestCommon):
def test_battery(self):
pl = Pl()
def _get_capacity(pl):
return 86
def _get_battery_status(pl):
return 86, False
with replace_attr(self.module, '_get_capacity', _get_capacity):
with replace_attr(self.module, '_get_battery_status', _get_battery_status):
self.assertEqual(self.module.battery(pl=pl), [{
'contents': '86%',
'contents': ' 86%',
'highlight_groups': ['battery_gradient', 'battery'],
'gradient_level': 14,
}])
@ -896,11 +972,17 @@ class TestBat(TestCommon):
'gradient_level': 14,
}])
self.assertEqual(self.module.battery(pl=pl, steps=7), [{
'contents': '86%',
'contents': ' 86%',
'highlight_groups': ['battery_gradient', 'battery'],
'gradient_level': 14,
}])
self.assertEqual(self.module.battery(pl=pl, gamify=True), [
{
'contents': ' ',
'draw_inner_divider': False,
'highlight_groups': ['battery_offline', 'battery_ac_state', 'battery_gradient', 'battery'],
'gradient_level': 0
},
{
'contents': 'OOOO',
'draw_inner_divider': False,
@ -915,6 +997,12 @@ class TestBat(TestCommon):
}
])
self.assertEqual(self.module.battery(pl=pl, gamify=True, full_heart='+', empty_heart='-', steps='10'), [
{
'contents': ' ',
'draw_inner_divider': False,
'highlight_groups': ['battery_offline', 'battery_ac_state', 'battery_gradient', 'battery'],
'gradient_level': 0
},
{
'contents': '++++++++',
'draw_inner_divider': False,
@ -929,6 +1017,34 @@ class TestBat(TestCommon):
}
])
def test_battery_with_ac_online(self):
pl = Pl()
def _get_battery_status(pl):
return 86, True
with replace_attr(self.module, '_get_battery_status', _get_battery_status):
self.assertEqual(self.module.battery(pl=pl, online='C', offline=' '), [
{
'contents': 'C 86%',
'highlight_groups': ['battery_gradient', 'battery'],
'gradient_level': 14,
}])
def test_battery_with_ac_offline(self):
pl = Pl()
def _get_battery_status(pl):
return 86, False
with replace_attr(self.module, '_get_battery_status', _get_battery_status):
self.assertEqual(self.module.battery(pl=pl, online='C', offline=' '), [
{
'contents': ' 86%',
'highlight_groups': ['battery_gradient', 'battery'],
'gradient_level': 14,
}])
class TestVim(TestCase):
def test_mode(self):

View File

@ -30,6 +30,7 @@ user = os.environ['USER']
REFS_RE = re.compile(r'^\[\d+ refs\]\n')
IPYPY_DEANSI_RE = re.compile(r'\033(?:\[(?:\?\d+[lh]|[^a-zA-Z]+[a-ln-zA-Z])|[=>])')
ZSH_HL_RE = re.compile(r'\033\[\?\d+[hl]')
start_str = 'cd tests/shell/3rd'
if shell == 'pdb':
@ -55,7 +56,10 @@ with codecs.open(fname, 'r', encoding='utf-8') as R:
line = line.replace(user, 'USER')
if pid is not None:
line = line.replace(pid, 'PID')
if shell == 'fish':
if shell == 'zsh':
line = line.replace('\033[0m\033[23m\033[24m\033[J', '')
line = ZSH_HL_RE.subn('', line)[0]
elif shell == 'fish':
res = ''
try:
while line.index('\033[0;'):

View File

@ -1,10 +1,8 @@
#!/bin/sh
. tests/bot-ci/scripts/common/main.sh
set +x
. tests/common.sh
enter_suite shells
: ${PYTHON:=python}
FAIL_SUMMARY=""
FAILED=0
if test "x$1" = "x--fast" ; then
FAST=1
shift
@ -285,9 +283,7 @@ check_test_client() {
esac
expected_mime_type="${expected_mime_type%/*}"
if test "$expected_mime_type" != "$actual_mime_type" ; then
echo "Expected $executable to have MIME type $expected_mime_type, but got $actual_mime_type"
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}M ${executable}"
fail "MIME-$executable" "M" "Expected $executable to have MIME type $expected_mime_type, but got $actual_mime_type"
fi
}
@ -382,8 +378,7 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
fi
echo ">>> $(readlink "tests/shell/path/$SH")"
if ! run_test $TEST_TYPE $TEST_CLIENT $TEST_COMMAND ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T ${TEST_TYPE} ${TEST_CLIENT} ${TEST_COMMAND}"
fail "$SH-$TEST_TYPE-$TEST_CLIENT:test" F "Failed checking $TEST_COMMAND"
fi
done
done
@ -395,8 +390,7 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
echo "Daemon log:"
echo '============================================================'
cat tests/shell/daemon_log
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}L ${TEST_TYPE} ${TEST_CLIENT} ${TEST_COMMAND}"
fail "$SH-$TEST_TYPE-$TEST_CLIENT:log" E "Non-empty daemon log for ${TEST_COMMAND}"
fi
fi
done
@ -406,9 +400,7 @@ if $PYTHON scripts/powerline-daemon -s$ADDRESS > tests/shell/daemon_log_2 2>&1 ;
sleep 1
$PYTHON scripts/powerline-daemon -s$ADDRESS -k
else
echo "Daemon exited with status $?"
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}D"
fail "daemon:run" F "Daemon exited with status $?"
fi
if ! test -z "$(cat tests/shell/daemon_log_2)" ; then
@ -416,8 +408,7 @@ if ! test -z "$(cat tests/shell/daemon_log_2)" ; then
echo "Daemon log (2nd):"
echo '============================================================'
cat tests/shell/daemon_log_2
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}L"
fail "daemon:log" E "Daemon run with non-empty log"
fi
if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \
@ -425,8 +416,7 @@ if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \
&& zsh tests/test_shells/zsh_test_script.zsh 2>/dev/null; then
echo "> zpython"
if ! run_test zpython zpython zsh -f -i ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T zpython zsh -f -i"
fail "zsh-zpython:test" F "Failed checking zsh -f -i"
fi
fi
@ -435,8 +425,7 @@ if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ; then
if test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xsubclass" ; then
echo "> pdb subclass"
if ! run_test subclass python $PDB_PYTHON "$PWD/tests/test_shells/pdb-main.py" ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON $PWD/tests/test_shells/pdb-main.py"
fail "pdb-subclass:test" F "Failed checking $PDB_PYTHON $PWD/tests/test_shells/pdb-main.py"
fi
fi
if test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xmodule" ; then
@ -446,8 +435,7 @@ if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ; then
MODULE="powerline.bindings.pdb.__main__"
fi
if ! run_test module python $PDB_PYTHON -m$MODULE "$PWD/tests/test_shells/pdb-script.py" ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -m$MODULE $PWD/tests/test_shells/pdb-script"
fail "pdb-module:test" F "Failed checking $PDB_PYTHON -m$MODULE $PWD/tests/test_shells/pdb-script"
fi
fi
fi
@ -460,8 +448,7 @@ if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xipython" ; then
export POWERLINE_THEME_OVERRIDES='in.segments.left=[]'
echo "> ipython"
if ! run_test ipython ipython ${IPYTHON_PYTHON} -mIPython ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T ipython"
fail "ipython:test" F "Failed checking ${IPYTHON_PYTHON} -mIPython"
fi
unset POWERLINE_THEME_OVERRIDES
unset POWERLINE_CONFIG_OVERRIDES
@ -470,7 +457,6 @@ fi
if test $FAILED -eq 0 ; then
rm -r tests/shell
else
echo "${FAIL_SUMMARY}"
fi
exit $FAILED
exit_suite

View File

@ -1,52 +1,52 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="/home/USER/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="/home/USER/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
[1] PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
[1] + terminated bgscript.sh
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
abc
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select                            do
 select                             echo $abc
 select                             break
 select                            done
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select                            do
 select                             echo $abc
 select                             break
 select                            done
1) def 2) ghi 3) jkl
                   Select variant  1
                   Select variant  1
def
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_LEFT"
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
 foo  
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_FULL"
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_LEFT"
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
                                                                                                                                                                                                                                                                                                      foo 
 foo  
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_FULL"
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
                                                                                                                                                                                                                                                                                                      foo 
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue

View File

@ -1,52 +1,52 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="/home/USER/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="/home/USER/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
[1] PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
[1] + terminated bgscript.sh
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bindkey -v ; set_theme default
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd   COMMND   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  echo abc
abc
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select  do
 select   echo $abc
 select   break
 select  done
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  false
 INSERT   HOSTNAME  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.hostname.display false
 INSERT  USER  ⋯  tests  shell  3rd  set_theme_option default.segment_data.user.display false
 INSERT  ⋯  tests  shell  3rd  select abc in def ghi jkl
 select  do
 select   echo $abc
 select   break
 select  done
1) def 2) ghi 3) jkl
 Select variant  1
 Select variant  1
def
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_LEFT"
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
 foo  
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_FULL"
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  cd .
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_LEFT"
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
                                                                                                                                                                                                                                                                                                      foo 
 foo  
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above "$ABOVE_FULL"
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  export DISPLAYED_ENV_VAR=foo
                                                                                                                                                                                                                                                                                                      foo 
 INSERT  ⋯  tests  shell  3rd  unset DISPLAYED_ENV_VAR
                                                                                                                                                                                                                                                                                                           
 INSERT  ⋯  tests  shell  3rd  set_theme_option default.segments.above
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue
 INSERT  ⋯  tests  shell  3rd  hash -d foo=$PWD:h ; cd .
 INSERT  ~foo  3rd  set_theme_option default.dividers.left.hard \$ABC
 INSERT $ABC~foo  3rd $ABCtrue