Merge pull request #1285 from ZyX-I/fixed-1256
Add BAR support with i3 bindings
This commit is contained in:
commit
edec4215c1
|
@ -44,13 +44,31 @@ Add the following to :file:`~/.config/qtile/config.py`:
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
.. _bar-usage:
|
||||||
|
|
||||||
|
LemonBoy’s bar
|
||||||
|
==============
|
||||||
|
|
||||||
|
To run the bar simply pipe the output of the binding script into ``bar`` and
|
||||||
|
specify appropriate options, for example like this::
|
||||||
|
|
||||||
|
python /path/to/powerline/bindings/bar/powerline-bar.py | bar
|
||||||
|
|
||||||
|
to run with i3, simply ``exec`` this in i3 config file::
|
||||||
|
|
||||||
|
exec python /path/to/powerline/bindings/bar/powerline-bar.py --i3 | bar
|
||||||
|
|
||||||
|
See the `bar documentation <https://github.com/LemonBoy/bar>`_ for more
|
||||||
|
information and options.
|
||||||
|
|
||||||
I3 bar
|
I3 bar
|
||||||
======
|
======
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Until the patch is done in i3 a custom ``i3bar`` build called ``i3bgbar`` is
|
As the patch to include background-colors in i3bar is likely not to be
|
||||||
needed. The source is available `in S0lll0s/i3bgbar github repository
|
merged, it is recommended to instead run ``bar`` (see above). The source for
|
||||||
<https://github.com/S0lll0s/i3bgbar>`_.
|
i3bgbar is however still available `here
|
||||||
|
<https://github.com/S0lll0s/i3bgbar>`_.
|
||||||
|
|
||||||
Add the following to :file:`~/.i3/config`::
|
Add the following to :file:`~/.i3/config`::
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
from threading import Lock
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
from powerline import Powerline
|
||||||
|
from powerline.lib.monotonic import monotonic
|
||||||
|
from powerline.lib.encoding import get_unicode_writer
|
||||||
|
|
||||||
|
|
||||||
|
class BarPowerline(Powerline):
|
||||||
|
get_encoding = staticmethod(lambda: 'utf-8')
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
super(BarPowerline, self).init(ext='wm', renderer_module='bar')
|
||||||
|
|
||||||
|
|
||||||
|
def render(event=None, data=None, sub=None):
|
||||||
|
global lock
|
||||||
|
with lock:
|
||||||
|
write(powerline.render())
|
||||||
|
write('\n')
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = ArgumentParser(description='Powerline BAR bindings.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--i3', action='store_true',
|
||||||
|
help='Subscribe for i3 events.'
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
powerline = BarPowerline()
|
||||||
|
|
||||||
|
interval = 0.5
|
||||||
|
lock = Lock()
|
||||||
|
|
||||||
|
write = get_unicode_writer(encoding='utf-8')
|
||||||
|
|
||||||
|
if args.i3:
|
||||||
|
import i3
|
||||||
|
sub = i3.Subscription(render, 'workspace')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
start_time = monotonic()
|
||||||
|
render()
|
||||||
|
time.sleep(max(interval - (monotonic() - start_time), 0.1))
|
|
@ -150,7 +150,7 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def write_output(args, powerline, segment_info, write, encoding):
|
def write_output(args, powerline, segment_info, write):
|
||||||
if args.renderer_arg:
|
if args.renderer_arg:
|
||||||
segment_info.update(args.renderer_arg)
|
segment_info.update(args.renderer_arg)
|
||||||
if args.side.startswith('above'):
|
if args.side.startswith('above'):
|
||||||
|
@ -159,8 +159,7 @@ def write_output(args, powerline, segment_info, write, encoding):
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
mode=segment_info.get('mode', None),
|
mode=segment_info.get('mode', None),
|
||||||
):
|
):
|
||||||
write(line.encode(encoding, 'replace'))
|
write(line + '\n')
|
||||||
write(b'\n')
|
|
||||||
args.side = args.side[len('above'):]
|
args.side = args.side[len('above'):]
|
||||||
|
|
||||||
if args.side:
|
if args.side:
|
||||||
|
@ -170,4 +169,4 @@ def write_output(args, powerline, segment_info, write, encoding):
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
mode=segment_info.get('mode', None),
|
mode=segment_info.get('mode', None),
|
||||||
)
|
)
|
||||||
write(rendered.encode(encoding, 'replace'))
|
write(rendered)
|
||||||
|
|
|
@ -86,3 +86,28 @@ def get_preferred_environment_encoding():
|
||||||
locale.getpreferredencoding()
|
locale.getpreferredencoding()
|
||||||
or 'utf-8'
|
or 'utf-8'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_unicode_writer(stream=sys.stdout, encoding=None, errors='replace'):
|
||||||
|
'''Get function which will write unicode string to the given stream
|
||||||
|
|
||||||
|
Writing is done using encoding returned by
|
||||||
|
:py:func:`get_preferred_output_encoding`.
|
||||||
|
|
||||||
|
:param file stream:
|
||||||
|
Stream to write to. Default value is :py:attr:`sys.stdout`.
|
||||||
|
:param str encoding:
|
||||||
|
Determines which encoding to use. If this argument is specified then
|
||||||
|
:py:func:`get_preferred_output_encoding` is not used.
|
||||||
|
:param str errors:
|
||||||
|
Determines what to do with characters which cannot be encoded. See
|
||||||
|
``errors`` argument of :py:func:`codecs.encode`.
|
||||||
|
|
||||||
|
:return: Callable which writes unicode string to the given stream using
|
||||||
|
the preferred output encoding.
|
||||||
|
'''
|
||||||
|
encoding = encoding or get_preferred_output_encoding()
|
||||||
|
if sys.version_info < (3,) or not hasattr(stream, 'buffer'):
|
||||||
|
return lambda s: stream.write(s.encode(encoding, errors))
|
||||||
|
else:
|
||||||
|
return lambda s: stream.buffer.write(s.encode(encoding, errors))
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||||
|
|
||||||
|
from powerline.renderer import Renderer
|
||||||
|
from powerline.colorscheme import ATTR_UNDERLINE
|
||||||
|
|
||||||
|
|
||||||
|
class BarRenderer(Renderer):
|
||||||
|
'''bar (bar ain't recursive) renderer
|
||||||
|
|
||||||
|
|
||||||
|
See documentation of `bar <https://github.com/LemonBoy/bar>`_ and :ref:`the usage instructions <bar-usage>`
|
||||||
|
'''
|
||||||
|
|
||||||
|
character_translations = Renderer.character_translations.copy()
|
||||||
|
character_translations[ord('%')] = '%%'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def hlstyle(*args, **kwargs):
|
||||||
|
# We don’t need to explicitly reset attributes, so skip those calls
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def hl(self, contents, fg=None, bg=None, attrs=None):
|
||||||
|
text = ''
|
||||||
|
|
||||||
|
if fg is not None:
|
||||||
|
if fg is not False and fg[1] is not False:
|
||||||
|
text += '%{{F#ff{0:06x}}}'.format(fg[1])
|
||||||
|
if bg is not None:
|
||||||
|
if bg is not False and bg[1] is not False:
|
||||||
|
text += '%{{B#ff{0:06x}}}'.format(bg[1])
|
||||||
|
|
||||||
|
if attrs & ATTR_UNDERLINE:
|
||||||
|
text += '%{+u}'
|
||||||
|
|
||||||
|
return text + contents + '%{F-B--u}'
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
return '%{{l}}{0}%{{r}}{1}'.format(
|
||||||
|
super(BarRenderer, self).render(side='left'),
|
||||||
|
super(BarRenderer, self).render(side='right'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
renderer = BarRenderer
|
|
@ -17,7 +17,7 @@ from io import BytesIO
|
||||||
from powerline.shell import ShellPowerline
|
from powerline.shell import ShellPowerline
|
||||||
from powerline.commands.main import finish_args, write_output
|
from powerline.commands.main import finish_args, write_output
|
||||||
from powerline.lib.monotonic import monotonic
|
from powerline.lib.monotonic import monotonic
|
||||||
from powerline.lib.encoding import get_preferred_output_encoding
|
from powerline.lib.encoding import get_preferred_output_encoding, get_preferred_arguments_encoding, get_unicode_writer
|
||||||
|
|
||||||
from powerline.commands.main import get_argparser as get_main_argparser
|
from powerline.commands.main import get_argparser as get_main_argparser
|
||||||
from powerline.commands.daemon import get_argparser as get_daemon_argparser
|
from powerline.commands.daemon import get_argparser as get_daemon_argparser
|
||||||
|
@ -107,7 +107,7 @@ def render(args, environ, cwd):
|
||||||
else:
|
else:
|
||||||
return 'Failed to render {0}: {1}'.format(str(key), str(e))
|
return 'Failed to render {0}: {1}'.format(str(key), str(e))
|
||||||
s = BytesIO()
|
s = BytesIO()
|
||||||
write_output(args, powerline, segment_info, s.write, encoding)
|
write_output(args, powerline, segment_info, get_unicode_writer(stream=s))
|
||||||
s.seek(0)
|
s.seek(0)
|
||||||
return s.read()
|
return s.read()
|
||||||
|
|
||||||
|
@ -150,10 +150,7 @@ def do_write(conn, result):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
encoding = get_preferred_output_encoding()
|
def safe_bytes(o, encoding=get_preferred_output_encoding()):
|
||||||
|
|
||||||
|
|
||||||
def safe_bytes(o, encoding=encoding):
|
|
||||||
'''Return bytes instance without ever throwing an exception.'''
|
'''Return bytes instance without ever throwing an exception.'''
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
@ -171,7 +168,7 @@ def safe_bytes(o, encoding=encoding):
|
||||||
return safe_bytes(str(e), encoding)
|
return safe_bytes(str(e), encoding)
|
||||||
|
|
||||||
|
|
||||||
def parse_args(req):
|
def parse_args(req, encoding=get_preferred_arguments_encoding()):
|
||||||
args = [x.decode(encoding) for x in req.split(b'\0') if x]
|
args = [x.decode(encoding) for x in req.split(b'\0') if x]
|
||||||
numargs = int(args[0], 16)
|
numargs = int(args[0], 16)
|
||||||
shell_args = parser.parse_args(args[1:numargs + 1])
|
shell_args = parser.parse_args(args[1:numargs + 1])
|
||||||
|
|
|
@ -13,7 +13,7 @@ except ImportError:
|
||||||
from powerline.shell import ShellPowerline
|
from powerline.shell import ShellPowerline
|
||||||
|
|
||||||
from powerline.commands.main import get_argparser, finish_args, write_output
|
from powerline.commands.main import get_argparser, finish_args, write_output
|
||||||
from powerline.lib.unicode import get_preferred_output_encoding
|
from powerline.lib.encoding import get_unicode_writer
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
|
@ -27,4 +27,4 @@ if __name__ == '__main__':
|
||||||
finish_args(os.environ, args)
|
finish_args(os.environ, args)
|
||||||
powerline = ShellPowerline(args, run_once=True)
|
powerline = ShellPowerline(args, run_once=True)
|
||||||
segment_info = {'args': args, 'environ': os.environ}
|
segment_info = {'args': args, 'environ': os.environ}
|
||||||
write_output(args, powerline, segment_info, write, get_preferred_output_encoding())
|
write_output(args, powerline, segment_info, get_unicode_writer())
|
||||||
|
|
|
@ -43,6 +43,10 @@ config = {
|
||||||
'theme': 'default',
|
'theme': 'default',
|
||||||
'colorscheme': 'default',
|
'colorscheme': 'default',
|
||||||
},
|
},
|
||||||
|
'wm': {
|
||||||
|
'theme': 'default',
|
||||||
|
'colorscheme': 'default',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'colors': {
|
'colors': {
|
||||||
|
@ -91,6 +95,14 @@ config = {
|
||||||
'environment': {'fg': 'col3', 'bg': 'col4', 'attrs': ['underline']},
|
'environment': {'fg': 'col3', 'bg': 'col4', 'attrs': ['underline']},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'colorschemes/wm/default': {
|
||||||
|
'groups': {
|
||||||
|
'hl1': {'fg': 'col1', 'bg': 'col2', 'attrs': ['underline']},
|
||||||
|
'hl2': {'fg': 'col2', 'bg': 'col1', 'attrs': []},
|
||||||
|
'hl3': {'fg': 'col3', 'bg': 'col1', 'attrs': ['underline']},
|
||||||
|
'hl4': {'fg': 'col2', 'bg': 'col4', 'attrs': []},
|
||||||
|
},
|
||||||
|
},
|
||||||
'themes/test/default': {
|
'themes/test/default': {
|
||||||
'segments': {
|
'segments': {
|
||||||
'left': [
|
'left': [
|
||||||
|
@ -142,6 +154,19 @@ config = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'themes/wm/default': {
|
||||||
|
'default_module': 'powerline.segments.common',
|
||||||
|
'segments': {
|
||||||
|
'left': [
|
||||||
|
highlighted_string('A', 'hl1'),
|
||||||
|
highlighted_string('B', 'hl2'),
|
||||||
|
],
|
||||||
|
'right': [
|
||||||
|
highlighted_string('C', 'hl3'),
|
||||||
|
highlighted_string('D', 'hl4'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -800,6 +825,31 @@ class TestVim(TestCase):
|
||||||
sys.path.pop(0)
|
sys.path.pop(0)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBar(TestRender):
|
||||||
|
def test_bar(self):
|
||||||
|
import powerline as powerline_module
|
||||||
|
with swap_attributes(config, powerline_module):
|
||||||
|
with get_powerline_raw(config, powerline_module.Powerline, replace_gcp=True, ext='wm', renderer_module='bar') as powerline:
|
||||||
|
self.assertRenderEqual(
|
||||||
|
powerline,
|
||||||
|
'%{l}%{F#ffc00000}%{B#ff008000}%{+u} A%{F-B--u}%{F#ff008000}%{B#ffc00000}>>%{F-B--u}%{F#ff008000}%{B#ffc00000}B%{F-B--u}%{F#ffc00000}>>%{F-B--u}%{r}%{F#ffc00000}<<%{F-B--u}%{F#ff804000}%{B#ffc00000}%{+u}C%{F-B--u}%{F#ff0000c0}%{B#ffc00000}<<%{F-B--u}%{F#ff008000}%{B#ff0000c0}D %{F-B--u}'
|
||||||
|
)
|
||||||
|
|
||||||
|
@with_new_config
|
||||||
|
def test_bar_escape(self, config):
|
||||||
|
import powerline as powerline_module
|
||||||
|
config['themes/wm/default']['segments']['left'] = (
|
||||||
|
highlighted_string('%{asd}', 'hl1'),
|
||||||
|
highlighted_string('10% %', 'hl2'),
|
||||||
|
)
|
||||||
|
with swap_attributes(config, powerline_module):
|
||||||
|
with get_powerline_raw(config, powerline_module.Powerline, replace_gcp=True, ext='wm', renderer_module='bar') as powerline:
|
||||||
|
self.assertRenderEqual(
|
||||||
|
powerline,
|
||||||
|
'%{l}%{F#ffc00000}%{B#ff008000}%{+u} %%{asd}%{F-B--u}%{F#ff008000}%{B#ffc00000}>>%{F-B--u}%{F#ff008000}%{B#ffc00000}10%% %%%{F-B--u}%{F#ffc00000}>>%{F-B--u}%{r}%{F#ffc00000}<<%{F-B--u}%{F#ff804000}%{B#ffc00000}%{+u}C%{F-B--u}%{F#ff0000c0}%{B#ffc00000}<<%{F-B--u}%{F#ff008000}%{B#ff0000c0}D %{F-B--u}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from tests import main
|
from tests import main
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue