123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- package door
- import (
- "bytes"
- "log"
- "strings"
- "unicode"
- )
- /*
- door.Line - Display a line of text
- Example:
- var basicLine door.Line = {Text: "Welcome",
- DefaultColor: door.Color("BRIGHT YELLOW"),
- }
- d.Write(basicLine.Output() + door.Reset + door.CRNL)
- This outputs Welcome in Bright/Bold Yellow.
- Example Render:
- var renderAlphaDigit ColorRender = func(text string) string {
- var r door.Render{Text: text}
- var alpha string = door.ColorText("BOLD YELLOW")
- var digit string = door.ColorText("BOLD GREEN")
- var other string = door.Reset
- for _, letter := range text {
- if unicode.IsAlpha(letter) {
- r.Append(alpha, 1)
- } else {
- if unicode.IsDigit(letter) {
- r.Append(digit, 1)
- } else {
- r.Append(other, 1)
- }
- }
- }
- return r.Result
- }
- var renderLine door.Line = {Text: "Render - 12345",
- RenderF: renderAlphaDigit,
- }
- d.Write(renderLine.Output() + door.Reset + door.CRNL)
- This outputs "Render" in Yellow, "12345" in Green, and " - " in White.
- Example Update:
- var updateTime() string {
- var now time.Time = time.Now()
- var result string = now.Format("3:04:05 PM")
- return result
- }
- var timeLine door.Line = {Text: updateTime(),
- UpdateF: updateTime,
- }
- d.Write(timeLine.Output() + door.CRNL)
- time.Sleep(time.Second)
- // Check timeLine for update
- if timeLine.Update() {
- // Yes, there's an update to the time, output it.
- d.Write(timeLine.Output() + door.CRNL)
- }
- if timeLine.Update() {
- // This isn't called. There were no changes.
- d.Write(timeLine.Output() + door.CRNL)
- }
- This outputs the Current time in 12 hour format. It pauses for a second,
- and outputs the new time.
- */
- /*
- Line of text to display.
- */
- type Line struct {
- Text *bytes.Buffer // Text to be displayed
- update *bytes.Buffer // Buffer for updates
- DefaultColor []byte // Default Color to use
- RenderF ColorRender // Render function (displays string with colors)
- render *bytes.Buffer // Buffer for rendering
- UpdateF Updater // Update function updates the text
- Width int // Line length
- }
- func NewLine(text string) *Line {
- return &Line{Text: bytes.NewBuffer([]byte(text))}
- }
- /*
- Line Update - This calls the UpdateF if present.
- Returns true if the line has been updated, and there's an Update function.
- */
- func (l *Line) Update() bool {
- if l.Text == nil {
- l.Text = &bytes.Buffer{}
- }
- if l.UpdateF == nil {
- return false
- }
- if l.update == nil {
- l.update = &bytes.Buffer{}
- }
- l.update.Reset()
- l.UpdateF(l.update)
- l.LineLength(l.update)
- // Has the line changed (update)?
- if bytes.Compare(l.update.Bytes(), l.Text.Bytes()) != 0 {
- // Yes, copy into Text.
- l.Text.Reset()
- l.Text.Write(l.update.Bytes())
- return true
- }
- return false
- }
- // If a line Width has been set, make sure we match it.
- func (l *Line) LineLength(text *bytes.Buffer) {
- if l.Width == 0 {
- return
- }
- var length int
- if Unicode {
- if l.render == nil {
- l.render = &bytes.Buffer{}
- }
- l.render.Reset()
- l.render.Write(text.Bytes())
- /*
- var ubuff *bytes.Buffer = bytes.NewBuffer(text.Bytes())
- */
- var e error
- var r rune
- for {
- r, _, e = l.render.ReadRune()
- if e != nil {
- break
- }
- length += UnicodeWidth(r)
- }
- l.render.Reset()
- } else {
- length = text.Len()
- }
- if length > l.Width {
- log.Printf("ERROR: Line Width %d: Have %d\n", l.Width, length)
- } else {
- for length < l.Width {
- text.WriteByte(' ')
- length++
- }
- // *text += strings.Repeat(" ", l.Width-length)
- }
- }
- /*
- Line Output - returns a string with ANSI Color codes.
- If there is no RenderF, we use the DefaultColor. Otherwise we pass the text
- to RenderF and return what it returns.
- */
- func (l *Line) Output() []byte {
- if l.UpdateF == nil {
- l.LineLength(l.Text)
- }
- if l.render == nil {
- l.render = &bytes.Buffer{}
- /*
- // No profiling changes here.
- if l.RenderF == nil {
- var cap int
- if l.DefaultColor != "" {
- cap += len(l.DefaultColor)
- }
- cap += l.Text.Len()
- l.render.Grow(cap)
- }
- */
- }
- if l.RenderF == nil {
- l.render.Reset()
- if len(l.DefaultColor) != 0 {
- l.render.Write(l.DefaultColor)
- }
- l.render.Write(l.Text.Bytes())
- return l.render.Bytes()
- // return l.DefaultColor + l.Text
- } else {
- l.RenderF(l.render, l.Text.Bytes())
- return l.render.Bytes()
- }
- }
- // Make Uppercase RenderF
- func RenderUppercase(Upper string, NonUpper string) ColorRender {
- var UpperColor, NonUpperColor []byte
- if strings.HasPrefix(Upper, "\x1b") {
- UpperColor = []byte(Upper)
- } else {
- UpperColor = []byte(ColorText(Upper))
- }
- if strings.HasPrefix(NonUpper, "\x1b") {
- NonUpperColor = []byte(NonUpper)
- } else {
- NonUpperColor = []byte(ColorText(NonUpper))
- }
- if Unicode {
- var runeBuffer *bytes.Buffer = &bytes.Buffer{}
- return func(output *bytes.Buffer, text []byte) {
- var lastColor *[]byte
- output.Reset()
- runeBuffer.Reset()
- runeBuffer.Write(text)
- for r, _, err := runeBuffer.ReadRune(); err != nil; r, _, err = runeBuffer.ReadRune() {
- // for _, letter := range text {
- if unicode.IsUpper(r) {
- if lastColor != &UpperColor {
- output.Write(UpperColor)
- lastColor = &UpperColor
- }
- } else {
- if lastColor != &NonUpperColor {
- output.Write(NonUpperColor)
- lastColor = &UpperColor
- }
- }
- output.WriteRune(r)
- }
- }
- } else {
- return func(output *bytes.Buffer, text []byte) {
- var lastColor *[]byte
- output.Reset()
- for _, letter := range text {
- if unicode.IsUpper(rune(letter)) {
- if lastColor != &UpperColor {
- output.Write(UpperColor)
- lastColor = &UpperColor
- }
- } else {
- if lastColor != &NonUpperColor {
- output.Write(NonUpperColor)
- lastColor = &UpperColor
- }
- }
- output.WriteByte(letter)
- }
- }
- }
- }
- func RenderBlueYellow(output *bytes.Buffer, text []byte) {
- output.Reset()
- // var output = RenderPool.Get().(*strings.Builder)
- // output.Reset()
- var blue []byte = ColorText("BOLD BLUE")
- var yellow []byte = ColorText("BOLD YELLOW")
- var last *[]byte
- for _, letter := range text {
- if unicode.IsUpper(rune(letter)) {
- if last != &blue {
- output.Write(blue)
- last = &blue
- }
- } else {
- if last != &yellow {
- output.Write(yellow)
- last = &yellow
- }
- }
- output.WriteByte(letter)
- }
- // var result = output.String()
- // RenderPool.Put(output)
- // return result
- }
|