mirror of
https://github.com/powerline/powerline.git
synced 2025-07-26 23:35:04 +02:00
Release 2.8.3
This commit is contained in:
parent
c86faf23cd
commit
8b07f63961
@ -54,7 +54,7 @@ Generic requirements
|
|||||||
Pip installation
|
Pip installation
|
||||||
================
|
================
|
||||||
|
|
||||||
Due to a naming conflict with an unrelated project powerline is available on
|
Due to a naming conflict with an unrelated project, powerline is available on
|
||||||
PyPI under the ``powerline-status`` name:
|
PyPI under the ``powerline-status`` name:
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
@ -66,7 +66,7 @@ development version
|
|||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
pip install --user git+git://github.com/powerline/powerline
|
pip install --user git+https://github.com/powerline/powerline
|
||||||
|
|
||||||
may be used. If powerline was already checked out into some directory
|
may be used. If powerline was already checked out into some directory
|
||||||
|
|
||||||
@ -85,10 +85,9 @@ will have to be done (:file:`~/.local/bin` should be replaced with some path
|
|||||||
present in ``$PATH``).
|
present in ``$PATH``).
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
If ISP blocks git protocol for some reason github also provides ``ssh``
|
We can use either ``https``(``git+ssh://git@github.com/powerline/powerline``)
|
||||||
(``git+ssh://git@github.com/powerline/powerline``) and ``https``
|
or ``https``(``git+https://github.com/powerline/powerline``) protocols.
|
||||||
(``git+https://github.com/powerline/powerline``) protocols. ``git`` protocol
|
``git`` protocol is deprecated by Github.
|
||||||
should be the fastest, but least secure one though.
|
|
||||||
|
|
||||||
Fonts installation
|
Fonts installation
|
||||||
==================
|
==================
|
||||||
|
@ -29,7 +29,7 @@ should be followed:
|
|||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
pip install --user git+git://github.com/powerline/powerline
|
pip install --user git+https://github.com/powerline/powerline
|
||||||
|
|
||||||
will get the latest development version.
|
will get the latest development version.
|
||||||
|
|
||||||
|
@ -16,9 +16,13 @@ Python package
|
|||||||
brew install python
|
brew install python
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
In case :file:`powerline.sh` as a client ``socat`` and ``coreutils`` need
|
There are three variants of the powerline client. The fastest is
|
||||||
to be installed. ``coreutils`` may be installed using ``brew install
|
written in C and will be compiled if the compiler and libraries are
|
||||||
coreutils``.
|
detected during installation. The second fastest option is
|
||||||
|
:file:`powerline.sh` which requires ``socat`` and ``coreutils``.
|
||||||
|
``coreutils`` may be installed using ``brew install
|
||||||
|
coreutils``. If neither of these are viable, then Powerline will
|
||||||
|
utilize a fallback client written in Python.
|
||||||
|
|
||||||
2. Install Powerline using one of the following commands:
|
2. Install Powerline using one of the following commands:
|
||||||
|
|
||||||
@ -30,7 +34,7 @@ Python package
|
|||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
pip install --user git+git://github.com/powerline/powerline
|
pip install --user git+https://github.com/powerline/powerline
|
||||||
|
|
||||||
will get latest development version.
|
will get latest development version.
|
||||||
|
|
||||||
|
@ -193,8 +193,12 @@ I am suffering bad lags before displaying shell prompt
|
|||||||
To get rid of these lags there currently are two options:
|
To get rid of these lags there currently are two options:
|
||||||
|
|
||||||
* Run ``powerline-daemon``. Powerline does not automatically start it for you.
|
* Run ``powerline-daemon``. Powerline does not automatically start it for you.
|
||||||
|
See installation instructions for more details.
|
||||||
* Compile and install ``libzpython`` module that lives in
|
* Compile and install ``libzpython`` module that lives in
|
||||||
https://bitbucket.org/ZyX_I/zpython. This variant is zsh-specific.
|
https://bitbucket.org/ZyX_I/zpython. This variant is zsh-specific.
|
||||||
|
* If you are a python package manager, be sure to set ``POWERLINE_COMMAND``
|
||||||
|
to your Powerline command. See installation instructions for details.
|
||||||
|
|
||||||
|
|
||||||
Prompt is spoiled after completing files in ksh
|
Prompt is spoiled after completing files in ksh
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
@ -5,8 +5,9 @@ Shell prompts
|
|||||||
*************
|
*************
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Powerline daemon is not run automatically by any of my bindings. It is
|
Powerline can operate without a background daemon, but the shell performance
|
||||||
advised to add
|
can be very slow. The Powerline daemon improves this performance
|
||||||
|
significantly, but must be started separately. It is advised to add
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@ -142,3 +143,19 @@ following in ``~/.profile``:
|
|||||||
.. warning::
|
.. warning::
|
||||||
Busybox has two shells: ``ash`` and ``hush``. Second is known to segfault in
|
Busybox has two shells: ``ash`` and ``hush``. Second is known to segfault in
|
||||||
busybox 1.22.1 when using :file:`powerline.sh` script.
|
busybox 1.22.1 when using :file:`powerline.sh` script.
|
||||||
|
|
||||||
|
Python Virtual Environments (conda, pyenv)
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
If your system uses virtual environments to manage different Python versions,
|
||||||
|
such as pyenv or anaconda, these tools will add a performance delay to every
|
||||||
|
shell prompt. This delay can be bypassed by explicitly specifying your command
|
||||||
|
path.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
export POWERLINE_COMMAND={path_to_powerline}
|
||||||
|
|
||||||
|
where ``{path_to_powerline}`` is the full filepath for powerline. If you
|
||||||
|
installed Powerline within an environment, you can find this path for pyenv
|
||||||
|
with ``pyenv which powerline`` or for conda with ``which powerline``.
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
|
||||||
|
|
||||||
from weakref import ref
|
from weakref import ref
|
||||||
|
from atexit import register as atexit
|
||||||
|
|
||||||
from IPython.terminal.prompts import Prompts
|
from IPython.terminal.prompts import Prompts
|
||||||
from pygments.token import Token # NOQA
|
from pygments.token import Token # NOQA
|
||||||
|
|
||||||
from powerline.ipython import IPythonPowerline
|
from powerline.ipython import IPythonPowerline
|
||||||
from powerline.renderers.ipython.since_7 import PowerlinePromptStyle
|
from powerline.renderers.ipython.since_7 import PowerlinePromptStyle
|
||||||
from powerline.bindings.ipython.post_0_11 import PowerlineMagics, ShutdownHook
|
from powerline.bindings.ipython.post_0_11 import PowerlineMagics
|
||||||
|
|
||||||
|
|
||||||
class ConfigurableIPythonPowerline(IPythonPowerline):
|
class ConfigurableIPythonPowerline(IPythonPowerline):
|
||||||
@ -20,7 +19,7 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
|
|||||||
super(ConfigurableIPythonPowerline, self).init(
|
super(ConfigurableIPythonPowerline, self).init(
|
||||||
renderer_module='.since_7')
|
renderer_module='.since_7')
|
||||||
|
|
||||||
def do_setup(self, ip, prompts, shutdown_hook):
|
def do_setup(self, ip, prompts):
|
||||||
prompts.powerline = self
|
prompts.powerline = self
|
||||||
|
|
||||||
msfn_missing = ()
|
msfn_missing = ()
|
||||||
@ -50,18 +49,16 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
|
|||||||
magics = PowerlineMagics(ip, self)
|
magics = PowerlineMagics(ip, self)
|
||||||
ip.register_magics(magics)
|
ip.register_magics(magics)
|
||||||
|
|
||||||
if shutdown_hook:
|
atexit(self.shutdown)
|
||||||
shutdown_hook.powerline = ref(self)
|
|
||||||
|
|
||||||
|
|
||||||
class PowerlinePrompts(Prompts):
|
class PowerlinePrompts(Prompts):
|
||||||
'''Class that returns powerline prompts
|
'''Class that returns powerline prompts
|
||||||
'''
|
'''
|
||||||
def __init__(self, shell):
|
def __init__(self, shell):
|
||||||
shutdown_hook = ShutdownHook(shell)
|
|
||||||
powerline = ConfigurableIPythonPowerline(shell)
|
powerline = ConfigurableIPythonPowerline(shell)
|
||||||
self.shell = shell
|
self.shell = shell
|
||||||
powerline.do_setup(shell, self, shutdown_hook)
|
powerline.do_setup(shell, self)
|
||||||
self.last_output_count = None
|
self.last_output_count = None
|
||||||
self.last_output = {}
|
self.last_output = {}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ _powerline_add_widget() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if test -z "${POWERLINE_CONFIG_COMMAND}" ; then
|
if test -z "${POWERLINE_CONFIG_COMMAND}" ; then
|
||||||
if which powerline-config >/dev/null ; then
|
if which powerline-config >/dev/null 2>/dev/null ; then
|
||||||
typeset -g POWERLINE_CONFIG_COMMAND=powerline-config
|
typeset -g POWERLINE_CONFIG_COMMAND=powerline-config
|
||||||
else
|
else
|
||||||
typeset -g POWERLINE_CONFIG_COMMAND="${_POWERLINE_SOURCED:h:h:h:h}/scripts/powerline-config"
|
typeset -g POWERLINE_CONFIG_COMMAND="${_POWERLINE_SOURCED:h:h:h:h}/scripts/powerline-config"
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"cwd:current_folder": "information:regular",
|
"cwd:current_folder": "information:regular",
|
||||||
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
|
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
|
||||||
"virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] },
|
"virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] },
|
||||||
"attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] }
|
"attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] },
|
||||||
|
"workspace": "information:regular"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
{
|
{
|
||||||
"segments": {
|
"segments": {
|
||||||
"right": [
|
"right": [
|
||||||
{
|
|
||||||
"function": "powerline.segments.common.wthr.weather",
|
|
||||||
"priority": 50
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"function": "powerline.segments.common.time.date"
|
"function": "powerline.segments.common.time.date"
|
||||||
},
|
},
|
||||||
@ -15,14 +11,6 @@
|
|||||||
"format": "%H:%M",
|
"format": "%H:%M",
|
||||||
"istime": true
|
"istime": true
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"function": "powerline.segments.common.mail.email_imap_alert",
|
|
||||||
"priority": 10,
|
|
||||||
"args": {
|
|
||||||
"username": "",
|
|
||||||
"password": ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ class BaseConstructor:
|
|||||||
mapping = {}
|
mapping = {}
|
||||||
for key_node, value_node in node.value:
|
for key_node, value_node in node.value:
|
||||||
key = self.construct_object(key_node, deep=deep)
|
key = self.construct_object(key_node, deep=deep)
|
||||||
if not isinstance(key, collections.Hashable):
|
if not isinstance(key, collections.abc.Hashable):
|
||||||
self.echoerr(
|
self.echoerr(
|
||||||
'While constructing a mapping', node.start_mark,
|
'While constructing a mapping', node.start_mark,
|
||||||
'found unhashable key', key_node.start_mark
|
'found unhashable key', key_node.start_mark
|
||||||
|
@ -6,17 +6,18 @@ import re
|
|||||||
from powerline.theme import requires_segment_info
|
from powerline.theme import requires_segment_info
|
||||||
from powerline.bindings.wm import get_i3_connection
|
from powerline.bindings.wm import get_i3_connection
|
||||||
|
|
||||||
|
|
||||||
WORKSPACE_REGEX = re.compile(r'^[0-9]+: ?')
|
WORKSPACE_REGEX = re.compile(r'^[0-9]+: ?')
|
||||||
|
|
||||||
|
|
||||||
def workspace_groups(w):
|
def workspace_groups(w):
|
||||||
group = []
|
group = []
|
||||||
if w.focused:
|
if w.focused:
|
||||||
|
group.append('workspace:focused')
|
||||||
group.append('w_focused')
|
group.append('w_focused')
|
||||||
if w.urgent:
|
if w.urgent:
|
||||||
|
group.append('workspace:urgent')
|
||||||
group.append('w_urgent')
|
group.append('w_urgent')
|
||||||
if w.visible:
|
if w.visible:
|
||||||
|
group.append('workspace:visible')
|
||||||
group.append('w_visible')
|
group.append('w_visible')
|
||||||
group.append('workspace')
|
group.append('workspace')
|
||||||
return group
|
return group
|
||||||
@ -28,41 +29,152 @@ def format_name(name, strip=False):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def is_empty_workspace(workspace, containers):
|
||||||
|
if workspace.focused or workspace.visible:
|
||||||
|
return False
|
||||||
|
wins = [win for win in containers[workspace.name].leaves()]
|
||||||
|
return False if len(wins) > 0 else True
|
||||||
|
|
||||||
|
WS_ICONS = {"multiple": "M"}
|
||||||
|
|
||||||
|
def get_icon(workspace, separator, icons, show_multiple_icons, ws_containers):
|
||||||
|
icons_tmp = WS_ICONS
|
||||||
|
icons_tmp.update(icons)
|
||||||
|
icons = icons_tmp
|
||||||
|
|
||||||
|
wins = [win for win in ws_containers[workspace.name].leaves() \
|
||||||
|
if win.parent.scratchpad_state == 'none']
|
||||||
|
if len(wins) == 0:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
result = ''
|
||||||
|
cnt = 0
|
||||||
|
for key in icons:
|
||||||
|
if not icons[key] or len(icons[key]) < 1:
|
||||||
|
continue
|
||||||
|
if any(key in win.window_class for win in wins if win.window_class):
|
||||||
|
result += (separator if cnt > 0 else '') + icons[key]
|
||||||
|
cnt += 1
|
||||||
|
if not show_multiple_icons and cnt > 1:
|
||||||
|
if 'multiple' in icons:
|
||||||
|
return icons['multiple']
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
return result
|
||||||
|
|
||||||
@requires_segment_info
|
@requires_segment_info
|
||||||
def workspaces(pl, segment_info, only_show=None, output=None, strip=0):
|
def workspaces(pl, segment_info, only_show=None, output=None, strip=0, format='{name}',
|
||||||
|
icons=WS_ICONS, sort_workspaces=False, show_output=False, priority_workspaces=[],
|
||||||
|
hide_empty_workspaces=False):
|
||||||
'''Return list of used workspaces
|
'''Return list of used workspaces
|
||||||
|
|
||||||
:param list only_show:
|
:param list only_show:
|
||||||
Specifies which workspaces to show. Valid entries are ``"visible"``,
|
Specifies which workspaces to show. Valid entries are ``"visible"``,
|
||||||
``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces
|
``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces
|
||||||
are shown.
|
are shown.
|
||||||
|
|
||||||
:param str output:
|
:param str output:
|
||||||
May be set to the name of an X output. If specified, only workspaces
|
May be set to the name of an X output. If specified, only workspaces
|
||||||
on that output are shown. Overrides automatic output detection by
|
on that output are shown. Overrides automatic output detection by
|
||||||
the lemonbar renderer and bindings.
|
the lemonbar renderer and bindings.
|
||||||
|
Use "__all__" to show workspaces on all outputs.
|
||||||
:param int strip:
|
:param int strip:
|
||||||
Specifies how many characters from the front of each workspace name
|
Specifies how many characters from the front of each workspace name
|
||||||
should be stripped (e.g. to remove workspace numbers). Defaults to zero.
|
should be stripped (e.g. to remove workspace numbers). Defaults to zero.
|
||||||
|
:param str format:
|
||||||
|
Specifies the format used to display workspaces; defaults to ``{name}``.
|
||||||
|
Valid fields are: ``name`` (workspace name), ``number`` (workspace number
|
||||||
|
if present), `stipped_name`` (workspace name stripped of leading number),
|
||||||
|
``icon`` (if available, icon for application running in the workspace,
|
||||||
|
uses the ``multiple`` icon instead of multiple different icons), ``multi_icon``
|
||||||
|
(similar to ``icon``, but does not use ``multiple``, instead joins all icons
|
||||||
|
with a single space)
|
||||||
|
:param dict icons:
|
||||||
|
A dictionary mapping a substring of window classes to strings to be used as an
|
||||||
|
icon for that window class.
|
||||||
|
Further, there is a ``multiple`` icon for workspaces containing more than one
|
||||||
|
window.
|
||||||
|
:param bool sort_workspaces:
|
||||||
|
Sort the workspaces displayed by their name according to the natural ordering.
|
||||||
|
:param bool show_output:
|
||||||
|
Shows the name of the output if more than one output is connected.
|
||||||
|
:param list priority_workspaces:
|
||||||
|
A list of workspace names to be sorted before any other workspaces in the given
|
||||||
|
order.
|
||||||
|
:param bool hide_empty_workspaces:
|
||||||
|
Hides all workspaces without any open window.
|
||||||
|
Also hides non-focussed workspaces containing only an open scratchpad.
|
||||||
|
|
||||||
Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``.
|
|
||||||
|
Highlight groups used: ``workspace`` or ``w_visible``, ``workspace:visible``, ``workspace`` or ``w_focused``, ``workspace:focused``, ``workspace`` or ``w_urgent``, ``workspace:urgent``, ``workspace`` or ``output``.
|
||||||
'''
|
'''
|
||||||
|
conn = get_i3_connection()
|
||||||
|
|
||||||
|
if not output == "__all__":
|
||||||
output = output or segment_info.get('output')
|
output = output or segment_info.get('output')
|
||||||
|
else:
|
||||||
|
output = None
|
||||||
|
|
||||||
return [
|
if output:
|
||||||
{
|
output = [output]
|
||||||
'contents': w.name[strip:],
|
else:
|
||||||
|
output = [o.name for o in conn.get_outputs() if o.active]
|
||||||
|
|
||||||
|
|
||||||
|
def sort_ws(ws):
|
||||||
|
if sort_workspaces:
|
||||||
|
def natural_key(ws):
|
||||||
|
str = ws.name
|
||||||
|
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', str)]
|
||||||
|
ws = sorted(ws, key=natural_key)
|
||||||
|
result = []
|
||||||
|
for n in priority_workspaces:
|
||||||
|
result += [w for w in ws if w.name == n]
|
||||||
|
return result + [w for w in ws if not w.name in priority_workspaces]
|
||||||
|
|
||||||
|
ws_containers = {w_con.name : w_con for w_con in conn.get_tree().workspaces()}
|
||||||
|
|
||||||
|
if len(output) <= 1:
|
||||||
|
res = []
|
||||||
|
if show_output:
|
||||||
|
res += [{
|
||||||
|
'contents': output[0],
|
||||||
|
'highlight_groups': ['output']
|
||||||
|
}]
|
||||||
|
res += [{
|
||||||
|
'contents': format.format(name = w.name[min(len(w.name), strip):],
|
||||||
|
stripped_name = format_name(w.name, strip=True),
|
||||||
|
number = w.num,
|
||||||
|
icon = get_icon(w, '', icons, False, ws_containers),
|
||||||
|
multi_icon = get_icon(w, ' ', icons, True, ws_containers)),
|
||||||
'highlight_groups': workspace_groups(w)
|
'highlight_groups': workspace_groups(w)
|
||||||
}
|
} for w in sort_ws(conn.get_workspaces()) \
|
||||||
for w in get_i3_connection().get_workspaces()
|
if (not only_show or any(getattr(w, tp) for tp in only_show)) \
|
||||||
if ((not only_show or any(getattr(w, typ) for typ in only_show))
|
if w.output == output[0] \
|
||||||
and (not output or w.output == output))
|
if not (hide_empty_workspaces and is_empty_workspace(w, ws_containers))]
|
||||||
]
|
return res
|
||||||
|
else:
|
||||||
|
res = []
|
||||||
|
for n in output:
|
||||||
|
if show_output:
|
||||||
|
res += [{
|
||||||
|
'contents': n,
|
||||||
|
'highlight_groups': ['output']
|
||||||
|
}]
|
||||||
|
res += [{
|
||||||
|
'contents': format.format(name = w.name[min(len(w.name), strip):],
|
||||||
|
stripped_name = format_name(w.name, strip=True),
|
||||||
|
number = w.num,
|
||||||
|
icon = get_icon(w, '', icons, False, ws_containers),
|
||||||
|
multi_icon = get_icon(w, ' ', icons, True, ws_containers)),
|
||||||
|
'highlight_groups': workspace_groups(w)
|
||||||
|
} for w in sort_ws(conn.get_workspaces()) \
|
||||||
|
if (not only_show or any(getattr(w, tp) for tp in only_show)) \
|
||||||
|
if w.output == n \
|
||||||
|
if not (hide_empty_workspaces and is_empty_workspace(w, ws_containers))]
|
||||||
|
return res
|
||||||
|
|
||||||
@requires_segment_info
|
@requires_segment_info
|
||||||
def workspace(pl, segment_info, workspace=None, strip=False):
|
def workspace(pl, segment_info, workspace=None, strip=False, format=None, icons=WS_ICONS):
|
||||||
'''Return the specified workspace name
|
'''Return the specified workspace name
|
||||||
|
|
||||||
:param str workspace:
|
:param str workspace:
|
||||||
@ -73,13 +185,35 @@ def workspace(pl, segment_info, workspace=None, strip=False):
|
|||||||
:param bool strip:
|
:param bool strip:
|
||||||
Specifies whether workspace numbers (in the ``1: name`` format) should
|
Specifies whether workspace numbers (in the ``1: name`` format) should
|
||||||
be stripped from workspace names before being displayed. Defaults to false.
|
be stripped from workspace names before being displayed. Defaults to false.
|
||||||
|
Deprecated: Use {name} or {stripped_name} of format instead.
|
||||||
|
|
||||||
Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``.
|
:param str format:
|
||||||
|
Specifies the format used to display workspaces; defaults to ``{name}``.
|
||||||
|
Valid fields are: ``name`` (workspace name), ``number`` (workspace number
|
||||||
|
if present), `stipped_name`` (workspace name stripped of leading number),
|
||||||
|
``icon`` (if available, icon for application running in the workspace,
|
||||||
|
uses the ``multiple`` icon instead of multiple different icons), ``multi_icon``
|
||||||
|
(similar to ``icon``, but does not use ``multiple``, instead joins all icons
|
||||||
|
with a single space)
|
||||||
|
|
||||||
|
:param dict icons:
|
||||||
|
A dictionary mapping a substring of window classes to strings to be used as an
|
||||||
|
icon for that window class.
|
||||||
|
Further, there is a ``multiple`` icon for workspaces containing more than one
|
||||||
|
window.
|
||||||
|
|
||||||
|
Highlight groups used: ``workspace`` or ``w_visible``, ``workspace:visible``, ``workspace`` or ``w_focused``, ``workspace:focused``, ``workspace`` or ``w_urgent``, ``workspace:urgent``, ``workspace``.
|
||||||
'''
|
'''
|
||||||
|
if format == None:
|
||||||
|
format = '{stripped_name}' if strip else '{name}'
|
||||||
|
|
||||||
|
conn = get_i3_connection()
|
||||||
|
ws_containers = {w_con.name : w_con for w_con in conn.get_tree().workspaces()}
|
||||||
|
|
||||||
if workspace:
|
if workspace:
|
||||||
try:
|
try:
|
||||||
w = next((
|
w = next((
|
||||||
w for w in get_i3_connection().get_workspaces()
|
w for w in conn.get_workspaces()
|
||||||
if w.name == workspace
|
if w.name == workspace
|
||||||
))
|
))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
@ -89,14 +223,18 @@ def workspace(pl, segment_info, workspace=None, strip=False):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
w = next((
|
w = next((
|
||||||
w for w in get_i3_connection().get_workspaces()
|
w for w in conn.get_workspaces()
|
||||||
if w.focused
|
if w.focused
|
||||||
))
|
))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
'contents': format_name(w.name, strip=strip),
|
'contents': format.format(name = w.name,
|
||||||
|
stripped_name = format_name(w.name, strip=True),
|
||||||
|
number = w.num,
|
||||||
|
icon = get_icon(w, '', icons, False, ws_containers),
|
||||||
|
multi_icon = get_icon(w, ' ', icons, True, ws_containers)),
|
||||||
'highlight_groups': workspace_groups(w)
|
'highlight_groups': workspace_groups(w)
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@ -153,3 +291,19 @@ def scratchpad(pl, icons=SCRATCHPAD_ICONS):
|
|||||||
for w in get_i3_connection().get_tree().descendants()
|
for w in get_i3_connection().get_tree().descendants()
|
||||||
if w.scratchpad_state != 'none'
|
if w.scratchpad_state != 'none'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def active_window(pl, cutoff=100):
|
||||||
|
'''Returns the title of the currently active window.
|
||||||
|
|
||||||
|
:param int cutoff:
|
||||||
|
Maximum title length. If the title is longer, the window_class is used instead.
|
||||||
|
|
||||||
|
Highlight groups used: ``active_window_title``.
|
||||||
|
'''
|
||||||
|
|
||||||
|
focused = get_i3_connection().get_tree().find_focused()
|
||||||
|
cont = focused.name
|
||||||
|
if len(cont) > cutoff:
|
||||||
|
cont = focused.window_class
|
||||||
|
|
||||||
|
return [{'contents': cont, 'highlight_groups': ['active_window_title']}] if focused.name != focused.workspace().name else []
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||||
|
|
||||||
import subprocess
|
__version__ = "2.8.3"
|
||||||
from traceback import print_exc
|
|
||||||
|
|
||||||
__version__ = "2.8.2"
|
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
return __version__
|
return __version__
|
||||||
|
@ -33,6 +33,7 @@ class PowerlineDummyTest(object):
|
|||||||
class PowerlineTestSuite(object):
|
class PowerlineTestSuite(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.suite = ''
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.saved_current_suite = os.environ['POWERLINE_CURRENT_SUITE']
|
self.saved_current_suite = os.environ['POWERLINE_CURRENT_SUITE']
|
||||||
|
@ -1001,81 +1001,158 @@ class TestWthr(TestCommon):
|
|||||||
|
|
||||||
|
|
||||||
class TestI3WM(TestCase):
|
class TestI3WM(TestCase):
|
||||||
@staticmethod
|
def test_workspaces(self):
|
||||||
def get_workspaces():
|
class Conn(object):
|
||||||
|
def get_tree(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def descendents(self):
|
||||||
|
nodes_unfocused = [Args(focused = False)]
|
||||||
|
nodes_focused = [Args(focused = True)]
|
||||||
|
|
||||||
|
workspace_scratch = lambda: Args(name='__i3_scratch')
|
||||||
|
workspace_noscratch = lambda: Args(name='2: w2')
|
||||||
|
return [
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state='changed', urgent=True, workspace=workspace_noscratch, nodes=nodes_focused),
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state=None, urgent=False, workspace=workspace_noscratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_focused),
|
||||||
|
Args(scratchpad_state=None, urgent=True, workspace=workspace_noscratch, nodes=nodes_unfocused),
|
||||||
|
]
|
||||||
|
|
||||||
|
def workspaces(self):
|
||||||
return iter([
|
return iter([
|
||||||
Args(name='1: w1', output='LVDS1', focused = False, urgent = False, visible = False),
|
Args(name='1: w1', output='LVDS1', focused=False, urgent=False, visible=False, num=1, leaves=lambda: []),
|
||||||
Args(name='2: w2', output='LVDS1', focused = False, urgent = False, visible = True),
|
Args(name='2: w2', output='LVDS1', focused=False, urgent=False, visible=True, num=2, leaves=lambda: []),
|
||||||
Args(name='3: w3', output='HDMI1', focused = False, urgent = True, visible = True),
|
Args(name='3: w3', output='HDMI1', focused=False, urgent=True, visible=True, num=3, leaves=lambda: []),
|
||||||
Args(name='4: w4', output='DVI01', focused = True, urgent = True, visible = True),
|
Args(name='4: w4', output='DVI01', focused=True, urgent=True, visible=True, num=None, leaves=lambda: [])
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_workspaces(self):
|
||||||
|
return iter([
|
||||||
|
Args(name='1: w1', output='LVDS1', focused=False, urgent=False, visible=False, num=1, leaves=lambda: []),
|
||||||
|
Args(name='2: w2', output='LVDS1', focused=False, urgent=False, visible=True, num=2, leaves=lambda: []),
|
||||||
|
Args(name='3: w3', output='HDMI1', focused=False, urgent=True, visible=True, num=3, leaves=lambda: []),
|
||||||
|
Args(name='4: w4', output='DVI01', focused=True, urgent=True, visible=True, num=None, leaves=lambda: [])
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_outputs(self):
|
||||||
|
return iter([
|
||||||
|
Args(name='LVDS1', active=True),
|
||||||
|
Args(name='HDMI1', active=True),
|
||||||
|
Args(name='DVI01', active=True),
|
||||||
|
Args(name='HDMI2', active=False),
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_workspaces(self):
|
|
||||||
pl = Pl()
|
pl = Pl()
|
||||||
with replace_attr(i3wm, 'get_i3_connection', lambda: Args(get_workspaces=self.get_workspaces)):
|
with replace_attr(i3wm, 'get_i3_connection', lambda: Conn()):
|
||||||
segment_info = {}
|
segment_info = {}
|
||||||
|
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info), [
|
||||||
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
||||||
{'contents': '2: w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': '2: w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=None), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=None), [
|
||||||
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
||||||
{'contents': '2: w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': '2: w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['focused', 'urgent']), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['focused', 'urgent']), [
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible']), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible']), [
|
||||||
{'contents': '2: w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': '2: w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3), [
|
||||||
{'contents': 'w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': 'w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': 'w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': 'w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
{'contents': 'w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': 'w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['focused', 'urgent'], output='DVI01'), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['focused', 'urgent'], output='DVI01'), [
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], output='HDMI1'), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], output='HDMI1'), [
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3, output='LVDS1'), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3, output='LVDS1'), [
|
||||||
{'contents': 'w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': 'w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
segment_info['output'] = 'LVDS1'
|
segment_info['output'] = 'LVDS1'
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], output='HDMI1'), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], output='HDMI1'), [
|
||||||
{'contents': '3: w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': '3: w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3), [
|
self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info, only_show=['visible'], strip=3), [
|
||||||
{'contents': 'w2', 'highlight_groups': ['w_visible', 'workspace']},
|
{'contents': 'w2', 'highlight_groups': ['workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_workspace(self):
|
def test_workspace(self):
|
||||||
|
class Conn(object):
|
||||||
|
def get_tree(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def descendents(self):
|
||||||
|
nodes_unfocused = [Args(focused = False)]
|
||||||
|
nodes_focused = [Args(focused = True)]
|
||||||
|
|
||||||
|
workspace_scratch = lambda: Args(name='__i3_scratch')
|
||||||
|
workspace_noscratch = lambda: Args(name='2: w2')
|
||||||
|
return [
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state='changed', urgent=True, workspace=workspace_noscratch, nodes=nodes_focused),
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state=None, urgent=False, workspace=workspace_noscratch, nodes=nodes_unfocused),
|
||||||
|
Args(scratchpad_state='fresh', urgent=False, workspace=workspace_scratch, nodes=nodes_focused),
|
||||||
|
Args(scratchpad_state=None, urgent=True, workspace=workspace_noscratch, nodes=nodes_unfocused),
|
||||||
|
]
|
||||||
|
|
||||||
|
def workspaces(self):
|
||||||
|
return iter([
|
||||||
|
Args(name='1: w1', output='LVDS1', focused=False, urgent=False, visible=False, num=1, leaves=lambda: []),
|
||||||
|
Args(name='2: w2', output='LVDS1', focused=False, urgent=False, visible=True, num=2, leaves=lambda: []),
|
||||||
|
Args(name='3: w3', output='HDMI1', focused=False, urgent=True, visible=True, num=3, leaves=lambda: []),
|
||||||
|
Args(name='4: w4', output='DVI01', focused=True, urgent=True, visible=True, num=None, leaves=lambda: [])
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_workspaces(self):
|
||||||
|
return iter([
|
||||||
|
Args(name='1: w1', output='LVDS1', focused=False, urgent=False, visible=False, num=1, leaves=lambda: []),
|
||||||
|
Args(name='2: w2', output='LVDS1', focused=False, urgent=False, visible=True, num=2, leaves=lambda: []),
|
||||||
|
Args(name='3: w3', output='HDMI1', focused=False, urgent=True, visible=True, num=3, leaves=lambda: []),
|
||||||
|
Args(name='4: w4', output='DVI01', focused=True, urgent=True, visible=True, num=None, leaves=lambda: [])
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_outputs(self):
|
||||||
|
return iter([
|
||||||
|
Args(name='LVDS1', active=True),
|
||||||
|
Args(name='HDMI1', active=True),
|
||||||
|
Args(name='DVI01', active=True),
|
||||||
|
Args(name='HDMI2', active=False),
|
||||||
|
])
|
||||||
|
|
||||||
pl = Pl()
|
pl = Pl()
|
||||||
with replace_attr(i3wm, 'get_i3_connection', lambda: Args(get_workspaces=self.get_workspaces)):
|
with replace_attr(i3wm, 'get_i3_connection', lambda: Conn()):
|
||||||
segment_info = {}
|
segment_info = {}
|
||||||
|
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='1: w1'), [
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='1: w1'), [
|
||||||
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
{'contents': '1: w1', 'highlight_groups': ['workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='3: w3', strip=True), [
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='3: w3', strip=True), [
|
||||||
{'contents': 'w3', 'highlight_groups': ['w_urgent', 'w_visible', 'workspace']},
|
{'contents': 'w3', 'highlight_groups': ['workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='9: w9'), None)
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='9: w9'), None)
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info), [
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info), [
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
segment_info['workspace'] = next(self.get_workspaces())
|
segment_info['workspace'] = next(Conn().get_workspaces())
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='4: w4'), [
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='4: w4'), [
|
||||||
{'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']},
|
{'contents': '4: w4', 'highlight_groups': ['workspace:focused', 'w_focused', 'workspace:urgent', 'w_urgent', 'workspace:visible', 'w_visible', 'workspace']},
|
||||||
])
|
])
|
||||||
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, strip=True), [
|
self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, strip=True), [
|
||||||
{'contents': 'w1', 'highlight_groups': ['workspace']},
|
{'contents': 'w1', 'highlight_groups': ['workspace']},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user