1
0
mirror of https://github.com/go-task/task.git synced 2024-12-16 10:59:23 +02:00
task/vendor/mvdan.cc/sh/v3/expand/braces.go
2019-09-26 19:04:13 -03:00

86 lines
1.9 KiB
Go

// Copyright (c) 2018, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information
package expand
import (
"strconv"
"mvdan.cc/sh/v3/syntax"
)
// Braces performs brace expansion on a word, given that it contains any
// syntax.BraceExp parts. For example, the word with a brace expansion
// "foo{bar,baz}" will return two literal words, "foobar" and "foobaz".
//
// Note that the resulting words may share word parts.
func Braces(word *syntax.Word) []*syntax.Word {
var all []*syntax.Word
var left []syntax.WordPart
for i, wp := range word.Parts {
br, ok := wp.(*syntax.BraceExp)
if !ok {
left = append(left, wp.(syntax.WordPart))
continue
}
if br.Sequence {
var from, to int
if br.Chars {
from = int(br.Elems[0].Lit()[0])
to = int(br.Elems[1].Lit()[0])
} else {
from, _ = strconv.Atoi(br.Elems[0].Lit())
to, _ = strconv.Atoi(br.Elems[1].Lit())
}
upward := from <= to
incr := 1
if !upward {
incr = -1
}
if len(br.Elems) > 2 {
n, _ := strconv.Atoi(br.Elems[2].Lit())
if n != 0 && n > 0 == upward {
incr = n
}
}
n := from
for {
if upward && n > to {
break
}
if !upward && n < to {
break
}
next := *word
next.Parts = next.Parts[i+1:]
lit := &syntax.Lit{}
if br.Chars {
lit.Value = string(n)
} else {
lit.Value = strconv.Itoa(n)
}
next.Parts = append([]syntax.WordPart{lit}, next.Parts...)
exp := Braces(&next)
for _, w := range exp {
w.Parts = append(left, w.Parts...)
}
all = append(all, exp...)
n += incr
}
return all
}
for _, elem := range br.Elems {
next := *word
next.Parts = next.Parts[i+1:]
next.Parts = append(elem.Parts, next.Parts...)
exp := Braces(&next)
for _, w := range exp {
w.Parts = append(left, w.Parts...)
}
all = append(all, exp...)
}
return all
}
return []*syntax.Word{{Parts: left}}
}