28de5aa0ec941a1fcc7bb6eb95df218807b418ee
- Author
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/cmd/soft/browse/browse.go b/cmd/soft/browse/browse.go
2index eebf28893885e9844dccd6787f03e613c67e8ffd..ecb3d5302d44aebee5147d5540477bd79d4ba6c6 100644
3--- a/cmd/soft/browse/browse.go
4+++ b/cmd/soft/browse/browse.go
5@@ -5,9 +5,9 @@ import (
6 "path/filepath"
7 "time"
8
9- "github.com/charmbracelet/bubbles/key"
10- tea "github.com/charmbracelet/bubbletea"
11- "github.com/charmbracelet/lipgloss"
12+ "github.com/charmbracelet/bubbles/v2/key"
13+ tea "github.com/charmbracelet/bubbletea/v2"
14+ "github.com/charmbracelet/lipgloss/v2"
15 "github.com/charmbracelet/soft-serve/git"
16 "github.com/charmbracelet/soft-serve/pkg/proto"
17 "github.com/charmbracelet/soft-serve/pkg/ui/common"
18@@ -39,9 +39,8 @@ var Command = &cobra.Command{
19
20 // Bubble Tea uses Termenv default output so we have to use the same
21 // thing here.
22- output := lipgloss.DefaultRenderer()
23 ctx := cmd.Context()
24- c := common.NewCommon(ctx, output, 0, 0)
25+ c := common.NewCommon(ctx, 0, 0)
26 c.HideCloneCmd = true
27 comps := []common.TabComponent{
28 repo.NewReadme(c),
29@@ -152,7 +151,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
30 switch msg := msg.(type) {
31 case tea.WindowSizeMsg:
32 m.SetSize(msg.Width, msg.Height)
33- case tea.KeyMsg:
34+ case tea.KeyPressMsg:
35 switch {
36 case key.Matches(msg, m.common.KeyMap.Back) && m.error != nil:
37 m.error = nil
38@@ -166,12 +165,10 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
39 m.common.Zone.Close()
40 return m, tea.Quit
41 }
42- case tea.MouseMsg:
43- if msg.Action != tea.MouseActionPress {
44- break
45- }
46- switch msg.Button {
47- case tea.MouseButtonLeft:
48+ case tea.MouseClickMsg:
49+ mouse := msg.Mouse()
50+ switch mouse.Button {
51+ case tea.MouseLeft:
52 switch {
53 case m.common.Zone.Get("footer").InBounds(msg):
54 cmds = append(cmds, footer.ToggleFooterCmd)
55diff --git a/cmd/soft/hook/hook.go b/cmd/soft/hook/hook.go
56index e9b3f1f5c1ff6c3ebf40cbf3f5d5160c53ed8953..8a6fb87dc4ca64a9eaf0da1a1ef7fdaf5a8c7faa 100644
57--- a/cmd/soft/hook/hook.go
58+++ b/cmd/soft/hook/hook.go
59@@ -12,7 +12,7 @@ import (
60 "path/filepath"
61 "strings"
62
63- "github.com/charmbracelet/log"
64+ "github.com/charmbracelet/log/v2"
65 "github.com/charmbracelet/soft-serve/cmd"
66 "github.com/charmbracelet/soft-serve/pkg/backend"
67 "github.com/charmbracelet/soft-serve/pkg/config"
68diff --git a/cmd/soft/main.go b/cmd/soft/main.go
69index 9849e8a268f22fba46644af33b1ee140f79f16a2..9b248fd37aa641d6d0707004413bf53ad959b4aa 100644
70--- a/cmd/soft/main.go
71+++ b/cmd/soft/main.go
72@@ -7,7 +7,8 @@ import (
73 "runtime/debug"
74 "strconv"
75
76- "github.com/charmbracelet/log"
77+ "github.com/charmbracelet/colorprofile"
78+ "github.com/charmbracelet/log/v2"
79 "github.com/charmbracelet/soft-serve/cmd/soft/admin"
80 "github.com/charmbracelet/soft-serve/cmd/soft/browse"
81 "github.com/charmbracelet/soft-serve/cmd/soft/hook"
82@@ -18,7 +19,6 @@ import (
83 "github.com/charmbracelet/soft-serve/pkg/version"
84 mcobra "github.com/muesli/mango-cobra"
85 "github.com/muesli/roff"
86- "github.com/muesli/termenv"
87 "github.com/spf13/cobra"
88 "go.uber.org/automaxprocs/maxprocs"
89 )
90@@ -67,7 +67,7 @@ var (
91
92 func init() {
93 if noColor, _ := strconv.ParseBool(os.Getenv("SOFT_SERVE_NO_COLOR")); noColor {
94- common.DefaultColorProfile = termenv.Ascii
95+ common.DefaultColorProfile = colorprofile.NoTTY
96 }
97
98 rootCmd.AddCommand(
99diff --git a/cmd/soft/serve/server.go b/cmd/soft/serve/server.go
100index 76e55f581234203600edebb4f7b7bcb5d1d155f7..56402f13e0182a0a5e9c0b089727cd398174a731 100644
101--- a/cmd/soft/serve/server.go
102+++ b/cmd/soft/serve/server.go
103@@ -6,7 +6,7 @@ import (
104 "fmt"
105 "net/http"
106
107- "github.com/charmbracelet/log"
108+ "github.com/charmbracelet/log/v2"
109
110 "github.com/charmbracelet/soft-serve/pkg/backend"
111 "github.com/charmbracelet/soft-serve/pkg/config"
112diff --git a/go.mod b/go.mod
113index bbb971c7f45e24d55c50295dd26b1354bd63a219..0a9d3ab30835bed93dc7ad4069bc81a5cca0292c 100644
114--- a/go.mod
115+++ b/go.mod
116@@ -2,31 +2,33 @@ module github.com/charmbracelet/soft-serve
117
118 go 1.23.0
119
120-toolchain go1.24.1
121-
122 require (
123- github.com/charmbracelet/bubbles v0.21.0
124- github.com/charmbracelet/bubbletea v1.3.5
125- github.com/charmbracelet/glamour v0.10.0
126- github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
127- github.com/charmbracelet/wish v1.4.7
128 github.com/dustin/go-humanize v1.0.1
129 github.com/go-git/go-git/v5 v5.16.2
130 github.com/matryer/is v1.4.1
131 github.com/muesli/reflow v0.3.0
132- github.com/muesli/termenv v0.16.0
133- github.com/sergi/go-diff v1.4.0
134 )
135
136 require (
137 github.com/alecthomas/chroma/v2 v2.18.0
138+ github.com/aymanbagabas/bubblezone/v2 v2.0.0-20250319214444-bb232f16d5e3
139+)
140+
141+require (
142 github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2
143 github.com/caarlos0/duration v0.0.0-20240108180406-5d492514f3c7
144- github.com/caarlos0/env/v11 v11.3.1
145+ github.com/caarlos0/env/v11 v11.2.2
146+ github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250603123720-56bbc4a1ba66
147+ github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.3.0.20250617194119-3f1d09f7d826
148+ github.com/charmbracelet/colorprofile v0.3.1
149 github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20240708204110-bacbfdb68d92
150+ github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe
151 github.com/charmbracelet/keygen v0.5.3
152- github.com/charmbracelet/log v0.4.2
153- github.com/charmbracelet/ssh v0.0.0-20250213143314-8712ec3ff3ef
154+ github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.2.0.20250703152125-8e1c474f8a71
155+ github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706
156+ github.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894
157+ github.com/charmbracelet/wish/v2 v2.0.0-20250505151211-5996fc7c1f33
158+ github.com/charmbracelet/x/ansi v0.9.3
159 github.com/go-jose/go-jose/v3 v3.0.4
160 github.com/gobwas/glob v0.2.3
161 github.com/golang-jwt/jwt/v5 v5.2.2
162@@ -37,12 +39,12 @@ require (
163 github.com/hashicorp/golang-lru/v2 v2.0.7
164 github.com/jmoiron/sqlx v1.4.0
165 github.com/lib/pq v1.10.9
166- github.com/lrstanley/bubblezone v1.0.0
167 github.com/muesli/mango-cobra v1.2.0
168 github.com/muesli/roff v0.1.0
169 github.com/prometheus/client_golang v1.22.0
170 github.com/robfig/cron/v3 v3.0.1
171 github.com/rogpeppe/go-internal v1.14.1
172+ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
173 github.com/spf13/cobra v1.9.1
174 go.uber.org/automaxprocs v1.6.0
175 golang.org/x/crypto v0.39.0
176@@ -54,23 +56,19 @@ require (
177 require (
178 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
179 github.com/atotto/clipboard v0.1.4 // indirect
180- github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
181 github.com/aymerick/douceur v0.2.0 // indirect
182 github.com/beorn7/perks v1.0.1 // indirect
183 github.com/cespare/xxhash/v2 v2.3.0 // indirect
184- github.com/charmbracelet/colorprofile v0.3.1 // indirect
185- github.com/charmbracelet/x/ansi v0.8.0 // indirect
186- github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
187+ github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa // indirect
188 github.com/charmbracelet/x/conpty v0.1.0 // indirect
189 github.com/charmbracelet/x/errors v0.0.0-20240725160154-f9f6568126ec // indirect
190 github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect
191- github.com/charmbracelet/x/input v0.3.4 // indirect
192+ github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86 // indirect
193 github.com/charmbracelet/x/term v0.2.1 // indirect
194 github.com/charmbracelet/x/termios v0.1.0 // indirect
195- github.com/charmbracelet/x/windows v0.2.0 // indirect
196+ github.com/charmbracelet/x/windows v0.2.1 // indirect
197 github.com/creack/pty v1.1.21 // indirect
198 github.com/dlclark/regexp2 v1.11.5 // indirect
199- github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
200 github.com/felixge/httpsnoop v1.0.4 // indirect
201 github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
202 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
203@@ -79,11 +77,9 @@ require (
204 github.com/inconshreveable/mousetrap v1.1.0 // indirect
205 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
206 github.com/mattn/go-isatty v0.0.20 // indirect
207- github.com/mattn/go-localereader v0.0.1 // indirect
208 github.com/mattn/go-runewidth v0.0.16 // indirect
209 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 // indirect
210 github.com/microcosm-cc/bluemonday v1.0.27 // indirect
211- github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
212 github.com/muesli/cancelreader v0.2.2 // indirect
213 github.com/muesli/mango v0.2.0 // indirect
214 github.com/muesli/mango-pflag v0.1.0 // indirect
215@@ -102,7 +98,6 @@ require (
216diff --git a/go.sum b/go.sum
217index ea0a226f43db522d88b6ac8dfa9c85679932b91f..db678352e5e86f5a654a991561bd1fa8f448ac90 100644
218--- a/go.sum
219+++ b/go.sum
220@@ -10,10 +10,10 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
221 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
222 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
223 github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
224+github.com/aymanbagabas/bubblezone/v2 v2.0.0-20250319214444-bb232f16d5e3 h1:1z2ihw0YUYUhNmRaavyXvG9ZU/9Tj0vj6sA3z5DFIJ8=
225+github.com/aymanbagabas/bubblezone/v2 v2.0.0-20250319214444-bb232f16d5e3/go.mod h1:sJwqZoo/BSKSizmr0pSJ758RuRsnjlkrOaxPtwlWtOs=
226 github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2 h1:3w5KT+shE3hzWhORGiu2liVjEoaCEXm9uZP47+Gw4So=
227 github.com/aymanbagabas/git-module v1.8.4-0.20231101154130-8d27204ac6d2/go.mod h1:d4gQ7/3/S2sPq4NnKdtAgUOVr6XtLpWFtxyVV5/+76U=
228-github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
229-github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
230 github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
231 github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
232 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
233@@ -22,50 +22,50 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
234 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
235 github.com/caarlos0/duration v0.0.0-20240108180406-5d492514f3c7 h1:kJP/C2eL9DCKrCOlX6lPVmAUAb6U4u9xllgws1kP9ds=
236 github.com/caarlos0/duration v0.0.0-20240108180406-5d492514f3c7/go.mod h1:mSkwb/eZEwOJJJ4tqAKiuhLIPe0e9+FKhlU0oMCpbf8=
237-github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA=
238-github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
239+github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
240+github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
241 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
242 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
243-github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
244-github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
245-github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc=
246-github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54=
247+github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250603123720-56bbc4a1ba66 h1:LDUnLzW0DZ4riy4juBAXJWeE94vvVChgZwzhZL/4wuk=
248+github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250603123720-56bbc4a1ba66/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw=
249+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.3.0.20250617194119-3f1d09f7d826 h1:pQxCWMojVjHePqGzWsANhplourZYsD6AuR6eR2Hi5yc=
250+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.3.0.20250617194119-3f1d09f7d826/go.mod h1:bfzSaUDPMKrWDjD6wo/ato9lfDdEX83rZgwcXHYWJ98=
251 github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
252 github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
253 github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20240708204110-bacbfdb68d92 h1:KtQlsiHfY3K4AoIEh0yUE/wCLHteZ9EzV1hKmx+p7U8=
254 github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20240708204110-bacbfdb68d92/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
255-github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY=
256-github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk=
257+github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe h1:i6ce4CcAlPpTj2ER69m1DBeLZ3RRcHnKExuwhKa3GfY=
258+github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe/go.mod h1:p3Q+aN4eQKeM5jhrmXPMgPrlKbmc59rWSnMsSA3udhk=
259 github.com/charmbracelet/keygen v0.5.3 h1:2MSDC62OUbDy6VmjIE2jM24LuXUvKywLCmaJDmr/Z/4=
260 github.com/charmbracelet/keygen v0.5.3/go.mod h1:TcpNoMAO5GSmhx3SgcEMqCrtn8BahKhB8AlwnLjRUpk=
261-github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE=
262-github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA=
263-github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
264-github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
265-github.com/charmbracelet/ssh v0.0.0-20250213143314-8712ec3ff3ef h1:dNZwn4is5svUd+sQEGsrXtp7VwD2ipYaCkKMzcpAEIE=
266-github.com/charmbracelet/ssh v0.0.0-20250213143314-8712ec3ff3ef/go.mod h1:hg+I6gvlMl16nS9ZzQNgBIrrCasGwEw0QiLsDcP01Ko=
267-github.com/charmbracelet/wish v1.4.7 h1:O+jdLac3s6GaqkOHHSwezejNK04vl6VjO1A+hl8J8Yc=
268-github.com/charmbracelet/wish v1.4.7/go.mod h1:OBZ8vC62JC5cvbxJLh+bIWtG7Ctmct+ewziuUWK+G14=
269-github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
270-github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
271-github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
272-github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
273+github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.2.0.20250703152125-8e1c474f8a71 h1:X0tsNa2UHCKNw+illiavosasVzqioRo32SRV35iwr2I=
274+github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.2.0.20250703152125-8e1c474f8a71/go.mod h1:EJWvaCrhOhNGVZMvcjc0yVryl4qqpMs8tz0r9WyEkdQ=
275+github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 h1:WkwO6Ks3mSIGnGuSdKl9qDSyfbYK50z2wc2gGMggegE=
276+github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706/go.mod h1:mjJGp00cxcfvD5xdCa+bso251Jt4owrQvuimJtVmEmM=
277+github.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894 h1:Ffon9TbltLGBsT6XE//YvNuu4OAaThXioqalhH11xEw=
278+github.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894/go.mod h1:hg+I6gvlMl16nS9ZzQNgBIrrCasGwEw0QiLsDcP01Ko=
279+github.com/charmbracelet/wish/v2 v2.0.0-20250505151211-5996fc7c1f33 h1:/TlxP6Lw9Z7NJCQ7TSbuvfO3/AL0UXGDPwH1zO9pV8U=
280+github.com/charmbracelet/wish/v2 v2.0.0-20250505151211-5996fc7c1f33/go.mod h1:Tssk2d4IKqV3tNiPgwrYSvJMQu+nN9J4JlGmYaXpiR4=
281+github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0=
282+github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
283+github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa h1:lphz0Z3rsiOtMYiz8axkT24i9yFiueDhJbzyNUADmME=
284+github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa/go.mod h1:xBlh2Yi3DL3zy/2n15kITpg0YZardf/aa/hgUaIM6Rk=
285 github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=
286 github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=
287 github.com/charmbracelet/x/errors v0.0.0-20240725160154-f9f6568126ec h1:O8c7pFFK0imuHH5JBqv5smlbVoFn4CZKGjtvCQKu1WE=
288 github.com/charmbracelet/x/errors v0.0.0-20240725160154-f9f6568126ec/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
289-github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
290-github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
291+github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a h1:FsHEJ52OC4VuTzU8t+n5frMjLvpYWEznSr/u8tnkCYw=
292+github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
293 github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI=
294 github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU=
295-github.com/charmbracelet/x/input v0.3.4 h1:Mujmnv/4DaitU0p+kIsrlfZl/UlmeLKw1wAP3e1fMN0=
296-github.com/charmbracelet/x/input v0.3.4/go.mod h1:JI8RcvdZWQIhn09VzeK3hdp4lTz7+yhiEdpEQtZN+2c=
297+github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86 h1:BxAEmOBIDajkgao3EsbBxKQCYvgYPGdT62WASLvtf4Y=
298+github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86/go.mod h1:62Rp/6EtTxoeJDSdtpA3tJp3y3ZRpsiekBSje+K8htA=
299 github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
300 github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
301 github.com/charmbracelet/x/termios v0.1.0 h1:y4rjAHeFksBAfGbkRDmVinMg7x7DELIGAFbdNvxg97k=
302 github.com/charmbracelet/x/termios v0.1.0/go.mod h1:H/EVv/KRnrYjz+fCYa9bsKdqF3S8ouDK0AZEbG7r+/U=
303-github.com/charmbracelet/x/windows v0.2.0 h1:ilXA1GJjTNkgOm94CLPeSz7rar54jtFatdmoiONPuEw=
304-github.com/charmbracelet/x/windows v0.2.0/go.mod h1:ZibNFR49ZFqCXgP76sYanisxRyC+EYrBE7TTknD8s1s=
305+github.com/charmbracelet/x/windows v0.2.1 h1:3x7vnbpQrjpuq/4L+I4gNsG5htYoCiA5oe9hLjAij5I=
306+github.com/charmbracelet/x/windows v0.2.1/go.mod h1:ptZp16h40gDYqs5TSawSVW+yiLB13j4kSMA0lSCHL0M=
307 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
308 github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
309 github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
310@@ -76,8 +76,6 @@ github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZ
311 github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
312 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
313 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
314-github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
315-github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
316 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
317 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
318 github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
319@@ -133,16 +131,12 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
320diff --git a/pkg/backend/auth.go b/pkg/backend/auth.go
321index 23713347883ddff6c9a2112d27db740f127052c2..7c8158f6d1ad67a580c2f6216b4ad02664f3a94b 100644
322--- a/pkg/backend/auth.go
323+++ b/pkg/backend/auth.go
324@@ -5,7 +5,7 @@ import (
325 "crypto/sha256"
326 "encoding/hex"
327
328- "github.com/charmbracelet/log"
329+ "github.com/charmbracelet/log/v2"
330 "golang.org/x/crypto/bcrypt"
331 )
332
333diff --git a/pkg/backend/backend.go b/pkg/backend/backend.go
334index ba8796b54546620df6b8377704ee5d76b1c10283..579d4cecbbc95118b8af451fdd8c9069d3c29e63 100644
335--- a/pkg/backend/backend.go
336+++ b/pkg/backend/backend.go
337@@ -3,7 +3,7 @@ package backend
338 import (
339 "context"
340
341- "github.com/charmbracelet/log"
342+ "github.com/charmbracelet/log/v2"
343 "github.com/charmbracelet/soft-serve/pkg/config"
344 "github.com/charmbracelet/soft-serve/pkg/db"
345 "github.com/charmbracelet/soft-serve/pkg/store"
346diff --git a/pkg/backend/webhooks.go b/pkg/backend/webhooks.go
347index e8e1fe9224f5b2bde6e7cae237599b7912fbcee4..cd3eb07e78ce3016c835c6ae00976f5b33fd427c 100644
348--- a/pkg/backend/webhooks.go
349+++ b/pkg/backend/webhooks.go
350@@ -4,7 +4,7 @@ import (
351 "context"
352 "encoding/json"
353
354- "github.com/charmbracelet/log"
355+ "github.com/charmbracelet/log/v2"
356 "github.com/charmbracelet/soft-serve/pkg/db"
357 "github.com/charmbracelet/soft-serve/pkg/db/models"
358 "github.com/charmbracelet/soft-serve/pkg/proto"
359diff --git a/pkg/cron/cron.go b/pkg/cron/cron.go
360index 6fed17b6a15ae6a954e9d6aa8d2418521231b4be..fa290a33e1e826515aeae2fbcd24e78b5a68e95d 100644
361--- a/pkg/cron/cron.go
362+++ b/pkg/cron/cron.go
363@@ -4,7 +4,7 @@ import (
364 "context"
365 "time"
366
367- "github.com/charmbracelet/log"
368+ "github.com/charmbracelet/log/v2"
369 "github.com/robfig/cron/v3"
370 )
371
372diff --git a/pkg/cron/cron_test.go b/pkg/cron/cron_test.go
373index c254191b2e45e889b5d2ce3f10fc1c7f16949c83..b8151db55fbbacb7444a87ad67e3f83ba87e6343 100644
374--- a/pkg/cron/cron_test.go
375+++ b/pkg/cron/cron_test.go
376@@ -6,7 +6,7 @@ import (
377 "fmt"
378 "testing"
379
380- "github.com/charmbracelet/log"
381+ "github.com/charmbracelet/log/v2"
382 )
383
384 func TestCronLogger(t *testing.T) {
385diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go
386index 3afe5e766b7765fb78321e6d5e80dad1f65e65b4..30faadd7aac103ccf7110b36f402908f3ee67ed1 100644
387--- a/pkg/daemon/daemon.go
388+++ b/pkg/daemon/daemon.go
389@@ -12,7 +12,7 @@ import (
390 "sync/atomic"
391 "time"
392
393- "github.com/charmbracelet/log"
394+ "github.com/charmbracelet/log/v2"
395 "github.com/charmbracelet/soft-serve/pkg/access"
396 "github.com/charmbracelet/soft-serve/pkg/backend"
397 "github.com/charmbracelet/soft-serve/pkg/config"
398diff --git a/pkg/db/db.go b/pkg/db/db.go
399index 968d0425afeb65cf7a62d6ebc6c406922178f692..7d5fc2ebea59141c5f40ff83341303792709eebf 100644
400--- a/pkg/db/db.go
401+++ b/pkg/db/db.go
402@@ -6,7 +6,7 @@ import (
403 "errors"
404 "fmt"
405
406- "github.com/charmbracelet/log"
407+ "github.com/charmbracelet/log/v2"
408 "github.com/charmbracelet/soft-serve/pkg/config"
409 "github.com/jmoiron/sqlx"
410 _ "github.com/lib/pq" // postgres driver
411diff --git a/pkg/db/logger.go b/pkg/db/logger.go
412index 821576d11990ebb4b14f76c2015d2a6a8c794f5d..605ec133a82c7676c3a7315904bb09a5fb219e5b 100644
413--- a/pkg/db/logger.go
414+++ b/pkg/db/logger.go
415@@ -5,7 +5,7 @@ import (
416 "database/sql"
417 "strings"
418
419- "github.com/charmbracelet/log"
420+ "github.com/charmbracelet/log/v2"
421 "github.com/jmoiron/sqlx"
422 )
423
424diff --git a/pkg/db/migrate/0003_migrate_lfs_objects.go b/pkg/db/migrate/0003_migrate_lfs_objects.go
425index d7acd7be715be008c6ad8d261de0af622a6a4496..c89775d8ed0b5fc0f0d414179ff6c3c8f6fc4d4c 100644
426--- a/pkg/db/migrate/0003_migrate_lfs_objects.go
427+++ b/pkg/db/migrate/0003_migrate_lfs_objects.go
428@@ -6,7 +6,7 @@ import (
429 "path/filepath"
430 "strconv"
431
432- "github.com/charmbracelet/log"
433+ "github.com/charmbracelet/log/v2"
434 "github.com/charmbracelet/soft-serve/pkg/config"
435 "github.com/charmbracelet/soft-serve/pkg/db"
436 "github.com/charmbracelet/soft-serve/pkg/db/models"
437diff --git a/pkg/db/migrate/migrate.go b/pkg/db/migrate/migrate.go
438index 18bc1780d488d13363e0be7b73768e337a1358e6..8273e454c9b5a8b1ac28edef580147be04dcafee 100644
439--- a/pkg/db/migrate/migrate.go
440+++ b/pkg/db/migrate/migrate.go
441@@ -6,7 +6,7 @@ import (
442 "errors"
443 "fmt"
444
445- "github.com/charmbracelet/log"
446+ "github.com/charmbracelet/log/v2"
447 "github.com/charmbracelet/soft-serve/pkg/db"
448 )
449
450diff --git a/pkg/git/git.go b/pkg/git/git.go
451index ed922e2649bf8c072a6197315507f465c676b85a..7b18cf22d562ebb638520501309a196a04a86cdb 100644
452--- a/pkg/git/git.go
453+++ b/pkg/git/git.go
454@@ -9,7 +9,7 @@ import (
455 "strings"
456
457 gitm "github.com/aymanbagabas/git-module"
458- "github.com/charmbracelet/log"
459+ "github.com/charmbracelet/log/v2"
460 "github.com/charmbracelet/soft-serve/git"
461 "github.com/go-git/go-git/v5/plumbing/format/pktline"
462 )
463diff --git a/pkg/git/lfs.go b/pkg/git/lfs.go
464index 3d3ae6f7e78f828360ccc11c3ff010e4f59a8438..212ad08041a14b20d54acbd50bf8da942f3e4c9a 100644
465--- a/pkg/git/lfs.go
466+++ b/pkg/git/lfs.go
467@@ -12,7 +12,7 @@ import (
468 "time"
469
470 "github.com/charmbracelet/git-lfs-transfer/transfer"
471- "github.com/charmbracelet/log"
472+ "github.com/charmbracelet/log/v2"
473 "github.com/charmbracelet/soft-serve/pkg/config"
474 "github.com/charmbracelet/soft-serve/pkg/db"
475 "github.com/charmbracelet/soft-serve/pkg/db/models"
476diff --git a/pkg/git/lfs_auth.go b/pkg/git/lfs_auth.go
477index edf0785d45e60c20dea26bb998276ec3a67581ac..32a8e6cba7abbc50d7499ba858bdb4ddffc9e83b 100644
478--- a/pkg/git/lfs_auth.go
479+++ b/pkg/git/lfs_auth.go
480@@ -7,7 +7,7 @@ import (
481 "fmt"
482 "time"
483
484- "github.com/charmbracelet/log"
485+ "github.com/charmbracelet/log/v2"
486 "github.com/charmbracelet/soft-serve/pkg/config"
487 "github.com/charmbracelet/soft-serve/pkg/jwk"
488 "github.com/charmbracelet/soft-serve/pkg/lfs"
489diff --git a/pkg/git/lfs_log.go b/pkg/git/lfs_log.go
490index 979932d51df6a5cfd9700c12f7d103d2d2a8aed3..fed14ba440aacc986c99e646fbef90e455c266b2 100644
491--- a/pkg/git/lfs_log.go
492+++ b/pkg/git/lfs_log.go
493@@ -2,7 +2,7 @@ package git
494
495 import (
496 "github.com/charmbracelet/git-lfs-transfer/transfer"
497- "github.com/charmbracelet/log"
498+ "github.com/charmbracelet/log/v2"
499 )
500
501 type lfsLogger struct {
502diff --git a/pkg/git/service.go b/pkg/git/service.go
503index 24576421d4b9a0850501a34143ae6482d4358391..af589c25719320f4c2d8581fe375de32158346b9 100644
504--- a/pkg/git/service.go
505+++ b/pkg/git/service.go
506@@ -10,7 +10,7 @@ import (
507 "strings"
508 "sync"
509
510- "github.com/charmbracelet/log"
511+ "github.com/charmbracelet/log/v2"
512 )
513
514 // Service is a Git daemon service.
515diff --git a/pkg/hooks/gen.go b/pkg/hooks/gen.go
516index 245e5eb69fe4844c19c721cd7573ff723b9b0aab..d06661be6010efa7ae6acc94e296fd072bae50b1 100644
517--- a/pkg/hooks/gen.go
518+++ b/pkg/hooks/gen.go
519@@ -7,7 +7,7 @@ import (
520 "path/filepath"
521 "text/template"
522
523- "github.com/charmbracelet/log"
524+ "github.com/charmbracelet/log/v2"
525 "github.com/charmbracelet/soft-serve/pkg/config"
526 "github.com/charmbracelet/soft-serve/pkg/utils"
527 )
528diff --git a/pkg/jobs/mirror.go b/pkg/jobs/mirror.go
529index 16ea923418ea49d4a24bf7892257d8a93688e3a6..9ebfdd864e76494b5081bb9ba244947989b591ee 100644
530--- a/pkg/jobs/mirror.go
531+++ b/pkg/jobs/mirror.go
532@@ -7,7 +7,7 @@ import (
533 "runtime"
534 "strings"
535
536- "github.com/charmbracelet/log"
537+ "github.com/charmbracelet/log/v2"
538 "github.com/charmbracelet/soft-serve/git"
539 "github.com/charmbracelet/soft-serve/pkg/backend"
540 "github.com/charmbracelet/soft-serve/pkg/config"
541diff --git a/pkg/lfs/basic_transfer.go b/pkg/lfs/basic_transfer.go
542index 609197c1035c176f6d31495d3a8cf57de7f5830c..d3e4100cd3477d77b3fe8a5953882f847336fd53 100644
543--- a/pkg/lfs/basic_transfer.go
544+++ b/pkg/lfs/basic_transfer.go
545@@ -9,7 +9,7 @@ import (
546 "io"
547 "net/http"
548
549- "github.com/charmbracelet/log"
550+ "github.com/charmbracelet/log/v2"
551 )
552
553 // BasicTransferAdapter implements the "basic" adapter
554diff --git a/pkg/lfs/http_client.go b/pkg/lfs/http_client.go
555index a8b55031f083d1fd5e4b9aaccd896fb50013f41c..c78a2e4b2e061a3f8b9c4a675b4f97226ee209bb 100644
556--- a/pkg/lfs/http_client.go
557+++ b/pkg/lfs/http_client.go
558@@ -8,7 +8,7 @@ import (
559 "fmt"
560 "net/http"
561
562- "github.com/charmbracelet/log"
563+ "github.com/charmbracelet/log/v2"
564 )
565
566 // httpClient is a Git LFS client to communicate with a LFS source API.
567diff --git a/pkg/log/log.go b/pkg/log/log.go
568index b9134ead76d6d5a96a413cfea5d2202647054374..0c1552589506a2cd82ae11aa77e300218e47d4d6 100644
569--- a/pkg/log/log.go
570+++ b/pkg/log/log.go
571@@ -5,7 +5,7 @@ import (
572 "strings"
573 "time"
574
575- "github.com/charmbracelet/log"
576+ "github.com/charmbracelet/log/v2"
577 "github.com/charmbracelet/soft-serve/pkg/config"
578 )
579
580diff --git a/pkg/ssh/cmd/blob.go b/pkg/ssh/cmd/blob.go
581index 9678a37a49ce426f3e6a910c04a7f804159d95ee..1aa8fbbe16ffc50c116c4e267f986d20663dcc8f 100644
582--- a/pkg/ssh/cmd/blob.go
583+++ b/pkg/ssh/cmd/blob.go
584@@ -2,8 +2,8 @@ package cmd
585
586 import (
587 "fmt"
588+ "os"
589
590- "github.com/charmbracelet/lipgloss"
591 "github.com/charmbracelet/soft-serve/git"
592 "github.com/charmbracelet/soft-serve/pkg/backend"
593 "github.com/charmbracelet/soft-serve/pkg/ui/common"
594@@ -12,12 +12,16 @@ import (
595 )
596
597 // blobCommand returns a command that prints the contents of a file.
598-func blobCommand(renderer *lipgloss.Renderer) *cobra.Command {
599+func blobCommand() *cobra.Command {
600 var linenumber bool
601 var color bool
602 var raw bool
603+ var noColor bool
604+ if testrun, ok := os.LookupEnv("SOFT_SERVE_NO_COLOR"); ok && testrun == "1" {
605+ noColor = true
606+ }
607
608- styles := styles.DefaultStyles(renderer)
609+ styles := styles.DefaultStyles()
610 cmd := &cobra.Command{
611 Use: "blob REPOSITORY [REFERENCE] [PATH]",
612 Aliases: []string{"cat", "show"},
613@@ -84,7 +88,7 @@ func blobCommand(renderer *lipgloss.Renderer) *cobra.Command {
614 return fmt.Errorf("binary file: use --raw to print")
615 }
616 } else {
617- if color {
618+ if color && !noColor {
619 c, err = common.FormatHighlight(fp, c)
620 if err != nil {
621 return err
622@@ -92,7 +96,7 @@ func blobCommand(renderer *lipgloss.Renderer) *cobra.Command {
623 }
624
625 if linenumber {
626- c, _ = common.FormatLineNumber(styles, c, color)
627+ c, _ = common.FormatLineNumber(styles, c, color && !noColor)
628 }
629
630 cmd.Println(c)
631diff --git a/pkg/ssh/cmd/commit.go b/pkg/ssh/cmd/commit.go
632index 52af6725a53692f7310a75cc6efbce33d0c8492b..88fb1b2c8bd310a3b30492c8e67a02d3c37df72d 100644
633--- a/pkg/ssh/cmd/commit.go
634+++ b/pkg/ssh/cmd/commit.go
635@@ -5,8 +5,7 @@ import (
636 "strings"
637 "time"
638
639- gansi "github.com/charmbracelet/glamour/ansi"
640- "github.com/charmbracelet/lipgloss"
641+ gansi "github.com/charmbracelet/glamour/v2/ansi"
642 "github.com/charmbracelet/soft-serve/git"
643 "github.com/charmbracelet/soft-serve/pkg/backend"
644 "github.com/charmbracelet/soft-serve/pkg/ui/common"
645@@ -15,7 +14,7 @@ import (
646 )
647
648 // commitCommand returns a command that prints the contents of a commit.
649-func commitCommand(renderer *lipgloss.Renderer) *cobra.Command {
650+func commitCommand() *cobra.Command {
651 var color bool
652 var patchOnly bool
653
654@@ -55,7 +54,7 @@ func commitCommand(renderer *lipgloss.Renderer) *cobra.Command {
655 return err
656 }
657
658- commonStyle := styles.DefaultStyles(renderer)
659+ commonStyle := styles.DefaultStyles()
660 style := commonStyle.Log
661
662 s := strings.Builder{}
663diff --git a/pkg/ssh/cmd/git.go b/pkg/ssh/cmd/git.go
664index 7265c9a762dd57ec62348b2da960d1ef7cca3651..620b9f0890e2ee4c19b202f9e97eee7ecab325b2 100644
665--- a/pkg/ssh/cmd/git.go
666+++ b/pkg/ssh/cmd/git.go
667@@ -6,7 +6,7 @@ import (
668 "strings"
669 "time"
670
671- "github.com/charmbracelet/log"
672+ "github.com/charmbracelet/log/v2"
673 "github.com/charmbracelet/soft-serve/pkg/access"
674 "github.com/charmbracelet/soft-serve/pkg/backend"
675 "github.com/charmbracelet/soft-serve/pkg/config"
676diff --git a/pkg/ssh/cmd/repo.go b/pkg/ssh/cmd/repo.go
677index 6a2bb541e62e5ac97da0516bb28440a91ccfbe19..fa3e72ff9a3098b40314acbca119c86628f9850c 100644
678--- a/pkg/ssh/cmd/repo.go
679+++ b/pkg/ssh/cmd/repo.go
680@@ -4,14 +4,13 @@ import (
681 "fmt"
682 "strings"
683
684- "github.com/charmbracelet/lipgloss"
685 "github.com/charmbracelet/soft-serve/pkg/backend"
686 "github.com/charmbracelet/soft-serve/pkg/proto"
687 "github.com/spf13/cobra"
688 )
689
690 // RepoCommand returns a command for managing repositories.
691-func RepoCommand(renderer *lipgloss.Renderer) *cobra.Command {
692+func RepoCommand() *cobra.Command {
693 cmd := &cobra.Command{
694 Use: "repo",
695 Aliases: []string{"repos", "repository", "repositories"},
696@@ -19,10 +18,10 @@ func RepoCommand(renderer *lipgloss.Renderer) *cobra.Command {
697 }
698
699 cmd.AddCommand(
700- blobCommand(renderer),
701+ blobCommand(),
702 branchCommand(),
703 collabCommand(),
704- commitCommand(renderer),
705+ commitCommand(),
706 createCommand(),
707 deleteCommand(),
708 descriptionCommand(),
709diff --git a/pkg/ssh/cmd/tag.go b/pkg/ssh/cmd/tag.go
710index 009ac03083a90c6809b61d2c904ae398a59572fe..fc21ce0e4f73a2a340d61ade327ecfd157c1af0e 100644
711--- a/pkg/ssh/cmd/tag.go
712+++ b/pkg/ssh/cmd/tag.go
713@@ -3,7 +3,7 @@ package cmd
714 import (
715 "strings"
716
717- "github.com/charmbracelet/log"
718+ "github.com/charmbracelet/log/v2"
719 "github.com/charmbracelet/soft-serve/git"
720 "github.com/charmbracelet/soft-serve/pkg/backend"
721 "github.com/charmbracelet/soft-serve/pkg/proto"
722diff --git a/pkg/ssh/cmd/token.go b/pkg/ssh/cmd/token.go
723index 6fb8295379189c7e42cf26907c26e08862f0da7d..6a11ebfcedbc9a5a3f2aa07ffb4cfb5f997002ad 100644
724--- a/pkg/ssh/cmd/token.go
725+++ b/pkg/ssh/cmd/token.go
726@@ -6,7 +6,7 @@ import (
727 "time"
728
729 "github.com/caarlos0/duration"
730- "github.com/charmbracelet/lipgloss/table"
731+ "github.com/charmbracelet/lipgloss/v2/table"
732 "github.com/charmbracelet/soft-serve/pkg/backend"
733 "github.com/charmbracelet/soft-serve/pkg/proto"
734 "github.com/dustin/go-humanize"
735diff --git a/pkg/ssh/cmd/webhooks.go b/pkg/ssh/cmd/webhooks.go
736index e7409ebbaeafd43b2ad37c48695d2ab1729bccf7..ca6e8978929c1ca283d3b5aff470ffed34358132 100644
737--- a/pkg/ssh/cmd/webhooks.go
738+++ b/pkg/ssh/cmd/webhooks.go
739@@ -5,7 +5,7 @@ import (
740 "strconv"
741 "strings"
742
743- "github.com/charmbracelet/lipgloss/table"
744+ "github.com/charmbracelet/lipgloss/v2/table"
745 "github.com/charmbracelet/soft-serve/pkg/backend"
746 "github.com/charmbracelet/soft-serve/pkg/webhook"
747 "github.com/dustin/go-humanize"
748diff --git a/pkg/ssh/middleware.go b/pkg/ssh/middleware.go
749index 1bd93f99c0c81122f18c956056fa07cebaedee96..32c31af933a807bef2de20dd37e53778a7cb91aa 100644
750--- a/pkg/ssh/middleware.go
751+++ b/pkg/ssh/middleware.go
752@@ -2,10 +2,9 @@ package ssh
753
754 import (
755 "fmt"
756- "os"
757 "time"
758
759- "github.com/charmbracelet/log"
760+ "github.com/charmbracelet/log/v2"
761 "github.com/charmbracelet/soft-serve/pkg/backend"
762 "github.com/charmbracelet/soft-serve/pkg/config"
763 "github.com/charmbracelet/soft-serve/pkg/db"
764@@ -14,9 +13,7 @@ import (
765 "github.com/charmbracelet/soft-serve/pkg/sshutils"
766 "github.com/charmbracelet/soft-serve/pkg/store"
767 "github.com/charmbracelet/ssh"
768- "github.com/charmbracelet/wish"
769- bm "github.com/charmbracelet/wish/bubbletea"
770- "github.com/muesli/termenv"
771+ "github.com/charmbracelet/wish/v2"
772 "github.com/prometheus/client_golang/prometheus"
773 "github.com/prometheus/client_golang/prometheus/promauto"
774 "github.com/spf13/cobra"
775@@ -91,12 +88,6 @@ func CommandMiddleware(sh ssh.Handler) ssh.Handler {
776 ctx := s.Context()
777 cfg := config.FromContext(ctx)
778
779- renderer := bm.MakeRenderer(s)
780- if testrun, ok := os.LookupEnv("SOFT_SERVE_NO_COLOR"); ok && testrun == "1" {
781- // Disable colors when running tests.
782- renderer.SetColorProfile(termenv.Ascii)
783- }
784-
785 args := s.Command()
786 cliCommandCounter.WithLabelValues(cmd.CommandName(args)).Inc()
787 rootCmd := &cobra.Command{
788@@ -111,7 +102,7 @@ func CommandMiddleware(sh ssh.Handler) ssh.Handler {
789 cmd.GitUploadPackCommand(),
790 cmd.GitUploadArchiveCommand(),
791 cmd.GitReceivePackCommand(),
792- cmd.RepoCommand(renderer),
793+ cmd.RepoCommand(),
794 cmd.SettingsCommand(),
795 cmd.UserCommand(),
796 cmd.InfoCommand(),
797diff --git a/pkg/ssh/session.go b/pkg/ssh/session.go
798index aecd4619511e977c7367d069d2900fb4b5d1a3f1..892da8bba0de8330c6761e0e30a76adbd80afe12 100644
799--- a/pkg/ssh/session.go
800+++ b/pkg/ssh/session.go
801@@ -1,19 +1,17 @@
802 package ssh
803
804 import (
805- "os"
806 "time"
807
808- tea "github.com/charmbracelet/bubbletea"
809+ tea "github.com/charmbracelet/bubbletea/v2"
810 "github.com/charmbracelet/soft-serve/pkg/access"
811 "github.com/charmbracelet/soft-serve/pkg/backend"
812 "github.com/charmbracelet/soft-serve/pkg/config"
813 "github.com/charmbracelet/soft-serve/pkg/proto"
814 "github.com/charmbracelet/soft-serve/pkg/ui/common"
815 "github.com/charmbracelet/ssh"
816- "github.com/charmbracelet/wish"
817- bm "github.com/charmbracelet/wish/bubbletea"
818- "github.com/muesli/termenv"
819+ "github.com/charmbracelet/wish/v2"
820+ bm "github.com/charmbracelet/wish/v2/bubbletea"
821 "github.com/prometheus/client_golang/prometheus"
822 "github.com/prometheus/client_golang/prometheus/promauto"
823 )
824@@ -54,22 +52,18 @@ func SessionHandler(s ssh.Session) *tea.Program {
825 }
826 }
827
828- renderer := bm.MakeRenderer(s)
829- if testrun, ok := os.LookupEnv("SOFT_SERVE_NO_COLOR"); ok && testrun == "1" {
830- // Disable colors when running tests.
831- renderer.SetColorProfile(termenv.Ascii)
832- }
833-
834- c := common.NewCommon(ctx, renderer, pty.Window.Width, pty.Window.Height)
835- c.SetValue(common.ConfigKey, cfg)
836- m := NewUI(c, initialRepo)
837 opts := bm.MakeOptions(s)
838 opts = append(opts,
839 tea.WithAltScreen(),
840 tea.WithoutCatchPanics(),
841 tea.WithMouseCellMotion(),
842 tea.WithContext(ctx),
843+ tea.WithColorProfile(common.DefaultColorProfile),
844 )
845+
846+ c := common.NewCommon(ctx, pty.Window.Width, pty.Window.Height)
847+ c.SetValue(common.ConfigKey, cfg)
848+ m := NewUI(c, initialRepo)
849 p := tea.NewProgram(m, opts...)
850
851 tuiSessionCounter.WithLabelValues(initialRepo, pty.Term).Inc()
852diff --git a/pkg/ssh/session_test.go b/pkg/ssh/session_test.go
853index 792759c167361c4bd9c10783dda279983e6bc890..f831327450cf92c32188bde1096473274c57e78e 100644
854--- a/pkg/ssh/session_test.go
855+++ b/pkg/ssh/session_test.go
856@@ -8,7 +8,7 @@ import (
857 "testing"
858 "time"
859
860- "github.com/charmbracelet/log"
861+ "github.com/charmbracelet/log/v2"
862 "github.com/charmbracelet/soft-serve/pkg/backend"
863 "github.com/charmbracelet/soft-serve/pkg/config"
864 "github.com/charmbracelet/soft-serve/pkg/db"
865@@ -17,10 +17,9 @@ import (
866 "github.com/charmbracelet/soft-serve/pkg/store/database"
867 "github.com/charmbracelet/soft-serve/pkg/test"
868 "github.com/charmbracelet/ssh"
869- bm "github.com/charmbracelet/wish/bubbletea"
870- "github.com/charmbracelet/wish/testsession"
871+ bm "github.com/charmbracelet/wish/v2/bubbletea"
872+ "github.com/charmbracelet/wish/v2/testsession"
873 "github.com/matryer/is"
874- "github.com/muesli/termenv"
875 gossh "golang.org/x/crypto/ssh"
876 _ "modernc.org/sqlite" // sqlite driver
877 )
878@@ -79,7 +78,7 @@ func setup(tb testing.TB) (*gossh.Session, func() error) {
879 be := backend.New(ctx, cfg, dbx, dbstore)
880 ctx = backend.WithContext(ctx, be)
881 return testsession.New(tb, &ssh.Server{
882- Handler: ContextMiddleware(cfg, dbx, dbstore, be, log.Default())(bm.MiddlewareWithProgramHandler(SessionHandler, termenv.ANSI256)(func(s ssh.Session) {
883+ Handler: ContextMiddleware(cfg, dbx, dbstore, be, log.Default())(bm.MiddlewareWithProgramHandler(SessionHandler)(func(s ssh.Session) {
884 _, _, active := s.Pty()
885 if !active {
886 os.Exit(1)
887diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go
888index f63b0d3897f53b95af494a99ee0a4dc00d872ddf..10d5edee632048c98e83fdfb9609c0426e57f2a0 100644
889--- a/pkg/ssh/ssh.go
890+++ b/pkg/ssh/ssh.go
891@@ -5,22 +5,20 @@ import (
892 "fmt"
893 "net"
894 "os"
895- "runtime"
896 "strconv"
897 "time"
898
899 "github.com/charmbracelet/keygen"
900- "github.com/charmbracelet/log"
901+ "github.com/charmbracelet/log/v2"
902 "github.com/charmbracelet/soft-serve/pkg/backend"
903 "github.com/charmbracelet/soft-serve/pkg/config"
904 "github.com/charmbracelet/soft-serve/pkg/db"
905 "github.com/charmbracelet/soft-serve/pkg/proto"
906 "github.com/charmbracelet/soft-serve/pkg/store"
907- "github.com/charmbracelet/soft-serve/pkg/ui/common"
908 "github.com/charmbracelet/ssh"
909- "github.com/charmbracelet/wish"
910- bm "github.com/charmbracelet/wish/bubbletea"
911- rm "github.com/charmbracelet/wish/recover"
912+ "github.com/charmbracelet/wish/v2"
913+ bm "github.com/charmbracelet/wish/v2/bubbletea"
914+ rm "github.com/charmbracelet/wish/v2/recover"
915 "github.com/prometheus/client_golang/prometheus"
916 "github.com/prometheus/client_golang/prometheus/promauto"
917 gossh "golang.org/x/crypto/ssh"
918@@ -71,7 +69,7 @@ func NewSSHServer(ctx context.Context) (*SSHServer, error) {
919 rm.MiddlewareWithLogger(
920 logger,
921 // BubbleTea middleware.
922- bm.MiddlewareWithProgramHandler(SessionHandler, common.DefaultColorProfile),
923+ bm.MiddlewareWithProgramHandler(SessionHandler),
924 // CLI middleware.
925 CommandMiddleware,
926 // Logging middleware.
927@@ -93,11 +91,10 @@ func NewSSHServer(ctx context.Context) (*SSHServer, error) {
928 wish.WithHostKeyPath(cfg.SSH.KeyPath),
929 wish.WithMiddleware(mw...),
930 }
931- if runtime.GOOS == "windows" {
932- opts = append(opts, ssh.EmulatePty())
933- } else {
934- opts = append(opts, ssh.AllocatePty())
935- }
936+
937+ // TODO: Support a real PTY in future version.
938+ opts = append(opts, ssh.EmulatePty())
939+
940 s.srv, err = wish.NewServer(opts...)
941 if err != nil {
942 return nil, err
943diff --git a/pkg/ssh/ui.go b/pkg/ssh/ui.go
944index 31f6a259cc2e677ac6b90ca2667c5ffee105cde4..204b80181e5ea48eefa9a475e9919ad9606367a3 100644
945--- a/pkg/ssh/ui.go
946+++ b/pkg/ssh/ui.go
947@@ -3,10 +3,10 @@ package ssh
948 import (
949 "errors"
950
951- "github.com/charmbracelet/bubbles/key"
952- "github.com/charmbracelet/bubbles/list"
953- tea "github.com/charmbracelet/bubbletea"
954- "github.com/charmbracelet/lipgloss"
955+ "github.com/charmbracelet/bubbles/v2/key"
956+ "github.com/charmbracelet/bubbles/v2/list"
957+ tea "github.com/charmbracelet/bubbletea/v2"
958+ "github.com/charmbracelet/lipgloss/v2"
959 "github.com/charmbracelet/soft-serve/git"
960 "github.com/charmbracelet/soft-serve/pkg/proto"
961 "github.com/charmbracelet/soft-serve/pkg/ui/common"
962@@ -179,40 +179,34 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
963 cmds = append(cmds, cmd)
964 }
965 }
966- case tea.KeyMsg, tea.MouseMsg:
967- switch msg := msg.(type) {
968- case tea.KeyMsg:
969+ case tea.KeyPressMsg:
970+ switch {
971+ case key.Matches(msg, ui.common.KeyMap.Back) && ui.error != nil:
972+ ui.error = nil
973+ ui.state = readyState
974+ // Always show the footer on error.
975+ ui.showFooter = ui.footer.ShowAll()
976+ case key.Matches(msg, ui.common.KeyMap.Help):
977+ cmds = append(cmds, footer.ToggleFooterCmd)
978+ case key.Matches(msg, ui.common.KeyMap.Quit):
979+ if !ui.IsFiltering() {
980+ // Stop bubblezone background workers.
981+ ui.common.Zone.Close()
982+ return ui, tea.Quit
983+ }
984+ case ui.activePage == repoPage &&
985+ ui.pages[ui.activePage].(*repo.Repo).Path() == "" &&
986+ key.Matches(msg, ui.common.KeyMap.Back):
987+ ui.activePage = selectionPage
988+ // Always show the footer on selection page.
989+ ui.showFooter = true
990+ }
991+ case tea.MouseClickMsg:
992+ switch msg.Mouse().Button {
993+ case tea.MouseLeft:
994 switch {
995- case key.Matches(msg, ui.common.KeyMap.Back) && ui.error != nil:
996- ui.error = nil
997- ui.state = readyState
998- // Always show the footer on error.
999- ui.showFooter = ui.footer.ShowAll()
1000- case key.Matches(msg, ui.common.KeyMap.Help):
1001+ case ui.common.Zone.Get("footer").InBounds(msg):
1002 cmds = append(cmds, footer.ToggleFooterCmd)
1003- case key.Matches(msg, ui.common.KeyMap.Quit):
1004- if !ui.IsFiltering() {
1005- // Stop bubblezone background workers.
1006- ui.common.Zone.Close()
1007- return ui, tea.Quit
1008- }
1009- case ui.activePage == repoPage &&
1010- ui.pages[ui.activePage].(*repo.Repo).Path() == "" &&
1011- key.Matches(msg, ui.common.KeyMap.Back):
1012- ui.activePage = selectionPage
1013- // Always show the footer on selection page.
1014- ui.showFooter = true
1015- }
1016- case tea.MouseMsg:
1017- if msg.Action != tea.MouseActionPress {
1018- break
1019- }
1020- switch msg.Button {
1021- case tea.MouseButtonLeft:
1022- switch {
1023- case ui.common.Zone.Get("footer").InBounds(msg):
1024- cmds = append(cmds, footer.ToggleFooterCmd)
1025- }
1026 }
1027 }
1028 case footer.ToggleFooterMsg:
1029diff --git a/pkg/store/database/database.go b/pkg/store/database/database.go
1030index 02c4bd19cf25e2c3dccd59829eeb71d1947e59af..e41087c7a8dfaa8f14da34715425c0f761d380ba 100644
1031--- a/pkg/store/database/database.go
1032+++ b/pkg/store/database/database.go
1033@@ -3,7 +3,7 @@ package database
1034 import (
1035 "context"
1036
1037- "github.com/charmbracelet/log"
1038+ "github.com/charmbracelet/log/v2"
1039 "github.com/charmbracelet/soft-serve/pkg/config"
1040 "github.com/charmbracelet/soft-serve/pkg/db"
1041 "github.com/charmbracelet/soft-serve/pkg/store"
1042diff --git a/pkg/ui/common/common.go b/pkg/ui/common/common.go
1043index 93d40f57328aa1d191dc5115e12b16f1f86d0c9d..687939407f8af05cc703dbf0ef1a60cd01302836 100644
1044--- a/pkg/ui/common/common.go
1045+++ b/pkg/ui/common/common.go
1046@@ -5,16 +5,14 @@ import (
1047 "fmt"
1048
1049 "github.com/alecthomas/chroma/v2/lexers"
1050- "github.com/charmbracelet/lipgloss"
1051- "github.com/charmbracelet/log"
1052+ zone "github.com/aymanbagabas/bubblezone/v2"
1053+ "github.com/charmbracelet/log/v2"
1054 "github.com/charmbracelet/soft-serve/git"
1055 "github.com/charmbracelet/soft-serve/pkg/backend"
1056 "github.com/charmbracelet/soft-serve/pkg/config"
1057 "github.com/charmbracelet/soft-serve/pkg/ui/keymap"
1058 "github.com/charmbracelet/soft-serve/pkg/ui/styles"
1059 "github.com/charmbracelet/ssh"
1060- zone "github.com/lrstanley/bubblezone"
1061- "github.com/muesli/termenv"
1062 )
1063
1064 type contextKey struct {
1065@@ -34,27 +32,23 @@ type Common struct {
1066 Styles *styles.Styles
1067 KeyMap *keymap.KeyMap
1068 Zone *zone.Manager
1069- Renderer *lipgloss.Renderer
1070- Output *termenv.Output
1071 Logger *log.Logger
1072 HideCloneCmd bool
1073 }
1074
1075 // NewCommon returns a new Common struct.
1076-func NewCommon(ctx context.Context, out *lipgloss.Renderer, width, height int) Common {
1077+func NewCommon(ctx context.Context, width, height int) Common {
1078 if ctx == nil {
1079 ctx = context.TODO()
1080 }
1081 return Common{
1082- ctx: ctx,
1083- Width: width,
1084- Height: height,
1085- Renderer: out,
1086- Output: out.Output(),
1087- Styles: styles.DefaultStyles(out),
1088- KeyMap: keymap.DefaultKeyMap(),
1089- Zone: zone.New(),
1090- Logger: log.FromContext(ctx).WithPrefix("ui"),
1091+ ctx: ctx,
1092+ Width: width,
1093+ Height: height,
1094+ Styles: styles.DefaultStyles(),
1095+ KeyMap: keymap.DefaultKeyMap(),
1096+ Zone: zone.New(),
1097+ Logger: log.FromContext(ctx).WithPrefix("ui"),
1098 }
1099 }
1100
1101diff --git a/pkg/ui/common/component.go b/pkg/ui/common/component.go
1102index 6fe7761f9b9c85cabae967b5246d361cb811d363..4b152a4ba81080af791446601d06133847d80102 100644
1103--- a/pkg/ui/common/component.go
1104+++ b/pkg/ui/common/component.go
1105@@ -1,13 +1,14 @@
1106 package common
1107
1108 import (
1109- "github.com/charmbracelet/bubbles/help"
1110- tea "github.com/charmbracelet/bubbletea"
1111+ "github.com/charmbracelet/bubbles/v2/help"
1112+ tea "github.com/charmbracelet/bubbletea/v2"
1113 )
1114
1115 // Component represents a Bubble Tea model that implements a SetSize function.
1116 type Component interface {
1117 tea.Model
1118+ tea.ViewModel
1119 help.KeyMap
1120 SetSize(width, height int)
1121 }
1122diff --git a/pkg/ui/common/error.go b/pkg/ui/common/error.go
1123index 753f5f26f77fc778157c2dc5d3c7b06440a29b8e..926df1d9ac7610b2a34648290e62c28a7d9d9629 100644
1124--- a/pkg/ui/common/error.go
1125+++ b/pkg/ui/common/error.go
1126@@ -3,7 +3,7 @@ package common
1127 import (
1128 "errors"
1129
1130- tea "github.com/charmbracelet/bubbletea"
1131+ tea "github.com/charmbracelet/bubbletea/v2"
1132 )
1133
1134 // ErrMissingRepo indicates that the requested repository could not be found.
1135diff --git a/pkg/ui/common/format.go b/pkg/ui/common/format.go
1136index 4344e057d8cfba2478b977a34f01a1d28c1cc6d2..f82c71aec65d6366f3f4d6da770979c94a4d18e4 100644
1137--- a/pkg/ui/common/format.go
1138+++ b/pkg/ui/common/format.go
1139@@ -6,7 +6,7 @@ import (
1140 "strings"
1141
1142 "github.com/alecthomas/chroma/v2/lexers"
1143- gansi "github.com/charmbracelet/glamour/ansi"
1144+ gansi "github.com/charmbracelet/glamour/v2/ansi"
1145 "github.com/charmbracelet/soft-serve/pkg/ui/styles"
1146 )
1147
1148diff --git a/pkg/ui/common/style.go b/pkg/ui/common/style.go
1149index 06d7ce3d2c9e4b61f2dd827051dd351f4bdca861..1f2032f8b5e0ffbb12c067427c397e34dc55944b 100644
1150--- a/pkg/ui/common/style.go
1151+++ b/pkg/ui/common/style.go
1152@@ -1,13 +1,13 @@
1153 package common
1154
1155 import (
1156- gansi "github.com/charmbracelet/glamour/ansi"
1157- "github.com/charmbracelet/glamour/styles"
1158- "github.com/muesli/termenv"
1159+ "github.com/charmbracelet/colorprofile"
1160+ gansi "github.com/charmbracelet/glamour/v2/ansi"
1161+ "github.com/charmbracelet/glamour/v2/styles"
1162 )
1163
1164 // DefaultColorProfile is the default color profile used by the SSH server.
1165-var DefaultColorProfile = termenv.ANSI256
1166+var DefaultColorProfile = colorprofile.ANSI256
1167
1168 func strptr(s string) *string {
1169 return &s
1170@@ -17,29 +17,20 @@ func strptr(s string) *string {
1171 func StyleConfig() gansi.StyleConfig {
1172 noColor := strptr("")
1173 s := styles.DarkStyleConfig
1174- s.H1.BackgroundColor = noColor
1175- s.H1.Prefix = "# "
1176- s.H1.Suffix = ""
1177- s.H1.Color = strptr("39")
1178- s.Document.StylePrimitive.Color = noColor
1179- s.CodeBlock.Chroma.Text.Color = noColor
1180- s.CodeBlock.Chroma.Name.Color = noColor
1181 // This fixes an issue with the default style config. For example
1182 // highlighting empty spaces with red in Dockerfile type.
1183 s.CodeBlock.Chroma.Error.BackgroundColor = noColor
1184 return s
1185 }
1186
1187-// StyleRenderer returns a new Glamour renderer with the DefaultColorProfile.
1188+// StyleRenderer returns a new Glamour renderer.
1189 func StyleRenderer() gansi.RenderContext {
1190 return StyleRendererWithStyles(StyleConfig())
1191 }
1192
1193-// StyleRendererWithStyles returns a new Glamour renderer with the
1194-// DefaultColorProfile and styles.
1195+// StyleRendererWithStyles returns a new Glamour renderer.
1196 func StyleRendererWithStyles(styles gansi.StyleConfig) gansi.RenderContext {
1197 return gansi.NewRenderContext(gansi.Options{
1198- ColorProfile: DefaultColorProfile,
1199- Styles: styles,
1200+ Styles: styles,
1201 })
1202 }
1203diff --git a/pkg/ui/components/code/code.go b/pkg/ui/components/code/code.go
1204index af7697260fc7d327f1791ded0ab84f69f8c86c72..6da77c65fe8040f9bf21c266eafbcf78328613c5 100644
1205--- a/pkg/ui/components/code/code.go
1206+++ b/pkg/ui/components/code/code.go
1207@@ -6,13 +6,12 @@ import (
1208 "sync"
1209
1210 "github.com/alecthomas/chroma/v2/lexers"
1211- tea "github.com/charmbracelet/bubbletea"
1212- "github.com/charmbracelet/glamour"
1213- gansi "github.com/charmbracelet/glamour/ansi"
1214- "github.com/charmbracelet/lipgloss"
1215+ tea "github.com/charmbracelet/bubbletea/v2"
1216+ "github.com/charmbracelet/glamour/v2"
1217+ gansi "github.com/charmbracelet/glamour/v2/ansi"
1218+ "github.com/charmbracelet/lipgloss/v2"
1219 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1220 vp "github.com/charmbracelet/soft-serve/pkg/ui/components/viewport"
1221- "github.com/muesli/termenv"
1222 )
1223
1224 const (
1225@@ -77,7 +76,11 @@ func (r *Code) SetSideNote(s string) tea.Cmd {
1226
1227 // Init implements tea.Model.
1228 func (r *Code) Init() tea.Cmd {
1229- w := r.common.Width
1230+ // XXX: We probably won't need the GetHorizontalFrameSize margin
1231+ // subtraction if we get the new viewport soft wrapping to play nicely with
1232+ // Glamour. This also introduces a bug where when it soft wraps, the
1233+ // viewport scrolls left/right for 2 columns on each side of the screen.
1234+ w := r.common.Width - r.common.Styles.App.GetHorizontalFrameSize()
1235 content := r.content
1236 if content == "" {
1237 r.Viewport.Model.SetContent(r.NoContentStyle.String())
1238@@ -110,7 +113,7 @@ func (r *Code) Init() tea.Cmd {
1239
1240 if r.sidenote != "" {
1241 lines := strings.Split(r.sidenote, "\n")
1242- sideNoteWidth := int(math.Ceil(float64(r.Model.Width) * r.SideNotePercent))
1243+ sideNoteWidth := int(math.Ceil(float64(r.Model.Width()) * r.SideNotePercent))
1244 for i, l := range lines {
1245 lines[i] = common.TruncateString(l, sideNoteWidth)
1246 }
1247@@ -121,7 +124,7 @@ func (r *Code) Init() tea.Cmd {
1248 // https://github.com/muesli/reflow/issues/43
1249 //
1250 // TODO: solve this upstream in Glamour/Reflow.
1251- content = r.common.Renderer.NewStyle().Width(w).Render(content)
1252+ content = lipgloss.NewStyle().Width(w).Render(content)
1253
1254 r.Viewport.Model.SetContent(content)
1255
1256@@ -169,26 +172,6 @@ func (r *Code) HalfViewUp() {
1257 r.Viewport.HalfViewUp()
1258 }
1259
1260-// ViewUp moves the viewport up by a page.
1261-func (r *Code) ViewUp() []string {
1262- return r.Viewport.ViewUp()
1263-}
1264-
1265-// ViewDown moves the viewport down by a page.
1266-func (r *Code) ViewDown() []string {
1267- return r.Viewport.ViewDown()
1268-}
1269-
1270-// LineUp moves the viewport up by the given number of lines.
1271-func (r *Code) LineUp(n int) []string {
1272- return r.Viewport.LineUp(n)
1273-}
1274-
1275-// LineDown moves the viewport down by the given number of lines.
1276-func (r *Code) LineDown(n int) []string {
1277- return r.Viewport.LineDown(n)
1278-}
1279-
1280 // ScrollPercent returns the viewport's scroll percentage.
1281 func (r *Code) ScrollPercent() float64 {
1282 return r.Viewport.ScrollPercent()
1283@@ -244,8 +227,7 @@ func (r *Code) renderFile(path, content string) (string, error) {
1284 var m uint
1285 st.CodeBlock.Margin = &m
1286 rc = gansi.NewRenderContext(gansi.Options{
1287- ColorProfile: termenv.TrueColor,
1288- Styles: st,
1289+ Styles: st,
1290 })
1291 }
1292 err := formatter.Render(&s, rc)
1293diff --git a/pkg/ui/components/footer/footer.go b/pkg/ui/components/footer/footer.go
1294index 44c800f420e1913c72f1289a00b7d273269a8247..05e1160dedbe717a213de8907fbbb65dccc5bd4e 100644
1295--- a/pkg/ui/components/footer/footer.go
1296+++ b/pkg/ui/components/footer/footer.go
1297@@ -1,10 +1,10 @@
1298 package footer
1299
1300 import (
1301- "github.com/charmbracelet/bubbles/help"
1302- "github.com/charmbracelet/bubbles/key"
1303- tea "github.com/charmbracelet/bubbletea"
1304- "github.com/charmbracelet/lipgloss"
1305+ "github.com/charmbracelet/bubbles/v2/help"
1306+ "github.com/charmbracelet/bubbles/v2/key"
1307+ tea "github.com/charmbracelet/bubbletea/v2"
1308+ "github.com/charmbracelet/lipgloss/v2"
1309 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1310 )
1311
1312diff --git a/pkg/ui/components/header/header.go b/pkg/ui/components/header/header.go
1313index 7de511426f6da83252b84884c4fa3a64fd992e65..63e47a4911f6618c31448cdbc8c902e80314be11 100644
1314--- a/pkg/ui/components/header/header.go
1315+++ b/pkg/ui/components/header/header.go
1316@@ -3,7 +3,7 @@ package header
1317 import (
1318 "strings"
1319
1320- tea "github.com/charmbracelet/bubbletea"
1321+ tea "github.com/charmbracelet/bubbletea/v2"
1322 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1323 )
1324
1325diff --git a/pkg/ui/components/selector/selector.go b/pkg/ui/components/selector/selector.go
1326index 72239d4083847a2ccd72c7d0e10ea9bfa90e10ba..e42ee3507a674a36561ae9255a7b6ea5f2e25c86 100644
1327--- a/pkg/ui/components/selector/selector.go
1328+++ b/pkg/ui/components/selector/selector.go
1329@@ -3,9 +3,9 @@ package selector
1330 import (
1331 "sync"
1332
1333- "github.com/charmbracelet/bubbles/key"
1334- "github.com/charmbracelet/bubbles/list"
1335- tea "github.com/charmbracelet/bubbletea"
1336+ "github.com/charmbracelet/bubbles/v2/key"
1337+ "github.com/charmbracelet/bubbles/v2/list"
1338+ tea "github.com/charmbracelet/bubbletea/v2"
1339 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1340 )
1341
1342@@ -230,16 +230,14 @@ func (s *Selector) Init() tea.Cmd {
1343 func (s *Selector) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
1344 cmds := make([]tea.Cmd, 0)
1345 switch msg := msg.(type) {
1346- case tea.MouseMsg:
1347- if msg.Action != tea.MouseActionPress {
1348- break
1349- }
1350- switch msg.Button {
1351- case tea.MouseButtonWheelUp:
1352+ case tea.MouseClickMsg:
1353+ m := msg.Mouse()
1354+ switch m.Button {
1355+ case tea.MouseWheelUp:
1356 s.CursorUp()
1357- case tea.MouseButtonWheelDown:
1358+ case tea.MouseWheelDown:
1359 s.CursorDown()
1360- case tea.MouseButtonLeft:
1361+ case tea.MouseLeft:
1362 curIdx := s.Index()
1363 for i, item := range s.Items() {
1364 item, _ := item.(IdentifiableItem)
1365@@ -254,7 +252,7 @@ func (s *Selector) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
1366 }
1367 }
1368 }
1369- case tea.KeyMsg:
1370+ case tea.KeyPressMsg:
1371 filterState := s.FilterState()
1372 switch {
1373 case key.Matches(msg, s.common.KeyMap.Help):
1374diff --git a/pkg/ui/components/statusbar/statusbar.go b/pkg/ui/components/statusbar/statusbar.go
1375index 20a5735e12da1729616ea9ead98ccfcadfda6a47..f913e644a2230ea4a3d6f1b46f9e7850de45a02e 100644
1376--- a/pkg/ui/components/statusbar/statusbar.go
1377+++ b/pkg/ui/components/statusbar/statusbar.go
1378@@ -1,10 +1,10 @@
1379 package statusbar
1380
1381 import (
1382- tea "github.com/charmbracelet/bubbletea"
1383- "github.com/charmbracelet/lipgloss"
1384+ tea "github.com/charmbracelet/bubbletea/v2"
1385+ "github.com/charmbracelet/lipgloss/v2"
1386 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1387- "github.com/muesli/reflow/truncate"
1388+ "github.com/charmbracelet/x/ansi"
1389 )
1390
1391 // Model is a status bar model.
1392@@ -75,12 +75,12 @@ func (s *Model) View() string {
1393 }
1394 branch := st.StatusBarBranch.Render(s.extra)
1395 maxWidth := s.common.Width - w(key) - w(info) - w(branch) - w(help)
1396- v := truncate.StringWithTail(s.value, uint(maxWidth-st.StatusBarValue.GetHorizontalFrameSize()), "…") //nolint:gosec
1397+ v := ansi.Truncate(s.value, maxWidth-st.StatusBarValue.GetHorizontalFrameSize(), "…")
1398 value := st.StatusBarValue.
1399 Width(maxWidth).
1400 Render(v)
1401
1402- return s.common.Renderer.NewStyle().MaxWidth(s.common.Width).
1403+ return lipgloss.NewStyle().MaxWidth(s.common.Width).
1404 Render(
1405 lipgloss.JoinHorizontal(lipgloss.Top,
1406 key,
1407diff --git a/pkg/ui/components/tabs/tabs.go b/pkg/ui/components/tabs/tabs.go
1408index bd31566216326910b991f732813daef756e733f2..36f0a19e85c2bda3dc172e02d8b5bb5b70919ad4 100644
1409--- a/pkg/ui/components/tabs/tabs.go
1410+++ b/pkg/ui/components/tabs/tabs.go
1411@@ -3,8 +3,8 @@ package tabs
1412 import (
1413 "strings"
1414
1415- tea "github.com/charmbracelet/bubbletea"
1416- "github.com/charmbracelet/lipgloss"
1417+ tea "github.com/charmbracelet/bubbletea/v2"
1418+ "github.com/charmbracelet/lipgloss/v2"
1419 "github.com/charmbracelet/soft-serve/pkg/ui/common"
1420 )
1421
1422@@ -54,7 +54,7 @@ func (t *Tabs) Init() tea.Cmd {
1423 func (t *Tabs) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
1424 cmds := make([]tea.Cmd, 0)
1425 switch msg := msg.(type) {
1426- case tea.KeyMsg:
1427+ case tea.KeyPressMsg:
1428 switch msg.String() {
1429 case "tab":
1430 t.activeTab = (t.activeTab + 1) % len(t.tabs)
1431@@ -63,12 +63,9 @@ func (t *Tabs) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
1432 t.activeTab = (t.activeTab - 1 + len(t.tabs)) % len(t.tabs)
1433 cmds = append(cmds, t.activeTabCmd)
1434 }
1435- case tea.MouseMsg:
1436- if msg.Action != tea.MouseActionPress {
1437- break
1438- }
1439+ case tea.MouseClickMsg:
1440 switch msg.Button {
1441- case tea.MouseButtonLeft:
1442+ case tea.MouseLeft:
1443 for i, tab := range t.tabs {
1444 if t.common.Zone.Get(tab).InBounds(msg) {
1445 t.activeTab = i
1446@@ -109,7 +106,7 @@ func (t *Tabs) View() string {
1447 s.WriteString(sep.String())
1448 }
1449 }
1450- return t.common.Renderer.NewStyle().
1451+ return lipgloss.NewStyle().
1452 MaxWidth(t.common.Width).
1453 Render(s.String())
1454 }