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 }