You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
2.3 KiB
Go

package shell
import (
"io"
"log"
"regexp"
"strings"
)
func NewWord(wordS string) *Word {
word := new(Word)
for _, c := range wordS {
word.AddToken(Char(c))
}
return word
}
type Word struct {
chars []Char
consecutiveBackslashes int
}
func (w *Word) Tokens() []Token {
return []Token{}
}
func (w *Word) AddToken(token Token) {
if char, ok := token.(Char); ok {
if rune(char) == '\\' {
w.consecutiveBackslashes += 1
} else if w.consecutiveBackslashes%2 == 1 {
if len(w.chars) > 0 {
w.chars = w.chars[:len(w.chars)-1]
} else {
log.Println(
"Parse error: funky shit is happening, a word with 0" +
" chars was expected to contain a backslash",
)
}
w.consecutiveBackslashes = 0
}
w.chars = append(w.chars, char)
}
}
func (w *Word) Expand(_ State, _ io.Reader, _ io.Writer) ([]string, uint8) {
var str string
for _, char := range w.chars {
str += string(char)
}
return []string{str}, 0
}
func (w *Word) String() string {
str, _ := w.Expand(nil, nil, nil)
return strings.Join(str, "")
}
type WordParameters struct{}
func (p *WordParameters) MakeToken() Token {
return new(Word)
}
var wordRegexp = regexp.MustCompile("[0-9a-zA-Z_.~/:\\\\=-]")
func (p *WordParameters) Supports(charsBefore []rune, r rune) bool {
return wordRegexp.MatchString(string(r))
}
func (p *WordParameters) ShouldLeave(charsBefore []rune, r rune) bool {
if !p.Supports(charsBefore, r) {
return countBackslashSuffixes(charsBefore)%2 == 0
}
return false
}
func (p *WordParameters) Leave(i *CharIterator) error {
return i.Previous()
}
func (p *WordParameters) SubParsers() []Parser {
return []Parser{
&BaseParser{
parameters: &CharParserParameters{},
},
}
}
type Char rune
func (c Char) Tokens() []Token {
return nil
}
func (c Char) AddToken(_ Token) {}
func (c Char) String() string {
return string(c)
}
type CharParserParameters struct {
currentRune rune
}
func (p *CharParserParameters) MakeToken() Token {
return Char(p.currentRune)
}
func (p *CharParserParameters) Supports(charsBefore []rune, r rune) bool {
p.currentRune = r
return true
}
func (p *CharParserParameters) ShouldLeave(charsBefore []rune, r rune) bool {
return true
}
func (p *CharParserParameters) SubParsers() []Parser {
return nil
}