mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-15 11:57:55 +08:00
edit: Factor out filtering stage of completion.
This commit is contained in:
parent
2abf1cf358
commit
b64227e498
|
@ -67,29 +67,8 @@ func evalFormPure(form *parse.Form, seed string, seedBegin int, ev pureEvaler) [
|
|||
|
||||
// To complete an argument, delegate the actual completion work to a suitable
|
||||
// complContext.
|
||||
func (ctx *argComplContext) complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error) {
|
||||
rawCands := make(chan rawCandidate)
|
||||
collectErr := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
defer func() {
|
||||
close(rawCands)
|
||||
collectErr <- err
|
||||
}()
|
||||
|
||||
err = completeArg(ctx.words, ev, rawCands)
|
||||
}()
|
||||
|
||||
cands, err := ev.Editor.(*Editor).filterAndCookCandidates(
|
||||
ev, matcher, ctx.seed, rawCands, ctx.quoting)
|
||||
if ce := <-collectErr; ce != nil {
|
||||
return nil, ce
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &complSpec{ctx.begin, ctx.end, cands}, nil
|
||||
func (ctx *argComplContext) generate(ev *eval.Evaler, ch chan<- rawCandidate) error {
|
||||
return completeArg(ctx.words, ev, ch)
|
||||
}
|
||||
|
||||
// TODO: getStyle does redundant stats.
|
||||
|
|
|
@ -55,28 +55,8 @@ func findCommandComplContext(n parse.Node, ev pureEvaler) complContext {
|
|||
|
||||
func (*commandComplContext) name() string { return "command" }
|
||||
|
||||
func (ctx *commandComplContext) complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error) {
|
||||
rawCands := make(chan rawCandidate)
|
||||
collectErr := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
defer func() {
|
||||
close(rawCands)
|
||||
collectErr <- err
|
||||
}()
|
||||
|
||||
err = complFormHeadInner(ctx.seed, ev, rawCands)
|
||||
}()
|
||||
|
||||
cands, err := ev.Editor.(*Editor).filterAndCookCandidates(
|
||||
ev, matcher, ctx.seed, rawCands, ctx.quoting)
|
||||
if ce := <-collectErr; ce != nil {
|
||||
return nil, ce
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &complSpec{ctx.begin, ctx.end, cands}, nil
|
||||
func (ctx *commandComplContext) generate(ev *eval.Evaler, ch chan<- rawCandidate) error {
|
||||
return complFormHeadInner(ctx.seed, ev, ch)
|
||||
}
|
||||
|
||||
func complFormHeadInner(head string, ev *eval.Evaler, rawCands chan<- rawCandidate) error {
|
||||
|
|
|
@ -79,31 +79,19 @@ func findIndexComplContext(n parse.Node, ev pureEvaler) complContext {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ctx *indexComplContext) complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error) {
|
||||
func (ctx *indexComplContext) generate(ev *eval.Evaler, ch chan<- rawCandidate) error {
|
||||
m, ok := ctx.indexee.(eval.IterateKeyer)
|
||||
if !ok {
|
||||
return nil, errCannotIterateKey
|
||||
return errCannotIterateKey
|
||||
}
|
||||
|
||||
rawCands := make(chan rawCandidate)
|
||||
go func() {
|
||||
defer close(rawCands)
|
||||
|
||||
complIndexInner(m, rawCands)
|
||||
}()
|
||||
|
||||
cands, err := ev.Editor.(*Editor).filterAndCookCandidates(
|
||||
ev, matcher, ctx.seed, rawCands, ctx.quoting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &complSpec{ctx.begin, ctx.end, cands}, nil
|
||||
complIndexInner(m, ch)
|
||||
return nil
|
||||
}
|
||||
|
||||
func complIndexInner(m eval.IterateKeyer, rawCands chan rawCandidate) {
|
||||
func complIndexInner(m eval.IterateKeyer, ch chan<- rawCandidate) {
|
||||
m.IterateKey(func(v eval.Value) bool {
|
||||
if keyv, ok := v.(eval.String); ok {
|
||||
rawCands <- plainCandidate(keyv)
|
||||
ch <- plainCandidate(keyv)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
|
|
@ -29,28 +29,6 @@ func findRedirComplContext(n parse.Node, ev pureEvaler) complContext {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ctx *redirComplContext) complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error) {
|
||||
|
||||
rawCands := make(chan rawCandidate)
|
||||
collectErr := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
defer func() {
|
||||
close(rawCands)
|
||||
collectErr <- err
|
||||
}()
|
||||
|
||||
err = complFilenameInner(ctx.seed, false, rawCands)
|
||||
}()
|
||||
|
||||
cands, err := ev.Editor.(*Editor).filterAndCookCandidates(
|
||||
ev, matcher, ctx.seed, rawCands, ctx.quoting)
|
||||
if ce := <-collectErr; ce != nil {
|
||||
return nil, ce
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &complSpec{ctx.begin, ctx.end, cands}, nil
|
||||
func (ctx *redirComplContext) generate(ev *eval.Evaler, ch chan<- rawCandidate) error {
|
||||
return complFilenameInner(ctx.seed, false, ch)
|
||||
}
|
||||
|
|
|
@ -34,42 +34,31 @@ func findVariableComplContext(n parse.Node, _ pureEvaler) complContext {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ctx *variableComplContext) complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error) {
|
||||
rawCands := make(chan rawCandidate)
|
||||
go func() {
|
||||
defer close(rawCands)
|
||||
func (ctx *variableComplContext) generate(ev *eval.Evaler, ch chan<- rawCandidate) error {
|
||||
|
||||
// Collect matching variables.
|
||||
iterateVariables(ev, ctx.ns, func(varname string) {
|
||||
rawCands <- noQuoteCandidate(varname)
|
||||
})
|
||||
// Collect matching variables.
|
||||
iterateVariables(ev, ctx.ns, func(varname string) {
|
||||
ch <- noQuoteCandidate(varname)
|
||||
})
|
||||
|
||||
seenMod := func(mod string) {
|
||||
modNsPart := mod + ":"
|
||||
// This is to match namespaces that are "nested" under the current
|
||||
// namespace.
|
||||
if hasProperPrefix(modNsPart, ctx.nsPart) {
|
||||
rawCands <- noQuoteCandidate(modNsPart[len(ctx.nsPart):])
|
||||
}
|
||||
seenMod := func(mod string) {
|
||||
modNsPart := mod + ":"
|
||||
// This is to match namespaces that are "nested" under the current
|
||||
// namespace.
|
||||
if hasProperPrefix(modNsPart, ctx.nsPart) {
|
||||
ch <- noQuoteCandidate(modNsPart[len(ctx.nsPart):])
|
||||
}
|
||||
|
||||
// Collect namespace prefixes.
|
||||
// TODO Support non-module namespaces.
|
||||
for mod := range ev.Global.Uses {
|
||||
seenMod(mod)
|
||||
}
|
||||
for mod := range ev.Builtin.Uses {
|
||||
seenMod(mod)
|
||||
}
|
||||
}()
|
||||
|
||||
cands, err := ev.Editor.(*Editor).filterAndCookCandidates(ev, matcher, ctx.seed,
|
||||
rawCands, parse.Bareword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &complSpec{ctx.begin, ctx.end, cands}, nil
|
||||
// Collect namespace prefixes.
|
||||
// TODO Support non-module namespaces.
|
||||
for mod := range ev.Global.Uses {
|
||||
seenMod(mod)
|
||||
}
|
||||
for mod := range ev.Builtin.Uses {
|
||||
seenMod(mod)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasProperPrefix(s, p string) bool {
|
||||
|
|
|
@ -34,12 +34,13 @@ package edit
|
|||
import (
|
||||
"github.com/elves/elvish/eval"
|
||||
"github.com/elves/elvish/parse"
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
type complContext interface {
|
||||
name() string
|
||||
common() *complContextCommon
|
||||
complete(ev *eval.Evaler, matcher eval.CallableValue) (*complSpec, error)
|
||||
generate(*eval.Evaler, chan<- rawCandidate) error
|
||||
}
|
||||
|
||||
type complContextCommon struct {
|
||||
|
@ -83,19 +84,31 @@ var complContextFinders = []complContextFinder{
|
|||
func complete(n parse.Node, ev *eval.Evaler) (string, *complSpec, error) {
|
||||
ed := ev.Editor.(*Editor)
|
||||
for _, finder := range complContextFinders {
|
||||
complContext := finder(n, ev)
|
||||
if complContext == nil {
|
||||
ctx := finder(n, ev)
|
||||
if ctx == nil {
|
||||
continue
|
||||
}
|
||||
name := complContext.name()
|
||||
name := ctx.name()
|
||||
ctxCommon := ctx.common()
|
||||
|
||||
matcher, ok := ed.lookupMatcher(name)
|
||||
if !ok {
|
||||
return name, nil, errMatcherMustBeFn
|
||||
}
|
||||
|
||||
ctx, err := complContext.complete(ev, matcher)
|
||||
return name, ctx, err
|
||||
chanRawCandidate := make(chan rawCandidate)
|
||||
chanErrGenerate := make(chan error)
|
||||
go func() {
|
||||
err := ctx.generate(ev, chanRawCandidate)
|
||||
close(chanRawCandidate)
|
||||
chanErrGenerate <- err
|
||||
}()
|
||||
|
||||
candidates, errFilter := ev.Editor.(*Editor).filterAndCookCandidates(
|
||||
ev, matcher, ctxCommon.seed, chanRawCandidate, ctxCommon.quoting)
|
||||
spec := &complSpec{ctxCommon.begin, ctxCommon.end, candidates}
|
||||
return name, spec, util.Errors(<-chanErrGenerate, errFilter)
|
||||
|
||||
}
|
||||
return "", nil, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user