def option(*, info): """A CompletionModel filled with settings and their descriptions.""" model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) options = ((opt.name, opt.description, info.config.get_str(opt.name)) for opt in configdata.DATA.values()) model.add_category(listcategory.ListCategory("Options", options)) return model
def buffer(): """A model to complete on open tabs across all windows. Used for switching the buffer command. """ def delete_buffer(data): """Close the selected tab.""" win_id, tab_index = data[0].split('/') tabbed_browser = objreg.get('tabbed-browser', scope='window', window=int(win_id)) tabbed_browser.on_tab_close_requested(int(tab_index) - 1) model = completionmodel.CompletionModel(column_widths=(6, 40, 54)) for win_id in objreg.window_registry: tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) if tabbed_browser.shutting_down: continue tabs = [] for idx in range(tabbed_browser.count()): tab = tabbed_browser.widget(idx) tabs.append(("{}/{}".format(win_id, idx + 1), tab.url().toDisplayString(), tabbed_browser.page_title(idx))) cat = listcategory.ListCategory("{}".format(win_id), tabs, delete_func=delete_buffer) model.add_category(cat) return model
def _back_forward(info, go_forward): history = info.cur_tab.history current_idx = history.current_idx() model = completionmodel.CompletionModel(column_widths=(5, 36, 50, 9)) if go_forward: start = current_idx + 1 items = history.forward_items() else: start = 0 items = history.back_items() entries = [ ( str(idx), entry.url().toDisplayString(), entry.title(), _qdatetime_to_completion_format(entry.lastVisited()) ) for idx, entry in enumerate(items, start) ] if not go_forward: # make sure the most recent is at the top for :back entries.reverse() cat = listcategory.ListCategory("History", entries, sort=False) model.add_category(cat) return model
def command(*, info): """A CompletionModel filled with non-hidden commands and descriptions.""" model = completionmodel.CompletionModel(column_widths=(20, 60, 20)) cmdlist = util.get_cmd_completions(info, include_aliases=True, include_hidden=False) model.add_category(listcategory.ListCategory("Commands", cmdlist)) return model
def value(optname, *_values, info): """A CompletionModel filled with setting values. Args: optname: The name of the config option this model shows. _values: The values already provided on the command line. info: A CompletionInfo instance. """ model = completionmodel.CompletionModel(column_widths=(30, 70, 0)) try: current = info.config.get_str(optname) except configexc.NoOptionError: return None opt = info.config.get_opt(optname) default = opt.typ.to_str(opt.default) cur_cat = listcategory.ListCategory("Current/Default", [(current, "Current value"), (default, "Default value")]) model.add_category(cur_cat) vals = opt.typ.complete() if vals is not None: model.add_category(listcategory.ListCategory("Completions", vals)) return model
def url(*, info): """A model which combines bookmarks, quickmarks and web history URLs. Used for the `open` command. """ model = completionmodel.CompletionModel(column_widths=(40, 50, 10)) quickmarks = ((url, name) for (name, url) in objreg.get('quickmark-manager').marks.items()) bookmarks = objreg.get('bookmark-manager').marks.items() model.add_category( listcategory.ListCategory('Quickmarks', quickmarks, delete_func=_delete_quickmark)) model.add_category( listcategory.ListCategory('Bookmarks', bookmarks, delete_func=_delete_bookmark)) if info.config.get('completion.web_history_max_items') != 0: hist_cat = histcategory.HistoryCategory(delete_func=_delete_history) model.add_category(hist_cat) return model
def test_completion_show(show, rows, quick_complete, completionview, config_stub): """Test that the completion widget is shown at appropriate times. Args: show: The completion show config setting. rows: Each entry represents a completion category with only one item. quick_complete: The `completion.quick` config setting. """ config_stub.val.completion.show = show config_stub.val.completion.quick = quick_complete model = completionmodel.CompletionModel() for name in rows: cat = listcategory.ListCategory('', [(name, )]) model.add_category(cat) assert not completionview.isVisible() completionview.set_model(model) assert completionview.isVisible() == (show == 'always' and len(rows) > 0) completionview.completion_item_focus('next') expected = (show != 'never' and len(rows) > 0 and not (quick_complete and len(rows) == 1)) assert completionview.isVisible() == expected completionview.set_model(None) completionview.completion_item_focus('next') assert not completionview.isVisible()
def test_completion_item_focus_fetch(completionview, qtbot): """Test that on_next_prev_item moves the selection properly. Args: which: the direction in which to move the selection. tree: Each list represents a completion category, with each string being an item under that category. expected: expected argument from on_selection_changed for each successive movement. None implies no signal should be emitted. """ model = completionmodel.CompletionModel() cat = mock.Mock(spec=[ 'layoutChanged', 'layoutAboutToBeChanged', 'canFetchMore', 'fetchMore', 'rowCount', 'index', 'data' ]) cat.canFetchMore = lambda *_: True cat.rowCount = lambda *_: 2 cat.fetchMore = mock.Mock() model.add_category(cat) completionview.set_model(model) # clear the fetchMore call that happens on set_model cat.reset_mock() # not at end, fetchMore shouldn't be called completionview.completion_item_focus('next') assert not cat.fetchMore.called # at end, fetchMore should be called completionview.completion_item_focus('next') assert cat.fetchMore.called
def value(sectname, optname): """A CompletionModel filled with setting values. Args: sectname: The name of the config section this model shows. optname: The name of the config option this model shows. """ model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) config = objreg.get('config') try: current = config.get(sectname, optname, raw=True) or '""' except (configexc.NoSectionError, configexc.NoOptionError): return None default = configdata.DATA[sectname][optname].default() or '""' if hasattr(configdata.DATA[sectname], 'valtype'): # Same type for all values (ValueList) vals = configdata.DATA[sectname].valtype.complete() else: if optname is None: raise ValueError("optname may only be None for ValueList " "sections, but {} is not!".format(sectname)) # Different type for each value (KeyValue) vals = configdata.DATA[sectname][optname].typ.complete() cur_cat = listcategory.ListCategory("Current/Default", [(current, "Current value"), (default, "Default value")]) model.add_category(cur_cat) if vals is not None: model.add_category(listcategory.ListCategory("Completions", vals)) return model
def bind(key, *, info): """A CompletionModel filled with all bindable commands and descriptions. Args: key: the key being bound. """ model = completionmodel.CompletionModel(column_widths=(20, 60, 20)) data = [] cmd_text = info.keyconf.get_command(key, 'normal') if cmd_text: parser = runners.CommandParser() try: cmd = parser.parse(cmd_text).cmd except cmdexc.NoSuchCommandError: data.append((cmd_text, '(Current) Invalid command!', key)) else: data.append((cmd_text, '(Current) {}'.format(cmd.desc), key)) cmd_text = info.keyconf.get_command(key, 'normal', default=True) if cmd_text: parser = runners.CommandParser() cmd = parser.parse(cmd_text).cmd data.append((cmd_text, '(Default) {}'.format(cmd.desc), key)) if data: model.add_category(listcategory.ListCategory("Current/Default", data)) cmdlist = util.get_cmd_completions(info, include_hidden=True, include_aliases=True) model.add_category(listcategory.ListCategory("Commands", cmdlist)) return model
def option(sectname): """A CompletionModel filled with settings and their descriptions. Args: sectname: The name of the config section this model shows. """ model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) try: sectdata = configdata.DATA[sectname] except KeyError: return None options = [] for name in sectdata: try: desc = sectdata.descriptions[name] except (KeyError, AttributeError): # Some stuff (especially ValueList items) don't have a # description. desc = "" else: desc = desc.splitlines()[0] config = objreg.get('config') val = config.get(sectname, name, raw=True) options.append((name, desc, val)) model.add_category(listcategory.ListCategory(sectname, options)) return model
def section(): """A CompletionModel filled with settings sections.""" model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) sections = ((name, configdata.SECTION_DESC[name].splitlines()[0].strip()) for name in configdata.DATA) model.add_category(listcategory.ListCategory("Sections", sections)) return model
def test_set_pattern(completionview): model = completionmodel.CompletionModel() model.set_pattern = mock.Mock(spec=[]) completionview.set_model(model) completionview.set_pattern('foo') model.set_pattern.assert_called_with('foo') assert not completionview.selectionModel().currentIndex().isValid()
def _buffer(skip_win_id=None): """Helper to get the completion model for buffer/other_buffer. Args: skip_win_id: The id of the window to skip, or None to include all. """ def delete_buffer(data): """Close the selected tab.""" win_id, tab_index = data[0].split('/') tabbed_browser = objreg.get('tabbed-browser', scope='window', window=int(win_id)) tabbed_browser.on_tab_close_requested(int(tab_index) - 1) model = completionmodel.CompletionModel(column_widths=(6, 40, 54)) for win_id in objreg.window_registry: if skip_win_id is not None and win_id == skip_win_id: continue tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) if tabbed_browser.shutting_down: continue tabs = [] for idx in range(tabbed_browser.widget.count()): tab = tabbed_browser.widget.widget(idx) tabs.append(("{}/{}".format(win_id, idx + 1), tab.url().toDisplayString(), tabbed_browser.widget.page_title(idx))) cat = listcategory.ListCategory("{}".format(win_id), tabs, delete_func=delete_buffer) model.add_category(cat) return model
def test_delete_cur_item(): func = mock.Mock(spec=[]) model = completionmodel.CompletionModel() cat = listcategory.ListCategory('', [('foo', 'bar')], delete_func=func) model.add_category(cat) parent = model.index(0, 0) model.delete_cur_item(model.index(0, 0, parent)) func.assert_called_once_with(['foo', 'bar'])
def test_count(counts): model = completionmodel.CompletionModel() for c in counts: cat = mock.Mock( spec=['rowCount', 'layoutChanged', 'layoutAboutToBeChanged']) cat.rowCount = mock.Mock(return_value=c, spec=[]) model.add_category(cat) assert model.count() == sum(counts)
def buffer(*, info=None): # pylint: disable=unused-argument """A model to complete on open tabs across all windows. Used for switching the buffer command. """ model = completionmodel.CompletionModel(column_widths=(6, 40, 54)) # return _buffer() return model
def other_buffer(*, info): """A model to complete on open tabs across all windows except the current. Used for the tab-take command. """ model = completionmodel.CompletionModel(column_widths=(6, 40, 54)) # return _buffer() return model
def customized_option(*, info): """A CompletionModel filled with set settings and their descriptions.""" model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) options = ((opt.name, opt.description, info.config.get_str(opt.name)) for opt, _value in info.config) model.add_category(listcategory.ListCategory("Customized options", options)) return model
def inspector_position(*, info): """A model for possible inspector positions.""" utils.unused(info) model = completionmodel.CompletionModel(column_widths=(100, 0, 0)) positions = [(e.name, ) for e in inspector.Position] category = listcategory.ListCategory("Position (optional)", positions) model.add_category(category) return model
def test_delete_cur_item_no_cat(): """Test completion_item_del with no selected category.""" callback = mock.Mock(spec=[]) model = completionmodel.CompletionModel() model.rowsAboutToBeRemoved.connect(callback) model.rowsRemoved.connect(callback) with pytest.raises(qtutils.QtValueError): model.delete_cur_item(QModelIndex()) callback.assert_not_called()
def _buffer(*, win_id_filter=lambda _win_id: True, add_win_id=True): """Helper to get the completion model for buffer/other_buffer. Args: win_id_filter: A filter function for window IDs to include. Should return True for all included windows. add_win_id: Whether to add the window ID to the completion items. """ def delete_buffer(data): """Close the selected tab.""" win_id, tab_index = data[0].split('/') tabbed_browser = objreg.get('tabbed-browser', scope='window', window=int(win_id)) tabbed_browser.on_tab_close_requested(int(tab_index) - 1) model = completionmodel.CompletionModel(column_widths=(6, 40, 54)) tabs_are_windows = config.val.tabs.tabs_are_windows # list storing all single-tabbed windows when tabs_are_windows windows = [] # type: typing.List[typing.Tuple[str, str, str]] for win_id in objreg.window_registry: if not win_id_filter(win_id): continue tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) if tabbed_browser.shutting_down: continue tabs = [] # type: typing.List[typing.Tuple[str, str, str]] for idx in range(tabbed_browser.widget.count()): tab = tabbed_browser.widget.widget(idx) tab_str = ("{}/{}".format(win_id, idx + 1) if add_win_id else str(idx + 1)) tabs.append((tab_str, tab.url().toDisplayString(), tabbed_browser.widget.page_title(idx))) if tabs_are_windows: windows += tabs else: title = str(win_id) if add_win_id else "Tabs" cat = listcategory.ListCategory(title, tabs, delete_func=delete_buffer, sort=False) model.add_category(cat) if tabs_are_windows: win = listcategory.ListCategory("Windows", windows, delete_func=delete_buffer, sort=False) model.add_category(win) return model
def test_set_model(completionview): """Ensure set_model actually sets the model and expands all categories.""" model = completionmodel.CompletionModel() for _i in range(3): model.add_category(listcategory.ListCategory('', [('foo', )])) completionview.set_model(model) assert completionview.model() is model for i in range(3): assert completionview.isExpanded(model.index(i, 0))
def _get_rules_completion(*args, info): tab = objreg.get('tab', scope='tab', window=info.win_id, tab='current') model = completionmodel.CompletionModel(column_widths=(100, )) entries = [("{:10}{:10}{}".format(action.name, res_type.name.lower(), dest), ) for dest, types in SEEN_REQUESTS.matrix_rules[tab.url().host()].items() for res_type, action in types.items()] cat = listcategory.ListCategory("Requests", entries) model.add_category(cat) return model
def test_completion_item_del_no_selection(completionview): """Test that completion_item_del with an invalid index.""" func = mock.Mock(spec=[]) model = completionmodel.CompletionModel() cat = listcategory.ListCategory('', [('foo', )], delete_func=func) model.add_category(cat) completionview.set_model(model) with pytest.raises(cmdutils.CommandError, match='No item selected!'): completionview.completion_item_del() func.assert_not_called()
def test_completion_item_del(completionview): """Test that completion_item_del invokes delete_cur_item in the model.""" func = mock.Mock(spec=[]) model = completionmodel.CompletionModel() cat = listcategory.ListCategory('', [('foo', 'bar')], delete_func=func) model.add_category(cat) completionview.set_model(model) completionview.completion_item_focus('next') completionview.completion_item_del() func.assert_called_once_with(['foo', 'bar'])
def session(*, info=None): # pylint: disable=unused-argument """A CompletionModel filled with session names.""" from qutebrowser.misc import sessions model = completionmodel.CompletionModel() try: sess = ((name, ) for name in sessions.session_manager.list_sessions() if not name.startswith('_')) model.add_category(listcategory.ListCategory("Sessions", sess)) except OSError: log.completion.exception("Failed to list sessions!") return model
def test_delete_cur_item_no_func(): callback = mock.Mock(spec=[]) model = completionmodel.CompletionModel() cat = listcategory.ListCategory('', [('foo', 'bar')], delete_func=None) model.rowsAboutToBeRemoved.connect(callback) model.rowsRemoved.connect(callback) model.add_category(cat) parent = model.index(0, 0) with pytest.raises(cmdexc.CommandError): model.delete_cur_item(model.index(0, 0, parent)) callback.assert_not_called()
def session(): """A CompletionModel filled with session names.""" model = completionmodel.CompletionModel() try: manager = objreg.get('session-manager') sessions = ((name, ) for name in manager.list_sessions() if not name.startswith('_')) model.add_category(listcategory.ListCategory("Sessions", sessions)) except OSError: log.completion.exception("Failed to list sessions!") return model
def test_completion_item_focus_no_model(which, completionview, qtbot): """Test that selectionChanged is not fired when the model is None. Validates #1812: help completion repeatedly completes """ with qtbot.assertNotEmitted(completionview.selection_changed): completionview.completion_item_focus(which) model = completionmodel.CompletionModel() completionview.set_model(model) completionview.set_model(None) with qtbot.assertNotEmitted(completionview.selection_changed): completionview.completion_item_focus(which)