Skip to content

Commit

Permalink
Add support for distinct outer and inner unicode line styles
Browse files Browse the repository at this point in the history
This is a follow-up to olekukonko#207
and caters for one of the motivating examples of
olekukonko#115, namely the example with
double outer boundary but single inner lines.

This change does *not* allow all the customization options of that latter
pull request at this stage, but instead reserves the actual representation
of the style as an implementation detail which can evolve as needed, while
only exposing few selected combinations to the caller.
  • Loading branch information
gagern committed Apr 26, 2023
1 parent f6b4e4a commit 3511557
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 111 deletions.
97 changes: 65 additions & 32 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ type symbolID int

// Symbol ID constants which indicates the compass points, in order NESW, where
// a given symbol has connections to. The order here matches the order of box
// drawing unicode symbols.
// drawing unicode symbols. The symbols with a 'b' in their name have the
// connections before the b on the boundary and the ones after the b on the
// inside. E.g. symEWbS is an east-west connection on the (upper) boundary, and
// an inner line from that to the south.
const (
symEW symbolID = iota
symNS
Expand All @@ -66,6 +69,16 @@ const (
symESW
symNEW
symNESW
symEWb
symNSb
symESb
symSWb
symNEb
symNWb
symNSbE
symNSbW
symEWbS
symEWbN
)

type Table struct {
Expand Down Expand Up @@ -504,58 +517,62 @@ func (t *Table) center(i int, isFirstRow, isLastRow bool) string {
return t.syms[symEW]
}
if isFirstRow {
return t.syms[symES]
return t.syms[symESb]
}
if isLastRow {
return t.syms[symNE]
return t.syms[symNEb]
}
return t.syms[symNES]
return t.syms[symNSbE]
}

if i == len(t.cs)-1 {
if !t.borders.Right {
return t.syms[symEW]
}
if isFirstRow {
return t.syms[symSW]
return t.syms[symSWb]
}
if isLastRow {
return t.syms[symNW]
return t.syms[symNWb]
}
return t.syms[symNSW]
return t.syms[symNSbW]
}

if isFirstRow {
return t.syms[symESW]
return t.syms[symEWbS]
}
if isLastRow {
return t.syms[symNEW]
return t.syms[symEWbN]
}
return t.syms[symNESW]
}

// Print line based on row width
func (t *Table) printLine(isFirst, isLast bool) {
fmt.Fprint(t.out, t.center(-1, isFirst, isLast))
horizontal := t.syms[symEW]
if isFirst || isLast {
horizontal = t.syms[symEWb]
}
for i := 0; i < len(t.cs); i++ {
v := t.cs[i]
fmt.Fprintf(t.out, "%s%s%s%s",
t.syms[symEW],
strings.Repeat(t.syms[symEW], v),
t.syms[symEW],
horizontal,
strings.Repeat(horizontal, v),
horizontal,
t.center(i, isFirst, isLast))
}
fmt.Fprint(t.out, t.newLine)
}

// Print line based on row width with our without cell separator
func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) {
fmt.Fprint(t.out, t.syms[symNES])
fmt.Fprint(t.out, t.syms[symNSbE])
centerSym := symNESW
for i := 0; i < len(t.cs); i++ {
v := t.cs[i]
if i == len(t.cs)-1 {
centerSym = symNSW
centerSym = symNSbW
}
if i > len(displayCellSeparator) || displayCellSeparator[i] {
// Display the cell separator
Expand Down Expand Up @@ -616,7 +633,7 @@ func (t *Table) printHeading() {
// Check if border is set
// Replace with space if not set
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.syms[symNS], SPACE))
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.syms[symNSb], SPACE))
}

for y := 0; y <= end; y++ {
Expand All @@ -629,7 +646,11 @@ func (t *Table) printHeading() {
if t.autoFmt {
h = Title(h)
}
pad := ConditionString((y == end && !t.borders.Left), SPACE, t.syms[symNS])
vertical := symNS
if y == end {
vertical = symNSb
}
pad := ConditionString((y == end && !t.borders.Left), SPACE, t.syms[vertical])
if t.noWhiteSpace {
pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding)
}
Expand Down Expand Up @@ -700,7 +721,7 @@ func (t *Table) printFooter() {
for x := 0; x < max; x++ {
// Check if border is set
// Replace with space if not set
fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.syms[symNS], SPACE))
fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.syms[symNSb], SPACE))

