Hilbish/readline/tokenise.go

185 lines
3.4 KiB
Go

package readline
import "strings"
// tokeniser - The input line must be splitted according to different rules (split between spaces, brackets, etc ?).
type tokeniser func(line []rune, cursorPos int) (split []string, index int, newPos int)
func tokeniseLine(line []rune, linePos int) ([]string, int, int) {
if len(line) == 0 {
return nil, 0, 0
}
var index, pos int
var punc bool
split := make([]string, 1)
for i, r := range line {
switch {
case (r >= 33 && 47 >= r) ||
(r >= 58 && 64 >= r) ||
(r >= 91 && 94 >= r) ||
r == 96 ||
(r >= 123 && 126 >= r):
if i > 0 && line[i-1] != r {
split = append(split, "")
}
split[len(split)-1] += string(r)
punc = true
case r == ' ' || r == '\t':
split[len(split)-1] += string(r)
punc = true
default:
if punc {
split = append(split, "")
}
split[len(split)-1] += string(r)
punc = false
}
if i == linePos {
index = len(split) - 1
pos = len(split[index]) - 1
}
}
// Hackish: if we are at the end of the line,
// currently appending to it, we return the pos
// as we would do when matching linePos
if linePos == len(line) {
if index == 0 {
index = len(split) - 1
}
if pos == 0 {
pos = len(split[index])
}
}
return split, index, pos
}
func tokeniseSplitSpaces(line []rune, linePos int) ([]string, int, int) {
if len(line) == 0 {
return nil, 0, 0
}
var index, pos int
split := make([]string, 1)
for i, r := range line {
switch {
case r == ' ' || r == '\t':
split[len(split)-1] += string(r)
default:
if i > 0 && (line[i-1] == ' ' || line[i-1] == '\t') {
split = append(split, "")
}
split[len(split)-1] += string(r)
}
if i == linePos {
index = len(split) - 1
pos = len(split[index]) - 1
}
}
return split, index, pos
}
func tokeniseBrackets(line []rune, linePos int) ([]string, int, int) {
var (
open, close rune
split []string
count int
pos = make(map[int]int)
match int
single, double bool
)
switch line[linePos] {
case '(', ')':
open = '('
close = ')'
case '{', '[':
open = line[linePos]
close = line[linePos] + 2
case '}', ']':
open = line[linePos] - 2
close = line[linePos]
default:
return nil, 0, 0
}
for i := range line {
switch line[i] {
case '\'':
if !single {
double = !double
}
case '"':
if !double {
single = !single
}
case open:
if !single && !double {
count++
pos[count] = i
if i == linePos {
match = count
split = []string{string(line[:i-1])}
}
} else if i == linePos {
return nil, 0, 0
}
case close:
if !single && !double {
if match == count {
split = append(split, string(line[pos[count]:i]))
return split, 1, 0
}
if i == linePos {
split = []string{
string(line[:pos[count]-1]),
string(line[pos[count]:i]),
}
return split, 1, len(split[1])
}
count--
} else if i == linePos {
return nil, 0, 0
}
}
}
return nil, 0, 0
}
func rTrimWhiteSpace(oldString string) (newString string) {
return strings.TrimRight(oldString, " ")
// TODO: support tab chars
/*defer fmt.Println(">" + oldString + "<" + newString + ">")
newString = oldString
for len(oldString) > 0 {
if newString[len(newString)-1] == ' ' || newString[len(newString)-1] == '\t' {
newString = newString[:len(newString)-1]
} else {
break
}
}
return*/
}