Skip to content

Commit

Permalink
devbox: add AppendScript method to ConfigShellCmds (#149)
Browse files Browse the repository at this point in the history
This method takes a script as a string and appends it to the slice of
shell commands in the config. From the docs:

	AppendScript appends each line of a script to s.Cmds. It also
	applies the following formatting rules:

	  - Trim leading newlines from the script.
	  - Trim trailing whitespace from the script.
- If the first line of the script begins with one or more tabs ('\t'),
then unindent each line by that same number of tabs.
	  - Remove trailing whitespace from each line.

	Note that unindenting only happens when a line starts with at
	least as many tabs as the first line. If it starts with
	fewer tabs, then it is not unindented at all.

See `config_test.go` for an example.
  • Loading branch information
gcurtis authored Sep 26, 2022
1 parent e8d5078 commit e4eee1b
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
28 changes: 28 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"strings"
"unicode"

"github.com/pkg/errors"
"go.jetpack.io/devbox/cuecfg"
Expand Down Expand Up @@ -93,6 +94,33 @@ type ConfigShellCmds struct {
Cmds []string
}

// AppendScript appends each line of a script to s.Cmds. It also applies the
// following formatting rules:
//
// - Trim leading newlines from the script.
// - Trim trailing whitespace from the script.
// - If the first line of the script begins with one or more tabs ('\t'), then
// unindent each line by that same number of tabs.
// - Remove trailing whitespace from each line.
//
// Note that unindenting only happens when a line starts with at least as many
// tabs as the first line. If it starts with fewer tabs, then it is not
// unindented at all.
func (s *ConfigShellCmds) AppendScript(script string) {
script = strings.TrimLeft(script, "\r\n ")
script = strings.TrimRightFunc(script, unicode.IsSpace)
if len(script) == 0 {
return
}
prefixLen := strings.IndexFunc(script, func(r rune) bool { return r != '\t' })
prefix := strings.Repeat("\t", prefixLen)
for _, line := range strings.Split(script, "\n") {
line = strings.TrimRightFunc(line, unicode.IsSpace)
line = strings.TrimPrefix(line, prefix)
s.Cmds = append(s.Cmds, line)
}
}

// MarshalJSON marshals shell commands according to s.MarshalAs. It marshals
// commands to a string by joining s.Cmds with newlines.
func (s ConfigShellCmds) MarshalJSON() ([]byte, error) {
Expand Down
104 changes: 104 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package devbox

import (
"encoding/json"
"fmt"
"testing"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -145,3 +146,106 @@ func TestConfigShellCmdsString(t *testing.T) {
})
}
}

func ExampleConfigShellCmds_AppendScript() {
shCmds := ConfigShellCmds{}
shCmds.AppendScript(`
# This script will be unindented by the number of leading tabs
# on the first line.
if true; then
echo "this is always printed"
fi`,
)
b, _ := json.MarshalIndent(&shCmds, "", " ")
fmt.Println(string(b))

// Output:
// [
// "# This script will be unindented by the number of leading tabs",
// "# on the first line.",
// "if true; then",
// "\techo \"this is always printed\"",
// "fi"
// ]
}

func TestAppendScript(t *testing.T) {
tests := []struct {
name string
script string
wantCmds []string
}{
{
name: "Empty",
script: "",
wantCmds: nil,
},
{
name: "OnlySpaces",
script: " ",
wantCmds: nil,
},
{
name: "Only newlines",
script: "\r\n",
wantCmds: nil,
},
{
name: "Simple",
script: "echo test",
wantCmds: []string{"echo test"},
},
{
name: "LeadingNewline",
script: "\necho test",
wantCmds: []string{"echo test"},
},
{
name: "LeadingNewlineAndSpace",
script: "\n echo test",
wantCmds: []string{"echo test"},
},
{
name: "TrailingWhitespace",
script: "echo test \n",
wantCmds: []string{"echo test"},
},
{
name: "SecondLineIndent",
script: "if true; then\n\techo test\nfi",
wantCmds: []string{
"if true; then",
"\techo test",
"fi",
},
},
{
name: "Unindent",
script: "\n\tif true; then\n\t\techo test\n\tfi",
wantCmds: []string{
"if true; then",
"\techo test",
"fi",
},
},
{
name: "UnindentTooFewTabs",
script: "\t\tif true; then\n\techo test\n\t\tfi",
wantCmds: []string{
"if true; then",
"\techo test",
"fi",
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
shCmds := ConfigShellCmds{}
shCmds.AppendScript(test.script)
gotCmds := shCmds.Cmds
if diff := cmp.Diff(test.wantCmds, gotCmds); diff != "" {
t.Errorf("Got incorrect commands slice (-want +got):\n%s", diff)
}
})
}
}

0 comments on commit e4eee1b

Please sign in to comment.