github.com/xiaq/elvish@v0.12.0/styled/text.go (about) 1 package styled 2 3 import ( 4 "bytes" 5 "fmt" 6 "strconv" 7 8 "github.com/elves/elvish/eval/vals" 9 ) 10 11 // Text contains of a list of styled Segments. 12 type Text []Segment 13 14 func (t Text) Kind() string { return "styled-text" } 15 16 // Repr returns the representation of the current Text. It is just a wrapper 17 // around the containing Segments. 18 func (t Text) Repr(indent int) string { 19 buf := new(bytes.Buffer) 20 for _, s := range t { 21 buf.WriteString(s.Repr(indent + 1)) 22 } 23 return fmt.Sprintf("(styled %s)", buf.String()) 24 } 25 26 func (t Text) IterateKeys(fn func(interface{}) bool) { 27 for i := 0; i < len(t); i++ { 28 if !fn(strconv.Itoa(i)) { 29 break 30 } 31 } 32 } 33 34 // Index provides access to the underlying Segments. 35 func (t Text) Index(k interface{}) (interface{}, error) { 36 index, err := vals.ConvertListIndex(k, len(t)) 37 if err != nil { 38 return nil, err 39 } else if index.Slice { 40 return t[index.Lower:index.Upper], nil 41 } else { 42 return t[index.Lower], nil 43 } 44 } 45 46 // Concat implements Text+string, Text+Segment and Text+Text. 47 func (t Text) Concat(v interface{}) (interface{}, error) { 48 switch rhs := v.(type) { 49 case string: 50 return Text(append(t, Segment{Text: rhs})), nil 51 case *Segment: 52 return Text(append(t, *rhs)), nil 53 case *Text: 54 return Text(append(t, *rhs...)), nil 55 } 56 57 return nil, vals.ErrConcatNotImplemented 58 } 59 60 // RConcat implements string+Text. 61 func (t Text) RConcat(v interface{}) (interface{}, error) { 62 switch lhs := v.(type) { 63 case string: 64 return Text(append([]Segment{{Text: lhs}}, t...)), nil 65 } 66 67 return nil, vals.ErrConcatNotImplemented 68 } 69 70 // Partition partitions the Text at n indicies into n+1 Text values. 71 func (t Text) Partition(indicies ...int) []Text { 72 out := make([]Text, len(indicies)+1) 73 segs := t 74 consumedSegsLen := 0 75 seg0Consumed := 0 76 for i, idx := range indicies { 77 text := make(Text, 0) 78 for len(segs) > 0 && idx >= consumedSegsLen+len(segs[0].Text) { 79 text = append(text, Segment{ 80 segs[0].Style, segs[0].Text[seg0Consumed:]}) 81 consumedSegsLen += len(segs[0].Text) 82 seg0Consumed = 0 83 segs = segs[1:] 84 } 85 if len(segs) > 0 && idx > consumedSegsLen { 86 text = append(text, Segment{ 87 segs[0].Style, segs[0].Text[:idx-consumedSegsLen]}) 88 seg0Consumed = idx - consumedSegsLen 89 } 90 out[i] = text 91 } 92 trailing := make(Text, 0) 93 for len(segs) > 0 { 94 trailing = append(trailing, Segment{ 95 segs[0].Style, segs[0].Text[seg0Consumed:]}) 96 seg0Consumed = 0 97 segs = segs[1:] 98 } 99 out[len(indicies)] = trailing 100 return out 101 }