diff --git a/qutebrowser/browser/adblock.py b/qutebrowser/browser/adblock.py index 312e36cf5..26d846074 100644 --- a/qutebrowser/browser/adblock.py +++ b/qutebrowser/browser/adblock.py @@ -108,8 +108,8 @@ class HostBlocker: message.info('current', "Run :adblock-update to get adblock lists.") - @cmdutils.register(instance='host-blocker') - def adblock_update(self, win_id: {'special': 'win_id'}): + @cmdutils.register(instance='host-blocker', win_id='win_id') + def adblock_update(self, win_id): """Update the adblock block lists.""" self.blocked_hosts = set() self._done_count = 0 diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index b1ec93658..1297168d6 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -153,8 +153,7 @@ class CommandDispatcher: else: return None - def _scroll_percent(self, perc=None, count: {'special': 'count'}=None, - orientation=None): + def _scroll_percent(self, perc=None, count=None, orientation=None): """Inner logic for scroll_percent_(x|y). Args: @@ -252,9 +251,9 @@ class CommandDispatcher: "'previous'!") return None - @cmdutils.register(instance='command-dispatcher', scope='window') - def tab_close(self, left=False, right=False, opposite=False, - count: {'special': 'count'}=None): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def tab_close(self, left=False, right=False, opposite=False, count=None): """Close the current/[count]th tab. Args: @@ -280,10 +279,9 @@ class CommandDispatcher: tabbar.setSelectionBehaviorOnRemove(old_selection_behavior) @cmdutils.register(instance='command-dispatcher', name='open', - maxsplit=0, scope='window', + maxsplit=0, scope='window', count='count', completion=[usertypes.Completion.url]) - def openurl(self, url=None, bg=False, tab=False, window=False, - count: {'special': 'count'}=None): + def openurl(self, url=None, bg=False, tab=False, window=False, count=None): """Open a URL in the current/[count]th tab. Args: @@ -320,8 +318,8 @@ class CommandDispatcher: curtab.openurl(url) @cmdutils.register(instance='command-dispatcher', name='reload', - scope='window') - def reloadpage(self, force=False, count: {'special': 'count'}=None): + scope='window', count='count') + def reloadpage(self, force=False, count=None): """Reload the current/[count]th tab. Args: @@ -335,8 +333,9 @@ class CommandDispatcher: else: tab.reload() - @cmdutils.register(instance='command-dispatcher', scope='window') - def stop(self, count: {'special': 'count'}=None): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def stop(self, count=None): """Stop loading in the current/[count]th tab. Args: @@ -347,8 +346,8 @@ class CommandDispatcher: tab.stop() @cmdutils.register(instance='command-dispatcher', name='print', - scope='window') - def printpage(self, preview=False, count: {'special': 'count'}=None): + scope='window', count='count') + def printpage(self, preview=False, count=None): """Print the current/[count]th tab. Args: @@ -432,9 +431,9 @@ class CommandDispatcher: else: widget.back() - @cmdutils.register(instance='command-dispatcher', scope='window') - def back(self, tab=False, bg=False, window=False, - count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def back(self, tab=False, bg=False, window=False, count=1): """Go back in the history of the current tab. Args: @@ -445,9 +444,9 @@ class CommandDispatcher: """ self._back_forward(tab, bg, window, count, forward=False) - @cmdutils.register(instance='command-dispatcher', scope='window') - def forward(self, tab=False, bg=False, window=False, - count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def forward(self, tab=False, bg=False, window=False, count=1): """Go forward in the history of the current tab. Args: @@ -555,9 +554,8 @@ class CommandDispatcher: "`where'.".format(where)) @cmdutils.register(instance='command-dispatcher', hide=True, - scope='window') - def scroll(self, dx: {'type': float}, dy: {'type': float}, - count: {'special': 'count'}=1): + scope='window', count='count') + def scroll(self, dx: {'type': float}, dy: {'type': float}, count=1): """Scroll the current tab by 'count * dx/dy'. Args: @@ -572,10 +570,9 @@ class CommandDispatcher: self._current_widget().page().currentFrame().scroll(dx, dy) @cmdutils.register(instance='command-dispatcher', hide=True, - scope='window') + scope='window', count='count') def scroll_perc(self, perc: {'type': float}=None, - horizontal: {'flag': 'x'}=False, - count: {'special': 'count'}=None): + horizontal: {'flag': 'x'}=False, count=None): """Scroll to a specific percentage of the page. The percentage can be given either as argument or as count. @@ -590,9 +587,8 @@ class CommandDispatcher: Qt.Horizontal if horizontal else Qt.Vertical) @cmdutils.register(instance='command-dispatcher', hide=True, - scope='window') - def scroll_page(self, x: {'type': float}, y: {'type': float}, - count: {'special': 'count'}=1): + scope='window', count='count') + def scroll_page(self, x: {'type': float}, y: {'type': float}, count=1): """Scroll the frame page-wise. Args: @@ -633,8 +629,9 @@ class CommandDispatcher: what = 'Title' if title else 'URL' message.info(self._win_id, "{} yanked to {}".format(what, target)) - @cmdutils.register(instance='command-dispatcher', scope='window') - def zoom_in(self, count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def zoom_in(self, count=1): """Increase the zoom level for the current tab. Args: @@ -643,8 +640,9 @@ class CommandDispatcher: tab = self._current_widget() tab.zoom(count) - @cmdutils.register(instance='command-dispatcher', scope='window') - def zoom_out(self, count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def zoom_out(self, count=1): """Decrease the zoom level for the current tab. Args: @@ -653,9 +651,9 @@ class CommandDispatcher: tab = self._current_widget() tab.zoom(-count) - @cmdutils.register(instance='command-dispatcher', scope='window') - def zoom(self, zoom: {'type': int}=None, - count: {'special': 'count'}=None): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def zoom(self, zoom: {'type': int}=None, count=None): """Set the zoom level for the current tab. The zoom can be given as argument or as [count]. If neither of both is @@ -701,8 +699,9 @@ class CommandDispatcher: except IndexError: raise cmdexc.CommandError("Nothing to undo!") - @cmdutils.register(instance='command-dispatcher', scope='window') - def tab_prev(self, count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def tab_prev(self, count=1): """Switch to the previous tab, or switch [count] tabs back. Args: @@ -716,8 +715,9 @@ class CommandDispatcher: else: raise cmdexc.CommandError("First tab") - @cmdutils.register(instance='command-dispatcher', scope='window') - def tab_next(self, count: {'special': 'count'}=1): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def tab_next(self, count=1): """Switch to the next tab, or switch [count] tabs forward. Args: @@ -758,9 +758,9 @@ class CommandDispatcher: raise cmdexc.CommandError(e) self._open(url, tab, bg, window) - @cmdutils.register(instance='command-dispatcher', scope='window') - def tab_focus(self, index: {'type': (int, 'last')}=None, - count: {'special': 'count'}=None): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def tab_focus(self, index: {'type': (int, 'last')}=None, count=None): """Select the tab given as argument/[count]. Args: @@ -783,9 +783,9 @@ class CommandDispatcher: raise cmdexc.CommandError("There's no tab with index {}!".format( idx)) - @cmdutils.register(instance='command-dispatcher', scope='window') - def tab_move(self, direction: {'type': ('+', '-')}=None, - count: {'special': 'count'}=None): + @cmdutils.register(instance='command-dispatcher', scope='window', + count='count') + def tab_move(self, direction: {'type': ('+', '-')}=None, count=None): """Move the current tab. Args: @@ -823,9 +823,9 @@ class CommandDispatcher: finally: tabbed_browser.setUpdatesEnabled(True) - @cmdutils.register(instance='command-dispatcher', scope='window') - def spawn(self, win_id: {'special': 'win_id'}, userscript=False, - quiet=False, *args): + @cmdutils.register(instance='command-dispatcher', scope='window', + win_id='win_id') + def spawn(self, win_id, userscript=False, quiet=False, *args): """Spawn a command in a shell. Note the {url} variable which gets replaced by the current URL might be @@ -1117,8 +1117,8 @@ class CommandDispatcher: view.search_flags = flags @cmdutils.register(instance='command-dispatcher', hide=True, - scope='window') - def search_next(self, count: {'special': 'count'}=1): + scope='window', count='count') + def search_next(self, count=1): """Continue the search to the ([count]th) next term. Args: @@ -1130,8 +1130,8 @@ class CommandDispatcher: view.search(view.search_text, view.search_flags) @cmdutils.register(instance='command-dispatcher', hide=True, - scope='window') - def search_prev(self, count: {'special': 'count'}=1): + scope='window', count='count') + def search_prev(self, count=1): """Continue the search to the ([count]th) previous term. Args: diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 8873d43c6..8238050bf 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -794,8 +794,9 @@ class DownloadManager(QAbstractListModel): raise cmdexc.CommandError("There's no download!") raise cmdexc.CommandError("There's no download {}!".format(count)) - @cmdutils.register(instance='download-manager', scope='window') - def download_cancel(self, count: {'special': 'count'}=0): + @cmdutils.register(instance='download-manager', scope='window', + count='count') + def download_cancel(self, count=0): """Cancel the last/[count]th download. Args: @@ -812,8 +813,9 @@ class DownloadManager(QAbstractListModel): .format(count)) download.cancel() - @cmdutils.register(instance='download-manager', scope='window') - def download_delete(self, count: {'special': 'count'}=0): + @cmdutils.register(instance='download-manager', scope='window', + count='count') + def download_delete(self, count=0): """Delete the last/[count]th download from disk. Args: @@ -831,8 +833,9 @@ class DownloadManager(QAbstractListModel): self.remove_item(download) @cmdutils.register(instance='download-manager', scope='window', - deprecated="Use :download-cancel instead.") - def cancel_download(self, count: {'special': 'count'}=1): + deprecated="Use :download-cancel instead.", + count='count') + def cancel_download(self, count=1): """Cancel the first/[count]th download. Args: @@ -840,8 +843,9 @@ class DownloadManager(QAbstractListModel): """ self.download_cancel(count) - @cmdutils.register(instance='download-manager', scope='window') - def download_open(self, count: {'special': 'count'}=0): + @cmdutils.register(instance='download-manager', scope='window', + count='count') + def download_open(self, count=0): """Open the last/[count]th download. Args: @@ -912,9 +916,9 @@ class DownloadManager(QAbstractListModel): """Check if there are finished downloads to clear.""" return any(download.done for download in self.downloads) - @cmdutils.register(instance='download-manager', scope='window') - def download_remove(self, all_: {'name': 'all'}=False, - count: {'special': 'count'}=0): + @cmdutils.register(instance='download-manager', scope='window', + count='count') + def download_remove(self, all_: {'name': 'all'}=False, count=0): """Remove the last/[count]th download from the list. Args: diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index ce051228b..c62c65d4d 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -693,9 +693,10 @@ class HintManager(QObject): tab=self._tab_id) webview.openurl(url) - @cmdutils.register(instance='hintmanager', scope='tab', name='hint') + @cmdutils.register(instance='hintmanager', scope='tab', name='hint', + win_id='win_id') def start(self, rapid=False, group=webelem.Group.all, target=Target.normal, - *args: {'nargs': '*'}, win_id: {'special': 'win_id'}): + *args: {'nargs': '*'}, win_id): """Start hinting. Args: diff --git a/qutebrowser/browser/quickmarks.py b/qutebrowser/browser/quickmarks.py index 578738ceb..305cf45a5 100644 --- a/qutebrowser/browser/quickmarks.py +++ b/qutebrowser/browser/quickmarks.py @@ -105,8 +105,8 @@ class QuickmarkManager(QObject): win_id, "Add quickmark:", usertypes.PromptMode.text, functools.partial(self.quickmark_add, win_id, urlstr)) - @cmdutils.register(instance='quickmark-manager') - def quickmark_add(self, win_id: {'special': 'win_id'}, url, name): + @cmdutils.register(instance='quickmark-manager', win_id='win_id') + def quickmark_add(self, win_id, url, name): """Add a new quickmark. Args: diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 6e8f6bce7..fae1cb997 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -44,8 +44,8 @@ class Command: completion: Completions to use for arguments, as a list of strings. debug: Whether this is a debugging command (only shown with --debug). parser: The ArgumentParser to use to parse this command. - special_params: A dict with the names of the special parameters as - values. + count_arg: The name of the count parameter, or None. + win_id_arg: The name of the win_id parameter, or None. flags_with_args: A list of flags which take an argument. no_cmd_split: If true, ';;' to split sub-commands is ignored. _type_conv: A mapping of conversion functions for arguments. @@ -62,13 +62,13 @@ class Command: """ AnnotationInfo = collections.namedtuple('AnnotationInfo', - ['kwargs', 'type', 'name', 'flag', - 'special']) + ['kwargs', 'type', 'name', 'flag']) def __init__(self, *, handler, name, instance=None, maxsplit=None, hide=False, completion=None, modes=None, not_modes=None, needs_js=False, debug=False, ignore_args=False, - deprecated=False, no_cmd_split=False, scope='global'): + deprecated=False, no_cmd_split=False, scope='global', + count=None, win_id=None): # I really don't know how to solve this in a better way, I tried. # pylint: disable=too-many-arguments,too-many-locals if modes is not None and not_modes is not None: @@ -98,6 +98,8 @@ class Command: self.ignore_args = ignore_args self.handler = handler self.no_cmd_split = no_cmd_split + self.count_arg = count + self.win_id_arg = win_id self.docparser = docutils.DocstringParser(handler) self.parser = argparser.ArgumentParser( name, description=self.docparser.short_desc, @@ -110,7 +112,6 @@ class Command: self.namespace = None self._count = None self.pos_args = [] - self.special_params = {'count': None, 'win_id': None} self.desc = None self.flags_with_args = [] self._type_conv = {} @@ -188,40 +189,22 @@ class Command: d[param.name] = annotation_info.name return d - def _inspect_special_param(self, param, annotation_info): + def _inspect_special_param(self, param): """Check if the given parameter is a special one. Args: param: The inspect.Parameter to handle. - annotation_info: The AnnotationInfo tuple for the parameter. Return: True if the parameter is special, False otherwise. """ - special = annotation_info.special - if special == 'count': - if self.special_params['count'] is not None: - raise ValueError("Registered multiple parameters ({}/{}) as " - "count!".format(self.special_params['count'], - param.name)) + if param.name == self.count_arg: if param.default is inspect.Parameter.empty: raise TypeError("{}: handler has count parameter " "without default!".format(self.name)) - self.special_params['count'] = param.name return True - elif special == 'win_id': - if self.special_params['win_id'] is not None: - raise ValueError("Registered multiple parameters ({}/{}) as " - "win_id!".format( - self.special_params['win_id'], - param.name)) - self.special_params['win_id'] = param.name + elif param.name == self.win_id_arg: return True - elif special is None: - return False - else: - raise ValueError("{}: Invalid value '{}' for 'special' " - "annotation!".format(self.name, special)) def _inspect_func(self): """Inspect the function to get useful informations from it. @@ -239,12 +222,22 @@ class Command: self.desc = doc.splitlines()[0].strip() else: self.desc = "" + + if (self.count_arg is not None and + self.count_arg not in signature.parameters): + raise ValueError("count parameter {} does not exist!".format( + self.count_arg)) + if (self.win_id_arg is not None and + self.win_id_arg not in signature.parameters): + raise ValueError("win_id parameter {} does not exist!".format( + self.win_id_arg)) + if not self.ignore_args: for param in signature.parameters.values(): annotation_info = self._parse_annotation(param) if param.name == 'self': continue - if self._inspect_special_param(param, annotation_info): + if self._inspect_special_param(param): continue arg_count += 1 typ = self._get_type(param, annotation_info) @@ -344,12 +337,11 @@ class Command: flag: The short name/flag if overridden. name: The long name if overridden. """ - info = {'kwargs': {}, 'type': None, 'flag': None, 'name': None, - 'special': None} + info = {'kwargs': {}, 'type': None, 'flag': None, 'name': None} if param.annotation is not inspect.Parameter.empty: log.commands.vdebug("Parsing annotation {}".format( param.annotation)) - for field in ('type', 'flag', 'name', 'special'): + for field in ('type', 'flag', 'name'): if field in param.annotation: info[field] = param.annotation[field] if 'nargs' in param.annotation: @@ -465,11 +457,11 @@ class Command: # Special case for 'self'. self._get_self_arg(win_id, param, args) continue - elif param.name == self.special_params['count']: + elif param.name == self.count_arg: # Special case for count parameter. self._get_count_arg(param, args, kwargs) continue - elif param.name == self.special_params['win_id']: + elif param.name == self.win_id_arg: # Special case for win_id parameter. self._get_win_id_arg(win_id, param, args, kwargs) continue diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 882973f3e..6a4c3b0b1 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -579,11 +579,10 @@ class ConfigManager(QObject): newval = val.typ.transform(newval) return newval - @cmdutils.register(name='set', instance='config', + @cmdutils.register(name='set', instance='config', win_id='win_id', completion=[Completion.section, Completion.option, Completion.value]) - def set_command(self, win_id: {'special': 'win_id'}, - sectname: {'name': 'section'}=None, + def set_command(self, win_id, sectname: {'name': 'section'}=None, optname: {'name': 'option'}=None, value=None, temp=False, print_val: {'name': 'print'}=False): """Set an option. diff --git a/qutebrowser/misc/savemanager.py b/qutebrowser/misc/savemanager.py index 3a7772b1c..b07457863 100644 --- a/qutebrowser/misc/savemanager.py +++ b/qutebrowser/misc/savemanager.py @@ -184,9 +184,8 @@ class SaveManager(QObject): message.error('current', "Failed to auto-save {}: " "{}".format(key, e)) - @cmdutils.register(instance='save-manager', name='save') - def save_command(self, win_id: {'special': 'win_id'}, - *what: {'nargs': '*'}): + @cmdutils.register(instance='save-manager', name='save', win_id='win_id') + def save_command(self, win_id, *what: {'nargs': '*'}): """Save configs and state. Args: diff --git a/qutebrowser/misc/sessions.py b/qutebrowser/misc/sessions.py index 53cfb32c6..2d9cc222d 100644 --- a/qutebrowser/misc/sessions.py +++ b/qutebrowser/misc/sessions.py @@ -323,12 +323,11 @@ class SessionManager(QObject): for win in old_windows: win.close() - @cmdutils.register(name=['session-save', 'w'], + @cmdutils.register(name=['session-save', 'w'], win_id='win_id', completion=[usertypes.Completion.sessions], instance='session-manager') - def session_save(self, win_id: {'special': 'win_id'}, - name: {'type': str}=default, current=False, quiet=False, - force=False): + def session_save(self, win_id, name: {'type': str}=default, current=False, + quiet=False, force=False): """Save a session. Args: diff --git a/qutebrowser/misc/utilcmds.py b/qutebrowser/misc/utilcmds.py index a777623b4..0d8305567 100644 --- a/qutebrowser/misc/utilcmds.py +++ b/qutebrowser/misc/utilcmds.py @@ -34,8 +34,8 @@ from qutebrowser.config import style from qutebrowser.misc import consolewidget -@cmdutils.register(maxsplit=1, no_cmd_split=True) -def later(ms: {'type': int}, command, win_id: {'special': 'win_id'}): +@cmdutils.register(maxsplit=1, no_cmd_split=True, win_id='win_id') +def later(ms: {'type': int}, command, win_id): """Execute a command after some time. Args: @@ -63,8 +63,8 @@ def later(ms: {'type': int}, command, win_id: {'special': 'win_id'}): raise -@cmdutils.register(maxsplit=1, no_cmd_split=True) -def repeat(times: {'type': int}, command, win_id: {'special': 'win_id'}): +@cmdutils.register(maxsplit=1, no_cmd_split=True, win_id='win_id') +def repeat(times: {'type': int}, command, win_id): """Repeat a given command. Args: @@ -78,8 +78,8 @@ def repeat(times: {'type': int}, command, win_id: {'special': 'win_id'}): commandrunner.run_safely(command) -@cmdutils.register(hide=True) -def message_error(win_id: {'special': 'win_id'}, text): +@cmdutils.register(hide=True, win_id='win_id') +def message_error(win_id, text): """Show an error message in the statusbar. Args: @@ -88,8 +88,8 @@ def message_error(win_id: {'special': 'win_id'}, text): message.error(win_id, text) -@cmdutils.register(hide=True) -def message_info(win_id: {'special': 'win_id'}, text): +@cmdutils.register(hide=True, win_id='win_id') +def message_info(win_id, text): """Show an info message in the statusbar. Args: @@ -98,8 +98,8 @@ def message_info(win_id: {'special': 'win_id'}, text): message.info(win_id, text) -@cmdutils.register(hide=True) -def message_warning(win_id: {'special': 'win_id'}, text): +@cmdutils.register(hide=True, win_id='win_id') +def message_warning(win_id, text): """Show a warning message in the statusbar. Args: diff --git a/scripts/src2asciidoc.py b/scripts/src2asciidoc.py index 5c471dfa5..767552ebd 100755 --- a/scripts/src2asciidoc.py +++ b/scripts/src2asciidoc.py @@ -208,10 +208,10 @@ def _get_command_doc_count(cmd, parser): Yield: Strings which should be added to the docs. """ - if cmd.special_params['count'] is not None: + if cmd.count_arg is not None: yield "" yield "==== count" - yield parser.arg_descs[cmd.special_params['count']] + yield parser.arg_descs[cmd.count_arg] def _get_command_doc_notes(cmd):