Skip to content

Commit

Permalink
Introduced a system for shell segment priorities, which, if space is
Browse files Browse the repository at this point in the history
limited, removes segments with lowest priority first.
  • Loading branch information
justjanne committed Aug 24, 2017
1 parent d54a8fc commit 16a46ce
Show file tree
Hide file tree
Showing 15 changed files with 69 additions and 26 deletions.
16 changes: 14 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type segment struct {
background uint8
separator string
separatorForeground uint8
priority int
}

type args struct {
Expand All @@ -26,6 +27,7 @@ type args struct {
Theme *string
Shell *string
Modules *string
Priority *string
PrevError *int
}

Expand All @@ -42,7 +44,6 @@ func pathExists(path string) bool {
}

func getValidCwd() string {

cwd, exists := os.LookupEnv("PWD")
if !exists {
warn("Your current directory is invalid.")
Expand Down Expand Up @@ -113,11 +114,22 @@ func main() {
"The list of modules to load. Separate with ','\n"+
" (valid choices: cwd, docker, exit, git, hg, host, jobs, perms, root, ssh, time, user, venv)\n"+
" "),
Priority: flag.String("priority",
"root,cwd,user,host,ssh,perms,git-branch,git-status,hg,jobs,exit",
"Segments sorted by priority, if not enough space exists, the least priorized segments are removed first. Separate with ','\n"+
" (valid choices: cwd, docker, exit, git-branch, git-status, hg, host, jobs, perms, root, ssh, time, user, venv)\n"+
" "),
PrevError: flag.Int("error", 0,
"Exit code of previously executed command"),
}
flag.Parse()
powerline := NewPowerline(args, getValidCwd())
priorities := map[string]int{}
priorityList := strings.Split(*args.Priority, ",")
for idx, priority := range priorityList {
priorities[priority] = len(priorityList) - idx
}

powerline := NewPowerline(args, getValidCwd(), priorities)

for _, module := range strings.Split(*powerline.args.Modules, ",") {
elem, ok := modules[module]
Expand Down
41 changes: 36 additions & 5 deletions powerline.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"bytes"
"fmt"
"golang.org/x/text/width"
"math"
"os"
"strconv"
)

type ShellInfo struct {
Expand All @@ -21,17 +24,19 @@ type powerline struct {
shellInfo ShellInfo
reset string
symbolTemplates Symbols
priorities map[string]int
Segments []segment
}

func NewPowerline(args args, cwd string) *powerline {
func NewPowerline(args args, cwd string, priorities map[string]int) *powerline {
p := new(powerline)
p.args = args
p.cwd = cwd
p.theme = themes[*args.Theme]
p.shellInfo = shellInfos[*args.Shell]
p.reset = fmt.Sprintf(p.shellInfo.colorTemplate, "[0m")
p.symbolTemplates = symbolTemplates[*args.Mode]
p.priorities = priorities
p.Segments = make([]segment, 0)
return p
}
Expand All @@ -52,21 +57,47 @@ func (p *powerline) bgColor(code uint8) string {
return p.color("48", code)
}

func (p *powerline) appendSegment(segment segment) {
func (p *powerline) appendSegment(origin string, segment segment) {
if segment.separator == "" {
segment.separator = p.symbolTemplates.Separator
}
if segment.separatorForeground == 0 {
segment.separatorForeground = segment.background
}
priority, _ := p.priorities[origin]
segment.priority = priority
p.Segments = append(p.Segments, segment)
}

func (p *powerline) draw() string {
var buffer bytes.Buffer
for idx := range p.Segments {
segment := p.Segments[idx]
shellMaxLengthStr, _ := os.LookupEnv("COLUMNS")
shellMaxLength64, _ := strconv.ParseInt(shellMaxLengthStr, 0, 64)
shellMaxLength := int(shellMaxLength64)

shellActualLength := 0
if shellMaxLength > 0 {
for _, segment := range p.Segments {
shellActualLength += len(segment.content) + len(segment.separator)
}
for shellActualLength > shellMaxLength {
minPriority := math.MaxInt64
minPrioritySegmentId := -1
for idx, segment := range p.Segments {
if segment.priority < minPriority {
minPriority = segment.priority
minPrioritySegmentId = idx
}
}
if minPrioritySegmentId != -1 {
segment := p.Segments[minPrioritySegmentId]
p.Segments = append(p.Segments[:minPrioritySegmentId], p.Segments[minPrioritySegmentId+1:]...)
shellActualLength -= len(segment.content) + len(segment.separator)
}
}
}

var buffer bytes.Buffer
for idx, segment := range p.Segments {
var separatorBackground string
if idx >= len(p.Segments)-1 {
separatorBackground = p.reset
Expand Down
4 changes: 2 additions & 2 deletions segment-cwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func segmentCwd(p *powerline) {
cwd = "~" + cwd[len(home):]
}

p.appendSegment(segment{
p.appendSegment("cwd", segment{
content: fmt.Sprintf(" %s ", cwd),
foreground: p.theme.CwdFg,
background: p.theme.PathBg,
Expand Down Expand Up @@ -128,7 +128,7 @@ func segmentCwd(p *powerline) {
segment.separatorForeground = p.theme.SeparatorFg
}

p.appendSegment(segment)
p.appendSegment("cwd", segment)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions segment-docker.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package main

import (
"os"
"fmt"
"os"
)

func segmentDocker(p *powerline) {
dockerMachineName, _ := os.LookupEnv("DOCKER_MACHINE_NAME")
if dockerMachineName != "" {
p.appendSegment(segment{
p.appendSegment("docker", segment{
content: fmt.Sprintf(" %s ", dockerMachineName),
foreground: p.theme.DockerMachineFg,
background: p.theme.DockerMachineBg,
Expand Down
2 changes: 1 addition & 1 deletion segment-exitcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func getMeaningFromExitCode(exitCode int) string {
func segmentExitCode(p *powerline) {
if *p.args.PrevError != 0 {
meaning := getMeaningFromExitCode(*p.args.PrevError)
p.appendSegment(segment{
p.appendSegment("exit", segment{
content: fmt.Sprintf(" %s ", meaning),
foreground: p.theme.CmdFailedFg,
background: p.theme.CmdFailedBg,
Expand Down
4 changes: 2 additions & 2 deletions segment-git.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (r repoStats) dirty() bool {

func addRepoStatsSegment(p *powerline, nChanges int, symbol string, foreground uint8, background uint8) {
if nChanges > 0 {
p.appendSegment(segment{
p.appendSegment("git-status", segment{
content: fmt.Sprintf(" %d%s ", nChanges, symbol),
foreground: foreground,
background: background,
Expand Down Expand Up @@ -152,7 +152,7 @@ func segmentGit(p *powerline) {
background = p.theme.RepoCleanBg
}

p.appendSegment(segment{
p.appendSegment("git-branch", segment{
content: fmt.Sprintf(" %s ", branch),
foreground: foreground,
background: background,
Expand Down
2 changes: 1 addition & 1 deletion segment-hg.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func segmentHg(p *powerline) {
content = fmt.Sprintf(" %s ", branch)
}

p.appendSegment(segment{
p.appendSegment("hg", segment{
content: content,
foreground: foreground,
background: background,
Expand Down
2 changes: 1 addition & 1 deletion segment-hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func segmentHost(p *powerline) {
background = p.theme.HostnameBg
}

p.appendSegment(segment{
p.appendSegment("host", segment{
content: hostPrompt,
foreground: foreground,
background: background,
Expand Down
2 changes: 1 addition & 1 deletion segment-jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func segmentJobs(p *powerline) {
}

if nJobs > 0 {
p.appendSegment(segment{
p.appendSegment("jobs", segment{
content: fmt.Sprintf(" %d ", nJobs),
foreground: p.theme.JobsFg,
background: p.theme.JobsBg,
Expand Down
4 changes: 2 additions & 2 deletions segment-readonly.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package main

import (
"os"
"fmt"
"golang.org/x/sys/unix"
"os"
)

func segmentPerms(p *powerline) {
Expand All @@ -12,7 +12,7 @@ func segmentPerms(p *powerline) {
cwd, _ = os.LookupEnv("PWD")
}
if unix.Access(cwd, unix.W_OK) != nil {
p.appendSegment(segment{
p.appendSegment("perms", segment{
content: fmt.Sprintf(" %s ", p.symbolTemplates.Lock),
foreground: p.theme.ReadonlyFg,
background: p.theme.ReadonlyBg,
Expand Down
2 changes: 1 addition & 1 deletion segment-root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func segmentRoot(p *powerline) {
background = p.theme.CmdFailedBg
}

p.appendSegment(segment{
p.appendSegment("root", segment{
content: p.shellInfo.rootIndicator,
foreground: foreground,
background: background,
Expand Down
4 changes: 2 additions & 2 deletions segment-ssh.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package main

import (
"os"
"fmt"
"os"
)

func segmentSsh(p *powerline) {
sshClient, _ := os.LookupEnv("SSH_CLIENT")
if sshClient != "" {
p.appendSegment(segment{
p.appendSegment("ssh", segment{
content: fmt.Sprintf(" %s ", p.symbolTemplates.Network),
foreground: p.theme.SshFg,
background: p.theme.SshBg,
Expand Down
2 changes: 1 addition & 1 deletion segment-time.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func segmentTime(p *powerline) {
p.appendSegment(segment{
p.appendSegment("time", segment{
content: fmt.Sprintf(" %s ", time.Now().Format("15:04:05")),
foreground: p.theme.TimeFg,
background: p.theme.TimeBg,
Expand Down
2 changes: 1 addition & 1 deletion segment-username.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func segmentUser(p *powerline) {
background = p.theme.UsernameBg
}

p.appendSegment(segment{
p.appendSegment("user", segment{
content: userPrompt,
foreground: p.theme.UsernameFg,
background: background,
Expand Down
4 changes: 2 additions & 2 deletions segment-virtualenv.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package main

import (
"os"
"fmt"
"os"
"path"
)

Expand All @@ -21,7 +21,7 @@ func segmentVirtualEnv(p *powerline) {
return
} else {
envName := path.Base(env)
p.appendSegment(segment{
p.appendSegment("venv", segment{
content: fmt.Sprintf(" %s ", envName),
foreground: p.theme.VirtualEnvFg,
background: p.theme.VirtualEnvBg,
Expand Down

0 comments on commit 16a46ce

Please sign in to comment.