Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

table: auto expand columns with Style().Size.WidthMin #335

Merged
merged 4 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Pretty-print tables into ASCII/Unicode strings.
- Limit the length of
- Rows (`SetAllowedRowLength`)
- Columns (`ColumnConfig.Width*`)
- Auto-size Rows (`Style().Size.WidthMin` and `Style().Size.WidthMax`)
- Page results by a specified number of Lines (`SetPageSize`)
- Alignment - Horizontal & Vertical
- Auto (horizontal) Align (numeric columns aligned Right)
Expand Down
13 changes: 8 additions & 5 deletions table/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func (t *Table) renderLine(out *strings.Builder, row rowStr, hint renderHint) {

// use a brand-new strings.Builder if a row length limit has been set
var outLine *strings.Builder
if t.allowedRowLength > 0 {
if t.style.Size.WidthMax > 0 {
outLine = &strings.Builder{}
} else {
outLine = out
Expand Down Expand Up @@ -227,8 +227,8 @@ func (t *Table) renderLine(out *strings.Builder, row rowStr, hint renderHint) {

func (t *Table) renderLineMergeOutputs(out *strings.Builder, outLine *strings.Builder) {
outLineStr := outLine.String()
if text.RuneWidthWithoutEscSequences(outLineStr) > t.allowedRowLength {
trimLength := t.allowedRowLength - utf8.RuneCountInString(t.style.Box.UnfinishedRow)
if text.RuneWidthWithoutEscSequences(outLineStr) > t.style.Size.WidthMax {
trimLength := t.style.Size.WidthMax - utf8.RuneCountInString(t.style.Box.UnfinishedRow)
if trimLength > 0 {
out.WriteString(text.Trim(outLineStr, trimLength))
out.WriteString(t.style.Box.UnfinishedRow)
Expand Down Expand Up @@ -385,8 +385,11 @@ func (t *Table) renderTitle(out *strings.Builder) {
colors := t.style.Title.Colors
colorsBorder := t.getBorderColors(renderHint{isTitleRow: true})
rowLength := t.maxRowLength
if t.allowedRowLength != 0 && t.allowedRowLength < rowLength {
rowLength = t.allowedRowLength
if wm := t.style.Size.WidthMax; wm > 0 && wm < rowLength {
rowLength = wm
}
if wm := t.style.Size.WidthMin; wm > 0 && wm > rowLength {
rowLength = wm
}
if t.style.Options.DrawBorder {
lenBorder := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.TopLeft+t.style.Box.TopRight)
Expand Down
62 changes: 46 additions & 16 deletions table/render_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ func (t *Table) initForRender() {

// find the longest continuous line in each column
t.initForRenderColumnLengths()
t.initForRenderMaxRowLength()
t.initForRenderPaddedColumns()

// generate a separator row and calculate maximum row length
t.initForRenderRowSeparator()
Expand Down Expand Up @@ -172,6 +174,50 @@ func (t *Table) initForRenderHideColumns() {
t.columnConfigMap = columnConfigMap
}

func (t *Table) initForRenderMaxRowLength() {
t.maxRowLength = 0
if t.autoIndex {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft)
t.maxRowLength += len(fmt.Sprint(len(t.rows)))
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingRight)
if t.style.Options.SeparateColumns {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
}
}
if t.style.Options.SeparateColumns {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator) * (t.numColumns - 1)
}
for _, maxColumnLength := range t.maxColumnLengths {
maxColumnLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
t.maxRowLength += maxColumnLength
}
if t.style.Options.DrawBorder {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
}
}

func (t *Table) initForRenderPaddedColumns() {
paddingSize := t.style.Size.WidthMin - t.maxRowLength
for paddingSize > 0 {
// distribute padding equally among all columns
numColumnsPadded := 0
for colIdx := 0; paddingSize > 0 && colIdx < t.numColumns; colIdx++ {
colWidthMax := t.getColumnWidthMax(colIdx)
if colWidthMax == 0 || t.maxColumnLengths[colIdx] < colWidthMax {
t.maxColumnLengths[colIdx]++
numColumnsPadded++
paddingSize--
}
}

// avoid endless looping because all columns are at max size and cannot
// be expanded any further
if numColumnsPadded == 0 {
break
}
}
}

func (t *Table) initForRenderRows() {
// auto-index: calc the index column's max length
t.autoIndexVIndexMaxLength = len(fmt.Sprint(len(t.rowsRaw)))
Expand Down Expand Up @@ -206,27 +252,11 @@ func (t *Table) initForRenderRowsStringify(rows []Row, hint renderHint) []rowStr
}

func (t *Table) initForRenderRowSeparator() {
t.maxRowLength = 0
if t.autoIndex {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft)
t.maxRowLength += len(fmt.Sprint(len(t.rows)))
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingRight)
if t.style.Options.SeparateColumns {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
}
}
if t.style.Options.SeparateColumns {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator) * (t.numColumns - 1)
}
t.rowSeparator = make(rowStr, t.numColumns)
for colIdx, maxColumnLength := range t.maxColumnLengths {
maxColumnLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
t.maxRowLength += maxColumnLength
t.rowSeparator[colIdx] = text.RepeatAndTrim(t.style.Box.MiddleHorizontal, maxColumnLength)
}
if t.style.Options.DrawBorder {
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
}
}

func (t *Table) initForRenderSortRows() {
Expand Down
Loading