Handle non-printable characters properly

Fixes #723
This commit is contained in:
ZyX 2013-12-01 15:42:57 +04:00
parent 48a076f658
commit ecff281304
6 changed files with 54 additions and 20 deletions

View File

@ -4,12 +4,15 @@ from powerline.theme import Theme
from unicodedata import east_asian_width, combining
import os
try:
NBSP = unicode(' ', 'utf-8')
except NameError:
NBSP = ' '
try:
from __builtin__ import unichr as chr
except ImportError:
pass
def construct_returned_value(rendered_highlighted, segments, output_raw):
if output_raw:
@ -65,6 +68,22 @@ class Renderer(object):
python-2) regular string or ``None``.
'''
character_translations = {ord(' '): NBSP}
'''Character translations for use in escape() function.
See documentation of ``unicode.translate`` for details.
'''
np_character_translations = dict(((i, '^' + chr(i + 0x40)) for i in range(0x20)))
'''Non-printable character translations
These are used to transform characters in range 0x000x1F into ``^@``,
``^A`` and so on. Unilke with ``.escape()`` method (and
``character_translations``) result is passed to ``.strwidth()`` method.
Note: transforms tab into ``^I``.
'''
def __init__(self,
theme_config,
local_themes,
@ -262,8 +281,8 @@ class Renderer(object):
contents_raw = (segment['_space_left'] * ' ') + contents_raw + (segment['_space_right'] * ' ') + outer_padding
# Replace spaces with no-break spaces
contents_raw = contents_raw.replace(' ', NBSP)
divider_raw = divider_raw.replace(' ', NBSP)
contents_raw = contents_raw.translate(self.np_character_translations)
# Apply highlighting to padded dividers and contents
if render_highlighted:
@ -295,11 +314,11 @@ class Renderer(object):
segment['_len'] = self.strwidth(segment['_rendered_raw'])
yield segment
@staticmethod
def escape(string):
@classmethod
def escape(cls, string):
'''Method that escapes segment contents.
'''
return string
return string.translate(cls.character_translations)
def hlstyle(fg=None, bg=None, attr=None):
'''Output highlight style string.

View File

@ -1,5 +1,7 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals
from powerline.renderers.shell import ShellRenderer
@ -8,9 +10,9 @@ class BashPromptRenderer(ShellRenderer):
escape_hl_start = '\['
escape_hl_end = '\]'
@staticmethod
def escape(string):
return string.replace('\\', '\\\\').replace('$', '\\$').replace('`', '\\`')
character_translations = ShellRenderer.character_translations
character_translations[ord('$')] = '\\$'
character_translations[ord('`')] = '\\`'
renderer = BashPromptRenderer

View File

@ -1,5 +1,7 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals
from powerline.renderer import Renderer
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
@ -19,6 +21,9 @@ class ShellRenderer(Renderer):
tmux_escape = False
screen_escape = False
character_translations = Renderer.character_translations
character_translations[ord('\\')] = '\\\\'
def hlstyle(self, fg=None, bg=None, attr=None):
'''Highlight a segment.
@ -62,9 +67,5 @@ class ShellRenderer(Renderer):
r = '\033P' + r.replace('\033', '\033\033') + '\033\\'
return self.escape_hl_start + r + self.escape_hl_end
@staticmethod
def escape(string):
return string.replace('\\', '\\\\')
renderer = ShellRenderer

View File

@ -1,11 +1,17 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals
from powerline.renderer import Renderer
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
class TmuxRenderer(Renderer):
'''Powerline tmux segment renderer.'''
character_translations = Renderer.character_translations
character_translations[ord('#')] = '##[]'
def hlstyle(self, fg=None, bg=None, attr=None):
'''Highlight a segment.'''
# We don't need to explicitly reset attributes, so skip those calls

View File

@ -1,6 +1,6 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import
from __future__ import absolute_import, unicode_literals
from powerline.bindings.vim import vim_get_func, environ
from powerline.renderer import Renderer
@ -11,6 +11,12 @@ import vim
import sys
try:
from __builtin__ import unichr as chr
except ImportError:
pass
vim_mode = vim_get_func('mode', rettype=str)
mode_translations = {
chr(ord('V') - 0x40): '^V',
@ -21,6 +27,9 @@ mode_translations = {
class VimRenderer(Renderer):
'''Powerline vim segment renderer.'''
character_translations = Renderer.character_translations
character_translations[ord('%')] = '%%'
def __init__(self, *args, **kwargs):
if not hasattr(vim, 'strwidth'):
# Hope nobody want to change this at runtime
@ -97,10 +106,6 @@ class VimRenderer(Renderer):
def reset_highlight(self):
self.hl_groups.clear()
@staticmethod
def escape(string):
return string.replace('%', '%%')
def hlstyle(self, fg=None, bg=None, attr=None):
'''Highlight a segment.

View File

@ -1,5 +1,7 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals
from powerline.renderers.shell import ShellRenderer
@ -8,9 +10,8 @@ class ZshPromptRenderer(ShellRenderer):
escape_hl_start = '%{'
escape_hl_end = '%}'
@staticmethod
def escape(string):
return string.replace('%', '%%').replace('\\', '\\\\')
character_translations = ShellRenderer.character_translations
character_translations[ord('%')] = '%%'
renderer = ZshPromptRenderer