Added --target command line argument #922

This argument is used to override the new-instance-open-target config
option.
This commit is contained in:
Jonas Schürmann 2015-10-05 21:09:26 +02:00
parent 228b4104b0
commit 45c9768c16
5 changed files with 60 additions and 31 deletions

View File

@ -103,8 +103,9 @@ def run(args):
if server is None:
sys.exit(usertypes.Exit.ok)
else:
server.got_args.connect(lambda args, cwd:
process_pos_args(args, cwd=cwd, via_ipc=True))
server.got_args.connect(lambda args, target_arg, cwd:
process_pos_args(args, cwd=cwd, via_ipc=True,
target_arg=target_arg))
init(args, crash_handler)
ret = qt_mainloop()
@ -229,7 +230,7 @@ def _load_session(name):
session_manager.delete('_restart')
def process_pos_args(args, via_ipc=False, cwd=None):
def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
"""Process positional commandline args.
URLs to open have no prefix, commands to execute begin with a colon.
@ -255,7 +256,11 @@ def process_pos_args(args, via_ipc=False, cwd=None):
log.init.debug("Empty argument")
win_id = mainwindow.get_window(via_ipc, force_window=True)
else:
win_id = mainwindow.get_window(via_ipc)
if via_ipc and target_arg and target_arg != 'auto':
open_target = target_arg
else:
open_target = config.get('general', 'new-instance-open-target')
win_id = mainwindow.get_window(via_ipc, open_target=open_target)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
log.init.debug("Startup URL {}".format(cmd))
@ -265,7 +270,6 @@ def process_pos_args(args, via_ipc=False, cwd=None):
message.error('current', "Error in startup argument '{}': "
"{}".format(cmd, e))
else:
open_target = config.get('general', 'new-instance-open-target')
background = open_target in ('tab-bg', 'tab-bg-silent')
tabbed_browser.tabopen(url, background=background)

View File

@ -41,7 +41,7 @@ from qutebrowser.misc import crashsignal
win_id_gen = itertools.count(0)
def get_window(via_ipc, force_window=False, force_tab=False):
def get_window(via_ipc, force_window=False, force_tab=False, open_target=None):
"""Helper function for app.py to get a window id.
Args:
@ -55,7 +55,8 @@ def get_window(via_ipc, force_window=False, force_tab=False):
# Initial main window
return 0
window_to_raise = None
open_target = config.get('general', 'new-instance-open-target')
if not open_target:
open_target = config.get('general', 'new-instance-open-target')
if (open_target == 'window' or force_window) and not force_tab:
window = MainWindow()
window.show()

View File

