diff --git a/qutebrowser/browser/curcommand.py b/qutebrowser/browser/curcommand.py index d1e122558..6b3eeb7bb 100644 --- a/qutebrowser/browser/curcommand.py +++ b/qutebrowser/browser/curcommand.py @@ -340,7 +340,7 @@ class CurCommandDispatcher(QObject): tab.zoom(-count) @cmdutils.register(instance='mainwindow.tabs.cur', modes=['insert'], - name='open_editor', hide=True) + name='open_editor', hide=True, needs_js=True) def editor(self): """Open an external editor with the current form field.""" frame = self._tabs.currentWidget().page_.currentFrame() diff --git a/qutebrowser/commands/_command.py b/qutebrowser/commands/_command.py index 7e7251459..0cd0cc386 100644 --- a/qutebrowser/commands/_command.py +++ b/qutebrowser/commands/_command.py @@ -20,9 +20,10 @@ import logging from qutebrowser.commands._exceptions import (ArgumentCountError, - InvalidModeError) + InvalidModeError, NeedsJSError) from PyQt5.QtCore import pyqtSignal, QObject +from PyQt5.QtWebKit import QWebSettings class Command(QObject): @@ -43,6 +44,7 @@ class Command(QObject): A dotted string as viewed from app.py, or None. handler: The handler function to call. completion: Completions to use for arguments, as a list of strings. + needs_js: Whether the command needs javascript enabled Signals: signal: Gets emitted when something should be called via handle_command @@ -56,7 +58,7 @@ class Command(QObject): signal = pyqtSignal(tuple) def __init__(self, name, maxsplit, hide, nargs, count, desc, instance, - handler, completion, modes, not_modes): + handler, completion, modes, not_modes, needs_js): # I really don't know how to solve this in a better way, I tried. # pylint: disable=too-many-arguments super().__init__() @@ -71,6 +73,7 @@ class Command(QObject): self.completion = completion self.modes = modes self.not_modes = not_modes + self.needs_js = needs_js def check(self, args): """Check if the argument count is valid and the command is permitted. @@ -90,6 +93,9 @@ class Command(QObject): modeman.manager.mode in self.not_modes): raise InvalidModeError("This command is not allowed in {} " "mode.".format('/'.join(self.not_modes))) + if self.needs_js and not QWebSettings.globalSettings().testAttribute( + QWebSettings.JavascriptEnabled): + raise NeedsJSError if self.nargs[1] is None and self.nargs[0] <= len(args): pass elif self.nargs[0] <= len(args) <= self.nargs[1]: diff --git a/qutebrowser/commands/_exceptions.py b/qutebrowser/commands/_exceptions.py index 328afcb24..17fadb22c 100644 --- a/qutebrowser/commands/_exceptions.py +++ b/qutebrowser/commands/_exceptions.py @@ -40,3 +40,10 @@ class InvalidModeError(Exception): """Raised when a command is called in a wrong input mode.""" pass + + +class NeedsJSError(Exception): + + """Raised when a command needs javascript but it is disabled.""" + + pass diff --git a/qutebrowser/commands/managers.py b/qutebrowser/commands/managers.py index 06c2184e1..8c553fb92 100644 --- a/qutebrowser/commands/managers.py +++ b/qutebrowser/commands/managers.py @@ -24,7 +24,7 @@ import qutebrowser.config.config as config import qutebrowser.commands.utils as cmdutils import qutebrowser.utils.message as message from qutebrowser.commands._exceptions import ( - ArgumentCountError, NoSuchCommandError, InvalidModeError) + ArgumentCountError, NoSuchCommandError, InvalidModeError, NeedsJSError) def split_cmdline(text): @@ -235,5 +235,11 @@ class CommandManager: return False else: raise + except NeedsJSError as e: + if ignore_exc: + message.error("{}: {}".format(self._cmd.name, e)) + return False + else: + raise self._run(count=count) return True diff --git a/qutebrowser/commands/utils.py b/qutebrowser/commands/utils.py index 690e90c20..db240f299 100644 --- a/qutebrowser/commands/utils.py +++ b/qutebrowser/commands/utils.py @@ -48,10 +48,12 @@ class register: # pylint: disable=invalid-name completion: Which completion to use for arguments, as a list of strings. modes/not_modes: List of modes to use/not use. + needs_js: If javascript is needed for this command. """ def __init__(self, instance=None, name=None, nargs=None, maxsplit=-1, - hide=False, completion=None, modes=None, not_modes=None): + hide=False, completion=None, modes=None, not_modes=None, + needs_js=False): """Save decorator arguments. Gets called on parse-time with the decorator arguments. @@ -69,6 +71,7 @@ class register: # pylint: disable=invalid-name self.completion = completion self.modes = modes self.not_modes = not_modes + self.needs_js = needs_js def __call__(self, func): """Register the command before running the function. @@ -106,7 +109,7 @@ class register: # pylint: disable=invalid-name hide=self.hide, nargs=nargs, count=count, desc=desc, instance=self.instance, handler=func, completion=self.completion, modes=self.modes, - not_modes=self.not_modes) + not_modes=self.not_modes, needs_js=self.needs_js) for name in names: cmd_dict[name] = cmd return func