Add modes=[]/not_modes=[] to cmdutils.register

This commit is contained in:
Florian Bruhin 2014-04-25 10:10:58 +02:00
parent 2c34a016db
commit 7787a67c45
8 changed files with 50 additions and 16 deletions

2
TODO
View File

@ -79,8 +79,6 @@ catch import errors for PyQt and QtWebKit
Allow binding to empty values for keys to override defaults Allow binding to empty values for keys to override defaults
How do we handle empty values in input bar? How do we handle empty values in input bar?
Human-readable error messages for unknown settings / wrong interpolations / ... Human-readable error messages for unknown settings / wrong interpolations / ...
- Add mode=[]/no_mode=[] to cmdutils.register so we can avoid executing
commands in the wrong mode
- Add more element-selection-detection code (with options?) based on: - Add more element-selection-detection code (with options?) based on:
-> javascript: http://stackoverflow.com/a/2848120/2085149 -> javascript: http://stackoverflow.com/a/2848120/2085149
-> microFocusChanged and check active element via: -> microFocusChanged and check active element via:

View File

@ -19,7 +19,8 @@
import logging import logging
from qutebrowser.commands.exceptions import ArgumentCountError from qutebrowser.commands.exceptions import (ArgumentCountError,
InvalidModeError)
from PyQt5.QtCore import pyqtSignal, QObject from PyQt5.QtCore import pyqtSignal, QObject
@ -55,7 +56,7 @@ class Command(QObject):
signal = pyqtSignal(tuple) signal = pyqtSignal(tuple)
def __init__(self, name, maxsplit, hide, nargs, count, desc, instance, def __init__(self, name, maxsplit, hide, nargs, count, desc, instance,
handler, completion): handler, completion, modes, not_modes):
super().__init__() super().__init__()
self.name = name self.name = name
self.maxsplit = maxsplit self.maxsplit = maxsplit
@ -66,18 +67,27 @@ class Command(QObject):
self.instance = instance self.instance = instance
self.handler = handler self.handler = handler
self.completion = completion self.completion = completion
self.modes = modes
self.not_modes = not_modes
def check(self, args): def check(self, args):
"""Check if the argument count is valid. """Check if the argument count is valid and the command is permitted.
Raise ArgumentCountError if not.
Args: Args:
args: The supplied arguments args: The supplied arguments
Raise: Raise:
ArgumentCountError if the argument count is wrong. ArgumentCountError if the argument count is wrong.
InvalidModeError if the command can't be called in this mode.
""" """
import qutebrowser.keyinput.modes as modeman
if self.modes is not None and modeman.manager.mode not in self.modes:
raise InvalidModeError("This command is only allowed in {} "
"mode.".format('/'.join(self.modes)))
elif (self.not_modes is not None and
modeman.manager.mode in self.not_modes):
raise InvalidModeError("This command is not allowed in {} "
"mode.".format('/'.join(self.not_modes)))
if self.nargs[1] is None and self.nargs[0] <= len(args): if self.nargs[1] is None and self.nargs[0] <= len(args):
pass pass
elif self.nargs[0] <= len(args) <= self.nargs[1]: elif self.nargs[0] <= len(args) <= self.nargs[1]:

View File

@ -33,3 +33,10 @@ class ArgumentCountError(TypeError):
"""Raised when a command was called with an invalid count of arguments.""" """Raised when a command was called with an invalid count of arguments."""
pass pass
class InvalidModeError(Exception):
"""Raised when a command is called in a wrong input mode."""
pass

View File

@ -24,7 +24,7 @@ import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils import qutebrowser.commands.utils as cmdutils
import qutebrowser.utils.message as message import qutebrowser.utils.message as message
from qutebrowser.commands.exceptions import (ArgumentCountError, from qutebrowser.commands.exceptions import (ArgumentCountError,
NoSuchCommandError) NoSuchCommandError, InvalidModeError)
def split_cmdline(text): def split_cmdline(text):
@ -202,6 +202,7 @@ class CommandParser:
NoSuchCommandError: if a command wasn't found. NoSuchCommandError: if a command wasn't found.
ArgumentCountError: if a command was called with the wrong count of ArgumentCountError: if a command was called with the wrong count of
arguments. arguments.
InvalidModeError: if a command can't be called in this mode.
Return: Return:
True if command was called (handler returnstatus is ignored!). True if command was called (handler returnstatus is ignored!).
@ -228,5 +229,11 @@ class CommandParser:
return False return False
else: else:
raise raise
except InvalidModeError as e:
if ignore_exc:
message.error("{}: {}".format(self._cmd.name, e))
return False
else:
raise
self._run(count=count) self._run(count=count)
return True return True

View File

