Skip to content

Commit

Permalink
Extract segments to a dedicated package
Browse files Browse the repository at this point in the history
This is the first step to allow creating powerline extensions inspired
by git and kubectl extensions where an executable starting with
powerline-go- will be considered as an extension that should print a
segment list on stdout.

To make extension developers life easier, export the segment structure
they will be able to import to fill their segments and dump it
  • Loading branch information
tjamet committed Dec 8, 2019
1 parent 9eab488 commit 403650b
Show file tree
Hide file tree
Showing 32 changed files with 258 additions and 200 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -15,3 +15,4 @@ powerline-go
.glide/

/.idea/
~
20 changes: 0 additions & 20 deletions main.go
Expand Up @@ -7,8 +7,6 @@ import (
"io/ioutil"
"os"
"strings"

"github.com/mattn/go-runewidth"
)

type alignment int
Expand All @@ -29,17 +27,6 @@ const (
MinInteger = ^MaxInteger
)

type segment struct {
content string
foreground uint8
background uint8
separator string
separatorForeground uint8
priority int
width int
hideSeparators bool
}

type args struct {
CwdMode *string
CwdMaxDepth *int
Expand Down Expand Up @@ -68,13 +55,6 @@ type args struct {
Condensed *bool
}

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

func warn(msg string) {
print("[powerline-go]", msg)
}
Expand Down
76 changes: 38 additions & 38 deletions powerline.go
Expand Up @@ -3,11 +3,11 @@ package main
import (
"bytes"
"fmt"
"strings"

"os"
"strconv"
"strings"

pwl "github.com/justjanne/powerline-go/powerline"
"github.com/mattn/go-runewidth"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/text/width"
Expand Down Expand Up @@ -36,7 +36,7 @@ type powerline struct {
symbolTemplates Symbols
priorities map[string]int
ignoreRepos map[string]bool
Segments [][]segment
Segments [][]pwl.Segment
curSegment int
align alignment
rightPowerline *powerline
Expand Down Expand Up @@ -68,7 +68,7 @@ func newPowerline(args args, cwd string, priorities map[string]int, align alignm
kv := strings.SplitN(pa, "=", 2)
p.pathAliases[kv[0]] = kv[1]
}
p.Segments = make([][]segment, 1)
p.Segments = make([][]pwl.Segment, 1)
var mods string
if p.align == alignLeft {
mods = *args.Modules
Expand Down Expand Up @@ -108,25 +108,25 @@ func (p *powerline) bgColor(code uint8) string {
return p.color("48", code)
}

func (p *powerline) appendSegment(origin string, segment segment) {
if segment.separator == "" {
func (p *powerline) appendSegment(origin string, segment pwl.Segment) {
if segment.Separator == "" {
if p.isRightPrompt() {
segment.separator = p.symbolTemplates.SeparatorReverse
segment.Separator = p.symbolTemplates.SeparatorReverse
} else {
segment.separator = p.symbolTemplates.Separator
segment.Separator = p.symbolTemplates.Separator
}
}
if segment.separatorForeground == 0 {
segment.separatorForeground = segment.background
if segment.SeparatorForeground == 0 {
segment.SeparatorForeground = segment.Background
}
priority, _ := p.priorities[origin]
segment.priority += priority
segment.width = segment.computeWidth(*p.args.Condensed)
segment.Priority += priority
segment.Width = segment.ComputeWidth(*p.args.Condensed)
p.Segments[p.curSegment] = append(p.Segments[p.curSegment], segment)
}

func (p *powerline) newRow() {
p.Segments = append(p.Segments, make([]segment, 0))
p.Segments = append(p.Segments, make([]pwl.Segment, 0))
p.curSegment = p.curSegment + 1
}

Expand Down Expand Up @@ -157,34 +157,34 @@ func (p *powerline) truncateRow(rowNum int) {

if shellMaxLength > 0 {
for _, segment := range row {
rowLength += segment.width
rowLength += segment.Width
}

if rowLength > shellMaxLength && *p.args.TruncateSegmentWidth > 0 {
minPriorityNotTruncated := MaxInteger
minPriorityNotTruncatedSegmentID := -1
for idx, segment := range row {
if segment.width > *p.args.TruncateSegmentWidth && segment.priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.priority
if segment.Width > *p.args.TruncateSegmentWidth && segment.Priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.Priority
minPriorityNotTruncatedSegmentID = idx
}
}
for minPriorityNotTruncatedSegmentID != -1 && rowLength > shellMaxLength {
segment := row[minPriorityNotTruncatedSegmentID]

rowLength -= segment.width
rowLength -= segment.Width

segment.content = runewidth.Truncate(segment.content, *p.args.TruncateSegmentWidth-runewidth.StringWidth(segment.separator)-3, "…")
segment.width = segment.computeWidth(*p.args.Condensed)
segment.Content = runewidth.Truncate(segment.Content, *p.args.TruncateSegmentWidth-runewidth.StringWidth(segment.Separator)-3, "…")
segment.Width = segment.ComputeWidth(*p.args.Condensed)

row = append(append(row[:minPriorityNotTruncatedSegmentID], segment), row[minPriorityNotTruncatedSegmentID+1:]...)
rowLength += segment.width
rowLength += segment.Width

minPriorityNotTruncated = MaxInteger
minPriorityNotTruncatedSegmentID = -1
for idx, segment := range row {
if segment.width > *p.args.TruncateSegmentWidth && segment.priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.priority
if segment.Width > *p.args.TruncateSegmentWidth && segment.Priority < minPriorityNotTruncated {
minPriorityNotTruncated = segment.Priority
minPriorityNotTruncatedSegmentID = idx
}
}
Expand All @@ -195,15 +195,15 @@ func (p *powerline) truncateRow(rowNum int) {
minPriority := MaxInteger
minPrioritySegmentID := -1
for idx, segment := range row {
if segment.priority < minPriority {
minPriority = segment.priority
if segment.Priority < minPriority {
minPriority = segment.Priority
minPrioritySegmentID = idx
}
}
if minPrioritySegmentID != -1 {
segment := row[minPrioritySegmentID]
row = append(row[:minPrioritySegmentID], row[minPrioritySegmentID+1:]...)
rowLength -= segment.width
rowLength -= segment.Width
}
}
}
Expand Down Expand Up @@ -238,8 +238,8 @@ func (p *powerline) drawRow(rowNum int, buffer *bytes.Buffer) {
buffer.WriteRune(' ')
}
for idx, segment := range row {
if segment.hideSeparators {
buffer.WriteString(segment.content)
if segment.HideSeparators {
buffer.WriteString(segment.Content)
continue
}
var separatorBackground string
Expand All @@ -248,38 +248,38 @@ func (p *powerline) drawRow(rowNum int, buffer *bytes.Buffer) {
separatorBackground = p.reset
} else {
prevSegment := row[idx-1]
separatorBackground = p.bgColor(prevSegment.background)
separatorBackground = p.bgColor(prevSegment.Background)
}
buffer.WriteString(separatorBackground)
buffer.WriteString(p.fgColor(segment.separatorForeground))
buffer.WriteString(segment.separator)
buffer.WriteString(p.fgColor(segment.SeparatorForeground))
buffer.WriteString(segment.Separator)
} else {
if idx >= len(row)-1 {
if !p.hasRightModules() || p.supportsRightModules() {
separatorBackground = p.reset
} else if p.hasRightModules() && rowNum >= len(p.Segments)-1 {
nextSegment := p.rightPowerline.Segments[0][0]
separatorBackground = p.bgColor(nextSegment.background)
separatorBackground = p.bgColor(nextSegment.Background)
}
} else {
nextSegment := row[idx+1]
separatorBackground = p.bgColor(nextSegment.background)
separatorBackground = p.bgColor(nextSegment.Background)
}
}
buffer.WriteString(p.fgColor(segment.foreground))
buffer.WriteString(p.bgColor(segment.background))
buffer.WriteString(p.fgColor(segment.Foreground))
buffer.WriteString(p.bgColor(segment.Background))
if !*p.args.Condensed {
buffer.WriteRune(' ')
}
buffer.WriteString(segment.content)
numEastAsianRunes += p.numEastAsianRunes(&segment.content)
buffer.WriteString(segment.Content)
numEastAsianRunes += p.numEastAsianRunes(&segment.Content)
if !*p.args.Condensed {
buffer.WriteRune(' ')
}
if !p.isRightPrompt() {
buffer.WriteString(separatorBackground)
buffer.WriteString(p.fgColor(segment.separatorForeground))
buffer.WriteString(segment.separator)
buffer.WriteString(p.fgColor(segment.SeparatorForeground))
buffer.WriteString(segment.Separator)
}
buffer.WriteString(p.reset)
}
Expand Down
31 changes: 31 additions & 0 deletions powerline/powerline.go
@@ -0,0 +1,31 @@
package powerline

import (
runewidth "github.com/mattn/go-runewidth"
)

// Segment describes an information to display on the command line prompt
type Segment struct {
// 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)
Foreground uint8
// Background is the color of the filling background (see https://misc.flogisoft.com/bash/tip_colors_and_formatting#background1)
Background uint8
// Separator is the character to be used when generating multiple segments to override the default separator
Separator string
// SeparatorForeground is the character to be used when generating multiple segments to override the default foreground separator
SeparatorForeground uint8
// Priority is the priority of the segment. The higher, the less probable the segment will be dropped if the total length is too long
Priority int
// HideSeparators indicated not to display any separator with next segment.
HideSeparators bool
Width int
}

func (s Segment) ComputeWidth(condensed bool) int {
if condensed {
return runewidth.StringWidth(s.Content) + runewidth.StringWidth(s.Separator)
}
return runewidth.StringWidth(s.Content) + runewidth.StringWidth(s.Separator) + 2
}
9 changes: 5 additions & 4 deletions segment-aws.go
@@ -1,6 +1,7 @@
package main

import (
pwl "github.com/justjanne/powerline-go/powerline"
"os"
)

Expand All @@ -12,10 +13,10 @@ func segmentAWS(p *powerline) {
if region != "" {
r = " (" + region + ")"
}
p.appendSegment("aws", segment{
content: profile + r,
foreground: p.theme.AWSFg,
background: p.theme.AWSBg,
p.appendSegment("aws", pwl.Segment{
Content: profile + r,
Foreground: p.theme.AWSFg,
Background: p.theme.AWSBg,
})
}
}
26 changes: 14 additions & 12 deletions segment-cwd.go
Expand Up @@ -4,6 +4,8 @@ import (
"os"
"sort"
"strings"

pwl "github.com/justjanne/powerline-go/powerline"
)

const ellipsis = "\u2026"
Expand Down Expand Up @@ -166,10 +168,10 @@ func segmentCwd(p *powerline) {
cwd = "~" + cwd[len(home):]
}

p.appendSegment("cwd", segment{
content: cwd,
foreground: p.theme.CwdFg,
background: p.theme.PathBg,
p.appendSegment("cwd", pwl.Segment{
Content: cwd,
Foreground: p.theme.CwdFg,
Background: p.theme.PathBg,
})
} else {
pathSegments := cwdToPathSegments(p, cwd)
Expand Down Expand Up @@ -204,19 +206,19 @@ func segmentCwd(p *powerline) {
isLastDir := idx == len(pathSegments)-1
foreground, background, special := getColor(p, pathSegment, isLastDir)

segment := segment{
content: escapeVariables(p, maybeShortenName(p, pathSegment.path)),
foreground: foreground,
background: background,
segment := pwl.Segment{
Content: escapeVariables(p, maybeShortenName(p, pathSegment.path)),
Foreground: foreground,
Background: background,
}

if !special {
if p.align == alignRight && p.supportsRightModules() && idx != 0 {
segment.separator = p.symbolTemplates.SeparatorReverseThin
segment.separatorForeground = p.theme.SeparatorFg
segment.Separator = p.symbolTemplates.SeparatorReverseThin
segment.SeparatorForeground = p.theme.SeparatorFg
} else if (p.align == alignLeft || !p.supportsRightModules()) && !isLastDir {
segment.separator = p.symbolTemplates.SeparatorThin
segment.separatorForeground = p.theme.SeparatorFg
segment.Separator = p.symbolTemplates.SeparatorThin
segment.SeparatorForeground = p.theme.SeparatorFg
}
}

Expand Down
10 changes: 6 additions & 4 deletions segment-docker.go
Expand Up @@ -3,6 +3,8 @@ package main
import (
"net/url"
"os"

pwl "github.com/justjanne/powerline-go/powerline"
)

func segmentDocker(p *powerline) {
Expand All @@ -20,10 +22,10 @@ func segmentDocker(p *powerline) {
}

if docker != "" {
p.appendSegment("docker", segment{
content: docker,
foreground: p.theme.DockerMachineFg,
background: p.theme.DockerMachineBg,
p.appendSegment("docker", pwl.Segment{
Content: docker,
Foreground: p.theme.DockerMachineFg,
Background: p.theme.DockerMachineBg,
})
}
}
9 changes: 5 additions & 4 deletions segment-dotenv.go
@@ -1,6 +1,7 @@
package main

import (
pwl "github.com/justjanne/powerline-go/powerline"
"os"
)

Expand All @@ -15,10 +16,10 @@ func segmentDotEnv(p *powerline) {
}
}
if dotEnv {
p.appendSegment("dotenv", segment{
content: "\u2235",
foreground: p.theme.DotEnvFg,
background: p.theme.DotEnvBg,
p.appendSegment("dotenv", pwl.Segment{
Content: "\u2235",
Foreground: p.theme.DotEnvFg,
Background: p.theme.DotEnvBg,
})
}
}

0 comments on commit 403650b

Please sign in to comment.