Merge branch 'feature/extended-vim-example' into develop

This commit is contained in:
Kim Silkebækken 2012-11-21 12:23:49 +01:00
commit 3be7dc2a40
7 changed files with 279 additions and 266 deletions

View File

@ -5,7 +5,7 @@
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from lib.core import Powerline, Segment
from lib.renderers import TerminalSegmentRenderer

View File

@ -2,9 +2,8 @@
import vim
import os
import re
from lib.core import Powerline, Segment
from lib.core import Powerline, mksegment
from lib.renderers import VimSegmentRenderer
modes = {
@ -28,6 +27,9 @@ modes = {
'!': 'SHELL',
}
# We need to replace this private use glyph with a double-percent later
percent_placeholder = u''
if hasattr(vim, 'bindeval'):
# This branch is used to avoid invoking vim parser as much as possible
@ -70,103 +72,119 @@ vim_funcs = {
'col': get_vim_func('col', rettype=int),
'expand': get_vim_func('expand'),
'tbcurtag': get_vim_func('tagbar#currenttag'),
'sstlflag': get_vim_func('SyntasticStatuslineFlag'),
'hlexists': get_vim_func('hlexists', rettype=int),
}
getwinvar = get_vim_func('getwinvar')
setwinvar = get_vim_func('setwinvar')
def statusline():
winwidth = vim_funcs['winwidth'](0)
# Prepare segment contents
def statusline(winnr):
winwidth = vim_funcs['winwidth'](winnr)
current = getwinvar(winnr, 'current')
windata = getwinvar(winnr, 'powerline')
if current:
# Recreate segment data for each redraw if we're in the current window
line_current = vim_funcs['line']('.')
line_end = vim_funcs['line']('$')
line_percent = line_current * 100 // line_end
try:
branch = vim_funcs['fghead'](5)
except vim.error:
vim_funcs['fghead'] = None
branch = ''
except TypeError:
branch = ''
if branch:
branch = u'' + branch
# Fun gradient colored percent segment
line_percent_gradient = [160, 166, 172, 178, 184, 190]
line_percent_color = line_percent_gradient[int((len(line_percent_gradient) - 1) * line_percent / 100)]
col_current = vim_funcs['col']('.')
filepath, filename = os.path.split(vim_funcs['expand']('%:~:.'))
filename_color = 231
if filepath:
filepath += os.sep
if not filename:
filename = '[No Name]'
filename_color = 250
readonly = vim.eval('&ro ? "" : ""')
modified = vim.eval('&mod ? " +" : ""')
try:
currenttag = vim_funcs['tbcurtag']('%s', '')
except vim.error:
vim_funcs['tbcurtag'] = None
currenttag = ''
except TypeError:
currenttag = ''
windata = {
'paste': vim.eval('&paste ? "PASTE" : ""'),
'branch': branch,
'readonly': readonly,
'filepath': filepath,
'filename': filename,
'filename_color': filename_color,
'modified': modified,
'currenttag': currenttag,
'fileformat': vim.eval('&ff'),
'fileencoding': vim.eval('&fenc'),
'filetype': vim.eval('&ft'),
'line_percent': str(line_percent).rjust(3) + percent_placeholder,
'line_percent_color': line_percent_color,
'linecurrent': str(line_current).rjust(3),
'colcurrent': ':' + str(col_current).ljust(2),
}
setwinvar(winnr, 'powerline', windata)
mode = modes[vim_funcs['mode']()]
try:
branch = vim_funcs['fghead'](5)
except vim.error:
vim_funcs['fghead'] = None
branch = ''
except TypeError:
branch = ''
if branch:
branch = '' + branch
line_current = vim_funcs['line']('.')
line_end = vim_funcs['line']('$')
line_percent = line_current * 100 // line_end
# Fun gradient colored percent segment
line_percent_gradient = [160, 166, 172, 178, 184, 190]
line_percent_color = line_percent_gradient[int((len(line_percent_gradient) - 1) * line_percent / 100)]
col_current = vim_funcs['col']('.')
filepath, filename = os.path.split(vim_funcs['expand']('%:~:.'))
filename_color = 231
if filepath:
filepath += os.sep
if not filename:
filename = '[No Name]'
filename_color = 250
readonly = vim.eval('&ro ? "" : ""')
modified = vim.eval('&mod ? " +" : ""')
try:
currenttag = vim_funcs['tbcurtag']('%s', '')
except vim.error:
vim_funcs['tbcurtag'] = None
currenttag = ''
except TypeError:
currenttag = ''
# The Syntastic segment is center aligned (filler segment on each side) to show off how the filler segments work
# Not necessarily how it's going to look in the final theme
set_global_var('syntastic_stl_format', '%E{ ERRORS (%e) ⭡ %fe }%W{ WARNINGS (%w) ⭡ %fw } ⮁')
try:
syntastic = vim_funcs['sstlflag']()
except vim.error:
vim_funcs['sstlflag'] = None
syntastic = ''
except TypeError:
syntastic = ''
if not current:
mode = None
powerline = Powerline([
Segment(mode, 22, 148, attr=Segment.ATTR_BOLD),
Segment(vim.eval('&paste ? "PASTE" : ""'), 231, 166, attr=Segment.ATTR_BOLD),
Segment(branch, 250, 240, priority=10),
Segment(readonly, 196, 240, draw_divider=False),
Segment(filepath, 250, 240, draw_divider=False, priority=5),
Segment(filename, filename_color, 240, attr=Segment.ATTR_BOLD, draw_divider=not len(modified)),
Segment(modified, 220, 240, attr=Segment.ATTR_BOLD),
Segment(currenttag, 246, 236, draw_divider=False, priority=100),
Segment(filler=True, fg=236, bg=236),
Segment(syntastic, 214, 236, attr=Segment.ATTR_BOLD, draw_divider=False, priority=100),
Segment(filler=True, fg=236, bg=236),
Segment(vim.eval('&ff'), 247, 236, side='r', priority=50),
Segment(vim.eval('&fenc'), 247, 236, side='r', priority=50),
Segment(vim.eval('&ft'), 247, 236, side='r', priority=50),
Segment(str(line_percent).rjust(3) + '%', line_percent_color, 240, side='r', priority=30),
Segment('', 239, 252, side='r'),
Segment(str(line_current).rjust(3), 235, 252, attr=Segment.ATTR_BOLD, side='r', draw_divider=False),
Segment(':' + str(col_current).ljust(2), 244, 252, side='r', priority=30, draw_divider=False),
mksegment(mode, 22, 148, attr=Powerline.ATTR_BOLD),
mksegment(windata['paste'], 231, 166, attr=Powerline.ATTR_BOLD),
mksegment(windata['branch'], 250, 240, priority=60),
mksegment(windata['readonly'], 196, 240, draw_divider=False),
mksegment(windata['filepath'], 250, 240, draw_divider=False, priority=40),
mksegment(windata['filename'], windata['filename_color'], 240, attr=Powerline.ATTR_BOLD, draw_divider=not len(windata['modified'])),
mksegment(windata['modified'], 220, 240, attr=Powerline.ATTR_BOLD),
mksegment(windata['currenttag'], 246, 236, draw_divider=False, priority=100),
mksegment(filler=True, cterm_fg=236, cterm_bg=236),
mksegment(windata['fileformat'], 247, 236, side='r', priority=50),
mksegment(windata['fileencoding'], 247, 236, side='r', priority=50),
mksegment(windata['filetype'], 247, 236, side='r', priority=50),
mksegment(windata['line_percent'], windata['line_percent_color'], 240, side='r', priority=30),
mksegment(u'', 239, 252, side='r'),
mksegment(windata['linecurrent'], 235, 252, attr=Powerline.ATTR_BOLD, side='r', draw_divider=False),
mksegment(windata['colcurrent'], 244, 252, side='r', priority=30, draw_divider=False),
])
renderer = VimSegmentRenderer()
stl = powerline.render(renderer, winwidth)
# Escape percent chars in the statusline, but only if they aren't part of any stl escape sequence
stl = re.sub('(\w+)\%(?![-{()<=#*%])', '\\1%%', stl)
# Replace percent placeholders
stl = stl.replace(percent_placeholder, '%%')
# Create highlighting groups
for group, hl in renderer.hl_groups.items():
if vim_funcs['hlexists'](group):
for idx, hl in renderer.hl_groups.items():
if vim_funcs['hlexists'](hl['name']):
# Only create hl group if it doesn't already exist
continue
vim.command('hi {group} ctermfg={ctermfg} guifg={guifg} guibg={guibg} ctermbg={ctermbg} cterm={attr} gui={attr}'.format(
group=group,
group=hl['name'],
ctermfg=hl['ctermfg'],
guifg='#{0:06x}'.format(hl['guifg']) if hl['guifg'] != 'NONE' else 'NONE',
ctermbg=hl['ctermbg'],
@ -176,6 +194,4 @@ def statusline():
return stl
statusline()
# vim: ft=python ts=4 sts=4 sw=4 noet

View File

@ -6,7 +6,7 @@ python sys.path.append(vim.eval('expand("<sfile>:h:h:h")'))
python from examples.vim.powerline import statusline
if exists('*pyeval')
let s:pyeval=function('pyeval')
let s:pyeval = function('pyeval')
else
python import json
function! s:pyeval(e)
@ -14,8 +14,20 @@ else
endfunction
endif
function! DynStl()
return s:pyeval('statusline()')
function! Powerline(winnr)
return s:pyeval('statusline('. a:winnr .')')
endfunction
set stl=%!DynStl()
function! s:WinDoPowerline()
if ! exists('w:powerline')
let w:powerline = {}
endif
let &l:stl = '%!Powerline('. winnr() .')'
endfunction
augroup Powerline
autocmd!
autocmd BufEnter,BufWinEnter,WinEnter * let w:current = 1 | let currwin = winnr() | windo call s:WinDoPowerline() | exec currwin . 'wincmd w'
autocmd BufLeave,BufWinLeave,WinLeave * let w:current = 0
augroup END

View File

@ -1,54 +1,42 @@
def cterm_to_hex(cterm_color):
'''Translate a cterm color index into the corresponding hex/RGB color.
'''
color_dict = {
16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,
22: 0x005f00, 23: 0x005f5f, 24: 0x005f87, 25: 0x005faf, 26: 0x005fd7, 27: 0x005fff,
28: 0x008700, 29: 0x00875f, 30: 0x008787, 31: 0x0087af, 32: 0x0087d7, 33: 0x0087ff,
34: 0x00af00, 35: 0x00af5f, 36: 0x00af87, 37: 0x00afaf, 38: 0x00afd7, 39: 0x00afff,
40: 0x00d700, 41: 0x00d75f, 42: 0x00d787, 43: 0x00d7af, 44: 0x00d7d7, 45: 0x00d7ff,
46: 0x00ff00, 47: 0x00ff5f, 48: 0x00ff87, 49: 0x00ffaf, 50: 0x00ffd7, 51: 0x00ffff,
52: 0x5f0000, 53: 0x5f005f, 54: 0x5f0087, 55: 0x5f00af, 56: 0x5f00d7, 57: 0x5f00ff,
58: 0x5f5f00, 59: 0x5f5f5f, 60: 0x5f5f87, 61: 0x5f5faf, 62: 0x5f5fd7, 63: 0x5f5fff,
64: 0x5f8700, 65: 0x5f875f, 66: 0x5f8787, 67: 0x5f87af, 68: 0x5f87d7, 69: 0x5f87ff,
70: 0x5faf00, 71: 0x5faf5f, 72: 0x5faf87, 73: 0x5fafaf, 74: 0x5fafd7, 75: 0x5fafff,
76: 0x5fd700, 77: 0x5fd75f, 78: 0x5fd787, 79: 0x5fd7af, 80: 0x5fd7d7, 81: 0x5fd7ff,
82: 0x5fff00, 83: 0x5fff5f, 84: 0x5fff87, 85: 0x5fffaf, 86: 0x5fffd7, 87: 0x5fffff,
88: 0x870000, 89: 0x87005f, 90: 0x870087, 91: 0x8700af, 92: 0x8700d7, 93: 0x8700ff,
94: 0x875f00, 95: 0x875f5f, 96: 0x875f87, 97: 0x875faf, 98: 0x875fd7, 99: 0x875fff,
100: 0x878700, 101: 0x87875f, 102: 0x878787, 103: 0x8787af, 104: 0x8787d7, 105: 0x8787ff,
106: 0x87af00, 107: 0x87af5f, 108: 0x87af87, 109: 0x87afaf, 110: 0x87afd7, 111: 0x87afff,
112: 0x87d700, 113: 0x87d75f, 114: 0x87d787, 115: 0x87d7af, 116: 0x87d7d7, 117: 0x87d7ff,
118: 0x87ff00, 119: 0x87ff5f, 120: 0x87ff87, 121: 0x87ffaf, 122: 0x87ffd7, 123: 0x87ffff,
124: 0xaf0000, 125: 0xaf005f, 126: 0xaf0087, 127: 0xaf00af, 128: 0xaf00d7, 129: 0xaf00ff,
130: 0xaf5f00, 131: 0xaf5f5f, 132: 0xaf5f87, 133: 0xaf5faf, 134: 0xaf5fd7, 135: 0xaf5fff,
136: 0xaf8700, 137: 0xaf875f, 138: 0xaf8787, 139: 0xaf87af, 140: 0xaf87d7, 141: 0xaf87ff,
142: 0xafaf00, 143: 0xafaf5f, 144: 0xafaf87, 145: 0xafafaf, 146: 0xafafd7, 147: 0xafafff,
148: 0xafd700, 149: 0xafd75f, 150: 0xafd787, 151: 0xafd7af, 152: 0xafd7d7, 153: 0xafd7ff,
154: 0xafff00, 155: 0xafff5f, 156: 0xafff87, 157: 0xafffaf, 158: 0xafffd7, 159: 0xafffff,
160: 0xd70000, 161: 0xd7005f, 162: 0xd70087, 163: 0xd700af, 164: 0xd700d7, 165: 0xd700ff,
166: 0xd75f00, 167: 0xd75f5f, 168: 0xd75f87, 169: 0xd75faf, 170: 0xd75fd7, 171: 0xd75fff,
172: 0xd78700, 173: 0xd7875f, 174: 0xd78787, 175: 0xd787af, 176: 0xd787d7, 177: 0xd787ff,
178: 0xd7af00, 179: 0xd7af5f, 180: 0xd7af87, 181: 0xd7afaf, 182: 0xd7afd7, 183: 0xd7afff,
184: 0xd7d700, 185: 0xd7d75f, 186: 0xd7d787, 187: 0xd7d7af, 188: 0xd7d7d7, 189: 0xd7d7ff,
190: 0xd7ff00, 191: 0xd7ff5f, 192: 0xd7ff87, 193: 0xd7ffaf, 194: 0xd7ffd7, 195: 0xd7ffff,
196: 0xff0000, 197: 0xff005f, 198: 0xff0087, 199: 0xff00af, 200: 0xff00d7, 201: 0xff00ff,
202: 0xff5f00, 203: 0xff5f5f, 204: 0xff5f87, 205: 0xff5faf, 206: 0xff5fd7, 207: 0xff5fff,
208: 0xff8700, 209: 0xff875f, 210: 0xff8787, 211: 0xff87af, 212: 0xff87d7, 213: 0xff87ff,
214: 0xffaf00, 215: 0xffaf5f, 216: 0xffaf87, 217: 0xffafaf, 218: 0xffafd7, 219: 0xffafff,
220: 0xffd700, 221: 0xffd75f, 222: 0xffd787, 223: 0xffd7af, 224: 0xffd7d7, 225: 0xffd7ff,
226: 0xffff00, 227: 0xffff5f, 228: 0xffff87, 229: 0xffffaf, 230: 0xffffd7, 231: 0xffffff,
232: 0x080808, 233: 0x121212, 234: 0x1c1c1c, 235: 0x262626, 236: 0x303030, 237: 0x3a3a3a,
238: 0x444444, 239: 0x4e4e4e, 240: 0x585858, 241: 0x626262, 242: 0x6c6c6c, 243: 0x767676,
244: 0x808080, 245: 0x8a8a8a, 246: 0x949494, 247: 0x9e9e9e, 248: 0xa8a8a8, 249: 0xb2b2b2,
250: 0xbcbcbc, 251: 0xc6c6c6, 252: 0xd0d0d0, 253: 0xdadada, 254: 0xe4e4e4, 255: 0xeeeeee,
}
if not cterm_color:
return None
try:
return color_dict[cterm_color]
except KeyError:
import sys
sys.stderr.write('Invalid cterm color index: {0}\n'.format(cterm_color))
return None
cterm_to_hex = {
16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,
22: 0x005f00, 23: 0x005f5f, 24: 0x005f87, 25: 0x005faf, 26: 0x005fd7, 27: 0x005fff,
28: 0x008700, 29: 0x00875f, 30: 0x008787, 31: 0x0087af, 32: 0x0087d7, 33: 0x0087ff,
34: 0x00af00, 35: 0x00af5f, 36: 0x00af87, 37: 0x00afaf, 38: 0x00afd7, 39: 0x00afff,
40: 0x00d700, 41: 0x00d75f, 42: 0x00d787, 43: 0x00d7af, 44: 0x00d7d7, 45: 0x00d7ff,
46: 0x00ff00, 47: 0x00ff5f, 48: 0x00ff87, 49: 0x00ffaf, 50: 0x00ffd7, 51: 0x00ffff,
52: 0x5f0000, 53: 0x5f005f, 54: 0x5f0087, 55: 0x5f00af, 56: 0x5f00d7, 57: 0x5f00ff,
58: 0x5f5f00, 59: 0x5f5f5f, 60: 0x5f5f87, 61: 0x5f5faf, 62: 0x5f5fd7, 63: 0x5f5fff,
64: 0x5f8700, 65: 0x5f875f, 66: 0x5f8787, 67: 0x5f87af, 68: 0x5f87d7, 69: 0x5f87ff,
70: 0x5faf00, 71: 0x5faf5f, 72: 0x5faf87, 73: 0x5fafaf, 74: 0x5fafd7, 75: 0x5fafff,
76: 0x5fd700, 77: 0x5fd75f, 78: 0x5fd787, 79: 0x5fd7af, 80: 0x5fd7d7, 81: 0x5fd7ff,
82: 0x5fff00, 83: 0x5fff5f, 84: 0x5fff87, 85: 0x5fffaf, 86: 0x5fffd7, 87: 0x5fffff,
88: 0x870000, 89: 0x87005f, 90: 0x870087, 91: 0x8700af, 92: 0x8700d7, 93: 0x8700ff,
94: 0x875f00, 95: 0x875f5f, 96: 0x875f87, 97: 0x875faf, 98: 0x875fd7, 99: 0x875fff,
100: 0x878700, 101: 0x87875f, 102: 0x878787, 103: 0x8787af, 104: 0x8787d7, 105: 0x8787ff,
106: 0x87af00, 107: 0x87af5f, 108: 0x87af87, 109: 0x87afaf, 110: 0x87afd7, 111: 0x87afff,
112: 0x87d700, 113: 0x87d75f, 114: 0x87d787, 115: 0x87d7af, 116: 0x87d7d7, 117: 0x87d7ff,
118: 0x87ff00, 119: 0x87ff5f, 120: 0x87ff87, 121: 0x87ffaf, 122: 0x87ffd7, 123: 0x87ffff,
124: 0xaf0000, 125: 0xaf005f, 126: 0xaf0087, 127: 0xaf00af, 128: 0xaf00d7, 129: 0xaf00ff,
130: 0xaf5f00, 131: 0xaf5f5f, 132: 0xaf5f87, 133: 0xaf5faf, 134: 0xaf5fd7, 135: 0xaf5fff,
136: 0xaf8700, 137: 0xaf875f, 138: 0xaf8787, 139: 0xaf87af, 140: 0xaf87d7, 141: 0xaf87ff,
142: 0xafaf00, 143: 0xafaf5f, 144: 0xafaf87, 145: 0xafafaf, 146: 0xafafd7, 147: 0xafafff,
148: 0xafd700, 149: 0xafd75f, 150: 0xafd787, 151: 0xafd7af, 152: 0xafd7d7, 153: 0xafd7ff,
154: 0xafff00, 155: 0xafff5f, 156: 0xafff87, 157: 0xafffaf, 158: 0xafffd7, 159: 0xafffff,
160: 0xd70000, 161: 0xd7005f, 162: 0xd70087, 163: 0xd700af, 164: 0xd700d7, 165: 0xd700ff,
166: 0xd75f00, 167: 0xd75f5f, 168: 0xd75f87, 169: 0xd75faf, 170: 0xd75fd7, 171: 0xd75fff,
172: 0xd78700, 173: 0xd7875f, 174: 0xd78787, 175: 0xd787af, 176: 0xd787d7, 177: 0xd787ff,
178: 0xd7af00, 179: 0xd7af5f, 180: 0xd7af87, 181: 0xd7afaf, 182: 0xd7afd7, 183: 0xd7afff,
184: 0xd7d700, 185: 0xd7d75f, 186: 0xd7d787, 187: 0xd7d7af, 188: 0xd7d7d7, 189: 0xd7d7ff,
190: 0xd7ff00, 191: 0xd7ff5f, 192: 0xd7ff87, 193: 0xd7ffaf, 194: 0xd7ffd7, 195: 0xd7ffff,
196: 0xff0000, 197: 0xff005f, 198: 0xff0087, 199: 0xff00af, 200: 0xff00d7, 201: 0xff00ff,
202: 0xff5f00, 203: 0xff5f5f, 204: 0xff5f87, 205: 0xff5faf, 206: 0xff5fd7, 207: 0xff5fff,
208: 0xff8700, 209: 0xff875f, 210: 0xff8787, 211: 0xff87af, 212: 0xff87d7, 213: 0xff87ff,
214: 0xffaf00, 215: 0xffaf5f, 216: 0xffaf87, 217: 0xffafaf, 218: 0xffafd7, 219: 0xffafff,
220: 0xffd700, 221: 0xffd75f, 222: 0xffd787, 223: 0xffd7af, 224: 0xffd7d7, 225: 0xffd7ff,
226: 0xffff00, 227: 0xffff5f, 228: 0xffff87, 229: 0xffffaf, 230: 0xffffd7, 231: 0xffffff,
232: 0x080808, 233: 0x121212, 234: 0x1c1c1c, 235: 0x262626, 236: 0x303030, 237: 0x3a3a3a,
238: 0x444444, 239: 0x4e4e4e, 240: 0x585858, 241: 0x626262, 242: 0x6c6c6c, 243: 0x767676,
244: 0x808080, 245: 0x8a8a8a, 246: 0x949494, 247: 0x9e9e9e, 248: 0xa8a8a8, 249: 0xb2b2b2,
250: 0xbcbcbc, 251: 0xc6c6c6, 252: 0xd0d0d0, 253: 0xdadada, 254: 0xe4e4e4, 255: 0xeeeeee,
}

View File

@ -1,15 +1,21 @@
# -*- coding: utf-8 -*-
from lib.colors import cterm_to_hex
class Powerline(object):
ATTR_BOLD = 1
ATTR_ITALIC = 2
ATTR_UNDERLINE = 4
class Powerline:
dividers = {
'l': {
'hard': '',
'soft': '',
'hard': u'',
'soft': u'',
},
'r': {
'hard': '',
'soft': '',
'hard': u'',
'soft': u'',
},
}
@ -19,7 +25,8 @@ class Powerline:
Segments that have empty contents and aren't filler segments are
dropped from the segment array.
'''
self.segments = [segment for segment in segments if segment.contents or segment.filler]
self.segments = [segment for segment in segments if segment['contents'] or segment['filler']]
self._hl = {}
def render(self, renderer, width=None):
'''Render all the segments with the specified renderer.
@ -34,7 +41,7 @@ class Powerline:
provided they will fill the remaining space until the desired width is
reached.
'''
def render_segments(segments, render_raw=True, render_highlighted=True):
def render_segments(segments, render_highlighted=True):
'''Render a segment array.
By default this function renders both raw (un-highlighted segments
@ -42,125 +49,114 @@ class Powerline:
rendering is used for calculating the total width for dropping
low-priority segments.
'''
rendered_raw = ''
rendered_highlighted = ''
rendered_highlighted = u''
segments_len = len(segments)
empty_segment = mksegment()
for idx, segment in enumerate(segments):
prev = segments[idx - 1] if idx > 0 else Segment()
next = segments[idx + 1] if idx < len(segments) - 1 else Segment()
prev = segments[idx - 1] if idx > 0 else empty_segment
next = segments[idx + 1] if idx < segments_len - 1 else empty_segment
compare_segment = next if segment.side == 'l' else prev
divider_type = 'soft' if compare_segment.bg == segment.bg else 'hard'
divider = self.dividers[segment.side][divider_type]
segment['rendered_raw'] = u''
compare = next if segment['side'] == 'l' else prev
outer_padding = ' ' if idx == 0 or idx == segments_len - 1 else ''
divider_type = 'soft' if compare['bg'] == segment['bg'] else 'hard'
divider = self.dividers[segment['side']][divider_type]
divider_hl = ''
segment_hl = ''
if segment.filler:
if render_highlighted:
# Generate and cache renderer highlighting
if divider_type == 'hard':
hl_key = (segment['bg'], compare['bg'])
if not hl_key in self._hl:
self._hl[hl_key] = renderer.hl(*hl_key)
divider_hl = self._hl[hl_key]
hl_key = (segment['fg'], segment['bg'], segment['attr'])
if not hl_key in self._hl:
self._hl[hl_key] = renderer.hl(*hl_key)
segment_hl = self._hl[hl_key]
if segment['filler']:
# Filler segments shouldn't be padded
segment_format = '{contents}'
elif segment.draw_divider and (divider_type == 'hard' or segment.side == compare_segment.side):
rendered_highlighted += segment['contents']
elif segment['draw_divider'] and (divider_type == 'hard' or segment['side'] == compare['side']):
# Draw divider if specified, and if the next segment is on
# the opposite side only draw the divider if it's a hard
# divider
if segment.side == 'l':
segment_format = '{segment_hl}{outer_padding}{contents} {divider_hl}{divider} '
if segment['side'] == 'l':
segment['rendered_raw'] += outer_padding + segment['contents'] + ' ' + divider + ' '
rendered_highlighted += segment_hl + outer_padding + segment['contents'] + ' ' + divider_hl + divider + ' '
else:
segment_format = ' {divider_hl}{divider}{segment_hl} {contents}{outer_padding}'
elif segment.contents:
segment['rendered_raw'] += ' ' + divider + ' ' + segment['contents'] + outer_padding
rendered_highlighted += ' ' + divider_hl + divider + segment_hl + ' ' + segment['contents'] + outer_padding
elif segment['contents']:
# Segments without divider
segment_format = '{segment_hl}{contents}{outer_padding}'
if segment['side'] == 'l':
segment['rendered_raw'] += outer_padding + segment['contents']
rendered_highlighted += segment_hl + outer_padding + segment['contents']
else:
segment['rendered_raw'] += segment['contents'] + outer_padding
rendered_highlighted += segment_hl + segment['contents'] + outer_padding
else:
# Unknown segment type, skip it
continue
if render_raw is True and segment.filler is False:
# Filler segments must be empty when used e.g. in vim (the
# %=%< segment which disappears), so they will be skipped
# when calculating the width using the raw rendering
rendered_raw += segment_format.format(
divider=divider,
contents=segment.contents,
divider_hl='',
segment_hl='',
outer_padding=' ' if idx == 0 or idx == len(segments) - 1 else '',
)
return rendered_highlighted
if render_highlighted is True:
rendered_highlighted += segment_format.format(
divider=divider,
contents=segment.contents,
divider_hl='' if divider_type == 'soft' else renderer.hl(segment.bg, compare_segment.bg),
segment_hl=renderer.hl(segment.fg, segment.bg, segment.attr),
outer_padding=' ' if idx == 0 or idx == len(segments) - 1 else '',
)
return {
'highlighted': rendered_highlighted.decode('utf-8'),
'raw': rendered_raw.decode('utf-8'),
}
rendered = render_segments(self.segments)
rendered_highlighted = render_segments(self.segments)
if not width:
# No width specified, so we don't need to crop or pad anything
return rendered['highlighted']
return rendered_highlighted
# Create an ordered list of segments that can be dropped
segments_priority = [segment for segment in sorted(self.segments, key=lambda segment: segment.priority, reverse=True) if segment.priority > 0]
segments_priority = [segment for segment in sorted(self.segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] > 0]
while len(rendered['raw']) > width and len(segments_priority):
while self._total_len() > width and len(segments_priority):
self.segments.remove(segments_priority[0])
segments_priority.pop(0)
rendered = render_segments(self.segments, render_highlighted=False)
# Do another render pass so we can calculate the correct amount of filler space
render_segments(self.segments)
# Distribute the remaining space on the filler segments
segments_fillers = [segment for segment in self.segments if segment.filler is True]
segments_fillers = [segment for segment in self.segments if segment['filler'] is True]
if segments_fillers:
segments_fillers_len, segments_fillers_remainder = divmod((width - len(rendered['raw'])), len(segments_fillers))
segments_fillers_len, segments_fillers_remainder = divmod((width - self._total_len()), len(segments_fillers))
segments_fillers_contents = ' ' * segments_fillers_len
for segment in segments_fillers:
segment.contents = segments_fillers_contents
segment['contents'] = segments_fillers_contents
# Add remainder whitespace to the first filler segment
segments_fillers[0].contents += ' ' * segments_fillers_remainder
segments_fillers[0]['contents'] += ' ' * segments_fillers_remainder
# Do a final render now that we have handled the cropping and padding
rendered = render_segments(self.segments, render_raw=False)
return render_segments(self.segments)
return rendered['highlighted']
def _total_len(self):
'''Return total/rendered length of all segments.
class Segment:
ATTR_BOLD = 1
ATTR_ITALIC = 2
ATTR_UNDERLINE = 4
def __init__(self, contents=None, fg=False, bg=False, attr=False, side='l', draw_divider=True, priority=-1, filler=False):
'''Create a new Powerline segment.
This method uses the rendered_raw property of the segments and requires
that the segments have been rendered using the render() method first.
'''
self.contents = str(contents or '')
self.fg = fg
self.bg = bg
self.attr = attr
self.side = side
self.draw_divider = draw_divider
self.priority = priority
self.filler = filler
return len(''.join([segment['rendered_raw'] for segment in self.segments]))
if self.filler:
# Filler segments should never have any dividers
self.draw_divider = False
try:
if len(self.fg) != 2:
raise TypeError
except TypeError:
# Only the terminal color is defined, so we need to get the hex color
from lib.colors import cterm_to_hex
self.fg = [self.fg, cterm_to_hex(self.fg)]
def mksegment(contents=None, cterm_fg=False, cterm_bg=False, attr=False, hex_fg=False, hex_bg=False, side='l', draw_divider=True, priority=-1, filler=False):
'''Convenience wrapper for segment generation.
'''
try:
contents = unicode(contents or u'')
except UnicodeDecodeError:
contents = contents.decode('utf-8') or u''
try:
if len(self.bg) != 2:
raise TypeError
except TypeError:
# Only the terminal color is defined, so we need to get the hex color
from lib.colors import cterm_to_hex
self.bg = [self.bg, cterm_to_hex(self.bg)]
return {
'contents': contents,
'fg': (cterm_fg, hex_fg or cterm_to_hex.get(cterm_fg, 0xffffff)),
'bg': (cterm_bg, hex_bg or cterm_to_hex.get(cterm_bg, 0x000000)),
'attr': attr,
'side': side,
'draw_divider': False if filler else draw_divider,
'priority': priority,
'filler': filler,
}

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
from lib.core import Segment
from lib.core import Powerline
from lib.renderers import SegmentRenderer
@ -32,7 +32,7 @@ class TerminalSegmentRenderer(SegmentRenderer):
if attr is False:
ansi += [22]
else:
if attr & Segment.ATTR_BOLD:
if attr & Powerline.ATTR_BOLD:
ansi += [1]
return '[{0}m'.format(';'.join(str(attr) for attr in ansi))

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
from lib.core import Segment
from lib.core import Powerline
from lib.renderers import SegmentRenderer
@ -17,43 +17,44 @@ class VimSegmentRenderer(SegmentRenderer):
False, the argument is reset to the terminal defaults. If an argument
is a valid color or attribute, it's added to the vim highlight group.
'''
hl_group = {
'ctermfg': 'NONE',
'guifg': 'NONE',
'ctermbg': 'NONE',
'guibg': 'NONE',
'attr': ['NONE'],
}
# We don't need to explicitly reset attributes in vim, so skip those calls
if not attr and not bg and not fg:
return ''
if fg is not None and fg is not False:
hl_group['ctermfg'] = fg[0]
hl_group['guifg'] = fg[1]
if not (fg, bg, attr) in self.hl_groups:
hl_group = {
'ctermfg': 'NONE',
'guifg': 'NONE',
'ctermbg': 'NONE',
'guibg': 'NONE',
'attr': ['NONE'],
'name': '',
}
if bg is not None and bg is not False:
hl_group['ctermbg'] = bg[0]
hl_group['guibg'] = bg[1]
if fg is not None and fg is not False:
hl_group['ctermfg'] = fg[0]
hl_group['guifg'] = fg[1]
if attr is not None and attr is not False and attr != 0:
hl_group['attr'] = []
if attr & Segment.ATTR_BOLD:
hl_group['attr'].append('bold')
if attr & Segment.ATTR_ITALIC:
hl_group['attr'].append('italic')
if attr & Segment.ATTR_UNDERLINE:
hl_group['attr'].append('underline')
if bg is not None and bg is not False:
hl_group['ctermbg'] = bg[0]
hl_group['guibg'] = bg[1]
hl_group_name = 'Pl_{ctermfg}_{guifg}_{ctermbg}_{guibg}_{attr}'.format(
ctermfg=hl_group['ctermfg'],
guifg=hl_group['guifg'],
ctermbg=hl_group['ctermbg'],
guibg=hl_group['guibg'],
attr=''.join(attr[0] for attr in hl_group['attr']),
)
if attr:
hl_group['attr'] = []
if attr & Powerline.ATTR_BOLD:
hl_group['attr'].append('bold')
if attr & Powerline.ATTR_ITALIC:
hl_group['attr'].append('italic')
if attr & Powerline.ATTR_UNDERLINE:
hl_group['attr'].append('underline')
self.hl_groups[hl_group_name] = hl_group
hl_group['name'] = 'Pl_' + \
str(hl_group['ctermfg']) + '_' + \
str(hl_group['guifg']) + '_' + \
str(hl_group['ctermbg']) + '_' + \
str(hl_group['guibg']) + '_' + \
''.join(hl_group['attr'])
return '%#{0}#'.format(hl_group_name)
self.hl_groups[(fg, bg, attr)] = hl_group
return '%#' + self.hl_groups[(fg, bg, attr)]['name'] + '#'