Check if the command entered after : is the abbreviation of an existing
command and run that instead. This is only done if there is no complete
name matching first-hand and if the abbreviation matches just one
command.
Signed-off-by: Vitaly Ovchinnikov <v@postbox.nz>
---
The reason behind the patch is that I want to exit aerc with :q -
something that I used to do with vim.
I tried making a command alias (like: quit/exit/q), but this appears in
the completion list which is not a good idea.
I also tried adding a binding: :q = :quit, but it crashes aerc when
pressed. Stack overflow? Didn't check it too deep...
The final implementation runs through all the commands sets and checks
if there is a partial or full match there. If there is no full match and
there is a single partial match - the command abbreviation is replaced
with the full command name. Then the command is processed as usual.
- v1 - initial version
- v2 - commit message refined
- v3 - multiple command sets support
- v3 - re-sending as the build failed for other reasons
main.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/main.go b/main.go
index 4705c43..e0c4f89 100644
--- a/main.go
+++ b/main.go
@@ -62,11 +62,68 @@ func getCommands(selected libui.Drawable) []*commands.Commands {
}
}
+// gets the command as an array of items and the array of command sets
+// checks the first element of the command array against the command names in all sets
+// if the first element matches one of the command names directly - does nothing
+// if the first element is an abbreviation of one and only one command name in the sets
+// it replaces the first element with the full command name
+// if it matches nothing - does nothing, too
+func expandAbbreviations(cmd []string, sets []*commands.Commands) []string {
+ if len(cmd) == 0 {
+ return cmd
+ }
+
+ name := cmd[0]
+ candidate := ""
+ for _, set := range sets {
+ // do we have a direct match?
+ if set.ByName(name) != nil {
+ if candidate != "" {
+ log.Tracef("found perfectly matched command '%s', ignoring the previous candidate '%s'", name, candidate)
+ }
+ return cmd
+ }
+
+ // check for partial
+ for _, n := range set.Names() {
+ if !strings.HasPrefix(n, name) {
+ continue
+ }
+
+ log.Tracef("command '%s' matches abbreviation '%s'", n, name)
+
+ // ok, we have a partial match
+ // do we have one already?
+ if candidate != "" {
+ log.Tracef("that's the second command matching that abbreviation, we cannot process that")
+ // we have more than one command partially matching the input
+ // we can't expand such an abbreviation, so return the command as is
+ // so it can raise an error later
+ return cmd
+ }
+
+ candidate = n
+ }
+ }
+
+ // as we are here, we could have a command name matching our partial name in `cmd`
+ // in that case we replace the name in `cmd` with the full name, otherwise we simply
+ // return `cmd` as is
+
+ if candidate != "" {
+ log.Tracef("expanding command abbreviation '%s' to '%s'", name, candidate)
+ cmd[0] = candidate
+ }
+
+ return cmd
+}
+
func execCommand(
aerc *widgets.Aerc, ui *libui.UI, cmd []string,
acct *config.AccountConfig, msg *models.MessageInfo,
) error {
cmds := getCommands(aerc.SelectedTabContent())
+ cmd = expandAbbreviations(cmd, cmds) // :q -> :quit
for i, set := range cmds {
err := set.ExecuteCommand(aerc, cmd, acct, msg)
if err != nil {
--
2.39.2 (Apple Git-143)
On Sun Sep 17, 2023 at 22:06, Vitaly Ovchinnikov wrote:
> Check if the command entered after : is the abbreviation of an existing
> command and run that instead. This is only done if there is no complete
> name matching first-hand and if the abbreviation matches just one
> command.
>
> Signed-off-by: Vitaly Ovchinnikov <v@postbox.nz>
> ---
I don't think I sent it yet:
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
--
+36305425054
bence.ferdinandy.com
Bence Ferdinandy, Sep 18, 2023 at 21:20:
>
> On Sun Sep 17, 2023 at 22:06, Vitaly Ovchinnikov wrote:
> > Check if the command entered after : is the abbreviation of an existing
> > command and run that instead. This is only done if there is no complete
> > name matching first-hand and if the abbreviation matches just one
> > command.
> >
> > Signed-off-by: Vitaly Ovchinnikov <v@postbox.nz>
> > ---
>
> I don't think I sent it yet:
>
> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
Acked-by: Robin-Jarry <robin@jarry.cc>
Applied after removing debug logging and rewording comments. Thanks!