elvish/eval/glob.go

111 lines
2.2 KiB
Go
Raw Normal View History

2016-02-19 05:52:05 +08:00
package eval
import (
"errors"
2016-02-19 05:52:05 +08:00
"fmt"
"github.com/elves/elvish/glob"
)
// GlobPattern is en ephemeral Value generated when evaluating tilde and
// wildcards.
type GlobPattern glob.Pattern
var (
_ Value = GlobPattern{}
_ Indexer = GlobPattern{}
)
var (
ErrMustFollowWildcard = errors.New("must follow wildcard")
ErrModifierMustBeString = errors.New("modifier must be string")
)
2016-02-19 05:52:05 +08:00
func (GlobPattern) Kind() string {
return "glob-pattern"
}
func (gp GlobPattern) Repr(int) string {
2016-02-19 05:52:05 +08:00
return fmt.Sprintf("<GlobPattern%v>", gp)
}
func (gp GlobPattern) Index(modifiers []Value) []Value {
for _, value := range modifiers {
modifier, ok := value.(String)
if !ok {
throw(ErrModifierMustBeString)
}
switch string(modifier) {
case "a", "all":
if len(gp.Segments) == 0 {
throw(ErrBadGlobPattern)
}
2017-02-03 03:15:42 +08:00
if !glob.IsWild(gp.Segments[len(gp.Segments)-1]) {
throw(ErrMustFollowWildcard)
}
2017-02-03 03:15:42 +08:00
gp.Segments[len(gp.Segments)-1] = glob.Wild{
gp.Segments[len(gp.Segments)-1].(glob.Wild).Type, true,
}
default:
throw(fmt.Errorf("unknown modifier %s", modifier.Repr(NoPretty)))
}
}
return []Value{gp}
}
2016-02-19 05:52:05 +08:00
func (gp *GlobPattern) append(segs ...glob.Segment) {
gp.Segments = append(gp.Segments, segs...)
}
func wildcardToSegment(s string) glob.Segment {
switch s {
case "*":
2017-02-03 03:15:42 +08:00
return glob.Wild{glob.Star, false}
2016-02-19 05:52:05 +08:00
case "**":
2017-02-03 03:15:42 +08:00
return glob.Wild{glob.StarStar, false}
2016-02-19 05:52:05 +08:00
case "?":
2017-02-03 03:15:42 +08:00
return glob.Wild{glob.Question, false}
2016-02-19 05:52:05 +08:00
default:
throw(fmt.Errorf("bad wildcard: %q", s))
panic("unreachable")
}
}
func stringToSegments(s string) []glob.Segment {
segs := []glob.Segment{}
for i := 0; i < len(s); {
j := i
for ; j < len(s) && s[j] != '/'; j++ {
}
if j > i {
2017-02-03 03:15:42 +08:00
segs = append(segs, glob.Literal{s[i:j]})
2016-02-19 05:52:05 +08:00
}
if j < len(s) {
for ; j < len(s) && s[j] == '/'; j++ {
}
2017-02-03 03:15:42 +08:00
segs = append(segs, glob.Slash{})
2016-02-19 05:52:05 +08:00
i = j
} else {
break
}
}
return segs
}
2016-06-29 05:08:15 +08:00
func doGlob(gp GlobPattern, abort <-chan struct{}) []Value {
2017-02-03 05:13:08 +08:00
vs := make([]Value, 0)
2016-06-29 05:08:15 +08:00
if !glob.Pattern(gp).Glob(func(name string) bool {
select {
case <-abort:
Logger.Println("glob aborted")
return false
default:
}
2017-02-03 05:00:48 +08:00
vs = append(vs, String(name))
2016-06-29 05:08:15 +08:00
return true
}) {
throw(ErrInterrupted)
}
2016-02-19 05:52:05 +08:00
return vs
}