diff options
author | Florian Bruhin <me@the-compiler.org> | 2019-12-14 22:35:00 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2019-12-14 22:35:00 +0100 |
commit | 0aff95bede61709918d120c63111d8122031cfee (patch) | |
tree | afed879c74673dd0db0b3f8b3c38c71f3b3a92e7 | |
parent | 02c3f02edc2152b2d41c5c004f9f047cadc3a244 (diff) | |
download | qutebrowser-0aff95bede61709918d120c63111d8122031cfee.tar.gz qutebrowser-0aff95bede61709918d120c63111d8122031cfee.zip |
Add :spawn --output-messages
-rw-r--r-- | doc/changelog.asciidoc | 2 | ||||
-rw-r--r-- | qutebrowser/browser/commands.py | 7 | ||||
-rw-r--r-- | qutebrowser/misc/guiprocess.py | 10 | ||||
-rw-r--r-- | tests/unit/misc/test_guiprocess.py | 47 |
4 files changed, 63 insertions, 3 deletions
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 70a66e5a5..753d29ced 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -50,6 +50,8 @@ Changed - qutebrowser now enables the new PyQt exit scheme, which should result in things being cleaned up more properly (e.g. cookies being saved even without a timeout) on PyQt 5.13.1 and newer. +- The `:spawn` command has a new `-m` / `--output-messages` argument which + shows qutebrowser messages based on a command's standard output/error. - Performance improvements for the following areas: * Adding settings with URL patterns * Matching of settings using URL patterns diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index c4b8e86f8..871d0f673 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -994,8 +994,9 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window', maxsplit=0, no_replace_variables=True) @cmdutils.argument('count', value=cmdutils.Value.count) + @cmdutils.argument('output_messages', flag='m') def spawn(self, cmdline, userscript=False, verbose=False, - output=False, detach=False, count=None): + output=False, output_messages=False, detach=False, count=None): """Spawn a command in a shell. Args: @@ -1006,7 +1007,8 @@ class CommandDispatcher: (or `$XDG_DATA_HOME`) - `/usr/share/qutebrowser/userscripts` verbose: Show notifications when the command started/exited. - output: Whether the output should be shown in a new tab. + output: Show the output in a new tab. + output_messages: Show the output as messages. detach: Whether the command should be detached from qutebrowser. cmdline: The commandline to execute. count: Given to userscripts as $QUTE_COUNT. @@ -1048,6 +1050,7 @@ class CommandDispatcher: else: cmd = os.path.expanduser(cmd) proc = guiprocess.GUIProcess(what='command', verbose=verbose, + output_messages=output_messages, parent=self._tabbed_browser) if detach: ok = proc.start_detached(cmd, args) diff --git a/qutebrowser/misc/guiprocess.py b/qutebrowser/misc/guiprocess.py index 13c270944..aedb07bd1 100644 --- a/qutebrowser/misc/guiprocess.py +++ b/qutebrowser/misc/guiprocess.py @@ -37,6 +37,7 @@ class GUIProcess(QObject): cmd: The command which was started. args: A list of arguments which gets passed. verbose: Whether to show more messages. + _output_messages: Show output as messages. _started: Whether the underlying process is started. _proc: The underlying QProcess. _what: What kind of thing is spawned (process/editor/userscript/...). @@ -51,10 +52,11 @@ class GUIProcess(QObject): started = pyqtSignal() def __init__(self, what, *, verbose=False, additional_env=None, - parent=None): + output_messages=False, parent=None): super().__init__(parent) self._what = what self.verbose = verbose + self._output_messages = output_messages self._started = False self.cmd = None self.args = None @@ -92,6 +94,12 @@ class GUIProcess(QObject): stdout = bytes(self._proc.readAllStandardOutput()).decode( encoding, 'replace') + if self._output_messages: + if stdout: + message.info(stdout.strip()) + if stderr: + message.error(stderr.strip()) + if status == QProcess.CrashExit: exitinfo = "{} crashed!".format(self._what.capitalize()) message.error(exitinfo) diff --git a/tests/unit/misc/test_guiprocess.py b/tests/unit/misc/test_guiprocess.py index bb14a0cf2..32320ff5c 100644 --- a/tests/unit/misc/test_guiprocess.py +++ b/tests/unit/misc/test_guiprocess.py @@ -84,6 +84,53 @@ def test_start_verbose(proc, qtbot, message_mock, py_proc): assert qutescheme.spawn_output == expected +@pytest.mark.parametrize('stdout', [True, False]) +@pytest.mark.parametrize('stderr', [True, False]) +def test_start_output_message(proc, qtbot, caplog, message_mock, py_proc, + stdout, stderr): + proc._output_messages = True + + code = ['import sys'] + if stdout: + code.append('print("stdout text")') + if stderr: + code.append(r'sys.stderr.write("stderr text\n")') + code.append("sys.exit(0)") + + with caplog.at_level(logging.ERROR, 'message'): + with qtbot.waitSignals([proc.started, proc.finished], + timeout=10000, + order='strict'): + argv = py_proc(';'.join(code)) + proc.start(*argv) + + if stdout and stderr: + stdout_msg = message_mock.messages[0] + stderr_msg = message_mock.messages[1] + msg_count = 2 + elif stdout: + stdout_msg = message_mock.messages[0] + stderr_msg = None + msg_count = 1 + elif stderr: + stdout_msg = None + stderr_msg = message_mock.messages[0] + msg_count = 1 + else: + stdout_msg = None + stderr_msg = None + msg_count = 0 + + assert len(message_mock.messages) == msg_count + + if stdout_msg is not None: + assert stdout_msg.level == usertypes.MessageLevel.info + assert stdout_msg.text == 'stdout text' + if stderr_msg is not None: + assert stderr_msg.level == usertypes.MessageLevel.error + assert stderr_msg.text == 'stderr text' + + def test_start_env(monkeypatch, qtbot, py_proc): monkeypatch.setenv('QUTEBROWSER_TEST_1', '1') env = {'QUTEBROWSER_TEST_2': '2'} |