about summary refs log tree commit diff stats
path: root/commands/commands.go
diff options
context:
space:
mode:
authorGregory Mullen <greg@cmdline.org>2019-06-27 10:33:11 -0700
committerDrew DeVault <sir@cmpwn.com>2019-06-29 14:24:19 -0400
commit2a0961701c4cabecc53d134ed1782e5612e64580 (patch)
tree57952ac82fb7104113ca7fc0e25dc3d225f77ea7 /commands/commands.go
parent177651bddab145c8a56cdfeb0d57b5fd95a6d0e2 (diff)
downloadaerc-2a0961701c4cabecc53d134ed1782e5612e64580.tar.gz
Implement basic tab completion support
Tab completion currently only works on commands. Contextual completion
will be added in the future.
Diffstat (limited to 'commands/commands.go')
-rw-r--r--commands/commands.go78
1 files changed, 69 insertions, 9 deletions
diff --git a/commands/commands.go b/commands/commands.go
index 04462d2..8d50b41 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -2,27 +2,47 @@ package commands
 
 import (
 	"errors"
+	"strings"
 
 	"github.com/google/shlex"
 
 	"git.sr.ht/~sircmpwn/aerc/widgets"
 )
 
-type AercCommand func(aerc *widgets.Aerc, args []string) error
+type Command interface {
+	Aliases() []string
+	Execute(*widgets.Aerc, []string) error
+	Complete(*widgets.Aerc, []string) []string
+}
 
-type Commands map[string]AercCommand
+type Commands map[string]Command
 
 func NewCommands() *Commands {
-	cmds := Commands(make(map[string]AercCommand))
+	cmds := Commands(make(map[string]Command))
 	return &cmds
 }
 
-func (cmds *Commands) dict() map[string]AercCommand {
-	return map[string]AercCommand(*cmds)
+func (cmds *Commands) dict() map[string]Command {
+	return map[string]Command(*cmds)
 }
 
-func (cmds *Commands) Register(name string, cmd AercCommand) {
-	cmds.dict()[name] = cmd
+func (cmds *Commands) Names() []string {
+	names := make([]string, 0)
+
+	for k := range cmds.dict() {
+		names = append(names, k)
+	}
+	return names
+}
+
+func (cmds *Commands) Register(cmd Command) {
+	// TODO enforce unique aliases, until then, duplicate each
+	if len(cmd.Aliases()) < 1 {
+		return
+	}
+	for _, alias := range cmd.Aliases() {
+		cmds.dict()[alias] = cmd
+	}
 }
 
 type NoSuchCommand string
@@ -43,8 +63,48 @@ func (cmds *Commands) ExecuteCommand(aerc *widgets.Aerc, cmd string) error {
 	if len(args) == 0 {
 		return errors.New("Expected a command.")
 	}
-	if fn, ok := cmds.dict()[args[0]]; ok {
-		return fn(aerc, args)
+	if cmd, ok := cmds.dict()[args[0]]; ok {
+		return cmd.Execute(aerc, args)
 	}
 	return NoSuchCommand(args[0])
 }
+
+func (cmds *Commands) GetCompletions(aerc *widgets.Aerc, cmd string) []string {
+	args, err := shlex.Split(cmd)
+	if err != nil {
+		return nil
+	}
+
+	if len(args) == 0 {
+		return nil
+	}
+
+	if len(args) > 1 {
+		if cmd, ok := cmds.dict()[args[0]]; ok {
+			completions := cmd.Complete(aerc, args[1:])
+			if completions != nil && len(completions) == 0 {
+				return nil
+			}
+
+			options := make([]string, 0)
+			for _, option := range completions {
+				options = append(options, args[0]+" "+option)
+			}
+			return options
+		}
+		return nil
+	}
+
+	names := cmds.Names()
+	options := make([]string, 0)
+	for _, name := range names {
+		if strings.HasPrefix(name, args[0]) {
+			options = append(options, name)
+		}
+	}
+
+	if len(options) > 0 {
+		return options
+	}
+	return nil
+}