@ -47,10 +47,11 @@ class register: # pylint: disable=invalid-name
hide: Whether to hide the command or not. hide: Whether to hide the command or not.
completion: Which completion to use for arguments, as a list of completion: Which completion to use for arguments, as a list of
strings. strings.
modes/not_modes: List of modes to use/not use.
""" """
def __init__(self, instance=None, name=None, nargs=None, maxsplit=-1, def __init__(self, instance=None, name=None, nargs=None, maxsplit=-1,
hide=False, completion=None): hide=False, completion=None, modes=None, not_modes=None):
"""Save decorator arguments. """Save decorator arguments.
Gets called on parse-time with the decorator arguments. Gets called on parse-time with the decorator arguments.
@ -58,12 +59,16 @@ class register: # pylint: disable=invalid-name
Args: Args:
See class attributes. See class attributes.
""" """
if modes is not None and not_modes is not None:
raise ValueError("Only modes or not_modes can be given!")
self.name = name self.name = name
self.maxsplit = maxsplit self.maxsplit = maxsplit
self.hide = hide self.hide = hide
self.nargs = nargs self.nargs = nargs
self.instance = instance self.instance = instance
self.completion = completion self.completion = completion
self.modes = modes
self.not_modes = not_modes
def __call__(self, func): def __call__(self, func):
"""Register the command before running the function. """Register the command before running the function.
@ -95,7 +100,8 @@ class register: # pylint: disable=invalid-name
cmd = Command(name=mainname, maxsplit=self.maxsplit, cmd = Command(name=mainname, maxsplit=self.maxsplit,
hide=self.hide, nargs=nargs, count=count, desc=desc, hide=self.hide, nargs=nargs, count=count, desc=desc,
instance=self.instance, handler=func, instance=self.instance, handler=func,
completion=self.completion) completion=self.completion, modes=self.modes,
not_modes=self.not_modes)
for name in names: for name in names:
cmd_dict[name] = cmd cmd_dict[name] = cmd
return func return func

View File

@ -158,7 +158,8 @@ class ModeManager(QObject):
logging.debug("New mode stack: {}".format(self._mode_stack)) logging.debug("New mode stack: {}".format(self._mode_stack))
self.left.emit(mode) self.left.emit(mode)
@cmdutils.register(instance='modeman', name='leave_mode', hide=True) @cmdutils.register(instance='modeman', name='leave_mode',
not_modes=['normal'], hide=True)
def leave_current_mode(self): def leave_current_mode(self):
if self.mode == "normal": if self.mode == "normal":
raise ValueError("Can't leave normal mode!") raise ValueError("Can't leave normal mode!")

View File

@ -297,12 +297,14 @@ class CompletionView(QTreeView):
selmod.clearSelection() selmod.clearSelection()
selmod.clearCurrentIndex() selmod.clearCurrentIndex()
@cmdutils.register(instance='mainwindow.completion', hide=True) @cmdutils.register(instance='mainwindow.completion', hide=True,
modes=['command'])
def completion_item_prev(self): def completion_item_prev(self):
"""Select the previous completion item.""" """Select the previous completion item."""
self._next_prev_item(prev=True) self._next_prev_item(prev=True)
@cmdutils.register(instance='mainwindow.completion', hide=True) @cmdutils.register(instance='mainwindow.completion', hide=True,
modes=['command'])
def completion_item_next(self): def completion_item_next(self):
"""Select the next completion item.""" """Select the next completion item."""
self._next_prev_item(prev=False) self._next_prev_item(prev=False)

View File

@ -290,7 +290,8 @@ class _Command(QLineEdit):
self.setFocus() self.setFocus()
self.show_cmd.emit() self.show_cmd.emit()
@cmdutils.register(instance='mainwindow.status.cmd', hide=True) @cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=['command'])
def command_history_prev(self): def command_history_prev(self):
"""Handle Up presses (go back in history).""" """Handle Up presses (go back in history)."""
try: try:
@ -303,7 +304,8 @@ class _Command(QLineEdit):
if item: if item:
self.set_cmd_text(item) self.set_cmd_text(item)
@cmdutils.register(instance='mainwindow.status.cmd', hide=True) @cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=['command'])
def command_history_next(self): def command_history_next(self):
"""Handle Down presses (go forward in history).""" """Handle Down presses (go forward in history)."""
if not self.history.browsing: if not self.history.browsing:
@ -315,7 +317,8 @@ class _Command(QLineEdit):
if item: if item:
self.set_cmd_text(item) self.set_cmd_text(item)
@cmdutils.register(instance='mainwindow.status.cmd', hide=True) @cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=['command'])
def command_accept(self): def command_accept(self):
"""Handle the command in the status bar. """Handle the command in the status bar.