go.mod 🔗
@@ -22,6 +22,7 @@ require (
)
require (
+ github.com/aymanbagabas/go-osc52 v1.0.0
github.com/charmbracelet/keygen v0.3.0
github.com/gobwas/glob v0.2.3
github.com/gogs/git-module v1.6.0
Ayman Bagabas created
go.mod | 1
go.sum | 2 +
server/session.go | 13 ++++++++---
ui/components/yankable/yankable.go | 33 ++++++++++++++++++++++++++++---
ui/pages/selection/item.go | 14 ++++++------
ui/pages/selection/selection.go | 3 +
ui/session/session.go | 1
7 files changed, 51 insertions(+), 16 deletions(-)
@@ -22,6 +22,7 @@ require (
)
require (
+ github.com/aymanbagabas/go-osc52 v1.0.0
github.com/charmbracelet/keygen v0.3.0
github.com/gobwas/glob v0.2.3
github.com/gogs/git-module v1.6.0
@@ -17,6 +17,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
+github.com/aymanbagabas/go-osc52 v1.0.0 h1:yjRSILSEUSIhuRcyOJ55tbSKtvBLmJDgbPErH8pXcxM=
+github.com/aymanbagabas/go-osc52 v1.0.0/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k=
@@ -16,8 +16,8 @@ import (
type Session struct {
tea.Model
*tea.Program
- ssh.Session
- Cfg *appCfg.Config
+ session ssh.Session
+ Cfg *appCfg.Config
}
func (s *Session) Config() *appCfg.Config {
@@ -29,8 +29,13 @@ func (s *Session) Send(msg tea.Msg) {
}
func (s *Session) PublicKey() ssh.PublicKey {
- return s.Session.PublicKey()
+ return s.session.PublicKey()
}
+
+func (s *Session) Session() ssh.Session {
+ return s.session
+}
+
func SessionHandler(ac *appCfg.Config) bm.ProgramHandler {
return func(s ssh.Session) *tea.Program {
pty, _, active := s.Pty()
@@ -39,7 +44,7 @@ func SessionHandler(ac *appCfg.Config) bm.ProgramHandler {
return nil
}
sess := &Session{
- Session: s,
+ session: s,
Cfg: ac,
}
cmd := s.Command()
@@ -1,8 +1,14 @@
package yankable
import (
+ "fmt"
+ "log"
+ "strings"
+
+ "github.com/aymanbagabas/go-osc52"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
+ "github.com/gliderlabs/ssh"
)
type Yankable struct {
@@ -10,14 +16,29 @@ type Yankable struct {
style lipgloss.Style
text string
clicked bool
+ osc52 *osc52.Output
}
-func New(style, yankStyle lipgloss.Style, text string) *Yankable {
+func New(s ssh.Session, style, yankStyle lipgloss.Style, text string) *Yankable {
+ environ := s.Environ()
+ termExists := false
+ for _, env := range environ {
+ if strings.HasPrefix(env, "TERM=") {
+ termExists = true
+ break
+ }
+ }
+ if !termExists {
+ pty, _, _ := s.Pty()
+ environ = append(environ, fmt.Sprintf("TERM=%s", pty.Term))
+ }
+ log.Print(environ)
return &Yankable{
yankStyle: yankStyle,
style: style,
text: text,
clicked: false,
+ osc52: osc52.NewOutput(s, environ),
}
}
@@ -30,18 +51,17 @@ func (y *Yankable) Init() tea.Cmd {
}
func (y *Yankable) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
- cmds := make([]tea.Cmd, 0)
switch msg := msg.(type) {
case tea.MouseMsg:
switch msg.Type {
case tea.MouseRight:
y.clicked = true
- return y, nil
+ return y, y.copy()
}
default:
y.clicked = false
}
- return y, tea.Batch(cmds...)
+ return y, nil
}
func (y *Yankable) View() string {
@@ -50,3 +70,8 @@ func (y *Yankable) View() string {
}
return y.style.Render(y.text)
}
+
+func (y *Yankable) copy() tea.Cmd {
+ y.osc52.Copy(y.text)
+ return nil
+}
@@ -55,9 +55,9 @@ func (d ItemDelegate) Spacing() int { return 1 }
// Update implements list.ItemDelegate.
func (d ItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
cmds := make([]tea.Cmd, 0)
- if d.activeBox == nil || *d.activeBox != selectorBox {
- return nil
- }
+ // if d.activeBox == nil || *d.activeBox != selectorBox {
+ // return nil
+ // }
for i, item := range m.VisibleItems() {
itm, ok := item.(Item)
if !ok {
@@ -66,14 +66,14 @@ func (d ItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
// FIXME check if X & Y are within the item box
switch msg := msg.(type) {
case tea.MouseMsg:
- x := msg.X
+ // x := msg.X
y := msg.Y
- minX := (i * d.Width())
- maxX := minX + d.Width()
+ // minX := (i * d.Width())
+ // maxX := minX + d.Width()
minY := (i * d.Height())
maxY := minY + d.Height()
// log.Printf("i: %d, x: %d, y: %d", i, x, y)
- if y < minY || y > maxY || x < minX || x > maxX {
+ if y < minY || y > maxY {
continue
}
}
@@ -106,9 +106,10 @@ func (s *Selection) FullHelp() [][]key.Binding {
func (s *Selection) Init() tea.Cmd {
items := make([]list.Item, 0)
cfg := s.s.Config()
- // TODO fix yankable component
+ // TODO clean up this
yank := func(text string) *yankable.Yankable {
return yankable.New(
+ s.s.Session(),
lipgloss.NewStyle().Foreground(lipgloss.Color("168")),
lipgloss.NewStyle().Foreground(lipgloss.Color("168")).SetString("Copied!"),
text,
@@ -14,4 +14,5 @@ type Session interface {
Config() *appCfg.Config
// PublicKey returns the public key of the user.
PublicKey() ssh.PublicKey
+ Session() ssh.Session
}