Add --output-to-tab flag for :spawn.

This puts the exit status, stdout, and stderr in a new tab.
This commit is contained in:
George Edward Bulmer 2017-12-08 16:44:53 +00:00
parent d4cadcc62e
commit 9f9311840a
4 changed files with 44 additions and 6 deletions

View File

@ -1148,7 +1148,7 @@ Set a mark at the current scroll position in the current tab.
[[spawn]] [[spawn]]
=== spawn === spawn
Syntax: +:spawn [*--userscript*] [*--verbose*] [*--detach*] 'cmdline'+ Syntax: +:spawn [*--userscript*] [*--verbose*] [*--output-to-tab*] [*--detach*] 'cmdline'+
Spawn a command in a shell. Spawn a command in a shell.
@ -1163,6 +1163,7 @@ Spawn a command in a shell.
- `/usr/share/qutebrowser/userscripts` - `/usr/share/qutebrowser/userscripts`
* +*-v*+, +*--verbose*+: Show notifications when the command started/exited. * +*-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. * +*-d*+, +*--detach*+: Whether the command should be detached from qutebrowser.
==== note ==== note

View File

@ -1177,7 +1177,8 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window', @cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0, no_replace_variables=True) 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. """Spawn a command in a shell.
Args: Args:
@ -1208,7 +1209,8 @@ class CommandDispatcher:
else: else:
cmd = os.path.expanduser(cmd) cmd = os.path.expanduser(cmd)
proc = guiprocess.GUIProcess(what='command', verbose=verbose, proc = guiprocess.GUIProcess(what='command', verbose=verbose,
parent=self._tabbed_browser) parent=self._tabbed_browser,
output_to_tab=output_to_tab)
if detach: if detach:
proc.start_detached(cmd, args) proc.start_detached(cmd, args)
else: else:

View File

@ -42,6 +42,7 @@ from qutebrowser.misc import objects
pyeval_output = ":pyeval was never called" pyeval_output = ":pyeval was never called"
spawn_output = ":spawn was never called"
_HANDLERS = {} _HANDLERS = {}
@ -268,6 +269,13 @@ def qute_pyeval(_url):
return 'text/html', html 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('version')
@add_handler('verizon') @add_handler('verizon')
def qute_version(_url): def qute_version(_url):

View File

@ -22,9 +22,11 @@
import shlex import shlex
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QProcess, 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. # A mapping of QProcess::ErrorCode's to human-readable strings.
@ -62,10 +64,11 @@ class GUIProcess(QObject):
started = pyqtSignal() started = pyqtSignal()
def __init__(self, what, *, verbose=False, additional_env=None, def __init__(self, what, *, verbose=False, additional_env=None,
parent=None): parent=None, output_to_tab=False):
super().__init__(parent) super().__init__(parent)
self._what = what self._what = what
self.verbose = verbose self.verbose = verbose
self.output_to_tab = output_to_tab
self._started = False self._started = False
self.cmd = None self.cmd = None
self.args = None self.args = None
@ -96,6 +99,30 @@ class GUIProcess(QObject):
self._started = False self._started = False
log.procs.debug("Process finished with code {}, status {}.".format( log.procs.debug("Process finished with code {}, status {}.".format(
code, status)) 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: if status == QProcess.CrashExit:
message.error("{} crashed!".format(self._what.capitalize())) message.error("{} crashed!".format(self._what.capitalize()))
elif status == QProcess.NormalExit and code == 0: elif status == QProcess.NormalExit and code == 0: