mirror of https://github.com/Hilbis/Hilbish
185 lines
3.4 KiB
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*/
|
||
|
}
|