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
|
||||
======
|
||||
|
||||
.. 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
|
||||
<https://github.com/S0lll0s/i3bgbar>`_.
|
||||
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`::
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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.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])
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue