Merge branch 'feature/extended-vim-example' into develop
This commit is contained in:
commit
3be7dc2a40
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
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.core import Powerline, Segment
|
||||||
from lib.renderers import TerminalSegmentRenderer
|
from lib.renderers import TerminalSegmentRenderer
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
import vim
|
import vim
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
|
|
||||||
from lib.core import Powerline, Segment
|
from lib.core import Powerline, mksegment
|
||||||
from lib.renderers import VimSegmentRenderer
|
from lib.renderers import VimSegmentRenderer
|
||||||
|
|
||||||
modes = {
|
modes = {
|
||||||
|
@ -28,6 +27,9 @@ modes = {
|
||||||
'!': 'SHELL',
|
'!': 'SHELL',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# We need to replace this private use glyph with a double-percent later
|
||||||
|
percent_placeholder = u''
|
||||||
|
|
||||||
if hasattr(vim, 'bindeval'):
|
if hasattr(vim, 'bindeval'):
|
||||||
# This branch is used to avoid invoking vim parser as much as possible
|
# 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),
|
'col': get_vim_func('col', rettype=int),
|
||||||
'expand': get_vim_func('expand'),
|
'expand': get_vim_func('expand'),
|
||||||
'tbcurtag': get_vim_func('tagbar#currenttag'),
|
'tbcurtag': get_vim_func('tagbar#currenttag'),
|
||||||
'sstlflag': get_vim_func('SyntasticStatuslineFlag'),
|
|
||||||
'hlexists': get_vim_func('hlexists', rettype=int),
|
'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']()]
|
mode = modes[vim_funcs['mode']()]
|
||||||
|
|
||||||
try:
|
if not current:
|
||||||
branch = vim_funcs['fghead'](5)
|
mode = None
|
||||||
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 = ''
|
|
||||||
|
|
||||||
powerline = Powerline([
|
powerline = Powerline([
|
||||||
Segment(mode, 22, 148, attr=Segment.ATTR_BOLD),
|
mksegment(mode, 22, 148, attr=Powerline.ATTR_BOLD),
|
||||||
Segment(vim.eval('&paste ? "PASTE" : ""'), 231, 166, attr=Segment.ATTR_BOLD),
|
mksegment(windata['paste'], 231, 166, attr=Powerline.ATTR_BOLD),
|
||||||
Segment(branch, 250, 240, priority=10),
|
mksegment(windata['branch'], 250, 240, priority=60),
|
||||||
Segment(readonly, 196, 240, draw_divider=False),
|
mksegment(windata['readonly'], 196, 240, draw_divider=False),
|
||||||
Segment(filepath, 250, 240, draw_divider=False, priority=5),
|
mksegment(windata['filepath'], 250, 240, draw_divider=False, priority=40),
|
||||||
Segment(filename, filename_color, 240, attr=Segment.ATTR_BOLD, draw_divider=not len(modified)),
|
mksegment(windata['filename'], windata['filename_color'], 240, attr=Powerline.ATTR_BOLD, draw_divider=not len(windata['modified'])),
|
||||||
Segment(modified, 220, 240, attr=Segment.ATTR_BOLD),
|
mksegment(windata['modified'], 220, 240, attr=Powerline.ATTR_BOLD),
|
||||||
Segment(currenttag, 246, 236, draw_divider=False, priority=100),
|
mksegment(windata['currenttag'], 246, 236, draw_divider=False, priority=100),
|
||||||
Segment(filler=True, fg=236, bg=236),
|
mksegment(filler=True, cterm_fg=236, cterm_bg=236),
|
||||||
Segment(syntastic, 214, 236, attr=Segment.ATTR_BOLD, draw_divider=False, priority=100),
|
mksegment(windata['fileformat'], 247, 236, side='r', priority=50),
|
||||||
Segment(filler=True, fg=236, bg=236),
|
mksegment(windata['fileencoding'], 247, 236, side='r', priority=50),
|
||||||
Segment(vim.eval('&ff'), 247, 236, side='r', priority=50),
|
mksegment(windata['filetype'], 247, 236, side='r', priority=50),
|
||||||
Segment(vim.eval('&fenc'), 247, 236, side='r', priority=50),
|
mksegment(windata['line_percent'], windata['line_percent_color'], 240, side='r', priority=30),
|
||||||
Segment(vim.eval('&ft'), 247, 236, side='r', priority=50),
|
mksegment(u'⭡ ', 239, 252, side='r'),
|
||||||
Segment(str(line_percent).rjust(3) + '%', line_percent_color, 240, side='r', priority=30),
|
mksegment(windata['linecurrent'], 235, 252, attr=Powerline.ATTR_BOLD, side='r', draw_divider=False),
|
||||||
Segment('⭡ ', 239, 252, side='r'),
|
mksegment(windata['colcurrent'], 244, 252, side='r', priority=30, draw_divider=False),
|
||||||
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),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
renderer = VimSegmentRenderer()
|
renderer = VimSegmentRenderer()
|
||||||
stl = powerline.render(renderer, winwidth)
|
stl = powerline.render(renderer, winwidth)
|
||||||
|
|
||||||
# Escape percent chars in the statusline, but only if they aren't part of any stl escape sequence
|
# Replace percent placeholders
|
||||||
stl = re.sub('(\w+)\%(?![-{()<=#*%])', '\\1%%', stl)
|
stl = stl.replace(percent_placeholder, '%%')
|
||||||
|
|
||||||
# Create highlighting groups
|
# Create highlighting groups
|
||||||
for group, hl in renderer.hl_groups.items():
|
for idx, hl in renderer.hl_groups.items():
|
||||||
if vim_funcs['hlexists'](group):
|
if vim_funcs['hlexists'](hl['name']):
|
||||||
# Only create hl group if it doesn't already exist
|
# Only create hl group if it doesn't already exist
|
||||||
continue
|
continue
|
||||||
|
|
||||||
vim.command('hi {group} ctermfg={ctermfg} guifg={guifg} guibg={guibg} ctermbg={ctermbg} cterm={attr} gui={attr}'.format(
|
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'],
|
ctermfg=hl['ctermfg'],
|
||||||
guifg='#{0:06x}'.format(hl['guifg']) if hl['guifg'] != 'NONE' else 'NONE',
|
guifg='#{0:06x}'.format(hl['guifg']) if hl['guifg'] != 'NONE' else 'NONE',
|
||||||
ctermbg=hl['ctermbg'],
|
ctermbg=hl['ctermbg'],
|
||||||
|
@ -176,6 +194,4 @@ def statusline():
|
||||||
|
|
||||||
return stl
|
return stl
|
||||||
|
|
||||||
statusline()
|
|
||||||
|
|
||||||
# vim: ft=python ts=4 sts=4 sw=4 noet
|
# 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
|
python from examples.vim.powerline import statusline
|
||||||
|
|
||||||
if exists('*pyeval')
|
if exists('*pyeval')
|
||||||
let s:pyeval=function('pyeval')
|
let s:pyeval = function('pyeval')
|
||||||
else
|
else
|
||||||
python import json
|
python import json
|
||||||
function! s:pyeval(e)
|
function! s:pyeval(e)
|
||||||
|
@ -14,8 +14,20 @@ else
|
||||||
endfunction
|
endfunction
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function! DynStl()
|
function! Powerline(winnr)
|
||||||
return s:pyeval('statusline()')
|
return s:pyeval('statusline('. a:winnr .')')
|
||||||
endfunction
|
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):
|
cterm_to_hex = {
|
||||||
'''Translate a cterm color index into the corresponding hex/RGB color.
|
16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,
|
||||||
'''
|
22: 0x005f00, 23: 0x005f5f, 24: 0x005f87, 25: 0x005faf, 26: 0x005fd7, 27: 0x005fff,
|
||||||
color_dict = {
|
28: 0x008700, 29: 0x00875f, 30: 0x008787, 31: 0x0087af, 32: 0x0087d7, 33: 0x0087ff,
|
||||||
16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,
|
34: 0x00af00, 35: 0x00af5f, 36: 0x00af87, 37: 0x00afaf, 38: 0x00afd7, 39: 0x00afff,
|
||||||
22: 0x005f00, 23: 0x005f5f, 24: 0x005f87, 25: 0x005faf, 26: 0x005fd7, 27: 0x005fff,
|
40: 0x00d700, 41: 0x00d75f, 42: 0x00d787, 43: 0x00d7af, 44: 0x00d7d7, 45: 0x00d7ff,
|
||||||
28: 0x008700, 29: 0x00875f, 30: 0x008787, 31: 0x0087af, 32: 0x0087d7, 33: 0x0087ff,
|
46: 0x00ff00, 47: 0x00ff5f, 48: 0x00ff87, 49: 0x00ffaf, 50: 0x00ffd7, 51: 0x00ffff,
|
||||||
34: 0x00af00, 35: 0x00af5f, 36: 0x00af87, 37: 0x00afaf, 38: 0x00afd7, 39: 0x00afff,
|
52: 0x5f0000, 53: 0x5f005f, 54: 0x5f0087, 55: 0x5f00af, 56: 0x5f00d7, 57: 0x5f00ff,
|
||||||
40: 0x00d700, 41: 0x00d75f, 42: 0x00d787, 43: 0x00d7af, 44: 0x00d7d7, 45: 0x00d7ff,
|
58: 0x5f5f00, 59: 0x5f5f5f, 60: 0x5f5f87, 61: 0x5f5faf, 62: 0x5f5fd7, 63: 0x5f5fff,
|
||||||
46: 0x00ff00, 47: 0x00ff5f, 48: 0x00ff87, 49: 0x00ffaf, 50: 0x00ffd7, 51: 0x00ffff,
|
64: 0x5f8700, 65: 0x5f875f, 66: 0x5f8787, 67: 0x5f87af, 68: 0x5f87d7, 69: 0x5f87ff,
|
||||||
52: 0x5f0000, 53: 0x5f005f, 54: 0x5f0087, 55: 0x5f00af, 56: 0x5f00d7, 57: 0x5f00ff,
|
70: 0x5faf00, 71: 0x5faf5f, 72: 0x5faf87, 73: 0x5fafaf, 74: 0x5fafd7, 75: 0x5fafff,
|
||||||
58: 0x5f5f00, 59: 0x5f5f5f, 60: 0x5f5f87, 61: 0x5f5faf, 62: 0x5f5fd7, 63: 0x5f5fff,
|
76: 0x5fd700, 77: 0x5fd75f, 78: 0x5fd787, 79: 0x5fd7af, 80: 0x5fd7d7, 81: 0x5fd7ff,
|
||||||
64: 0x5f8700, 65: 0x5f875f, 66: 0x5f8787, 67: 0x5f87af, 68: 0x5f87d7, 69: 0x5f87ff,
|
82: 0x5fff00, 83: 0x5fff5f, 84: 0x5fff87, 85: 0x5fffaf, 86: 0x5fffd7, 87: 0x5fffff,
|
||||||
70: 0x5faf00, 71: 0x5faf5f, 72: 0x5faf87, 73: 0x5fafaf, 74: 0x5fafd7, 75: 0x5fafff,
|
88: 0x870000, 89: 0x87005f, 90: 0x870087, 91: 0x8700af, 92: 0x8700d7, 93: 0x8700ff,
|
||||||
76: 0x5fd700, 77: 0x5fd75f, 78: 0x5fd787, 79: 0x5fd7af, 80: 0x5fd7d7, 81: 0x5fd7ff,
|
94: 0x875f00, 95: 0x875f5f, 96: 0x875f87, 97: 0x875faf, 98: 0x875fd7, 99: 0x875fff,
|
||||||
82: 0x5fff00, 83: 0x5fff5f, 84: 0x5fff87, 85: 0x5fffaf, 86: 0x5fffd7, 87: 0x5fffff,
|
100: 0x878700, 101: 0x87875f, 102: 0x878787, 103: 0x8787af, 104: 0x8787d7, 105: 0x8787ff,
|
||||||
88: 0x870000, 89: 0x87005f, 90: 0x870087, 91: 0x8700af, 92: 0x8700d7, 93: 0x8700ff,
|
106: 0x87af00, 107: 0x87af5f, 108: 0x87af87, 109: 0x87afaf, 110: 0x87afd7, 111: 0x87afff,
|
||||||
94: 0x875f00, 95: 0x875f5f, 96: 0x875f87, 97: 0x875faf, 98: 0x875fd7, 99: 0x875fff,
|
112: 0x87d700, 113: 0x87d75f, 114: 0x87d787, 115: 0x87d7af, 116: 0x87d7d7, 117: 0x87d7ff,
|
||||||
100: 0x878700, 101: 0x87875f, 102: 0x878787, 103: 0x8787af, 104: 0x8787d7, 105: 0x8787ff,
|
118: 0x87ff00, 119: 0x87ff5f, 120: 0x87ff87, 121: 0x87ffaf, 122: 0x87ffd7, 123: 0x87ffff,
|
||||||
106: 0x87af00, 107: 0x87af5f, 108: 0x87af87, 109: 0x87afaf, 110: 0x87afd7, 111: 0x87afff,
|
124: 0xaf0000, 125: 0xaf005f, 126: 0xaf0087, 127: 0xaf00af, 128: 0xaf00d7, 129: 0xaf00ff,
|
||||||
112: 0x87d700, 113: 0x87d75f, 114: 0x87d787, 115: 0x87d7af, 116: 0x87d7d7, 117: 0x87d7ff,
|
130: 0xaf5f00, 131: 0xaf5f5f, 132: 0xaf5f87, 133: 0xaf5faf, 134: 0xaf5fd7, 135: 0xaf5fff,
|
||||||
118: 0x87ff00, 119: 0x87ff5f, 120: 0x87ff87, 121: 0x87ffaf, 122: 0x87ffd7, 123: 0x87ffff,
|
136: 0xaf8700, 137: 0xaf875f, 138: 0xaf8787, 139: 0xaf87af, 140: 0xaf87d7, 141: 0xaf87ff,
|
||||||
124: 0xaf0000, 125: 0xaf005f, 126: 0xaf0087, 127: 0xaf00af, 128: 0xaf00d7, 129: 0xaf00ff,
|
142: 0xafaf00, 143: 0xafaf5f, 144: 0xafaf87, 145: 0xafafaf, 146: 0xafafd7, 147: 0xafafff,
|
||||||
130: 0xaf5f00, 131: 0xaf5f5f, 132: 0xaf5f87, 133: 0xaf5faf, 134: 0xaf5fd7, 135: 0xaf5fff,
|
148: 0xafd700, 149: 0xafd75f, 150: 0xafd787, 151: 0xafd7af, 152: 0xafd7d7, 153: 0xafd7ff,
|
||||||
136: 0xaf8700, 137: 0xaf875f, 138: 0xaf8787, 139: 0xaf87af, 140: 0xaf87d7, 141: 0xaf87ff,
|
154: 0xafff00, 155: 0xafff5f, 156: 0xafff87, 157: 0xafffaf, 158: 0xafffd7, 159: 0xafffff,
|
||||||
142: 0xafaf00, 143: 0xafaf5f, 144: 0xafaf87, 145: 0xafafaf, 146: 0xafafd7, 147: 0xafafff,
|
160: 0xd70000, 161: 0xd7005f, 162: 0xd70087, 163: 0xd700af, 164: 0xd700d7, 165: 0xd700ff,
|
||||||
148: 0xafd700, 149: 0xafd75f, 150: 0xafd787, 151: 0xafd7af, 152: 0xafd7d7, 153: 0xafd7ff,
|
166: 0xd75f00, 167: 0xd75f5f, 168: 0xd75f87, 169: 0xd75faf, 170: 0xd75fd7, 171: 0xd75fff,
|
||||||
154: 0xafff00, 155: 0xafff5f, 156: 0xafff87, 157: 0xafffaf, 158: 0xafffd7, 159: 0xafffff,
|
172: 0xd78700, 173: 0xd7875f, 174: 0xd78787, 175: 0xd787af, 176: 0xd787d7, 177: 0xd787ff,
|
||||||
160: 0xd70000, 161: 0xd7005f, 162: 0xd70087, 163: 0xd700af, 164: 0xd700d7, 165: 0xd700ff,
|
178: 0xd7af00, 179: 0xd7af5f, 180: 0xd7af87, 181: 0xd7afaf, 182: 0xd7afd7, 183: 0xd7afff,
|
||||||
166: 0xd75f00, 167: 0xd75f5f, 168: 0xd75f87, 169: 0xd75faf, 170: 0xd75fd7, 171: 0xd75fff,
|
184: 0xd7d700, 185: 0xd7d75f, 186: 0xd7d787, 187: 0xd7d7af, 188: 0xd7d7d7, 189: 0xd7d7ff,
|
||||||
172: 0xd78700, 173: 0xd7875f, 174: 0xd78787, 175: 0xd787af, 176: 0xd787d7, 177: 0xd787ff,
|
190: 0xd7ff00, 191: 0xd7ff5f, 192: 0xd7ff87, 193: 0xd7ffaf, 194: 0xd7ffd7, 195: 0xd7ffff,
|
||||||
178: 0xd7af00, 179: 0xd7af5f, 180: 0xd7af87, 181: 0xd7afaf, 182: 0xd7afd7, 183: 0xd7afff,
|
196: 0xff0000, 197: 0xff005f, 198: 0xff0087, 199: 0xff00af, 200: 0xff00d7, 201: 0xff00ff,
|
||||||
184: 0xd7d700, 185: 0xd7d75f, 186: 0xd7d787, 187: 0xd7d7af, 188: 0xd7d7d7, 189: 0xd7d7ff,
|
202: 0xff5f00, 203: 0xff5f5f, 204: 0xff5f87, 205: 0xff5faf, 206: 0xff5fd7, 207: 0xff5fff,
|
||||||
190: 0xd7ff00, 191: 0xd7ff5f, 192: 0xd7ff87, 193: 0xd7ffaf, 194: 0xd7ffd7, 195: 0xd7ffff,
|
208: 0xff8700, 209: 0xff875f, 210: 0xff8787, 211: 0xff87af, 212: 0xff87d7, 213: 0xff87ff,
|
||||||
196: 0xff0000, 197: 0xff005f, 198: 0xff0087, 199: 0xff00af, 200: 0xff00d7, 201: 0xff00ff,
|
214: 0xffaf00, 215: 0xffaf5f, 216: 0xffaf87, 217: 0xffafaf, 218: 0xffafd7, 219: 0xffafff,
|
||||||
202: 0xff5f00, 203: 0xff5f5f, 204: 0xff5f87, 205: 0xff5faf, 206: 0xff5fd7, 207: 0xff5fff,
|
220: 0xffd700, 221: 0xffd75f, 222: 0xffd787, 223: 0xffd7af, 224: 0xffd7d7, 225: 0xffd7ff,
|
||||||
208: 0xff8700, 209: 0xff875f, 210: 0xff8787, 211: 0xff87af, 212: 0xff87d7, 213: 0xff87ff,
|
226: 0xffff00, 227: 0xffff5f, 228: 0xffff87, 229: 0xffffaf, 230: 0xffffd7, 231: 0xffffff,
|
||||||
214: 0xffaf00, 215: 0xffaf5f, 216: 0xffaf87, 217: 0xffafaf, 218: 0xffafd7, 219: 0xffafff,
|
232: 0x080808, 233: 0x121212, 234: 0x1c1c1c, 235: 0x262626, 236: 0x303030, 237: 0x3a3a3a,
|
||||||
220: 0xffd700, 221: 0xffd75f, 222: 0xffd787, 223: 0xffd7af, 224: 0xffd7d7, 225: 0xffd7ff,
|
238: 0x444444, 239: 0x4e4e4e, 240: 0x585858, 241: 0x626262, 242: 0x6c6c6c, 243: 0x767676,
|
||||||
226: 0xffff00, 227: 0xffff5f, 228: 0xffff87, 229: 0xffffaf, 230: 0xffffd7, 231: 0xffffff,
|
244: 0x808080, 245: 0x8a8a8a, 246: 0x949494, 247: 0x9e9e9e, 248: 0xa8a8a8, 249: 0xb2b2b2,
|
||||||
232: 0x080808, 233: 0x121212, 234: 0x1c1c1c, 235: 0x262626, 236: 0x303030, 237: 0x3a3a3a,
|
250: 0xbcbcbc, 251: 0xc6c6c6, 252: 0xd0d0d0, 253: 0xdadada, 254: 0xe4e4e4, 255: 0xeeeeee,
|
||||||
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
|
|
||||||
|
|
180
lib/core.py
180
lib/core.py
|
@ -1,15 +1,21 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- 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 = {
|
dividers = {
|
||||||
'l': {
|
'l': {
|
||||||
'hard': '⮀',
|
'hard': u'⮀',
|
||||||
'soft': '⮁',
|
'soft': u'⮁',
|
||||||
},
|
},
|
||||||
'r': {
|
'r': {
|
||||||
'hard': '⮂',
|
'hard': u'⮂',
|
||||||
'soft': '⮃',
|
'soft': u'⮃',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +25,8 @@ class Powerline:
|
||||||
Segments that have empty contents and aren't filler segments are
|
Segments that have empty contents and aren't filler segments are
|
||||||
dropped from the segment array.
|
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):
|
def render(self, renderer, width=None):
|
||||||
'''Render all the segments with the specified renderer.
|
'''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
|
provided they will fill the remaining space until the desired width is
|
||||||
reached.
|
reached.
|
||||||
'''
|
'''
|
||||||
def render_segments(segments, render_raw=True, render_highlighted=True):
|
def render_segments(segments, render_highlighted=True):
|
||||||
'''Render a segment array.
|
'''Render a segment array.
|
||||||
|
|
||||||
By default this function renders both raw (un-highlighted segments
|
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
|
rendering is used for calculating the total width for dropping
|
||||||
low-priority segments.
|
low-priority segments.
|
||||||
'''
|
'''
|
||||||
rendered_raw = ''
|
rendered_highlighted = u''
|
||||||
rendered_highlighted = ''
|
segments_len = len(segments)
|
||||||
|
empty_segment = mksegment()
|
||||||
|
|
||||||
for idx, segment in enumerate(segments):
|
for idx, segment in enumerate(segments):
|
||||||
prev = segments[idx - 1] if idx > 0 else Segment()
|
prev = segments[idx - 1] if idx > 0 else empty_segment
|
||||||
next = segments[idx + 1] if idx < len(segments) - 1 else Segment()
|
next = segments[idx + 1] if idx < segments_len - 1 else empty_segment
|
||||||
|
|
||||||
compare_segment = next if segment.side == 'l' else prev
|
segment['rendered_raw'] = u''
|
||||||
divider_type = 'soft' if compare_segment.bg == segment.bg else 'hard'
|
compare = next if segment['side'] == 'l' else prev
|
||||||
divider = self.dividers[segment.side][divider_type]
|
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
|
# Filler segments shouldn't be padded
|
||||||
segment_format = '{contents}'
|
rendered_highlighted += segment['contents']
|
||||||
elif segment.draw_divider and (divider_type == 'hard' or segment.side == compare_segment.side):
|
elif segment['draw_divider'] and (divider_type == 'hard' or segment['side'] == compare['side']):
|
||||||
# Draw divider if specified, and if the next segment is on
|
# Draw divider if specified, and if the next segment is on
|
||||||
# the opposite side only draw the divider if it's a hard
|
# the opposite side only draw the divider if it's a hard
|
||||||
# divider
|
# divider
|
||||||
if segment.side == 'l':
|
if segment['side'] == 'l':
|
||||||
segment_format = '{segment_hl}{outer_padding}{contents} {divider_hl}{divider} '
|
segment['rendered_raw'] += outer_padding + segment['contents'] + ' ' + divider + ' '
|
||||||
|
rendered_highlighted += segment_hl + outer_padding + segment['contents'] + ' ' + divider_hl + divider + ' '
|
||||||
else:
|
else:
|
||||||
segment_format = ' {divider_hl}{divider}{segment_hl} {contents}{outer_padding}'
|
segment['rendered_raw'] += ' ' + divider + ' ' + segment['contents'] + outer_padding
|
||||||
elif segment.contents:
|
rendered_highlighted += ' ' + divider_hl + divider + segment_hl + ' ' + segment['contents'] + outer_padding
|
||||||
|
elif segment['contents']:
|
||||||
# Segments without divider
|
# 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:
|
else:
|
||||||
# Unknown segment type, skip it
|
# Unknown segment type, skip it
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if render_raw is True and segment.filler is False:
|
return rendered_highlighted
|
||||||
# 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 '',
|
|
||||||
)
|
|
||||||
|
|
||||||
if render_highlighted is True:
|
rendered_highlighted = render_segments(self.segments)
|
||||||
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)
|
|
||||||
|
|
||||||
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 rendered['highlighted']
|
return rendered_highlighted
|
||||||
|
|
||||||
# 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(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])
|
self.segments.remove(segments_priority[0])
|
||||||
segments_priority.pop(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
|
# 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:
|
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
|
segments_fillers_contents = ' ' * segments_fillers_len
|
||||||
for segment in segments_fillers:
|
for segment in segments_fillers:
|
||||||
segment.contents = segments_fillers_contents
|
segment['contents'] = segments_fillers_contents
|
||||||
# Add remainder whitespace to the first filler segment
|
# 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
|
return render_segments(self.segments)
|
||||||
rendered = render_segments(self.segments, render_raw=False)
|
|
||||||
|
|
||||||
return rendered['highlighted']
|
def _total_len(self):
|
||||||
|
'''Return total/rendered length of all segments.
|
||||||
|
|
||||||
|
This method uses the rendered_raw property of the segments and requires
|
||||||
class Segment:
|
that the segments have been rendered using the render() method first.
|
||||||
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.
|
|
||||||
'''
|
'''
|
||||||
self.contents = str(contents or '')
|
return len(''.join([segment['rendered_raw'] for segment in self.segments]))
|
||||||
self.fg = fg
|
|
||||||
self.bg = bg
|
|
||||||
self.attr = attr
|
|
||||||
self.side = side
|
|
||||||
self.draw_divider = draw_divider
|
|
||||||
self.priority = priority
|
|
||||||
self.filler = filler
|
|
||||||
|
|
||||||
if self.filler:
|
|
||||||
# Filler segments should never have any dividers
|
|
||||||
self.draw_divider = False
|
|
||||||
|
|
||||||
try:
|
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):
|
||||||
if len(self.fg) != 2:
|
'''Convenience wrapper for segment generation.
|
||||||
raise TypeError
|
'''
|
||||||
except TypeError:
|
try:
|
||||||
# Only the terminal color is defined, so we need to get the hex color
|
contents = unicode(contents or u'')
|
||||||
from lib.colors import cterm_to_hex
|
except UnicodeDecodeError:
|
||||||
self.fg = [self.fg, cterm_to_hex(self.fg)]
|
contents = contents.decode('utf-8') or u''
|
||||||
|
|
||||||
try:
|
return {
|
||||||
if len(self.bg) != 2:
|
'contents': contents,
|
||||||
raise TypeError
|
'fg': (cterm_fg, hex_fg or cterm_to_hex.get(cterm_fg, 0xffffff)),
|
||||||
except TypeError:
|
'bg': (cterm_bg, hex_bg or cterm_to_hex.get(cterm_bg, 0x000000)),
|
||||||
# Only the terminal color is defined, so we need to get the hex color
|
'attr': attr,
|
||||||
from lib.colors import cterm_to_hex
|
'side': side,
|
||||||
self.bg = [self.bg, cterm_to_hex(self.bg)]
|
'draw_divider': False if filler else draw_divider,
|
||||||
|
'priority': priority,
|
||||||
|
'filler': filler,
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from lib.core import Segment
|
from lib.core import Powerline
|
||||||
from lib.renderers import SegmentRenderer
|
from lib.renderers import SegmentRenderer
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class TerminalSegmentRenderer(SegmentRenderer):
|
||||||
if attr is False:
|
if attr is False:
|
||||||
ansi += [22]
|
ansi += [22]
|
||||||
else:
|
else:
|
||||||
if attr & Segment.ATTR_BOLD:
|
if attr & Powerline.ATTR_BOLD:
|
||||||
ansi += [1]
|
ansi += [1]
|
||||||
|
|
||||||
return '[{0}m'.format(';'.join(str(attr) for attr in ansi))
|
return '[{0}m'.format(';'.join(str(attr) for attr in ansi))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from lib.core import Segment
|
from lib.core import Powerline
|
||||||
from lib.renderers import SegmentRenderer
|
from lib.renderers import SegmentRenderer
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,43 +17,44 @@ class VimSegmentRenderer(SegmentRenderer):
|
||||||
False, the argument is reset to the terminal defaults. If an argument
|
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.
|
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
|
# We don't need to explicitly reset attributes in vim, so skip those calls
|
||||||
if not attr and not bg and not fg:
|
if not attr and not bg and not fg:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
if fg is not None and fg is not False:
|
if not (fg, bg, attr) in self.hl_groups:
|
||||||
hl_group['ctermfg'] = fg[0]
|
hl_group = {
|
||||||
hl_group['guifg'] = fg[1]
|
'ctermfg': 'NONE',
|
||||||
|
'guifg': 'NONE',
|
||||||
|
'ctermbg': 'NONE',
|
||||||
|
'guibg': 'NONE',
|
||||||
|
'attr': ['NONE'],
|
||||||
|
'name': '',
|
||||||
|
}
|
||||||
|
|
||||||
if bg is not None and bg is not False:
|
if fg is not None and fg is not False:
|
||||||
hl_group['ctermbg'] = bg[0]
|
hl_group['ctermfg'] = fg[0]
|
||||||
hl_group['guibg'] = bg[1]
|
hl_group['guifg'] = fg[1]
|
||||||
|
|
||||||
if attr is not None and attr is not False and attr != 0:
|
if bg is not None and bg is not False:
|
||||||
hl_group['attr'] = []
|
hl_group['ctermbg'] = bg[0]
|
||||||
if attr & Segment.ATTR_BOLD:
|
hl_group['guibg'] = bg[1]
|
||||||
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')
|
|
||||||
|
|
||||||
hl_group_name = 'Pl_{ctermfg}_{guifg}_{ctermbg}_{guibg}_{attr}'.format(
|
if attr:
|
||||||
ctermfg=hl_group['ctermfg'],
|
hl_group['attr'] = []
|
||||||
guifg=hl_group['guifg'],
|
if attr & Powerline.ATTR_BOLD:
|
||||||
ctermbg=hl_group['ctermbg'],
|
hl_group['attr'].append('bold')
|
||||||
guibg=hl_group['guibg'],
|
if attr & Powerline.ATTR_ITALIC:
|
||||||
attr=''.join(attr[0] for attr in hl_group['attr']),
|
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