-
Notifications
You must be signed in to change notification settings - Fork 0
/
printer.go
159 lines (141 loc) · 4.27 KB
/
printer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// This file is part of Palette.
// Copyright (C) 2024 Enindu Alahapperuma
//
// Palette is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// Palette is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// Palette. If not, see <https://www.gnu.org/licenses/>.
package palette
import (
"bytes"
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
)
var mutex *sync.Mutex = &sync.Mutex{}
// Printer represents a new printer. A printer is safe to use concurrently in
// multiple goroutines except setters.
type Printer struct {
writer io.Writer
styles []uint64
foreground uint64
background uint64
buffer *bytes.Buffer
}
// Print formats i and a, and writes it to p.writer. It returns number bytes
// written and any error occurred.
func (p *Printer) Print(i string, a ...any) (int64, error) {
mutex.Lock()
defer mutex.Unlock()
defer p.buffer.Reset()
p.format(i, a...)
return p.buffer.WriteTo(p.writer)
}
// SetWriter sets p.writer using w. It returns a pointer to p.
func (p *Printer) SetWriter(w io.Writer) *Printer {
p.writer = w
return p
}
// SetStyles sets p.styles using s. It returns a pointer to p.
func (p *Printer) SetStyles(s ...uint64) *Printer {
p.styles = s
return p
}
// SetForeground sets p.foreground using f. It returns a pointer to p.
func (p *Printer) SetForeground(f uint64) *Printer {
p.foreground = f
return p
}
// SetBackground sets p.background using b. It returns a pointer to p.
func (p *Printer) SetBackground(b uint64) *Printer {
p.background = b
return p
}
func (p *Printer) format(i string, a ...any) {
format := fmt.Sprintf(i, a...)
if !strings.Contains(format, "\n") {
p.set()
p.buffer.WriteString(format)
p.unset()
return
}
lines := strings.SplitAfter(format, "\n")
length := len(lines)
if strings.HasSuffix(format, "\n") {
length = length - 1
}
for _, v := range lines[:length] {
end := ""
if strings.HasSuffix(v, "\n") {
v = strings.TrimSuffix(v, "\n")
end = "\n"
}
p.set()
p.buffer.WriteString(v)
p.unset()
p.buffer.WriteString(end)
}
}
func (p *Printer) set() {
p.buffer.WriteString("\x1b[")
for _, v := range p.styles {
style := strconv.FormatUint(v, 10)
p.buffer.WriteString(style)
p.buffer.WriteString(";")
}
foreground := strconv.FormatUint(p.foreground, 10)
background := strconv.FormatUint(p.background, 10)
p.buffer.WriteString(foreground)
p.buffer.WriteString(";")
p.buffer.WriteString(background)
p.buffer.WriteString("m")
}
func (p *Printer) unset() {
p.buffer.WriteString("\x1b[0m")
}
// NewPrinterRegu creates a new [Printer] to print regular messages. It returns
// a pointer to [Printer] with pre-defined values.
func NewPrinterRegu() *Printer {
return NewPrinter(FgRegular, BgRegular, StRegular)
}
// NewPrinterSucc creates a new [Printer] to print success messages. It returns
// a pointer to [Printer] with pre-defined values.
func NewPrinterSucc() *Printer {
return NewPrinter(FgGreen, BgRegular, StBold)
}
// NewPrinterInfo creates a new [Printer] to print information messages. It
// returns a pointer to [Printer] with pre-defined values.
func NewPrinterInfo() *Printer {
return NewPrinter(FgBlue, BgRegular, StBold)
}
// NewPrinterWarn creates a new [Printer] to print warning messages. It returns
// a pointer to [Printer] with pre-defined values.
func NewPrinterWarn() *Printer {
return NewPrinter(FgYellow, BgRegular, StBold)
}
// NewPrinterErro creates a new [Printer] to print error messages. It returns a
// pointer to [Printer] with pre-defined values.
func NewPrinterErro() *Printer {
return NewPrinter(FgRed, BgRegular, StBold).SetWriter(os.Stderr)
}
// NewPrinter creates a new [Printer] using f, b, and s. It returns a pointer to
// [Printer] with default values.
func NewPrinter(f uint64, b uint64, s ...uint64) *Printer {
return &Printer{
writer: os.Stdout,
styles: s,
foreground: f,
background: b,
buffer: &bytes.Buffer{},
}
}