@ -2,6 +2,7 @@ package config
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"regexp"
@ -17,13 +18,14 @@ var Funcs map[string]ast.Function
func init ( ) {
Funcs = map [ string ] ast . Function {
"file" : interpolationFuncFile ( ) ,
"format" : interpolationFuncFormat ( ) ,
"join" : interpolationFuncJoin ( ) ,
"element" : interpolationFuncElement ( ) ,
"replace" : interpolationFuncReplace ( ) ,
"split" : interpolationFuncSplit ( ) ,
"length" : interpolationFuncLength ( ) ,
"file" : interpolationFuncFile ( ) ,
"format" : interpolationFuncFormat ( ) ,
"formatlist" : interpolationFuncFormatList ( ) ,
"join" : interpolationFuncJoin ( ) ,
"element" : interpolationFuncElement ( ) ,
"replace" : interpolationFuncReplace ( ) ,
"split" : interpolationFuncSplit ( ) ,
"length" : interpolationFuncLength ( ) ,
// Concat is a little useless now since we supported embeddded
// interpolations but we keep it around for backwards compat reasons.
@ -88,6 +90,69 @@ func interpolationFuncFormat() ast.Function {
}
}
// interpolationFuncFormatList implements the "formatlist" function that does
// string formatting on lists.
func interpolationFuncFormatList ( ) ast . Function {
return ast . Function {
ArgTypes : [ ] ast . Type { ast . TypeString } ,
Variadic : true ,
VariadicType : ast . TypeAny ,
ReturnType : ast . TypeString ,
Callback : func ( args [ ] interface { } ) ( interface { } , error ) {
// Make a copy of the variadic part of args
// to avoid modifying the original.
varargs := make ( [ ] interface { } , len ( args ) - 1 )
copy ( varargs , args [ 1 : ] )
// Convert arguments that are lists into slices.
// Confirm along the way that all lists have the same length (n).
var n int
for i := 1 ; i < len ( args ) ; i ++ {
s , ok := args [ i ] . ( string )
if ! ok {
continue
}
parts := strings . Split ( s , InterpSplitDelim )
if len ( parts ) == 1 {
continue
}
varargs [ i - 1 ] = parts
if n == 0 {
// first list we've seen
n = len ( parts )
continue
}
if n != len ( parts ) {
return nil , fmt . Errorf ( "format: mismatched list lengths: %d != %d" , n , len ( parts ) )
}
}
if n == 0 {
return nil , errors . New ( "no lists in arguments to formatlist" )
}
// Do the formatting.
format := args [ 0 ] . ( string )
// Generate a list of formatted strings.
list := make ( [ ] string , n )
fmtargs := make ( [ ] interface { } , len ( varargs ) )
for i := 0 ; i < n ; i ++ {
for j , arg := range varargs {
switch arg := arg . ( type ) {
default :
fmtargs [ j ] = arg
case [ ] string :
fmtargs [ j ] = arg [ i ]
}
}
list [ i ] = fmt . Sprintf ( format , fmtargs ... )
}
return strings . Join ( list , InterpSplitDelim ) , nil
} ,
}
}
// interpolationFuncJoin implements the "join" function that allows
// multi-variable values to be joined by some character.
func interpolationFuncJoin ( ) ast . Function {