package shell import ( "io" "log" ) type DollarParameters struct { ignoreParams *IgnoreFirstCharParameters } func (p *DollarParameters) SubParsers() []Parser { if p.ignoreParams == nil { p.ignoreParams = &IgnoreFirstCharParameters{} } return []Parser{ &BaseParser{ parameters: p.ignoreParams, }, &BaseParser{ parameters: &WordParameters{}, }, &BaseParser{ parameters: &SubshellParameters{}, }, &BaseParser{ parameters: &DollarBlockParameters{}, }, } } func (p *DollarParameters) Enter(_ *CharIterator) error { if p.ignoreParams != nil { p.ignoreParams.Reset() } return nil } func (p *DollarParameters) Supports(charsBefore []rune, r rune) bool { if r == '$' { return len(charsBefore) == 0 || countBackslashSuffixes(charsBefore)%2 == 0 } return false } func (p *DollarParameters) ShouldLeave(charsBefore []rune, r rune) bool { if isWhitespace(r) || r == ';' { return true } return false } func (p *DollarParameters) Leave(i *CharIterator) error { return i.Previous() } func (p *DollarParameters) MakeToken() Token { return &Dollar{} } type Dollar struct { BaseToken } func (d *Dollar) Expand(state State, stdin io.Reader, stderr io.Writer) ([]string, uint8) { if len(d.tokens) > 1 { logstr := "Unexpected tokens after dollar sign: " + d.tokens[1].String() log.Println(logstr) stderr.Write([]byte(logstr)) return []string{""}, 2 } if word, ok := d.tokens[0].(*Word); ok { return []string{state.Variable(word.String())}, 0 } else if block, ok := d.tokens[0].(*DollarBlock); ok && len(block.Tokens()) > 0 { if word, ok := block.Tokens()[0].(*Word); ok { return []string{state.Variable(word.String())}, 0 } else { log.Println("Whaat") } } else { logstr := "Unexpected tokens after dollar sign: " + d.String() log.Println(logstr) stderr.Write([]byte(logstr)) return []string{""}, 2 } return []string{""}, 1 } type IgnoreFirstCharParameters struct { entered bool } func (p *IgnoreFirstCharParameters) Reset() { p.entered = false } func (p *IgnoreFirstCharParameters) Enter(_ *CharIterator) error { p.entered = true return nil } func (p *IgnoreFirstCharParameters) SubParsers() []Parser { return []Parser{ &BaseParser{ parameters: &CharParserParameters{}, }, } } func (p *IgnoreFirstCharParameters) MakeToken() Token { return nil } func (p *IgnoreFirstCharParameters) Supports(_ []rune, r rune) bool { if !p.entered { return true } return false } func (p *IgnoreFirstCharParameters) ShouldLeave(_ []rune, r rune) bool { return true }