Skip to content

Commit 74fe700

Browse files
authored
Allow user to dump current tmux session (#45)
1 parent 0e3b9a4 commit 74fe700

File tree

6 files changed

+185
-26
lines changed

6 files changed

+185
-26
lines changed

config.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ import (
1111
)
1212

1313
type Pane struct {
14-
Root string `yaml:"root"`
15-
Type string `yaml:"type"`
14+
Root string `yaml:"root,omitempty"`
15+
Type string `yaml:"type,omitempty"`
1616
Commands []string `yaml:"commands"`
1717
}
1818

1919
type Window struct {
2020
Name string `yaml:"name"`
21-
Root string `yaml:"root"`
21+
Root string `yaml:"root,omitempty"`
2222
BeforeStart []string `yaml:"before_start"`
2323
Panes []Pane `yaml:"panes"`
2424
Commands []string `yaml:"commands"`
2525
Layout string `yaml:"layout"`
26-
Manual bool `yaml:"manual"`
26+
Manual bool `yaml:"manual,omitempty"`
2727
}
2828

2929
type Config struct {

main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"os"
77
"path/filepath"
88
"strings"
9+
10+
"gopkg.in/yaml.v2"
911
)
1012

1113
var version = "[dev build]"
@@ -125,5 +127,19 @@ func main() {
125127
}
126128

127129
fmt.Println(strings.Join(configs, "\n"))
130+
case CommandPrint:
131+
config, err := smug.GetConfigFromSession(options, context)
132+
if err != nil {
133+
fmt.Fprintf(os.Stderr, err.Error())
134+
os.Exit(1)
135+
}
136+
137+
d, err := yaml.Marshal(&config)
138+
if err != nil {
139+
fmt.Fprintf(os.Stderr, err.Error())
140+
os.Exit(1)
141+
}
142+
143+
fmt.Println(string(d))
128144
}
129145
}

options.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ const (
1313
CommandNew = "new"
1414
CommandEdit = "edit"
1515
CommandList = "list"
16+
CommandPrint = "print"
1617
)
1718

18-
var validCommands = []string{CommandStart, CommandStop, CommandNew, CommandEdit, CommandList}
19+
var validCommands = []string{CommandStart, CommandStop, CommandNew, CommandEdit, CommandList, CommandPrint}
1920

