Skip to content

Commit

Permalink
Add ssh example
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed Jun 1, 2022
1 parent d1fa5a5 commit 34c324c
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 4 deletions.
4 changes: 3 additions & 1 deletion examples/hello-world/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ func main() {
fmt.Printf("\n\t%s %s\n", termenv.String("Has foreground color").Bold(), termenv.ForegroundColor())
fmt.Printf("\t%s %s\n", termenv.String("Has background color").Bold(), termenv.BackgroundColor())
fmt.Printf("\t%s %t\n", termenv.String("Has dark background?").Bold(), termenv.HasDarkBackground())
fmt.Println()

hw := "Hello, world!"
termenv.Copy(hw)
fmt.Println()
fmt.Printf("\t%q copied to clipboard\n", hw)
fmt.Println()

fmt.Printf("\t%s", termenv.Hyperlink("http://example.com", "This is a link"))
fmt.Println()
}
24 changes: 24 additions & 0 deletions examples/ssh/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module github.com/muesli/termenv/examples/ssh

go 1.18

require (
github.com/charmbracelet/wish v0.4.0
github.com/creack/pty v1.1.18
github.com/gliderlabs/ssh v0.3.4
github.com/muesli/termenv v0.11.1-0.20220601154942-afd10a1cfe15
)

require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
github.com/caarlos0/sshmarshal v0.1.0 // indirect
github.com/charmbracelet/keygen v0.3.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
)
43 changes: 43 additions & 0 deletions examples/ssh/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/caarlos0/sshmarshal v0.1.0 h1:zTCZrDORFfWh526Tsb7vCm3+Yg/SfW/Ub8aQDeosk0I=
github.com/caarlos0/sshmarshal v0.1.0/go.mod h1:7Pd/0mmq9x/JCzKauogNjSQEhivBclCQHfr9dlpDIyA=
github.com/charmbracelet/keygen v0.3.0 h1:mXpsQcH7DDlST5TddmXNXjS0L7ECk4/kLQYyBcsan2Y=
github.com/charmbracelet/keygen v0.3.0/go.mod h1:1ukgO8806O25lUZ5s0IrNur+RlwTBERlezdgW71F5rM=
github.com/charmbracelet/wish v0.4.0 h1:MLo8JjyvSK1lYkhPCzpI+8pwpKO8cUDP4GZtEoOKu4c=
github.com/charmbracelet/wish v0.4.0/go.mod h1:jRL2Shd80OlP77bR8x3v8PrLCtkYCc/1nUV1eGexNj0=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/gliderlabs/ssh v0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
github.com/gliderlabs/ssh v0.3.4/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 h1:QANkGiGr39l1EESqrE0gZw0/AJNYzIvoGLhIoVYtluI=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.11.1-0.20220601154942-afd10a1cfe15 h1:Rtce5txOG+kHRA1VwLUez8ZNgJPoYTJerC3lVv8v5eQ=
github.com/muesli/termenv v0.11.1-0.20220601154942-afd10a1cfe15/go.mod h1:bN6sPNtkiahdhHv2Xm6RGU16LSCxfbIZvMfqjOCfrR4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU=
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed h1:Ei4bQjjpYUsS4efOUz+5Nz++IVkHk87n2zBA0NxBWc0=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
124 changes: 124 additions & 0 deletions examples/ssh/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"fmt"
"log"
"os"
"strings"

"github.com/charmbracelet/wish"
"github.com/creack/pty"
"github.com/gliderlabs/ssh"
"github.com/muesli/termenv"
)

type sshOutput struct {
ssh.Session
pty *os.File
}

func (s *sshOutput) Fd() uintptr {
return s.pty.Fd()
}

type sshEnviron struct {
environ []string
}

func (s *sshEnviron) Getenv(key string) string {
for _, v := range s.environ {
if strings.HasPrefix(v, key+"=") {
return v[len(key)+1:]
}
}
return ""
}

func (s *sshEnviron) Environ() []string {
return s.environ
}

