Revert zero counts
This initially seemed like a nice feature, but it means 0 can't be bound as a separate key anymore, and 0<Esc> gives weird error messages... Reverts #1953. Fixes #2032.
This commit is contained in:
parent
1507cfcae7
commit
552e0551af
@ -837,8 +837,7 @@ If neither count nor index are given, it behaves like tab-next. If both are give
|
|||||||
|
|
||||||
|
|
||||||
==== count
|
==== count
|
||||||
The tab index to focus, starting with 1. The special value 0 focuses the rightmost tab.
|
The tab index to focus, starting with 1.
|
||||||
|
|
||||||
|
|
||||||
[[tab-move]]
|
[[tab-move]]
|
||||||
=== tab-move
|
=== tab-move
|
||||||
|
@ -959,7 +959,7 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('index', choices=['last'])
|
@cmdutils.argument('index', choices=['last'])
|
||||||
@cmdutils.argument('count', count=True, zero_count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def tab_focus(self, index: typing.Union[str, int]=None, count=None):
|
def tab_focus(self, index: typing.Union[str, int]=None, count=None):
|
||||||
"""Select the tab given as argument/[count].
|
"""Select the tab given as argument/[count].
|
||||||
|
|
||||||
@ -972,7 +972,6 @@ class CommandDispatcher:
|
|||||||
Negative indices count from the end, such that -1 is the
|
Negative indices count from the end, such that -1 is the
|
||||||
last tab.
|
last tab.
|
||||||
count: The tab index to focus, starting with 1.
|
count: The tab index to focus, starting with 1.
|
||||||
The special value 0 focuses the rightmost tab.
|
|
||||||
"""
|
"""
|
||||||
if index == 'last':
|
if index == 'last':
|
||||||
self._tab_focus_last()
|
self._tab_focus_last()
|
||||||
@ -982,9 +981,8 @@ class CommandDispatcher:
|
|||||||
if index is None:
|
if index is None:
|
||||||
self.tab_next()
|
self.tab_next()
|
||||||
return
|
return
|
||||||
elif index == 0:
|
|
||||||
index = self._count()
|
if index < 0:
|
||||||
elif index < 0:
|
|
||||||
index = self._count() + index + 1
|
index = self._count() + index + 1
|
||||||
|
|
||||||
if 1 <= index <= self._count():
|
if 1 <= index <= self._count():
|
||||||
|
@ -34,14 +34,11 @@ class ArgInfo:
|
|||||||
"""Information about an argument."""
|
"""Information about an argument."""
|
||||||
|
|
||||||
def __init__(self, win_id=False, count=False, hide=False, metavar=None,
|
def __init__(self, win_id=False, count=False, hide=False, metavar=None,
|
||||||
zero_count=False, flag=None, completion=None, choices=None):
|
flag=None, completion=None, choices=None):
|
||||||
if win_id and count:
|
if win_id and count:
|
||||||
raise TypeError("Argument marked as both count/win_id!")
|
raise TypeError("Argument marked as both count/win_id!")
|
||||||
if zero_count and not count:
|
|
||||||
raise TypeError("zero_count argument cannot exist without count!")
|
|
||||||
self.win_id = win_id
|
self.win_id = win_id
|
||||||
self.count = count
|
self.count = count
|
||||||
self.zero_count = zero_count
|
|
||||||
self.flag = flag
|
self.flag = flag
|
||||||
self.hide = hide
|
self.hide = hide
|
||||||
self.metavar = metavar
|
self.metavar = metavar
|
||||||
@ -51,7 +48,6 @@ class ArgInfo:
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (self.win_id == other.win_id and
|
return (self.win_id == other.win_id and
|
||||||
self.count == other.count and
|
self.count == other.count and
|
||||||
self.zero_count == other.zero_count and
|
|
||||||
self.flag == other.flag and
|
self.flag == other.flag and
|
||||||
self.hide == other.hide and
|
self.hide == other.hide and
|
||||||
self.metavar == other.metavar and
|
self.metavar == other.metavar and
|
||||||
@ -61,7 +57,6 @@ class ArgInfo:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return utils.get_repr(self, win_id=self.win_id, count=self.count,
|
return utils.get_repr(self, win_id=self.win_id, count=self.count,
|
||||||
flag=self.flag, hide=self.hide,
|
flag=self.flag, hide=self.hide,
|
||||||
zero_count=self.zero_count,
|
|
||||||
metavar=self.metavar, completion=self.completion,
|
metavar=self.metavar, completion=self.completion,
|
||||||
choices=self.choices, constructor=True)
|
choices=self.choices, constructor=True)
|
||||||
|
|
||||||
@ -142,7 +137,6 @@ class Command:
|
|||||||
self.opt_args = collections.OrderedDict()
|
self.opt_args = collections.OrderedDict()
|
||||||
self.namespace = None
|
self.namespace = None
|
||||||
self._count = None
|
self._count = None
|
||||||
self._zero_count = None
|
|
||||||
self.pos_args = []
|
self.pos_args = []
|
||||||
self.desc = None
|
self.desc = None
|
||||||
self.flags_with_args = []
|
self.flags_with_args = []
|
||||||
@ -154,7 +148,7 @@ class Command:
|
|||||||
|
|
||||||
self._inspect_func()
|
self._inspect_func()
|
||||||
|
|
||||||
def _check_prerequisites(self, win_id, count):
|
def _check_prerequisites(self, win_id):
|
||||||
"""Check if the command is permitted to run currently.
|
"""Check if the command is permitted to run currently.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -170,11 +164,6 @@ class Command:
|
|||||||
"{}: Only available with {} "
|
"{}: Only available with {} "
|
||||||
"backend.".format(self.name, self.backend.name))
|
"backend.".format(self.name, self.backend.name))
|
||||||
|
|
||||||
if count == 0 and not self._zero_count:
|
|
||||||
raise cmdexc.PrerequisitesError(
|
|
||||||
"{}: A zero count is not allowed for this command!"
|
|
||||||
.format(self.name))
|
|
||||||
|
|
||||||
if self.deprecated:
|
if self.deprecated:
|
||||||
message.warning('{} is deprecated - {}'.format(self.name,
|
message.warning('{} is deprecated - {}'.format(self.name,
|
||||||
self.deprecated))
|
self.deprecated))
|
||||||
@ -246,9 +235,6 @@ class Command:
|
|||||||
assert param.kind != inspect.Parameter.POSITIONAL_ONLY
|
assert param.kind != inspect.Parameter.POSITIONAL_ONLY
|
||||||
if param.name == 'self':
|
if param.name == 'self':
|
||||||
continue
|
continue
|
||||||
arg_info = self.get_arg_info(param)
|
|
||||||
if arg_info.count:
|
|
||||||
self._zero_count = arg_info.zero_count
|
|
||||||
if self._inspect_special_param(param):
|
if self._inspect_special_param(param):
|
||||||
continue
|
continue
|
||||||
if (param.kind == inspect.Parameter.KEYWORD_ONLY and
|
if (param.kind == inspect.Parameter.KEYWORD_ONLY and
|
||||||
@ -532,7 +518,7 @@ class Command:
|
|||||||
e.status, e))
|
e.status, e))
|
||||||
return
|
return
|
||||||
self._count = count
|
self._count = count
|
||||||
self._check_prerequisites(win_id, count)
|
self._check_prerequisites(win_id)
|
||||||
posargs, kwargs = self._get_call_args(win_id)
|
posargs, kwargs = self._get_call_args(win_id)
|
||||||
log.commands.debug('Calling {}'.format(
|
log.commands.debug('Calling {}'.format(
|
||||||
debug_utils.format_call(self.handler, posargs, kwargs)))
|
debug_utils.format_call(self.handler, posargs, kwargs)))
|
||||||
|
@ -147,6 +147,9 @@ class BaseKeyParser(QObject):
|
|||||||
(countstr, cmd_input) = re.match(r'^(\d*)(.*)',
|
(countstr, cmd_input) = re.match(r'^(\d*)(.*)',
|
||||||
self._keystring).groups()
|
self._keystring).groups()
|
||||||
count = int(countstr) if countstr else None
|
count = int(countstr) if countstr else None
|
||||||
|
if count == 0 and not cmd_input:
|
||||||
|
cmd_input = self._keystring
|
||||||
|
count = None
|
||||||
else:
|
else:
|
||||||
cmd_input = self._keystring
|
cmd_input = self._keystring
|
||||||
count = None
|
count = None
|
||||||
|
@ -529,10 +529,6 @@ Feature: Various utility commands.
|
|||||||
And I set general -> private-browsing to false
|
And I set general -> private-browsing to false
|
||||||
Then the page should contain the plaintext "Local storage status: not working"
|
Then the page should contain the plaintext "Local storage status: not working"
|
||||||
|
|
||||||
Scenario: Using 0 as count
|
|
||||||
When I run :scroll down with count 0
|
|
||||||
Then the error "scroll: A zero count is not allowed for this command!" should be shown
|
|
||||||
|
|
||||||
@no_xvfb
|
@no_xvfb
|
||||||
Scenario: :window-only
|
Scenario: :window-only
|
||||||
Given I run :tab-only
|
Given I run :tab-only
|
||||||
|
@ -255,6 +255,7 @@ Feature: Tab management
|
|||||||
- data/numbers/2.txt (active)
|
- data/numbers/2.txt (active)
|
||||||
- data/numbers/3.txt
|
- data/numbers/3.txt
|
||||||
|
|
||||||
|
Scenario: :tab-focus with invalid negative index
|
||||||
Scenario: :tab-focus with count 0
|
Scenario: :tab-focus with count 0
|
||||||
When I open data/numbers/1.txt
|
When I open data/numbers/1.txt
|
||||||
And I open data/numbers/2.txt in a new tab
|
And I open data/numbers/2.txt in a new tab
|
||||||
@ -266,7 +267,6 @@ Feature: Tab management
|
|||||||
- data/numbers/2.txt
|
- data/numbers/2.txt
|
||||||
- data/numbers/3.txt (active)
|
- data/numbers/3.txt (active)
|
||||||
|
|
||||||
Scenario: :tab-focus with invalid negative index
|
|
||||||
When I open data/numbers/1.txt
|
When I open data/numbers/1.txt
|
||||||
And I open data/numbers/2.txt in a new tab
|
And I open data/numbers/2.txt in a new tab
|
||||||
And I open data/numbers/3.txt in a new tab
|
And I open data/numbers/3.txt in a new tab
|
||||||
|
@ -423,16 +423,6 @@ class TestArgument:
|
|||||||
|
|
||||||
assert str(excinfo.value) == "Argument marked as both count/win_id!"
|
assert str(excinfo.value) == "Argument marked as both count/win_id!"
|
||||||
|
|
||||||
def test_count_and_zero_count_arg(self):
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
|
||||||
@cmdutils.argument('arg', count=False, zero_count=True)
|
|
||||||
def fun(arg=0):
|
|
||||||
"""Blah."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
expected = "zero_count argument cannot exist without count!"
|
|
||||||
assert str(excinfo.value) == expected
|
|
||||||
|
|
||||||
def test_no_docstring(self, caplog):
|
def test_no_docstring(self, caplog):
|
||||||
with caplog.at_level(logging.WARNING):
|
with caplog.at_level(logging.WARNING):
|
||||||
@cmdutils.register()
|
@cmdutils.register()
|
||||||
|
@ -245,6 +245,12 @@ class TestKeyChain:
|
|||||||
'ba', keyparser.Type.chain, None)
|
'ba', keyparser.Type.chain, None)
|
||||||
assert keyparser._keystring == ''
|
assert keyparser._keystring == ''
|
||||||
|
|
||||||
|
def test_0_press(self, handle_text, keyparser):
|
||||||
|
handle_text((Qt.Key_0, '0'))
|
||||||
|
keyparser.execute.assert_called_once_with(
|
||||||
|
'0', keyparser.Type.chain, None)
|
||||||
|
assert keyparser._keystring == ''
|
||||||
|
|
||||||
def test_ambiguous_keychain(self, qapp, handle_text, config_stub,
|
def test_ambiguous_keychain(self, qapp, handle_text, config_stub,
|
||||||
keyparser):
|
keyparser):
|
||||||
config_stub.data = CONFIG
|
config_stub.data = CONFIG
|
||||||
@ -308,8 +314,9 @@ class TestCount:
|
|||||||
|
|
||||||
def test_count_0(self, handle_text, keyparser):
|
def test_count_0(self, handle_text, keyparser):
|
||||||
handle_text((Qt.Key_0, '0'), (Qt.Key_B, 'b'), (Qt.Key_A, 'a'))
|
handle_text((Qt.Key_0, '0'), (Qt.Key_B, 'b'), (Qt.Key_A, 'a'))
|
||||||
keyparser.execute.assert_called_once_with(
|
calls = [mock.call('0', keyparser.Type.chain, None),
|
||||||
'ba', keyparser.Type.chain, 0)
|
mock.call('ba', keyparser.Type.chain, None)]
|
||||||
|
keyparser.execute.assert_has_calls(calls)
|
||||||
assert keyparser._keystring == ''
|
assert keyparser._keystring == ''
|
||||||
|
|
||||||
def test_count_42(self, handle_text, keyparser):
|
def test_count_42(self, handle_text, keyparser):
|
||||||
|
Loading…
Reference in New Issue
Block a user