Skip to content

Commit da63c35

Browse files
committed
Fix: respect Left, Right, and Vertical borderConfig in RenderBorderLine
- RenderBorderLine now properly omits left/right border characters when borderConfig.Left or borderConfig.Right is false. - Vertical separators between columns are now omitted when borderConfig.Vertical is false. - Ensures table border rendering is fully consistent with custom BorderConfig
1 parent 5363bec commit da63c35

File tree

7 files changed

+95
-74
lines changed

7 files changed

+95
-74
lines changed

borders.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ var (
196196
}
197197
)
198198

199-
// getBorderConfig returns border configuration for the specified style.
200-
func getBorderConfig(style BorderStyle) BorderConfig {
199+
// GetBorderConfig returns border configuration for the specified style.
200+
func GetBorderConfig(style BorderStyle) BorderConfig {
201201
switch style {
202202
case ASCIIStyle:
203203
return asciiConfig

examples/custom_borders/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func main() {
3131

3232
for _, config := range testConfigs {
3333
fmt.Printf("=== %s Style ===\n", config.name)
34-
table := termhyo.NewTableWithStyle(os.Stdout, columns, termhyo.WithBorderStyle(config.style))
34+
table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(config.style))
3535

3636
// Add header
3737
table.AddRow("Test", config.desc, config.border)

examples/markdown/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func main() {
1515
}
1616

1717
// Create table with Markdown style
18-
table := termhyo.NewTableWithStyle(os.Stdout, columns, termhyo.WithBorderStyle(termhyo.MarkdownStyle))
18+
table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(termhyo.MarkdownStyle))
1919
// table.SetAlign(false) // Disable alignment for streaming mode
2020
// Simulate real-time data streaming in Markdown format
2121
events := [][]string{

examples/streaming/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func main() {
1616
}
1717

1818
// Create table with fixed width (enables streaming mode)
19-
table := termhyo.NewTableWithStyle(os.Stdout, columns, termhyo.WithBorderStyle(termhyo.ASCIIStyle))
19+
table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(termhyo.ASCIIStyle))
2020

2121
// Disable alignment for streaming mode using Table-level setting
2222
// table.SetAlign(false)

examples/styles/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func main() {
3636
for i, style := range styles {
3737
fmt.Printf("\n=== %s ===\n", data[i][0])
3838

39-
table := termhyo.NewTableWithStyle(os.Stdout, columns, termhyo.WithBorderStyle(style))
39+
table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(style))
4040
for _, row := range data {
4141
table.AddRow(row...)
4242
}

table.go

Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,8 @@ import (
55
"strings"
66
)
77

8-
// TableStyle represents the complete styling configuration for a table.
9-
type TableStyle struct {
10-
BorderStyle BorderStyle // Border style configuration
11-
HeaderStyle HeaderStyle // Header styling configuration
12-
}
13-
14-
// DefaultTableStyle returns the default table style.
15-
func DefaultTableStyle() TableStyle {
16-
return TableStyle{
17-
BorderStyle: BoxDrawingStyle,
18-
HeaderStyle: HeaderStyle{},
19-
}
20-
}
21-
22-
// WithBorderStyle creates a TableStyle with the specified border style.
23-
func WithBorderStyle(borderStyle BorderStyle) TableStyle {
24-
return TableStyle{
25-
BorderStyle: borderStyle,
26-
HeaderStyle: HeaderStyle{},
27-
}
28-
}
29-
30-
// WithHeaderStyle creates a TableStyle with the specified header style.
31-
func WithHeaderStyle(headerStyle HeaderStyle) TableStyle {
32-
return TableStyle{
33-
BorderStyle: BoxDrawingStyle,
34-
HeaderStyle: headerStyle,
35-
}
36-
}
37-
38-
// WithStyles creates a TableStyle with both border and header styles.
39-
func WithStyles(borderStyle BorderStyle, headerStyle HeaderStyle) TableStyle {
40-
return TableStyle{
41-
BorderStyle: borderStyle,
42-
HeaderStyle: headerStyle,
43-
}
44-
}
8+
// TableOption is a functional option for configuring Table.
9+
type TableOption func(*Table)
4510

4611
// Table represents the main table structure.
4712
type Table struct {
@@ -84,25 +49,37 @@ func (t *Table) GetAlign() bool {
8449
return t.align
8550
}
8651

87-
// NewTable creates a new table with default styling.
88-
func NewTable(writer io.Writer, columns []Column) *Table {
89-
return NewTableWithStyle(writer, columns, DefaultTableStyle())
90-
}
91-
92-
// NewTableWithStyle creates a new table with specified styling.
93-
func NewTableWithStyle(writer io.Writer, columns []Column, style TableStyle) *Table {
94-
borderConfig := getBorderConfig(style.BorderStyle)
52+
// NewTable creates a new table with the given columns and optional configuration.
53+
//
54+
// This function uses the Functional Option Pattern:
55+
//
56+
// table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(termhyo.BoxDrawingStyle), termhyo.Header(headerStyle), ...)
57+
//
58+
// You can specify border style, header style, alignment, etc. by passing option functions.
59+
//
60+
// Example:
61+
//
62+
// table := termhyo.NewTable(os.Stdout, columns, termhyo.Border(termhyo.DoubleStyle), termhyo.Align(false))
63+
//
64+
// This is the recommended way to create and configure tables in termhyo.
65+
func NewTable(writer io.Writer, columns []Column, opts ...TableOption) *Table {
66+
borderConfig := GetBorderConfig(BoxDrawingStyle)
9567

9668
t := &Table{
9769
columns: columns,
9870
writer: writer,
9971
rows: make([]Row, 0),
10072
padding: 1,
10173
align: true, // Default to aligned columns
102-
borderStyle: style.BorderStyle,
74+
borderStyle: BoxDrawingStyle,
10375
borderConfig: borderConfig,
10476
borders: borderConfig.Chars,
105-
headerStyle: style.HeaderStyle,
77+
headerStyle: HeaderStyle{},
78+
}
79+
80+
// Apply options
81+
for _, opt := range opts {
82+
opt(t)
10683
}
10784

10885
// Determine render mode based on column configuration
@@ -120,6 +97,43 @@ func NewTableWithStyle(writer io.Writer, columns []Column, style TableStyle) *Ta
12097
return t
12198
}
12299

100+
// Border sets the border style (option).
101+
func Border(style BorderStyle) TableOption {
102+
return func(t *Table) {
103+
t.borderStyle = style
104+
t.borderConfig = GetBorderConfig(style)
105+
t.borders = t.borderConfig.Chars
106+
}
107+
}
108+
109+
// Header sets the header style (option).
110+
func Header(style HeaderStyle) TableOption {
111+
return func(t *Table) {
112+
t.headerStyle = style
113+
}
114+
}
115+
116+
// Align sets the align flag (option).
117+
func Align(align bool) TableOption {
118+
return func(t *Table) {
119+
t.align = align
120+
}
121+
}
122+
123+
// BorderConfigOpt sets a custom border configuration (option).
124+
//
125+
// Example:
126+
//
127+
// cfg := termhyo.GetBorderConfig(termhyo.BoxDrawingStyle)
128+
// cfg.Left = false
129+
// table := termhyo.NewTable(os.Stdout, columns, termhyo.BorderConfigOpt(cfg))
130+
func BorderConfigOpt(cfg BorderConfig) TableOption {
131+
return func(t *Table) {
132+
t.borderConfig = cfg
133+
t.borders = cfg.Chars
134+
}
135+
}
136+
123137
// determineRenderMode decides whether to use buffered or streaming mode.
124138
func (t *Table) determineRenderMode() RenderMode {
125139
hasAutoWidth := false
@@ -403,13 +417,16 @@ func (t *Table) formatCell(content string, width int, align Alignment) string {
403417
func (t *Table) RenderBorderLine(position string) error {
404418
var builder strings.Builder
405419

406-
switch position {
407-
case "top":
408-
builder.WriteString(t.borders["top_left"])
409-
case "bottom":
410-
builder.WriteString(t.borders["bottom_left"])
411-
default: // middle
412-
builder.WriteString(t.borders["left_cross"])
420+
// left border (only if enabled)
421+
if t.borderConfig.Left {
422+
switch position {
423+
case "top":
424+
builder.WriteString(t.borders["top_left"])
425+
case "bottom":
426+
builder.WriteString(t.borders["bottom_left"])
427+
default:
428+
builder.WriteString(t.borders["left_cross"])
429+
}
413430
}
414431

415432
for i, col := range t.columns {
@@ -420,7 +437,8 @@ func (t *Table) RenderBorderLine(position string) error {
420437
}
421438
builder.WriteString(strings.Repeat(t.borders["horizontal"], cellWidth))
422439

423-
if i < len(t.columns)-1 {
440+
// Draw vertical separator between columns only if enabled
441+
if t.borderConfig.Vertical && i < len(t.columns)-1 {
424442
switch position {
425443
case "top":
426444
builder.WriteString(t.borders["top_cross"])
@@ -432,13 +450,16 @@ func (t *Table) RenderBorderLine(position string) error {
432450
}
433451
}
434452

435-
switch position {
436-
case "top":
437-
builder.WriteString(t.borders["top_right"])
438-
case "bottom":
439-
builder.WriteString(t.borders["bottom_right"])
440-
default:
441-
builder.WriteString(t.borders["right_cross"])
453+
// right border (only if enabled)
454+
if t.borderConfig.Right {
455+
switch position {
456+
case "top":
457+
builder.WriteString(t.borders["top_right"])
458+
case "bottom":
459+
builder.WriteString(t.borders["bottom_right"])
460+
default:
461+
builder.WriteString(t.borders["right_cross"])
462+
}
442463
}
443464

444465
builder.WriteString("\n")
@@ -463,7 +484,7 @@ func (t *Table) SetRenderer(renderer Renderer) {
463484
// SetBorderStyle changes the border style of the table.
464485
func (t *Table) SetBorderStyle(style BorderStyle) {
465486
t.borderStyle = style
466-
t.borderConfig = getBorderConfig(style)
487+
t.borderConfig = GetBorderConfig(style)
467488
t.borders = t.borderConfig.Chars
468489
}
469490

table_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,21 +262,21 @@ func testDifferentBorderStyles() string {
262262

263263
// Box Drawing Style
264264
buf.WriteString("=== Box Drawing Style ===\n")
265-
table1 := NewTableWithStyle(&buf, columns, WithBorderStyle(BoxDrawingStyle))
265+
table1 := NewTable(&buf, columns, Border(BoxDrawingStyle))
266266
table1.AddRow("Box", "Unicode box drawing")
267267
table1.Render()
268268
buf.WriteString("\n")
269269

270270
// ASCII Style
271271
buf.WriteString("=== ASCII Style ===\n")
272-
table2 := NewTableWithStyle(&buf, columns, WithBorderStyle(ASCIIStyle))
272+
table2 := NewTable(&buf, columns, Border(ASCIIStyle))
273273
table2.AddRow("ASCII", "ASCII characters")
274274
table2.Render()
275275
buf.WriteString("\n")
276276

277277
// Rounded Style
278278
buf.WriteString("=== Rounded Style ===\n")
279-
table3 := NewTableWithStyle(&buf, columns, WithBorderStyle(RoundedStyle))
279+
table3 := NewTable(&buf, columns, Border(RoundedStyle))
280280
table3.AddRow("Rounded", "Rounded corners")
281281
table3.Render()
282282

@@ -291,7 +291,7 @@ func testMarkdownTable() string {
291291
{Title: "Priority", Width: 0, Align: Right},
292292
}
293293

294-
table := NewTableWithStyle(&buf, columns, WithBorderStyle(MarkdownStyle))
294+
table := NewTable(&buf, columns, Border(MarkdownStyle))
295295
table.AddRow("Header styles", "Done", "High")
296296
table.AddRow("Border controls", "Done", "High")
297297
table.AddRow("Documentation", "In Progress", "Medium")
@@ -313,7 +313,7 @@ func testMarkdownWithHeaderStyle() string {
313313
ForegroundColor: AnsiWhite,
314314
BackgroundColor: AnsiBgBlue,
315315
}
316-
table := NewTableWithStyle(&buf, columns, WithStyles(MarkdownStyle, headerStyle))
316+
table := NewTable(&buf, columns, Border(MarkdownStyle), Header(headerStyle))
317317
table.AddRow("Header styles", "Done", "High")
318318
table.AddRow("Border controls", "Done", "High")
319319
table.Render()

0 commit comments

Comments
 (0)