Skip to content

Commit

Permalink
Merge pull request Masterminds#133 from mortent/StringHandleNil
Browse files Browse the repository at this point in the history
Handle untyped nil values as parameters to string functions
  • Loading branch information
technosophos authored Feb 12, 2019
2 parents 544a9b1 + 2b2ec8f commit 45a0d1b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 13 deletions.
49 changes: 36 additions & 13 deletions strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,27 @@ func untitle(str string) string {
}

func quote(str ...interface{}) string {
out := make([]string, len(str))
for i, s := range str {
out[i] = fmt.Sprintf("%q", strval(s))
out := make([]string, 0, len(str))
for _, s := range str {
if s != nil {
out = append(out, fmt.Sprintf("%q", strval(s)))
}
}
return strings.Join(out, " ")
}

func squote(str ...interface{}) string {
out := make([]string, len(str))
for i, s := range str {
out[i] = fmt.Sprintf("'%v'", s)
out := make([]string, 0, len(str))
for _, s := range str {
if s != nil {
out = append(out, fmt.Sprintf("'%v'", s))
}
}
return strings.Join(out, " ")
}

func cat(v ...interface{}) string {
v = removeNilElements(v)
r := strings.TrimSpace(strings.Repeat("%v ", len(v)))
return fmt.Sprintf(r, v...)
}
Expand Down Expand Up @@ -126,26 +131,44 @@ func strslice(v interface{}) []string {
case []string:
return v
case []interface{}:
l := len(v)
b := make([]string, l)
for i := 0; i < l; i++ {
b[i] = strval(v[i])
b := make([]string, 0, len(v))
for _, s := range v {
if s != nil {
b = append(b, strval(s))
}
}
return b
default:
val := reflect.ValueOf(v)
switch val.Kind() {
case reflect.Array, reflect.Slice:
l := val.Len()
b := make([]string, l)
b := make([]string, 0, l)
for i := 0; i < l; i++ {
b[i] = strval(val.Index(i).Interface())
value := val.Index(i).Interface()
if value != nil {
b = append(b, strval(value))
}
}
return b
default:
return []string{strval(v)}
if v == nil {
return []string{}
} else {
return []string{strval(v)}
}
}
}
}

func removeNilElements(v []interface{}) []interface{} {
newSlice := make([]interface{}, 0, len(v))
for _, i := range v {
if i != nil {
newSlice = append(newSlice, i)
}
}
return newSlice
}

func strval(v interface{}) string {
Expand Down
21 changes: 21 additions & 0 deletions strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func TestQuote(t *testing.T) {
if err := runt(tpl, `"1" "2" "3"`); err != nil {
t.Error(err)
}
tpl = `{{ .value | quote }}`
values := map[string]interface{}{"value": nil}
if err := runtv(tpl, ``, values); err != nil {
t.Error(err)
}
}
func TestSquote(t *testing.T) {
tpl := `{{squote "a" "b" "c"}}`
Expand All @@ -48,6 +53,11 @@ func TestSquote(t *testing.T) {
if err := runt(tpl, `'1' '2' '3'`); err != nil {
t.Error(err)
}
tpl = `{{ .value | squote }}`
values := map[string]interface{}{"value": nil}
if err := runtv(tpl, ``, values); err != nil {
t.Error(err)
}
}

func TestContains(t *testing.T) {
Expand Down Expand Up @@ -100,6 +110,11 @@ func TestToString(t *testing.T) {
func TestToStrings(t *testing.T) {
tpl := `{{ $s := list 1 2 3 | toStrings }}{{ index $s 1 | kindOf }}`
assert.NoError(t, runt(tpl, "string"))
tpl = `{{ list 1 .value 2 | toStrings }}`
values := map[string]interface{}{"value": nil}
if err := runtv(tpl, `[1 2]`, values); err != nil {
t.Error(err)
}
}

func TestJoin(t *testing.T) {
Expand All @@ -108,6 +123,7 @@ func TestJoin(t *testing.T) {
assert.NoError(t, runtv(`{{ join "-" .V }}`, "a-b-c", map[string]interface{}{"V": []string{"a", "b", "c"}}))
assert.NoError(t, runtv(`{{ join "-" .V }}`, "abc", map[string]interface{}{"V": "abc"}))
assert.NoError(t, runtv(`{{ join "-" .V }}`, "1-2-3", map[string]interface{}{"V": []int{1, 2, 3}}))
assert.NoError(t, runtv(`{{ join "-" .value }}`, "1-2", map[string]interface{}{"value": []interface{}{"1", nil, "2"}}))
}

func TestSortAlpha(t *testing.T) {
Expand Down Expand Up @@ -199,6 +215,11 @@ func TestCat(t *testing.T) {
if err := runt(tpl, "a b c"); err != nil {
t.Error(err)
}
tpl = `{{ .value | cat "a" "b"}}`
values := map[string]interface{}{"value": nil}
if err := runtv(tpl, "a b", values); err != nil {
t.Error(err)
}
}

func TestIndent(t *testing.T) {
Expand Down

0 comments on commit 45a0d1b

Please sign in to comment.