func (t *TabComplete) set(stringTokens []string, items []string, whitespaceEnds bool) {
	t.items = items
	t.cursor = t.Len()
	if whitespaceEnds {
		t.base = strings.Join(stringTokens, "")
	} else if len(stringTokens) > 0 {
		maxLen := len(stringTokens) - 1
		t.original = stringTokens[maxLen]
		t.base = strings.Join(stringTokens[:maxLen], "")
	}
}
set stores the tabcomplete configuration.
package tabcomplete
import (
	"fmt"
	"strings"
	"github.com/ambientsound/visp/api"
	"github.com/ambientsound/visp/commands"
	"github.com/ambientsound/visp/input/lexer"
	"github.com/ambientsound/visp/parser"
	"github.com/ambientsound/visp/utils"
)
type TabComplete struct {
	api      api.API
	base     string    
	cursor   int       
	items    []string  
	original string    
	source   string    
}
func New(source string, a api.API) *TabComplete {
	return &TabComplete{
		api:    a,
		source: source,
	}
}
func (t *TabComplete) Len() int {
	return len(t.items)
}
func (t *TabComplete) Active() bool {
	return t.Len() > 0
}
func (t *TabComplete) Scan() (string, error) {
	if !t.Active() {
		if err := t.init(); err != nil {
			return "", err
		}
	}
	return t.next(), nil
}
func (t *TabComplete) next() string {
	if t.cursor >= t.Len() {
		t.cursor = 0
	}
	s := t.base + t.items[t.cursor]
	t.cursor++
	return s
}
func (t *TabComplete) init() error {
	reader := strings.NewReader(t.source)
	scanner := lexer.NewScanner(reader)
	parser := parser.New(scanner)
	tok, verb := parser.ScanIgnoreWhitespace()
	switch tok {
	case lexer.TokenEnd:
		items := utils.TokenFilter("", commands.Keys())
		t.set([]string{}, items, false)
		return nil
	case lexer.TokenIdentifier:
	default:
		return fmt.Errorf("Tab completing verb '%s', but this is not an identifier", verb)
	}
	cmd := commands.New(verb, t.api)
	if cmd == nil {
		tok, _ := parser.Scan()
		if tok != lexer.TokenEnd {
			return fmt.Errorf("No command '%s', cannot autocomplete", verb)
		}
		items := utils.TokenFilter(verb, commands.Keys())
		if len(items) == 0 {
			return fmt.Errorf("No tab complete candidates")
		}
		t.set([]string{}, items, false)
		return nil
	}
	cmd.SetScanner(scanner)
	cmd.Parse()
	tokens := cmd.Scanned()
	if len(tokens) < 2 {
		return fmt.Errorf("Not enough data to tab complete")
	}
	items := cmd.TabComplete()
	if len(items) == 0 {
		return fmt.Errorf("No tab complete candidates")
	}
	lastToken := lexer.TokenEnd
	stringTokens := make([]string, 1)
	stringTokens[0] = verb
	for i := range tokens {
		if tokens[i].Tok == lexer.TokenEnd {
			break
		}
		lastToken = tokens[i].Tok
		stringTokens = append(stringTokens, tokens[i].Lit)
	}
	whitespaceEnds := lastToken == lexer.TokenWhitespace
	t.set(stringTokens, items, whitespaceEnds)
	return nil
}