twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
12.85k stars 477 forks source link

Do loop in template with prompt*Once #2590

Closed issenn closed 1 year ago

issenn commented 1 year ago

What exactly are you trying to do?

Do loop in template with prompt*Once, but will got error like this:

chezmoi: template: chezmoi.yaml:55:33: executing "chezmoi.yaml" at <.>: wrong type for value; expected map[string]interface {}; got int

What have you tried so far?

This is bad.

{{- range $_, $i := until 99 -}}
{{-   $answer := "" -}}
{{-   $answer = promptStringOnce . "answer" "answer" -}}
{{-   if regexMatch "^[A-Z][-' a-zA-Z]+$" $answer -}}
{{-     writeToStdout (printf "✅ Answer set as '%s'\n" $answer) -}}
{{-     break -}}
{{-   end -}}
{{-   writeToStdout (printf "❌ '%s' is invalid\n" $answer) -}}
{{-   if eq $i 98 -}}
{{-     writeToStdout "❌ ERROR: maximum tries exceeded\n" -}}
{{-     exit 1 -}}
{{-   end -}}
{{- end -}}

If change promptStringOnce to promptString, that is ok.

{{- range $_, $i := until 99 -}}
{{-   $answer := "" -}}
{{-   $answer = promptString "answer" -}}
{{-   if regexMatch "^[A-Z][-' a-zA-Z]+$" $answer -}}
{{-     writeToStdout (printf "✅ Answer set as '%s'\n" $answer) -}}
{{-     break -}}
{{-   end -}}
{{-   writeToStdout (printf "❌ '%s' is invalid\n" $answer) -}}
{{-   if eq $i 98 -}}
{{-     writeToStdout "❌ ERROR: maximum tries exceeded\n" -}}
{{-     exit 1 -}}
{{-   end -}}
{{- end -}}

Where else have you checked for solutions?

Output of any commands you've tried with --verbose flag

$ chezmoi --verbose init
chezmoi: template: chezmoi.yaml:55:33: executing "chezmoi.yaml" at <.>: wrong type for value; expected map[string]interface {}; got int

Output of chezmoi doctor

```console $ chezmoi doctor RESULT CHECK MESSAGE ok version v2.27.1, commit b6039e787dfffe970fec4f9165ec9ebe1b3ceaa6, built at 2022-11-11T18:25:15Z, built by Homebrew ok latest-version v2.27.1 ok os-arch darwin/amd64 ok uname Darwin IssenndeMBP.lan 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64 x86_64 ok go-version go1.19.3 (gc) ok executable /usr/local/bin/chezmoi ok upgrade-method replace-executable ok config-file no config file found ok source-dir ~/.local/share/chezmoi is a git working tree (clean) ok suspicious-entries no suspicious entries ok working-tree ~/.local/share/chezmoi is a git working tree (clean) ok dest-dir ~ is a directory ok umask 022 ok cd-command found /usr/local/bin/zsh ok cd-args /usr/local/bin/zsh info diff-command not set ok edit-command found /usr/local/bin/vi ok edit-args /usr/local/bin/vi ok git-command found /usr/local/bin/git, version 2.37.3 ok merge-command found /usr/local/bin/vimdiff ok shell-command found /usr/local/bin/zsh ok shell-args /usr/local/bin/zsh ok age-command found /usr/local/bin/age, version 1.0.0 ok gpg-command found /usr/local/bin/gpg, version 2.3.7 info pinentry-command not set info 1password-command op not found in $PATH ok bitwarden-command found /usr/local/bin/bw, version 2022.9.0 info gopass-command gopass not found in $PATH info keepassxc-command keepassxc-cli not found in $PATH info keepassxc-db not set info keeper-command keeper not found in $PATH info lastpass-command lpass not found in $PATH info pass-command pass not found in $PATH info passhole-command ph not found in $PATH info vault-command vault not found in $PATH info secret-command not set ```

Additional context

Add any other context about the problem here.

halostatue commented 1 year ago

Can you try this?

{{- range $_, $i := until 99 -}}
{{-   $answer := "" -}}
{{-   $answer = promptStringOnce . (printf "%s_%i" "answer" $i) "answer" -}}
{{-   if regexMatch "^[A-Z][-' a-zA-Z]+$" $answer -}}
{{-     writeToStdout (printf "✅ Answer set as '%s'\n" $answer) -}}
{{-     break -}}
{{-   end -}}
{{-   writeToStdout (printf "❌ '%s' is invalid\n" $answer) -}}
{{-   if eq $i 98 -}}
{{-     writeToStdout "❌ ERROR: maximum tries exceeded\n" -}}
{{-     exit 1 -}}
{{-   end -}}
{{- end -}}

That said, prompt*Once seem to me to be better used when you want to prompt for a value exactly once. They pull from the current chezmoi.data to provide the default answer.

issenn commented 1 year ago

Can you try this?

{{- range $_, $i := until 99 -}}
{{-   $answer := "" -}}
{{-   $answer = promptStringOnce . (printf "%s_%i" "answer" $i) "answer" -}}
{{-   if regexMatch "^[A-Z][-' a-zA-Z]+$" $answer -}}
{{-     writeToStdout (printf "✅ Answer set as '%s'\n" $answer) -}}
{{-     break -}}
{{-   end -}}
{{-   writeToStdout (printf "❌ '%s' is invalid\n" $answer) -}}
{{-   if eq $i 98 -}}
{{-     writeToStdout "❌ ERROR: maximum tries exceeded\n" -}}
{{-     exit 1 -}}
{{-   end -}}
{{- end -}}

That said, prompt*Once seem to me to be better used when you want to prompt for a value exactly once. They pull from the current chezmoi.data to provide the default answer.

I tried but still got error.

I'm getting the value as you said, but checking the value, repeating the check in an interactive mode until it meets expectations. Prompt only once if the value is correct.

twpayne commented 1 year ago

chezmoi's template language is for templating. It's not a general purpose scripting language and attempts to use it for scripting are unlikely to be successful.

Instead, I would suggest writing a script with the behavior you want and using the output template function to call that script and collect its output.

issenn commented 1 year ago

Ok, I'll try it.