Skip to content

Commit

Permalink
feat: Add default argument to promptInt template function
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Oct 17, 2021
1 parent 35eb651 commit 7e2e64d
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 11 deletions.
11 changes: 6 additions & 5 deletions docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Manage your dotfiles across multiple machines, securely.
* [`pass` *pass-name*](#pass-pass-name)
* [`passRaw` *pass-name*](#passraw-pass-name)
* [`promptBool` *prompt* [*default*]](#promptbool-prompt-default)
* [`promptInt` *prompt*](#promptint-prompt)
* [`promptInt` *prompt* [*default*]](#promptint-prompt-default)
* [`promptString` *prompt*](#promptstring-prompt)
* [`secret` [*arg*...]](#secret-arg)
* [`secretJSON` [*arg*...]](#secretjson-arg)
Expand Down Expand Up @@ -2371,11 +2371,12 @@ config file. The user's response is interpreted as follows (case insensitive):

---

### `promptInt` *prompt*
### `promptInt` *prompt* [*default*]

`promptInt` prompts the user with *prompt* and returns the user's response with
interpreted as an integer. It is only available when generating the initial
config file.
`promptInt` prompts the user with *prompt* and returns the user's response
interpreted as an integer. 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.

---

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

func (c *Config) promptInt(field string) int64 {
value, err := strconv.ParseInt(c.promptString(field), 10, 64)
if err != nil {
func (c *Config) promptInt(field string, args ...int64) int64 {
switch len(args) {
case 0:
value, err := strconv.ParseInt(c.promptString(field), 10, 64)
if err != nil {
returnTemplateError(err)
return 0
}
return value
case 1:
promptStr := field + " (default " + strconv.FormatInt(args[0], 10) + ")"
valueStr := c.promptString(promptStr)
if valueStr == "" {
return args[0]
}
value, err := strconv.ParseInt(valueStr, 10, 64)
if err != nil {
returnTemplateError(err)
return 0
}
return value
default:
err := fmt.Errorf("want 1 or 2 arguments, got %d", len(args)+1)
returnTemplateError(err)
return 0
}
return value
}

func (c *Config) promptString(field string) string {
Expand Down
72 changes: 72 additions & 0 deletions internal/cmd/inittemplatefuncs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,75 @@ func TestPromptBool(t *testing.T) {
})
}
}

func TestPromptInt(t *testing.T) {
for _, tc := range []struct {
name string
prompt string
args []int64
stdinStr string
expectedStdoutStr string
expected int64
expectedErr bool
}{
{
name: "response_without_default",
prompt: "int",
stdinStr: "1\n",
expectedStdoutStr: "int? ",
expected: 1,
},
{
name: "response_with_default",
prompt: "int",
args: []int64{1},
stdinStr: "2\n",
expectedStdoutStr: "int (default 1)? ",
expected: 2,
},
{
name: "no_response_with_default",
prompt: "int",
args: []int64{1},
stdinStr: "\n",
expectedStdoutStr: "int (default 1)? ",
expected: 1,
},
{
name: "invalid_response",
stdinStr: "invalid\n",
expectedErr: true,
},
{
name: "invalid_response_with_default",
args: []int64{1},
stdinStr: "invalid\n",
expectedErr: true,
},
{
name: "too_many_args",
prompt: "bool",
args: []int64{0, 0},
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.promptInt(tc.prompt, tc.args...)
})
} else {
assert.Equal(t, tc.expected, config.promptInt(tc.prompt, tc.args...))
assert.Equal(t, tc.expectedStdoutStr, stdout.String())
}
})
}
}
4 changes: 4 additions & 0 deletions internal/cmd/testdata/scripts/executetemplate.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ stdout 1
! chezmoi execute-template --promptInt value=error
stderr 'invalid syntax'

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

# test --init --promptString
chezmoi execute-template --init --promptString email=user@example.com '{{ promptString "email" }}'
stdout 'user@example.com'
Expand Down

0 comments on commit 7e2e64d

Please sign in to comment.