diff --git a/context.go b/context.go index c9faff2..756b11f 100644 --- a/context.go +++ b/context.go @@ -8,7 +8,6 @@ type Context struct { func CreateContext() Context { _, tmux := os.LookupEnv("TMUX") - os.Environ() insideTmuxSession := os.Getenv("TERM") == "screen" || tmux return Context{insideTmuxSession} } diff --git a/main.go b/main.go index 46375d2..01bb518 100644 --- a/main.go +++ b/main.go @@ -42,7 +42,7 @@ func main() { } if err != nil { - fmt.Fprintf(os.Stderr, "Cannot parse command line otions: %q", err.Error()) + fmt.Fprintf(os.Stderr, "Cannot parse command line options: %q", err.Error()) os.Exit(1) } @@ -80,7 +80,6 @@ func main() { commander := DefaultCommander{logger} tmux := Tmux{commander} smug := Smug{tmux, commander} - context := CreateContext() switch options.Command { diff --git a/smug.go b/smug.go index 2bcb988..dbc7b38 100644 --- a/smug.go +++ b/smug.go @@ -4,9 +4,12 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" ) +const defaultWindowName = "smug_def" + func ExpandPath(path string) string { if strings.HasPrefix(path, "~/") { userHome, err := os.UserHomeDir() @@ -48,11 +51,11 @@ func (smug Smug) execShellCommands(commands []string, path string) error { return nil } -func (smug Smug) switchOrAttach(sessionName string, attach bool, insideTmuxSession bool) error { +func (smug Smug) switchOrAttach(target string, attach bool, insideTmuxSession bool) error { if insideTmuxSession && attach { - return smug.tmux.SwitchClient(sessionName) + return smug.tmux.SwitchClient(target) } else if !insideTmuxSession { - return smug.tmux.Attach(sessionName, os.Stdin, os.Stdout, os.Stderr) + return smug.tmux.Attach(target, os.Stdin, os.Stdout, os.Stderr) } return nil } @@ -94,14 +97,7 @@ func (smug Smug) Start(config Config, options Options, context Context) error { return err } - var defaultWindowName string - if len(windows) > 0 { - defaultWindowName = windows[0] - } else if len(config.Windows) > 0 { - defaultWindowName = config.Windows[0].Name - } - - _, err = smug.tmux.NewSession(strings.Replace(sessionName, ":", "", 1), sessionRoot, defaultWindowName) + _, err = smug.tmux.NewSession(config.Session, sessionRoot, defaultWindowName) if err != nil { return err } @@ -109,7 +105,7 @@ func (smug Smug) Start(config Config, options Options, context Context) error { return smug.switchOrAttach(sessionName, attach, context.InsideTmuxSession) } - for wIndex, w := range config.Windows { + for _, w := range config.Windows { if (len(windows) == 0 && w.Manual) || (len(windows) > 0 && !Contains(windows, w.Name)) { continue } @@ -120,11 +116,9 @@ func (smug Smug) Start(config Config, options Options, context Context) error { } window := sessionName + w.Name - if (!sessionExists && wIndex > 0 && len(windows) == 0) || (sessionExists && len(windows) > 0) { - _, err := smug.tmux.NewWindow(sessionName, w.Name, windowRoot) - if err != nil { - return err - } + _, err := smug.tmux.NewWindow(sessionName, w.Name, windowRoot) + if err != nil { + return err } for _, c := range w.Commands { @@ -134,31 +128,41 @@ func (smug Smug) Start(config Config, options Options, context Context) error { } } - for _, p := range w.Panes { + layout := w.Layout + if layout == "" { + layout = EvenHorizontal + } + + _, err = smug.tmux.SelectLayout(sessionName+w.Name, layout) + if err != nil { + return err + } + + for pIndex, p := range w.Panes { paneRoot := ExpandPath(p.Root) if paneRoot == "" || !filepath.IsAbs(p.Root) { paneRoot = filepath.Join(windowRoot, p.Root) } - _, err := smug.tmux.SplitWindow(window, p.Type, paneRoot, p.Commands) + _, err := smug.tmux.SplitWindow(window, p.Type, paneRoot) if err != nil { return err } - } - - layout := w.Layout - if layout == "" { - layout = EvenHorizontal - } - _, err := smug.tmux.SelectLayout(sessionName+w.Name, layout) - if err != nil { - return err + for _, c := range p.Commands { + err = smug.tmux.SendKeys(window+"."+strconv.Itoa(pIndex+1), c) + if err != nil { + return err + } + } } } - if len(windows) == 0 { - return smug.switchOrAttach(sessionName, attach, context.InsideTmuxSession) + smug.tmux.KillWindow(sessionName + defaultWindowName) + smug.tmux.RenumberWindows(sessionName) + + if len(windows) == 0 && len(config.Windows) > 0 { + return smug.switchOrAttach(sessionName+config.Windows[0].Name, attach, context.InsideTmuxSession) } return nil diff --git a/smug_test.go b/smug_test.go index 43e6055..22ca894 100644 --- a/smug_test.go +++ b/smug_test.go @@ -20,6 +20,11 @@ var testTable = []struct { Session: "ses", Root: "root", BeforeStart: []string{"command1", "command2"}, + Windows: []Window{ + { + Name: "win1", + }, + }, }, Options{ Windows: []string{}, @@ -29,8 +34,12 @@ var testTable = []struct { "tmux has-session -t ses:", "/bin/sh -c command1", "/bin/sh -c command2", - "tmux new -Pd -s ses -n -c root", - "tmux attach -d -t ses:", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win1 -c root", + "tmux select-layout -t ses:win1 even-horizontal", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", + "tmux attach -d -t ses:win1", }, []string{ "tmux kill-session -t ses", @@ -67,10 +76,13 @@ var testTable = []struct { Context{}, []string{ "tmux has-session -t ses:", - "tmux new -Pd -s ses -n win1 -c root", - "tmux split-window -Pd -t ses:win1 -c root -h", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win1 -c root", "tmux select-layout -t ses:win1 main-horizontal", - "tmux attach -d -t ses:", + "tmux split-window -Pd -t ses:win1 -c root -h", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", + "tmux attach -d -t ses:win1", }, []string{ "/bin/sh -c stop1", @@ -100,8 +112,11 @@ var testTable = []struct { Context{}, []string{ "tmux has-session -t ses:", - "tmux new -Pd -s ses -n win2 -c root", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win2 -c root", "tmux select-layout -t ses:win2 even-horizontal", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", }, []string{ "tmux kill-window -t ses:win2", @@ -131,7 +146,8 @@ var testTable = []struct { Context{}, []string{ "tmux has-session -t ses:", - "tmux new -Pd -s ses -n win1 -c root", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win1 -c root", "tmux send-keys -t ses:win1 command1 Enter", "tmux send-keys -t ses:win1 command2 Enter", "tmux select-layout -t ses:win1 even-horizontal", @@ -139,19 +155,62 @@ var testTable = []struct { "tmux send-keys -t ses:win2 command3 Enter", "tmux send-keys -t ses:win2 command4 Enter", "tmux select-layout -t ses:win2 even-horizontal", - "tmux attach -d -t ses:", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", + "tmux attach -d -t ses:win1", + }, + []string{ + "tmux kill-session -t ses", + }, + "xyz", + }, + { + Config{ + Session: "ses", + Root: "root", + Windows: []Window{ + { + Name: "win1", + Manual: false, + Root: "./win1", + Panes: []Pane{ + { + Root: "pane1", + Type: "vertical", + Commands: []string{ + "command1", + }, + }, + }, + }, + }, + }, + Options{}, + Context{}, + []string{ + "tmux has-session -t ses:", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win1 -c root/win1", + "tmux select-layout -t ses:win1 even-horizontal", + "tmux split-window -Pd -t ses:win1 -c root/win1/pane1 -v", + "tmux send-keys -t ses:win1.1 command1 Enter", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", + "tmux attach -d -t ses:win1", }, []string{ "tmux kill-session -t ses", }, "xyz", }, - { Config{ Session: "ses", Root: "root", BeforeStart: []string{"command1", "command2"}, + Windows: []Window{ + {Name: "win1"}, + }, }, Options{}, Context{}, @@ -168,13 +227,22 @@ var testTable = []struct { Config{ Session: "ses", Root: "root", + Windows: []Window{ + { + Name: "win1", + }, + }, }, Options{Attach: true}, Context{InsideTmuxSession: true}, []string{ "tmux has-session -t ses:", - "tmux new -Pd -s ses -n -c root", - "tmux switch-client -t ses:", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux neww -Pd -t ses: -n win1 -c root", + "tmux select-layout -t ses:win1 even-horizontal", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", + "tmux switch-client -t ses:win1", }, []string{ "tmux kill-session -t ses", @@ -190,7 +258,9 @@ var testTable = []struct { Context{InsideTmuxSession: true}, []string{ "tmux has-session -t ses:", - "tmux new -Pd -s ses -n -c root", + "tmux new -Pd -s ses -n smug_def -c root", + "tmux kill-window -t ses:smug_def", + "tmux move-window -r -s ses: -t ses:", }, []string{ "tmux kill-session -t ses", @@ -201,6 +271,9 @@ var testTable = []struct { Config{ Session: "ses", Root: "root", + Windows: []Window{ + {Name: "win1"}, + }, }, Options{Attach: true}, Context{InsideTmuxSession: true}, diff --git a/tmux.go b/tmux.go index 830e37e..ad48d14 100644 --- a/tmux.go +++ b/tmux.go @@ -47,8 +47,7 @@ func (tmux Tmux) NewWindow(target string, name string, root string) (string, err func (tmux Tmux) SendKeys(target string, command string) error { cmd := exec.Command("tmux", "send-keys", "-t", target, command, "Enter") - _, err := tmux.commander.Exec(cmd) - return err + return tmux.commander.ExecSilently(cmd) } func (tmux Tmux) Attach(target string, stdin *os.File, stdout *os.File, stderr *os.File) error { @@ -62,12 +61,12 @@ func (tmux Tmux) Attach(target string, stdin *os.File, stdout *os.File, stderr * } func (tmux Tmux) RenumberWindows(target string) error { - cmd := exec.Command("tmux", "move-window", "-r") + cmd := exec.Command("tmux", "move-window", "-r", "-s", target, "-t", target) _, err := tmux.commander.Exec(cmd) return err } -func (tmux Tmux) SplitWindow(target string, splitType string, root string, commands []string) (string, error) { +func (tmux Tmux) SplitWindow(target string, splitType string, root string) (string, error) { args := []string{"split-window", "-Pd", "-t", target, "-c", root} switch splitType { @@ -84,13 +83,6 @@ func (tmux Tmux) SplitWindow(target string, splitType string, root string, comma return "", err } - for _, c := range commands { - err = tmux.SendKeys(pane, c) - if err != nil { - return "", err - } - } - return pane, nil }