From 53aca6b1905e06f1899b70950fcfc0493b82af4c Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Tue, 12 Jan 2016 18:05:40 +0100 Subject: [PATCH 1/6] Add i3wm segment_info keys to developer reference --- docs/source/develop/segments.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst index d96bb1cb..a47d0a52 100644 --- a/docs/source/develop/segments.rst +++ b/docs/source/develop/segments.rst @@ -517,6 +517,16 @@ Pdb Equal to the length of :py:attr:`pdb.Pdb.stack` at the first invocation of the prompt decremented by one. +i3wm +---- + +``mode`` + Currently active i3 mode (as a string). + +``output`` + ``xrandr`` output name currently drawing to. Currently only available + in lemonbar bindings. + Segment class ============= From bc7d571d0053b91ecc04b45c77c05074481978d6 Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Tue, 12 Jan 2016 23:42:17 +0100 Subject: [PATCH 2/6] Add i3wm segment for singular workspace --- powerline/segments/i3wm.py | 41 +++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/powerline/segments/i3wm.py b/powerline/segments/i3wm.py index 9d214cfe..29093072 100644 --- a/powerline/segments/i3wm.py +++ b/powerline/segments/i3wm.py @@ -51,7 +51,7 @@ def workspaces(pl, segment_info, only_show=None, output=None, strip=0): output = output or segment_info.get('output') return [{ - 'contents': w['name'][min(len(w['name']), strip):], + 'contents': 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)) @@ -59,6 +59,45 @@ def workspaces(pl, segment_info, only_show=None, output=None, strip=0): ] +@requires_segment_info +def workspace(pl, segment_info, workspace=None, strip=0): + '''Return the specified workspace name + + :param str workspace: + Specifies which workspace to show. If unspecified, may be set by the + ``list_workspaces`` lister. + + :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. + + Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. + ''' + workspace = workspace or segment_info.get('workspace')['name'] + if segment_info.get('workspace') and segment_info.get('workspace')['name'] == workspace: + w = segment_info.get('workspace') + else: + global conn + if not conn: + try: + import i3ipc + except ImportError: + import i3 as conn + else: + conn = i3ipc.Connection() + try: + w = next(( + w for w in get_i3_connection().get_workspaces() + if w['name'] == workspace + )) + except StopIteration: + return None + return [{ + 'contents': w['name'][min(len(w['name']), strip):], + 'highlight_groups': calcgrp(w) + }] + + @requires_segment_info def mode(pl, segment_info, names={'default': None}): '''Returns current i3 mode From 24fa03567e5034728ddb7cdff697dfed058b03ab Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Tue, 12 Jan 2016 22:38:03 +0100 Subject: [PATCH 3/6] Add listers for i3wm workspaces and outputs --- docs/source/configuration/listers.rst | 8 +- docs/source/develop/segments.rst | 6 ++ .../bindings/lemonbar/powerline-lemonbar.py | 9 +-- powerline/lib/dict.py | 8 ++ powerline/lint/imp.py | 6 ++ powerline/listers/i3wm.py | 78 +++++++++++++++++++ powerline/segments/i3wm.py | 4 +- 7 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 powerline/listers/i3wm.py diff --git a/docs/source/configuration/listers.rst b/docs/source/configuration/listers.rst index 04e5371e..e6ba06e7 100644 --- a/docs/source/configuration/listers.rst +++ b/docs/source/configuration/listers.rst @@ -16,8 +16,6 @@ their type and ``segments`` key with a list of segments (a bit more details in More information in :ref:`Writing listers ` section. -Currently only Vim listers are available. - Vim listers ----------- @@ -29,3 +27,9 @@ Pdb listers .. automodule:: powerline.listers.pdb :members: + +i3wm listers +---------- + +.. automodule:: powerline.listers.i3wm + :members: diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst index a47d0a52..30f4a664 100644 --- a/docs/source/develop/segments.rst +++ b/docs/source/develop/segments.rst @@ -527,6 +527,12 @@ i3wm ``xrandr`` output name currently drawing to. Currently only available in lemonbar bindings. +``workspace`` + dictionary containing the workspace name under the key ``"name"`` and + boolean values for the ``"visible"``, ``"urgent"`` and ``"focused"`` + keys, indicating the state of the workspace. Currently only provided by + the :py:func:`powerline.listers.i3wm.workspace_lister` lister. + Segment class ============= diff --git a/powerline/bindings/lemonbar/powerline-lemonbar.py b/powerline/bindings/lemonbar/powerline-lemonbar.py index ae4ffb34..5a272ab5 100755 --- a/powerline/bindings/lemonbar/powerline-lemonbar.py +++ b/powerline/bindings/lemonbar/powerline-lemonbar.py @@ -9,8 +9,8 @@ import subprocess from threading import Lock, Timer from powerline.lemonbar import LemonbarPowerline -from powerline.lib.shell import run_cmd from powerline.commands.lemonbar import get_argparser +from powerline.listers.i3wm import get_connected_xrandr_outputs if __name__ == '__main__': @@ -20,13 +20,8 @@ if __name__ == '__main__': powerline = LemonbarPowerline() powerline.update_renderer() bars = [] - active_screens = [match.groupdict() for match in re.finditer( - '^(?P[0-9A-Za-z-]+) connected (?P\d+)x(?P\d+)\+(?P\d+)\+(?P\d+)', - run_cmd(powerline.pl, ['xrandr', '-q']), - re.MULTILINE - )] - for screen in active_screens: + for screen in get_connected_xrandr_outputs(powerline.pl): command = [args.bar_command, '-g', '{0}x{1}+{2}'.format(screen['width'], args.height, screen['x'])] + args.args[1:] process = subprocess.Popen(command, stdin=subprocess.PIPE) bars.append((screen['name'], process, int(screen['width']) / 5)) diff --git a/powerline/lib/dict.py b/powerline/lib/dict.py index d8d2088b..c06ab30c 100644 --- a/powerline/lib/dict.py +++ b/powerline/lib/dict.py @@ -78,3 +78,11 @@ def mergedicts_copy(d1, d2): else: ret[k] = d2[k] return ret + + +def updated(d, *args, **kwargs): + '''Copy dictionary and update it with provided arguments + ''' + d = d.copy() + d.update(*args, **kwargs) + return d diff --git a/powerline/lint/imp.py b/powerline/lint/imp.py index 6e402132..399654e1 100644 --- a/powerline/lint/imp.py +++ b/powerline/lint/imp.py @@ -21,6 +21,12 @@ class WithPath(object): def import_function(function_type, name, data, context, echoerr, module): havemarks(name, module) + if module == 'powerline.segments.i3wm' and name == 'workspaces': + echoerr(context='Warning while checking segments (key {key})'.format(key=context.key), + context_mark=name.mark, + problem='segment {0} from {1} is deprecated'.format(name, module), + problem_mark=module.mark) + with WithPath(data['import_paths']): try: func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) diff --git a/powerline/listers/i3wm.py b/powerline/listers/i3wm.py new file mode 100644 index 00000000..fedb7c81 --- /dev/null +++ b/powerline/listers/i3wm.py @@ -0,0 +1,78 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import re + +from powerline.theme import requires_segment_info +from powerline.lib.shell import run_cmd +from powerline.lib.dict import updated + + +conn = None +XRANDR_OUTPUT_RE = re.compile(r'^(?P[0-9A-Za-z-]+) connected (?P\d+)x(?P\d+)\+(?P\d+)\+(?P\d+)', re.MULTILINE) +def get_connected_xrandr_outputs(pl): + return (match.groupdict() for match in XRANDR_OUTPUT_RE.finditer( + run_cmd(pl, ['xrandr', '-q']) + )) + + +@requires_segment_info +def output_lister(pl, segment_info): + '''List all outputs in segment_info format + ''' + + return ( + ( + updated(segment_info, output=output['name']), + { + 'draw_inner_divider': None + } + ) + for output in get_connected_xrandr_outputs(pl) + ) + + +@requires_segment_info +def workspace_lister(pl, segment_info, only_show=None, output=None): + '''List all workspaces in segment_info format + + Sets the segment info values of ``workspace`` and ``output`` to the name of + the i3 workspace and the ``xrandr`` output respectively and the keys + ``"visible"``, ``"urgent"`` and ``"focused`` to a boolean indicating these + states. + + :param list only_show: + Specifies which workspaces to list. Valid entries are ``"visible"``, + ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces + are listed. + + :param str output: + May be set to the name of an X output. If specified, only workspaces + on that output are listed. Overrides automatic output detection by + the lemonbar renderer and bindings. Set to ``false`` to force + all workspaces to be shown. + ''' + + if output == None: + output = output or segment_info.get('output') + + return ( + ( + updated( + segment_info, + output=w['output'], + workspace={ + 'name': w['name'], + 'visible': w['visible'], + 'urgent': w['urgent'], + 'focused': w['focused'], + }, + ), + { + 'draw_inner_divider': None + } + ) + 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))) + ) diff --git a/powerline/segments/i3wm.py b/powerline/segments/i3wm.py index 29093072..8be8ada0 100644 --- a/powerline/segments/i3wm.py +++ b/powerline/segments/i3wm.py @@ -54,8 +54,8 @@ def workspaces(pl, segment_info, only_show=None, output=None, strip=0): 'contents': 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)) - and (not output or w['output'] == output) + if ((not only_show or any(w[typ] for typ in only_show)) + and (not output or w['output'] == output)) ] From db99ad1d90e818b1ce9df782edcdc6612277d0eb Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Fri, 15 Jan 2016 15:37:37 +0100 Subject: [PATCH 4/6] Refactor i3wm segment and lemonbar binding Move get_i3_connection and get_xrandr_outputs into bindings.wm --- .../bindings/lemonbar/powerline-lemonbar.py | 2 +- powerline/bindings/wm/__init__.py | 38 ++++++++++++++ powerline/listers/i3wm.py | 16 ++---- powerline/segments/i3wm.py | 52 ++++++++----------- tests/test_segments.py | 2 +- 5 files changed, 65 insertions(+), 45 deletions(-) create mode 100644 powerline/bindings/wm/__init__.py diff --git a/powerline/bindings/lemonbar/powerline-lemonbar.py b/powerline/bindings/lemonbar/powerline-lemonbar.py index 5a272ab5..76372541 100755 --- a/powerline/bindings/lemonbar/powerline-lemonbar.py +++ b/powerline/bindings/lemonbar/powerline-lemonbar.py @@ -10,7 +10,7 @@ from threading import Lock, Timer from powerline.lemonbar import LemonbarPowerline from powerline.commands.lemonbar import get_argparser -from powerline.listers.i3wm import get_connected_xrandr_outputs +from powerline.bindings.wm import get_connected_xrandr_outputs if __name__ == '__main__': diff --git a/powerline/bindings/wm/__init__.py b/powerline/bindings/wm/__init__.py new file mode 100644 index 00000000..6f8be621 --- /dev/null +++ b/powerline/bindings/wm/__init__.py @@ -0,0 +1,38 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import re + +from powerline.theme import requires_segment_info +from powerline.lib.shell import run_cmd + + +conn = None + + +def get_i3_connection(): + '''Return a valid, cached i3 Connection instance + ''' + global conn + if not conn: + try: + import i3ipc + except ImportError: + import i3 as conn + else: + conn = i3ipc.Connection() + return conn + + +XRANDR_OUTPUT_RE = re.compile(r'^(?P[0-9A-Za-z-]+) connected (?P\d+)x(?P\d+)\+(?P\d+)\+(?P\d+)', re.MULTILINE) + + +def get_connected_xrandr_outputs(pl): + '''Iterate over xrandr outputs + + Outputs are represented by a dictionary with ``name``, ``width``, + ``height``, ``x`` and ``y`` keys. + ''' + return (match.groupdict() for match in XRANDR_OUTPUT_RE.finditer( + run_cmd(pl, ['xrandr', '-q']) + )) diff --git a/powerline/listers/i3wm.py b/powerline/listers/i3wm.py index fedb7c81..188e888b 100644 --- a/powerline/listers/i3wm.py +++ b/powerline/listers/i3wm.py @@ -1,19 +1,9 @@ # vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) -import re - from powerline.theme import requires_segment_info -from powerline.lib.shell import run_cmd from powerline.lib.dict import updated - - -conn = None -XRANDR_OUTPUT_RE = re.compile(r'^(?P[0-9A-Za-z-]+) connected (?P\d+)x(?P\d+)\+(?P\d+)\+(?P\d+)', re.MULTILINE) -def get_connected_xrandr_outputs(pl): - return (match.groupdict() for match in XRANDR_OUTPUT_RE.finditer( - run_cmd(pl, ['xrandr', '-q']) - )) +from powerline.bindings.wm import get_i3_connection, get_connected_xrandr_outputs @requires_segment_info @@ -72,7 +62,7 @@ def workspace_lister(pl, segment_info, only_show=None, output=None): 'draw_inner_divider': None } ) - for w in conn.get_workspaces() + for w in get_i3_connection().get_workspaces() if (((not only_show or any(w[typ] for typ in only_show)) - and (not output or w['output'] == output))) + and (not output or w['output'] == output))) ) diff --git a/powerline/segments/i3wm.py b/powerline/segments/i3wm.py index 8be8ada0..b0b405d4 100644 --- a/powerline/segments/i3wm.py +++ b/powerline/segments/i3wm.py @@ -2,9 +2,7 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) from powerline.theme import requires_segment_info - - -conn = None +from powerline.bindings.wm import get_i3_connection def calcgrp(w): @@ -39,23 +37,16 @@ def workspaces(pl, segment_info, only_show=None, output=None, strip=0): Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' - global conn - if not conn: - try: - import i3ipc - except ImportError: - import i3 as conn - else: - conn = i3ipc.Connection() - output = output or segment_info.get('output') - return [{ - 'contents': w['name'][strip:], - 'highlight_groups': calcgrp(w) - } for w in conn.get_workspaces() + return [ + { + 'contents': w['name'][strip:], + 'highlight_groups': calcgrp(w) + } + for w in get_i3_connection().get_workspaces() if ((not only_show or any(w[typ] for typ in only_show)) - and (not output or w['output'] == output)) + and (not output or w['output'] == output)) ] @@ -65,7 +56,8 @@ def workspace(pl, segment_info, workspace=None, strip=0): :param str workspace: Specifies which workspace to show. If unspecified, may be set by the - ``list_workspaces`` lister. + ``list_workspaces`` lister if used, otherwise falls back to + currently focused workspace. :param int strip: Specifies how many characters from the front of each workspace name @@ -73,18 +65,7 @@ def workspace(pl, segment_info, workspace=None, strip=0): Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' - workspace = workspace or segment_info.get('workspace')['name'] - if segment_info.get('workspace') and segment_info.get('workspace')['name'] == workspace: - w = segment_info.get('workspace') - else: - global conn - if not conn: - try: - import i3ipc - except ImportError: - import i3 as conn - else: - conn = i3ipc.Connection() + if workspace: try: w = next(( w for w in get_i3_connection().get_workspaces() @@ -92,6 +73,17 @@ def workspace(pl, segment_info, workspace=None, strip=0): )) except StopIteration: return None + elif segment_info.get('workspace'): + w = segment_info['workspace'] + else: + try: + w = next(( + w for w in get_i3_connection().get_workspaces() + if w['focused'] + )) + except StopIteration: + return None + return [{ 'contents': w['name'][min(len(w['name']), strip):], 'highlight_groups': calcgrp(w) diff --git a/tests/test_segments.py b/tests/test_segments.py index edb69a59..3cb1aa0e 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -885,7 +885,7 @@ class TestWthr(TestCommon): class TestI3WM(TestCase): def test_workspaces(self): pl = Pl() - with replace_attr(i3wm, 'conn', Args(get_workspaces=lambda: iter([ + with replace_attr(i3wm, 'conn', Args(get_i3_workspaces=lambda: iter([ {'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}, From 10243ad89f1a04068379568067ddf3f2f2e4f538 Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Thu, 4 Feb 2016 04:41:58 +0300 Subject: [PATCH 5/6] Make workspace(strip) strip `{number}:` prefix if true --- powerline/segments/i3wm.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/powerline/segments/i3wm.py b/powerline/segments/i3wm.py index b0b405d4..eb0d3c44 100644 --- a/powerline/segments/i3wm.py +++ b/powerline/segments/i3wm.py @@ -1,10 +1,15 @@ # vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) +import re + from powerline.theme import requires_segment_info from powerline.bindings.wm import get_i3_connection +WORKSPACE_REGEX = re.compile(r'^[0-9]+: ?') + + def calcgrp(w): group = [] if w['focused']: @@ -17,6 +22,12 @@ def calcgrp(w): return group +def format_name(name, strip=False): + if strip: + return WORKSPACE_REGEX.sub('', name, count=1) + return name + + @requires_segment_info def workspaces(pl, segment_info, only_show=None, output=None, strip=0): '''Return list of used workspaces @@ -51,7 +62,7 @@ def workspaces(pl, segment_info, only_show=None, output=None, strip=0): @requires_segment_info -def workspace(pl, segment_info, workspace=None, strip=0): +def workspace(pl, segment_info, workspace=None, strip=False): '''Return the specified workspace name :param str workspace: @@ -59,9 +70,9 @@ def workspace(pl, segment_info, workspace=None, strip=0): ``list_workspaces`` lister if used, otherwise falls back to currently focused workspace. - :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. + :param bool strip: + Specifies whether workspace numbers (in the ``1: name`` format) should + be stripped from workspace names before being displayed. Defaults to false. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' @@ -85,7 +96,7 @@ def workspace(pl, segment_info, workspace=None, strip=0): return None return [{ - 'contents': w['name'][min(len(w['name']), strip):], + 'contents': format_name(w['name'], strip=strip), 'highlight_groups': calcgrp(w) }] From 623c1f85bc5411552088a264902037e23ffb45ac Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Fri, 15 Jan 2016 18:18:04 +0100 Subject: [PATCH 6/6] Add tests for i3wm listers and workspace segment --- tests/test_listers.py | 227 +++++++++++++++++++++++++++++++++++++++++ tests/test_segments.py | 43 +++++++- 2 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 tests/test_listers.py diff --git a/tests/test_listers.py b/tests/test_listers.py new file mode 100644 index 00000000..3d3ed094 --- /dev/null +++ b/tests/test_listers.py @@ -0,0 +1,227 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import powerline.listers.i3wm as i3wm + +from tests.lib import Args, replace_attr, Pl +from tests import TestCase + + +class TestI3WM(TestCase): + @staticmethod + def get_workspaces(): + return iter([ + {'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}, + ]) + + @staticmethod + def get_outputs(pl): + return iter([ + {'name': 'LVDS1'}, + {'name': 'HDMI1'}, + {'name': 'DVI01'}, + ]) + + def test_output_lister(self): + pl = Pl() + with replace_attr(i3wm, 'get_connected_xrandr_outputs', self.get_outputs): + self.assertEqual( + list(i3wm.output_lister(pl=pl, segment_info={'a': 1})), + [ + ({'a': 1, 'output': 'LVDS1'}, {'draw_inner_divider': None}), + ({'a': 1, 'output': 'HDMI1'}, {'draw_inner_divider': None}), + ({'a': 1, 'output': 'DVI01'}, {'draw_inner_divider': None}), + ] + ) + + def test_workspace_lister(self): + pl = Pl() + with replace_attr(i3wm, 'get_i3_connection', lambda: Args(get_workspaces=self.get_workspaces)): + self.assertEqual( + list(i3wm.workspace_lister(pl=pl, segment_info={'a': 1})), + [ + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '1: w1', + 'focused': False, + 'urgent': False, + 'visible': False + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '2: w2', + 'focused': False, + 'urgent': False, + 'visible': True + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'HDMI1', + 'workspace': { + 'name': '3: w3', + 'focused': False, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'DVI01', + 'workspace': { + 'name': '4: w4', + 'focused': True, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ] + ) + + self.assertEqual( + list(i3wm.workspace_lister(pl=pl, segment_info={'a': 1}, output='LVDS1')), + [ + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '1: w1', + 'focused': False, + 'urgent': False, + 'visible': False + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '2: w2', + 'focused': False, + 'urgent': False, + 'visible': True + } + }, {'draw_inner_divider': None}), + ] + ) + + self.assertEqual( + list(i3wm.workspace_lister( + pl=pl, + segment_info={'a': 1, 'output': 'LVDS1'} + )), + [ + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '1: w1', + 'focused': False, + 'urgent': False, + 'visible': False + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '2: w2', + 'focused': False, + 'urgent': False, + 'visible': True + } + }, {'draw_inner_divider': None}), + ] + ) + + self.assertEqual( + list(i3wm.workspace_lister( + pl=pl, + segment_info={'a': 1, 'output': 'LVDS1'}, + output=False + )), + [ + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '1: w1', + 'focused': False, + 'urgent': False, + 'visible': False + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'LVDS1', + 'workspace': { + 'name': '2: w2', + 'focused': False, + 'urgent': False, + 'visible': True + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'HDMI1', + 'workspace': { + 'name': '3: w3', + 'focused': False, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'DVI01', + 'workspace': { + 'name': '4: w4', + 'focused': True, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ] + ) + + self.assertEqual( + list(i3wm.workspace_lister( + pl=pl, + segment_info={'a': 1}, + only_show=['focused', 'urgent'] + )), + [ + ({ + 'a': 1, + 'output': 'HDMI1', + 'workspace': { + 'name': '3: w3', + 'focused': False, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ({ + 'a': 1, + 'output': 'DVI01', + 'workspace': { + 'name': '4: w4', + 'focused': True, + 'urgent': True, + 'visible': True + } + }, {'draw_inner_divider': None}), + ] + ) + + +if __name__ == '__main__': + from tests import main + main() diff --git a/tests/test_segments.py b/tests/test_segments.py index 3cb1aa0e..55fa8137 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -883,14 +883,26 @@ class TestWthr(TestCommon): class TestI3WM(TestCase): - def test_workspaces(self): - pl = Pl() - with replace_attr(i3wm, 'conn', Args(get_i3_workspaces=lambda: iter([ + @staticmethod + def get_workspaces(): + return iter([ {'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}, - ]))): + ]) + + @staticmethod + def get_outputs(pl): + return iter([ + {'name': 'LVDS1'}, + {'name': 'HDMI1'}, + {'name': 'DVI01'}, + ]) + + def test_workspaces(self): + pl = Pl() + with replace_attr(i3wm, 'get_i3_connection', lambda: Args(get_workspaces=self.get_workspaces)): segment_info = {} self.assertEqual(i3wm.workspaces(pl=pl, segment_info=segment_info), [ @@ -936,6 +948,29 @@ class TestI3WM(TestCase): {'contents': 'w2', 'highlight_groups': ['w_visible', 'workspace']}, ]) + def test_workspace(self): + pl = Pl() + with replace_attr(i3wm, 'get_i3_connection', lambda: Args(get_workspaces=self.get_workspaces)): + segment_info = {} + + self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='1: w1'), [ + {'contents': '1: w1', 'highlight_groups': ['workspace']}, + ]) + self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, workspace='3: w3', strip=True), [ + {'contents': 'w3', 'highlight_groups': ['w_urgent', '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), [ + {'contents': '4: w4', 'highlight_groups': ['w_focused', 'w_urgent', 'w_visible', 'workspace']}, + ]) + segment_info['workspace'] = next(self.get_workspaces()) + 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']}, + ]) + self.assertEqual(i3wm.workspace(pl=pl, segment_info=segment_info, strip=True), [ + {'contents': 'w1', 'highlight_groups': ['workspace']}, + ]) + def test_mode(self): pl = Pl() self.assertEqual(i3wm.mode(pl=pl, segment_info={'mode': 'default'}), None)