tangled
alpha
login
or
join now
oppi.li
/
gust
6
fork
atom
background code checker for golang
6
fork
atom
overview
issues
2
pulls
pipelines
model: introduce config
oppi.li
11 months ago
d5525055
da3af29b
+337
-131
5 changed files
expand all
collapse all
unified
split
config.go
go.mod
go.sum
model.go
view.go
+272
config.go
···
1
1
+
package gust
2
2
+
3
3
+
import (
4
4
+
"bytes"
5
5
+
"fmt"
6
6
+
"os"
7
7
+
"strings"
8
8
+
9
9
+
"github.com/BurntSushi/toml"
10
10
+
"github.com/charmbracelet/lipgloss"
11
11
+
)
12
12
+
13
13
+
type Config struct {
14
14
+
Mode string `toml:"mode"`
15
15
+
Package string `toml:"package"`
16
16
+
Summarized bool `toml:"summarized"`
17
17
+
Help bool `toml:"help"`
18
18
+
Styles Styles `toml:"styles"`
19
19
+
Signs Signs `toml:"signs"`
20
20
+
}
21
21
+
22
22
+
type Styles struct {
23
23
+
Mode Style `toml:"mode"`
24
24
+
Success Style `toml:"success"`
25
25
+
Running Style `toml:"running"`
26
26
+
Error Style `toml:"error"`
27
27
+
Warning Style `toml:"warning"`
28
28
+
Duration Style `toml:"duration"`
29
29
+
Separator Style `toml:"separator"`
30
30
+
File Style `toml:"file"`
31
31
+
Line Style `toml:"line"`
32
32
+
Context ContextStyles `toml:"context"`
33
33
+
}
34
34
+
35
35
+
type ContextStyles struct {
36
36
+
ActiveLine Style `toml:"activeLine"`
37
37
+
ActiveLineNr Style `toml:"activeLineNr"`
38
38
+
PassiveLine Style `toml:"passiveLine"`
39
39
+
PassiveLineNr Style `toml:"passiveLineNr"`
40
40
+
}
41
41
+
42
42
+
type Signs struct {
43
43
+
Error string `toml:"error"`
44
44
+
Warning string `toml:"warning"`
45
45
+
System string `toml:"system"`
46
46
+
Separator string `toml:"separator"`
47
47
+
PassiveIndent string `toml:"passiveIndent"`
48
48
+
ActiveIndent string `toml:"activeIndent"`
49
49
+
}
50
50
+
51
51
+
type Style struct {
52
52
+
lipgloss.Style
53
53
+
}
54
54
+
55
55
+
type styleTOML struct {
56
56
+
Fg string `toml:"fg,omitempty"`
57
57
+
Bg string `toml:"bg,omitempty"`
58
58
+
Bold bool `toml:"bold,omitempty"`
59
59
+
Italic bool `toml:"italic,omitempty"`
60
60
+
Underline bool `toml:"underline,omitempty"`
61
61
+
Faint bool `toml:"faint,omitempty"`
62
62
+
Reverse bool `toml:"reverse,omitempty"`
63
63
+
}
64
64
+
65
65
+
func (s Style) MarshalTOML() ([]byte, error) {
66
66
+
fg := "5"
67
67
+
bg := ""
68
68
+
69
69
+
color, err := marshalColor(s.GetForeground())
70
70
+
if err != nil {
71
71
+
return nil, err
72
72
+
}
73
73
+
if color != nil {
74
74
+
fg = *color
75
75
+
}
76
76
+
77
77
+
color, err = marshalColor(s.GetBackground())
78
78
+
if err != nil {
79
79
+
return nil, err
80
80
+
}
81
81
+
if color != nil {
82
82
+
bg = *color
83
83
+
}
84
84
+
85
85
+
tomlData := styleTOML{
86
86
+
Fg: fg,
87
87
+
Bg: bg,
88
88
+
Bold: s.GetBold(),
89
89
+
Italic: s.GetItalic(),
90
90
+
Underline: s.GetUnderline(),
91
91
+
Faint: s.GetFaint(),
92
92
+
Reverse: s.GetReverse(),
93
93
+
}
94
94
+
95
95
+
var buf bytes.Buffer
96
96
+
err = toml.NewEncoder(&buf).Encode(tomlData)
97
97
+
if err != nil {
98
98
+
return nil, fmt.Errorf("failed to encode styleTOML to TOML: %w", err)
99
99
+
}
100
100
+
101
101
+
return buf.Bytes(), nil
102
102
+
}
103
103
+
104
104
+
func (s styleTOML) MarshalTOML() ([]byte, error) {
105
105
+
var parts []string
106
106
+
107
107
+
if s.Fg != "" {
108
108
+
parts = append(parts, fmt.Sprintf("fg = \"%s\"", s.Fg))
109
109
+
}
110
110
+
if s.Bg != "" {
111
111
+
parts = append(parts, fmt.Sprintf("bg = \"%s\"", s.Bg))
112
112
+
}
113
113
+
if s.Bold {
114
114
+
parts = append(parts, fmt.Sprintf("bold = %v", s.Bold))
115
115
+
}
116
116
+
if s.Italic {
117
117
+
parts = append(parts, fmt.Sprintf("italic = %v", s.Italic))
118
118
+
}
119
119
+
if s.Underline {
120
120
+
parts = append(parts, fmt.Sprintf("underline = %v", s.Underline))
121
121
+
}
122
122
+
if s.Faint {
123
123
+
parts = append(parts, fmt.Sprintf("faint = %v", s.Faint))
124
124
+
}
125
125
+
if s.Reverse {
126
126
+
parts = append(parts, fmt.Sprintf("reverse = %v", s.Reverse))
127
127
+
}
128
128
+
129
129
+
if len(parts) == 0 {
130
130
+
return nil, nil
131
131
+
}
132
132
+
133
133
+
return []byte("{ " + strings.Join(parts, ", ") + " }"), nil
134
134
+
}
135
135
+
136
136
+
func marshalColor(tc lipgloss.TerminalColor) (*string, error) {
137
137
+
if tc != nil {
138
138
+
switch color := tc.(type) {
139
139
+
case lipgloss.ANSIColor:
140
140
+
s := fmt.Sprintf("%d", color)
141
141
+
return &s, nil
142
142
+
case lipgloss.Color:
143
143
+
s := string(color)
144
144
+
return &s, nil
145
145
+
case lipgloss.NoColor:
146
146
+
return nil, nil
147
147
+
default:
148
148
+
return nil, fmt.Errorf("fg is not serializable, type: %T", color)
149
149
+
}
150
150
+
} else {
151
151
+
return nil, nil
152
152
+
}
153
153
+
}
154
154
+
155
155
+
func (s *Style) UnmarshalTOML(data any) error {
156
156
+
m := data.(map[string]any)
157
157
+
style := lipgloss.NewStyle()
158
158
+
159
159
+
if v, ok := m["fg"].(string); ok {
160
160
+
style = style.Foreground(lipgloss.Color(v))
161
161
+
}
162
162
+
if v, ok := m["bg"].(string); ok {
163
163
+
style = style.Background(lipgloss.Color(v))
164
164
+
}
165
165
+
if v, ok := m["bold"].(bool); ok {
166
166
+
style = style.Bold(v)
167
167
+
}
168
168
+
if v, ok := m["italic"].(bool); ok {
169
169
+
style = style.Italic(v)
170
170
+
}
171
171
+
if v, ok := m["underline"].(bool); ok {
172
172
+
style = style.Underline(v)
173
173
+
}
174
174
+
if v, ok := m["faint"].(bool); ok {
175
175
+
style = style.Faint(v)
176
176
+
}
177
177
+
if v, ok := m["reverse"].(bool); ok {
178
178
+
style = style.Reverse(v)
179
179
+
}
180
180
+
s.Style = style
181
181
+
return nil
182
182
+
}
183
183
+
184
184
+
func (s *Style) UnmarshalText(text []byte) error {
185
185
+
str := string(text)
186
186
+
tokens := strings.Fields(str)
187
187
+
style := lipgloss.NewStyle()
188
188
+
for i := 0; i < len(tokens); i++ {
189
189
+
switch tokens[i] {
190
190
+
case "bold":
191
191
+
style = style.Bold(true)
192
192
+
case "italic":
193
193
+
style = style.Italic(true)
194
194
+
case "underline":
195
195
+
style = style.Underline(true)
196
196
+
case "faint":
197
197
+
style = style.Faint(true)
198
198
+
case "on":
199
199
+
if i+1 < len(tokens) {
200
200
+
style = style.Background(lipgloss.Color(tokens[i+1]))
201
201
+
i++
202
202
+
}
203
203
+
default:
204
204
+
style = style.Foreground(lipgloss.Color(tokens[i]))
205
205
+
}
206
206
+
}
207
207
+
s.Style = style
208
208
+
return nil
209
209
+
}
210
210
+
211
211
+
func DefaultConfig() Config {
212
212
+
return Config{
213
213
+
Summarized: false,
214
214
+
Help: true,
215
215
+
Mode: "build",
216
216
+
Package: "./cmd/gust",
217
217
+
Styles: Styles{
218
218
+
Mode: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("5"))},
219
219
+
Success: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("2"))},
220
220
+
Running: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("3"))},
221
221
+
Error: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("1"))},
222
222
+
Warning: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("3"))},
223
223
+
File: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("4"))},
224
224
+
Duration: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("7"))},
225
225
+
Separator: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("8"))},
226
226
+
Line: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("7"))},
227
227
+
Context: ContextStyles{
228
228
+
ActiveLine: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("12"))},
229
229
+
ActiveLineNr: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("1"))},
230
230
+
PassiveLine: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("12"))},
231
231
+
PassiveLineNr: Style{lipgloss.NewStyle().Foreground(lipgloss.Color("12"))},
232
232
+
},
233
233
+
},
234
234
+
Signs: Signs{
235
235
+
Error: "err",
236
236
+
Warning: "wrn",
237
237
+
System: "sys",
238
238
+
Separator: " · ",
239
239
+
PassiveIndent: " | ",
240
240
+
ActiveIndent: " > ",
241
241
+
},
242
242
+
}
243
243
+
}
244
244
+
245
245
+
func (cfg Config) Dump() {
246
246
+
err := toml.NewEncoder(os.Stdout).Encode(cfg)
247
247
+
if err != nil {
248
248
+
fmt.Fprintf(os.Stderr, "Failed to write config: %v", err)
249
249
+
}
250
250
+
}
251
251
+
252
252
+
func LoadConfig() Config {
253
253
+
cfg := DefaultConfig()
254
254
+
255
255
+
if _, err := toml.DecodeFile("config.toml", &cfg); err != nil {
256
256
+
fmt.Fprintf(os.Stderr, "%s", err.Error())
257
257
+
}
258
258
+
259
259
+
return cfg
260
260
+
}
261
261
+
262
262
+
func WithPackage(pkg string) func(*Config) {
263
263
+
return func(cfg *Config) {
264
264
+
cfg.Package = pkg
265
265
+
}
266
266
+
}
267
267
+
268
268
+
func WithMode(mode string) func(*Config) {
269
269
+
return func(cfg *Config) {
270
270
+
cfg.Mode = mode
271
271
+
}
272
272
+
}
+1
go.mod
···
11
11
)
12
12
13
13
require (
14
14
+
github.com/BurntSushi/toml v1.5.0 // indirect
14
15
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
15
16
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
16
17
github.com/charmbracelet/x/ansi v0.8.0 // indirect
+2
go.sum
···
1
1
+
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
2
2
+
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
1
3
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
2
4
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
3
5
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
+15
-84
model.go
···
8
8
9
9
"github.com/charmbracelet/bubbles/spinner"
10
10
tea "github.com/charmbracelet/bubbletea"
11
11
-
"github.com/charmbracelet/lipgloss"
12
11
"github.com/fsnotify/fsnotify"
13
12
)
14
13
···
17
16
stderr string
18
17
stdout string
19
18
20
20
-
mode string
21
19
messages []CompilerMessage
22
20
fs Fs
23
21
w *fsnotify.Watcher
24
24
-
options Options
22
22
+
config Config
25
23
context int
26
24
27
25
status Status
···
31
29
width, height int
32
30
}
33
31
34
34
-
type Options struct {
35
35
-
summarized bool
36
36
-
help bool
37
37
-
styles Styles
38
38
-
signs Signs
39
39
-
}
40
40
-
41
41
-
type Styles struct {
42
42
-
mode lipgloss.Style
43
43
-
success lipgloss.Style
44
44
-
running lipgloss.Style
45
45
-
error lipgloss.Style
46
46
-
warning lipgloss.Style
47
47
-
duration lipgloss.Style
48
48
-
separator lipgloss.Style
49
49
-
file lipgloss.Style
50
50
-
line lipgloss.Style
51
51
-
context ContextStyles
52
52
-
}
53
53
-
54
54
-
type ContextStyles struct {
55
55
-
activeLine lipgloss.Style
56
56
-
activeLineNr lipgloss.Style
57
57
-
passiveLine lipgloss.Style
58
58
-
passiveLineNr lipgloss.Style
59
59
-
}
32
32
+
func NewModel(watcher *fsnotify.Watcher, config Config, options ...func(*Config)) Model {
33
33
+
for _, o := range options {
34
34
+
o(&config)
35
35
+
}
60
36
61
61
-
type Signs struct {
62
62
-
// sign for error messages
63
63
-
error string
64
64
-
// sign for warning messages
65
65
-
warning string
66
66
-
// sign for system messages
67
67
-
system string
68
68
-
// separator for UI bits
69
69
-
separator string
70
70
-
// indentation prefix string for passive line in context
71
71
-
passiveIndent string
72
72
-
// indentation prefix string for active line in context
73
73
-
activeIndent string
74
74
-
}
75
75
-
76
76
-
func NewModel(watcher *fsnotify.Watcher) Model {
77
37
return Model{
78
38
w: watcher,
79
79
-
mode: "build",
80
39
status: NewStatus(),
81
40
context: 1,
82
82
-
options: Options{
83
83
-
summarized: false,
84
84
-
help: true,
85
85
-
styles: Styles{
86
86
-
mode: lipgloss.NewStyle().Foreground(lipgloss.Color("5")),
87
87
-
success: lipgloss.NewStyle().Foreground(lipgloss.Color("2")),
88
88
-
running: lipgloss.NewStyle().Foreground(lipgloss.Color("3")),
89
89
-
error: lipgloss.NewStyle().Foreground(lipgloss.Color("1")),
90
90
-
warning: lipgloss.NewStyle().Foreground(lipgloss.Color("3")),
91
91
-
file: lipgloss.NewStyle().Foreground(lipgloss.Color("4")),
92
92
-
duration: lipgloss.NewStyle().Foreground(lipgloss.Color("7")),
93
93
-
separator: lipgloss.NewStyle().Foreground(lipgloss.Color("8")),
94
94
-
line: lipgloss.NewStyle().Foreground(lipgloss.Color("7")),
95
95
-
context: ContextStyles{
96
96
-
activeLine: lipgloss.NewStyle().Foreground(lipgloss.Color("12")),
97
97
-
activeLineNr: lipgloss.NewStyle().Foreground(lipgloss.Color("1")),
98
98
-
passiveLine: lipgloss.NewStyle().Foreground(lipgloss.Color("12")),
99
99
-
passiveLineNr: lipgloss.NewStyle().Foreground(lipgloss.Color("12")),
100
100
-
},
101
101
-
},
102
102
-
signs: Signs{
103
103
-
error: "err",
104
104
-
warning: "wrn",
105
105
-
system: "sys",
106
106
-
separator: " · ",
107
107
-
passiveIndent: " | ",
108
108
-
activeIndent: " > ",
109
109
-
},
110
110
-
},
41
41
+
config: config,
111
42
}
112
43
}
113
44
···
126
57
return m, tea.Quit
127
58
case "r":
128
59
var cmd tea.Cmd
129
129
-
if m.mode != "run" {
130
130
-
m.mode = "run"
60
60
+
if m.config.Mode != "run" {
61
61
+
m.config.Mode = "run"
131
62
cmd = reload
132
63
}
133
64
return m, cmd
134
65
case "b":
135
66
var cmd tea.Cmd
136
136
-
if m.mode != "build" {
137
137
-
m.mode = "build"
67
67
+
if m.config.Mode != "build" {
68
68
+
m.config.Mode = "build"
138
69
cmd = reload
139
70
}
140
71
return m, cmd
141
72
case "s":
142
142
-
m.options.summarized = !m.options.summarized
73
73
+
m.config.Summarized = !m.config.Summarized
143
74
return m, nil
144
75
case "h", "?":
145
145
-
m.options.help = !m.options.help
76
76
+
m.config.Help = !m.config.Help
146
77
return m, nil
147
78
default:
148
79
return m, nil
···
196
127
cmd := Success.Cmd()
197
128
m.systemErrors = []error{}
198
129
199
199
-
command := exec.Command("go", m.mode, "./cmd/gust")
130
130
+
command := exec.Command("go", m.config.Mode, m.config.Package)
200
131
stderr, err := command.StderrPipe()
201
132
if err != nil {
202
133
m.systemErrors = append(m.systemErrors, err)
···
229
160
m.stderr = string(stderrData)
230
161
m.stdout = string(stdoutData)
231
162
232
232
-
if m.mode == "build" {
163
163
+
if m.config.Mode == "build" {
233
164
messages := Parse(m.stderr)
234
165
fs := Fs{}
235
235
-
if !m.options.summarized {
166
166
+
if !m.config.Summarized {
236
167
fs = BuildFs(messages)
237
168
fs.PopulateContext(messages, m.context)
238
169
}
+47
-47
view.go
···
28
28
}
29
29
}
30
30
31
31
-
style := m.options.styles
32
32
-
sign := m.options.signs
31
31
+
style := m.config.Styles
32
32
+
sign := m.config.Signs
33
33
34
34
for _, msg := range m.messages {
35
35
var mb strings.Builder
36
36
if msg.Type == "error" {
37
37
-
mb.WriteString(style.error.Render(sign.error))
37
37
+
mb.WriteString(style.Error.Render(sign.Error))
38
38
mb.WriteString(" ")
39
39
} else {
40
40
-
mb.WriteString(style.warning.Render(sign.warning))
40
40
+
mb.WriteString(style.Warning.Render(sign.Warning))
41
41
mb.WriteString(" ")
42
42
}
43
43
44
44
if msg.Location.Line != "" {
45
45
-
mb.WriteString(style.line.Align(lipgloss.Right).Width(maxLineLen).Render(msg.Location.Line))
45
45
+
mb.WriteString(style.Line.Align(lipgloss.Right).Width(maxLineLen).Render(msg.Location.Line))
46
46
47
47
if msg.Location.Column != "" {
48
48
mb.WriteString(":")
49
49
-
mb.WriteString(style.line.Align(lipgloss.Left).Width(maxColLen).Render(msg.Location.Column))
49
49
+
mb.WriteString(style.Line.Align(lipgloss.Left).Width(maxColLen).Render(msg.Location.Column))
50
50
}
51
51
}
52
52
if msg.Location.File != "" {
53
53
mb.WriteString(" ")
54
54
-
mb.WriteString(style.file.Render(msg.Location.File))
54
54
+
mb.WriteString(style.File.Render(msg.Location.File))
55
55
mb.WriteString(" ")
56
56
}
57
57
···
60
60
b.WriteString(wordwrap.String(mb.String(), m.width))
61
61
62
62
// display context
63
63
-
if !m.options.summarized {
63
63
+
if !m.config.Summarized {
64
64
b.WriteString("\n")
65
65
start := msg.Context.Start()
66
66
-
style := style.context
66
66
+
style := style.Context
67
67
for offset, line := range msg.Context.Ordered() {
68
68
nr := fmt.Sprintf("%d", start+offset)
69
69
-
nrStyle := style.passiveLineNr
70
70
-
lineStyle := style.passiveLine
71
71
-
indent := sign.passiveIndent
69
69
+
nrStyle := style.PassiveLineNr
70
70
+
lineStyle := style.PassiveLine
71
71
+
indent := sign.PassiveIndent
72
72
active := false
73
73
if msg.Location.Line == nr {
74
74
active = true
75
75
-
nrStyle = style.activeLineNr
76
76
-
lineStyle = style.activeLine
77
77
-
indent = sign.activeIndent
75
75
+
nrStyle = style.ActiveLineNr
76
76
+
lineStyle = style.ActiveLine
77
77
+
indent = sign.ActiveIndent
78
78
}
79
79
b.WriteString(nrStyle.Render(indent))
80
80
b.WriteString(nrStyle.Align(lipgloss.Right).Render(nr))
···
88
88
tabCount := strings.Count(line[:col-1], "\t")
89
89
90
90
b.WriteString("\n")
91
91
-
b.WriteString(style.passiveLineNr.Render(sign.passiveIndent))
91
91
+
b.WriteString(style.PassiveLineNr.Render(sign.PassiveIndent))
92
92
93
93
leftPadding := col + // current column to place the pointer at
94
94
3*tabCount + // if the line has tabs, we convert to spaces and offset
95
95
len(msg.Location.Line) + // we always print line-numbers, so offset by that too
96
96
1 // there is a single space between line-number and line content
97
97
-
b.WriteString(style.activeLineNr.Width(leftPadding).Align(lipgloss.Right).Render("^"))
97
97
+
b.WriteString(style.ActiveLineNr.Width(leftPadding).Align(lipgloss.Right).Render("^"))
98
98
}
99
99
b.WriteString("\n")
100
100
}
···
104
104
}
105
105
106
106
for _, e := range m.systemErrors {
107
107
-
b.WriteString(style.error.Render(sign.system))
107
107
+
b.WriteString(style.Error.Render(sign.System))
108
108
b.WriteString(" ")
109
109
b.WriteString(e.Error())
110
110
b.WriteString("\n")
···
112
112
113
113
b.WriteString("\n")
114
114
115
115
-
if m.options.help {
115
115
+
if m.config.Help {
116
116
b.WriteString(m.viewHelp())
117
117
}
118
118
···
132
132
}
133
133
}
134
134
135
135
-
style := m.options.styles
136
136
-
sign := m.options.signs
135
135
+
style := m.config.Styles
136
136
+
sign := m.config.Signs
137
137
138
138
// write mode
139
139
-
b.WriteString(style.mode.Render(m.mode))
139
139
+
b.WriteString(style.Mode.Render(m.config.Mode))
140
140
141
141
// write status
142
142
-
statusStyle := style.success
142
142
+
statusStyle := style.Success
143
143
switch m.status.Kind {
144
144
case Running, Initializing:
145
145
-
statusStyle = style.running
145
145
+
statusStyle = style.Running
146
146
case Error:
147
147
-
statusStyle = style.error
147
147
+
statusStyle = style.Error
148
148
}
149
149
if len(m.messages) == 0 {
150
150
-
b.WriteString(style.separator.Render(sign.separator))
150
150
+
b.WriteString(style.Separator.Render(sign.Separator))
151
151
b.WriteString(statusStyle.Render(m.status.View()))
152
152
}
153
153
···
161
161
162
162
// write message summary
163
163
if errorCount != 0 {
164
164
-
b.WriteString(style.separator.Render(sign.separator))
165
165
-
b.WriteString(style.error.Render(fmt.Sprintf("%d error%s", errorCount, plural(errorCount))))
164
164
+
b.WriteString(style.Separator.Render(sign.Separator))
165
165
+
b.WriteString(style.Error.Render(fmt.Sprintf("%d error%s", errorCount, plural(errorCount))))
166
166
}
167
167
if warningCount != 0 {
168
168
-
b.WriteString(style.separator.Render(sign.separator))
169
169
-
b.WriteString(style.warning.Render(fmt.Sprintf("%d warning%s", warningCount, plural(warningCount))))
168
168
+
b.WriteString(style.Separator.Render(sign.Separator))
169
169
+
b.WriteString(style.Warning.Render(fmt.Sprintf("%d warning%s", warningCount, plural(warningCount))))
170
170
}
171
171
172
172
-
b.WriteString(style.separator.Render(sign.separator))
173
173
-
b.WriteString(style.duration.Render(m.duration.String()))
172
172
+
b.WriteString(style.Separator.Render(sign.Separator))
173
173
+
b.WriteString(style.Duration.Render(m.duration.String()))
174
174
175
175
b.WriteString("\n")
176
176
···
179
179
180
180
func (m Model) viewHelp() string {
181
181
var b strings.Builder
182
182
-
style := m.options.styles
183
183
-
sign := m.options.signs
182
182
+
style := m.config.Styles
183
183
+
sign := m.config.Signs
184
184
185
185
b.WriteString("s ")
186
186
-
if m.options.summarized {
187
187
-
b.WriteString(style.separator.Render("show context"))
186
186
+
if m.config.Summarized {
187
187
+
b.WriteString(style.Separator.Render("show context"))
188
188
} else {
189
189
-
b.WriteString(style.separator.Render("hide context"))
189
189
+
b.WriteString(style.Separator.Render("hide context"))
190
190
}
191
191
-
b.WriteString(style.separator.Render(sign.separator))
191
191
+
b.WriteString(style.Separator.Render(sign.Separator))
192
192
193
193
-
if m.mode != "build" {
193
193
+
if m.config.Mode != "build" {
194
194
b.WriteString("b ")
195
195
-
b.WriteString(style.separator.Render("build"))
196
196
-
b.WriteString(style.separator.Render(sign.separator))
195
195
+
b.WriteString(style.Separator.Render("build"))
196
196
+
b.WriteString(style.Separator.Render(sign.Separator))
197
197
}
198
198
199
199
-
if m.mode != "run" {
199
199
+
if m.config.Mode != "run" {
200
200
b.WriteString("r ")
201
201
-
b.WriteString(style.separator.Render("run"))
202
202
-
b.WriteString(style.separator.Render(sign.separator))
201
201
+
b.WriteString(style.Separator.Render("run"))
202
202
+
b.WriteString(style.Separator.Render(sign.Separator))
203
203
}
204
204
205
205
b.WriteString("q ")
206
206
-
b.WriteString(style.separator.Render("quit"))
207
207
-
b.WriteString(style.separator.Render(sign.separator))
206
206
+
b.WriteString(style.Separator.Render("quit"))
207
207
+
b.WriteString(style.Separator.Render(sign.Separator))
208
208
209
209
b.WriteString("h/? ")
210
210
-
b.WriteString(style.separator.Render("hide help"))
210
210
+
b.WriteString(style.Separator.Render("hide help"))
211
211
212
212
return lipgloss.NewStyle().PaddingTop(2).Render(b.String())
213
213
}