github.com/wtfutil/wtf@v0.43.0/modules/git/widget.go (about) 1 package git 2 3 import ( 4 "log" 5 "os" 6 "strings" 7 8 "github.com/gdamore/tcell/v2" 9 "github.com/rivo/tview" 10 "github.com/wtfutil/wtf/utils" 11 "github.com/wtfutil/wtf/view" 12 ) 13 14 const ( 15 modalHeight = 7 16 modalWidth = 80 17 offscreen = -1000 18 ) 19 20 type Widget struct { 21 view.MultiSourceWidget 22 view.TextWidget 23 24 GitRepos []*GitRepo 25 26 pages *tview.Pages 27 settings *Settings 28 tviewApp *tview.Application 29 } 30 31 func NewWidget(tviewApp *tview.Application, redrawChan chan bool, pages *tview.Pages, settings *Settings) *Widget { 32 widget := Widget{ 33 MultiSourceWidget: view.NewMultiSourceWidget(settings.Common, "repository", "repositories"), 34 TextWidget: view.NewTextWidget(tviewApp, redrawChan, pages, settings.Common), 35 36 tviewApp: tviewApp, 37 pages: pages, 38 settings: settings, 39 } 40 41 widget.initializeKeyboardControls() 42 43 widget.SetDisplayFunction(widget.display) 44 45 return &widget 46 } 47 48 /* -------------------- Exported Functions -------------------- */ 49 50 func (widget *Widget) Checkout() { 51 form := widget.modalForm("Branch to checkout:", "") 52 53 checkoutFctn := func() { 54 text := form.GetFormItem(0).(*tview.InputField).GetText() 55 repoToCheckout := widget.GitRepos[widget.Idx] 56 repoToCheckout.checkout(text) 57 widget.pages.RemovePage("modal") 58 widget.tviewApp.SetFocus(widget.View) 59 widget.display() 60 widget.Refresh() 61 } 62 63 widget.addButtons(form, checkoutFctn) 64 widget.modalFocus(form) 65 } 66 67 func (widget *Widget) Pull() { 68 repoToPull := widget.GitRepos[widget.Idx] 69 repoToPull.pull() 70 widget.Refresh() 71 72 } 73 74 func (widget *Widget) Refresh() { 75 repoPaths := utils.ToStrs(widget.settings.repositories) 76 77 widget.GitRepos = widget.gitRepos(repoPaths) 78 79 widget.display() 80 } 81 82 /* -------------------- Unexported Functions -------------------- */ 83 84 func (widget *Widget) addCheckoutButton(form *tview.Form, fctn func()) { 85 form.AddButton("Checkout", fctn) 86 } 87 88 func (widget *Widget) addButtons(form *tview.Form, checkoutFctn func()) { 89 widget.addCheckoutButton(form, checkoutFctn) 90 widget.addCancelButton(form) 91 } 92 93 func (widget *Widget) addCancelButton(form *tview.Form) { 94 cancelFn := func() { 95 widget.pages.RemovePage("modal") 96 widget.tviewApp.SetFocus(widget.View) 97 widget.display() 98 } 99 100 form.AddButton("Cancel", cancelFn) 101 form.SetCancelFunc(cancelFn) 102 } 103 104 func (widget *Widget) modalFocus(form *tview.Form) { 105 frame := widget.modalFrame(form) 106 widget.pages.AddPage("modal", frame, false, true) 107 widget.tviewApp.SetFocus(frame) 108 } 109 110 func (widget *Widget) modalForm(lbl, text string) *tview.Form { 111 form := tview.NewForm() 112 form.SetButtonsAlign(tview.AlignCenter) 113 form.SetButtonTextColor(tview.Styles.PrimaryTextColor) 114 115 form.AddInputField(lbl, text, 60, nil, nil) 116 117 return form 118 } 119 120 func (widget *Widget) modalFrame(form *tview.Form) *tview.Frame { 121 frame := tview.NewFrame(form) 122 frame.SetBorders(0, 0, 0, 0, 0, 0) 123 frame.SetRect(offscreen, offscreen, modalWidth, modalHeight) 124 frame.SetBorder(true) 125 frame.SetBorders(1, 1, 0, 0, 1, 1) 126 127 drawFunc := func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) { 128 w, h := screen.Size() 129 frame.SetRect((w/2)-(width/2), (h/2)-(height/2), width, height) 130 return x, y, width, height 131 } 132 133 frame.SetDrawFunc(drawFunc) 134 135 return frame 136 } 137 138 func (widget *Widget) currentData() *GitRepo { 139 if len(widget.GitRepos) == 0 { 140 return nil 141 } 142 143 if widget.Idx < 0 || widget.Idx >= len(widget.GitRepos) { 144 return nil 145 } 146 147 return widget.GitRepos[widget.Idx] 148 } 149 150 func (widget *Widget) gitRepos(repoPaths []string) []*GitRepo { 151 repos := []*GitRepo{} 152 153 for _, repoPath := range repoPaths { 154 if strings.HasSuffix(repoPath, string(os.PathSeparator)) { 155 repos = append(repos, widget.findGitRepositories(make([]*GitRepo, 0), repoPath)...) 156 157 } else { 158 repo := NewGitRepo( 159 repoPath, 160 widget.settings.commitCount, 161 widget.settings.commitFormat, 162 widget.settings.dateFormat, 163 ) 164 165 repos = append(repos, repo) 166 } 167 } 168 169 return repos 170 } 171 172 func (widget *Widget) findGitRepositories(repositories []*GitRepo, directory string) []*GitRepo { 173 directory = strings.TrimSuffix(directory, string(os.PathSeparator)) 174 175 files, err := os.ReadDir(directory) 176 if err != nil { 177 log.Fatal(err) 178 } 179 180 var path string 181 182 for _, file := range files { 183 if file.IsDir() { 184 path = directory + string(os.PathSeparator) + file.Name() 185 186 if file.Name() == ".git" { 187 path = strings.TrimSuffix(path, string(os.PathSeparator)+".git") 188 189 repo := NewGitRepo( 190 path, 191 widget.settings.commitCount, 192 widget.settings.commitFormat, 193 widget.settings.dateFormat, 194 ) 195 196 repositories = append(repositories, repo) 197 continue 198 } 199 if file.Name() == "vendor" || file.Name() == "node_modules" { 200 continue 201 } 202 repositories = widget.findGitRepositories(repositories, path) 203 } 204 } 205 206 return repositories 207 }