fix: use lipgloss renderers

Ayman Bagabas created

Fixes: https://github.com/charmbracelet/soft-serve/pull/468

Change summary

pkg/jobs/mirror.go                       |  31 +++-
pkg/ssh/cmd/blob.go                      |   5 
pkg/ssh/cmd/commit.go                    |   5 
pkg/ssh/cmd/repo.go                      |   7 
pkg/ssh/middleware.go                    |  11 +
pkg/ssh/session.go                       |  11 +
pkg/ui/common/common.go                  |  18 +-
pkg/ui/components/code/code.go           |   2 
pkg/ui/components/statusbar/statusbar.go |   2 
pkg/ui/components/tabs/tabs.go           |   2 
pkg/ui/pages/repo/filesitem.go           |   9 +
pkg/ui/pages/repo/repo.go                |   2 
pkg/ui/pages/selection/selection.go      |   8 
pkg/ui/styles/styles.go                  | 160 +++++++++++++-------------
14 files changed, 155 insertions(+), 118 deletions(-)

Detailed changes

pkg/jobs/mirror.go 🔗

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"path/filepath"
 	"runtime"
+	"strings"
 
 	"github.com/charmbracelet/log"
 	"github.com/charmbracelet/soft-serve/git"
@@ -62,16 +63,26 @@ func (m mirrorPull) Func(ctx context.Context) func() {
 				name := repo.Name()
 				wq.Add(name, func() {
 					repo := repo
-					cmd := git.NewCommand("remote", "update", "--prune").WithContext(ctx)
-					cmd.AddEnvs(
-						fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
-							filepath.Join(cfg.DataPath, "ssh", "known_hosts"),
-							cfg.SSH.ClientKeyPath,
-						),
-					)
-
-					if _, err := cmd.RunInDir(r.Path); err != nil {
-						logger.Error("error running git remote update", "repo", name, "err", err)
+
+					cmds := []string{
+						"fetch --prune",               // fetch prune before updating remote
+						"gc --aggressive --prune=now", // aggressive garbage collection
+						"remote update --prune",       // update remote and prune remote refs
+					}
+
+					for _, c := range cmds {
+						args := strings.Split(c, " ")
+						cmd := git.NewCommand(args...).WithContext(ctx)
+						cmd.AddEnvs(
+							fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
+								filepath.Join(cfg.DataPath, "ssh", "known_hosts"),
+								cfg.SSH.ClientKeyPath,
+							),
+						)
+
+						if _, err := cmd.RunInDir(r.Path); err != nil {
+							logger.Error("error running git remote update", "repo", name, "err", err)
+						}
 					}
 
 					if cfg.LFS.Enabled {

pkg/ssh/cmd/blob.go 🔗

@@ -3,6 +3,7 @@ package cmd
 import (
 	"fmt"
 
+	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
 	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/charmbracelet/soft-serve/pkg/ui/common"
@@ -11,12 +12,12 @@ import (
 )
 
 // blobCommand returns a command that prints the contents of a file.
-func blobCommand() *cobra.Command {
+func blobCommand(renderer *lipgloss.Renderer) *cobra.Command {
 	var linenumber bool
 	var color bool
 	var raw bool
 
-	styles := styles.DefaultStyles()
+	styles := styles.DefaultStyles(renderer)
 	cmd := &cobra.Command{
 		Use:               "blob REPOSITORY [REFERENCE] [PATH]",
 		Aliases:           []string{"cat", "show"},

pkg/ssh/cmd/commit.go 🔗

@@ -6,6 +6,7 @@ import (
 	"time"
 
 	gansi "github.com/charmbracelet/glamour/ansi"
+	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
 	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/charmbracelet/soft-serve/pkg/ui/common"
@@ -14,7 +15,7 @@ import (
 )
 
 // commitCommand returns a command that prints the contents of a commit.
-func commitCommand() *cobra.Command {
+func commitCommand(renderer *lipgloss.Renderer) *cobra.Command {
 	var color bool
 	var patchOnly bool
 
@@ -54,7 +55,7 @@ func commitCommand() *cobra.Command {
 				return err
 			}
 
-			commonStyle := styles.DefaultStyles()
+			commonStyle := styles.DefaultStyles(renderer)
 			style := commonStyle.Log
 
 			s := strings.Builder{}

pkg/ssh/cmd/repo.go 🔗

@@ -4,13 +4,14 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/spf13/cobra"
 )
 
 // RepoCommand returns a command for managing repositories.
-func RepoCommand() *cobra.Command {
+func RepoCommand(renderer *lipgloss.Renderer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "repo",
 		Aliases: []string{"repos", "repository", "repositories"},
@@ -18,10 +19,10 @@ func RepoCommand() *cobra.Command {
 	}
 
 	cmd.AddCommand(
-		blobCommand(),
+		blobCommand(renderer),
 		branchCommand(),
 		collabCommand(),
-		commitCommand(),
+		commitCommand(renderer),
 		createCommand(),
 		deleteCommand(),
 		descriptionCommand(),

pkg/ssh/middleware.go 🔗

@@ -2,6 +2,7 @@ package ssh
 
 import (
 	"fmt"
+	"os"
 	"time"
 
 	"github.com/charmbracelet/log"
@@ -14,6 +15,8 @@ import (
 	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
+	bm "github.com/charmbracelet/wish/bubbletea"
+	"github.com/muesli/termenv"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"
 	"github.com/spf13/cobra"
@@ -87,6 +90,12 @@ func CommandMiddleware(sh ssh.Handler) ssh.Handler {
 		ctx := s.Context()
 		cfg := config.FromContext(ctx)
 
+		renderer := bm.MakeRenderer(s)
+		if testrun, ok := os.LookupEnv("SOFT_SERVE_NO_COLOR"); ok && testrun == "1" {
+			// Disable colors when running tests.
+			renderer.SetColorProfile(termenv.Ascii)
+		}
+
 		args := s.Command()
 		cliCommandCounter.WithLabelValues(cmd.CommandName(args)).Inc()
 		rootCmd := &cobra.Command{
@@ -101,7 +110,7 @@ func CommandMiddleware(sh ssh.Handler) ssh.Handler {
 			cmd.GitUploadPackCommand(),
 			cmd.GitUploadArchiveCommand(),
 			cmd.GitReceivePackCommand(),
-			cmd.RepoCommand(),
+			cmd.RepoCommand(renderer),
 			cmd.SettingsCommand(),
 			cmd.UserCommand(),
 			cmd.InfoCommand(),

pkg/ssh/session.go 🔗

@@ -1,6 +1,7 @@
 package ssh
 
 import (
+	"os"
 	"time"
 
 	tea "github.com/charmbracelet/bubbletea"
@@ -12,6 +13,7 @@ import (
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
 	bm "github.com/charmbracelet/wish/bubbletea"
+	"github.com/muesli/termenv"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"
 )
@@ -52,8 +54,13 @@ func SessionHandler(s ssh.Session) *tea.Program {
 		}
 	}
 
-	output := bm.MakeRenderer(s)
-	c := common.NewCommon(ctx, output, pty.Window.Width, pty.Window.Height)
+	renderer := bm.MakeRenderer(s)
+	if testrun, ok := os.LookupEnv("SOFT_SERVE_NO_COLOR"); ok && testrun == "1" {
+		// Disable colors when running tests.
+		renderer.SetColorProfile(termenv.Ascii)
+	}
+
+	c := common.NewCommon(ctx, renderer, pty.Window.Width, pty.Window.Height)
 	c.SetValue(common.ConfigKey, cfg)
 	m := NewUI(c, initialRepo)
 	opts := bm.MakeOptions(s)

pkg/ui/common/common.go 🔗

@@ -34,6 +34,7 @@ type Common struct {
 	Styles        *styles.Styles
 	KeyMap        *keymap.KeyMap
 	Zone          *zone.Manager
+	Renderer      *lipgloss.Renderer
 	Output        *termenv.Output
 	Logger        *log.Logger
 	HideCloneCmd  bool
@@ -45,14 +46,15 @@ func NewCommon(ctx context.Context, out *lipgloss.Renderer, width, height int) C
 		ctx = context.TODO()
 	}
 	return Common{
-		ctx:    ctx,
-		Width:  width,
-		Height: height,
-		Output: out.Output(),
-		Styles: styles.DefaultStyles(),
-		KeyMap: keymap.DefaultKeyMap(),
-		Zone:   zone.New(),
-		Logger: log.FromContext(ctx).WithPrefix("ui"),
+		ctx:      ctx,
+		Width:    width,
+		Height:   height,
+		Renderer: out,
+		Output:   out.Output(),
+		Styles:   styles.DefaultStyles(out),
+		KeyMap:   keymap.DefaultKeyMap(),
+		Zone:     zone.New(),
+		Logger:   log.FromContext(ctx).WithPrefix("ui"),
 	}
 }
 

pkg/ui/components/code/code.go 🔗

@@ -121,7 +121,7 @@ func (r *Code) Init() tea.Cmd {
 	// https://github.com/muesli/reflow/issues/43
 	//
 	// TODO: solve this upstream in Glamour/Reflow.
-	content = lipgloss.NewStyle().Width(w).Render(content)
+	content = r.common.Renderer.NewStyle().Width(w).Render(content)
 
 	r.Viewport.Model.SetContent(content)
 

pkg/ui/components/statusbar/statusbar.go 🔗

@@ -80,7 +80,7 @@ func (s *Model) View() string {
 		Width(maxWidth).
 		Render(v)
 
-	return lipgloss.NewStyle().MaxWidth(s.common.Width).
+	return s.common.Renderer.NewStyle().MaxWidth(s.common.Width).
 		Render(
 			lipgloss.JoinHorizontal(lipgloss.Top,
 				key,

pkg/ui/components/tabs/tabs.go 🔗

@@ -105,7 +105,7 @@ func (t *Tabs) View() string {
 			s.WriteString(sep.String())
 		}
 	}
-	return lipgloss.NewStyle().
+	return t.common.Renderer.NewStyle().
 		MaxWidth(t.common.Width).
 		Render(s.String())
 }

pkg/ui/pages/repo/filesitem.go 🔗

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
+	"strconv"
 	"strings"
 
 	"github.com/charmbracelet/bubbles/key"
@@ -22,7 +23,11 @@ type FileItem struct {
 
 // ID returns the ID of the file item.
 func (i FileItem) ID() string {
-	return i.entry.Name()
+	name := i.entry.Name()
+	if n, err := strconv.Unquote(name); err == nil {
+		name = n
+	}
+	return name
 }
 
 // Title returns the title of the file item.
@@ -139,7 +144,7 @@ func (d FileItemDelegate) Render(w io.Writer, m list.Model, index int, listItem
 	name = nameStyle.Render(name)
 	size = sizeStyle.Render(size)
 	modeStr := modeStyle.Render(mode.String())
-	truncate := lipgloss.NewStyle().MaxWidth(m.Width() -
+	truncate := d.common.Renderer.NewStyle().MaxWidth(m.Width() -
 		s.Selector.GetHorizontalFrameSize() -
 		s.Selector.GetWidth())
 	fmt.Fprint(w,

pkg/ui/pages/repo/repo.go 🔗

@@ -323,7 +323,7 @@ func (r *Repo) headerView() string {
 	if r.selectedRepo == nil {
 		return ""
 	}
-	truncate := lipgloss.NewStyle().MaxWidth(r.common.Width)
+	truncate := r.common.Renderer.NewStyle().MaxWidth(r.common.Width)
 	header := r.selectedRepo.ProjectName()
 	if header == "" {
 		header = r.selectedRepo.Name()

pkg/ui/pages/selection/selection.go 🔗

@@ -51,7 +51,7 @@ func New(c common.Common) *Selection {
 		ts[i] = b.String()
 	}
 	t := tabs.New(c, ts)
-	t.TabSeparator = lipgloss.NewStyle()
+	t.TabSeparator = c.Renderer.NewStyle()
 	t.TabInactive = c.Styles.TopLevelNormalTab.Copy()
 	t.TabActive = c.Styles.TopLevelActiveTab.Copy()
 	t.TabDot = c.Styles.TopLevelActiveTabDot.Copy()
@@ -289,15 +289,15 @@ func (s *Selection) View() string {
 	wm, hm := s.getMargins()
 	switch s.activePane {
 	case selectorPane:
-		ss := lipgloss.NewStyle().
+		ss := s.common.Renderer.NewStyle().
 			Width(s.common.Width - wm).
 			Height(s.common.Height - hm)
 		view = ss.Render(s.selector.View())
 	case readmePane:
-		rs := lipgloss.NewStyle().
+		rs := s.common.Renderer.NewStyle().
 			Height(s.common.Height - hm)
 		status := fmt.Sprintf("☰ %.f%%", s.readme.ScrollPercent()*100)
-		readmeStatus := lipgloss.NewStyle().
+		readmeStatus := s.common.Renderer.NewStyle().
 			Align(lipgloss.Right).
 			Width(s.common.Width - wm).
 			Foreground(s.common.Styles.InactiveBorderColor).

pkg/ui/styles/styles.go 🔗

@@ -165,7 +165,7 @@ type Styles struct {
 }
 
 // DefaultStyles returns default styles for the UI.
-func DefaultStyles() *Styles {
+func DefaultStyles(r *lipgloss.Renderer) *Styles {
 	highlightColor := lipgloss.Color("210")
 	highlightColorDim := lipgloss.Color("174")
 	selectorColor := lipgloss.Color("167")
@@ -176,10 +176,10 @@ func DefaultStyles() *Styles {
 	s.ActiveBorderColor = lipgloss.Color("62")
 	s.InactiveBorderColor = lipgloss.Color("241")
 
-	s.App = lipgloss.NewStyle().
+	s.App = r.NewStyle().
 		Margin(1, 2)
 
-	s.ServerName = lipgloss.NewStyle().
+	s.ServerName = r.NewStyle().
 		Height(1).
 		MarginLeft(1).
 		MarginBottom(1).
@@ -188,29 +188,29 @@ func DefaultStyles() *Styles {
 		Foreground(lipgloss.Color("229")).
 		Bold(true)
 
-	s.TopLevelNormalTab = lipgloss.NewStyle().
+	s.TopLevelNormalTab = r.NewStyle().
 		MarginRight(2)
 
 	s.TopLevelActiveTab = s.TopLevelNormalTab.Copy().
 		Foreground(lipgloss.Color("36"))
 
-	s.TopLevelActiveTabDot = lipgloss.NewStyle().
+	s.TopLevelActiveTabDot = r.NewStyle().
 		Foreground(lipgloss.Color("36"))
 
-	s.RepoSelector.Normal.Base = lipgloss.NewStyle().
+	s.RepoSelector.Normal.Base = r.NewStyle().
 		PaddingLeft(1).
 		Border(lipgloss.Border{Left: " "}, false, false, false, true).
 		Height(3)
 
-	s.RepoSelector.Normal.Title = lipgloss.NewStyle().Bold(true)
+	s.RepoSelector.Normal.Title = r.NewStyle().Bold(true)
 
-	s.RepoSelector.Normal.Desc = lipgloss.NewStyle().
+	s.RepoSelector.Normal.Desc = r.NewStyle().
 		Foreground(lipgloss.Color("243"))
 
-	s.RepoSelector.Normal.Command = lipgloss.NewStyle().
+	s.RepoSelector.Normal.Command = r.NewStyle().
 		Foreground(lipgloss.Color("132"))
 
-	s.RepoSelector.Normal.Updated = lipgloss.NewStyle().
+	s.RepoSelector.Normal.Updated = r.NewStyle().
 		Foreground(lipgloss.Color("243"))
 
 	s.RepoSelector.Active.Base = s.RepoSelector.Normal.Base.Copy().
@@ -229,78 +229,78 @@ func DefaultStyles() *Styles {
 	s.RepoSelector.Active.Command = s.RepoSelector.Normal.Command.Copy().
 		Foreground(lipgloss.Color("204"))
 
-	s.MenuItem = lipgloss.NewStyle().
+	s.MenuItem = r.NewStyle().
 		PaddingLeft(1).
 		Border(lipgloss.Border{
 			Left: " ",
 		}, false, false, false, true).
 		Height(3)
 
-	s.MenuLastUpdate = lipgloss.NewStyle().
+	s.MenuLastUpdate = r.NewStyle().
 		Foreground(lipgloss.Color("241")).
 		Align(lipgloss.Right)
 
-	s.Repo.Base = lipgloss.NewStyle()
+	s.Repo.Base = r.NewStyle()
 
-	s.Repo.Title = lipgloss.NewStyle().
+	s.Repo.Title = r.NewStyle().
 		Padding(0, 2)
 
-	s.Repo.Command = lipgloss.NewStyle().
+	s.Repo.Command = r.NewStyle().
 		Foreground(lipgloss.Color("168"))
 
-	s.Repo.Body = lipgloss.NewStyle().
+	s.Repo.Body = r.NewStyle().
 		Margin(1, 0)
 
-	s.Repo.Header = lipgloss.NewStyle().
+	s.Repo.Header = r.NewStyle().
 		MaxHeight(2).
 		Border(lipgloss.NormalBorder(), false, false, true, false).
 		BorderForeground(lipgloss.Color("236"))
 
-	s.Repo.HeaderName = lipgloss.NewStyle().
+	s.Repo.HeaderName = r.NewStyle().
 		Foreground(lipgloss.Color("212")).
 		Bold(true)
 
-	s.Repo.HeaderDesc = lipgloss.NewStyle().
+	s.Repo.HeaderDesc = r.NewStyle().
 		Foreground(lipgloss.Color("243"))
 
-	s.Footer = lipgloss.NewStyle().
+	s.Footer = r.NewStyle().
 		MarginTop(1).
 		Padding(0, 1).
 		Height(1)
 
-	s.Branch = lipgloss.NewStyle().
+	s.Branch = r.NewStyle().
 		Foreground(lipgloss.Color("203")).
 		Background(lipgloss.Color("236")).
 		Padding(0, 1)
 
-	s.HelpKey = lipgloss.NewStyle().
+	s.HelpKey = r.NewStyle().
 		Foreground(lipgloss.Color("241"))
 
-	s.HelpValue = lipgloss.NewStyle().
+	s.HelpValue = r.NewStyle().
 		Foreground(lipgloss.Color("239"))
 
-	s.HelpDivider = lipgloss.NewStyle().
+	s.HelpDivider = r.NewStyle().
 		Foreground(lipgloss.Color("237")).
 		SetString(" • ")
 
-	s.URLStyle = lipgloss.NewStyle().
+	s.URLStyle = r.NewStyle().
 		MarginLeft(1).
 		Foreground(lipgloss.Color("168"))
 
-	s.Error = lipgloss.NewStyle().
+	s.Error = r.NewStyle().
 		MarginTop(2)
 
-	s.ErrorTitle = lipgloss.NewStyle().
+	s.ErrorTitle = r.NewStyle().
 		Foreground(lipgloss.Color("230")).
 		Background(lipgloss.Color("204")).
 		Bold(true).
 		Padding(0, 1)
 
-	s.ErrorBody = lipgloss.NewStyle().
+	s.ErrorBody = r.NewStyle().
 		Foreground(lipgloss.Color("252")).
 		MarginLeft(2)
 
-	s.LogItem.Normal.Base = lipgloss.NewStyle().
+	s.LogItem.Normal.Base = r.NewStyle().
 		Border(lipgloss.Border{
 			Left: " ",
 		}, false, false, false, true).
@@ -315,113 +315,113 @@ func DefaultStyles() *Styles {
 	s.LogItem.Active.Hash = s.LogItem.Normal.Hash.Copy().
 		Foreground(hashColor)
 
-	s.LogItem.Active.Hash = lipgloss.NewStyle().
+	s.LogItem.Active.Hash = r.NewStyle().
 		Bold(true).
 		Foreground(highlightColor)
 
-	s.LogItem.Normal.Title = lipgloss.NewStyle().
+	s.LogItem.Normal.Title = r.NewStyle().
 		Foreground(lipgloss.Color("105"))
 
-	s.LogItem.Active.Title = lipgloss.NewStyle().
+	s.LogItem.Active.Title = r.NewStyle().
 		Foreground(highlightColor).
 		Bold(true)
 
-	s.LogItem.Normal.Desc = lipgloss.NewStyle().
+	s.LogItem.Normal.Desc = r.NewStyle().
 		Foreground(lipgloss.Color("246"))
 
-	s.LogItem.Active.Desc = lipgloss.NewStyle().
+	s.LogItem.Active.Desc = r.NewStyle().
 		Foreground(lipgloss.Color("95"))
 
 	s.LogItem.Active.Keyword = s.LogItem.Active.Desc.Copy().
 		Foreground(highlightColorDim)
 
-	s.LogItem.Normal.Hash = lipgloss.NewStyle().
+	s.LogItem.Normal.Hash = r.NewStyle().
 		Foreground(hashColor)
 
-	s.LogItem.Active.Hash = lipgloss.NewStyle().
+	s.LogItem.Active.Hash = r.NewStyle().
 		Foreground(highlightColor)
 
-	s.Log.Commit = lipgloss.NewStyle().
+	s.Log.Commit = r.NewStyle().
 		Margin(0, 2)
 
-	s.Log.CommitHash = lipgloss.NewStyle().
+	s.Log.CommitHash = r.NewStyle().
 		Foreground(hashColor).
 		Bold(true)
 
-	s.Log.CommitBody = lipgloss.NewStyle().
+	s.Log.CommitBody = r.NewStyle().
 		MarginTop(1).
 		MarginLeft(2)
 
-	s.Log.CommitStatsAdd = lipgloss.NewStyle().
+	s.Log.CommitStatsAdd = r.NewStyle().
 		Foreground(lipgloss.Color("42")).
 		Bold(true)
 
-	s.Log.CommitStatsDel = lipgloss.NewStyle().
+	s.Log.CommitStatsDel = r.NewStyle().
 		Foreground(lipgloss.Color("203")).
 		Bold(true)
 
-	s.Log.Paginator = lipgloss.NewStyle().
+	s.Log.Paginator = r.NewStyle().
 		Margin(0).
 		Align(lipgloss.Center)
 
-	s.Ref.Normal.Item = lipgloss.NewStyle()
+	s.Ref.Normal.Item = r.NewStyle()
 
-	s.Ref.ItemSelector = lipgloss.NewStyle().
+	s.Ref.ItemSelector = r.NewStyle().
 		Foreground(selectorColor).
 		SetString("> ")
 
-	s.Ref.Active.Item = lipgloss.NewStyle().
+	s.Ref.Active.Item = r.NewStyle().
 		Foreground(highlightColorDim)
 
-	s.Ref.Normal.Base = lipgloss.NewStyle()
+	s.Ref.Normal.Base = r.NewStyle()
 
-	s.Ref.Active.Base = lipgloss.NewStyle()
+	s.Ref.Active.Base = r.NewStyle()
 
-	s.Ref.Normal.ItemTag = lipgloss.NewStyle().
+	s.Ref.Normal.ItemTag = r.NewStyle().
 		Foreground(lipgloss.Color("39"))
 
-	s.Ref.Active.ItemTag = lipgloss.NewStyle().
+	s.Ref.Active.ItemTag = r.NewStyle().
 		Bold(true).
 		Foreground(highlightColor)
 
-	s.Ref.Active.Item = lipgloss.NewStyle().
+	s.Ref.Active.Item = r.NewStyle().
 		Bold(true).
 		Foreground(highlightColor)
 
-	s.Ref.Normal.ItemDesc = lipgloss.NewStyle().
+	s.Ref.Normal.ItemDesc = r.NewStyle().
 		Faint(true)
 
-	s.Ref.Active.ItemDesc = lipgloss.NewStyle().
+	s.Ref.Active.ItemDesc = r.NewStyle().
 		Foreground(highlightColor).
 		Faint(true)
 
-	s.Ref.Normal.ItemHash = lipgloss.NewStyle().
+	s.Ref.Normal.ItemHash = r.NewStyle().
 		Foreground(hashColor).
 		Bold(true)
 
-	s.Ref.Active.ItemHash = lipgloss.NewStyle().
+	s.Ref.Active.ItemHash = r.NewStyle().
 		Foreground(highlightColor).
 		Bold(true)
 
 	s.Ref.Paginator = s.Log.Paginator.Copy()
 
-	s.Ref.Selector = lipgloss.NewStyle()
+	s.Ref.Selector = r.NewStyle()
 
 	s.Tree.Selector = s.Tree.Normal.FileName.Copy().
 		Width(1).
 		Foreground(selectorColor)
 
-	s.Tree.Normal.FileName = lipgloss.NewStyle().
+	s.Tree.Normal.FileName = r.NewStyle().
 		MarginLeft(1)
 
 	s.Tree.Active.FileName = s.Tree.Normal.FileName.Copy().
 		Bold(true).
 		Foreground(highlightColor)
 
-	s.Tree.Normal.FileDir = lipgloss.NewStyle().
+	s.Tree.Normal.FileDir = r.NewStyle().
 		Foreground(lipgloss.Color("39"))
 
-	s.Tree.Active.FileDir = lipgloss.NewStyle().
+	s.Tree.Active.FileDir = r.NewStyle().
 		Foreground(highlightColor)
 
 	s.Tree.Normal.FileMode = s.Tree.Active.FileName.Copy().
@@ -437,87 +437,87 @@ func DefaultStyles() *Styles {
 	s.Tree.Active.FileSize = s.Tree.Normal.FileName.Copy().
 		Foreground(highlightColorDim)
 
-	s.Tree.FileContent = lipgloss.NewStyle()
+	s.Tree.FileContent = r.NewStyle()
 
 	s.Tree.Paginator = s.Log.Paginator.Copy()
 
-	s.Tree.Blame.Hash = lipgloss.NewStyle().
+	s.Tree.Blame.Hash = r.NewStyle().
 		Foreground(hashColor).
 		Bold(true)
 
-	s.Tree.Blame.Message = lipgloss.NewStyle()
+	s.Tree.Blame.Message = r.NewStyle()
 
-	s.Tree.Blame.Who = lipgloss.NewStyle().
+	s.Tree.Blame.Who = r.NewStyle().
 		Faint(true)
 
-	s.Spinner = lipgloss.NewStyle().
+	s.Spinner = r.NewStyle().
 		MarginTop(1).
 		MarginLeft(2).
 		Foreground(lipgloss.Color("205"))
 
-	s.SpinnerContainer = lipgloss.NewStyle()
+	s.SpinnerContainer = r.NewStyle()
 
-	s.NoContent = lipgloss.NewStyle().
+	s.NoContent = r.NewStyle().
 		MarginTop(1).
 		MarginLeft(2).
 		Foreground(lipgloss.Color("242"))
 
-	s.StatusBar = lipgloss.NewStyle().
+	s.StatusBar = r.NewStyle().
 		Height(1)
 
-	s.StatusBarKey = lipgloss.NewStyle().
+	s.StatusBarKey = r.NewStyle().
 		Bold(true).
 		Padding(0, 1).
 		Background(lipgloss.Color("206")).
 		Foreground(lipgloss.Color("228"))
 
-	s.StatusBarValue = lipgloss.NewStyle().
+	s.StatusBarValue = r.NewStyle().
 		Padding(0, 1).
 		Background(lipgloss.Color("235")).
 		Foreground(lipgloss.Color("243"))
 
-	s.StatusBarInfo = lipgloss.NewStyle().
+	s.StatusBarInfo = r.NewStyle().
 		Padding(0, 1).
 		Background(lipgloss.Color("212")).
 		Foreground(lipgloss.Color("230"))
 
-	s.StatusBarBranch = lipgloss.NewStyle().
+	s.StatusBarBranch = r.NewStyle().
 		Padding(0, 1).
 		Background(lipgloss.Color("62")).
 		Foreground(lipgloss.Color("230"))
 
-	s.StatusBarHelp = lipgloss.NewStyle().
+	s.StatusBarHelp = r.NewStyle().
 		Padding(0, 1).
 		Background(lipgloss.Color("237")).
 		Foreground(lipgloss.Color("243"))
 
-	s.Tabs = lipgloss.NewStyle().
+	s.Tabs = r.NewStyle().
 		Height(1)
 
-	s.TabInactive = lipgloss.NewStyle()
+	s.TabInactive = r.NewStyle()
 
-	s.TabActive = lipgloss.NewStyle().
+	s.TabActive = r.NewStyle().
 		Underline(true).
 		Foreground(lipgloss.Color("36"))
 
-	s.TabSeparator = lipgloss.NewStyle().
+	s.TabSeparator = r.NewStyle().
 		SetString("│").
 		Padding(0, 1).
 		Foreground(lipgloss.Color("238"))
 
-	s.Code.LineDigit = lipgloss.NewStyle().Foreground(lipgloss.Color("239"))
+	s.Code.LineDigit = r.NewStyle().Foreground(lipgloss.Color("239"))
 
-	s.Code.LineBar = lipgloss.NewStyle().Foreground(lipgloss.Color("236"))
+	s.Code.LineBar = r.NewStyle().Foreground(lipgloss.Color("236"))
 
-	s.Stash.Normal.Message = lipgloss.NewStyle().MarginLeft(1)
+	s.Stash.Normal.Message = r.NewStyle().MarginLeft(1)
 
 	s.Stash.Active.Message = s.Stash.Normal.Message.Copy().Foreground(selectorColor)
 
-	s.Stash.Title = lipgloss.NewStyle().
+	s.Stash.Title = r.NewStyle().
 		Foreground(hashColor).
 		Bold(true)
 
-	s.Stash.Selector = lipgloss.NewStyle().
+	s.Stash.Selector = r.NewStyle().
 		Width(1).
 		Foreground(selectorColor)