Skip to content

Commit

Permalink
Merge pull request #14 from a8m/feat/escape
Browse files Browse the repository at this point in the history
parse: add support for escaping expressions
  • Loading branch information
a8m authored Sep 14, 2018
2 parents 7e664e3 + 309c6cb commit 41dec24
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 8 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ func main() {
|__Expression__ | __Meaning__ |
| ----------------- | -------------- |
|`${var}` | Value of var (same as `$var`)
|`${var}` | Value of var (same as `$var`)
|`${var-$DEFAULT}` | If var not set, evaluate expression as $DEFAULT
|`${var:-$DEFAULT}` | If var not set or is empty, evaluate expression as $DEFAULT
|`${var=$DEFAULT}` | If var not set, evaluate expression as $DEFAULT
|`${var:=$DEFAULT}` | If var not set or is empty, evaluate expression as $DEFAULT
|`${var+$OTHER}` | If var set, evaluate expression as $OTHER, otherwise as empty string
|`${var+$OTHER}` | If var set, evaluate expression as $OTHER, otherwise as empty string
|`${var:+$OTHER}` | If var set, evaluate expression as $OTHER, otherwise as empty string
<sub>table taken from [here](http://www.tldp.org/LDP/abs/html/refcards.html#AEN22728)</sub>
|`$$var` | Escape expressions. Result will be `$var`.

<sub>Most of the rows in this table were taken from [here](http://www.tldp.org/LDP/abs/html/refcards.html#AEN22728)</sub>

### See also

Expand Down
15 changes: 11 additions & 4 deletions parse/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,24 @@ Loop:
switch r := l.next(); r {
case '$':
l.pos--
// emit the text we've found until here, if any.
if l.pos > l.start {
l.emit(itemText)
}
l.pos++
if r := l.next(); isAlphaNumeric(r) {
l.backup()
return lexVariable
} else if r == '{' {
switch r := l.peek(); {
case r == '$':
// ignore the previous '$'.
l.ignore()
l.next()
l.emit(itemText)
case r == '{':
l.next()
l.subsDepth++
l.emit(itemLeftDelim)
return lexSubstitution
case isAlphaNumeric(r):
return lexVariable
}
case eof:
break Loop
Expand Down
14 changes: 13 additions & 1 deletion parse/lex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,25 @@ var lexTests = []lexTest{
{itemVariable, 0, "world"},
{itemError, 0, "closing brace expected"},
}},
{"escaping $$var", "hello $$HOME", []item{
{itemText, 0, "hello "},
{itemText, 7, "$"},
{itemText, 8, "HOME"},
tEOF,
}},
{"escaping $${subst}", "hello $${HOME}", []item{
{itemText, 0, "hello "},
{itemText, 7, "$"},
{itemText, 8, "{HOME}"},
tEOF,
}},
}

func TestLex(t *testing.T) {
for _, test := range lexTests {
items := collect(&test)
if !equal(items, test.items, false) {
t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items)
t.Errorf("%s:\ninput\n\t%q\ngot\n\t%+v\nexpected\n\t%v", test.name, test.input, items, test.items)
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions parse/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ var parseTests = []parseTest{
{"$var and $DEFAULT empty :=", "${EMPTY:=$ALSO_EMPTY}", "", errEmpty},
{"$var and $OTHER empty +", "${EMPTY+$ALSO_EMPTY}", "", errEmpty},
{"$var and $OTHER empty :+", "${EMPTY:+$ALSO_EMPTY}", "", errEmpty},

// escaping.
{"escape $$var", "FOO $$BAR BAZ", "FOO $BAR BAZ", errNone},
{"escape $${subst}", "FOO $${BAR} BAZ", "FOO ${BAR} BAZ", errNone},
{"escape $$$var", "$$$BAR", "$bar", errNone},
{"escape $$${subst}", "$$${BAZ:-baz}", "$baz", errNone},
}

func TestParse(t *testing.T) {
Expand Down

0 comments on commit 41dec24

Please sign in to comment.