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  }