@ -152,7 +152,7 @@ class IPCServer(QObject):
got_invalid_data: Emitted when there was invalid incoming data.
"""
got_args = pyqtSignal(list, str)
got_args = pyqtSignal(list, str, str)
got_raw = pyqtSignal(bytes)
got_invalid_data = pyqtSignal()
@ -287,6 +287,7 @@ class IPCServer(QObject):
@pyqtSlot()
def on_ready_read(self):
"""Read json data from the client."""
# pylint: disable=too-many-return-statements
if self._socket is None:
# This happens when doing a connection while another one is already
# active for some reason.
@ -321,6 +322,13 @@ class IPCServer(QObject):
self._handle_invalid_data()
return
try:
target_arg = json_data['target_arg']
except KeyError:
log.ipc.error("target arg missing: {}".format(decoded.strip()))
self._handle_invalid_data()
return
try:
protocol_version = int(json_data['protocol_version'])
except (KeyError, ValueError):
@ -336,7 +344,7 @@ class IPCServer(QObject):
return
cwd = json_data.get('cwd', None)
self.got_args.emit(args, cwd)
self.got_args.emit(args, target_arg, cwd)
@pyqtSlot()
def on_timeout(self):
@ -418,8 +426,8 @@ def _has_legacy_server(name):
return False
def send_to_running_instance(socketname, command, *, legacy_name=None,
socket=None):
def send_to_running_instance(socketname, command, target_arg, *,
legacy_name=None, socket=None):
"""Try to send a commandline to a running instance.
Blocks for CONNECT_TIMEOUT ms.
@ -448,7 +456,8 @@ def send_to_running_instance(socketname, command, *, legacy_name=None,
connected = socket.waitForConnected(CONNECT_TIMEOUT)
if connected:
log.ipc.info("Opening in existing instance")
json_data = {'args': command, 'version': qutebrowser.__version__,
json_data = {'args': command, 'target_arg': target_arg,
'version': qutebrowser.__version__,
'protocol_version': PROTOCOL_VERSION}
try:
cwd = os.getcwd()
@ -500,6 +509,7 @@ def send_or_listen(args):
try:
try:
sent = send_to_running_instance(socketname, args.command,
args.target,
legacy_name=legacy_socketname)
if sent:
return None
@ -513,6 +523,7 @@ def send_or_listen(args):
log.init.debug("Got AddressInUseError, trying again.")
time.sleep(0.5)
sent = send_to_running_instance(socketname, args.command,
args.target,
legacy_name=legacy_socketname)
if sent:
return None

View File

@ -66,6 +66,10 @@ def get_argparser():
"session even if one would be restored.",
action='store_true')
parser.add_argument('--json-args', help=argparse.SUPPRESS)
parser.add_argument('--target', choices=['auto', 'tab', 'tab-bg',
'tab-silent', 'tab-bg-silent', 'window'],
help="How the urls should be opened if there is "
"already a qutebrowser instance running.")
debug = parser.add_argument_group('debug arguments')
debug.add_argument('-l', '--loglevel', dest='loglevel',

View File

@ -442,8 +442,8 @@ class TestHandleConnection:
assert msg in all_msgs
def test_read_line_immediately(self, qtbot, ipc_server, caplog):
data = '{{"args": ["foo"], "protocol_version": {}}}\n'.format(
ipc.PROTOCOL_VERSION)
data = '{{"args": ["foo"], "target_arg": "tab", ' \
'"protocol_version": {}}}\n'.format(ipc.PROTOCOL_VERSION)
socket = FakeSocket(data=data.encode('utf-8'))
ipc_server._server = FakeServer(socket)
@ -454,6 +454,7 @@ class TestHandleConnection:
assert len(spy) == 1
assert spy[0][0] == ['foo']
assert spy[0][1] == 'tab'
all_msgs = [r.message for r in caplog.records()]
assert "We can read a line immediately." in all_msgs
@ -490,12 +491,14 @@ NEW_VERSION = str(ipc.PROTOCOL_VERSION + 1).encode('utf-8')
(b'\n', 'invalid json'),
(b'{"is this invalid json?": true\n', 'invalid json'),
(b'{"valid json without args": true}\n', 'no args'),
(b'{"args": [], "protocol_version": ' + OLD_VERSION + b'}\n',
'incompatible version'),
(b'{"args": [], "protocol_version": ' + NEW_VERSION + b'}\n',
'incompatible version'),
(b'{"args": [], "protocol_version": "foo"}\n', 'invalid version'),
(b'{"args": []}\n', 'invalid version'),
(b'{"args": []}\n', 'target arg missing'),
(b'{"args": [], "target_arg": null, "protocol_version": ' + OLD_VERSION +
b'}\n', 'incompatible version'),
(b'{"args": [], "target_arg": null, "protocol_version": ' + NEW_VERSION +
b'}\n', 'incompatible version'),
(b'{"args": [], "target_arg": null, "protocol_version": "foo"}\n',
'invalid version'),
(b'{"args": [], "target_arg": null}\n', 'invalid version'),
])
def test_invalid_data(qtbot, ipc_server, connected_socket, caplog, data, msg):
got_args_spy = QSignalSpy(ipc_server.got_args)
@ -515,8 +518,10 @@ def test_multiline(qtbot, ipc_server, connected_socket):
spy = QSignalSpy(ipc_server.got_args)
error_spy = QSignalSpy(ipc_server.got_invalid_data)
data = ('{{"args": ["one"], "protocol_version": {version}}}\n'
'{{"args": ["two"], "protocol_version": {version}}}\n'.format(
data = ('{{"args": ["one"], "target_arg": "tab",'
' "protocol_version": {version}}}\n'
'{{"args": ["two"], "target_arg": null,'
' "protocol_version": {version}}}\n'.format(
version=ipc.PROTOCOL_VERSION))
with qtbot.waitSignals([ipc_server.got_args, ipc_server.got_args],
@ -526,13 +531,15 @@ def test_multiline(qtbot, ipc_server, connected_socket):
assert len(spy) == 2
assert not error_spy
assert spy[0][0] == ['one']
assert spy[0][1] == 'tab'
assert spy[1][0] == ['two']
assert spy[1][1] == ''
class TestSendToRunningInstance:
def test_no_server(self, caplog):
sent = ipc.send_to_running_instance('qute-test', [])
sent = ipc.send_to_running_instance('qute-test', [], None)
assert not sent
msg = caplog.records()[-1].message
assert msg == "No existing instance present (error 2)"
@ -550,7 +557,7 @@ class TestSendToRunningInstance:
if not has_cwd:
m = mocker.patch('qutebrowser.misc.ipc.os')
m.getcwd.side_effect = OSError
sent = ipc.send_to_running_instance('qute-test', ['foo'])
sent = ipc.send_to_running_instance('qute-test', ['foo'], None)
assert sent
@ -558,11 +565,12 @@ class TestSendToRunningInstance:
expected_cwd = str(tmpdir) if has_cwd else ''
assert len(spy) == 1
assert spy[0] == [['foo'], expected_cwd]
assert spy[0] == [['foo'], '', expected_cwd]
assert len(raw_spy) == 1
assert len(raw_spy[0]) == 1
raw_expected = {'args': ['foo'], 'version': qutebrowser.__version__,
raw_expected = {'args': ['foo'], 'target_arg': None,
'version': qutebrowser.__version__,
'protocol_version': ipc.PROTOCOL_VERSION}
if has_cwd:
raw_expected['cwd'] = str(tmpdir)
@ -572,20 +580,20 @@ class TestSendToRunningInstance:
def test_socket_error(self):
socket = FakeSocket(error=QLocalSocket.ConnectionError)
with pytest.raises(ipc.Error) as excinfo:
ipc.send_to_running_instance('qute-test', [], socket=socket)
ipc.send_to_running_instance('qute-test', [], None, socket=socket)
msg = "Error while writing to running instance: Error string (error 7)"
assert str(excinfo.value) == msg
def test_not_disconnected_immediately(self):
socket = FakeSocket()
ipc.send_to_running_instance('qute-test', [], socket=socket)
ipc.send_to_running_instance('qute-test', [], None, socket=socket)
def test_socket_error_no_server(self):
socket = FakeSocket(error=QLocalSocket.ConnectionError,
connect_successful=False)
with pytest.raises(ipc.Error) as excinfo:
ipc.send_to_running_instance('qute-test', [], socket=socket)
ipc.send_to_running_instance('qute-test', [], None, socket=socket)
msg = ("Error while connecting to running instance: Error string "
"(error 7)")
@ -628,12 +636,13 @@ def test_ipcserver_socket_none(ipc_server, caplog, method, args):
class TestSendOrListen:
Args = collections.namedtuple('Args', 'no_err_windows, basedir, command')
Args = collections.namedtuple('Args', 'no_err_windows, basedir, command, '
'target')
@pytest.fixture
def args(self):
return self.Args(no_err_windows=True, basedir='/basedir/for/testing',
command=['test'])
command=['test'], target=None)
@pytest.fixture(autouse=True)
def cleanup(self):