161 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			3.3 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 WordToLeft (text []rune, dot Dot) (length int) {
 | 
						|
	cursor := dot.End
 | 
						|
	if cursor < 1 { return }
 | 
						|
	if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
	index := cursor - 1
 | 
						|
	for index >= 0 && unicode.IsSpace(text[index]) {
 | 
						|
		length ++
 | 
						|
		index --
 | 
						|
	}
 | 
						|
	for index >= 0 && !unicode.IsSpace(text[index]) {
 | 
						|
		length ++
 | 
						|
		index --
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func WordToRight (text []rune, dot Dot) (length int) {
 | 
						|
	cursor := dot.End
 | 
						|
	if cursor < 0 { return }
 | 
						|
	if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
	index := cursor
 | 
						|
	for index < len(text) && unicode.IsSpace(text[index]) {
 | 
						|
		length ++
 | 
						|
		index ++
 | 
						|
	}
 | 
						|
	for index < len(text) && !unicode.IsSpace(text[index]) {
 | 
						|
		length ++
 | 
						|
		index ++
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func Backspace (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
 | 
						|
	if dot.Empty() {
 | 
						|
		cursor := dot.End
 | 
						|
		if cursor < 1         { return text, dot }
 | 
						|
		if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
		distance := 1
 | 
						|
		if word {
 | 
						|
			distance = WordToLeft(text, dot)
 | 
						|
		}
 | 
						|
		result = append(result, text[:cursor - distance]...)
 | 
						|
		result = append(result, text[cursor:]...)
 | 
						|
		moved = EmptyDot(cursor - distance)
 | 
						|
	} else {
 | 
						|
		return Delete(text, dot, word)
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func Delete (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
 | 
						|
	if dot.Empty() {
 | 
						|
		cursor := dot.End
 | 
						|
		if cursor < 0         { return text, dot }
 | 
						|
		if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
		distance := 1
 | 
						|
		if word {
 | 
						|
			distance = WordToRight(text, dot)
 | 
						|
		}
 | 
						|
		result = append(result, text[:cursor]...)
 | 
						|
		result = append(result, text[cursor + distance:]...)
 | 
						|
		moved = dot
 | 
						|
		return	
 | 
						|
	} else {
 | 
						|
		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) {
 | 
						|
	if dot.Empty() {
 | 
						|
		cursor := dot.End
 | 
						|
		if cursor < 0         { cursor = 0 }
 | 
						|
		if cursor > len(text) { cursor = len(text) }
 | 
						|
		result = append(result, text[:cursor]...)
 | 
						|
		result = append(result, character)
 | 
						|
		if cursor < len(text) {
 | 
						|
			result = append(result, text[cursor:]...)
 | 
						|
		}
 | 
						|
		moved = EmptyDot(cursor + 1)
 | 
						|
		return
 | 
						|
	} else {
 | 
						|
		result = append(result, text[:dot.Start]...)
 | 
						|
		result = append(result, character)
 | 
						|
		result = append(result, text[dot.End:]...)
 | 
						|
		moved = EmptyDot(dot.Start)
 | 
						|
		return
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func MoveLeft (text []rune, dot Dot, word bool) (moved Dot) {
 | 
						|
	cursor := dot.Start
 | 
						|
 | 
						|
	if cursor < 1         { return EmptyDot(cursor) }
 | 
						|
	if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
	distance := 1
 | 
						|
	if word {
 | 
						|
		distance = WordToLeft(text, dot)
 | 
						|
	}
 | 
						|
	moved = EmptyDot(cursor - distance)
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func MoveRight (text []rune, dot Dot, word bool) (moved Dot) {
 | 
						|
	cursor := dot.End
 | 
						|
	
 | 
						|
	if cursor < 0         { return EmptyDot(cursor) }
 | 
						|
	if cursor > len(text) { cursor = len(text) }
 | 
						|
 | 
						|
	distance := 1
 | 
						|
	if word {
 | 
						|
		distance = WordToRight(text, dot)
 | 
						|
	}
 | 
						|
	moved = EmptyDot(cursor + distance)
 | 
						|
	return
 | 
						|
}
 |