-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a config parser and init a config validor for future features
- Loading branch information
1 parent
e031ccf
commit df7625e
Showing
8 changed files
with
261 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/BurntSushi/toml" | ||
) | ||
|
||
// Pane contains a pane configuration | ||
type Pane struct { | ||
Dir string | ||
Zoom bool | ||
Split string | ||
Scripts []string | ||
} | ||
|
||
// Window contains a window configuration | ||
type Window struct { | ||
Name string | ||
Dir string | ||
Layout string | ||
Sync bool | ||
Scripts []string | ||
Panes []Pane | ||
PaneScripts []string `toml:"pane-scripts"` | ||
} | ||
|
||
// Session contains a tmux session configuration | ||
type Session struct { | ||
Name string | ||
Dir string | ||
ClearPanes bool `toml:"clear-panes"` | ||
Windows []Window | ||
SelectWindow string `toml:"select-window"` | ||
SelectPane int `toml:"select-pane"` | ||
WindowScripts []string `toml:"window-scripts"` | ||
} | ||
|
||
var ( | ||
validLayouts = []string{ | ||
"even-horizontal", | ||
"even-vertical", | ||
"main-horizontal", | ||
"main-vertical", | ||
"tiled", | ||
} | ||
) | ||
|
||
func checkValid(conf Session) error { | ||
// check at least one window | ||
if len(conf.Windows) == 0 { | ||
return errors.New("you must declare at least on window (0 provided)") | ||
} | ||
|
||
// check select-window and select-pane exist | ||
if conf.SelectWindow != "" { | ||
var win Window | ||
found := false | ||
for _, w := range conf.Windows { | ||
if w.Name == conf.SelectWindow { | ||
win = w | ||
found = true | ||
break | ||
} | ||
} | ||
|
||
if !found { | ||
return fmt.Errorf("selected window %s doesn't exist", conf.SelectWindow) | ||
} | ||
|
||
if conf.SelectPane != 0 { | ||
if len(win.Panes) < conf.SelectPane { | ||
return fmt.Errorf("selected pane %d doesn't exist", conf.SelectPane) | ||
} | ||
} | ||
} | ||
|
||
for _, w := range conf.Windows { | ||
if w.Layout != "" { | ||
found := false | ||
for _, l := range validLayouts { | ||
if l == w.Layout { | ||
found = true | ||
} | ||
} | ||
|
||
if !found { | ||
return fmt.Errorf("invalid layout '%s' in window '%s'", w.Layout, w.Name) | ||
} | ||
} | ||
} | ||
|
||
// check only on zoom in a window | ||
|
||
return nil | ||
} | ||
|
||
// Parse return a sessionConfig from a io.Reader | ||
func Parse(reader io.ReadCloser) (Session, error) { | ||
defer reader.Close() | ||
|
||
var conf Session | ||
if _, err := toml.DecodeReader(reader, &conf); err != nil { | ||
return conf, fmt.Errorf("parsing configuration: %v", err) | ||
} | ||
|
||
if err := checkValid(conf); err != nil { | ||
return conf, err | ||
} | ||
|
||
return conf, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,31 @@ | ||
package tmux | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os/exec" | ||
"strconv" | ||
"strings" | ||
var ( | ||
// DefaultRunner is the default tmux command runner | ||
DefaultRunner = &Runner{} | ||
) | ||
|
||
// Result is a commadn result | ||
type Result struct { | ||
Stdout string | ||
Stderr string | ||
} | ||
|
||
// Exec runs a tmux command | ||
func Exec(args ...string) (Result, error) { | ||
var stdin bytes.Buffer | ||
var stderr bytes.Buffer | ||
var stdout bytes.Buffer | ||
|
||
cmd := exec.Command("tmux", args...) | ||
cmd.Stdin = &stdin | ||
cmd.Stdout = &stdout | ||
cmd.Stderr = &stderr | ||
|
||
err := cmd.Run() | ||
if err != nil { | ||
return Result{}, fmt.Errorf("Error running command \"tmux %v\", %s", args, stderr.String()) | ||
} | ||
|
||
return Result{stdout.String(), stderr.String()}, nil | ||
return DefaultRunner.Exec(args...) | ||
} | ||
|
||
// SendKeys sends keys to tmux (e.g to run a command) | ||
func SendKeys(target, keys string) error { | ||
_, err := Exec("send-keys", "-R", "-t", target, keys, "C-m") | ||
return err | ||
return DefaultRunner.SendKeys(target, keys) | ||
} | ||
|
||
// SendRawKeys sends keys to tmux (e.g to run a command) | ||
func SendRawKeys(target, keys string) error { | ||
_, err := Exec("send-keys", "-R", "-t", target, keys) | ||
return err | ||
return DefaultRunner.SendRawKeys(target, keys) | ||
} | ||
|
||
// SessionInfo infos about a running tmux session | ||
type SessionInfo struct{} | ||
|
||
// ListSessions returns the list of sessions currently running | ||
func ListSessions() (map[string]SessionInfo, error) { | ||
sessionMap := make(map[string]SessionInfo) | ||
|
||
res, err := Exec("ls") | ||
if err != nil { | ||
if strings.Contains(err.Error(), "no server running on") { | ||
return sessionMap, nil | ||
} | ||
return sessionMap, fmt.Errorf("error listing sessions %v", err) | ||
} | ||
|
||
splits := strings.Split(res.Stdout, "\n") | ||
for _, sess := range splits { | ||
sessSplits := strings.Split(sess, ":") | ||
if len(sessSplits) > 1 { | ||
sessionMap[sessSplits[0]] = SessionInfo{} | ||
} | ||
} | ||
|
||
return sessionMap, nil | ||
} | ||
|
||
// Options tmux options | ||
type Options struct { | ||
BaseIndex int | ||
PaneBaseIndex int | ||
return DefaultRunner.ListSessions() | ||
} | ||
|
||
// GetOptions get tmux options | ||
func GetOptions() (*Options, error) { | ||
options := &Options{ | ||
BaseIndex: 0, | ||
PaneBaseIndex: 0, | ||
} | ||
|
||
var stderr bytes.Buffer | ||
var stdout bytes.Buffer | ||
cmd := exec.Command("sh", "-c", "tmux start-server\\; show-options -g\\; show-window-options -g") | ||
cmd.Stdout = &stdout | ||
|
||
err := cmd.Run() | ||
if err != nil { | ||
return options, fmt.Errorf("Error getting tmux options %v, %s", err, stderr.String()) | ||
} | ||
|
||
optionsString := strings.Split(stdout.String(), "\n") | ||
for _, option := range optionsString { | ||
optionSplits := strings.Split(option, " ") | ||
if len(optionSplits) == 2 { | ||
name := optionSplits[0] | ||
if name == "base-index" { | ||
if v, err := strconv.Atoi(optionSplits[1]); err == nil { | ||
options.BaseIndex = v | ||
} | ||
} else if name == "pane-base-index" { | ||
if v, err := strconv.Atoi(optionSplits[1]); err == nil { | ||
options.PaneBaseIndex = v | ||
} | ||
|
||
} | ||
} | ||
} | ||
|
||
return options, nil | ||
return DefaultRunner.GetOptions() | ||
} |
Oops, something went wrong.