fix: Parsing of double quoted options

This commit is contained in:
2019-12-09 21:46:01 +00:00
parent bb1d544f43
commit 048455a6bc
5 changed files with 46 additions and 33 deletions

3
options.go Normal file
View File

@@ -0,0 +1,3 @@
package tmux
type Options map[string]string

View File

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

View File

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

30
tmux.go
View File

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

View File

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