Merge branch 'feature/extended-vim-example' into develop
This commit is contained in:
commit
3be7dc2a40
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
180
lib/core.py
180
lib/core.py
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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'] + '#'
|
||||
|
|
Loading…
Reference in New Issue