Beispiel #1
0
func startCompletion(ed *Editor, k Key) *leReturn {
	c := &completion{}
	ctx, err := parse.Complete("<completion>", ed.line[:ed.dot])
	if err != nil {
		ed.pushTip("parser error")
		return nil
	}
	compound, start, err := peekCurrentCompound(ctx, ed.dot)
	if err != nil {
		ed.pushTip("cannot complete :(")
		return nil
	}
	switch ctx.Typ {
	case parse.CommandContext:
		// BUG(xiaq): When completing, CommandContext is not supported
		ed.pushTip("command context not yet supported :(")
	case parse.NewArgContext, parse.ArgContext:
		// BUG(xiaq): When completing, [New]ArgContext is treated like RedirFilenameContext
		fallthrough
	case parse.RedirFilenameContext:
		// BUG(xiaq): When completing, only plain expressions are supported
		names, err := fileNames(".")
		if err != nil {
			ed.pushTip(err.Error())
			return nil
		}
		c.start = start
		c.end = ed.dot
		// BUG(xiaq) When completing, completion.typ is always ItemBare
		c.typ = parse.ItemBare
		c.candidates = findCandidates(compound, names)
		if len(c.candidates) > 0 {
			// TODO(xiaq): Support completions other than filename completion
			for _, c := range c.candidates {
				c.attr = defaultLsColor.determineAttr(c.text)
			}
			ed.completion = c
			ed.mode = modeCompletion
		} else {
			ed.pushTip(fmt.Sprintf("No completion for %s", compound))
		}
	}
	return nil
}
Beispiel #2
0
func startCompletion(ed *Editor, k Key) *leReturn {
	c := &completion{}
	ctx, err := parse.Complete("<completion>", ed.line[:ed.dot])
	if err != nil {
		ed.pushTip("parser error: " + err.Error())
		return nil
	}
	compound, start, err := peekCurrentCompound(ctx, ed.dot)
	if err != nil {
		ed.pushTip("cannot complete: " + err.Error())
		return nil
	}

	var findAll func() ([]string, error)
	var makeCandidates func([]string) []*candidate

	switch ctx.Typ {
	case parse.CommandContext:
		// BUG(xiaq): When completing commands, only builtins are searched
		findAll = func() ([]string, error) {
			return builtins, nil
		}
		makeCandidates = func(all []string) (cands []*candidate) {
			return prefixMatchCandidates(compound, all)
		}
	case parse.NewArgContext, parse.ArgContext:
		// BUG(xiaq): When completing, [New]ArgContext is treated like RedirFilenameContext
		fallthrough
	case parse.RedirFilenameContext:
		// BUG(xiaq): File name completion does not deal with meta characters.
		// Assume that compound is an incomplete filename
		dir, file := path.Split(compound)
		findAll = func() ([]string, error) {
			if dir == "" {
				return fileNames(".")
			}
			return fileNames(dir)
		}
		makeCandidates = func(all []string) (cands []*candidate) {
			// Make candidates out of elements that match the file component.
			for _, s := range all {
				if strings.HasPrefix(s, file) {
					cand := newCandidate()
					cand.push(tokenPart{compound, false})
					cand.push(tokenPart{s[len(file):], true})
					cand.attr = defaultLsColor.determineAttr(cand.text)
					cands = append(cands, cand)
				}
			}
			return
		}
	}
	// BUG(xiaq): When completing, only plain expressions are supported
	all, err := findAll()
	if err != nil {
		ed.pushTip(err.Error())
		return nil
	}
	c.start = start
	c.end = ed.dot
	// BUG(xiaq) When completing, completion.typ is always ItemBare
	c.typ = parse.ItemBare
	c.candidates = makeCandidates(all)
	if len(c.candidates) > 0 {
		ed.completion = c
		ed.mode = modeCompletion
	} else {
		ed.pushTip(fmt.Sprintf("No completion for %s", compound))
	}
	return nil
}