feat(ui): use termenv to copy text to clipboard

Ayman Bagabas created

Change summary

server/ssh/session.go      | 29 ++++++++++++++++++++++++-----
ui/common/common.go        |  8 ++++----
ui/pages/repo/repo.go      |  2 +-
ui/pages/selection/item.go |  2 +-
4 files changed, 30 insertions(+), 11 deletions(-)

Detailed changes

server/ssh/session.go 🔗

@@ -1,9 +1,8 @@
 package ssh
 
 import (
-	"fmt"
+	"strings"
 
-	"github.com/aymanbagabas/go-osc52"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/soft-serve/server/backend"
 	"github.com/charmbracelet/soft-serve/server/config"
@@ -13,6 +12,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"
 )
@@ -46,9 +46,8 @@ func SessionHandler(cfg *config.Config) bm.ProgramHandler {
 			}
 		}
 
-		envs := s.Environ()
-		envs = append(envs, fmt.Sprintf("TERM=%s", pty.Term))
-		output := osc52.NewOutput(s, envs)
+		envs := &sessionEnv{s}
+		output := termenv.NewOutput(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs))
 		c := common.NewCommon(s.Context(), output, pty.Window.Width, pty.Window.Height)
 		c.SetValue(common.ConfigKey, cfg)
 		m := ui.New(c, initialRepo)
@@ -65,3 +64,23 @@ func SessionHandler(cfg *config.Config) bm.ProgramHandler {
 		return p
 	}
 }
+
+var _ termenv.Environ = &sessionEnv{}
+
+type sessionEnv struct {
+	ssh.Session
+}
+
+func (s *sessionEnv) Environ() []string {
+	pty, _, _ := s.Pty()
+	return append(s.Session.Environ(), "TERM="+pty.Term)
+}
+
+func (s *sessionEnv) Getenv(key string) string {
+	for _, env := range s.Environ() {
+		if strings.HasPrefix(env, key+"=") {
+			return strings.TrimPrefix(env, key+"=")
+		}
+	}
+	return ""
+}

ui/common/common.go 🔗

@@ -3,13 +3,13 @@ package common
 import (
 	"context"
 
-	"github.com/aymanbagabas/go-osc52"
 	"github.com/charmbracelet/soft-serve/git"
 	"github.com/charmbracelet/soft-serve/server/config"
 	"github.com/charmbracelet/soft-serve/ui/keymap"
 	"github.com/charmbracelet/soft-serve/ui/styles"
 	"github.com/charmbracelet/ssh"
 	zone "github.com/lrstanley/bubblezone"
+	"github.com/muesli/termenv"
 )
 
 type contextKey struct {
@@ -28,12 +28,12 @@ type Common struct {
 	Width, Height int
 	Styles        *styles.Styles
 	KeyMap        *keymap.KeyMap
-	Copy          *osc52.Output
 	Zone          *zone.Manager
+	Output        *termenv.Output
 }
 
 // NewCommon returns a new Common struct.
-func NewCommon(ctx context.Context, copy *osc52.Output, width, height int) Common {
+func NewCommon(ctx context.Context, out *termenv.Output, width, height int) Common {
 	if ctx == nil {
 		ctx = context.TODO()
 	}
@@ -41,7 +41,7 @@ func NewCommon(ctx context.Context, copy *osc52.Output, width, height int) Commo
 		ctx:    ctx,
 		Width:  width,
 		Height: height,
-		Copy:   copy,
+		Output: out,
 		Styles: styles.DefaultStyles(),
 		KeyMap: keymap.DefaultKeyMap(),
 		Zone:   zone.New(),

ui/pages/repo/repo.go 🔗

@@ -239,7 +239,7 @@ func (r *Repo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	case CopyMsg:
 		txt := msg.Text
 		if cfg := r.common.Config(); cfg != nil {
-			r.common.Copy.Copy(txt)
+			r.common.Output.Copy(txt)
 		}
 		cmds = append(cmds, func() tea.Msg {
 			return statusbar.StatusBarMsg{

ui/pages/selection/item.go 🔗

@@ -136,7 +136,7 @@ func (d *ItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
 		switch {
 		case key.Matches(msg, d.common.KeyMap.Copy):
 			d.copiedIdx = idx
-			d.common.Copy.Copy(item.Command())
+			d.common.Output.Copy(item.Command())
 			return m.SetItem(idx, item)
 		}
 	}