Skip to content

Commit

Permalink
Allow creating sessions without nesting (#16)
Browse files Browse the repository at this point in the history
* Allow creating sessions without nesting
* New `--attach` flag allows you to switch a client when you're inside tmux session
* If the session already exists, Smug won't throw an error. Instead, it will attach you to an existing session
  • Loading branch information
ivaaaan authored Dec 23, 2020
1 parent a7ab672 commit f9b4217
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 68 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ go install

## Usage

`smug <command> <project>[:window name] [-w window name]`.
`smug <command> <project>[:window name] [-w window name]... [--attach]`.

### Examples

Expand Down
8 changes: 6 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ func main() {

switch options.Command {
case "start":
fmt.Println("Starting a new session...")
err = smug.Start(*config, options.Windows)
if len(options.Windows) == 0 {
fmt.Println("Starting a new session...")
} else {
fmt.Println("Starting new windows...")
}
err = smug.Start(*config, options.Windows, options.Attach)
if err != nil {
fmt.Println("Oops, an error occurred! Rolling back...")
smug.Stop(*config, options.Windows)
Expand Down
11 changes: 7 additions & 4 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
const usage = `Smug - tmux session manager.
Usage:
smug <command> <project> [-w <window>]...
smug <command> <project> [-w <window>]... [--attach]
Options:
-w List of windows to start. If session exists, those windows will be attached to current session.
Expand All @@ -26,23 +26,26 @@ type Options struct {
Command string
Project string
Windows []string
Attach bool
}

func ParseOptions(p docopt.Parser, argv []string) (Options, error) {
arguments, err := p.ParseArgs(usage, argv, "")

if err != nil {
return Options{}, err
}

cmd, err := arguments.String("<command>")

if err != nil {
return Options{}, err
}

project, err := arguments.String("<project>")
if err != nil {
return Options{}, err
}

attach, err := arguments.Bool("--attach")
if err != nil {
return Options{}, err
}
Expand All @@ -57,5 +60,5 @@ func ParseOptions(p docopt.Parser, argv []string) (Options, error) {
windows = arguments["-w"].([]string)
}

return Options{cmd, project, windows}, nil
return Options{cmd, project, windows, attach}, nil
}
10 changes: 7 additions & 3 deletions options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ var usageTestTable = []struct {
}{
{
[]string{"start", "smug"},
Options{"start", "smug", []string{}},
Options{"start", "smug", []string{}, false},
},
{
[]string{"start", "smug", "-wfoo"},
Options{"start", "smug", []string{"foo"}},
Options{"start", "smug", []string{"foo"}, false},
},
{
[]string{"start", "smug:foo,bar"},
Options{"start", "smug", []string{"foo", "bar"}},
Options{"start", "smug", []string{"foo", "bar"}, false},
},
{
[]string{"start", "smug", "--attach"},
Options{"start", "smug", []string{}, true},
},
}

Expand Down
69 changes: 44 additions & 25 deletions smug.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ func (smug Smug) execShellCommands(commands []string, path string) error {
return nil
}

func (smug Smug) switchOrAttach(ses string, windows []string, attach bool) error {
insideTmuxSession := os.Getenv("TERM") == "screen"
if insideTmuxSession && attach {
return smug.tmux.SwitchClient(ses)
} else if !insideTmuxSession {
return smug.tmux.Attach(ses, os.Stdin, os.Stdout, os.Stderr)
}
return nil
}

func (smug Smug) Stop(config Config, windows []string) error {
if len(windows) == 0 {

Expand All @@ -72,7 +82,7 @@ func (smug Smug) Stop(config Config, windows []string) error {
return nil
}

func (smug Smug) Start(config Config, windows []string) error {
func (smug Smug) Start(config Config, windows []string, attach bool) error {
var ses string
var err error

Expand All @@ -85,15 +95,27 @@ func (smug Smug) Start(config Config, windows []string) error {
return err
}

ses, err = smug.tmux.NewSession(config.Session)
var defaultWindowName string
if len(windows) > 0 {
defaultWindowName = windows[0]
} else if len(config.Windows) > 0 {
defaultWindowName = config.Windows[0].Name
}

ses, err = smug.tmux.NewSession(config.Session, sessionRoot, defaultWindowName)
if err != nil {
return err
}
} else {
ses = config.Session + ":"
if len(windows) == 0 {
smug.switchOrAttach(ses, windows, attach)
return nil
}
}

for _, w := range config.Windows {
var createdWindows []string
for wIndex, w := range config.Windows {
if (len(windows) == 0 && w.Manual) || (len(windows) > 0 && !Contains(windows, w.Name)) {
continue
}
Expand All @@ -103,9 +125,24 @@ func (smug Smug) Start(config Config, windows []string) error {
windowRoot = filepath.Join(sessionRoot, w.Root)
}

window, err := smug.tmux.NewWindow(ses, w.Name, windowRoot, w.Commands)
if err != nil {
return err
var window string

if (wIndex == 0 || len(createdWindows) == 0) && !sessionExists {
window = ses + w.Name
} else {

window, err = smug.tmux.NewWindow(ses, w.Name, windowRoot)
if err != nil {
return err
}
createdWindows = append(createdWindows, window)
}

for _, c := range w.Commands {
err = smug.tmux.SendKeys(window, c)
if err != nil {
return err
}
}

for _, p := range w.Panes {
Expand All @@ -132,25 +169,7 @@ func (smug Smug) Start(config Config, windows []string) error {
}

if len(windows) == 0 {
windows, err := smug.tmux.ListWindows(ses)
if err != nil {
return err
}

err = smug.tmux.KillWindow(ses + windows[0])
if err != nil {
return err
}

err = smug.tmux.RenumberWindows()
if err != nil {
return err
}

err = smug.tmux.Attach(ses + windows[0], os.Stdin, os.Stdout, os.Stderr)
if err != nil {
return err
}
smug.switchOrAttach(ses, windows, attach)
}

return nil
Expand Down
22 changes: 7 additions & 15 deletions smug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ var testTable = []struct {
"tmux has-session -t ses",
"/bin/sh -c command1",
"/bin/sh -c command2",
"tmux new -Pd -s ses",
"tmux list-windows -t ses: -F #{window_index}",
"tmux kill-window -t ses:ses:",
"tmux move-window -r",
"tmux attach -t ses:ses:",
"tmux new -Pd -s ses -n -c root",
"tmux attach -d -t ses:",
},
[]string{
"tmux kill-session -t ses",
Expand Down Expand Up @@ -62,14 +59,10 @@ var testTable = []struct {
},
[]string{
"tmux has-session -t ses",
"tmux new -Pd -s ses",
"tmux neww -Pd -t ses: -n win1 -c root",
"tmux split-window -Pd -t ses: -c root -h",
"tmux new -Pd -s ses -n win1 -c root",
"tmux split-window -Pd -t ses:win1 -c root -h",
"tmux select-layout -t ses:win1 main-horizontal",
"tmux list-windows -t ses: -F #{window_index}",
"tmux kill-window -t ses:ses:",
"tmux move-window -r",
"tmux attach -t ses:ses:",
"tmux attach -d -t ses:",
},
[]string{
"/bin/sh -c stop1",
Expand All @@ -95,8 +88,7 @@ var testTable = []struct {
},
[]string{
"tmux has-session -t ses",
"tmux new -Pd -s ses",
"tmux neww -Pd -t ses: -n win2 -c root",
"tmux new -Pd -s ses -n win2 -c root",
"tmux select-layout -t ses:win2 even-horizontal",
},
[]string{
Expand Down Expand Up @@ -131,7 +123,7 @@ func TestStartSession(t *testing.T) {
tmux := Tmux{commander}
smug := Smug{tmux, commander}

err := smug.Start(params.config, params.windows)
err := smug.Start(params.config, params.windows, false)
if err != nil {
t.Fatalf("error %v", err)
}
Expand Down
29 changes: 11 additions & 18 deletions tmux.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type Tmux struct {
commander Commander
}

func (tmux Tmux) NewSession(name string) (string, error) {
cmd := exec.Command("tmux", "new", "-Pd", "-s", name)
func (tmux Tmux) NewSession(name string, root string, windowName string) (string, error) {
cmd := exec.Command("tmux", "new", "-Pd", "-s", name, "-n", windowName, "-c", root)
return tmux.commander.Exec(cmd)
}

Expand All @@ -40,22 +40,10 @@ func (tmux Tmux) KillWindow(target string) error {
return err
}

func (tmux Tmux) NewWindow(target string, name string, root string, commands []string) (string, error) {
func (tmux Tmux) NewWindow(target string, name string, root string) (string, error) {
cmd := exec.Command("tmux", "neww", "-Pd", "-t", target, "-n", name, "-c", root)

window, err := tmux.commander.Exec(cmd)
if err != nil {
return "", err
}

for _, c := range commands {
err = tmux.SendKeys(window, c)
if err != nil {
return "", err
}
}

return window, nil
return tmux.commander.Exec(cmd)
}

func (tmux Tmux) SendKeys(target string, command string) error {
Expand All @@ -65,7 +53,7 @@ func (tmux Tmux) SendKeys(target string, command string) error {
}

func (tmux Tmux) Attach(target string, stdin *os.File, stdout *os.File, stderr *os.File) error {
cmd := exec.Command("tmux", "attach", "-t", target)
cmd := exec.Command("tmux", "attach", "-d", "-t", target)

cmd.Stdin = stdin
cmd.Stdout = stdout
Expand All @@ -74,7 +62,7 @@ func (tmux Tmux) Attach(target string, stdin *os.File, stdout *os.File, stderr *
return tmux.commander.ExecSilently(cmd)
}

func (tmux Tmux) RenumberWindows() error {
func (tmux Tmux) RenumberWindows(target string) error {
cmd := exec.Command("tmux", "move-window", "-r")
_, err := tmux.commander.Exec(cmd)
return err
Expand Down Expand Up @@ -127,3 +115,8 @@ func (tmux Tmux) ListWindows(target string) ([]string, error) {

return strings.Split(output, "\n"), nil
}

func (tmux Tmux) SwitchClient(target string) error {
cmd := exec.Command("tmux", "switch-client", "-t", target)
return tmux.commander.ExecSilently(cmd)
}

0 comments on commit f9b4217

Please sign in to comment.