mirror of
https://github.com/powerline/powerline.git
synced 2025-07-25 14:54:54 +02:00
Merge remote-tracking branch 'zyx-i/fix-322' into develop
This commit is contained in:
commit
747c75c1c4
@ -6,19 +6,18 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from powerline.colorscheme import Colorscheme
|
from powerline.colorscheme import Colorscheme
|
||||||
from powerline.lib import underscore_to_camelcase
|
|
||||||
|
|
||||||
|
|
||||||
def open_file(path):
|
def open_file(path):
|
||||||
return open(path, 'r')
|
return open(path, 'r')
|
||||||
|
|
||||||
|
|
||||||
def load_json_config(search_paths, config_file, load=json.load, open=open_file):
|
def load_json_config(search_paths, config_file, load=json.load, open_file=open_file):
|
||||||
config_file += '.json'
|
config_file += '.json'
|
||||||
for path in search_paths:
|
for path in search_paths:
|
||||||
config_file_path = os.path.join(path, config_file)
|
config_file_path = os.path.join(path, config_file)
|
||||||
if os.path.isfile(config_file_path):
|
if os.path.isfile(config_file_path):
|
||||||
with open(config_file_path) as config_file_fp:
|
with open_file(config_file_path) as config_file_fp:
|
||||||
return load(config_file_fp)
|
return load(config_file_fp)
|
||||||
raise IOError('Config file not found in search path: {0}'.format(config_file))
|
raise IOError('Config file not found in search path: {0}'.format(config_file))
|
||||||
|
|
||||||
@ -65,9 +64,8 @@ class Powerline(object):
|
|||||||
# Load and initialize extension renderer
|
# Load and initialize extension renderer
|
||||||
renderer_module_name = renderer_module or ext
|
renderer_module_name = renderer_module or ext
|
||||||
renderer_module_import = 'powerline.renderers.{0}'.format(renderer_module_name)
|
renderer_module_import = 'powerline.renderers.{0}'.format(renderer_module_name)
|
||||||
renderer_class_name = '{0}Renderer'.format(underscore_to_camelcase(renderer_module_name))
|
|
||||||
try:
|
try:
|
||||||
Renderer = getattr(__import__(renderer_module_import, fromlist=[renderer_class_name]), renderer_class_name)
|
Renderer = __import__(renderer_module_import, fromlist=['renderer']).renderer
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
sys.stderr.write('Error while importing renderer module: {0}\n'.format(e))
|
sys.stderr.write('Error while importing renderer module: {0}\n'.format(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -7,11 +7,6 @@ from powerline.lib.humanize_bytes import humanize_bytes # NOQA
|
|||||||
from powerline.lib.url import urllib_read, urllib_urlencode # NOQA
|
from powerline.lib.url import urllib_read, urllib_urlencode # NOQA
|
||||||
|
|
||||||
|
|
||||||
def underscore_to_camelcase(string):
|
|
||||||
'''Return a underscore_separated_string as CamelCase.'''
|
|
||||||
return ''.join(word.capitalize() or '_' for word in string.split('_'))
|
|
||||||
|
|
||||||
|
|
||||||
def mergedicts(d1, d2):
|
def mergedicts(d1, d2):
|
||||||
'''Recursively merge two dictionaries. First dictionary is modified in-place.
|
'''Recursively merge two dictionaries. First dictionary is modified in-place.
|
||||||
'''
|
'''
|
||||||
|
@ -604,7 +604,7 @@ def check_segment_name(name, data, context, echoerr):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
echoerr(context='Error while loading segment function (key {key})'.format(key=context_key(context)),
|
echoerr(context='Error while loading segment function (key {key})'.format(key=context_key(context)),
|
||||||
problem='failed to load function {0} from module {1}'.format(name, module),
|
problem='failed to load function {0} from module {1}'.format(name, module),
|
||||||
problem_mark=match_name.mark)
|
problem_mark=name.mark)
|
||||||
return True, False, True
|
return True, False, True
|
||||||
|
|
||||||
if not callable(func):
|
if not callable(func):
|
||||||
@ -875,7 +875,7 @@ def check(path=None):
|
|||||||
|
|
||||||
hadproblem = False
|
hadproblem = False
|
||||||
try:
|
try:
|
||||||
main_config = load_json_config(search_paths, 'config', load=load_config, open=open_file)
|
main_config = load_json_config(search_paths, 'config', load=load_config, open_file=open_file)
|
||||||
except IOError:
|
except IOError:
|
||||||
main_config = {}
|
main_config = {}
|
||||||
sys.stderr.write('\nConfiguration file not found: config.json\n')
|
sys.stderr.write('\nConfiguration file not found: config.json\n')
|
||||||
@ -891,7 +891,7 @@ def check(path=None):
|
|||||||
import_paths = [os.path.expanduser(path) for path in main_config.get('common', {}).get('paths', [])]
|
import_paths = [os.path.expanduser(path) for path in main_config.get('common', {}).get('paths', [])]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
colors_config = load_json_config(search_paths, 'colors', load=load_config, open=open_file)
|
colors_config = load_json_config(search_paths, 'colors', load=load_config, open_file=open_file)
|
||||||
except IOError:
|
except IOError:
|
||||||
colors_config = {}
|
colors_config = {}
|
||||||
sys.stderr.write('\nConfiguration file not found: colors.json\n')
|
sys.stderr.write('\nConfiguration file not found: colors.json\n')
|
||||||
|
@ -88,7 +88,6 @@ class Reader(object):
|
|||||||
def check_printable(self, data):
|
def check_printable(self, data):
|
||||||
match = NON_PRINTABLE.search(data)
|
match = NON_PRINTABLE.search(data)
|
||||||
if match:
|
if match:
|
||||||
character = match.group()
|
|
||||||
self.update_pointer(match.start())
|
self.update_pointer(match.start())
|
||||||
raise ReaderError('while reading from stream', None,
|
raise ReaderError('while reading from stream', None,
|
||||||
'found special characters which are not allowed',
|
'found special characters which are not allowed',
|
||||||
|
@ -10,6 +10,13 @@ except NameError:
|
|||||||
NBSP = ' '
|
NBSP = ' '
|
||||||
|
|
||||||
|
|
||||||
|
def construct_returned_value(rendered_highlighted, segments, output_raw):
|
||||||
|
if output_raw:
|
||||||
|
return rendered_highlighted, ''.join((segment['_rendered_raw'] for segment in segments))
|
||||||
|
else:
|
||||||
|
return rendered_highlighted
|
||||||
|
|
||||||
|
|
||||||
class Renderer(object):
|
class Renderer(object):
|
||||||
def __init__(self, theme_config, local_themes, theme_kwargs, colorscheme, **options):
|
def __init__(self, theme_config, local_themes, theme_kwargs, colorscheme, **options):
|
||||||
self.__dict__.update(options)
|
self.__dict__.update(options)
|
||||||
@ -64,7 +71,7 @@ class Renderer(object):
|
|||||||
|
|
||||||
if not width:
|
if not width:
|
||||||
# No width specified, so we don't need to crop or pad anything
|
# No width specified, so we don't need to crop or pad anything
|
||||||
return self._returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw)
|
return construct_returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw)
|
||||||
|
|
||||||
# Create an ordered list of segments that can be dropped
|
# Create an ordered list of segments that can be dropped
|
||||||
segments_priority = [segment for segment in sorted(segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] > 0]
|
segments_priority = [segment for segment in sorted(segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] > 0]
|
||||||
@ -89,7 +96,7 @@ class Renderer(object):
|
|||||||
|
|
||||||
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
||||||
|
|
||||||
return self._returned_value(rendered_highlighted, segments, output_raw)
|
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
||||||
|
|
||||||
def _render_segments(self, theme, segments, render_highlighted=True):
|
def _render_segments(self, theme, segments, render_highlighted=True):
|
||||||
'''Internal segment rendering method.
|
'''Internal segment rendering method.
|
||||||
@ -166,24 +173,10 @@ class Renderer(object):
|
|||||||
segment['_len'] = self.strwidth(segment['_rendered_raw'])
|
segment['_len'] = self.strwidth(segment['_rendered_raw'])
|
||||||
yield segment
|
yield segment
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _returned_value(rendered_highlighted, segments, output_raw):
|
|
||||||
if output_raw:
|
|
||||||
return rendered_highlighted, ''.join((segment['_rendered_raw'] for segment in segments))
|
|
||||||
else:
|
|
||||||
return rendered_highlighted
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def escape(string):
|
def escape(string):
|
||||||
return string
|
return string
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _int_to_rgb(int):
|
|
||||||
r = (int >> 16) & 0xff
|
|
||||||
g = (int >> 8) & 0xff
|
|
||||||
b = int & 0xff
|
|
||||||
return r, g, b
|
|
||||||
|
|
||||||
def hlstyle(fg=None, bg=None, attr=None):
|
def hlstyle(fg=None, bg=None, attr=None):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -11,3 +11,6 @@ class BashPromptRenderer(ShellRenderer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def escape(string):
|
def escape(string):
|
||||||
return string.replace('\\', '\\\\').replace('$', '\\$').replace('`', '\\`')
|
return string.replace('\\', '\\\\').replace('$', '\\$').replace('`', '\\`')
|
||||||
|
|
||||||
|
|
||||||
|
renderer = BashPromptRenderer
|
||||||
|
@ -7,3 +7,6 @@ class IpythonRenderer(ShellRenderer):
|
|||||||
'''Powerline ipython segment renderer.'''
|
'''Powerline ipython segment renderer.'''
|
||||||
escape_hl_start = '\x01'
|
escape_hl_start = '\x01'
|
||||||
escape_hl_end = '\x02'
|
escape_hl_end = '\x02'
|
||||||
|
|
||||||
|
|
||||||
|
renderer = IpythonRenderer
|
||||||
|
@ -29,3 +29,6 @@ class PangoMarkupRenderer(Renderer):
|
|||||||
if attr & ATTR_UNDERLINE:
|
if attr & ATTR_UNDERLINE:
|
||||||
awesome_attr += ['underline="single"']
|
awesome_attr += ['underline="single"']
|
||||||
return '<span ' + ' '.join(awesome_attr) + '>' + contents + '</span>'
|
return '<span ' + ' '.join(awesome_attr) + '>' + contents + '</span>'
|
||||||
|
|
||||||
|
|
||||||
|
renderer = PangoMarkupRenderer
|
||||||
|
@ -4,6 +4,13 @@ from powerline.renderer import Renderer
|
|||||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||||
|
|
||||||
|
|
||||||
|
def int_to_rgb(num):
|
||||||
|
r = (num >> 16) & 0xff
|
||||||
|
g = (num >> 8) & 0xff
|
||||||
|
b = num & 0xff
|
||||||
|
return r, g, b
|
||||||
|
|
||||||
|
|
||||||
class ShellRenderer(Renderer):
|
class ShellRenderer(Renderer):
|
||||||
'''Powerline shell segment renderer.'''
|
'''Powerline shell segment renderer.'''
|
||||||
escape_hl_start = ''
|
escape_hl_start = ''
|
||||||
@ -25,7 +32,7 @@ class ShellRenderer(Renderer):
|
|||||||
ansi += [39]
|
ansi += [39]
|
||||||
else:
|
else:
|
||||||
if self.term_truecolor:
|
if self.term_truecolor:
|
||||||
ansi += [38, 2] + list(self._int_to_rgb(fg[1]))
|
ansi += [38, 2] + list(int_to_rgb(fg[1]))
|
||||||
else:
|
else:
|
||||||
ansi += [38, 5, fg[0]]
|
ansi += [38, 5, fg[0]]
|
||||||
if bg is not None:
|
if bg is not None:
|
||||||
@ -33,7 +40,7 @@ class ShellRenderer(Renderer):
|
|||||||
ansi += [49]
|
ansi += [49]
|
||||||
else:
|
else:
|
||||||
if self.term_truecolor:
|
if self.term_truecolor:
|
||||||
ansi += [48, 2] + list(self._int_to_rgb(bg[1]))
|
ansi += [48, 2] + list(int_to_rgb(bg[1]))
|
||||||
else:
|
else:
|
||||||
ansi += [48, 5, bg[0]]
|
ansi += [48, 5, bg[0]]
|
||||||
if attr is not None:
|
if attr is not None:
|
||||||
@ -58,3 +65,6 @@ class ShellRenderer(Renderer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def escape(string):
|
def escape(string):
|
||||||
return string.replace('\\', '\\\\')
|
return string.replace('\\', '\\\\')
|
||||||
|
|
||||||
|
|
||||||
|
renderer = ShellRenderer
|
||||||
|
@ -39,3 +39,6 @@ class TmuxRenderer(Renderer):
|
|||||||
else:
|
else:
|
||||||
tmux_attr += ['nounderscore']
|
tmux_attr += ['nounderscore']
|
||||||
return '#[' + ','.join(tmux_attr) + ']'
|
return '#[' + ','.join(tmux_attr) + ']'
|
||||||
|
|
||||||
|
|
||||||
|
renderer = TmuxRenderer
|
||||||
|
@ -9,6 +9,7 @@ from powerline.theme import Theme
|
|||||||
|
|
||||||
import vim
|
import vim
|
||||||
|
|
||||||
|
|
||||||
vim_mode = vim_get_func('mode')
|
vim_mode = vim_get_func('mode')
|
||||||
vim_getwinvar = vim_get_func('getwinvar')
|
vim_getwinvar = vim_get_func('getwinvar')
|
||||||
vim_setwinvar = vim_get_func('setwinvar')
|
vim_setwinvar = vim_get_func('setwinvar')
|
||||||
@ -132,3 +133,6 @@ class VimRenderer(Renderer):
|
|||||||
attr=','.join(hl_group['attr']),
|
attr=','.join(hl_group['attr']),
|
||||||
))
|
))
|
||||||
return '%#' + self.hl_groups[(fg, bg, attr)]['name'] + '#'
|
return '%#' + self.hl_groups[(fg, bg, attr)]['name'] + '#'
|
||||||
|
|
||||||
|
|
||||||
|
renderer = VimRenderer
|
||||||
|
@ -11,3 +11,6 @@ class ZshPromptRenderer(ShellRenderer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def escape(string):
|
def escape(string):
|
||||||
return string.replace('%', '%%').replace('\\', '\\\\')
|
return string.replace('%', '%%').replace('\\', '\\\\')
|
||||||
|
|
||||||
|
|
||||||
|
renderer = ZshPromptRenderer
|
||||||
|
@ -151,16 +151,23 @@ def readonly_indicator(segment_info, text=''):
|
|||||||
|
|
||||||
|
|
||||||
@requires_segment_info
|
@requires_segment_info
|
||||||
def file_directory(segment_info, shorten_home=False):
|
def file_directory(segment_info, shorten_user=True, shorten_cwd=True, shorten_home=False):
|
||||||
'''Return file directory (head component of the file path).
|
'''Return file directory (head component of the file path).
|
||||||
|
|
||||||
|
:param bool shorten_user:
|
||||||
|
shorten ``$HOME`` directory to :file:`~/`
|
||||||
|
|
||||||
|
:param bool shorten_cwd:
|
||||||
|
shorten current directory to :file:`./`
|
||||||
|
|
||||||
:param bool shorten_home:
|
:param bool shorten_home:
|
||||||
shorten all directories in :file:`/home/` to :file:`~user/` instead of :file:`/home/user/`.
|
shorten all directories in :file:`/home/` to :file:`~user/` instead of :file:`/home/user/`.
|
||||||
'''
|
'''
|
||||||
name = segment_info['buffer'].name
|
name = segment_info['buffer'].name
|
||||||
if not name:
|
if not name:
|
||||||
return None
|
return None
|
||||||
file_directory = vim_funcs['fnamemodify'](name, ':~:.:h')
|
file_directory = vim_funcs['fnamemodify'](name, (':~' if shorten_user else '')
|
||||||
|
+ (':.' if shorten_home else '') + ':h')
|
||||||
if shorten_home and file_directory.startswith('/home/'):
|
if shorten_home and file_directory.startswith('/home/'):
|
||||||
file_directory = '~' + file_directory[6:]
|
file_directory = '~' + file_directory[6:]
|
||||||
return file_directory + os.sep if file_directory else None
|
return file_directory + os.sep if file_directory else None
|
||||||
|
@ -57,6 +57,34 @@ class TestConfig(TestCase):
|
|||||||
from powerline.shell import ShellPowerline
|
from powerline.shell import ShellPowerline
|
||||||
with replace_module_attr(common, 'urllib_read', urllib_read):
|
with replace_module_attr(common, 'urllib_read', urllib_read):
|
||||||
ShellPowerline(Args(ext=['tmux'])).renderer.render()
|
ShellPowerline(Args(ext=['tmux'])).renderer.render()
|
||||||
|
reload(common)
|
||||||
|
|
||||||
|
def test_zsh(self):
|
||||||
|
from powerline.shell import ShellPowerline
|
||||||
|
ShellPowerline(Args(last_pipe_status=[1, 0], ext=['shell'], renderer_module='zsh_prompt')).renderer.render()
|
||||||
|
|
||||||
|
def test_bash(self):
|
||||||
|
from powerline.shell import ShellPowerline
|
||||||
|
ShellPowerline(Args(last_exit_code=1, ext=['shell'], renderer_module='bash_prompt', config=[('ext', {'shell': {'theme': 'default_leftonly'}})])).renderer.render()
|
||||||
|
|
||||||
|
def test_ipython(self):
|
||||||
|
from powerline.ipython import IpythonPowerline
|
||||||
|
|
||||||
|
class IpyPowerline(IpythonPowerline):
|
||||||
|
path = None
|
||||||
|
config_overrides = None
|
||||||
|
theme_overrides = {}
|
||||||
|
|
||||||
|
IpyPowerline().renderer.render()
|
||||||
|
|
||||||
|
def test_wm(self):
|
||||||
|
from powerline.segments import common
|
||||||
|
from imp import reload
|
||||||
|
reload(common)
|
||||||
|
from powerline import Powerline
|
||||||
|
with replace_module_attr(common, 'urllib_read', urllib_read):
|
||||||
|
Powerline(ext='wm', renderer_module='pango_markup').renderer.render()
|
||||||
|
reload(common)
|
||||||
|
|
||||||
|
|
||||||
old_cwd = None
|
old_cwd = None
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from powerline.lib import mergedicts, underscore_to_camelcase, add_divider_highlight_group, humanize_bytes
|
from powerline.lib import mergedicts, add_divider_highlight_group, humanize_bytes
|
||||||
from powerline.lib.vcs import guess
|
from powerline.lib.vcs import guess
|
||||||
from subprocess import call, PIPE
|
from subprocess import call, PIPE
|
||||||
import os
|
import os
|
||||||
@ -8,10 +8,6 @@ from tests import TestCase
|
|||||||
|
|
||||||
|
|
||||||
class TestLib(TestCase):
|
class TestLib(TestCase):
|
||||||
def test_underscore_to_camelcase(self):
|
|
||||||
self.assertEqual(underscore_to_camelcase('abc_def_ghi'), 'AbcDefGhi')
|
|
||||||
self.assertEqual(underscore_to_camelcase('abc_def__ghi'), 'AbcDef_Ghi')
|
|
||||||
|
|
||||||
def test_mergedicts(self):
|
def test_mergedicts(self):
|
||||||
d = {}
|
d = {}
|
||||||
mergedicts(d, {'abc': {'def': 'ghi'}})
|
mergedicts(d, {'abc': {'def': 'ghi'}})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user