func outputFromSession(s ssh.Session) *termenv.Output {
sshPty, _, _ := s.Pty()
pty, _, err := pty.Open()
if err != nil {
panic(err)
}
o := &sshOutput{
Session: s,
pty: pty,
}
environ := s.Environ()
environ = append(environ, fmt.Sprintf("TERM=%s", sshPty.Term))
e := &sshEnviron{
environ: environ,
}
return termenv.NewOutput(o, e)
}

func main() {
s, err := wish.NewServer(
wish.WithAddress(":2345"),
wish.WithHostKeyPath("termenv"),
wish.WithMiddleware(
func(sh ssh.Handler) ssh.Handler {
return func(s ssh.Session) {
output := outputFromSession(s)

p := output.ColorProfile()
fmt.Fprintf(s, "\tColor Profile: %d\n", p)

fmt.Fprintf(s, "\n\t%s %s %s %s %s",
output.String("bold").Bold(),
output.String("faint").Faint(),
output.String("italic").Italic(),
output.String("underline").Underline(),
output.String("crossout").CrossOut(),
)

fmt.Fprintf(s, "\n\t%s %s %s %s %s %s %s",
output.String("red").Foreground(p.Color("#E88388")),
output.String("green").Foreground(p.Color("#A8CC8C")),
output.String("yellow").Foreground(p.Color("#DBAB79")),
output.String("blue").Foreground(p.Color("#71BEF2")),
output.String("magenta").Foreground(p.Color("#D290E4")),
output.String("cyan").Foreground(p.Color("#66C2CD")),
output.String("gray").Foreground(p.Color("#B9BFCA")),
)

fmt.Fprintf(s, "\n\t%s %s %s %s %s %s %s\n\n",
output.String("red").Foreground(p.Color("0")).Background(p.Color("#E88388")),
output.String("green").Foreground(p.Color("0")).Background(p.Color("#A8CC8C")),
output.String("yellow").Foreground(p.Color("0")).Background(p.Color("#DBAB79")),
output.String("blue").Foreground(p.Color("0")).Background(p.Color("#71BEF2")),
output.String("magenta").Foreground(p.Color("0")).Background(p.Color("#D290E4")),
output.String("cyan").Foreground(p.Color("0")).Background(p.Color("#66C2CD")),
output.String("gray").Foreground(p.Color("0")).Background(p.Color("#B9BFCA")),
)

fmt.Fprintf(s, "\n\t%s %s\n", output.String("Has foreground color").Bold(), output.ForegroundColor())
fmt.Fprintf(s, "\t%s %s\n", output.String("Has background color").Bold(), output.BackgroundColor())
fmt.Fprintf(s, "\t%s %t\n", output.String("Has dark background?").Bold(), output.HasDarkBackground())
fmt.Fprintln(s)

hw := "Hello, world!"
output.Copy(hw)
fmt.Fprintf(s, "\t%q copied to clipboard\n", hw)
fmt.Fprintln(s)

fmt.Fprintf(s, "\t%s", output.Hyperlink("http://example.com", "This is a link"))
fmt.Fprintln(s)

sh(s)
}
},
),
)
if err != nil {
log.Fatal(err)
}
log.Printf("Listening on %s", s.Addr)
if err := s.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
6 changes: 3 additions & 3 deletions termenv_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ func (o Output) termStatusReport(sequence int) (string, error) {

t, err := unix.IoctlGetTermios(fd, tcgetattr)
if err != nil {
return "", ErrStatusReport
return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
}
defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck

noecho := *t
noecho.Lflag = noecho.Lflag &^ unix.ECHO
noecho.Lflag = noecho.Lflag &^ unix.ICANON
if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
return "", ErrStatusReport
return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
}

// first, send OSC query, which is ignored by terminal which do not support it
Expand All @@ -251,7 +251,7 @@ func (o Output) termStatusReport(sequence int) (string, error) {
// read the next response
res, isOSC, err := readNextResponse(o.tty)
if err != nil {
return "", err
return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
}

// if this is not OSC response, then the terminal does not support it
Expand Down

0 comments on commit 34c324c

Please sign in to comment.