From 6327d0fe36ccefe2f0958d148d25d0f0e18c0c18 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Sat, 9 Jan 2016 11:26:17 +0100 Subject: [PATCH 1/8] Strip url before trying to open it as a path --- qutebrowser/utils/urlutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index 307ade709..fb1771d12 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -168,6 +168,7 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): Return: A target QUrl to a search page or the original URL. """ + urlstr = urlstr.strip() expanded = os.path.expanduser(urlstr) if os.path.isabs(expanded): path = expanded @@ -181,7 +182,6 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): else: path = None - stripped = urlstr.strip() if path is not None and os.path.exists(path): log.url.debug("URL is a local file") url = QUrl.fromLocalFile(path) From 1b31a3fee4e7b0b23d454bead6fa79dc4a5d27e9 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Sat, 9 Jan 2016 11:32:12 +0100 Subject: [PATCH 2/8] Allows to paste multiple URLs - The paste command will now open one tab/window per url if multiple URLs (separated by newline) are present in the clipboard - Adds the tests for the new multitab functionality - Changes test/integration/conftest.py to be able to insert newlines in the clipboard for the test --- qutebrowser/browser/commands.py | 18 ++++-- tests/integration/features/conftest.py | 1 + tests/integration/features/yankpaste.feature | 59 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 76b267121..4195ed094 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -825,12 +825,18 @@ class CommandDispatcher: text = clipboard.text(mode) if not text: raise cmdexc.CommandError("{} is empty.".format(target)) - log.misc.debug("{} contained: '{}'".format(target, text)) - try: - url = urlutils.fuzzy_url(text) - except urlutils.InvalidUrlError as e: - raise cmdexc.CommandError(e) - self._open(url, tab, bg, window) + log.misc.debug("{} contained: '{}'".format(target, + text.replace('\n', '\\n'))) + text_urls = enumerate([u for u in text.split('\n') if u != '']) + for i, text_url in text_urls: + if not window and i > 0: + tab = False + bg = True + try: + url = urlutils.fuzzy_url(text_url) + except urlutils.InvalidUrlError as e: + raise cmdexc.CommandError(e) + self._open(url, tab, bg, window) @cmdutils.register(instance='command-dispatcher', scope='window', count='count') diff --git a/tests/integration/features/conftest.py b/tests/integration/features/conftest.py index 3d856f396..72de45fc6 100644 --- a/tests/integration/features/conftest.py +++ b/tests/integration/features/conftest.py @@ -199,6 +199,7 @@ def selection_supported(qapp): def fill_clipboard(qtbot, qapp, httpbin, what, content): mode = _clipboard_mode(qapp, what) content = content.replace('(port)', str(httpbin.port)) + content = content.replace('\\n', '\n') clipboard = qapp.clipboard() with qtbot.waitSignal(clipboard.changed): diff --git a/tests/integration/features/yankpaste.feature b/tests/integration/features/yankpaste.feature index e4a0dbfe6..89a2d8426 100644 --- a/tests/integration/features/yankpaste.feature +++ b/tests/integration/features/yankpaste.feature @@ -104,3 +104,62 @@ Feature: Yanking and pasting. And I put "foo bar" into the clipboard And I run :paste Then the error "Invalid URL" should be shown + + Scenario: Pasting multiple urls in a new tab + Given I have a fresh instance + When I run :tab-only + And I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + And I run :paste -t + And I wait until data/hello.txt is loaded + And I wait until data/hello2.txt is loaded + And I wait until data/hello3.txt is loaded + Then the following tabs should be open: + - about:blank + - data/hello.txt (active) + - data/hello2.txt + - data/hello3.txt + + Scenario: Pasting multiple urls in a background tab + Given I open about:blank + When I run :tab-only + And I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + And I run :paste -b + And I wait until data/hello.txt is loaded + And I wait until data/hello2.txt is loaded + And I wait until data/hello3.txt is loaded + Then the following tabs should be open: + - about:blank (active) + - data/hello.txt + - data/hello2.txt + - data/hello3.txt + + Scenario: Pasting multiple urls in new windows + Given I have a fresh instance + When I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + And I run :paste -w + And I wait until data/hello.txt is loaded + And I wait until data/hello2.txt is loaded + And I wait until data/hello3.txt is loaded + Then the session should look like: + windows: + - tabs: + - active: true + history: + - active: true + url: about:blank + - tabs: + - active: true + history: + - active: true + url: http://localhost:*/data/hello.txt + - tabs: + - active: true + history: + - active: true + url: http://localhost:*/data/hello2.txt + - tabs: + - active: true + history: + - active: true + url: http://localhost:*/data/hello3.txt + From b2c7ab9211cec1c7d449191aaf914e7cb1779aac Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Sat, 9 Jan 2016 12:49:56 +0100 Subject: [PATCH 3/8] Fixes: forgot to rename removed variable instances --- qutebrowser/utils/urlutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index fb1771d12..53637a466 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -185,7 +185,7 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): if path is not None and os.path.exists(path): log.url.debug("URL is a local file") url = QUrl.fromLocalFile(path) - elif (not do_search) or is_url(stripped): + elif (not do_search) or is_url(urlstr): # probably an address log.url.debug("URL is a fuzzy address") url = qurl_from_user_input(urlstr) @@ -194,7 +194,7 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): try: url = _get_search_url(urlstr) except ValueError: # invalid search engine - url = qurl_from_user_input(stripped) + url = qurl_from_user_input(urlstr) log.url.debug("Converting fuzzy term {} to URL -> {}".format( urlstr, url.toDisplayString())) if do_search and config.get('general', 'auto-search'): From 4bbc1e2d8a79205a24cfa1e927668e8baa1310c9 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Tue, 12 Jan 2016 09:58:08 +0100 Subject: [PATCH 4/8] Changes line as suggested in review --- qutebrowser/browser/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 4195ed094..42d4d08e4 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -827,7 +827,7 @@ class CommandDispatcher: raise cmdexc.CommandError("{} is empty.".format(target)) log.misc.debug("{} contained: '{}'".format(target, text.replace('\n', '\\n'))) - text_urls = enumerate([u for u in text.split('\n') if u != '']) + text_urls = enumerate(u for u in text.split('\n') if u) for i, text_url in text_urls: if not window and i > 0: tab = False From f08704e789c1c782b853418ad5452ba8aab84deb Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Tue, 12 Jan 2016 09:59:03 +0100 Subject: [PATCH 5/8] Adds function to insert multiple lines in the clipboard --- tests/integration/features/conftest.py | 9 ++++++++- tests/integration/features/yankpaste.feature | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/integration/features/conftest.py b/tests/integration/features/conftest.py index 72de45fc6..076f91942 100644 --- a/tests/integration/features/conftest.py +++ b/tests/integration/features/conftest.py @@ -199,13 +199,20 @@ def selection_supported(qapp): def fill_clipboard(qtbot, qapp, httpbin, what, content): mode = _clipboard_mode(qapp, what) content = content.replace('(port)', str(httpbin.port)) - content = content.replace('\\n', '\n') clipboard = qapp.clipboard() with qtbot.waitSignal(clipboard.changed): clipboard.setText(content, mode) +@bdd.when(bdd.parsers.re(r'I put the following lines into the ' + r'(?Pprimary selection|clipboard):\n' + r'(?P.+)$', flags=re.DOTALL)) +def fill_clipboard_multiline(qtbot, qapp, httpbin, what, content): + content = '\n'.join(l.strip() for l in content.strip().split('\n')) + fill_clipboard(qtbot, qapp, httpbin, what, content) + + ## Then diff --git a/tests/integration/features/yankpaste.feature b/tests/integration/features/yankpaste.feature index 89a2d8426..e8487848f 100644 --- a/tests/integration/features/yankpaste.feature +++ b/tests/integration/features/yankpaste.feature @@ -108,7 +108,10 @@ Feature: Yanking and pasting. Scenario: Pasting multiple urls in a new tab Given I have a fresh instance When I run :tab-only - And I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + And I put the following lines into the clipboard: + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -t And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded @@ -122,7 +125,10 @@ Feature: Yanking and pasting. Scenario: Pasting multiple urls in a background tab Given I open about:blank When I run :tab-only - And I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + And I put the following lines into the clipboard: + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -b And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded @@ -135,7 +141,10 @@ Feature: Yanking and pasting. Scenario: Pasting multiple urls in new windows Given I have a fresh instance - When I put "http://localhost:(port)/data/hello.txt\nhttp://localhost:(port)/data/hello2.txt\nhttp://localhost:(port)/data/hello3.txt" into the clipboard + When I put the following lines into the clipboard: + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -w And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded From 524341fd7ae1b74928e0ae7966d7d481e4793bb4 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Tue, 12 Jan 2016 11:24:31 +0100 Subject: [PATCH 6/8] Use textwrap.dedent to parse multiline clipboard text --- tests/integration/features/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/features/conftest.py b/tests/integration/features/conftest.py index 076f91942..69fd2e942 100644 --- a/tests/integration/features/conftest.py +++ b/tests/integration/features/conftest.py @@ -25,6 +25,7 @@ import json import os.path import logging import collections +import textwrap import pytest import yaml @@ -209,8 +210,7 @@ def fill_clipboard(qtbot, qapp, httpbin, what, content): r'(?Pprimary selection|clipboard):\n' r'(?P.+)$', flags=re.DOTALL)) def fill_clipboard_multiline(qtbot, qapp, httpbin, what, content): - content = '\n'.join(l.strip() for l in content.strip().split('\n')) - fill_clipboard(qtbot, qapp, httpbin, what, content) + fill_clipboard(qtbot, qapp, httpbin, what, textwrap.dedent(content)) ## Then From 5917bbbe5c5d640655b182d598189484246f2ef7 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Tue, 12 Jan 2016 11:25:14 +0100 Subject: [PATCH 7/8] Fixes wrong indentation in multiline clipboard text --- tests/integration/features/yankpaste.feature | 21 ++++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/integration/features/yankpaste.feature b/tests/integration/features/yankpaste.feature index e8487848f..881cb1ede 100644 --- a/tests/integration/features/yankpaste.feature +++ b/tests/integration/features/yankpaste.feature @@ -107,11 +107,10 @@ Feature: Yanking and pasting. Scenario: Pasting multiple urls in a new tab Given I have a fresh instance - When I run :tab-only - And I put the following lines into the clipboard: - http://localhost:(port)/data/hello.txt - http://localhost:(port)/data/hello2.txt - http://localhost:(port)/data/hello3.txt + When I put the following lines into the clipboard: + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -t And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded @@ -126,9 +125,9 @@ Feature: Yanking and pasting. Given I open about:blank When I run :tab-only And I put the following lines into the clipboard: - http://localhost:(port)/data/hello.txt - http://localhost:(port)/data/hello2.txt - http://localhost:(port)/data/hello3.txt + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -b And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded @@ -142,9 +141,9 @@ Feature: Yanking and pasting. Scenario: Pasting multiple urls in new windows Given I have a fresh instance When I put the following lines into the clipboard: - http://localhost:(port)/data/hello.txt - http://localhost:(port)/data/hello2.txt - http://localhost:(port)/data/hello3.txt + http://localhost:(port)/data/hello.txt + http://localhost:(port)/data/hello2.txt + http://localhost:(port)/data/hello3.txt And I run :paste -w And I wait until data/hello.txt is loaded And I wait until data/hello2.txt is loaded From f813bc24157372ff974ec4c6144711b626b79878 Mon Sep 17 00:00:00 2001 From: Tarcisio Fedrizzi Date: Tue, 12 Jan 2016 11:27:11 +0100 Subject: [PATCH 8/8] Adds unit test to check that paths ending with newlines are handled correctly --- tests/unit/utils/test_urlutils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/unit/utils/test_urlutils.py b/tests/unit/utils/test_urlutils.py index 6ee82a586..99e61a832 100644 --- a/tests/unit/utils/test_urlutils.py +++ b/tests/unit/utils/test_urlutils.py @@ -166,13 +166,17 @@ class TestFuzzyUrl: assert not os_mock.path.exists.called assert url == QUrl('http://foo') - def test_file_absolute(self, os_mock): + @pytest.mark.parametrize('path, expected', [ + ('/foo', QUrl('file:///foo')), + ('/bar\n', QUrl('file:///bar')), + ]) + def test_file_absolute(self, path, expected, os_mock): """Test with an absolute path.""" os_mock.path.exists.return_value = True os_mock.path.isabs.return_value = True - url = urlutils.fuzzy_url('/foo') - assert url == QUrl('file:///foo') + url = urlutils.fuzzy_url(path) + assert url == expected @pytest.mark.posix def test_file_absolute_expanded(self, os_mock):