mirror of
https://github.com/go-task/task.git
synced 2026-06-25 13:46:13 +00:00
106
vendor/github.com/mvdan/sh/interp/interp.go
generated
vendored
106
vendor/github.com/mvdan/sh/interp/interp.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -97,7 +98,6 @@ func (r *Runner) varInd(v varValue, e syntax.ArithmExpr) string {
|
||||
return x
|
||||
}
|
||||
case []string:
|
||||
// TODO: @ between double quotes
|
||||
if w, ok := e.(*syntax.Word); ok {
|
||||
if lit, ok := w.Parts[0].(*syntax.Lit); ok {
|
||||
switch lit.Value {
|
||||
@@ -224,10 +224,43 @@ func (r *Runner) errf(format string, a ...interface{}) {
|
||||
fmt.Fprintf(r.Stderr, format, a...)
|
||||
}
|
||||
|
||||
func fieldJoin(parts []fieldPart) string {
|
||||
var buf bytes.Buffer
|
||||
for _, part := range parts {
|
||||
buf.WriteString(part.val)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func escapeQuotedParts(parts []fieldPart) string {
|
||||
var buf bytes.Buffer
|
||||
for _, part := range parts {
|
||||
if !part.quoted {
|
||||
buf.WriteString(part.val)
|
||||
continue
|
||||
}
|
||||
for _, r := range part.val {
|
||||
switch r {
|
||||
case '*', '?', '\\', '[':
|
||||
buf.WriteByte('\\')
|
||||
}
|
||||
buf.WriteRune(r)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (r *Runner) fields(words []*syntax.Word) []string {
|
||||
fields := make([]string, 0, len(words))
|
||||
for _, word := range words {
|
||||
fields = append(fields, r.wordParts(word.Parts, false)...)
|
||||
for _, field := range r.wordFields(word.Parts, false) {
|
||||
matches, _ := filepath.Glob(escapeQuotedParts(field))
|
||||
if len(matches) > 0 {
|
||||
fields = append(fields, matches...)
|
||||
} else {
|
||||
fields = append(fields, fieldJoin(field))
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
@@ -236,7 +269,13 @@ func (r *Runner) loneWord(word *syntax.Word) string {
|
||||
if word == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.Join(r.wordParts(word.Parts, false), "")
|
||||
var buf bytes.Buffer
|
||||
for _, field := range r.wordFields(word.Parts, false) {
|
||||
for _, part := range field {
|
||||
buf.WriteString(part.val)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (r *Runner) stop() bool {
|
||||
@@ -453,8 +492,11 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
str := r.loneWord(x.Word)
|
||||
for _, ci := range x.Items {
|
||||
for _, word := range ci.Patterns {
|
||||
pat := r.loneWord(word)
|
||||
if match(pat, str) {
|
||||
var buf bytes.Buffer
|
||||
for _, field := range r.wordFields(word.Parts, false) {
|
||||
buf.WriteString(escapeQuotedParts(field))
|
||||
}
|
||||
if match(buf.String(), str) {
|
||||
r.stmts(ci.Stmts)
|
||||
return
|
||||
}
|
||||
@@ -560,16 +602,21 @@ func (r *Runner) loopStmtsBroken(stmts []*syntax.Stmt) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
||||
var parts []string
|
||||
var curBuf bytes.Buffer
|
||||
type fieldPart struct {
|
||||
val string
|
||||
quoted bool
|
||||
}
|
||||
|
||||
func (r *Runner) wordFields(wps []syntax.WordPart, quoted bool) [][]fieldPart {
|
||||
var fields [][]fieldPart
|
||||
var curField []fieldPart
|
||||
allowEmpty := false
|
||||
flush := func() {
|
||||
if curBuf.Len() == 0 {
|
||||
if len(curField) == 0 {
|
||||
return
|
||||
}
|
||||
parts = append(parts, curBuf.String())
|
||||
curBuf.Reset()
|
||||
fields = append(fields, curField)
|
||||
curField = nil
|
||||
}
|
||||
splitAdd := func(val string) {
|
||||
// TODO: use IFS
|
||||
@@ -577,7 +624,7 @@ func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
||||
if i > 0 {
|
||||
flush()
|
||||
}
|
||||
curBuf.WriteString(field)
|
||||
curField = append(curField, fieldPart{val: field})
|
||||
}
|
||||
}
|
||||
for i, wp := range wps {
|
||||
@@ -589,10 +636,13 @@ func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
||||
// TODO: ~someuser
|
||||
s = r.getVar("HOME") + s[1:]
|
||||
}
|
||||
curBuf.WriteString(s)
|
||||
curField = append(curField, fieldPart{val: s})
|
||||
case *syntax.SglQuoted:
|
||||
allowEmpty = true
|
||||
curBuf.WriteString(x.Value)
|
||||
curField = append(curField, fieldPart{
|
||||
quoted: true,
|
||||
val: x.Value,
|
||||
})
|
||||
case *syntax.DblQuoted:
|
||||
allowEmpty = true
|
||||
if len(x.Parts) == 1 {
|
||||
@@ -602,18 +652,26 @@ func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
||||
if i > 0 {
|
||||
flush()
|
||||
}
|
||||
curBuf.WriteString(elem)
|
||||
curField = append(curField, fieldPart{
|
||||
quoted: true,
|
||||
val: elem,
|
||||
})
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, str := range r.wordParts(x.Parts, true) {
|
||||
curBuf.WriteString(str)
|
||||
for _, field := range r.wordFields(x.Parts, true) {
|
||||
for _, part := range field {
|
||||
curField = append(curField, fieldPart{
|
||||
quoted: true,
|
||||
val: part.val,
|
||||
})
|
||||
}
|
||||
}
|
||||
case *syntax.ParamExp:
|
||||
val := r.paramExp(x)
|
||||
if quoted {
|
||||
curBuf.WriteString(val)
|
||||
curField = append(curField, fieldPart{val: val})
|
||||
} else {
|
||||
splitAdd(val)
|
||||
}
|
||||
@@ -624,21 +682,23 @@ func (r *Runner) wordParts(wps []syntax.WordPart, quoted bool) []string {
|
||||
r2.stmts(x.Stmts)
|
||||
val := strings.TrimRight(buf.String(), "\n")
|
||||
if quoted {
|
||||
curBuf.WriteString(val)
|
||||
curField = append(curField, fieldPart{val: val})
|
||||
} else {
|
||||
splitAdd(val)
|
||||
}
|
||||
case *syntax.ArithmExp:
|
||||
curBuf.WriteString(strconv.Itoa(r.arithm(x.X)))
|
||||
curField = append(curField, fieldPart{
|
||||
val: strconv.Itoa(r.arithm(x.X)),
|
||||
})
|
||||
default:
|
||||
r.runErr(wp.Pos(), "unhandled word part: %T", x)
|
||||
}
|
||||
}
|
||||
flush()
|
||||
if allowEmpty && len(parts) == 0 {
|
||||
parts = append(parts, "")
|
||||
if allowEmpty && len(fields) == 0 {
|
||||
fields = append(fields, []fieldPart{{}})
|
||||
}
|
||||
return parts
|
||||
return fields
|
||||
}
|
||||
|
||||
func (r *Runner) call(pos syntax.Pos, name string, args []string) {
|
||||
|
||||
18
vendor/github.com/mvdan/sh/interp/test.go
generated
vendored
18
vendor/github.com/mvdan/sh/interp/test.go
generated
vendored
@@ -4,6 +4,7 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -20,6 +21,19 @@ func (r *Runner) bashTest(expr syntax.TestExpr) string {
|
||||
case *syntax.ParenTest:
|
||||
return r.bashTest(x.X)
|
||||
case *syntax.BinaryTest:
|
||||
switch x.Op {
|
||||
case syntax.TsMatch, syntax.TsNoMatch:
|
||||
str := r.loneWord(x.X.(*syntax.Word))
|
||||
var buf bytes.Buffer
|
||||
yw := x.Y.(*syntax.Word)
|
||||
for _, field := range r.wordFields(yw.Parts, false) {
|
||||
buf.WriteString(escapeQuotedParts(field))
|
||||
}
|
||||
if match(buf.String(), str) == (x.Op == syntax.TsMatch) {
|
||||
return "1"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
if r.binTest(x.Op, r.bashTest(x.X), r.bashTest(x.Y)) {
|
||||
return "1"
|
||||
}
|
||||
@@ -73,10 +87,6 @@ func (r *Runner) binTest(op syntax.BinTestOperator, x, y string) bool {
|
||||
return x != "" && y != ""
|
||||
case syntax.OrTest:
|
||||
return x != "" || y != ""
|
||||
case syntax.TsMatch:
|
||||
return match(y, x)
|
||||
case syntax.TsNoMatch:
|
||||
return !match(y, x)
|
||||
case syntax.TsBefore:
|
||||
return x < y
|
||||
default: // syntax.TsAfter
|
||||
|
||||
20
vendor/github.com/mvdan/sh/syntax/nodes.go
generated
vendored
20
vendor/github.com/mvdan/sh/syntax/nodes.go
generated
vendored
@@ -172,12 +172,16 @@ func (*TimeClause) commandNode() {}
|
||||
func (*CoprocClause) commandNode() {}
|
||||
|
||||
// Assign represents an assignment to a variable.
|
||||
//
|
||||
// Here and elsewhere, Index can either mean an index into an indexed or
|
||||
// an associative array. In the former, it's just an arithmetic
|
||||
// expression. In the latter, it will be a word with a single DblQuoted
|
||||
// part.
|
||||
type Assign struct {
|
||||
Append bool // +=
|
||||
Naked bool // without '='
|
||||
Name *Lit
|
||||
Index ArithmExpr // [i]
|
||||
Key *DblQuoted // ["k"]
|
||||
Index ArithmExpr // [i], ["k"]
|
||||
Value *Word // =val
|
||||
Array *ArrayExpr // =(arr)
|
||||
}
|
||||
@@ -192,8 +196,6 @@ func (a *Assign) End() Pos {
|
||||
}
|
||||
if a.Index != nil {
|
||||
return a.Index.End() + 2
|
||||
} else if a.Key != nil {
|
||||
return a.Key.End() + 2
|
||||
}
|
||||
if a.Naked {
|
||||
return a.Name.End()
|
||||
@@ -429,8 +431,7 @@ type ParamExp struct {
|
||||
Length bool // ${#a}
|
||||
Width bool // ${%a}
|
||||
Param *Lit
|
||||
Index ArithmExpr // ${a[i]}
|
||||
Key *DblQuoted // ${a["k"]}
|
||||
Index ArithmExpr // ${a[i]}, ${a["k"]}
|
||||
Slice *Slice // ${a:x:y}
|
||||
Repl *Replace // ${a/x/y}
|
||||
Exp *Expansion // ${a:-b}, ${a#b}, etc
|
||||
@@ -443,14 +444,12 @@ func (p *ParamExp) End() Pos {
|
||||
}
|
||||
if p.Index != nil {
|
||||
return p.Index.End() + 1
|
||||
} else if p.Key != nil {
|
||||
return p.Key.End() + 1
|
||||
}
|
||||
return p.Param.End()
|
||||
}
|
||||
|
||||
func (p *ParamExp) nakedIndex() bool {
|
||||
return p.Short && (p.Index != nil || p.Key != nil)
|
||||
return p.Short && p.Index != nil
|
||||
}
|
||||
|
||||
// Slice represents character slicing inside a ParamExp.
|
||||
@@ -673,15 +672,12 @@ func (a *ArrayExpr) End() Pos { return a.Rparen + 1 }
|
||||
|
||||
type ArrayElem struct {
|
||||
Index ArithmExpr
|
||||
Key *DblQuoted
|
||||
Value *Word
|
||||
}
|
||||
|
||||
func (a *ArrayElem) Pos() Pos {
|
||||
if a.Index != nil {
|
||||
return a.Index.Pos()
|
||||
} else if a.Key != nil {
|
||||
return a.Key.Pos()
|
||||
}
|
||||
return a.Value.Pos()
|
||||
}
|
||||
|
||||
8
vendor/github.com/mvdan/sh/syntax/parser.go
generated
vendored
8
vendor/github.com/mvdan/sh/syntax/parser.go
generated
vendored
@@ -901,7 +901,7 @@ func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
|
||||
old := p.preNested(arithmExprBrack)
|
||||
p.next()
|
||||
if p.tok == dblQuote {
|
||||
pe.Key = p.dblQuoted()
|
||||
pe.Index = p.word(p.wps(p.dblQuoted()))
|
||||
} else {
|
||||
pe.Index = p.followArithm(leftBrack, left)
|
||||
}
|
||||
@@ -1028,7 +1028,7 @@ func (p *Parser) paramExp() *ParamExp {
|
||||
p.tok, p.val = _LitWord, p.tok.String()
|
||||
}
|
||||
if p.tok == dblQuote {
|
||||
pe.Key = p.dblQuoted()
|
||||
pe.Index = p.word(p.wps(p.dblQuoted()))
|
||||
} else {
|
||||
pe.Index = p.followArithm(leftBrack, lpos)
|
||||
}
|
||||
@@ -1170,7 +1170,7 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
||||
p.tok, p.val = _LitWord, p.tok.String()
|
||||
}
|
||||
if p.tok == dblQuote {
|
||||
as.Key = p.dblQuoted()
|
||||
as.Index = p.word(p.wps(p.dblQuoted()))
|
||||
} else {
|
||||
as.Index = p.followArithm(leftBrack, left)
|
||||
}
|
||||
@@ -1219,7 +1219,7 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
||||
p.quote = arithmExprBrack
|
||||
p.next()
|
||||
if p.tok == dblQuote {
|
||||
ae.Key = p.dblQuoted()
|
||||
ae.Index = p.word(p.wps(p.dblQuoted()))
|
||||
} else {
|
||||
ae.Index = p.followArithm(leftBrack, left)
|
||||
}
|
||||
|
||||
18
vendor/github.com/mvdan/sh/syntax/printer.go
generated
vendored
18
vendor/github.com/mvdan/sh/syntax/printer.go
generated
vendored
@@ -345,16 +345,12 @@ func (p *Printer) dblQuoted(dq *DblQuoted) {
|
||||
p.WriteByte('"')
|
||||
}
|
||||
|
||||
func (p *Printer) wroteIndex(index ArithmExpr, key *DblQuoted) bool {
|
||||
if index == nil && key == nil {
|
||||
func (p *Printer) wroteIndex(index ArithmExpr) bool {
|
||||
if index == nil {
|
||||
return false
|
||||
}
|
||||
p.WriteByte('[')
|
||||
if index != nil {
|
||||
p.arithmExpr(index, false, false)
|
||||
} else {
|
||||
p.dblQuoted(key)
|
||||
}
|
||||
p.arithmExpr(index, false, false)
|
||||
p.WriteByte(']')
|
||||
return true
|
||||
}
|
||||
@@ -362,7 +358,7 @@ func (p *Printer) wroteIndex(index ArithmExpr, key *DblQuoted) bool {
|
||||
func (p *Printer) paramExp(pe *ParamExp) {
|
||||
if pe.nakedIndex() { // arr[x]
|
||||
p.WriteString(pe.Param.Value)
|
||||
p.wroteIndex(pe.Index, pe.Key)
|
||||
p.wroteIndex(pe.Index)
|
||||
return
|
||||
}
|
||||
if pe.Short { // $var
|
||||
@@ -381,7 +377,7 @@ func (p *Printer) paramExp(pe *ParamExp) {
|
||||
p.WriteByte('!')
|
||||
}
|
||||
p.WriteString(pe.Param.Value)
|
||||
p.wroteIndex(pe.Index, pe.Key)
|
||||
p.wroteIndex(pe.Index)
|
||||
if pe.Slice != nil {
|
||||
p.WriteByte(':')
|
||||
p.arithmExpr(pe.Slice.Offset, true, true)
|
||||
@@ -560,7 +556,7 @@ func (p *Printer) elemJoin(elems []*ArrayElem) {
|
||||
p.WriteByte(' ')
|
||||
p.wantSpace = false
|
||||
}
|
||||
if p.wroteIndex(el.Index, el.Key) {
|
||||
if p.wroteIndex(el.Index) {
|
||||
p.WriteByte('=')
|
||||
}
|
||||
p.word(el.Value)
|
||||
@@ -981,7 +977,7 @@ func (p *Printer) assigns(assigns []*Assign, alwaysEqual bool) {
|
||||
}
|
||||
if a.Name != nil {
|
||||
p.WriteString(a.Name.Value)
|
||||
p.wroteIndex(a.Index, a.Key)
|
||||
p.wroteIndex(a.Index)
|
||||
if a.Append {
|
||||
p.WriteByte('+')
|
||||
}
|
||||
|
||||
4
vendor/github.com/mvdan/sh/syntax/simplify.go
generated
vendored
4
vendor/github.com/mvdan/sh/syntax/simplify.go
generated
vendored
@@ -149,8 +149,8 @@ func (s *simplifier) inlineSimpleParams(x ArithmExpr) ArithmExpr {
|
||||
if pe == nil || !ValidName(pe.Param.Value) {
|
||||
return x
|
||||
}
|
||||
if pe.Indirect || pe.Length || pe.Width || pe.Key != nil ||
|
||||
pe.Slice != nil || pe.Repl != nil || pe.Exp != nil {
|
||||
if pe.Indirect || pe.Length || pe.Width || pe.Slice != nil ||
|
||||
pe.Repl != nil || pe.Exp != nil {
|
||||
return x
|
||||
}
|
||||
if pe.Index != nil {
|
||||
|
||||
6
vendor/github.com/mvdan/sh/syntax/walk.go
generated
vendored
6
vendor/github.com/mvdan/sh/syntax/walk.go
generated
vendored
@@ -48,8 +48,6 @@ func Walk(node Node, f func(Node) bool) {
|
||||
}
|
||||
if x.Index != nil {
|
||||
Walk(x.Index, f)
|
||||
} else if x.Key != nil {
|
||||
Walk(x.Key, f)
|
||||
}
|
||||
if x.Array != nil {
|
||||
Walk(x.Array, f)
|
||||
@@ -117,8 +115,6 @@ func Walk(node Node, f func(Node) bool) {
|
||||
Walk(x.Param, f)
|
||||
if x.Index != nil {
|
||||
Walk(x.Index, f)
|
||||
} else if x.Key != nil {
|
||||
Walk(x.Key, f)
|
||||
}
|
||||
if x.Repl != nil {
|
||||
if x.Repl.Orig != nil {
|
||||
@@ -169,8 +165,6 @@ func Walk(node Node, f func(Node) bool) {
|
||||
case *ArrayElem:
|
||||
if x.Index != nil {
|
||||
Walk(x.Index, f)
|
||||
} else if x.Key != nil {
|
||||
Walk(x.Key, f)
|
||||
}
|
||||
Walk(x.Value, f)
|
||||
case *ExtGlob:
|
||||
|
||||
Reference in New Issue
Block a user