diff --git a/options.go b/options.go new file mode 100644 index 0000000..42221c9 --- /dev/null +++ b/options.go @@ -0,0 +1,3 @@ +package tmux + +type Options map[string]string diff --git a/options_scope.go b/scope.go similarity index 59% rename from options_scope.go rename to scope.go index da659cf..5955347 100644 --- a/options_scope.go +++ b/scope.go @@ -1,21 +1,21 @@ package tmux -// OptionsScope represents one of the five scopes that Tmux holds options +// Scope represents one of the five scopes that Tmux holds options // within. -type OptionsScope int +type Scope int const ( - Server OptionsScope = iota + 1 + Server Scope = iota + 1 GlobalSession Session GlobalWindow Window ) -// OptionsScopeFlags converts a given OptionsScope to the command line flags +// ScopeToFlags converts a given OptionsScope to the command line flags // needed to restrict "set-option" and "show-options" commands to the scope in // question. -func OptionsScopeFlags(scope OptionsScope) string { +func ScopeToFlags(scope Scope) string { switch scope { case 0, Session: return "" diff --git a/options_scope_test.go b/scope_test.go similarity index 70% rename from options_scope_test.go rename to scope_test.go index 4a69c4e..99b22ef 100644 --- a/options_scope_test.go +++ b/scope_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" ) -func TestOptionsScopeFlags(t *testing.T) { +func TestScopeToFlags(t *testing.T) { tests := []struct { - scope OptionsScope + scope Scope flags string }{ {0, ""}, @@ -22,6 +22,6 @@ func TestOptionsScopeFlags(t *testing.T) { } for _, tt := range tests { - assert.Equal(t, tt.flags, OptionsScopeFlags(tt.scope)) + assert.Equal(t, tt.flags, ScopeToFlags(tt.scope)) } } diff --git a/tmux.go b/tmux.go index 88fa28a..d956a1d 100644 --- a/tmux.go +++ b/tmux.go @@ -4,10 +4,10 @@ import ( "bufio" "bytes" "regexp" + "strconv" ) var optMatcher = regexp.MustCompile(`^\s*([@\w-][\w-]+)\s+(.*)$`) -var quote = []byte(`"`) // Tmux enables easily running tmux commands. type Tmux struct { @@ -49,8 +49,10 @@ func (s *Tmux) Args() []string { return args } -func (s *Tmux) GetOptions(scope OptionsScope) (map[string]string, error) { - out, err := s.Exec("show-options", OptionsScopeFlags(scope)) +// GetOptions uses the "show-options" command to get all options within given +// SCOPE. +func (s *Tmux) GetOptions(scope Scope) (Options, error) { + out, err := s.Exec("show-options", ScopeToFlags(scope)) if err != nil { return nil, err } @@ -58,24 +60,24 @@ func (s *Tmux) GetOptions(scope OptionsScope) (map[string]string, error) { return s.parseOptions(out), nil } -func (s *Tmux) parseOptions(options []byte) map[string]string { +func (s *Tmux) parseOptions(options []byte) Options { scanner := bufio.NewScanner(bytes.NewBuffer(options)) - result := map[string]string{} + result := Options{} for scanner.Scan() { match := optMatcher.FindSubmatch(scanner.Bytes()) if len(match) > 2 { - result[string(match[1])] = string(s.unwrap(match[2], quote)) + key := string(match[1]) + val := string(match[2]) + + unquoted, err := strconv.Unquote(val) + if err == nil { + result[key] = unquoted + } else { + result[key] = val + } } } return result } - -func (s *Tmux) unwrap(input, wrap []byte) []byte { - if bytes.HasPrefix(input, wrap) && bytes.HasSuffix(input, wrap) { - return bytes.TrimSuffix(bytes.TrimPrefix(input, wrap), wrap) - } - - return input -} diff --git a/tmux_test.go b/tmux_test.go index e634451..c21d351 100644 --- a/tmux_test.go +++ b/tmux_test.go @@ -152,49 +152,57 @@ func TestTmuxArgs(t *testing.T) { func TestTmuxGetOptions(t *testing.T) { tests := []struct { flags string - scope OptionsScope - opts map[string]string + scope Scope + opts Options out []byte error error }{ { - opts: map[string]string{"hello-world": "FooBar"}, + opts: Options{"hello-world": "FooBar"}, out: []byte(`hello-world FooBar`), }, { scope: Server, flags: "-s", - opts: map[string]string{"hello-world": "Foo Bar"}, + opts: Options{"hello-world": "Foo Bar"}, out: []byte(`hello-world "Foo Bar"`), }, { scope: GlobalSession, flags: "-g", - opts: map[string]string{"hello-world": "Foo Bar"}, + opts: Options{"hello-world": "Foo Bar"}, out: []byte(`hello-world "Foo Bar"`), }, { scope: GlobalWindow, flags: "-gw", - opts: map[string]string{"hello-world": " Foo Bar "}, + opts: Options{"hello-world": " Foo Bar "}, out: []byte(`hello-world " Foo Bar "`), }, { scope: Window, flags: "-w", - opts: map[string]string{"@foo": "bar"}, + opts: Options{"@foo": "bar"}, out: []byte(`@foo bar`), }, { - opts: map[string]string{ - "@foo": "bar", - "@themepack": "powerline/default/green", - "status-left": "This Is Left", + scope: Window, + flags: "-w", + opts: Options{"status-left": "\"#H\" >>"}, + out: []byte(`status-left "\"#H\" >>"`), + }, + { + opts: Options{ + "@foo": "bar", + "@themepack": "powerline/default/green", + "status-left": "This Is Left", + "status-right": "\"#H\" >>", }, out: []byte(` @foo bar @themepack "powerline/default/green" status-left This Is Left +status-right "\"#H\" >>" `), }, }