diff --git a/main.go b/main.go index 93ba6ab3..b1941d35 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "io/ioutil" "os" "strings" + + pwl "github.com/justjanne/powerline-go/powerline" ) type alignment int @@ -88,7 +90,7 @@ func getValidCwd() string { return cwd } -var modules = map[string]func(*powerline){ +var modules = map[string]func(*powerline) []pwl.Segment{ "aws": segmentAWS, "cwd": segmentCwd, "docker": segmentDocker, diff --git a/powerline.go b/powerline.go index 8e66ad58..d7cda3a4 100644 --- a/powerline.go +++ b/powerline.go @@ -6,6 +6,7 @@ import ( "os" "strconv" "strings" + "sync" pwl "github.com/justjanne/powerline-go/powerline" "github.com/mattn/go-runewidth" @@ -43,6 +44,11 @@ type powerline struct { appendEastAsianPadding int } +type prioritizedSegments struct { + i int + segs []pwl.Segment +} + func newPowerline(args args, cwd string, priorities map[string]int, align alignment) *powerline { p := new(powerline) p.args = args @@ -82,17 +88,48 @@ func newPowerline(args args, cwd string, priorities map[string]int, align alignm } else { mods = *args.ModulesRight } - for _, module := range strings.Split(mods, ",") { - elem, ok := modules[module] - if ok { - elem(p) - } else { - if ok := segmentPlugin(p, module); !ok { - println("Module not found: " + module) + initSegments(p, strings.Split(mods, ",")) + + return p +} + +func initSegments(p *powerline, mods []string) { + orderedSegments := map[int][]pwl.Segment{} + c := make(chan prioritizedSegments, len(mods)) + wg := sync.WaitGroup{} + for i, module := range mods { + wg.Add(1) + go func(w *sync.WaitGroup, i int, module string, c chan prioritizedSegments) { + elem, ok := modules[module] + if ok { + c <- prioritizedSegments{ + i: i, + segs: elem(p), + } + } else { + s, ok := segmentPlugin(p, module) + if ok { + c <- prioritizedSegments{ + i: i, + segs: s, + } + } else { + println("Module not found: " + module) + } } + wg.Done() + }(&wg, i, module, c) + } + wg.Wait() + close(c) + for s := range c { + orderedSegments[s.i] = s.segs + } + for i := 0; i < len(mods); i++ { + for _, seg := range orderedSegments[i] { + p.appendSegment(seg.Name, seg) } } - return p } func (p *powerline) color(prefix string, code uint8) string { @@ -128,7 +165,11 @@ func (p *powerline) appendSegment(origin string, segment pwl.Segment) { priority, _ := p.priorities[origin] segment.Priority += priority segment.Width = segment.ComputeWidth(*p.args.Condensed) - p.Segments[p.curSegment] = append(p.Segments[p.curSegment], segment) + if segment.NewLine { + p.newRow() + } else { + p.Segments[p.curSegment] = append(p.Segments[p.curSegment], segment) + } } func (p *powerline) newRow() { diff --git a/powerline/powerline.go b/powerline/powerline.go index 1bac59a4..d0f6234d 100644 --- a/powerline/powerline.go +++ b/powerline/powerline.go @@ -6,6 +6,7 @@ import ( // Segment describes an information to display on the command line prompt type Segment struct { + Name string // Content is the text to be displayed on the command line prompt Content string // Foreground is the text color (see https://misc.flogisoft.com/bash/tip_colors_and_formatting#background1) @@ -21,6 +22,8 @@ type Segment struct { // HideSeparators indicated not to display any separator with next segment. HideSeparators bool Width int + // NewLine defines a newline segment to break the powerline in multi lines + NewLine bool } func (s Segment) ComputeWidth(condensed bool) int { diff --git a/segment-aws.go b/segment-aws.go index 776e6474..e039f62b 100644 --- a/segment-aws.go +++ b/segment-aws.go @@ -5,7 +5,7 @@ import ( "os" ) -func segmentAWS(p *powerline) { +func segmentAWS(p *powerline) []pwl.Segment { profile := os.Getenv("AWS_PROFILE") region := os.Getenv("AWS_DEFAULT_REGION") if profile != "" { @@ -13,10 +13,12 @@ func segmentAWS(p *powerline) { if region != "" { r = " (" + region + ")" } - p.appendSegment("aws", pwl.Segment{ + return []pwl.Segment{{ + Name: "aws", Content: profile + r, Foreground: p.theme.AWSFg, Background: p.theme.AWSBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-cwd.go b/segment-cwd.go index 28160dc2..bc914b4a 100644 --- a/segment-cwd.go +++ b/segment-cwd.go @@ -156,7 +156,7 @@ func getColor(p *powerline, pathSegment pathSegment, isLastDir bool) (uint8, uin return p.theme.PathFg, p.theme.PathBg, false } -func segmentCwd(p *powerline) { +func segmentCwd(p *powerline) (segments []pwl.Segment) { cwd := p.cwd if cwd == "" { cwd, _ = os.LookupEnv("PWD") @@ -168,7 +168,8 @@ func segmentCwd(p *powerline) { cwd = "~" + cwd[len(home):] } - p.appendSegment("cwd", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "cwd", Content: cwd, Foreground: p.theme.CwdFg, Background: p.theme.PathBg, @@ -222,12 +223,13 @@ func segmentCwd(p *powerline) { } } - origin := "cwd-path" + segment.Name = "cwd-path" if isLastDir { - origin = "cwd" + segment.Name = "cwd" } - p.appendSegment(origin, segment) + segments = append(segments, segment) } } + return segments } diff --git a/segment-docker.go b/segment-docker.go index ce77fa45..f7fa2da0 100644 --- a/segment-docker.go +++ b/segment-docker.go @@ -7,7 +7,7 @@ import ( pwl "github.com/justjanne/powerline-go/powerline" ) -func segmentDocker(p *powerline) { +func segmentDocker(p *powerline) []pwl.Segment { var docker string dockerMachineName, _ := os.LookupEnv("DOCKER_MACHINE_NAME") dockerHost, _ := os.LookupEnv("DOCKER_HOST") @@ -22,10 +22,12 @@ func segmentDocker(p *powerline) { } if docker != "" { - p.appendSegment("docker", pwl.Segment{ + return []pwl.Segment{{ + Name: "docker", Content: docker, Foreground: p.theme.DockerMachineFg, Background: p.theme.DockerMachineBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-dotenv.go b/segment-dotenv.go index 5522afbd..c3c28b71 100644 --- a/segment-dotenv.go +++ b/segment-dotenv.go @@ -5,7 +5,7 @@ import ( "os" ) -func segmentDotEnv(p *powerline) { +func segmentDotEnv(p *powerline) []pwl.Segment { files := []string{".env", ".envrc"} dotEnv := false for _, file := range files { @@ -16,10 +16,12 @@ func segmentDotEnv(p *powerline) { } } if dotEnv { - p.appendSegment("dotenv", pwl.Segment{ + return []pwl.Segment{{ + Name: "dotenv", Content: "\u2235", Foreground: p.theme.DotEnvFg, Background: p.theme.DotEnvBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-duration.go b/segment-duration.go index 26e70650..de5b2b70 100644 --- a/segment-duration.go +++ b/segment-duration.go @@ -26,14 +26,14 @@ const ( hours int64 = minutes * 60 ) -func segmentDuration(p *powerline) { +func segmentDuration(p *powerline) []pwl.Segment { if p.args.Duration == nil || *p.args.Duration == "" { - p.appendSegment("duration", pwl.Segment{ + return []pwl.Segment{{ + Name: "duration", Content: "No duration", Foreground: p.theme.DurationFg, Background: p.theme.DurationBg, - }) - return + }} } durationValue := strings.Trim(*p.args.Duration, "'\"") @@ -44,16 +44,16 @@ func segmentDuration(p *powerline) { durationFloat, err := strconv.ParseFloat(durationValue, 64) durationMinFloat, _ := strconv.ParseFloat(durationMinValue, 64) if err != nil { - p.appendSegment("duration", pwl.Segment{ + return []pwl.Segment{{ + Name: "duration", Content: fmt.Sprintf("Failed to convert '%s' to a number", *p.args.Duration), Foreground: p.theme.DurationFg, Background: p.theme.DurationBg, - }) - return + }} } if durationFloat < durationMinFloat { - return + return []pwl.Segment{} } duration := time.Duration(durationFloat * float64(time.Second.Nanoseconds())) @@ -88,10 +88,12 @@ func segmentDuration(p *powerline) { content = fmt.Sprintf("%d\u00B5s", ns/microseconds) } - p.appendSegment("duration", pwl.Segment{ + return []pwl.Segment{{ + Name: "duration", Content: content, Foreground: p.theme.DurationFg, Background: p.theme.DurationBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-exitcode.go b/segment-exitcode.go index ca4b3fff..2b9a8884 100644 --- a/segment-exitcode.go +++ b/segment-exitcode.go @@ -65,7 +65,7 @@ func getMeaningFromExitCode(exitCode int) string { } } -func segmentExitCode(p *powerline) { +func segmentExitCode(p *powerline) []pwl.Segment { var meaning string if *p.args.PrevError != 0 { if *p.args.NumericExitCodes { @@ -73,10 +73,12 @@ func segmentExitCode(p *powerline) { } else { meaning = getMeaningFromExitCode(*p.args.PrevError) } - p.appendSegment("exit", pwl.Segment{ + return []pwl.Segment{{ + Name: "exit", Content: meaning, Foreground: p.theme.CmdFailedFg, Background: p.theme.CmdFailedBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-git.go b/segment-git.go index 513cc05f..990aa08f 100644 --- a/segment-git.go +++ b/segment-git.go @@ -24,24 +24,27 @@ func (r repoStats) dirty() bool { return r.untracked+r.notStaged+r.staged+r.conflicted > 0 } -func addRepoStatsSegment(p *powerline, nChanges int, symbol string, foreground uint8, background uint8) { +func addRepoStatsSegment(nChanges int, symbol string, foreground uint8, background uint8) []pwl.Segment { if nChanges > 0 { - p.appendSegment("git-status", pwl.Segment{ + return []pwl.Segment{{ + Name: "git-status", Content: fmt.Sprintf("%d%s", nChanges, symbol), Foreground: foreground, Background: background, - }) + }} } + return []pwl.Segment{} } -func (r repoStats) addToPowerline(p *powerline) { - addRepoStatsSegment(p, r.ahead, p.symbolTemplates.RepoAhead, p.theme.GitAheadFg, p.theme.GitAheadBg) - addRepoStatsSegment(p, r.behind, p.symbolTemplates.RepoBehind, p.theme.GitBehindFg, p.theme.GitBehindBg) - addRepoStatsSegment(p, r.staged, p.symbolTemplates.RepoStaged, p.theme.GitStagedFg, p.theme.GitStagedBg) - addRepoStatsSegment(p, r.notStaged, p.symbolTemplates.RepoNotStaged, p.theme.GitNotStagedFg, p.theme.GitNotStagedBg) - addRepoStatsSegment(p, r.untracked, p.symbolTemplates.RepoUntracked, p.theme.GitUntrackedFg, p.theme.GitUntrackedBg) - addRepoStatsSegment(p, r.conflicted, p.symbolTemplates.RepoConflicted, p.theme.GitConflictedFg, p.theme.GitConflictedBg) - addRepoStatsSegment(p, r.stashed, p.symbolTemplates.RepoStashed, p.theme.GitStashedFg, p.theme.GitStashedBg) +func (r repoStats) GitSegments(p *powerline) (segments []pwl.Segment) { + segments = append(segments, addRepoStatsSegment(r.ahead, p.symbolTemplates.RepoAhead, p.theme.GitAheadFg, p.theme.GitAheadBg)...) + segments = append(segments, addRepoStatsSegment(r.behind, p.symbolTemplates.RepoBehind, p.theme.GitBehindFg, p.theme.GitBehindBg)...) + segments = append(segments, addRepoStatsSegment(r.staged, p.symbolTemplates.RepoStaged, p.theme.GitStagedFg, p.theme.GitStagedBg)...) + segments = append(segments, addRepoStatsSegment(r.notStaged, p.symbolTemplates.RepoNotStaged, p.theme.GitNotStagedFg, p.theme.GitNotStagedBg)...) + segments = append(segments, addRepoStatsSegment(r.untracked, p.symbolTemplates.RepoUntracked, p.theme.GitUntrackedFg, p.theme.GitUntrackedBg)...) + segments = append(segments, addRepoStatsSegment(r.conflicted, p.symbolTemplates.RepoConflicted, p.theme.GitConflictedFg, p.theme.GitConflictedBg)...) + segments = append(segments, addRepoStatsSegment(r.stashed, p.symbolTemplates.RepoStashed, p.theme.GitStashedFg, p.theme.GitStashedBg)...) + return } var branchRegex = regexp.MustCompile(`^## (?P\S+?)(\.{3}(?P\S+?)( \[(ahead (?P\d+)(, )?)?(behind (?P\d+))?])?)?$`) @@ -124,21 +127,21 @@ func parseGitStats(status []string) repoStats { return stats } -func segmentGit(p *powerline) { +func segmentGit(p *powerline) []pwl.Segment { if len(p.ignoreRepos) > 0 { out, err := runGitCommand("git", "rev-parse", "--show-toplevel") if err != nil { - return + return []pwl.Segment{} } out = strings.TrimSpace(out) if p.ignoreRepos[out] { - return + return []pwl.Segment{} } } out, err := runGitCommand("git", "status", "--porcelain", "-b", "--ignore-submodules") if err != nil { - return + return []pwl.Segment{} } status := strings.Split(out, "\n") @@ -172,10 +175,12 @@ func segmentGit(p *powerline) { stats.stashed = len(strings.Split(out, "\n")) - 1 } - p.appendSegment("git-branch", pwl.Segment{ + segments := []pwl.Segment{{ + Name: "git-branch", Content: branch, Foreground: foreground, Background: background, - }) - stats.addToPowerline(p) + }} + segments = append(segments, stats.GitSegments(p)...) + return segments } diff --git a/segment-gitlite.go b/segment-gitlite.go index 113262fe..835fc700 100644 --- a/segment-gitlite.go +++ b/segment-gitlite.go @@ -5,21 +5,21 @@ import ( "strings" ) -func segmentGitLite(p *powerline) { +func segmentGitLite(p *powerline) []pwl.Segment { if len(p.ignoreRepos) > 0 { out, err := runGitCommand("git", "rev-parse", "--show-toplevel") if err != nil { - return + return []pwl.Segment{} } out = strings.TrimSpace(out) if p.ignoreRepos[out] { - return + return []pwl.Segment{} } } out, err := runGitCommand("git", "rev-parse", "--abbrev-ref", "HEAD") if err != nil { - return + return []pwl.Segment{} } status := strings.TrimSpace(out) @@ -31,9 +31,10 @@ func segmentGitLite(p *powerline) { branch = getGitDetachedBranch(p) } - p.appendSegment("git-branch", pwl.Segment{ + return []pwl.Segment{{ + Name: "git-branch", Content: branch, Foreground: p.theme.RepoCleanFg, Background: p.theme.RepoCleanBg, - }) + }} } diff --git a/segment-hg.go b/segment-hg.go index 949f7ac2..1ecfcb70 100644 --- a/segment-hg.go +++ b/segment-hg.go @@ -30,7 +30,7 @@ func getHgStatus() (bool, bool, bool) { return hasModifiedFiles, hasUntrackedFiles, hasMissingFiles } -func segmentHg(p *powerline) { +func segmentHg(p *powerline) []pwl.Segment { out, _ := exec.Command("hg", "branch").Output() output := strings.SplitN(string(out), "\n", 2) if len(output) > 0 && output[0] != "" { @@ -61,10 +61,12 @@ func segmentHg(p *powerline) { content = fmt.Sprintf(branch) } - p.appendSegment("hg", pwl.Segment{ + return []pwl.Segment{{ + Name: "hg", Content: content, Foreground: foreground, Background: background, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-hostname.go b/segment-hostname.go index 89ad052f..9beea67a 100644 --- a/segment-hostname.go +++ b/segment-hostname.go @@ -18,7 +18,7 @@ func getMd5(text string) []byte { return hasher.Sum(nil) } -func segmentHost(p *powerline) { +func segmentHost(p *powerline) []pwl.Segment { var hostPrompt string var foreground, background uint8 if *p.args.ColorizeHostname { @@ -41,9 +41,10 @@ func segmentHost(p *powerline) { background = p.theme.HostnameBg } - p.appendSegment("host", pwl.Segment{ + return []pwl.Segment{{ + Name: "host", Content: hostPrompt, Foreground: foreground, Background: background, - }) + }} } diff --git a/segment-jobs.go b/segment-jobs.go index 3bcbd590..106d7748 100644 --- a/segment-jobs.go +++ b/segment-jobs.go @@ -9,7 +9,7 @@ import ( "strings" ) -func segmentJobs(p *powerline) { +func segmentJobs(p *powerline) []pwl.Segment { nJobs := -1 ppid := os.Getppid() @@ -29,10 +29,12 @@ func segmentJobs(p *powerline) { } if nJobs > 0 { - p.appendSegment("jobs", pwl.Segment{ + return []pwl.Segment{{ + Name: "jobs", Content: fmt.Sprintf("%d", nJobs), Foreground: p.theme.JobsFg, Background: p.theme.JobsBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-kube.go b/segment-kube.go index 01dc202e..9ca0ab45 100644 --- a/segment-kube.go +++ b/segment-kube.go @@ -55,7 +55,7 @@ func readKubeConfig(config *KubeConfig, path string) (err error) { return } -func segmentKube(p *powerline) { +func segmentKube(p *powerline) []pwl.Segment { paths := append(strings.Split(os.Getenv("KUBECONFIG"), ":"), path.Join(homePath(), ".kube", "config")) config := &KubeConfig{} for _, configPath := range paths { @@ -96,12 +96,13 @@ func segmentKube(p *powerline) { if arnMatches := arnRe.FindStringSubmatch(cluster); arnMatches != nil && *p.args.ShortenEKSNames { cluster = arnMatches[1] } - + segments := []pwl.Segment{} // Only draw the icon once kubeIconHasBeenDrawnYet := false if cluster != "" { kubeIconHasBeenDrawnYet = true - p.appendSegment("kube-cluster", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "kube-cluster", Content: fmt.Sprintf("⎈ %s", cluster), Foreground: p.theme.KubeClusterFg, Background: p.theme.KubeClusterBg, @@ -113,10 +114,12 @@ func segmentKube(p *powerline) { if !kubeIconHasBeenDrawnYet { content = fmt.Sprintf("⎈ %s", content) } - p.appendSegment("kube-namespace", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "kube-namespace", Content: content, Foreground: p.theme.KubeNamespaceFg, Background: p.theme.KubeNamespaceBg, }) } + return segments } diff --git a/segment-load.go b/segment-load.go index 6797461c..4815c520 100644 --- a/segment-load.go +++ b/segment-load.go @@ -8,11 +8,11 @@ import ( "github.com/shirou/gopsutil/load" ) -func segmentLoad(p *powerline) { +func segmentLoad(p *powerline) []pwl.Segment { c := runtime.NumCPU() a, err := load.Avg() if err != nil { - return + return []pwl.Segment{} } bg := p.theme.LoadBg @@ -28,9 +28,10 @@ func segmentLoad(p *powerline) { bg = p.theme.LoadHighBg } - p.appendSegment("load", pwl.Segment{ + return []pwl.Segment{{ + Name: "load", Content: fmt.Sprintf("%.2f", a.Load5), Foreground: p.theme.LoadFg, Background: bg, - }) + }} } diff --git a/segment-newline.go b/segment-newline.go index 83f03268..69e7c9df 100644 --- a/segment-newline.go +++ b/segment-newline.go @@ -1,5 +1,7 @@ package main -func segmentNewline(p *powerline) { - p.newRow() +import pwl "github.com/justjanne/powerline-go/powerline" + +func segmentNewline(p *powerline) []pwl.Segment { + return []pwl.Segment{{NewLine: true}} } diff --git a/segment-nix-shell.go b/segment-nix-shell.go index 8359c4c3..00f8c459 100644 --- a/segment-nix-shell.go +++ b/segment-nix-shell.go @@ -5,15 +5,16 @@ import ( "os" ) -func segmentNixShell(p *powerline) { +func segmentNixShell(p *powerline) []pwl.Segment { var nixShell string nixShell, _ = os.LookupEnv("IN_NIX_SHELL") if nixShell == "" { - return + return []pwl.Segment{} } - p.appendSegment("nix-shell", pwl.Segment{ + return []pwl.Segment{{ + Name: "nix-shell", Content: nixShell, Foreground: p.theme.NixShellFg, Background: p.theme.NixShellBg, - }) + }} } diff --git a/segment-node.go b/segment-node.go index ec5bf475..898c2f94 100644 --- a/segment-node.go +++ b/segment-node.go @@ -14,7 +14,7 @@ type packageJSON struct { Version string `json:"version"` } -func segmentNode(p *powerline) { +func segmentNode(p *powerline) []pwl.Segment { stat, err := os.Stat(pkgfile) if err == nil && !stat.IsDir() { pkg := packageJSON{"!"} @@ -22,12 +22,14 @@ func segmentNode(p *powerline) { if err == nil { err = json.Unmarshal(raw, &pkg) if err == nil { - p.appendSegment("node-version", pwl.Segment{ + return []pwl.Segment{{ + Name: "node-segment", Content: pkg.Version + " \u2B22", Foreground: p.theme.NodeFg, Background: p.theme.NodeBg, - }) + }} } } } + return []pwl.Segment{} } diff --git a/segment-perlbrew.go b/segment-perlbrew.go index a6c59926..ba0483ff 100644 --- a/segment-perlbrew.go +++ b/segment-perlbrew.go @@ -6,16 +6,17 @@ import ( "path" ) -func segmentPerlbrew(p *powerline) { +func segmentPerlbrew(p *powerline) []pwl.Segment { env, _ := os.LookupEnv("PERLBREW_PERL") if env == "" { - return + return []pwl.Segment{} } envName := path.Base(env) - p.appendSegment("perlbrew", pwl.Segment{ + return []pwl.Segment{{ + Name: "perlbrew", Content: envName, Foreground: p.theme.PerlbrewFg, Background: p.theme.PerlbrewBg, - }) + }} } diff --git a/segment-plenv.go b/segment-plenv.go index 2ed3524f..f87d6956 100644 --- a/segment-plenv.go +++ b/segment-plenv.go @@ -6,19 +6,19 @@ import ( "path" ) -func segmentPlEnv(p *powerline) { +func segmentPlEnv(p *powerline) []pwl.Segment { var env string if env == "" { env, _ = os.LookupEnv("PLENV_VERSION") } - if env == "" { - return - } else { + if env != "" { envName := path.Base(env) - p.appendSegment("plenv", pwl.Segment{ + return []pwl.Segment{{ + Name: "plenv", Content: envName, Foreground: p.theme.PlEnvFg, Background: p.theme.PlEnvBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-plugin.go b/segment-plugin.go index f2ac8cb7..6208cd63 100644 --- a/segment-plugin.go +++ b/segment-plugin.go @@ -7,19 +7,16 @@ import ( pwl "github.com/justjanne/powerline-go/powerline" ) -func segmentPlugin(p *powerline, plugin string) bool { +func segmentPlugin(p *powerline, plugin string) ([]pwl.Segment, bool) { output, err := exec.Command("powerline-go-" + plugin).Output() if err != nil { - return false + return nil, false } segments := []pwl.Segment{} err = json.Unmarshal(output, &segments) if err != nil { // The plugin was found but no valid data was returned. Ignore it - return true + return []pwl.Segment{}, true } - for _, s := range segments { - p.appendSegment(plugin, s) - } - return true + return segments, true } diff --git a/segment-readonly.go b/segment-readonly.go index 9f48c370..ab3dc5bc 100644 --- a/segment-readonly.go +++ b/segment-readonly.go @@ -9,16 +9,18 @@ import ( "golang.org/x/sys/unix" ) -func segmentPerms(p *powerline) { +func segmentPerms(p *powerline) []pwl.Segment { cwd := p.cwd if cwd == "" { cwd, _ = os.LookupEnv("PWD") } if unix.Access(cwd, unix.W_OK) != nil { - p.appendSegment("perms", pwl.Segment{ + return []pwl.Segment{{ + Name: "perms", Content: p.symbolTemplates.Lock, Foreground: p.theme.ReadonlyFg, Background: p.theme.ReadonlyBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-readonly_windows.go b/segment-readonly_windows.go index 4dda8e28..11d34329 100644 --- a/segment-readonly_windows.go +++ b/segment-readonly_windows.go @@ -7,7 +7,7 @@ import ( "os" ) -func segmentPerms(p *powerline) { +func segmentPerms(p *powerline) []pwl.Segment { cwd := p.cwd if cwd == "" { cwd, _ = os.LookupEnv("PWD") @@ -17,10 +17,12 @@ func segmentPerms(p *powerline) { // Check user's permissions on directory in a portable but probably slower way fileInfo, _ := os.Stat(cwd) if fileInfo.Mode()&W_USR != W_USR { - p.appendSegment("perms", pwl.Segment{ + return []pwl.Segment{{ + Name: "perms", Content: p.symbolTemplates.Lock, Foreground: p.theme.ReadonlyFg, Background: p.theme.ReadonlyBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-root.go b/segment-root.go index e1a4df4e..4d5f0121 100644 --- a/segment-root.go +++ b/segment-root.go @@ -2,7 +2,7 @@ package main import pwl "github.com/justjanne/powerline-go/powerline" -func segmentRoot(p *powerline) { +func segmentRoot(p *powerline) []pwl.Segment { var foreground, background uint8 if *p.args.PrevError == 0 { foreground = p.theme.CmdPassedFg @@ -12,9 +12,10 @@ func segmentRoot(p *powerline) { background = p.theme.CmdFailedBg } - p.appendSegment("root", pwl.Segment{ + return []pwl.Segment{{ + Name: "root", Content: p.shellInfo.rootIndicator, Foreground: foreground, Background: background, - }) + }} } diff --git a/segment-shellvar.go b/segment-shellvar.go index 7afb1a48..ba832260 100644 --- a/segment-shellvar.go +++ b/segment-shellvar.go @@ -5,21 +5,23 @@ import ( "os" ) -func segmentShellVar(p *powerline) { +func segmentShellVar(p *powerline) []pwl.Segment { shellVarName := *p.args.ShellVar varContent, varExists := os.LookupEnv(shellVarName) if varExists { if varContent != "" { - p.appendSegment("shell-var", pwl.Segment{ + return []pwl.Segment{{ + Name: "shell-var", Content: varContent, Foreground: p.theme.ShellVarFg, Background: p.theme.ShellVarBg, - }) - } else { - warn("Shell variable " + shellVarName + " is empty.") + }} } + warn("Shell variable " + shellVarName + " is empty.") + } else { warn("Shell variable " + shellVarName + " does not exist.") } + return []pwl.Segment{} } diff --git a/segment-ssh.go b/segment-ssh.go index 4a57b6df..90c70ec4 100644 --- a/segment-ssh.go +++ b/segment-ssh.go @@ -5,13 +5,15 @@ import ( "os" ) -func segmentSSH(p *powerline) { +func segmentSSH(p *powerline) []pwl.Segment { sshClient, _ := os.LookupEnv("SSH_CLIENT") if sshClient != "" { - p.appendSegment("ssh", pwl.Segment{ + return []pwl.Segment{{ + Name: "ssh", Content: p.symbolTemplates.Network, Foreground: p.theme.SSHFg, Background: p.theme.SSHBg, - }) + }} } + return []pwl.Segment{} } diff --git a/segment-subversion.go b/segment-subversion.go index d2d17b34..7a2e7cb7 100644 --- a/segment-subversion.go +++ b/segment-subversion.go @@ -10,24 +10,27 @@ import ( var otherModified int -func addSvnRepoStatsSegment(p *powerline, nChanges int, symbol string, foreground uint8, background uint8) { +func addSvnRepoStatsSegment(p *powerline, nChanges int, symbol string, foreground uint8, background uint8) (segments []pwl.Segment) { if nChanges > 0 { - p.appendSegment("svn-status", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "svn-status", Content: fmt.Sprintf("%d%s", nChanges, symbol), Foreground: foreground, Background: background, }) } + return segments } -func (r repoStats) addSvnToPowerline(p *powerline) { - addSvnRepoStatsSegment(p, r.ahead, p.symbolTemplates.RepoAhead, p.theme.GitAheadFg, p.theme.GitAheadBg) - addSvnRepoStatsSegment(p, r.behind, p.symbolTemplates.RepoBehind, p.theme.GitBehindFg, p.theme.GitBehindBg) - addSvnRepoStatsSegment(p, r.staged, p.symbolTemplates.RepoStaged, p.theme.GitStagedFg, p.theme.GitStagedBg) - addSvnRepoStatsSegment(p, r.notStaged, p.symbolTemplates.RepoNotStaged, p.theme.GitNotStagedFg, p.theme.GitNotStagedBg) - addSvnRepoStatsSegment(p, r.untracked, p.symbolTemplates.RepoUntracked, p.theme.GitUntrackedFg, p.theme.GitUntrackedBg) - addSvnRepoStatsSegment(p, r.conflicted, p.symbolTemplates.RepoConflicted, p.theme.GitConflictedFg, p.theme.GitConflictedBg) - addSvnRepoStatsSegment(p, r.stashed, p.symbolTemplates.RepoStashed, p.theme.GitStashedFg, p.theme.GitStashedBg) +func (r repoStats) SvnSegments(p *powerline) (segments []pwl.Segment) { + segments = append(segments, addSvnRepoStatsSegment(p, r.ahead, p.symbolTemplates.RepoAhead, p.theme.GitAheadFg, p.theme.GitAheadBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.behind, p.symbolTemplates.RepoBehind, p.theme.GitBehindFg, p.theme.GitBehindBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.staged, p.symbolTemplates.RepoStaged, p.theme.GitStagedFg, p.theme.GitStagedBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.notStaged, p.symbolTemplates.RepoNotStaged, p.theme.GitNotStagedFg, p.theme.GitNotStagedBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.untracked, p.symbolTemplates.RepoUntracked, p.theme.GitUntrackedFg, p.theme.GitUntrackedBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.conflicted, p.symbolTemplates.RepoConflicted, p.theme.GitConflictedFg, p.theme.GitConflictedBg)...) + segments = append(segments, addSvnRepoStatsSegment(p, r.stashed, p.symbolTemplates.RepoStashed, p.theme.GitStashedFg, p.theme.GitStashedBg)...) + return segments } func runSvnCommand(cmd string, args ...string) (string, error) { @@ -112,16 +115,16 @@ func parseSvnStatus() repoStats { return stats } -func segmentSubversion(p *powerline) { +func segmentSubversion(p *powerline) []pwl.Segment { svnInfo, err := parseSvnURL() if err != nil { - return + return []pwl.Segment{} } if len(p.ignoreRepos) > 0 { if p.ignoreRepos[svnInfo["URL"]] || p.ignoreRepos[svnInfo["Relative URL"]] { - return + return []pwl.Segment{} } } @@ -136,11 +139,13 @@ func segmentSubversion(p *powerline) { background = p.theme.RepoCleanBg } - p.appendSegment("svn-branch", pwl.Segment{ + segments := []pwl.Segment{{ + Name: "svn-branch", Content: svnInfo["Relative URL"], Foreground: foreground, Background: background, - }) + }} - svnStats.addSvnToPowerline(p) + segments = append(segments, svnStats.SvnSegments(p)...) + return segments } diff --git a/segment-termtitle.go b/segment-termtitle.go index e0c1c165..a3b2ec8d 100644 --- a/segment-termtitle.go +++ b/segment-termtitle.go @@ -10,12 +10,12 @@ import ( "strings" ) -func segmentTermTitle(p *powerline) { +func segmentTermTitle(p *powerline) []pwl.Segment { var title string term := os.Getenv("TERM") if !(strings.Contains(term, "xterm") || strings.Contains(term, "rxvt")) { - return + return []pwl.Segment{} } if *p.args.Shell == "bash" { @@ -29,9 +29,10 @@ func segmentTermTitle(p *powerline) { title = fmt.Sprintf("\033]0;%s@%s: %s\007", user, host, cwd) } - p.appendSegment("termtitle", pwl.Segment{ + return []pwl.Segment{{ + Name: "termtitle", Content: title, Priority: MaxInteger, // do not truncate HideSeparators: true, // do not draw separators - }) + }} } diff --git a/segment-terraform_workspace.go b/segment-terraform_workspace.go index 46d5047a..35c41edb 100644 --- a/segment-terraform_workspace.go +++ b/segment-terraform_workspace.go @@ -8,19 +8,20 @@ import ( const wsFile = "./.terraform/environment" -func segmentTerraformWorkspace(p *powerline) { +func segmentTerraformWorkspace(p *powerline) []pwl.Segment { stat, err := os.Stat(wsFile) if err == nil && !stat.IsDir() { workspace, err := ioutil.ReadFile(wsFile) if err == nil { - p.appendSegment("terraform-workspace", pwl.Segment{ + return []pwl.Segment{{ + Name: "terraform-workspace", Content: string(workspace), Foreground: p.theme.TFWsFg, Background: p.theme.TFWsBg, - }) + }} } } - + return []pwl.Segment{} } diff --git a/segment-time.go b/segment-time.go index 0488f6b9..e5c49730 100644 --- a/segment-time.go +++ b/segment-time.go @@ -5,10 +5,11 @@ import ( "time" ) -func segmentTime(p *powerline) { - p.appendSegment("time", pwl.Segment{ +func segmentTime(p *powerline) []pwl.Segment { + return []pwl.Segment{{ + Name: "time", Content: time.Now().Format("15:04:05"), Foreground: p.theme.TimeFg, Background: p.theme.TimeBg, - }) + }} } diff --git a/segment-username.go b/segment-username.go index ab51892c..3b2a0760 100644 --- a/segment-username.go +++ b/segment-username.go @@ -5,7 +5,7 @@ import ( "os" ) -func segmentUser(p *powerline) { +func segmentUser(p *powerline) []pwl.Segment { var userPrompt string if *p.args.Shell == "bash" { userPrompt = "\\u" @@ -23,9 +23,10 @@ func segmentUser(p *powerline) { background = p.theme.UsernameBg } - p.appendSegment("user", pwl.Segment{ + return []pwl.Segment{{ + Name: "user", Content: userPrompt, Foreground: p.theme.UsernameFg, Background: background, - }) + }} } diff --git a/segment-vgo.go b/segment-vgo.go index 99fb1f22..76ce3487 100644 --- a/segment-vgo.go +++ b/segment-vgo.go @@ -5,23 +5,27 @@ import ( "os" ) -func segmentVirtualGo(p *powerline) { +func segmentVirtualGo(p *powerline) []pwl.Segment { var env string if env == "" { env, _ = os.LookupEnv("VIRTUALGO") } + segments := []pwl.Segment{} if env == "" { - return + return segments } else { - p.appendSegment("vgo", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "vgo", Content: env, Foreground: p.theme.VirtualGoFg, Background: p.theme.VirtualGoBg, }) } - p.appendSegment("vgo", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "vgo", Content: env, Foreground: p.theme.VirtualGoFg, Background: p.theme.VirtualGoBg, }) + return segments } diff --git a/segment-virtualenv.go b/segment-virtualenv.go index e4f61309..4c5d143c 100644 --- a/segment-virtualenv.go +++ b/segment-virtualenv.go @@ -7,7 +7,7 @@ import ( pwl "github.com/justjanne/powerline-go/powerline" ) -func segmentVirtualEnv(p *powerline) { +func segmentVirtualEnv(p *powerline) []pwl.Segment { var env string if env == "" { env, _ = os.LookupEnv("VIRTUAL_ENV") @@ -18,20 +18,24 @@ func segmentVirtualEnv(p *powerline) { if env == "" { env, _ = os.LookupEnv("CONDA_DEFAULT_ENV") } + segments := []pwl.Segment{} if env == "" { - return + return segments } else { envName := path.Base(env) - p.appendSegment("venv", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "venv", Content: envName, Foreground: p.theme.VirtualEnvFg, Background: p.theme.VirtualEnvBg, }) } envName := path.Base(env) - p.appendSegment("venv", pwl.Segment{ + segments = append(segments, pwl.Segment{ + Name: "venv", Content: envName, Foreground: p.theme.VirtualEnvFg, Background: p.theme.VirtualEnvBg, }) + return segments }