Skip to content

Commit

Permalink
feat: Add default argument to promptString template function
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Oct 17, 2021
1 parent 7e2e64d commit 951fc7e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 11 deletions.
7 changes: 4 additions & 3 deletions docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Manage your dotfiles across multiple machines, securely.
* [`passRaw` *pass-name*](#passraw-pass-name)
* [`promptBool` *prompt* [*default*]](#promptbool-prompt-default)
* [`promptInt` *prompt* [*default*]](#promptint-prompt-default)
* [`promptString` *prompt*](#promptstring-prompt)
* [`promptString` *prompt* [*default*]](#promptstring-prompt-default)
* [`secret` [*arg*...]](#secret-arg)
* [`secretJSON` [*arg*...]](#secretjson-arg)
* [`stat` *name*](#stat-name)
Expand Down Expand Up @@ -2380,10 +2380,11 @@ initial config file.

---

### `promptString` *prompt*
### `promptString` *prompt* [*default*]

`promptString` prompts the user with *prompt* and returns the user's response
with all leading and trailing spaces stripped. It is only available when
with all leading and trailing spaces stripped. If *default* is passed and the
user's response is empty then it returns *default*. It is only available when
generating the initial config file.

#### `promptString` examples
Expand Down
20 changes: 16 additions & 4 deletions internal/cmd/executetemplatecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,23 @@ func (c *Config) runExecuteTemplateCmd(cmd *cobra.Command, args []string) error
return 0
}
},
"promptString": func(prompt string) string {
if value, ok := c.executeTemplate.promptString[prompt]; ok {
return value
"promptString": func(prompt string, args ...string) string {
switch len(args) {
case 0:
if value, ok := c.executeTemplate.promptString[prompt]; ok {
return value
}
return prompt
case 1:
if value, ok := c.executeTemplate.promptString[prompt]; ok {
return value
}
return args[0]
default:
err := fmt.Errorf("want 1 or 2 arguments, got %d", len(args)+1)
returnTemplateError(err)
return ""
}
return prompt
},
"stdinIsATTY": func() bool {
return c.executeTemplate.stdinIsATTY
Expand Down
27 changes: 23 additions & 4 deletions internal/cmd/inittemplatefuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,32 @@ func (c *Config) promptInt(field string, args ...int64) int64 {
}
}

func (c *Config) promptString(field string) string {
value, err := c.readLine(fmt.Sprintf("%s? ", field))
if err != nil {
func (c *Config) promptString(prompt string, args ...string) string {
switch len(args) {
case 0:
value, err := c.readLine(prompt + "? ")
if err != nil {
returnTemplateError(err)
return ""
}
return strings.TrimSpace(value)
case 1:
defaultStr := strings.TrimSpace(args[0])
promptStr := prompt + " (default " + strconv.Quote(defaultStr) + ")? "
switch value, err := c.readLine(promptStr); {
case err != nil:
returnTemplateError(err)
return ""
case value == "":
return defaultStr
default:
return strings.TrimSpace(value)
}
default:
err := fmt.Errorf("want 1 or 2 arguments, got %d", len(args)+1)
returnTemplateError(err)
return ""
}
return strings.TrimSpace(value)
}

func (c *Config) stdinIsATTY() bool {
Expand Down
77 changes: 77 additions & 0 deletions internal/cmd/inittemplatefuncs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,80 @@ func TestPromptInt(t *testing.T) {
})
}
}

func TestPromptString(t *testing.T) {
for _, tc := range []struct {
name string
prompt string
args []string
stdinStr string
expectedStdoutStr string
expected string
expectedErr bool
}{
{
name: "response_without_default",
prompt: "string",
stdinStr: "one\n",
expectedStdoutStr: "string? ",
expected: "one",
},
{
name: "response_with_default",
prompt: "string",
args: []string{"one"},
stdinStr: "two\n",
expectedStdoutStr: `string (default "one")? `,
expected: "two",
},
{
name: "response_with_space_with_default",
prompt: "string",
args: []string{"one"},
stdinStr: " two \n",
expectedStdoutStr: `string (default "one")? `,
expected: "two",
},
{
name: "no_response_with_default_with_space",
prompt: "string",
args: []string{" one "},
stdinStr: "\n",
expectedStdoutStr: `string (default "one")? `,
expected: "one",
},
{
name: "no_response_with_default",
prompt: "string",
args: []string{"one"},
stdinStr: "\n",
expectedStdoutStr: `string (default "one")? `,
expected: "one",
},
{
name: "too_many_args",
prompt: "bool",
args: []string{"", ""},
stdinStr: "\n",
expectedErr: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
stdin := strings.NewReader(tc.stdinStr)
stdout := &strings.Builder{}
config, err := newConfig(
withStdin(stdin),
withStdout(stdout),
)
require.NoError(t, err)
if tc.expectedErr {
assert.Panics(t, func() {
config.promptString(tc.prompt, tc.args...)
})
} else {
assert.Equal(t, tc.expected, config.promptString(tc.prompt, tc.args...))
assert.Equal(t, tc.expectedStdoutStr, stdout.String())
}
})
}
}
8 changes: 8 additions & 0 deletions internal/cmd/testdata/scripts/executetemplate.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ stdout 1
chezmoi execute-template --init --promptString email=user@example.com '{{ promptString "email" }}'
stdout 'user@example.com'

# test --init --promptString without a default value
chezmoi execute-template --init '{{ promptString "value" }}'
stdout value

# test --init --promptString with a default value
chezmoi execute-template --init '{{ promptString "value" "default" }}'
stdout default

-- golden/stdin.tmpl --
{{ "stdin-template" }}
-- home/user/.config/chezmoi/chezmoi.toml --
Expand Down

0 comments on commit 951fc7e

Please sign in to comment.