Allow creating sessions without nesting (#16)

* 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
master
Ivan 3 years ago committed by GitHub
parent a7ab672b7d
commit f9b4217af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

@ -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)

@ -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.
@ -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
}
@ -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
}

@ -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},
},
}

@ -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 {
@ -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
@ -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
}
@ -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 {
@ -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

@ -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",
@ -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",
@ -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{
@ -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)
}

@ -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)
}
@ -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 {
@ -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
@ -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
@ -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)
}

Loading…
Cancel
Save