Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions internal/lang/funcs/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,58 @@ import (
"github.com/zclconf/go-cty/cty/function"
)

// StartsWithFunc constructs a function that checks if a string starts with
// a specific prefix using strings.HasPrefix
var StartsWithFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "str",
Type: cty.String,
},
{
Name: "prefix",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.Bool),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
str := args[0].AsString()
prefix := args[1].AsString()

if strings.HasPrefix(str, prefix) {
return cty.True, nil
}

return cty.False, nil
},
})

// EndsWithFunc constructs a function that checks if a string ends with
// a specific suffix using strings.HasSuffix
var EndsWithFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "str",
Type: cty.String,
},
{
Name: "suffix",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.Bool),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
str := args[0].AsString()
suffix := args[1].AsString()

if strings.HasSuffix(str, suffix) {
return cty.True, nil
}

return cty.False, nil
},
})

// ReplaceFunc constructs a function that searches a given string for another
// given substring, and replaces each occurence with a given replacement string.
var ReplaceFunc = function.New(&function.Spec{
Expand Down
2 changes: 2 additions & 0 deletions internal/lang/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (s *Scope) Functions() map[string]function.Function {
"dirname": funcs.DirnameFunc,
"distinct": stdlib.DistinctFunc,
"element": stdlib.ElementFunc,
"endswith": funcs.EndsWithFunc,
"chunklist": stdlib.ChunklistFunc,
"file": funcs.MakeFileFunc(s.BaseDir, false),
"fileexists": funcs.MakeFileExistsFunc(s.BaseDir),
Expand Down Expand Up @@ -115,6 +116,7 @@ func (s *Scope) Functions() map[string]function.Function {
"slice": stdlib.SliceFunc,
"sort": stdlib.SortFunc,
"split": stdlib.SplitFunc,
"startswith": funcs.StartsWithFunc,
"strrev": stdlib.ReverseFunc,
"substr": stdlib.SubstrFunc,
"sum": funcs.SumFunc,
Expand Down
82 changes: 82 additions & 0 deletions internal/lang/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,47 @@ func TestFunctions(t *testing.T) {
},
},

"endswith": {
{
`endswith("hello world", "world")`,
cty.True,
},
{
`endswith("hello world", "hello")`,
cty.False,
},
{
`endswith("hello world", "")`,
cty.True,
// Completely empty suffix value ( "" )
// will always evaluate to true for all strings.
},
{
`endswith("hello world", " ")`,
cty.False,
},
{
`endswith("", "")`,
cty.True,
},
{
`endswith("", " ")`,
cty.False,
},
{
`endswith(" ", "")`,
cty.True,
},
{
`endswith("", "hello")`,
cty.False,
},
{
`endswith(" ", "hello")`,
cty.False,
},
},

"file": {
{
`file("hello.txt")`,
Expand Down Expand Up @@ -816,6 +857,47 @@ func TestFunctions(t *testing.T) {
},
},

"startswith": {
{
`startswith("hello world", "hello")`,
cty.True,
},
{
`startswith("hello world", "world")`,
cty.False,
},
{
`startswith("hello world", "")`,
cty.True,
// Completely empty prefix value ( "" )
// will always evaluate to true for all strings.
},
{
`startswith("hello world", " ")`,
cty.False,
},
{
`startswith("", "")`,
cty.True,
},
{
`startswith("", " ")`,
cty.False,
},
{
`startswith(" ", "")`,
cty.True,
},
{
`startswith("", "hello")`,
cty.False,
},
{
`startswith(" ", "hello")`,
cty.False,
},
},

"strrev": {
{
`strrev("hello world")`,
Expand Down
10 changes: 10 additions & 0 deletions website/data/language-nav-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@
"title": "<code>chomp</code>",
"href": "/language/functions/chomp"
},
{
"title": "<code>endswith</code>",
"href": "/language/functions/endswith"
},
{
"title": "<code>format</code>",
"href": "/language/functions/format"
Expand Down Expand Up @@ -352,6 +356,10 @@
"title": "<code>split</code>",
"href": "/language/functions/split"
},
{
"title": "<code>startswith</code>",
"href": "/language/functions/startswith"
},
{
"title": "<code>strrev</code>",
"href": "/language/functions/strrev"
Expand Down Expand Up @@ -776,6 +784,7 @@
{ "title": "dirname", "path": "functions/dirname", "hidden": true },
{ "title": "distinct", "path": "functions/distinct", "hidden": true },
{ "title": "element", "path": "functions/element", "hidden": true },
{ "title": "endswith", "path": "functions/endswith", "hidden": true },
{ "title": "file", "path": "functions/file", "hidden": true },
{ "title": "filebase64", "path": "functions/filebase64", "hidden": true },
{
Expand Down Expand Up @@ -851,6 +860,7 @@
{ "title": "slice", "path": "functions/slice", "hidden": true },
{ "title": "sort", "path": "functions/sort", "hidden": true },
{ "title": "split", "path": "functions/split", "hidden": true },
{ "title": "startswith", "path": "functions/startswith", "hidden": true },
{ "title": "strrev", "path": "functions/strrev", "hidden": true },
{ "title": "substr", "path": "functions/substr", "hidden": true },
{ "title": "sum", "path": "functions/sum", "hidden": true },
Expand Down
27 changes: 27 additions & 0 deletions website/docs/language/functions/endswith.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
page_title: endswith - Functions - Configuration Language
description: |-
The endswith function takes two values: a string to check and a suffix string. It returns true if the first string ends with that exact suffix.
---

# `endswith` Function

`endswith` takes two values: a string to check and a suffix string. The function returns true if the first string ends with that exact suffix.

```hcl
endswith(string, suffix)
```

## Examples

```
> endswith("hello world", "world")
true

> endswith("hello world", "hello")
false
```

## Related Functions

- [`startswith`](/language/functions/startswith) takes two values: a string to check and a prefix string. The function returns true if the string begins with that exact prefix.
27 changes: 27 additions & 0 deletions website/docs/language/functions/startswith.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
page_title: startsswith - Functions - Configuration Language
description: |-
The startswith function takes two values: a string to check and a prefix string. It returns true if the string begins with that exact prefix.
---

# `startswith` Function

`startswith` takes two values: a string to check and a prefix string. The function returns true if the string begins with that exact prefix.

```hcl
startswith(string, prefix)
```

## Examples

```
> startswith("hello world", "hello")
true

> startswith("hello world", "world")
false
```

## Related Functions

- [`endswith`](/language/functions/endswith) takes two values: a string to check and a suffix string. The function returns true if the first string ends with that exact suffix.
8 changes: 8 additions & 0 deletions website/layouts/language.erb
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,10 @@
<a href="/docs/language/functions/chomp.html">chomp</a>
</li>

<li>
<a href="/docs/language/functions/endswith.html">endswith</a>
</li>

<li>
<a href="/docs/language/functions/format.html">format</a>
</li>
Expand Down Expand Up @@ -406,6 +410,10 @@
<a href="/docs/language/functions/split.html">split</a>
</li>

<li>
<a href="/docs/language/functions/startswith.html">startswith</a>
</li>

<li>
<a href="/docs/language/functions/strrev.html">strrev</a>
</li>
Expand Down