|
|
package readline
import ( "bytes" "unicode" "unicode/utf8" )
var runes = Runes{} var TabWidth = 4
type Runes struct{}
func (Runes) EqualRune(a, b rune, fold bool) bool { if a == b { return true } if !fold { return false } if a > b { a, b = b, a } if b < utf8.RuneSelf && 'A' <= a && a <= 'Z' { if b == a+'a'-'A' { return true } } return false }
func (r Runes) EqualRuneFold(a, b rune) bool { return r.EqualRune(a, b, true) }
func (r Runes) EqualFold(a, b []rune) bool { if len(a) != len(b) { return false } for i := 0; i < len(a); i++ { if r.EqualRuneFold(a[i], b[i]) { continue } return false }
return true }
func (Runes) Equal(a, b []rune) bool { if len(a) != len(b) { return false } for i := 0; i < len(a); i++ { if a[i] != b[i] { return false } } return true }
func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int { for i := len(r) - len(sub); i >= 0; i-- { found := true for j := 0; j < len(sub); j++ { if !rs.EqualRune(r[i+j], sub[j], fold) { found = false break } } if found { return i } } return -1 }
// Search in runes from end to front
func (rs Runes) IndexAllBck(r, sub []rune) int { return rs.IndexAllBckEx(r, sub, false) }
// Search in runes from front to end
func (rs Runes) IndexAll(r, sub []rune) int { return rs.IndexAllEx(r, sub, false) }
func (rs Runes) IndexAllEx(r, sub []rune, fold bool) int { for i := 0; i < len(r); i++ { found := true if len(r[i:]) < len(sub) { return -1 } for j := 0; j < len(sub); j++ { if !rs.EqualRune(r[i+j], sub[j], fold) { found = false break } } if found { return i } } return -1 }
func (Runes) Index(r rune, rs []rune) int { for i := 0; i < len(rs); i++ { if rs[i] == r { return i } } return -1 }
func (Runes) ColorFilter(r []rune) []rune { newr := make([]rune, 0, len(r)) for pos := 0; pos < len(r); pos++ { if r[pos] == '\033' && r[pos+1] == '[' { idx := runes.Index('m', r[pos+2:]) if idx == -1 { continue } pos += idx + 2 continue } newr = append(newr, r[pos]) } return newr }
var zeroWidth = []*unicode.RangeTable{ unicode.Mn, unicode.Me, unicode.Cc, unicode.Cf, }
var doubleWidth = []*unicode.RangeTable{ unicode.Han, unicode.Hangul, unicode.Hiragana, unicode.Katakana, }
func (Runes) Width(r rune) int { if r == '\t' { return TabWidth } if unicode.IsOneOf(zeroWidth, r) { return 0 } if unicode.IsOneOf(doubleWidth, r) { return 2 } return 1 }
func (Runes) WidthAll(r []rune) (length int) { for i := 0; i < len(r); i++ { length += runes.Width(r[i]) } return }
func (Runes) Backspace(r []rune) []byte { return bytes.Repeat([]byte{'\b'}, runes.WidthAll(r)) }
func (Runes) Copy(r []rune) []rune { n := make([]rune, len(r)) copy(n, r) return n }
func (Runes) HasPrefixFold(r, prefix []rune) bool { if len(r) < len(prefix) { return false } return runes.EqualFold(r[:len(prefix)], prefix) }
func (Runes) HasPrefix(r, prefix []rune) bool { if len(r) < len(prefix) { return false } return runes.Equal(r[:len(prefix)], prefix) }
func (Runes) Aggregate(candicate [][]rune) (same []rune, size int) { for i := 0; i < len(candicate[0]); i++ { for j := 0; j < len(candicate)-1; j++ { if i >= len(candicate[j]) || i >= len(candicate[j+1]) { goto aggregate } if candicate[j][i] != candicate[j+1][i] { goto aggregate } } size = i + 1 } aggregate: if size > 0 { same = runes.Copy(candicate[0][:size]) for i := 0; i < len(candicate); i++ { n := runes.Copy(candicate[i]) copy(n, n[size:]) candicate[i] = n[:len(n)-size] } } return }
func (Runes) TrimSpaceLeft(in []rune) []rune { firstIndex := len(in) for i, r := range in { if unicode.IsSpace(r) == false { firstIndex = i break } } return in[firstIndex:] }
|