Detect when one tries to bind a lfun to a prefix of longer commands

Change KeyMap::getBinding to return FuncRequest::prefix in this case.

Add handling of this case in PrefShortcuts::validateNewShortcut.

What does not seem to work is that if, for example, accent-acute is
bound to M-s (which is a prefix for size-related bindings), and then
the binding is removed, the functions are not visibly restored.

Part of bug #10131.
This commit is contained in:
Jean-Marc Lasgouttes 2022-12-09 14:45:14 +01:00
parent d59046512c
commit c8c589353a
3 changed files with 21 additions and 3 deletions

View File

@ -203,7 +203,7 @@ FuncRequest KeyMap::getBinding(KeySequence const & seq, unsigned int r)
&& mod1 == it->mod.first
&& mod2 == it->mod.second) {
if (r + 1 == seq.length())
return it->func;
return (it->prefixes) ? FuncRequest::prefix : it->func;
else if (it->prefixes)
return it->prefixes->getBinding(seq, r + 1);
}

View File

@ -65,8 +65,9 @@ public:
unsigned int r = 0);
/// returns the function bound to this key sequence, or
/// FuncRequest::unknown if no binding exists for it.
/// returns the function bound to this key sequence, or:
/// * FuncRequest::unknown if no binding exists for it;
/// * FuncRequest::prefix if this is the start of longer keysequences
/// @param r an internal recursion counter
// FIXME Surely there's a better way to do that?
FuncRequest getBinding(KeySequence const & seq, unsigned int r = 0);

View File

@ -3408,6 +3408,23 @@ bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
// nothing to change
return false;
// Check whether the key sequence is a prefix for other shortcuts.
if (oldBinding == FuncRequest::prefix) {
docstring const new_action_string = makeCmdString(func);
docstring const text = bformat(_("Shortcut `%1$s' is already a prefix for other commands.\n"
"Are you sure you want to unbind these commands and bind it to %2$s?"),
k.print(KeySequence::ForGui), new_action_string);
int ret = Alert::prompt(_("Redefine shortcut?"),
text, 0, 1, _("&Redefine"), _("&Cancel"));
if (ret != 0)
return false;
QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchRecursive), 1);
deactivateShortcuts(items);
return true;
}
// make sure this key isn't already bound---and, if so, prompt user
// (exclude the lfun the user already wants to modify)
docstring const action_string = makeCmdString(oldBinding);