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",
|
||||
"exclude_modes": ["nc"],
|
||||
"include_modes": ["v", "V", "^V", "s", "S", "^S"],
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
|
|
|
@ -74,7 +74,10 @@ def window_cached(func):
|
|||
if segment_info['mode'] == 'nc':
|
||||
return cache.get(window_id)
|
||||
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
|
||||
return r
|
||||
|
||||
|
@ -99,29 +102,57 @@ def mode(pl, segment_info, override=None):
|
|||
return vim_modes[mode]
|
||||
|
||||
|
||||
@window_cached
|
||||
@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.
|
||||
|
||||
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'):
|
||||
return None
|
||||
pos_start = vim_funcs['getpos']('v')
|
||||
pos_end = vim_funcs['getpos']('.')
|
||||
# Workaround for vim's "excellent" handling of multibyte characters and display widths
|
||||
pos_start[2] = vim_funcs['virtcol']([pos_start[1], pos_start[2], pos_start[3]])
|
||||
pos_end[2] = vim_funcs['virtcol']([pos_end[1], pos_end[2], pos_end[3]])
|
||||
visual_start = (int(pos_start[1]), int(pos_start[2]))
|
||||
visual_end = (int(pos_end[1]), int(pos_end[2]))
|
||||
diff_rows = abs(visual_end[0] - visual_start[0]) + 1
|
||||
diff_cols = abs(visual_end[1] - visual_start[1]) + 1
|
||||
if segment_info['mode'] == '^V':
|
||||
return '{0} × {1}'.format(diff_rows, diff_cols)
|
||||
elif segment_info['mode'] == 'V' or diff_rows > 1:
|
||||
return '{0} rows'.format(diff_rows)
|
||||
else:
|
||||
return '{0} cols'.format(diff_cols)
|
||||
sline, scol, soff = [int(v) for v in vim_funcs['getpos']("v")[1:]]
|
||||
eline, ecol, eoff = [int(v) for v in vim_funcs['getpos'](".")[1:]]
|
||||
svcol = vim_funcs['virtcol']([sline, scol, soff])
|
||||
evcol = vim_funcs['virtcol']([eline, ecol, eoff])
|
||||
rows = abs(eline - sline) + 1
|
||||
cols = abs(ecol - scol) + 1
|
||||
vcols = abs(evcol - svcol) + 1
|
||||
return {
|
||||
'^': CTRL_V_text,
|
||||
's': v_text_oneline if rows == 1 else v_text_multiline,
|
||||
'S': V_text,
|
||||
'v': v_text_oneline if rows == 1 else v_text_multiline,
|
||||
'V': V_text,
|
||||
}.get(segment_info['mode'][0], '').format(
|
||||
sline=sline, eline=eline,
|
||||
scol=scol, ecol=ecol,
|
||||
svcol=svcol, evcol=evcol,
|
||||
rows=rows, cols=cols, vcols=vcols,
|
||||
)
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
|
|
|
@ -589,8 +589,50 @@ class TestVim(TestCase):
|
|||
self.assertEqual(vim.mode(pl=pl, segment_info=segment_info, override={'^V': 'VBLK'}), 'VBLK')
|
||||
|
||||
def test_visual_range(self):
|
||||
# TODO
|
||||
pass
|
||||
pl = Pl()
|
||||
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):
|
||||
pl = Pl()
|
||||
|
|
30
tests/vim.py
30
tests/vim.py
|
@ -342,15 +342,22 @@ def _emul_setwinvar(winnr, varname, value):
|
|||
|
||||
@_vim
|
||||
def _emul_virtcol(expr):
|
||||
if expr == '.' or isinstance(expr, list):
|
||||
if expr == '.':
|
||||
return current.window.cursor[1] + 1
|
||||
if isinstance(expr, list) and len(expr) == 3:
|
||||
return expr[-2] + expr[-1]
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
_v_pos = None
|
||||
|
||||
|
||||
@_vim
|
||||
def _emul_getpos(expr):
|
||||
if expr == '.' or expr == 'v':
|
||||
if expr == '.':
|
||||
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
|
||||
|
||||
|
||||
|
@ -848,6 +855,23 @@ class _WithNewTabPage(object):
|
|||
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
|
||||
def _with(key, *args, **kwargs):
|
||||
if key == 'buffer':
|
||||
|
@ -870,6 +894,8 @@ def _with(key, *args, **kwargs):
|
|||
return _WithSplit()
|
||||
elif key == 'tabpage':
|
||||
return _WithNewTabPage(*args, **kwargs)
|
||||
elif key == 'vpos':
|
||||
return _WithGlobal(_v_pos=[0, kwargs['line'], kwargs['col'], kwargs['off']])
|
||||
|
||||
|
||||
class error(Exception):
|
||||
|
|
Loading…
Reference in New Issue