for y := 0; y <= end; y++ {
v := t.cs[y]
Expand All @@ -711,7 +732,11 @@ func (t *Table) printFooter() {
if t.autoFmt {
f = Title(f)
}
pad := ConditionString((y == end && !t.borders.Top), SPACE, t.syms[symNS])
vertical := symNS
if y == end {
vertical = symNSb
}
pad := ConditionString((y == end && !t.borders.Top), SPACE, t.syms[vertical])

if erasePad[y] || (x == 0 && len(f) == 0) {
pad = SPACE
Expand Down Expand Up @@ -740,8 +765,8 @@ func (t *Table) printFooter() {

for i := 0; i <= end; i++ {
v := t.cs[i]
pad := t.syms[symEW]
center := t.syms[symNEW]
pad := t.syms[symEWb]
center := t.syms[symEWbN]
length := len(t.footers[i][0])

if length > 0 {
Expand All @@ -756,9 +781,9 @@ func (t *Table) printFooter() {
// Print first junction
if i == 0 {
if length > 0 && !t.borders.Left {
center = t.syms[symEW]
center = t.syms[symEWb]
} else if center != SPACE {
center = t.syms[symNE]
center = t.syms[symNEb]
}
fmt.Fprint(t.out, center)
}
Expand All @@ -769,17 +794,17 @@ func (t *Table) printFooter() {
}
// Ignore left space as it has printed before
if hasPrinted || t.borders.Left {
pad = t.syms[symEW]
center = t.syms[symNEW]
pad = t.syms[symEWb]
center = t.syms[symEWbN]
}

// Change Center end position
if center != SPACE {
if i == end {
if t.borders.Right {
center = t.syms[symNW]
center = t.syms[symNWb]
} else {
center = t.syms[symEW]
center = t.syms[symEWb]
}
}
}
Expand All @@ -788,9 +813,9 @@ func (t *Table) printFooter() {
if center == SPACE {
if i < end && len(t.footers[i+1][0]) != 0 {
if !t.borders.Left {
center = t.syms[symEW]
center = t.syms[symEWb]
} else {
center = t.syms[symNEW]
center = t.syms[symEWbN]
}
}
}
Expand Down Expand Up @@ -887,7 +912,11 @@ func (t *Table) printRow(columns [][]string, rowIdx int) {

// Check if border is set
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.syms[symNS]))
vertical := symNS
if y == 0 {
vertical = symNSb
}
fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.syms[vertical]))
fmt.Fprintf(t.out, SPACE)
}

Expand Down Expand Up @@ -931,7 +960,7 @@ func (t *Table) printRow(columns [][]string, rowIdx int) {
// Check if border is set
// Replace with space if not set
if !t.noWhiteSpace {
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.syms[symNS], SPACE))
fmt.Fprint(t.out, ConditionString(t.borders.Left, t.syms[symNSb], SPACE))
}
fmt.Fprint(t.out, t.newLine)
}
Expand Down Expand Up @@ -992,7 +1021,11 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
for y := 0; y < total; y++ {

// Check if border is set
fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.syms[symNS]))
vertical := symNS
if y == 0 {
vertical = symNSb
}
fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.syms[vertical]))

fmt.Fprintf(writer, SPACE)

Expand Down Expand Up @@ -1046,7 +1079,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
}
// Check if border is set
// Replace with space if not set
fmt.Fprint(writer, ConditionString(t.borders.Left, t.syms[symNS], SPACE))
fmt.Fprint(writer, ConditionString(t.borders.Left, t.syms[symNSb], SPACE))
fmt.Fprint(writer, t.newLine)
}

Expand Down
Loading

0 comments on commit 3511557

Please sign in to comment.