Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: tmux command execution #59

Merged
merged 2 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ jobs:
go-version: "1.21"
- name: Install deps
run: go install github.com/jstemmer/go-junit-report/v2@latest
- if: startsWith(matrix.os, 'macOS')
run: |
brew update
brew install tmux
joshmedeski marked this conversation as resolved.
Show resolved Hide resolved
- name: Run tests
run: go test -cover -bench=. -benchmem -race -v 2>&1 ./... | go-junit-report -set-exit-code > report.xml
- name: Test Summary
Expand Down
10 changes: 5 additions & 5 deletions tmux/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ func sortSessions(sessions []*TmuxSession) []*TmuxSession {

func List(o Options) ([]*TmuxSession, error) {
format := format()
output, err := tmuxCmd([]string{"list-sessions", "-F", format})
cleanOutput := strings.TrimSpace(output)
if err != nil || strings.HasPrefix(cleanOutput, "no server running on") {
return nil, nil
output, err := command.Run([]string{"list-sessions", "-F", format})
if err != nil {
return nil, err
}
sessionList := strings.TrimSpace(string(output))

sessionList := output
lines := strings.Split(sessionList, "\n")
sessions := processSessions(o, lines)

Expand Down
42 changes: 42 additions & 0 deletions tmux/list_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tmux

import (
_ "embed"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -86,6 +87,47 @@ func TestProcessSessions(t *testing.T) {
}
}

//go:embed testdata/session_list.txt
var sessionList string

func TestList(t *testing.T) {
testCase := map[string]struct {
MockResponse string
MockError error
Options Options
ExpectedLength int
Error error
}{
"happy path": {
MockResponse: sessionList,
ExpectedLength: 3,
},
"happy path show hidden": {
MockResponse: sessionList,
Options: Options{HideAttached: true},
ExpectedLength: 2,
},
}

for name, tc := range testCase {
t.Run(name, func(t *testing.T) {
command = &Command{
execFunc: func(string, []string) (string, error) {
return tc.MockResponse, tc.MockError
},
}
res, err := List(tc.Options)
require.ErrorIs(t, tc.Error, err)
if err != nil {
return
}

require.Len(t, res, tc.ExpectedLength)
t.Log(res)
})
}
}

func BenchmarkProcessSessions(b *testing.B) {
for n := 0; n < b.N; n++ {
processSessions(Options{}, []string{
Expand Down
3 changes: 3 additions & 0 deletions tmux/testdata/session_list.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1706646951 1 /dev/ttys000 1706475706 1 0 $2 1706643877 0 0 sesh /Users/test_user/dev/sesh 2,1 2
1706632190 0 1706485534 1 0 $8 1706632189 0 0 dotfiles /Users/test_user/dotfiles 1 1
1706485830 0 1706485825 1 0 $10 1706485825 0 0 window-name /Users/test_user/test_user/tmux-nerd-font-window-name 1 1
93 changes: 72 additions & 21 deletions tmux/tmux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,82 @@ import (
"os"
"os/exec"
"strings"
"sync"

"github.com/joshmedeski/sesh/config"
"github.com/joshmedeski/sesh/dir"
)

var (
command *Command
once sync.Once
)

func init() {
once.Do(func() {
var err error
command, err = NewCommand()
if err != nil {
log.Fatal(err)
}
})
}

type Error struct{ msg string }

func (e Error) Error() string { return e.msg }

var ErrNotRunning = Error{"no server running"}

func executeCommand(command string, args []string) (string, error) {
var stdout, stderr bytes.Buffer
cmd := exec.Command(command, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = &stdout
cmd.Stderr = &stderr

if err := cmd.Start(); err != nil {
return "", err
}

if err := cmd.Wait(); err != nil {
if strings.Contains(stderr.String(), "no server running on") {
return "", ErrNotRunning
}

return "", err
}

out := strings.TrimSpace(stdout.String())
if strings.Contains(out, "no server running on") {
return "", ErrNotRunning
}

return out, nil
}

type Command struct {
cliPath string
execFunc func(string, []string) (string, error)
}

func NewCommand() (c *Command, err error) {
joshmedeski marked this conversation as resolved.
Show resolved Hide resolved
c = new(Command)

c.cliPath, err = exec.LookPath("tmux")
if err != nil {
return nil, err
}

c.execFunc = executeCommand

return c, nil
}

func (c *Command) Run(args []string) (string, error) {
return c.execFunc(c.cliPath, args)
}

func GetSession(s string) (TmuxSession, error) {
sessionList, err := List(Options{})
if err != nil {
Expand Down Expand Up @@ -41,27 +112,7 @@ func GetSession(s string) (TmuxSession, error) {
}

func tmuxCmd(args []string) (string, error) {
tmux, err := exec.LookPath("tmux")
if err != nil {
return "", err
}
var stdout, stderr bytes.Buffer
cmd := exec.Command(tmux, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = &stdout
cmd.Stderr = os.Stderr
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
return "", err
}
if err := cmd.Wait(); err != nil {
errString := strings.TrimSpace(stderr.String())
if strings.HasPrefix(errString, "no server running on") {
return "", nil
}
return "", err
}
return stdout.String(), nil
return command.Run(args)
}

func isAttached() bool {
Expand Down
Loading