From 9f9311840a2a46b25288d5ed2f432bec27802a9a Mon Sep 17 00:00:00 2001 From: George Edward Bulmer Date: Fri, 8 Dec 2017 16:44:53 +0000 Subject: [PATCH] Add --output-to-tab flag for :spawn. This puts the exit status, stdout, and stderr in a new tab. --- doc/help/commands.asciidoc | 3 ++- qutebrowser/browser/commands.py | 6 ++++-- qutebrowser/browser/qutescheme.py | 8 ++++++++ qutebrowser/misc/guiprocess.py | 33 ++++++++++++++++++++++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 5d026bfca..2487b8c85 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -1148,7 +1148,7 @@ Set a mark at the current scroll position in the current tab. [[spawn]] === spawn -Syntax: +:spawn [*--userscript*] [*--verbose*] [*--detach*] 'cmdline'+ +Syntax: +:spawn [*--userscript*] [*--verbose*] [*--output-to-tab*] [*--detach*] 'cmdline'+ Spawn a command in a shell. @@ -1163,6 +1163,7 @@ Spawn a command in a shell. - `/usr/share/qutebrowser/userscripts` * +*-v*+, +*--verbose*+: Show notifications when the command started/exited. +* +*-v*+, +*--output-to-tab*+: Show stderr, stdout, and exit status in a new tab. * +*-d*+, +*--detach*+: Whether the command should be detached from qutebrowser. ==== note diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index bced4daf4..8c623aa37 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1177,7 +1177,8 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window', maxsplit=0, no_replace_variables=True) - def spawn(self, cmdline, userscript=False, verbose=False, detach=False): + def spawn(self, cmdline, userscript=False, verbose=False, + output_to_tab=False, detach=False): """Spawn a command in a shell. Args: @@ -1208,7 +1209,8 @@ class CommandDispatcher: else: cmd = os.path.expanduser(cmd) proc = guiprocess.GUIProcess(what='command', verbose=verbose, - parent=self._tabbed_browser) + parent=self._tabbed_browser, + output_to_tab=output_to_tab) if detach: proc.start_detached(cmd, args) else: diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index e6262a007..3bd2c66a4 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -42,6 +42,7 @@ from qutebrowser.misc import objects pyeval_output = ":pyeval was never called" +spawn_output = ":spawn was never called" _HANDLERS = {} @@ -268,6 +269,13 @@ def qute_pyeval(_url): return 'text/html', html +@add_handler('spawn_output') +def qute_spawn_output(_url): + """Handler for qute://spawn_output.""" + html = jinja.render('pre.html', title='spawn output', content=spawn_output) + return 'text/html', html + + @add_handler('version') @add_handler('verizon') def qute_version(_url): diff --git a/qutebrowser/misc/guiprocess.py b/qutebrowser/misc/guiprocess.py index 1adf6817e..3c2057864 100644 --- a/qutebrowser/misc/guiprocess.py +++ b/qutebrowser/misc/guiprocess.py @@ -22,9 +22,11 @@ import shlex from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QProcess, - QProcessEnvironment) + QProcessEnvironment, QUrl) -from qutebrowser.utils import message, log +from qutebrowser.utils import message, log, objreg + +from qutebrowser.browser import qutescheme # A mapping of QProcess::ErrorCode's to human-readable strings. @@ -62,10 +64,11 @@ class GUIProcess(QObject): started = pyqtSignal() def __init__(self, what, *, verbose=False, additional_env=None, - parent=None): + parent=None, output_to_tab=False): super().__init__(parent) self._what = what self.verbose = verbose + self.output_to_tab = output_to_tab self._started = False self.cmd = None self.args = None @@ -96,6 +99,30 @@ class GUIProcess(QObject): self._started = False log.procs.debug("Process finished with code {}, status {}.".format( code, status)) + + stdout = None + stderr = None + + if self.output_to_tab: + stderr = bytes(self._proc.readAllStandardError()).decode('utf-8') + stdout = bytes(self._proc.readAllStandardOutput()).decode('utf-8') + + spawn_log = "" + + spawn_log += "Process finished with code {},status {}.".format( + code, status) + + if stdout: + spawn_log += "\nProcess stdout:\n" + stdout.strip() + if stderr: + spawn_log += "\nProcess stderr:\n" + stderr.strip() + + qutescheme.spawn_output = spawn_log + + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window='last-focused') + tabbed_browser.openurl(QUrl('qute://spawn_output'), newtab=True) + if status == QProcess.CrashExit: message.error("{} crashed!".format(self._what.capitalize())) elif status == QProcess.NormalExit and code == 0: