This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/textmanip/textmanip.go

189 lines
3.9 KiB
Go

package textmanip
import "unicode"
type Dot struct { Start, End int }
func EmptyDot (position int) Dot {
return Dot { position, position }
}
func (dot Dot) Canon () Dot {
if dot.Start > dot.End {
return Dot { dot.End, dot.Start }
} else {
return dot
}
}
func (dot Dot) Empty () bool {
return dot.Start == dot.End
}
func (dot Dot) Add (delta int) Dot {
return Dot {
dot.Start + delta,
dot.End + delta,
}
}
func (dot Dot) Sub (delta int) Dot {
return Dot {
dot.Start - delta,
dot.End - delta,
}
}
func (dot Dot) Constrain (length int) Dot {
if dot.Start < 0 { dot.Start = 0 }
if dot.Start > length { dot.Start = length}
if dot.End < 0 { dot.End = 0 }
if dot.End > length { dot.End = length}
return dot
}
func WordToLeft (text []rune, position int) (length int) {
if position < 1 { return }
if position > len(text) { position = len(text) }
index := position - 1
for index >= 0 && unicode.IsSpace(text[index]) {
length ++
index --
}
for index >= 0 && !unicode.IsSpace(text[index]) {
length ++
index --
}
return
}
func WordToRight (text []rune, position int) (length int) {
if position < 0 { return }
if position > len(text) { position = len(text) }
index := position
for index < len(text) && unicode.IsSpace(text[index]) {
length ++
index ++
}
for index < len(text) && !unicode.IsSpace(text[index]) {
length ++
index ++
}
return
}
func WordAround (text []rune, position int) (around Dot) {
return Dot {
WordToLeft(text, position),
WordToRight(text, position),
}
}
func Backspace (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
dot = dot.Constrain(len(text))
if dot.Empty() {
distance := 1
if word {
distance = WordToLeft(text, dot.End)
}
result = append (
result,
text[:dot.Sub(distance).Constrain(len(text)).End]...)
result = append(result, text[dot.End:]...)
moved = EmptyDot(dot.Sub(distance).Start)
return
} else {
return Delete(text, dot, word)
}
}
func Delete (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
dot = dot.Constrain(len(text))
if dot.Empty() {
distance := 1
if word {
distance = WordToRight(text, dot.End)
}
result = append(result, text[:dot.End]...)
result = append (
result,
text[dot.Add(distance).Constrain(len(text)).End:]...)
moved = dot
return
} else {
dot = dot.Canon()
result = append(result, text[:dot.Start]...)
result = append(result, text[dot.End:]...)
moved = EmptyDot(dot.Start)
return
}
}
func Type (text []rune, dot Dot, character rune) (result []rune, moved Dot) {
dot = dot.Constrain(len(text))
if dot.Empty() {
result = append(result, text[:dot.End]...)
result = append(result, character)
if dot.End < len(text) {
result = append(result, text[dot.End:]...)
}
moved = EmptyDot(dot.Add(1).End)
return
} else {
dot = dot.Canon()
result = append(result, text[:dot.Start]...)
result = append(result, character)
result = append(result, text[dot.End:]...)
moved = EmptyDot(dot.Add(1).Start)
return
}
}
func MoveLeft (text []rune, dot Dot, word bool) (moved Dot) {
dot = dot.Canon().Constrain(len(text))
distance := 0
if dot.Empty() {
distance = 1
}
if word {
distance = WordToLeft(text, dot.Start)
}
moved = EmptyDot(dot.Sub(distance).Start)
return
}
func MoveRight (text []rune, dot Dot, word bool) (moved Dot) {
dot = dot.Canon().Constrain(len(text))
distance := 0
if dot.Empty() {
distance = 1
}
if word {
distance = WordToRight(text, dot.End)
}
moved = EmptyDot(dot.Add(distance).End)
return
}
func SelectLeft (text []rune, dot Dot, word bool) (moved Dot) {
dot = dot.Constrain(len(text))
distance := 1
if word {
distance = WordToLeft(text, dot.Start)
}
dot.Start -= distance
return dot
}
func SelectRight (text []rune, dot Dot, word bool) (moved Dot) {
dot = dot.Constrain(len(text))
distance := 1
if word {
distance = WordToRight(text, dot.End)
}
dot.Start += distance
return dot
}