mirror of
https://github.com/powerline/powerline.git
synced 2025-07-27 07:44:36 +02:00
Merge pull request #957 from ZyX-I/better-visual-range
Improve visual_range segment
This commit is contained in:
commit
b1a2b44db1
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "visual_range",
|
"name": "visual_range",
|
||||||
"exclude_modes": ["nc"],
|
"include_modes": ["v", "V", "^V", "s", "S", "^S"],
|
||||||
"priority": 10
|
"priority": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -74,7 +74,10 @@ def window_cached(func):
|
|||||||
if segment_info['mode'] == 'nc':
|
if segment_info['mode'] == 'nc':
|
||||||
return cache.get(window_id)
|
return cache.get(window_id)
|
||||||
else:
|
else:
|
||||||
r = func(**kwargs)
|
if getattr(func, 'powerline_requires_segment_info', False):
|
||||||
|
r = func(segment_info=segment_info, **kwargs)
|
||||||
|
else:
|
||||||
|
r = func(**kwargs)
|
||||||
cache[window_id] = r
|
cache[window_id] = r
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@ -99,29 +102,57 @@ def mode(pl, segment_info, override=None):
|
|||||||
return vim_modes[mode]
|
return vim_modes[mode]
|
||||||
|
|
||||||
|
|
||||||
|
@window_cached
|
||||||
@requires_segment_info
|
@requires_segment_info
|
||||||
def visual_range(pl, segment_info):
|
def visual_range(pl, segment_info, CTRL_V_text='{rows} × {vcols}', v_text_oneline='C:{vcols}', v_text_multiline='L:{rows}', V_text='L:{rows}'):
|
||||||
'''Return the current visual selection range.
|
'''Return the current visual selection range.
|
||||||
|
|
||||||
Returns a value similar to `showcmd`.
|
:param str CTRL_V_text:
|
||||||
|
Text to display when in block visual or select mode.
|
||||||
|
:param str v_text_oneline:
|
||||||
|
Text to display when in charaterwise visual or select mode, assuming
|
||||||
|
selection occupies only one line.
|
||||||
|
:param str v_text_multiline:
|
||||||
|
Text to display when in charaterwise visual or select mode, assuming
|
||||||
|
selection occupies more then one line.
|
||||||
|
:param str V_text:
|
||||||
|
Text to display when in linewise visual or select mode.
|
||||||
|
|
||||||
|
All texts are format strings which are passed the following parameters:
|
||||||
|
|
||||||
|
========= =============================================================
|
||||||
|
Parameter Description
|
||||||
|
========= =============================================================
|
||||||
|
sline Line number of the first line of the selection
|
||||||
|
eline Line number of the last line of the selection
|
||||||
|
scol Column number of the first character of the selection
|
||||||
|
ecol Column number of the last character of the selection
|
||||||
|
svcol Virtual column number of the first character of the selection
|
||||||
|
secol Virtual column number of the last character of the selection
|
||||||
|
rows Number of lines in the selection
|
||||||
|
cols Number of columns in the selection
|
||||||
|
vcols Number of virtual columns in the selection
|
||||||
|
========= =============================================================
|
||||||
'''
|
'''
|
||||||
if segment_info['mode'] not in ('v', 'V', '^V'):
|
sline, scol, soff = [int(v) for v in vim_funcs['getpos']("v")[1:]]
|
||||||
return None
|
eline, ecol, eoff = [int(v) for v in vim_funcs['getpos'](".")[1:]]
|
||||||
pos_start = vim_funcs['getpos']('v')
|
svcol = vim_funcs['virtcol']([sline, scol, soff])
|
||||||
pos_end = vim_funcs['getpos']('.')
|
evcol = vim_funcs['virtcol']([eline, ecol, eoff])
|
||||||
# Workaround for vim's "excellent" handling of multibyte characters and display widths
|
rows = abs(eline - sline) + 1
|
||||||
pos_start[2] = vim_funcs['virtcol']([pos_start[1], pos_start[2], pos_start[3]])
|
cols = abs(ecol - scol) + 1
|
||||||
pos_end[2] = vim_funcs['virtcol']([pos_end[1], pos_end[2], pos_end[3]])
|
vcols = abs(evcol - svcol) + 1
|
||||||
visual_start = (int(pos_start[1]), int(pos_start[2]))
|
return {
|
||||||
visual_end = (int(pos_end[1]), int(pos_end[2]))
|
'^': CTRL_V_text,
|
||||||
diff_rows = abs(visual_end[0] - visual_start[0]) + 1
|
's': v_text_oneline if rows == 1 else v_text_multiline,
|
||||||
diff_cols = abs(visual_end[1] - visual_start[1]) + 1
|
'S': V_text,
|
||||||
if segment_info['mode'] == '^V':
|
'v': v_text_oneline if rows == 1 else v_text_multiline,
|
||||||
return '{0} × {1}'.format(diff_rows, diff_cols)
|
'V': V_text,
|
||||||
elif segment_info['mode'] == 'V' or diff_rows > 1:
|
}.get(segment_info['mode'][0], '').format(
|
||||||
return '{0} rows'.format(diff_rows)
|
sline=sline, eline=eline,
|
||||||
else:
|
scol=scol, ecol=ecol,
|
||||||
return '{0} cols'.format(diff_cols)
|
svcol=svcol, evcol=evcol,
|
||||||
|
rows=rows, cols=cols, vcols=vcols,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@requires_segment_info
|
@requires_segment_info
|
||||||
|
@ -589,8 +589,50 @@ class TestVim(TestCase):
|
|||||||
self.assertEqual(vim.mode(pl=pl, segment_info=segment_info, override={'^V': 'VBLK'}), 'VBLK')
|
self.assertEqual(vim.mode(pl=pl, segment_info=segment_info, override={'^V': 'VBLK'}), 'VBLK')
|
||||||
|
|
||||||
def test_visual_range(self):
|
def test_visual_range(self):
|
||||||
# TODO
|
pl = Pl()
|
||||||
pass
|
vr = partial(vim.visual_range, pl=pl)
|
||||||
|
vim_module.current.window.cursor = [0, 0]
|
||||||
|
try:
|
||||||
|
with vim_module._with('mode', 'i') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '')
|
||||||
|
with vim_module._with('mode', '^V') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '1 × 1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '5 × 5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '5 × 4')
|
||||||
|
with vim_module._with('mode', '^S') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '1 × 1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '5 × 5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), '5 × 4')
|
||||||
|
with vim_module._with('mode', 'V') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('mode', 'S') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('mode', 'v') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'C:1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('mode', 's') as segment_info:
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'C:1')
|
||||||
|
with vim_module._with('vpos', line=5, col=5, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
with vim_module._with('vpos', line=5, col=4, off=0):
|
||||||
|
self.assertEqual(vr(segment_info=segment_info), 'L:5')
|
||||||
|
finally:
|
||||||
|
vim_module._close(1)
|
||||||
|
|
||||||
def test_modified_indicator(self):
|
def test_modified_indicator(self):
|
||||||
pl = Pl()
|
pl = Pl()
|
||||||
|
30
tests/vim.py
30
tests/vim.py
@ -342,15 +342,22 @@ def _emul_setwinvar(winnr, varname, value):
|
|||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_virtcol(expr):
|
def _emul_virtcol(expr):
|
||||||
if expr == '.' or isinstance(expr, list):
|
if expr == '.':
|
||||||
return current.window.cursor[1] + 1
|
return current.window.cursor[1] + 1
|
||||||
|
if isinstance(expr, list) and len(expr) == 3:
|
||||||
|
return expr[-2] + expr[-1]
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
_v_pos = None
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_getpos(expr):
|
def _emul_getpos(expr):
|
||||||
if expr == '.' or expr == 'v':
|
if expr == '.':
|
||||||
return [0, current.window.cursor[0] + 1, current.window.cursor[1] + 1, 0]
|
return [0, current.window.cursor[0] + 1, current.window.cursor[1] + 1, 0]
|
||||||
|
if expr == 'v':
|
||||||
|
return _v_pos or [0, current.window.cursor[0] + 1, current.window.cursor[1] + 1, 0]
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@ -848,6 +855,23 @@ class _WithNewTabPage(object):
|
|||||||
self.tab._close()
|
self.tab._close()
|
||||||
|
|
||||||
|
|
||||||
|
class _WithGlobal(object):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.empty = object()
|
||||||
|
self.old = dict(((key, globals().get(key, self.empty)) for key in self.kwargs))
|
||||||
|
globals().update(self.kwargs)
|
||||||
|
|
||||||
|
def __exit__(self, *args):
|
||||||
|
for k, v in self.old.items():
|
||||||
|
if v is self.empty:
|
||||||
|
globals().pop(k, None)
|
||||||
|
else:
|
||||||
|
globals()[k] = v
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _with(key, *args, **kwargs):
|
def _with(key, *args, **kwargs):
|
||||||
if key == 'buffer':
|
if key == 'buffer':
|
||||||
@ -870,6 +894,8 @@ def _with(key, *args, **kwargs):
|
|||||||
return _WithSplit()
|
return _WithSplit()
|
||||||
elif key == 'tabpage':
|
elif key == 'tabpage':
|
||||||
return _WithNewTabPage(*args, **kwargs)
|
return _WithNewTabPage(*args, **kwargs)
|
||||||
|
elif key == 'vpos':
|
||||||
|
return _WithGlobal(_v_pos=[0, kwargs['line'], kwargs['col'], kwargs['off']])
|
||||||
|
|
||||||
|
|
||||||
class error(Exception):
|
class error(Exception):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user