Skip to content

Commit

Permalink
text: 256 and true color support
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t committed Aug 31, 2023
1 parent 05c0986 commit fb57f75
Show file tree
Hide file tree
Showing 19 changed files with 368 additions and 178 deletions.
18 changes: 9 additions & 9 deletions list/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import (
)

// Render renders the List in a human-readable "pretty" format. Example:
// * Game Of Thrones
// * Winter
// * Is
// * Coming
// * This
// * Is
// * Known
// * The Dark Tower
// * The Gunslinger
// - Game Of Thrones
// - Winter
// - Is
// - Coming
// - This
// - Is
// - Known
// - The Dark Tower
// - The Gunslinger
func (l *List) Render() string {
l.initForRender()

Expand Down
35 changes: 18 additions & 17 deletions list/render_html.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,24 @@ import (
)

// RenderHTML renders the List in the HTML format. Example:
// <ul class="go-pretty-table">
// <li>Game Of Thrones</li>
// <ul class="go-pretty-table-1">
// <li>Winter</li>
// <li>Is</li>
// <li>Coming</li>
// <ul class="go-pretty-table-2">
// <li>This</li>
// <li>Is</li>
// <li>Known</li>
// </ul>
// </ul>
// <li>The Dark Tower</li>
// <ul class="go-pretty-table-1">
// <li>The Gunslinger</li>
// </ul>
// </ul>
//
// <ul class="go-pretty-table">
// <li>Game Of Thrones</li>
// <ul class="go-pretty-table-1">
// <li>Winter</li>
// <li>Is</li>
// <li>Coming</li>
// <ul class="go-pretty-table-2">
// <li>This</li>
// <li>Is</li>
// <li>Known</li>
// </ul>
// </ul>
// <li>The Dark Tower</li>
// <ul class="go-pretty-table-1">
// <li>The Gunslinger</li>
// </ul>
// </ul>
func (l *List) RenderHTML() string {
l.initForRender()

Expand Down
18 changes: 9 additions & 9 deletions list/render_markdown.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package list

// RenderMarkdown renders the List in the Markdown format. Example:
// * Game Of Thrones
// * Winter
// * Is
// * Coming
// * This
// * Is
// * Known
// * The Dark Tower
// * The Gunslinger
// - Game Of Thrones
// - Winter
// - Is
// - Coming
// - This
// - Is
// - Known
// - The Dark Tower
// - The Gunslinger
func (l *List) RenderMarkdown() string {
// make a copy of the original style and ensure it is restored on exit
originalStyle := l.style
Expand Down
8 changes: 4 additions & 4 deletions progress/tracker_sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (sb sortByMessage) Less(i, j int) bool { return sb[i].message() < sb[j].mes

type sortByPercent []*Tracker

func (sb sortByPercent) Len() int { return len(sb) }
func (sb sortByPercent) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByPercent) Len() int { return len(sb) }
func (sb sortByPercent) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByPercent) Less(i, j int) bool {
if sb[i].PercentDone() == sb[j].PercentDone() {
return sb[i].timeStart.Before(sb[j].timeStart)
Expand All @@ -67,8 +67,8 @@ func (sb sortByPercent) Less(i, j int) bool {

type sortByValue []*Tracker

func (sb sortByValue) Len() int { return len(sb) }
func (sb sortByValue) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByValue) Len() int { return len(sb) }
func (sb sortByValue) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByValue) Less(i, j int) bool {
if sb[i].value == sb[j].value {
return sb[i].timeStart.Before(sb[j].timeStart)
Expand Down
19 changes: 10 additions & 9 deletions table/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import (
)

// Render renders the Table in a human-readable "pretty" format. Example:
// ┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
// │ # │ FIRST NAME │ LAST NAME │ SALARY │ │
// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
// │ 1 │ Arya │ Stark │ 3000 │ │
// │ 20 │ Jon │ Snow │ 2000 │ You know nothing, Jon Snow! │
// │ 300 │ Tyrion │ Lannister │ 5000 │ │
// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
// │ │ │ TOTAL │ 10000 │ │
// └─────┴────────────┴───────────┴────────┴─────────────────────────────┘
//
// ┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
// │ # │ FIRST NAME │ LAST NAME │ SALARY │ │
// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
// │ 1 │ Arya │ Stark │ 3000 │ │
// │ 20 │ Jon │ Snow │ 2000 │ You know nothing, Jon Snow! │
// │ 300 │ Tyrion │ Lannister │ 5000 │ │
// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
// │ │ │ TOTAL │ 10000 │ │
// └─────┴────────────┴───────────┴────────┴─────────────────────────────┘
func (t *Table) Render() string {
t.initForRender()

Expand Down
11 changes: 6 additions & 5 deletions table/render_csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
)

// RenderCSV renders the Table in CSV format. Example:
// #,First Name,Last Name,Salary,
// 1,Arya,Stark,3000,
// 20,Jon,Snow,2000,"You know nothing\, Jon Snow!"
// 300,Tyrion,Lannister,5000,
// ,,Total,10000,
//
// #,First Name,Last Name,Salary,
// 1,Arya,Stark,3000,
// 20,Jon,Snow,2000,"You know nothing\, Jon Snow!"
// 300,Tyrion,Lannister,5000,
// ,,Total,10000,
func (t *Table) RenderCSV() string {
t.initForRender()

Expand Down
87 changes: 44 additions & 43 deletions table/render_html.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,50 @@ const (
)

// RenderHTML renders the Table in HTML format. Example:
// <table class="go-pretty-table">
// <thead>
// <tr>
// <th align="right">#</th>
// <th>First Name</th>
// <th>Last Name</th>
// <th align="right">Salary</th>
// <th>&nbsp;</th>
// </tr>
// </thead>
// <tbody>
// <tr>
// <td align="right">1</td>
// <td>Arya</td>
// <td>Stark</td>
// <td align="right">3000</td>
// <td>&nbsp;</td>
// </tr>
// <tr>
// <td align="right">20</td>
// <td>Jon</td>
// <td>Snow</td>
// <td align="right">2000</td>
// <td>You know nothing, Jon Snow!</td>
// </tr>
// <tr>
// <td align="right">300</td>
// <td>Tyrion</td>
// <td>Lannister</td>
// <td align="right">5000</td>
// <td>&nbsp;</td>
// </tr>
// </tbody>
// <tfoot>
// <tr>
// <td align="right">&nbsp;</td>
// <td>&nbsp;</td>
// <td>Total</td>
// <td align="right">10000</td>
// <td>&nbsp;</td>
// </tr>
// </tfoot>
// </table>
//
// <table class="go-pretty-table">
// <thead>
// <tr>
// <th align="right">#</th>
// <th>First Name</th>
// <th>Last Name</th>
// <th align="right">Salary</th>
// <th>&nbsp;</th>
// </tr>
// </thead>
// <tbody>
// <tr>
// <td align="right">1</td>
// <td>Arya</td>
// <td>Stark</td>
// <td align="right">3000</td>
// <td>&nbsp;</td>
// </tr>
// <tr>
// <td align="right">20</td>
// <td>Jon</td>
// <td>Snow</td>
// <td align="right">2000</td>
// <td>You know nothing, Jon Snow!</td>
// </tr>
// <tr>
// <td align="right">300</td>
// <td>Tyrion</td>
// <td>Lannister</td>
// <td align="right">5000</td>
// <td>&nbsp;</td>
// </tr>
// </tbody>
// <tfoot>
// <tr>
// <td align="right">&nbsp;</td>
// <td>&nbsp;</td>
// <td>Total</td>
// <td align="right">10000</td>
// <td>&nbsp;</td>
// </tr>
// </tfoot>
// </table>
func (t *Table) RenderHTML() string {
t.initForRender()

Expand Down
13 changes: 7 additions & 6 deletions table/render_markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (
)

// RenderMarkdown renders the Table in Markdown format. Example:
// | # | First Name | Last Name | Salary | |
// | ---:| --- | --- | ---:| --- |
// | 1 | Arya | Stark | 3000 | |
// | 20 | Jon | Snow | 2000 | You know nothing, Jon Snow! |
// | 300 | Tyrion | Lannister | 5000 | |
// | | | Total | 10000 | |
//
// | # | First Name | Last Name | Salary | |
// | ---:| --- | --- | ---:| --- |
// | 1 | Arya | Stark | 3000 | |
// | 20 | Jon | Snow | 2000 | You know nothing, Jon Snow! |
// | 300 | Tyrion | Lannister | 5000 | |
// | | | Total | 10000 | |
func (t *Table) RenderMarkdown() string {
t.initForRender()

Expand Down
15 changes: 8 additions & 7 deletions table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,15 @@ func (t *Table) AppendRows(rows []Row, config ...RowConfig) {
// append is a separator, it will not be rendered in addition to the usual table
// separator.
//
//******************************************************************************
// ******************************************************************************
// Please note the following caveats:
// 1. SetPageSize(): this may end up creating consecutive separator rows near
// the end of a page or at the beginning of a page
// 2. SortBy(): since SortBy could inherently alter the ordering of rows, the
// separators may not appear after the row it was originally intended to
// follow
//******************************************************************************
// 1. SetPageSize(): this may end up creating consecutive separator rows near
// the end of a page or at the beginning of a page
// 2. SortBy(): since SortBy could inherently alter the ordering of rows, the
// separators may not appear after the row it was originally intended to
// follow
//
// ******************************************************************************
func (t *Table) AppendSeparator() {
if t.separators == nil {
t.separators = make(map[int]bool)
Expand Down
10 changes: 5 additions & 5 deletions text/align.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const (
)

// Apply aligns the text as directed. For ex.:
// * AlignDefault.Apply("Jon Snow", 12) returns "Jon Snow "
// * AlignLeft.Apply("Jon Snow", 12) returns "Jon Snow "
// * AlignCenter.Apply("Jon Snow", 12) returns " Jon Snow "
// * AlignJustify.Apply("Jon Snow", 12) returns "Jon Snow"
// * AlignRight.Apply("Jon Snow", 12) returns " Jon Snow"
// - AlignDefault.Apply("Jon Snow", 12) returns "Jon Snow "
// - AlignLeft.Apply("Jon Snow", 12) returns "Jon Snow "
// - AlignCenter.Apply("Jon Snow", 12) returns " Jon Snow "
// - AlignJustify.Apply("Jon Snow", 12) returns "Jon Snow"
// - AlignRight.Apply("Jon Snow", 12) returns " Jon Snow"
func (a Align) Apply(text string, maxLength int) string {
text = a.trimString(text)
sLen := utf8.RuneCountInString(text)
Expand Down
22 changes: 12 additions & 10 deletions text/ansi.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ var ANSICodesSupported = areANSICodesSupported()

// Escape encodes the string with the ANSI Escape Sequence.
// For ex.:
// Escape("Ghost", "") == "Ghost"
// Escape("Ghost", "\x1b[91m") == "\x1b[91mGhost\x1b[0m"
// Escape("\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
// Escape("Nymeria\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
// Escape("Nymeria \x1b[94mGhost\x1b[0m Lady", "\x1b[91m") == "\x1b[91mNymeria \x1b[94mGhost\x1b[0m\x1b[91m Lady\x1b[0m"
//
// Escape("Ghost", "") == "Ghost"
// Escape("Ghost", "\x1b[91m") == "\x1b[91mGhost\x1b[0m"
// Escape("\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
// Escape("Nymeria\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
// Escape("Nymeria \x1b[94mGhost\x1b[0m Lady", "\x1b[91m") == "\x1b[91mNymeria \x1b[94mGhost\x1b[0m\x1b[91m Lady\x1b[0m"
func Escape(str string, escapeSeq string) string {
out := ""
if !strings.HasPrefix(str, EscapeStart) {
Expand All @@ -30,11 +31,12 @@ func Escape(str string, escapeSeq string) string {

// StripEscape strips all ANSI Escape Sequence from the string.
// For ex.:
// StripEscape("Ghost") == "Ghost"
// StripEscape("\x1b[91mGhost\x1b[0m") == "Ghost"
// StripEscape("\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "GhostLady"
// StripEscape("\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "NymeriaGhostLady"
// StripEscape("\x1b[91mNymeria \x1b[94mGhost\x1b[0m\x1b[91m Lady\x1b[0m") == "Nymeria Ghost Lady"
//
// StripEscape("Ghost") == "Ghost"
// StripEscape("\x1b[91mGhost\x1b[0m") == "Ghost"
// StripEscape("\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "GhostLady"
// StripEscape("\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "NymeriaGhostLady"
// StripEscape("\x1b[91mNymeria \x1b[94mGhost\x1b[0m\x1b[91m Lady\x1b[0m") == "Nymeria Ghost Lady"
func StripEscape(str string) string {
var out strings.Builder
out.Grow(RuneWidthWithoutEscSequences(str))
Expand Down
49 changes: 49 additions & 0 deletions text/colors_256.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package text

import (
"fmt"
)

const (
escCodeColor256Background = "48;5;"
escCodeColor256Foreground = "38;5;"
)

// Colors256 contains 8-bit (256) colors for foreground and background.
type Colors256 struct {
Background uint8 `json:"background"`
Foreground uint8 `json:"foreground"`
}

var (
mapColors256EscapeSeq = map[uint]string{}
)

// EscapeSeq returns the ANSI escape sequence for the color.
func (c Colors256) EscapeSeq() string {
mapKey := (uint(c.Background) * 1000) + uint(c.Foreground)
if _, ok := mapColors256EscapeSeq[mapKey]; !ok {
mapColors256EscapeSeq[mapKey] = fmt.Sprintf("%s%s%d;%s%d;%s",
EscapeStart,
escCodeColor256Background, c.Background,
escCodeColor256Foreground, c.Foreground,
EscapeStop,
)
}
return mapColors256EscapeSeq[mapKey]
}

// HTMLProperty returns the "style" attribute for the colors with for.
func (c Colors256) HTMLProperty() string {
return "" // TODO
}

// Sprint colorizes and prints the given string(s).
func (c Colors256) Sprint(a ...interface{}) string {
return colorize(fmt.Sprint(a...), c.EscapeSeq())
}

// Sprintf formats and colorizes and prints the given string(s).
func (c Colors256) Sprintf(format string, a ...interface{}) string {
return colorize(fmt.Sprintf(format, a...), c.EscapeSeq())
}
Binary file added text/colors_256.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit fb57f75

Please sign in to comment.