Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ParseComment option to trim comments #58

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ args, err := p.Parse("./foo `echo $SHELL`")
// args should be ["./foo", "/bin/bash"]
```

```go
p := shellwords.NewParser()
p.ParseComment = true
args, err := p.Parse("./foo # comment")
// args should be ["./foo"]
```

# Thanks

This is based on cpan module [Parse::CommandLine](https://metacpan.org/pod/Parse::CommandLine).
Expand Down
18 changes: 17 additions & 1 deletion shellwords.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
var (
ParseEnv bool = false
ParseBacktick bool = false
ParseComment bool = false
)

func isSpace(r rune) bool {
Expand Down Expand Up @@ -97,6 +98,7 @@ func replaceEnv(getenv func(string) string, s string) string {
type Parser struct {
ParseEnv bool
ParseBacktick bool
ParseComment bool
Position int
Dir string

Expand All @@ -109,6 +111,7 @@ func NewParser() *Parser {
return &Parser{
ParseEnv: ParseEnv,
ParseBacktick: ParseBacktick,
ParseComment: ParseComment,
Position: 0,
Dir: "",
}
Expand All @@ -125,7 +128,7 @@ const (
func (p *Parser) Parse(line string) ([]string, error) {
args := []string{}
buf := ""
var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool
var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote, comment bool
backtick := ""

pos := -1
Expand All @@ -135,6 +138,14 @@ func (p *Parser) Parse(line string) ([]string, error) {
loop:
for _, r := range line {
i++

if comment {
if r == '\n' {
comment = false
}
continue
}

if escaped {
if r == 't' {
r = '\t'
Expand Down Expand Up @@ -254,6 +265,11 @@ loop:
pos = i
break loop
}
case '#':
if p.ParseComment && len(buf) == 0 && !(escaped || singleQuoted || doubleQuoted) {
comment = true
continue loop
}
}

got = argSingle
Expand Down
30 changes: 28 additions & 2 deletions shellwords_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"testing"
)

var testcases = []struct {
type testcase struct {
line string
expected []string
}{
}

var testcases = []testcase{
{``, []string{}},
{`""`, []string{``}},
{`''`, []string{``}},
Expand Down Expand Up @@ -53,6 +55,30 @@ func TestSimple(t *testing.T) {
}
}

func TestComment(t *testing.T) {
allCases := append(testcases, []testcase{
{"# comment", []string{}},
{"foo not#comment", []string{"foo", "not#comment"}},
{`foo "bar # baz" # comment`, []string{"foo", "bar # baz"}},
{"foo \"bar # baz\" # comment\nfoo\nbar # baz",
[]string{"foo", "bar # baz", "foo", "bar"}},
{"echo '# list all files' # line\\ncomment\n# whole line comment\nls -al '#' # more comment",
[]string{"echo", "# list all files", "ls", "-al", "#"}},
}...)

parser := NewParser()
parser.ParseComment = true
for _, testcase := range allCases {
args, err := parser.Parse(testcase.line)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(args, testcase.expected) {
t.Fatalf("Expected %#v for %q, but %#v:", testcase.expected, testcase.line, args)
}
}
}

func TestError(t *testing.T) {
_, err := Parse("foo '")
if err == nil {
Expand Down