Merge pull request #1285 from ZyX-I/fixed-1256

Add BAR support with i3 bindings
This commit is contained in:
Nikolai Aleksandrovich Pavlov 2015-01-25 19:20:09 +03:00
commit edec4215c1
8 changed files with 202 additions and 16 deletions

View File

@ -44,12 +44,30 @@ Add the following to :file:`~/.config/qtile/config.py`:
),
]
.. _bar-usage:
LemonBoys 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
======
.. note::
Until the patch is done in i3 a custom ``i3bar`` build called ``i3bgbar`` is
needed. The source is available `in S0lll0s/i3bgbar github repository
As the patch to include background-colors in i3bar is likely not to be
merged, it is recommended to instead run ``bar`` (see above). The source for
i3bgbar is however still available `here
<https://github.com/S0lll0s/i3bgbar>`_.
Add the following to :file:`~/.i3/config`::

View File

@ -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))

View File

@ -150,7 +150,7 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
return parser
def write_output(args, powerline, segment_info, write, encoding):
def write_output(args, powerline, segment_info, write):
if args.renderer_arg:
segment_info.update(args.renderer_arg)
if args.side.startswith('above'):
@ -159,8 +159,7 @@ def write_output(args, powerline, segment_info, write, encoding):
segment_info=segment_info,
mode=segment_info.get('mode', None),
):
write(line.encode(encoding, 'replace'))
write(b'\n')
write(line + '\n')
args.side = args.side[len('above'):]
if args.side:
@ -170,4 +169,4 @@ def write_output(args, powerline, segment_info, write, encoding):
segment_info=segment_info,
mode=segment_info.get('mode', None),
)
write(rendered.encode(encoding, 'replace'))
write(rendered)

View File

@ -86,3 +86,28 @@ def get_preferred_environment_encoding():
locale.getpreferredencoding()
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))

View File

@ -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 dont 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

View File

@ -17,7 +17,7 @@ from io import BytesIO
from powerline.shell import ShellPowerline
from powerline.commands.main import finish_args, write_output
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.daemon import get_argparser as get_daemon_argparser
@ -107,7 +107,7 @@ def render(args, environ, cwd):
else:
return 'Failed to render {0}: {1}'.format(str(key), str(e))
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)
return s.read()
@ -150,10 +150,7 @@ def do_write(conn, result):
pass
encoding = get_preferred_output_encoding()
def safe_bytes(o, encoding=encoding):
def safe_bytes(o, encoding=get_preferred_output_encoding()):
'''Return bytes instance without ever throwing an exception.'''
try:
try:
@ -171,7 +168,7 @@ def safe_bytes(o, encoding=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]
numargs = int(args[0], 16)
shell_args = parser.parse_args(args[1:numargs + 1])

View File

@ -13,7 +13,7 @@ except ImportError:
from powerline.shell import ShellPowerline
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,):
@ -27,4 +27,4 @@ if __name__ == '__main__':
finish_args(os.environ, args)
powerline = ShellPowerline(args, run_once=True)
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())

View File

@ -43,6 +43,10 @@ config = {
'theme': 'default',
'colorscheme': 'default',
},
'wm': {
'theme': 'default',
'colorscheme': 'default',
},
},
},
'colors': {
@ -91,6 +95,14 @@ config = {
'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': {
'segments': {
'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)
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__':
from tests import main
main()