github.com/charmbracelet/glamour@v0.7.0/ansi/table.go (about) 1 package ansi 2 3 import ( 4 "io" 5 6 "github.com/muesli/reflow/indent" 7 "github.com/olekukonko/tablewriter" 8 astext "github.com/yuin/goldmark/extension/ast" 9 ) 10 11 // A TableElement is used to render tables. 12 type TableElement struct { 13 writer *tablewriter.Table 14 styleWriter *StyleWriter 15 header []string 16 cell []string 17 table *astext.Table 18 } 19 20 // A TableRowElement is used to render a single row in a table. 21 type TableRowElement struct { 22 } 23 24 // A TableHeadElement is used to render a table's head element. 25 type TableHeadElement struct { 26 } 27 28 // A TableCellElement is used to render a single cell in a row. 29 type TableCellElement struct { 30 Text string 31 Head bool 32 } 33 34 func (e *TableElement) Render(w io.Writer, ctx RenderContext) error { 35 bs := ctx.blockStack 36 37 var indentation uint 38 var margin uint 39 rules := ctx.options.Styles.Table 40 if rules.Indent != nil { 41 indentation = *rules.Indent 42 } 43 if rules.Margin != nil { 44 margin = *rules.Margin 45 } 46 47 iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) { 48 renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ") 49 }) 50 51 style := bs.With(rules.StylePrimitive) 52 ctx.table.styleWriter = NewStyleWriter(ctx, iw, style) 53 54 renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) 55 renderText(ctx.table.styleWriter, ctx.options.ColorProfile, style, rules.Prefix) 56 table := tablewriter.NewWriter(ctx.table.styleWriter) 57 58 alignments := make([]int, len(e.table.Alignments)) 59 for i, a := range e.table.Alignments { 60 switch a { 61 case astext.AlignLeft: 62 alignments[i] = tablewriter.ALIGN_LEFT 63 case astext.AlignCenter: 64 alignments[i] = tablewriter.ALIGN_CENTER 65 case astext.AlignRight: 66 alignments[i] = tablewriter.ALIGN_RIGHT 67 } 68 } 69 table.SetColumnAlignment(alignments) 70 71 ctx.table.writer = table 72 return nil 73 } 74 75 func (e *TableElement) Finish(w io.Writer, ctx RenderContext) error { 76 rules := ctx.options.Styles.Table 77 78 ctx.table.writer.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false}) 79 if rules.CenterSeparator != nil { 80 ctx.table.writer.SetCenterSeparator(*rules.CenterSeparator) 81 } 82 if rules.ColumnSeparator != nil { 83 ctx.table.writer.SetColumnSeparator(*rules.ColumnSeparator) 84 } 85 if rules.RowSeparator != nil { 86 ctx.table.writer.SetRowSeparator(*rules.RowSeparator) 87 } 88 89 ctx.table.writer.Render() 90 ctx.table.writer = nil 91 92 renderText(ctx.table.styleWriter, ctx.options.ColorProfile, ctx.blockStack.With(rules.StylePrimitive), rules.Suffix) 93 renderText(ctx.table.styleWriter, ctx.options.ColorProfile, ctx.blockStack.Current().Style.StylePrimitive, rules.BlockSuffix) 94 return ctx.table.styleWriter.Close() 95 } 96 97 func (e *TableRowElement) Finish(w io.Writer, ctx RenderContext) error { 98 if ctx.table.writer == nil { 99 return nil 100 } 101 102 ctx.table.writer.Append(ctx.table.cell) 103 ctx.table.cell = []string{} 104 return nil 105 } 106 107 func (e *TableHeadElement) Finish(w io.Writer, ctx RenderContext) error { 108 if ctx.table.writer == nil { 109 return nil 110 } 111 112 ctx.table.writer.SetHeader(ctx.table.header) 113 ctx.table.header = []string{} 114 return nil 115 } 116 117 func (e *TableCellElement) Render(w io.Writer, ctx RenderContext) error { 118 if e.Head { 119 ctx.table.header = append(ctx.table.header, e.Text) 120 } else { 121 ctx.table.cell = append(ctx.table.cell, e.Text) 122 } 123 124 return nil 125 }