2021
type Options struct {
2122
Command string

smug.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,40 @@ func (smug Smug) Start(config Config, options Options, context Context) error {
165165

166166
return nil
167167
}
168+
169+
func (smug Smug) GetConfigFromSession(options Options, context Context) (Config, error) {
170+
config := Config{}
171+
config.Session = options.Project
172+
173+
tmuxWindows, err := smug.tmux.ListWindows(options.Project)
174+
if err != nil {
175+
return Config{}, err
176+
}
177+
178+
for _, w := range tmuxWindows {
179+
tmuxPanes, err := smug.tmux.ListPanes(options.Project + ":" + w.Id)
180+
if err != nil {
181+
return Config{}, err
182+
}
183+
184+
panes := []Pane{}
185+
for _, p := range tmuxPanes {
186+
root := p.Root
187+
if root == w.Root {
188+
root = ""
189+
}
190+
panes = append(panes, Pane{
191+
Root: root,
192+
})
193+
}
194+
195+
config.Windows = append(config.Windows, Window{
196+
Name: w.Name,
197+
Layout: w.Layout,
198+
Root: w.Root,
199+
Panes: panes,
200+
})
201+
}
202+
203+
return config, nil
204+
}

smug_test.go

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import (
88
)
99

1010
var testTable = []struct {
11-
config Config
12-
options Options
13-
context Context
14-
startCommands []string
15-
stopCommands []string
16-
commanderOutput string
11+
config Config
12+
options Options
13+
context Context
14+
startCommands []string
15+
stopCommands []string
16+
commanderOutputs []string
1717
}{
1818
{
1919
Config{
@@ -44,7 +44,7 @@ var testTable = []struct {
4444
[]string{
4545
"tmux kill-session -t ses",
4646
},
47-
"xyz",
47+
[]string{"xyz"},
4848
},
4949
{
5050
Config{
@@ -89,7 +89,7 @@ var testTable = []struct {
8989
"/bin/sh -c stop2 -d --foo=bar",
9090
"tmux kill-session -t ses",
9191
},
92-
"1",
92+
[]string{"1"},
9393
},
9494
{
9595
Config{
@@ -121,7 +121,7 @@ var testTable = []struct {
121121
[]string{
122122
"tmux kill-window -t ses:win2",
123123
},
124-
"xyz",
124+
[]string{"xyz"},
125125
},
126126
{
127127
Config{
@@ -162,7 +162,7 @@ var testTable = []struct {
162162
[]string{
163163
"tmux kill-session -t ses",
164164
},
165-
"xyz",
165+
[]string{"xyz"},
166166
},
167167
{
168168
Config{
@@ -201,7 +201,7 @@ var testTable = []struct {
201201
[]string{
202202
"tmux kill-session -t ses",
203203
},
204-
"1",
204+
[]string{"1"},
205205
},
206206
{
207207
Config{
@@ -221,7 +221,7 @@ var testTable = []struct {
221221
[]string{
222222
"tmux kill-session -t ses",
223223
},
224-
"",
224+
[]string{""},
225225
},
226226
{
227227
Config{
@@ -247,7 +247,7 @@ var testTable = []struct {
247247
[]string{
248248
"tmux kill-session -t ses",
249249
},
250-
"xyz",
250+
[]string{"xyz"},
251251
},
252252
{
253253
Config{
@@ -265,7 +265,7 @@ var testTable = []struct {
265265
[]string{
266266
"tmux kill-session -t ses",
267267
},
268-
"xyz",
268+
[]string{"xyz"},
269269
},
270270
{
271271
Config{
@@ -284,31 +284,38 @@ var testTable = []struct {
284284
[]string{
285285
"tmux kill-session -t ses",
286286
},
287-
"",
287+
[]string{""},
288288
},
289289
}
290290

291291
type MockCommander struct {
292-
Commands []string
293-
DefaultOutput string
292+
Commands []string
293+
Outputs []string
294294
}
295295

296296
func (c *MockCommander) Exec(cmd *exec.Cmd) (string, error) {
297297
c.Commands = append(c.Commands, strings.Join(cmd.Args, " "))
298298

299-
return c.DefaultOutput, nil
299+
output := ""
300+
if len(c.Outputs) > 1 {
301+
output, c.Outputs = c.Outputs[0], c.Outputs[1:]
302+
} else if len(c.Outputs) == 1 {
303+
output = c.Outputs[0]
304+
}
305+
306+
return output, nil
300307
}
301308

302309
func (c *MockCommander) ExecSilently(cmd *exec.Cmd) error {
303310
c.Commands = append(c.Commands, strings.Join(cmd.Args, " "))
304311
return nil
305312
}
306313

307-
func TestStartSession(t *testing.T) {
314+
func TestStartStopSession(t *testing.T) {
308315
for _, params := range testTable {
309316

310317
t.Run("test start session", func(t *testing.T) {
311-
commander := &MockCommander{[]string{}, params.commanderOutput}
318+
commander := &MockCommander{[]string{}, params.commanderOutputs}
312319
tmux := Tmux{commander}
313320
smug := Smug{tmux, commander}
314321

@@ -323,7 +330,7 @@ func TestStartSession(t *testing.T) {
323330
})
324331

325332
t.Run("test stop session", func(t *testing.T) {
326-
commander := &MockCommander{[]string{}, params.commanderOutput}
333+
commander := &MockCommander{[]string{}, params.commanderOutputs}
327334
tmux := Tmux{commander}
328335
smug := Smug{tmux, commander}
329336

@@ -339,3 +346,39 @@ func TestStartSession(t *testing.T) {
339346

340347
}
341348
}
349+
350+
func TestPrintCurrentSession(t *testing.T) {
351+
expectedConfig := Config{
352+
Session: "test",
353+
Windows: []Window{
354+
Window{
355+
Name: "win1",
356+
Root: "root",
357+
Layout: "layout",
358+
Panes: []Pane{
359+
Pane{},
360+
Pane{
361+
Root: "/tmp",
362+
},
363+
},
364+
},
365+
},
366+
}
367+
368+
commander := &MockCommander{[]string{}, []string{
369+
"id1;win1;layout;root",
370+
"root\n/tmp",
371+
}}
372+
tmux := Tmux{commander}
373+
374+
smug := Smug{tmux, commander}
375+
376+
actualConfig, err := smug.GetConfigFromSession(Options{Project: "test"}, Context{})
377+
if err != nil {
378+
t.Fatalf("error %v", err)
379+
}
380+
381+
if !reflect.DeepEqual(expectedConfig, actualConfig) {
382+
t.Errorf("expected %v, got %v", expectedConfig, actualConfig)
383+
}
384+
}

tmux.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"os"
55
"os/exec"
6+
"strings"
67
)
78

89
const (
@@ -22,6 +23,17 @@ type Tmux struct {
2223
commander Commander
2324
}
2425

26+
type TmuxWindow struct {
27+
Id string
28+
Name string
29+
Layout string
30+
Root string
31+
}
32+
33+
type TmuxPane struct {
34+
Root string
35+
}
36+
2537
func (tmux Tmux) NewSession(name string, root string, windowName string) (string, error) {
2638
cmd := exec.Command("tmux", "new", "-Pd", "-s", name, "-n", windowName, "-c", root)
2739
return tmux.commander.Exec(cmd)
@@ -102,3 +114,53 @@ func (tmux Tmux) SwitchClient(target string) error {
102114
cmd := exec.Command("tmux", "switch-client", "-t", target)
103115
return tmux.commander.ExecSilently(cmd)
104116
}
117+
118+
func (tmux Tmux) ListWindows(target string) ([]TmuxWindow, error) {
119+
var windows []TmuxWindow
120+
121+
cmd := exec.Command("tmux", "list-windows", "-F", "#{window_id};#{window_name};#{window_layout};#{pane_current_path}", "-t", target)
122+
out, err := tmux.commander.Exec(cmd)
123+
if err != nil {
124+
return windows, err
125+
}
126+
127+
windowsList := strings.Split(out, "\n")
128+
129+
for _, w := range windowsList {
130+
windowInfo := strings.Split(w, ";")
131+
window := TmuxWindow{
132+
Id: windowInfo[0],
133+
Name: windowInfo[1],
134+
Layout: windowInfo[2],
135+
Root: windowInfo[3],
136+
}
137+
windows = append(windows, window)
138+
}
139+
140+
return windows, nil
141+
142+
}
143+
144+
func (tmux Tmux) ListPanes(target string) ([]TmuxPane, error) {
145+
var panes []TmuxPane
146+
147+
cmd := exec.Command("tmux", "list-panes", "-F", "#{pane_current_path}", "-t", target)
148+
149+
out, err := tmux.commander.Exec(cmd)
150+
if err != nil {
151+
return panes, err
152+
}
153+
154+
panesList := strings.Split(out, "\n")
155+
156+
for _, p := range panesList {
157+
paneInfo := strings.Split(p, ";")
158+
pane := TmuxPane{
159+
Root: paneInfo[0],
160+
}
161+
162+
panes = append(panes, pane)
163+
}
164+
165+
return panes, nil
166+
}

0 commit comments

Comments
 (0)