github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/elvish/edit/completion/complete_variable.go (about)

     1  package completion
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/u-root/u-root/cmds/elvish/eval"
     7  	"github.com/u-root/u-root/cmds/elvish/parse"
     8  )
     9  
    10  type variableComplContext struct {
    11  	complContextCommon
    12  	ns, nsPart string
    13  }
    14  
    15  func (*variableComplContext) name() string { return "variable" }
    16  
    17  func findVariableComplContext(n parse.Node, _ pureEvaler) complContext {
    18  	primary := parse.GetPrimary(n)
    19  	if primary != nil && primary.Type == parse.Variable {
    20  		explode, nsPart, nameSeed := eval.SplitIncompleteVariableRef(primary.Value)
    21  		// Move past "$", "@" and "<ns>:".
    22  		begin := primary.Begin() + 1 + len(explode) + len(nsPart)
    23  		ns := nsPart
    24  		if len(ns) > 0 {
    25  			ns = ns[:len(ns)-1]
    26  		}
    27  		return &variableComplContext{
    28  			complContextCommon{nameSeed, parse.Bareword, begin, primary.End()},
    29  			ns, nsPart,
    30  		}
    31  	}
    32  	return nil
    33  }
    34  
    35  type evalerScopes interface {
    36  	EachVariableInTop(string, func(string))
    37  	EachNsInTop(func(string))
    38  }
    39  
    40  func (ctx *variableComplContext) generate(env *complEnv, ch chan<- rawCandidate) error {
    41  	complVariable(ctx.ns, ctx.nsPart, env.evaler, ch)
    42  	return nil
    43  }
    44  
    45  func complVariable(ctxNs, ctxNsPart string, ev evalerScopes, ch chan<- rawCandidate) {
    46  	ev.EachVariableInTop(ctxNs, func(varname string) {
    47  		ch <- noQuoteCandidate(varname)
    48  	})
    49  
    50  	ev.EachNsInTop(func(ns string) {
    51  		nsPart := ns + ":"
    52  		// This is to match namespaces that are "nested" under the current
    53  		// namespace.
    54  		if hasProperPrefix(nsPart, ctxNsPart) {
    55  			ch <- noQuoteCandidate(nsPart[len(ctxNsPart):])
    56  		}
    57  	})
    58  }
    59  
    60  func hasProperPrefix(s, p string) bool {
    61  	return len(s) > len(p) && strings.HasPrefix(s, p)
    62  }