diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 586573948..c34c766a2 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -818,10 +818,13 @@ class CommandDispatcher: text = utils.get_clipboard(selection=sel) if not text.strip(): 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.strip()) - for i, text_url in text_urls: + log.misc.debug("{} contained: {!r}".format(target, text)) + text_urls = [u for u in text.split('\n') if u.strip()] + if (len(text_urls) > 1 and not urlutils.is_url(text_urls[0]) and + urlutils.get_path_if_valid( + text_urls[0], check_exists=True) is None): + text_urls = [text] + for i, text_url in enumerate(text_urls): if not window and i > 0: tab = False bg = True diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index e70a09f2d..ac9a49c7e 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -80,7 +80,7 @@ def _parse_search_term(s): engine = None term = s - log.url.debug("engine {}, term '{}'".format(engine, term)) + log.url.debug("engine {}, term {!r}".format(engine, term)) return (engine, term) @@ -93,7 +93,7 @@ def _get_search_url(txt): Return: The search URL as a QUrl. """ - log.url.debug("Finding search engine for '{}'".format(txt)) + log.url.debug("Finding search engine for {!r}".format(txt)) engine, term = _parse_search_term(txt) assert term if engine is None: @@ -171,22 +171,10 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): A target QUrl to a search page or the original URL. """ urlstr = urlstr.strip() - expanded = os.path.expanduser(urlstr) + path = get_path_if_valid(urlstr, cwd=cwd, relative=relative, + check_exists=True) - if os.path.isabs(expanded): - path = expanded - elif relative and cwd: - path = os.path.join(cwd, expanded) - elif relative: - try: - path = os.path.abspath(expanded) - except OSError: - path = None - else: - path = None - - if path is not None and os.path.exists(path): - log.url.debug("URL is a local file") + if path is not None: url = QUrl.fromLocalFile(path) elif (not do_search) or is_url(urlstr): # probably an address @@ -198,7 +186,7 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True): url = _get_search_url(urlstr) except ValueError: # invalid search engine url = qurl_from_user_input(urlstr) - log.url.debug("Converting fuzzy term {} to URL -> {}".format( + log.url.debug("Converting fuzzy term {!r} to URL -> {}".format( urlstr, url.toDisplayString())) if do_search and config.get('general', 'auto-search') and urlstr: qtutils.ensure_valid(url) @@ -246,7 +234,7 @@ def is_url(urlstr): """ autosearch = config.get('general', 'auto-search') - log.url.debug("Checking if '{}' is a URL (autosearch={}).".format( + log.url.debug("Checking if {!r} is a URL (autosearch={}).".format( urlstr, autosearch)) urlstr = urlstr.strip() @@ -349,6 +337,44 @@ def raise_cmdexc_if_invalid(url): raise cmdexc.CommandError(get_errstring(url)) +def get_path_if_valid(pathstr, cwd=None, relative=False, check_exists=False): + """Check if path is a valid path. + + Args: + pathstr: The path as string. + cwd: The current working directory, or None. + relative: Whether to resolve relative files. + check_exists: Whether to check if the file + actually exists of filesystem. + + Return: + The path if it is a valid path, None otherwise. + """ + pathstr = pathstr.strip() + log.url.debug("Checking if {!r} is a path".format(pathstr)) + expanded = os.path.expanduser(pathstr) + + if os.path.isabs(expanded): + path = expanded + elif relative and cwd: + path = os.path.join(cwd, expanded) + elif relative: + try: + path = os.path.abspath(expanded) + except OSError: + path = None + else: + path = None + + if check_exists: + if path is not None and os.path.exists(path): + log.url.debug("URL is a local file") + else: + path = None + + return path + + def filename_from_url(url): """Get a suitable filename from an URL. diff --git a/tests/integration/features/yankpaste.feature b/tests/integration/features/yankpaste.feature index b1e329ce9..8f6c6552f 100644 --- a/tests/integration/features/yankpaste.feature +++ b/tests/integration/features/yankpaste.feature @@ -126,6 +126,19 @@ Feature: Yanking and pasting. - data/hello2.txt - data/hello3.txt + Scenario: Pasting multiline text + Given I have a fresh instance + When I set searchengines -> DEFAULT to http://localhost:(port)/data/hello.txt?q={} + And I put the following lines into the clipboard: + this url: + http://qutebrowser.org + should not open + And I run :paste -t + And I wait until data/hello.txt?q=this%20url%3A%0Ahttp%3A//qutebrowser.org%0Ashould%20not%20open is loaded + Then the following tabs should be open: + - about:blank + - data/hello.txt?q=this%20url%3A%0Ahttp%3A//qutebrowser.org%0Ashould%20not%20open (active) + Scenario: Pasting multiple urls in a background tab Given I open about:blank When I run :tab-only diff --git a/tests/unit/utils/test_urlutils.py b/tests/unit/utils/test_urlutils.py index bb2778765..99e1eac56 100644 --- a/tests/unit/utils/test_urlutils.py +++ b/tests/unit/utils/test_urlutils.py @@ -238,6 +238,18 @@ class TestFuzzyUrl: with pytest.raises(urlutils.InvalidUrlError): urlutils.fuzzy_url(url, do_search=True) + @pytest.mark.parametrize('path, check_exists', [ + ('/foo', False), + ('/bar', True), + ]) + def test_get_path_existing(self, path, check_exists, os_mock): + """Test with an absolute path.""" + os_mock.path.exists.return_value = False + expected = None if check_exists else path + + url = urlutils.get_path_if_valid(path, check_exists=check_exists) + assert url == expected + @pytest.mark.parametrize('url, special', [ ('file:///tmp/foo', True),