Skip to content

Commit

Permalink
Improved truncation functionality for terminals of smaller width
Browse files Browse the repository at this point in the history
  • Loading branch information
justjanne committed Oct 18, 2017
1 parent 40d9ab9 commit 87f784d
Show file tree
Hide file tree
Showing 21 changed files with 412 additions and 373 deletions.
3 changes: 1 addition & 2 deletions aws.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package main

import (
"fmt"
"os"
)

func segmentAWS(p *powerline) {
profile, _ := os.LookupEnv("AWS_PROFILE")
if profile != "" {
p.appendSegment("aws", segment{
content: fmt.Sprintf(" %s ", profile),
content: profile,
foreground: p.theme.AWSFg,
background: p.theme.AWSBg,
})
Expand Down
6 changes: 3 additions & 3 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ var symbolTemplates = map[string]Symbols{
var shellInfos = map[string]ShellInfo{
"bash": {
colorTemplate: "\\[\\e%s\\]",
rootIndicator: " \\$ ",
rootIndicator: "\\$",
escapedBackslash: `\\\\`,
escapedBacktick: "\\`",
escapedDollar: `\$`,
},
"zsh": {
colorTemplate: "%%{\u001b%s%%}",
rootIndicator: " %# ",
rootIndicator: "%#",
escapedBackslash: `\\`,
escapedBacktick: "\\`",
escapedDollar: `\$`,
},
"bare": {
colorTemplate: "%s",
rootIndicator: " $ ",
rootIndicator: "$",
escapedBackslash: `\`,
escapedBacktick: "`",
escapedDollar: `$`,
Expand Down
39 changes: 25 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"flag"
"fmt"
"github.com/mattn/go-runewidth"
"io/ioutil"
"os"
"strings"
Expand All @@ -23,23 +24,29 @@ type segment struct {
separator string
separatorForeground uint8
priority int
width int
}

type args struct {
CwdMode *string
CwdMaxDepth *int
CwdMaxDirSize *int
ColorizeHostname *bool
EastAsianWidth *bool
PromptOnNewLine *bool
Mode *string
Theme *string
Shell *string
Modules *string
Priority *string
MaxWidthPercentage *int
IgnoreRepos *string
PrevError *int
CwdMode *string
CwdMaxDepth *int
CwdMaxDirSize *int
ColorizeHostname *bool
EastAsianWidth *bool
PromptOnNewLine *bool
Mode *string
Theme *string
Shell *string
Modules *string
Priority *string
MaxWidthPercentage *int
TruncateSegmentWidth *int
IgnoreRepos *string
PrevError *int
}

func (s segment) computeWidth() int {
return runewidth.StringWidth(s.content) + runewidth.StringWidth(s.separator) + 2
}

func warn(msg string) {
Expand Down Expand Up @@ -139,6 +146,10 @@ func main() {
50,
"Maximum width of the shell that the prompt may use, in percent. Setting this to 0 disables the shrinking subsystem.\n"+
" "),
TruncateSegmentWidth: flag.Int("truncate-segment-width",
16,
"Minimum width of a segment, segments longer than this will be shortened if space is limited. Setting this to 0 disables it.\n"+
" "),
PrevError: flag.Int("error", 0,
"Exit code of previously executed command"),
IgnoreRepos: flag.String("ignore-repos",
Expand Down
48 changes: 40 additions & 8 deletions powerline.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@ func (p *powerline) appendSegment(origin string, segment segment) {
segment.separatorForeground = segment.background
}
priority, _ := p.priorities[origin]
segment.priority = priority
segment.priority += priority
segment.width = segment.computeWidth()
p.Segments = append(p.Segments, segment)
}

func termWidth() int {
width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
termWidth, _, err := terminal.GetSize(int(os.Stdout.Fd()))
if err != nil {
shellMaxLengthStr, found := os.LookupEnv("COLUMNS")
if !found {
Expand All @@ -90,10 +91,10 @@ func termWidth() int {
return 80 // Otherwise 0 default.
}

width = int(shellMaxLength64)
termWidth = int(shellMaxLength64)
}

return width
return termWidth
}

func (p *powerline) draw() string {
Expand All @@ -103,11 +104,40 @@ func (p *powerline) draw() string {

shellActualLength := 0
if shellMaxLength > 0 {
rlen := runewidth.StringWidth

for _, segment := range p.Segments {
shellActualLength += rlen(segment.content) + rlen(segment.separator)
shellActualLength += segment.width
}
if shellActualLength > shellMaxLength && *p.args.TruncateSegmentWidth > 0 {
minPriorityNotTruncated := MaxInteger
minPriorityNotTruncatedSegmentId := -1
for idx, segment := range p.Segments {
if segment.width > *p.args.TruncateSegmentWidth && segment.priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.priority
minPriorityNotTruncatedSegmentId = idx
}
}
for minPriorityNotTruncatedSegmentId != -1 && shellActualLength > shellMaxLength {
segment := p.Segments[minPriorityNotTruncatedSegmentId]

shellActualLength -= segment.width

segment.content = runewidth.Truncate(segment.content, *p.args.TruncateSegmentWidth-runewidth.StringWidth(segment.separator)-5, "")
segment.width = segment.computeWidth()

p.Segments = append(append(p.Segments[:minPriorityNotTruncatedSegmentId], segment), p.Segments[minPriorityNotTruncatedSegmentId+1:]...)
shellActualLength += segment.width

minPriorityNotTruncated = MaxInteger
minPriorityNotTruncatedSegmentId = -1
for idx, segment := range p.Segments {
if segment.width > *p.args.TruncateSegmentWidth && segment.priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.priority
minPriorityNotTruncatedSegmentId = idx
}
}
}
}

for shellActualLength > shellMaxLength {
minPriority := MaxInteger
minPrioritySegmentId := -1
Expand All @@ -120,7 +150,7 @@ func (p *powerline) draw() string {
if minPrioritySegmentId != -1 {
segment := p.Segments[minPrioritySegmentId]
p.Segments = append(p.Segments[:minPrioritySegmentId], p.Segments[minPrioritySegmentId+1:]...)
shellActualLength -= rlen(segment.content) + rlen(segment.separator)
shellActualLength -= segment.width
}
}
}
Expand All @@ -137,7 +167,9 @@ func (p *powerline) draw() string {

buffer.WriteString(p.fgColor(segment.foreground))
buffer.WriteString(p.bgColor(segment.background))
buffer.WriteRune(' ')
buffer.WriteString(segment.content)
buffer.WriteRune(' ')
buffer.WriteString(separatorBackground)
buffer.WriteString(p.fgColor(segment.separatorForeground))
buffer.WriteString(segment.separator)
Expand Down
17 changes: 12 additions & 5 deletions segment-cwd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"fmt"
"os"
"strings"
)
Expand All @@ -13,6 +12,7 @@ type pathSegment struct {
home bool
root bool
ellipsis bool
priority int
}

func cwdToPathSegments(cwd string) []pathSegment {
Expand Down Expand Up @@ -85,7 +85,7 @@ func segmentCwd(p *powerline) {
}

p.appendSegment("cwd", segment{
content: fmt.Sprintf(" %s ", cwd),
content: cwd,
foreground: p.theme.CwdFg,
background: p.theme.PathBg,
})
Expand All @@ -107,18 +107,25 @@ func segmentCwd(p *powerline) {
}
firstPart := pathSegments[:nBefore]
secondPart := pathSegments[len(pathSegments)+nBefore-maxDepth:]
pathSegments = append(append(firstPart, pathSegment{
pathSegments = make([]pathSegment, 0)
for _, segment := range firstPart {
segment.priority = -2
pathSegments = append(pathSegments, segment)
}
pathSegments = append(pathSegments, pathSegment{
priority: -1,
path: ellipsis,
ellipsis: true,
}), secondPart...)
})
pathSegments = append(pathSegments, secondPart...)
}

for idx, pathSegment := range pathSegments {
isLastDir := idx == len(pathSegments)-1
foreground, background := getColor(p, pathSegment, isLastDir)

segment := segment{
content: fmt.Sprintf(" %s ", escapeVariables(p, maybeShortenName(p, pathSegment.path))),
content: escapeVariables(p, maybeShortenName(p, pathSegment.path)),
foreground: foreground,
background: background,
}
Expand Down
3 changes: 1 addition & 2 deletions segment-docker.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"fmt"
"net/url"
"os"
)
Expand All @@ -22,7 +21,7 @@ func segmentDocker(p *powerline) {

if docker != "" {
p.appendSegment("docker", segment{
content: fmt.Sprintf(" %s ", docker),
content: docker,
foreground: p.theme.DockerMachineFg,
background: p.theme.DockerMachineBg,
})
Expand Down
2 changes: 1 addition & 1 deletion segment-dotenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ func segmentDotEnv(p *powerline) {
stat, err := os.Stat(".env")
if err == nil && !stat.IsDir() {
p.appendSegment("dotenv", segment{
content: " \u2235 ",
content: "\u2235",
foreground: p.theme.DotEnvFg,
background: p.theme.DotEnvBg,
})
Expand Down
2 changes: 1 addition & 1 deletion segment-exitcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func segmentExitCode(p *powerline) {
if *p.args.PrevError != 0 {
meaning := getMeaningFromExitCode(*p.args.PrevError)
p.appendSegment("exit", segment{
content: fmt.Sprintf(" %s ", meaning),
content: 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 @@ -25,7 +25,7 @@ func (r repoStats) dirty() bool {
func addRepoStatsSegment(p *powerline, nChanges int, symbol string, foreground uint8, background uint8) {
if nChanges > 0 {
p.appendSegment("git-status", segment{
content: fmt.Sprintf(" %d%s ", nChanges, symbol),
content: fmt.Sprintf("%d%s", nChanges, symbol),
foreground: foreground,
background: background,
})
Expand Down Expand Up @@ -167,7 +167,7 @@ func segmentGit(p *powerline) {
}

p.appendSegment("git-branch", segment{
content: fmt.Sprintf(" %s ", branch),
content: branch,
foreground: foreground,
background: background,
})
Expand Down
3 changes: 1 addition & 2 deletions segment-gitlite.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"fmt"
"strings"
)

Expand Down Expand Up @@ -32,7 +31,7 @@ func segmentGitLite(p *powerline) {
}

p.appendSegment("git-branch", segment{
content: fmt.Sprintf(" %s ", branch),
content: branch,
foreground: p.theme.RepoCleanFg,
background: p.theme.RepoCleanBg,
})
Expand Down
4 changes: 2 additions & 2 deletions segment-hg.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ func segmentHg(p *powerline) {
extra += "!"
}

content = fmt.Sprintf(" %s %s ", branch, extra)
content = fmt.Sprintf("%s %s", branch, extra)
} else {
foreground = p.theme.RepoCleanFg
background = p.theme.RepoCleanBg

content = fmt.Sprintf(" %s ", branch)
content = fmt.Sprintf(branch)
}

p.appendSegment("hg", segment{
Expand Down
9 changes: 4 additions & 5 deletions segment-hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"crypto/md5"
"fmt"
"os"
"strings"
)
Expand All @@ -23,18 +22,18 @@ func segmentHost(p *powerline) {
var foreground, background uint8
if *p.args.ColorizeHostname {
hostName := getHostName()
hostPrompt = fmt.Sprintf(" %s ", hostName)
hostPrompt = hostName

hash := getMd5(hostName)
background = hash[0]
foreground = p.theme.HostnameColorizedFgMap[background]
} else {
if *p.args.Shell == "bash" {
hostPrompt = " \\h "
hostPrompt = "\\h"
} else if *p.args.Shell == "zsh" {
hostPrompt = " %m "
hostPrompt = "%m"
} else {
hostPrompt = fmt.Sprintf(" %s ", getHostName())
hostPrompt = getHostName()
}

foreground = p.theme.HostnameFg
Expand Down
2 changes: 1 addition & 1 deletion segment-jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func segmentJobs(p *powerline) {

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

import (
"fmt"
"os"
"path"
)
Expand All @@ -14,7 +13,7 @@ func segmentPerlbrew(p *powerline) {

envName := path.Base(env)
p.appendSegment("perlbrew", segment{
content: fmt.Sprintf(" %s ", envName),
content: envName,
foreground: p.theme.PerlbrewFg,
background: p.theme.PerlbrewBg,
})
Expand Down
Loading

0 comments on commit 87f784d

Please sign in to comment.