package main import ( "errors" "flag" "strings" "unicode" "unicode/utf8" ) const mutationMessageMaxRunes = 240 type mutationMessageCopy struct { MessageHelp, NoPromptHelp, Prompt, Invalid string } var mutationMessageText = mutationMessageCopy{ MessageHelp: "Add a short note describing this change (shown alongside the recorded action).", NoPromptHelp: "Skip the optional change description prompt.", Prompt: "Describe this change (optional):", Invalid: "Message must be one line and 240 characters or fewer.", } func firstMutationMessage(messages []string) string { if len(messages) == 0 { return "" } return messages[0] } type mutationMessageFlags struct { message *string noPrompt *bool } func addMutationMessageFlags(fs *flag.FlagSet) mutationMessageFlags { return mutationMessageFlags{ message: fs.String("message", "", mutationMessageText.MessageHelp), noPrompt: fs.Bool("no-prompt", false, mutationMessageText.NoPromptHelp), } } func resolveMutationMessage(fs *flag.FlagSet, flags mutationMessageFlags) (string, error) { if flagWasSet(fs, "message") { return validateMutationMessage(*flags.message) } if *flags.noPrompt || !interactiveTerminal() { return "", nil } pref, err := configMessagePrompt() if err != nil { return "", err } if pref == "off" { return "", nil } return validateMutationMessage(promptLine(stdout, mutationMessageText.Prompt)) } func validateMutationMessage(message string) (string, error) { if !utf8.ValidString(message) || utf8.RuneCountInString(message) > mutationMessageMaxRunes { return "", errors.New(mutationMessageText.Invalid) } for _, r := range message { if unicode.IsControl(r) { return "", errors.New(mutationMessageText.Invalid) } } return strings.TrimSpace(message), nil }