43 lines
1.1 KiB
Go
43 lines
1.1 KiB
Go
package braille
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Region is one semantic piece of a braille line. Cursor is a zero-based rune
|
|
// offset within Text, including the position just after the final rune.
|
|
type Region struct {
|
|
Text string
|
|
Cursor int
|
|
}
|
|
|
|
// Line follows Python Cthulhu's Line: regions are concatenated exactly as
|
|
// supplied and one region may own the visible cursor. A focus of -1 hides it.
|
|
type Line struct {
|
|
Regions []Region
|
|
Focus int
|
|
}
|
|
|
|
func (line Line) Frame() (Frame, error) {
|
|
if line.Focus < -1 || line.Focus >= len(line.Regions) {
|
|
return Frame{}, errors.New("invalid focused braille region")
|
|
}
|
|
var text strings.Builder
|
|
cursor := -1
|
|
position := 0
|
|
for index, region := range line.Regions {
|
|
length := utf8.RuneCountInString(region.Text)
|
|
if index == line.Focus {
|
|
if region.Cursor < 0 || region.Cursor > length {
|
|
return Frame{}, errors.New("invalid braille region cursor")
|
|
}
|
|
cursor = position + region.Cursor
|
|
}
|
|
text.WriteString(region.Text)
|
|
position += length
|
|
}
|
|
return Frame{Text: text.String(), Cursor: cursor}, nil
|
|
}
|