From 1dedd398649679b99e8983b937500e56d5ef4b73 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Wed, 27 Jul 2022 11:52:50 +0200 Subject: [PATCH] Allow to unbind without specifying the lfun When unbinding a shortcut, it may happen that the exact definition of the request is not known. A typical example it Tab, which is bound to a complex command sequence. In this case it is convenient to use the syntax \unbind "Tab" "*" To make this word, the special "*" value is translated to the FuncRequest::unknown lfun and this value is considered specially in several places. --- src/KeyMap.cpp | 52 +++++++++++++++++++---------------- src/frontends/qt/GuiPrefs.cpp | 10 +++---- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/KeyMap.cpp b/src/KeyMap.cpp index f469da5c44..b4a87d227c 100644 --- a/src/KeyMap.cpp +++ b/src/KeyMap.cpp @@ -160,29 +160,30 @@ void KeyMap::unbind(KeySequence * seq, FuncRequest const & func, unsigned int r) KeyModifier const mod2 = seq->modifiers[r].second; // check if key is already there + vector removes; Table::iterator end = table.end(); - Table::iterator remove = end; for (Table::iterator it = table.begin(); it != end; ++it) { if (code == it->code && mod1 == it->mod.first && mod2 == it->mod.second) { // remove if (r + 1 == seq->length()) { - if (it->func == func) { - remove = it; + if (it->func == func || func == FuncRequest::unknown) { + removes.push_back(it); if (it->prefixes) it->prefixes.reset(); } } else if (it->prefixes) { it->prefixes->unbind(seq, func, r + 1); if (it->prefixes->empty()) - remove = it; + removes.push_back(it); return; } } } - if (remove != end) - table.erase(remove); + + for (unsigned i = removes.size(); i > 0; --i) + table.erase(removes[i-1]); } @@ -333,7 +334,7 @@ KeyMap::ReturnValues KeyMap::readWithoutConv(FileName const & bind_file, KeyMap string cmd = lexrc.getString(); FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action() == LFUN_UNKNOWN_ACTION) { + if (func == FuncRequest::unknown) { lexrc.printError("BN_BIND: Unknown LyX function `$$Token'"); error = true; break; @@ -357,13 +358,16 @@ KeyMap::ReturnValues KeyMap::readWithoutConv(FileName const & bind_file, KeyMap break; } string cmd = lexrc.getString(); - - FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action() == LFUN_UNKNOWN_ACTION) { - lexrc.printError("BN_UNBIND: Unknown LyX" - " function `$$Token'"); - error = true; - break; + FuncRequest func; + if (cmd == "*") + func = FuncRequest::unknown; + else { + func = lyxaction.lookupFunc(cmd); + if (func == FuncRequest::unknown) { + lexrc.printError("BN_UNBIND: Unknown LyX function `$$Token'"); + error = true; + break; + } } if (unbind_map) @@ -409,17 +413,17 @@ void KeyMap::write(string const & bind_file, bool append, bool unbind) const << "Format " << LFUN_FORMAT << "\n\n"; string tag = unbind ? "\\unbind" : "\\bind"; - BindingList const list = listBindings(false); - BindingList::const_iterator it = list.begin(); - BindingList::const_iterator it_end = list.end(); - for (; it != it_end; ++it) { - FuncCode action = it->request.action(); - string arg = to_utf8(it->request.argument()); - - string const cmd = lyxaction.getActionName(action) - + (arg.empty() ? string() : " " + arg) ; + for (auto const & bnd : listBindings(false)) { + FuncCode const action = bnd.request.action(); + string const arg = to_utf8(bnd.request.argument()); + + string cmd; + if (unbind && bnd.request == FuncRequest::unknown) + cmd = "*"; + else + cmd = lyxaction.getActionName(action) + (arg.empty() ? string() : " " + arg); os << tag << " \"" - << to_utf8(it->sequence.print(KeySequence::BindFile)) + << to_utf8(bnd.sequence.print(KeySequence::BindFile)) << "\" " << Lexer::quoteString(cmd) << "\n"; } diff --git a/src/frontends/qt/GuiPrefs.cpp b/src/frontends/qt/GuiPrefs.cpp index 2b6b9cd1cb..31da12936f 100644 --- a/src/frontends/qt/GuiPrefs.cpp +++ b/src/frontends/qt/GuiPrefs.cpp @@ -3087,10 +3087,10 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun, QTreeWidgetItem * newItem = nullptr; // for unbind items, try to find an existing item in the system bind list if (tag == KeyMap::UserUnbind) { - QList const items = shortcutsTW->findItems(lfun_name, - Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0); + QList const items = shortcutsTW->findItems(shortcut, + Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1); for (auto const & item : items) { - if (item->text(1) == shortcut) { + if (item->text(0) == lfun_name || lfun == FuncRequest::unknown) { newItem = item; break; } @@ -3125,10 +3125,10 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun, // this should not happen newItem = new QTreeWidgetItem(shortcutsTW); } + newItem->setText(0, lfun_name); + newItem->setText(1, shortcut); } - newItem->setText(0, lfun_name); - newItem->setText(1, shortcut); // record BindFile representation to recover KeySequence when needed. newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile))); setItemType(newItem, tag); -- 2.39.2