From 6df8108fc8ddee4841bbbf38f457232a5af0eba8 Mon Sep 17 00:00:00 2001 From: Ibrahim Serdar Acikgoz Date: Wed, 28 Nov 2018 23:16:42 +0300 Subject: handle styles in a more convenient way --- pkg/git/repository.go | 13 +++++- pkg/gui/branchview.go | 4 +- pkg/gui/commitsview.go | 4 +- pkg/gui/gui-util.go | 10 +--- pkg/gui/gui.go | 7 +-- pkg/gui/keybindings.go | 23 +++++----- pkg/gui/mainview.go | 86 ++--------------------------------- pkg/gui/remotebranchview.go | 4 +- pkg/gui/remotesview.go | 10 ++-- pkg/gui/textstyle.go | 108 ++++++++++++++++++++++++++++++++++++++++++++ pkg/job/job.go | 23 +++++++++- pkg/utils/utils.go | 39 ---------------- 12 files changed, 175 insertions(+), 156 deletions(-) create mode 100644 pkg/gui/textstyle.go diff --git a/pkg/git/repository.go b/pkg/git/repository.go index 8c6366c..f019731 100644 --- a/pkg/git/repository.go +++ b/pkg/git/repository.go @@ -46,7 +46,7 @@ func InitializeRepository(directory string) (entity *RepoEntity, err error) { if err != nil { return nil, err } - entity = &RepoEntity{RepoID: utils.NewHash(), + entity = &RepoEntity{RepoID: utils.RandomString(8), Name: fileInfo.Name(), AbsPath: directory, Repository: *r, @@ -105,6 +105,17 @@ func (entity *RepoEntity) Fetch() error { entity.Checkout(entity.Branch) return nil } + +func (entity *RepoEntity) Merge() error { + entity.Checkout(entity.Branch) + if err := entity.MergeWithGit(entity.Remote.Branch.Name); err != nil { + entity.Refresh() + return err + } + entity.Refresh() + return nil +} + func (entity *RepoEntity) Refresh() error { r, err := git.PlainOpen(entity.AbsPath) if err != nil { diff --git a/pkg/gui/branchview.go b/pkg/gui/branchview.go index 05e079f..1983656 100644 --- a/pkg/gui/branchview.go +++ b/pkg/gui/branchview.go @@ -20,10 +20,10 @@ func (gui *Gui) updateBranch(g *gocui.Gui, entity *git.RepoEntity) error { for i, b := range entity.Branches { if b.Name == entity.Branch.Name { currentindex = i - fmt.Fprintln(out, selectionIndicator()+b.Name) + fmt.Fprintln(out, selectionIndicator+b.Name) continue } - fmt.Fprintln(out, tab()+b.Name) + fmt.Fprintln(out, tab+b.Name) } if err = gui.smartAnchorRelativeToLine(out, currentindex, totalbranches); err != nil { return err diff --git a/pkg/gui/commitsview.go b/pkg/gui/commitsview.go index 200b962..81c81bd 100644 --- a/pkg/gui/commitsview.go +++ b/pkg/gui/commitsview.go @@ -22,10 +22,10 @@ func (gui *Gui) updateCommits(g *gocui.Gui, entity *git.RepoEntity) error { for i, c := range entity.Commits { if c.Hash == entity.Commit.Hash { currentindex = i - fmt.Fprintln(out, selectionIndicator()+green.Sprint(c.Hash[:git.Hashlimit])+" "+c.Message) + fmt.Fprintln(out, selectionIndicator+green.Sprint(c.Hash[:git.Hashlimit])+" "+c.Message) continue } - fmt.Fprintln(out, tab()+cyan.Sprint(c.Hash[:git.Hashlimit])+" "+c.Message) + fmt.Fprintln(out, tab+cyan.Sprint(c.Hash[:git.Hashlimit])+" "+c.Message) } if err = gui.smartAnchorRelativeToLine(out, currentindex, totalcommits); err != nil { return err diff --git a/pkg/gui/gui-util.go b/pkg/gui/gui-util.go index 7f30bed..0f2252c 100644 --- a/pkg/gui/gui-util.go +++ b/pkg/gui/gui-util.go @@ -39,6 +39,8 @@ func (gui *Gui) switchMode(g *gocui.Gui, v *gocui.View) error { case FetchMode: gui.State.Mode = pullMode case PullMode: + gui.State.Mode = mergeMode + case MergeMode: gui.State.Mode = fetchMode default: gui.State.Mode = fetchMode @@ -97,14 +99,6 @@ func (gui *Gui) smartAnchorRelativeToLine(v *gocui.View, currentindex, totalline return nil } -func selectionIndicator() string { - return green.Sprint("→ ") -} - -func tab() string { - return green.Sprint(" ") -} - func writeRightHandSide(v *gocui.View, text string, cx, cy int) error { runes := []rune(text) tl := len(runes) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index cf35a17..658a4a8 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -30,7 +30,6 @@ type mode struct { ModeID ModeID DisplayString string CommandString string - ExecString string } type ModeID int8 @@ -38,6 +37,7 @@ type ModeID int8 const ( FetchMode ModeID = 0 PullMode ModeID = 1 + MergeMode ModeID = 2 ) var ( @@ -53,8 +53,9 @@ var ( cheatSheetViewFeature = viewFeature{Name: "cheatsheet", Title: " Application Controls "} errorViewFeature = viewFeature{Name: "error", Title: " Error "} - fetchMode = mode{ModeID: FetchMode, DisplayString: "Fetch", CommandString: "fetch", ExecString: "repositories will be fetched"} - pullMode = mode{ModeID: PullMode, DisplayString: "Pull", CommandString: "pull", ExecString: "repositories will be pulled"} + fetchMode = mode{ModeID: FetchMode, DisplayString: "Fetch", CommandString: "fetch"} + pullMode = mode{ModeID: PullMode, DisplayString: "Pull", CommandString: "pull"} + mergeMode = mode{ModeID: MergeMode, DisplayString: "Merge", CommandString: "merge"} ) func NewGui(directoies []string) (*Gui, error) { diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 599d471..55e90cc 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -185,31 +185,32 @@ func (gui *Gui) updateKeyBindingsView(g *gocui.Gui, viewName string) error { v.BgColor = gocui.ColorWhite v.FgColor = gocui.ColorBlack v.Frame = false + fmt.Fprint(v, ws) + switch mode := gui.State.Mode.ModeID; mode { case FetchMode: v.BgColor = gocui.ColorBlue v.FgColor = gocui.ColorWhite - fmt.Fprint(v, " ↓ Fetch Mode █▓▒") + fmt.Fprint(v, "↓ Fetch Mode") case PullMode: v.BgColor = gocui.ColorMagenta v.FgColor = gocui.ColorWhite - fmt.Fprint(v, " ↓↳ Pull Mode █▓▒") + fmt.Fprint(v, "↓↳ Pull Mode") + case MergeMode: + v.BgColor = gocui.ColorCyan + v.FgColor = gocui.ColorBlack + fmt.Fprint(v, "↳ Merge Mode") default: writeRightHandSide(v, "No-Mode", 0, 0) } + + fmt.Fprint(v, ws + modeSeperator) + for _, k := range gui.KeyBindings { if k.View == viewName && k.Vital { - binding := "░ " + k.Display + ": " + k.Description + " " + binding := keyBindingSeperator + ws + k.Display + ":" + ws + k.Description + ws fmt.Fprint(v, binding) } } - // switch mode := gui.State.Mode.ModeID; mode { - // case FetchMode: - // writeRightHandSide(v, " ⭠ Fetch", 0, 0) - // case PullMode: - // writeRightHandSide(v, " ⭠ Pull", 0, 0) - // default: - // writeRightHandSide(v, "No-Mode", 0, 0) - // } return nil } diff --git a/pkg/gui/mainview.go b/pkg/gui/mainview.go index aca5daf..a9fb17a 100644 --- a/pkg/gui/mainview.go +++ b/pkg/gui/mainview.go @@ -2,8 +2,6 @@ package gui import ( "fmt" - // "regexp" - // "sync" "github.com/isacikgoz/gitbatch/pkg/git" "github.com/isacikgoz/gitbatch/pkg/job" @@ -17,7 +15,7 @@ func (gui *Gui) fillMain(g *gocui.Gui) error { return err } for _, r := range gui.State.Repositories { - fmt.Fprintln(v, displayString(r)) + fmt.Fprintln(v, gui.displayString(r)) } err = g.DeleteView(loadingViewFeature.Name) if err != nil { @@ -80,23 +78,13 @@ func (gui *Gui) cursorUp(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) getSelectedRepository(g *gocui.Gui, v *gocui.View) (*git.RepoEntity, error) { - // var l string - var err error var r *git.RepoEntity _, cy := v.Cursor() - if _, err = v.Line(cy); err != nil { + if _, err := v.Line(cy); err != nil { return r, err } return gui.State.Repositories[cy], nil - // rg := regexp.MustCompile(` → .+ `) - // ss := rg.Split(l, 5) - // for _, sr := range gui.State.Repositories { - // if ss[len(ss)-1] == sr.Name { - // return sr, nil - // } - // } - return r, err } func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error { @@ -106,12 +94,6 @@ func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error { if err != nil { return err } - // if !r.Branch.Clean { - // if err = gui.openErrorView(g, "Stage your changes before pull", "You should manually resolve this issue"); err != nil { - // return err - // } - // return nil - // } if r.State == git.Available || r.State == git.Success { var jt job.JobType switch mode := gui.State.Mode.ModeID; mode { @@ -119,6 +101,8 @@ func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error { jt = job.Fetch case PullMode: jt = job.Pull + case MergeMode: + jt = job.Merge default: return nil } @@ -152,67 +136,7 @@ func (gui *Gui) refreshMain(g *gocui.Gui) error { } mainView.Clear() for _, r := range gui.State.Repositories { - fmt.Fprintln(mainView, displayString(r)) + fmt.Fprintln(mainView, gui.displayString(r)) } return nil } - -func displayString(entity *git.RepoEntity) string { - - prefix := "" - if entity.Branch.Pushables != "?" { - prefix = prefix + string(blue.Sprint("↖")) + " " + entity.Branch.Pushables + " " + - string(blue.Sprint("↘")) + " " + entity.Branch.Pullables + string(magenta.Sprint(" → ")) - } else { - prefix = prefix + " " + magenta.Sprint("?") + string(yellow.Sprint(" → ")) - } - branch := "" + entity.Branch.Name - if len(branch) > 16 { - branch = branch[:13] + "..." - } - prefix = prefix + string(cyan.Sprint(branch)) - if !entity.Branch.Clean { - prefix = prefix + string(yellow.Sprint("✗") + " ") - } else { - prefix = prefix + " " - } - if entity.State == git.Queued { - return prefix + entity.Name + " " + string(green.Sprint("•") + " ") - } else if entity.State == git.Working { - return prefix + entity.Name + " " + string(blue.Sprint("•") + " ") - } else if entity.State == git.Success { - return prefix + entity.Name + " " + string(green.Sprint("✔") + " ") - } else if entity.State == git.Fail { - return prefix + entity.Name + " " + string(red.Sprint("✗") + " ") - } else { - return prefix + entity.Name - } -} - -// func displayString(entity *git.RepoEntity) string { - -// prefix := "" -// if entity.Branch.Pushables != "?" { -// prefix = prefix + string(blue.Sprint("↑")) + " " + entity.Branch.Pushables + " " + -// string(blue.Sprint("↓")) + " " + entity.Branch.Pullables + " " -// } else { -// prefix = prefix + " " + magenta.Sprint("?") -// } -// if !entity.Branch.Clean { -// prefix = prefix + " " + string(yellow.Sprint("✗") + " ") -// } else { -// prefix = prefix + " " + string(magenta.Sprint(" ")) -// } -// prefix = prefix + " " + string(cyan.Sprint(entity.Branch.Name)) + " " -// if entity.State == git.Queued { -// return prefix + entity.Name + " " + string(blue.Sprint("•") + " ") -// } else if entity.State == git.Working { -// return prefix + entity.Name + " " + string(blue.Sprint("•") + " ") -// } else if entity.State == git.Success { -// return prefix + entity.Name + " " + string(green.Sprint("✔") + " ") -// } else if entity.State == git.Fail { -// return prefix + entity.Name + " " + string(red.Sprint("✗") + " ") -// } else { -// return prefix + entity.Name -// } -// } diff --git a/pkg/gui/remotebranchview.go b/pkg/gui/remotebranchview.go index adc5dcb..ea81d4c 100644 --- a/pkg/gui/remotebranchview.go +++ b/pkg/gui/remotebranchview.go @@ -21,10 +21,10 @@ func (gui *Gui) updateRemoteBranches(g *gocui.Gui, entity *git.RepoEntity) error for i, r := range entity.Remote.Branches { if r.Name == entity.Remote.Branch.Name { currentindex = i - fmt.Fprintln(out, selectionIndicator()+r.Name) + fmt.Fprintln(out, selectionIndicator+r.Name) continue } - fmt.Fprintln(out, tab()+r.Name) + fmt.Fprintln(out, tab+r.Name) } if err = gui.smartAnchorRelativeToLine(out, currentindex, trb); err != nil { return err diff --git a/pkg/gui/remotesview.go b/pkg/gui/remotesview.go index bbc6ce4..c156f2b 100644 --- a/pkg/gui/remotesview.go +++ b/pkg/gui/remotesview.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/isacikgoz/gitbatch/pkg/git" - "github.com/isacikgoz/gitbatch/pkg/utils" + "github.com/jroimartin/gocui" ) @@ -21,14 +21,14 @@ func (gui *Gui) updateRemotes(g *gocui.Gui, entity *git.RepoEntity) error { totalRemotes := len(entity.Remotes) if totalRemotes > 0 { for i, r := range entity.Remotes { - URLtype, shortURL := utils.TrimRemoteURL(r.URL[0]) - suffix := "(" + URLtype + ")" + " " + shortURL + _, shortURL := trimRemoteURL(r.URL[0]) + suffix := shortURL if r.Name == entity.Remote.Name { currentindex = i - fmt.Fprintln(out, selectionIndicator()+r.Name+": "+suffix) + fmt.Fprintln(out, selectionIndicator+r.Name+": "+suffix) continue } - fmt.Fprintln(out, tab()+r.Name+": "+suffix) + fmt.Fprintln(out, tab+r.Name+": "+suffix) } if err = gui.smartAnchorRelativeToLine(out, currentindex, totalRemotes); err != nil { return err diff --git a/pkg/gui/textstyle.go b/pkg/gui/textstyle.go new file mode 100644 index 0000000..1514b46 --- /dev/null +++ b/pkg/gui/textstyle.go @@ -0,0 +1,108 @@ +package gui + +import ( + "regexp" + + "github.com/isacikgoz/gitbatch/pkg/git" + "github.com/isacikgoz/gitbatch/pkg/job" +) + +var ( + maxBranchLength = 15 + maxRepositoryLength = 20 + + ws = " " + pushable = string(blue.Sprint("↖")) + pullable = string(blue.Sprint("↘")) + confidentArrow = string(magenta.Sprint("→")) + unconfidentArrow = string(yellow.Sprint("→")) + dirty = string(yellow.Sprint("✗")) + unkown = magenta.Sprint("?") + + queuedSymbol = "•" + workingSymbol = "•" + successSymbol = "✔" + failSymbol = "✗" + + modeSeperator = "▓▒" + keyBindingSeperator = "░" + + selectionIndicator = string(green.Sprint("→")) + ws + tab = ws + ws +) + +func (gui *Gui) displayString(entity *git.RepoEntity) string { + suffix := "" + prefix := "" + + if entity.Branch.Pushables != "?" { + prefix = prefix + pushable + ws + entity.Branch.Pushables + ws + + pullable + ws + entity.Branch.Pullables + ws + confidentArrow + ws + } else { + prefix = prefix + unkown + ws + unconfidentArrow + ws + } + + branch := adjustTextLength(entity.Branch.Name, maxBranchLength) + prefix = prefix + string(cyan.Sprint(branch)) + + if !entity.Branch.Clean { + prefix = prefix + ws + dirty + ws + } else { + prefix = prefix + ws + } + + if entity.State == git.Queued { + if inQueue, ty := gui.State.Queue.IsInTheQueue(entity); inQueue { + switch mode := ty; mode { + case job.Fetch: + suffix = blue.Sprint(queuedSymbol) + case job.Pull: + suffix = magenta.Sprint(queuedSymbol) + case job.Merge: + suffix = cyan.Sprint(queuedSymbol) + default: + suffix = green.Sprint(queuedSymbol) + } + } + return prefix + entity.Name + ws + suffix + } else if entity.State == git.Working { + return prefix + entity.Name + ws + green.Sprint(workingSymbol) + } else if entity.State == git.Success { + return prefix + entity.Name + ws + green.Sprint(successSymbol) + } else if entity.State == git.Fail { + return prefix + entity.Name + ws + red.Sprint(failSymbol) + } else { + return prefix + entity.Name + } +} + +func adjustTextLength(text string, maxLength int) (adjusted string) { + if len(text) > maxLength { + adjusted := text[:maxLength-2] + ".." + return adjusted + } else { + return text + } +} + +func trimRemoteURL(url string) (urltype string, shorturl string) { + regit := regexp.MustCompile(`.git`) + if regit.MatchString(url[len(url)-4:]) { + url = url[:len(url)-4] + } + ressh := regexp.MustCompile(`git@`) + rehttp := regexp.MustCompile(`http://`) + rehttps := regexp.MustCompile(`https://`) + + if ressh.MatchString(url) { + shorturl = ressh.Split(url, 5)[1] + urltype = "ssh" + } else if rehttp.MatchString(url) { + shorturl = rehttp.Split(url, 5)[1] + urltype = "http" + } else if rehttps.MatchString(url) { + shorturl = rehttps.Split(url, 5)[1] + urltype = "https" + } + return urltype, shorturl +} diff --git a/pkg/job/job.go b/pkg/job/job.go index 8341e69..9638292 100644 --- a/pkg/job/job.go +++ b/pkg/job/job.go @@ -20,8 +20,9 @@ type JobQueue struct { type JobType string const ( - Fetch JobType = "FETCH" - Pull JobType = "PULL" + Fetch JobType = "fetch" + Pull JobType = "pull" + Merge JobType = "merge" ) func CreateJob() (j *Job, err error) { @@ -48,6 +49,13 @@ func (job *Job) start() error { } job.Entity.RefreshPushPull() job.Entity.State = git.Success + case Merge: + if err := job.Entity.Merge(); err != nil { + job.Entity.State = git.Fail + return nil + } + job.Entity.RefreshPushPull() + job.Entity.State = git.Success default: job.Entity.State = git.Available return nil @@ -100,3 +108,14 @@ func (jobQueue *JobQueue) RemoveFromQueue(entity *git.RepoEntity) error { } return nil } + +func (jobQueue *JobQueue) IsInTheQueue(entity *git.RepoEntity) (inTheQueue bool, jt JobType) { + inTheQueue = false + for _, job := range jobQueue.series { + if job.Entity.RepoID == entity.RepoID { + inTheQueue = true + jt = job.JobType + } + } + return inTheQueue, jt +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 05fcc8e..d4a4b4e 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -1,10 +1,7 @@ package utils import ( - "crypto/sha1" - "fmt" "math/rand" - "regexp" "strings" "time" ) @@ -26,24 +23,6 @@ func Min(x, y int) int { return y } -func TrimRemoteURL(url string) (urltype string, shorturl string) { - ressh := regexp.MustCompile(`git@`) - rehttp := regexp.MustCompile(`http://`) - rehttps := regexp.MustCompile(`https://`) - - if ressh.MatchString(url) { - shorturl = ressh.Split(url, 5)[1] - urltype = "ssh" - } else if rehttp.MatchString(url) { - shorturl = rehttp.Split(url, 5)[1] - urltype = "http" - } else if rehttps.MatchString(url) { - shorturl = rehttps.Split(url, 5)[1] - urltype = "https" - } - return urltype, shorturl -} - // RandomString generates a random string of n length func RandomString(n int) string { b := make([]rune, n) @@ -52,21 +31,3 @@ func RandomString(n int) string { } return string(b) } - -// NewSHA1Hash generates a new SHA1 hash based on -// a random number of characters. -func NewHash(n ...int) string { - noRandomCharacters := 32 - - if len(n) > 0 { - noRandomCharacters = n[0] - } - - randString := RandomString(noRandomCharacters) - - hash := sha1.New() - hash.Write([]byte(randString)) - bs := hash.Sum(nil) - - return fmt.Sprintf("%x", bs) -} -- cgit v1.2.3