diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index f70bdd9af..6e27a4f07 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -100,6 +100,7 @@ |<<completion.delay,completion.delay>>|Delay (in milliseconds) before updating completions after typing a character. |<<completion.height,completion.height>>|Height (in pixels or as percentage of the window) of the completion. |<<completion.min_chars,completion.min_chars>>|Minimum amount of characters needed to update completions. +|<<completion.open_categories,completion.open_categories>>|Which categories to show (in which order) in the :open completion. |<<completion.quick,completion.quick>>|Move on to the next part when there's only one possible completion left. |<<completion.scrollbar.padding,completion.scrollbar.padding>>|Padding (in pixels) of the scrollbar handle in the completion window. |<<completion.scrollbar.width,completion.scrollbar.width>>|Width (in pixels) of the scrollbar in the completion window. @@ -1400,6 +1401,26 @@ Type: <<types,Int>> Default: +pass:[1]+ +[[completion.open_categories]] +=== completion.open_categories +Which categories to show (in which order) in the :open completion. + +Type: <<types,FlagList>> + +Valid values: + + * +searchengines+ + * +quickmarks+ + * +bookmarks+ + * +history+ + +Default: + +- +pass:[searchengines]+ +- +pass:[quickmarks]+ +- +pass:[bookmarks]+ +- +pass:[history]+ + [[completion.quick]] === completion.quick Move on to the next part when there's only one possible completion left. diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index d4b56ae7c..530916787 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -18,6 +18,8 @@ python-dateutil==2.7.3 ./scripts/dev/pylint_checkers requests==2.19.1 six==1.11.0 +typed-ast==1.1.0 +typing==3.6.4 uritemplate==3.0.0 urllib3==1.23 wrapt==1.10.11 diff --git a/qutebrowser/completion/models/urlmodel.py b/qutebrowser/completion/models/urlmodel.py index 0a684fb89..3ef2a2213 100644 --- a/qutebrowser/completion/models/urlmodel.py +++ b/qutebrowser/completion/models/urlmodel.py @@ -22,6 +22,7 @@ from qutebrowser.completion.models import (completionmodel, listcategory, histcategory) from qutebrowser.utils import log, objreg +from qutebrowser.config import config _URLCOL = 0 @@ -50,7 +51,8 @@ def _delete_quickmark(data): def url(*, info): - """A model which combines bookmarks, quickmarks and web history URLs. + """A model which combines bookmarks, quickmarks, search engines and web + history URLs. Used for the `open` command. """ @@ -59,16 +61,32 @@ def url(*, info): quickmarks = [(url, name) for (name, url) in objreg.get('quickmark-manager').marks.items()] bookmarks = objreg.get('bookmark-manager').marks.items() + # pylint: disable=bad-config-option + searchengines = {k:v for k, v in config.val.url.searchengines.items() + if k not in "DEFAULT"}.items() + # pylint: enable=bad-config-option + categories = config.val.completion.open_categories + models = {} - if quickmarks: - model.add_category(listcategory.ListCategory( + + if searchengines and "searchengines" in categories: + models["searchengines"] = listcategory.ListCategory( + 'Search engines', searchengines, sort=False) + + if quickmarks and "quickmarks" in categories: + models["quickmarks"] = listcategory.ListCategory( 'Quickmarks', quickmarks, delete_func=_delete_quickmark, - sort=False)) - if bookmarks: - model.add_category(listcategory.ListCategory( - 'Bookmarks', bookmarks, delete_func=_delete_bookmark, sort=False)) + sort=False) + if bookmarks and "bookmarks" in categories: + models["bookmarks"] = listcategory.ListCategory( + 'Bookmarks', bookmarks, delete_func=_delete_bookmark, sort=False) - if info.config.get('completion.web_history.max_items') != 0: + if info.config.get('completion.web_history.max_items') != 0 and "history" in categories: hist_cat = histcategory.HistoryCategory(delete_func=_delete_history) - model.add_category(hist_cat) + models["history"] = hist_cat + + for category in categories: + if category in models: + model.add_category(models[category]) + return model diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 3c7ed09af..a81a98604 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -976,6 +976,18 @@ downloads.location.suggestion: - both: Show download path and filename. desc: What to display in the download filename input. +completion.open_categories: + type: + name: FlagList + valid_values: [searchengines, quickmarks, bookmarks, history] + none_ok: true + default: + - searchengines + - quickmarks + - bookmarks + - history + desc: Which categories to show (in which order) in the :open completion. + downloads.open_dispatcher: type: name: String diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index 173135d73..a366444f9 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -459,6 +459,12 @@ class BookmarkManagerStub(UrlMarkManagerStub): pass +class SearchenginesManagerStub(UrlMarkManagerStub): + + """Stub for the bookmark-manager object.""" + + pass + class QuickmarkManagerStub(UrlMarkManagerStub): diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py index 81cdfc19e..b6a3da497 100644 --- a/tests/unit/completion/test_models.py +++ b/tests/unit/completion/test_models.py @@ -141,6 +141,24 @@ def configdata_stub(config_stub, monkeypatch, configdata_init): default=True, backends=[], raw_backends=None)), + ('completion.open_categories', configdata.Option( + name='completion.open_categories', + description='Which categories to show (in which order) in the :open completion.', + typ=configtypes.FlagList( + ), + default=["searchengines", "quickmarks", "bookmarks", "history"], + backends=[], + raw_backends=None)), + ('url.searchengines', configdata.Option( + name='url.searchengines', + description='searchengines list', + typ=configtypes.Dict( + keytype=configtypes.String(), + valtype=configtypes.String(), + ), + default={"DEFAULT": "https://duckduckgo.com/?q={}", "google": "https://google.com/?q={}"}, + backends=[], + raw_backends=None)), ])) config_stub._init_values() @@ -247,11 +265,100 @@ def test_help_completion(qtmodeltester, cmdutils_stub, key_config_stub, ('aliases', 'Aliases for commands.', None), ('bindings.commands', 'Default keybindings', None), ('bindings.default', 'Default keybindings', None), + ('completion.open_categories', 'Which categories to show (in which order) in the :open completion.', None), ('content.javascript.enabled', 'Enable/Disable JavaScript', None), - ] + ('url.searchengines', 'searchengines list', None), + ], }) +def test_open_categories(qtmodeltester, config_stub, web_history_populated, + quickmarks, bookmarks, info): + """Test that open_categories settings has the desired effect. + + Verify that: + - All categories are listed when they are defined in the completion.open_categories list + """ + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}", + "google": "https://google.com/?q={}"} + config_stub.val.completion.open_categories = ["searchengines", "quickmarks", "bookmarks", "history"] + model = urlmodel.url(info=info) + model.set_pattern('') + qtmodeltester.data_display_may_return_none = True + qtmodeltester.check(model) + + _check_completions(model, { + "Search engines": [ + ('google', 'https://google.com/?q={}', None), + ], + "Quickmarks": [ + ('https://wiki.archlinux.org', 'aw', None), + ('https://wikipedia.org', 'wiki', None), + ('https://duckduckgo.com', 'ddg', None), + ], + "Bookmarks": [ + ('https://github.com', 'GitHub', None), + ('https://python.org', 'Welcome to Python.org', None), + ('http://qutebrowser.org', 'qutebrowser | qutebrowser', None), + ], + "History": [ + ('https://github.com', 'https://github.com', '2016-05-01'), + ('https://python.org', 'Welcome to Python.org', '2016-03-08'), + ('http://qutebrowser.org', 'qutebrowser', '2015-09-05'), + ], + }) + + +def test_open_categories_remove_all(qtmodeltester, config_stub, web_history_populated, + quickmarks, bookmarks, info): + """Test that removing an item (boookmarks) from the open_categories settings has the desired effect. + + Verify that: + - Only categories + """ + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}", + "google": "https://google.com/?q={}"} + config_stub.val.completion.open_categories = [] + model = urlmodel.url(info=info) + model.set_pattern('') + qtmodeltester.data_display_may_return_none = True + qtmodeltester.check(model) + + _check_completions(model, { + }) + + +def test_open_categories_remove_one(qtmodeltester, config_stub, web_history_populated, + quickmarks, bookmarks, info): + """Test that removing an item (boookmarks) from the open_categories settings has the desired effect. + + Verify that: + - Only categories + """ + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}", + "google": "https://google.com/?q={}"} + config_stub.val.completion.open_categories = ["searchengines", "quickmarks", "history"] + model = urlmodel.url(info=info) + model.set_pattern('') + qtmodeltester.data_display_may_return_none = True + qtmodeltester.check(model) + + _check_completions(model, { + "Search engines": [ + ('google', 'https://google.com/?q={}', None), + ], + "Quickmarks": [ + ('https://wiki.archlinux.org', 'aw', None), + ('https://wikipedia.org', 'wiki', None), + ('https://duckduckgo.com', 'ddg', None), + ], + "History": [ + ('https://github.com', 'https://github.com', '2016-05-01'), + ('https://python.org', 'Welcome to Python.org', '2016-03-08'), + ('http://qutebrowser.org', 'qutebrowser', '2015-09-05'), + ], + }) + def test_quickmark_completion(qtmodeltester, quickmarks): """Test the results of quickmark completion.""" model = miscmodels.quickmark() @@ -332,15 +439,53 @@ def url_args(fake_args): fake_args.debug_flags = [] -def test_url_completion(qtmodeltester, web_history_populated, +def test_url_completion(qtmodeltester, config_stub, web_history_populated, quickmarks, bookmarks, info): """Test the results of url completion. Verify that: - - quickmarks, bookmarks, and urls are included + - searchengines, quickmarks, bookmarks, and urls are included + - default search engine is not displayed - entries are sorted by access time - only the most recent entry is included for each url """ + config_stub.val.completion.open_categories = ["searchengines", "quickmarks", "bookmarks", "history"] + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}", "google": "https://google.com/?q={}"} + model = urlmodel.url(info=info) + model.set_pattern('') + qtmodeltester.data_display_may_return_none = True + qtmodeltester.check(model) + + _check_completions(model, { + "Search engines": [ + ('google', 'https://google.com/?q={}', None), + ], + "Quickmarks": [ + ('https://wiki.archlinux.org', 'aw', None), + ('https://wikipedia.org', 'wiki', None), + ('https://duckduckgo.com', 'ddg', None), + ], + "Bookmarks": [ + ('https://github.com', 'GitHub', None), + ('https://python.org', 'Welcome to Python.org', None), + ('http://qutebrowser.org', 'qutebrowser | qutebrowser', None), + ], + "History": [ + ('https://github.com', 'https://github.com', '2016-05-01'), + ('https://python.org', 'Welcome to Python.org', '2016-03-08'), + ('http://qutebrowser.org', 'qutebrowser', '2015-09-05'), + ], + }) + +def test_search_only_default(qtmodeltester, config_stub, web_history_populated, + quickmarks, bookmarks, info): + """Test that Seardh engines is not shown when only default search engine is set in settings. + + Verify that: + - No Search engines categories is shown + """ + config_stub.val.completion.open_categories = ["searchengines", "quickmarks", "bookmarks", "history"] + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}",} model = urlmodel.url(info=info) model.set_pattern('') qtmodeltester.data_display_may_return_none = True @@ -364,7 +509,6 @@ def test_url_completion(qtmodeltester, web_history_populated, ], }) - def test_url_completion_no_quickmarks(qtmodeltester, web_history_populated, quickmark_manager_stub, bookmarks, info): """Test that the quickmark category is gone with no quickmarks.""" @@ -507,9 +651,11 @@ def test_url_completion_zero_limit(config_stub, web_history, quickmarks, info, bookmarks): """Make sure there's no history if the limit was set to zero.""" config_stub.val.completion.web_history.max_items = 0 + config_stub.val.completion.open_categories = ["searchengines", "quickmarks", "bookmarks", "history"] + config_stub.val.url.searchengines = {"DEFAULT": "https://duckduckgo.com/?q={}", "google": "https://google.com/?q={}"} model = urlmodel.url(info=info) model.set_pattern('') - category = model.index(2, 0) # "History" normally + category = model.index(3, 0) # "History" normally assert model.data(category) is None @@ -697,8 +843,12 @@ def test_setting_option_completion(qtmodeltester, config_stub, ('bindings.commands', 'Default keybindings', ( '{"normal": {"<Ctrl+q>": "quit", "ZQ": "quit", ' '"I": "invalid", "d": "scroll down"}}')), + ('completion.open_categories', 'Which categories to show (in which order) in the :open completion.', + '["searchengines", "quickmarks", "bookmarks", "history"]'), ('content.javascript.enabled', 'Enable/Disable JavaScript', 'true'), + ('url.searchengines', 'searchengines list', + '{"DEFAULT": "https://duckduckgo.com/?q={}", "google": "https://google.com/?q={}"}'), ] })