Unverified Commit f93c53c5 authored by Kevin Lyda's avatar Kevin Lyda
Browse files

Add completer

parent 0dd6536b
Loading
Loading
Loading
Loading

dclish/completer.go

0 → 100644
+81 −0
Original line number Diff line number Diff line
package dclish

import (
	"strings"
	"unicode"
)

// Completer command completer type.
type Completer struct {
	commands []string
	flags    map[string][]string
}

// NewCompleter creates a new completer.
func NewCompleter(commands Commands) Completer {
	comps := []string{}
	flags := map[string][]string{}
	for c := range commands {
		comps = append(comps, c)
		if len(commands[c].Commands) > 0 {
			subcommands := commands[c].Commands
			for subc := range subcommands {
				fullc := c + " " + subc
				comps = append(comps, fullc)
				flags[fullc] = []string{}
				if subcommands[subc].Flags != nil {
					for f := range subcommands[subc].Flags {
						flags[fullc] = append(flags[fullc], f)
					}
				}
			}
		}
		flags[c] = []string{}
		if commands[c].Flags != nil {
			for f := range commands[c].Flags {
				flags[c] = append(flags[c], f)
			}
		}
	}
	return Completer{
		commands: comps,
		flags:    flags,
	}
}

// Do return a list of possible completions.
func (c Completer) Do(line []rune, pos int) ([][]rune, int) {
	// Nothing typed in.
	if pos == 0 {
		newline := make([][]rune, len(c.commands))
		for i := range c.commands {
			newline[i] = []rune(c.commands[i])
		}
		return newline, pos
	}

	// Command partially typed in.
	newline := [][]rune{}
	cmd := strings.ToUpper(string(line[0:pos]))
	lower := false
	if unicode.IsLower(line[0]) {
		lower = true
	}
	for i := range c.commands {
		if strings.HasPrefix(c.commands[i], cmd) {
			rest := strings.Replace(c.commands[i], cmd, "", 1)
			if lower {
				newline = append(newline, []rune(strings.ToLower(rest)))
			} else {
				newline = append(newline, []rune(rest))
			}
		}
	}
	if len(newline) > 0 {
		return newline, pos
	}

	// Command completely typed in.
	// TODO: figure out flags.
	return newline, pos
}
+5 −0
Original line number Diff line number Diff line
@@ -10,6 +10,10 @@ import (
// ActionFunc is the function that a command runs.
type ActionFunc func(*Command) error

// CompleterFunc is a function to provide completions for arguments for
// a given command.
type CompleterFunc func() []string

// Flag is a flag for a command.
type Flag struct {
	OptArg      bool
@@ -30,6 +34,7 @@ type Command struct {
	MinArgs     int
	Commands    Commands
	Action      ActionFunc
	Completer   CompleterFunc
	Description string
}

+5 −3
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import (
	"strings"
	"unicode"

	"git.lyda.ie/kevin/bulletin/dclish"
	"git.lyda.ie/kevin/bulletin/this"
	"github.com/adrg/xdg"
	"github.com/chzyer/readline"
@@ -15,6 +16,7 @@ import (

// Loop is the main event loop.
func Loop() error {
	completer := dclish.NewCompleter(commands)
	histdir := path.Join(xdg.ConfigHome, "BULLETIN")
	os.MkdirAll(histdir, 0700)
	histfile := path.Join(histdir, fmt.Sprintf("%s.history", this.User.Login))
@@ -22,7 +24,7 @@ func Loop() error {
		&readline.Config{
			Prompt:            "BULLETIN> ",
			HistoryFile:       histfile,
			// TODO: AutoComplete:    completer,
			AutoComplete:      completer,
			InterruptPrompt:   "^C",
			EOFPrompt:         "EXIT",
			HistorySearchFold: true,