github.com/fredbi/git-chglog@v0.0.0-20190706071416-d35c598eac81/cmd/git-chglog/questioner.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "path/filepath" 7 "strings" 8 9 gitcmd "github.com/tsuyoshiwada/go-gitcmd" 10 survey "gopkg.in/AlecAivazis/survey.v1" 11 ) 12 13 // Answer ... 14 type Answer struct { 15 RepositoryURL string `survey:"repository_url"` 16 Style string `survey:"style"` 17 CommitMessageFormat string `survey:"commit_message_format"` 18 Template string `survey:"template"` 19 IncludeMerges bool `survey:"include_merges"` 20 IncludeReverts bool `survey:"include_reverts"` 21 ConfigDir string `survey:"config_dir"` 22 } 23 24 // Questioner ... 25 type Questioner interface { 26 Ask() (*Answer, error) 27 } 28 29 type questionerImpl struct { 30 client gitcmd.Client 31 fs FileSystem 32 } 33 34 // NewQuestioner ... 35 func NewQuestioner(client gitcmd.Client, fs FileSystem) Questioner { 36 return &questionerImpl{ 37 client: client, 38 fs: fs, 39 } 40 } 41 42 // Ask ... 43 func (q *questionerImpl) Ask() (*Answer, error) { 44 ans, err := q.ask() 45 if err != nil { 46 return nil, err 47 } 48 49 config := filepath.Join(ans.ConfigDir, defaultConfigFilename) 50 tpl := filepath.Join(ans.ConfigDir, defaultTemplateFilename) 51 c := q.fs.Exists(config) 52 t := q.fs.Exists(tpl) 53 msg := "" 54 55 if c && t { 56 msg = fmt.Sprintf("\"%s\" and \"%s\" already exists. Do you want to overwrite?", config, tpl) 57 } else if c { 58 msg = fmt.Sprintf("\"%s\" already exists. Do you want to overwrite?", config) 59 } else if t { 60 msg = fmt.Sprintf("\"%s\" already exists. Do you want to overwrite?", tpl) 61 } 62 63 if msg != "" { 64 overwrite := false 65 err = survey.AskOne(&survey.Confirm{ 66 Message: msg, 67 Default: true, 68 }, &overwrite, nil) 69 70 if err != nil || !overwrite { 71 return nil, errors.New("creation of the file was interrupted") 72 } 73 } 74 75 return ans, nil 76 } 77 78 func (q *questionerImpl) ask() (*Answer, error) { 79 ans := &Answer{} 80 fmts := q.getPreviewableList(formats) 81 tpls := q.getPreviewableList(templates) 82 83 var previewableTransform = func(ans interface{}) (newAns interface{}) { 84 if s, ok := ans.(string); ok { 85 newAns = q.parsePreviewableList(s) 86 } 87 return 88 } 89 90 questions := []*survey.Question{ 91 { 92 Name: "repository_url", 93 Prompt: &survey.Input{ 94 Message: "What is the URL of your repository?", 95 Default: q.getRepositoryURL(), 96 }, 97 }, 98 { 99 Name: "style", 100 Prompt: &survey.Select{ 101 Message: "What is your favorite style?", 102 Options: styles, 103 Default: styles[0], 104 }, 105 }, 106 { 107 Name: "commit_message_format", 108 Prompt: &survey.Select{ 109 Message: "Choose the format of your favorite commit message", 110 Options: fmts, 111 Default: fmts[0], 112 }, 113 Transform: previewableTransform, 114 }, 115 { 116 Name: "template", 117 Prompt: &survey.Select{ 118 Message: "What is your favorite template style?", 119 Options: tpls, 120 Default: tpls[0], 121 }, 122 Transform: previewableTransform, 123 }, 124 { 125 Name: "include_merges", 126 Prompt: &survey.Confirm{ 127 Message: "Do you include Merge Commit in CHANGELOG?", 128 Default: true, 129 }, 130 }, 131 { 132 Name: "include_reverts", 133 Prompt: &survey.Confirm{ 134 Message: "Do you include Revert Commit in CHANGELOG?", 135 Default: true, 136 }, 137 }, 138 { 139 Name: "config_dir", 140 Prompt: &survey.Input{ 141 Message: "In which directory do you output configuration files and templates?", 142 Default: defaultConfigDir, 143 }, 144 }, 145 } 146 147 err := survey.Ask(questions, ans) 148 if err != nil { 149 return nil, err 150 } 151 152 return ans, nil 153 } 154 155 func (*questionerImpl) getPreviewableList(list []Previewable) []string { 156 arr := make([]string, len(list)) 157 max := 0 158 159 for _, p := range list { 160 l := len(p.Display()) 161 if max < l { 162 max = l 163 } 164 } 165 166 for i, p := range list { 167 arr[i] = fmt.Sprintf( 168 "%s -- %s", 169 p.Display()+strings.Repeat(" ", max-len(p.Display())), 170 p.Preview(), 171 ) 172 } 173 174 return arr 175 } 176 177 func (*questionerImpl) parsePreviewableList(input string) string { 178 return strings.TrimSpace(strings.Split(input, "--")[0]) 179 } 180 181 func (q *questionerImpl) getRepositoryURL() string { 182 if q.client.CanExec() != nil || q.client.InsideWorkTree() != nil { 183 return "" 184 } 185 186 rawurl, err := q.client.Exec("config", "--get", "remote.origin.url") 187 if err != nil { 188 return "" 189 } 190 191 return remoteOriginURLToHTTP(rawurl) 192 }