...

Source file src/github.com/yuin/goldmark/text/segment.go

Documentation: github.com/yuin/goldmark/text

     1  package text
     2  
     3  import (
     4  	"bytes"
     5  	"github.com/yuin/goldmark/util"
     6  )
     7  
     8  var space = []byte(" ")
     9  
    10  // A Segment struct holds information about source positions.
    11  type Segment struct {
    12  	// Start is a start position of the segment.
    13  	Start int
    14  
    15  	// Stop is a stop position of the segment.
    16  	// This value should be excluded.
    17  	Stop int
    18  
    19  	// Padding is a padding length of the segment.
    20  	Padding int
    21  }
    22  
    23  // NewSegment return a new Segment.
    24  func NewSegment(start, stop int) Segment {
    25  	return Segment{
    26  		Start:   start,
    27  		Stop:    stop,
    28  		Padding: 0,
    29  	}
    30  }
    31  
    32  // NewSegmentPadding returns a new Segment with the given padding.
    33  func NewSegmentPadding(start, stop, n int) Segment {
    34  	return Segment{
    35  		Start:   start,
    36  		Stop:    stop,
    37  		Padding: n,
    38  	}
    39  }
    40  
    41  // Value returns a value of the segment.
    42  func (t *Segment) Value(buffer []byte) []byte {
    43  	if t.Padding == 0 {
    44  		return buffer[t.Start:t.Stop]
    45  	}
    46  	result := make([]byte, 0, t.Padding+t.Stop-t.Start+1)
    47  	result = append(result, bytes.Repeat(space, t.Padding)...)
    48  	return append(result, buffer[t.Start:t.Stop]...)
    49  }
    50  
    51  // Len returns a length of the segment.
    52  func (t *Segment) Len() int {
    53  	return t.Stop - t.Start + t.Padding
    54  }
    55  
    56  // Between returns a segment between this segment and the given segment.
    57  func (t *Segment) Between(other Segment) Segment {
    58  	if t.Stop != other.Stop {
    59  		panic("invalid state")
    60  	}
    61  	return NewSegmentPadding(
    62  		t.Start,
    63  		other.Start,
    64  		t.Padding-other.Padding,
    65  	)
    66  }
    67  
    68  // IsEmpty returns true if this segment is empty, otherwise false.
    69  func (t *Segment) IsEmpty() bool {
    70  	return t.Start >= t.Stop && t.Padding == 0
    71  }
    72  
    73  // TrimRightSpace returns a new segment by slicing off all trailing
    74  // space characters.
    75  func (t *Segment) TrimRightSpace(buffer []byte) Segment {
    76  	v := buffer[t.Start:t.Stop]
    77  	l := util.TrimRightSpaceLength(v)
    78  	if l == len(v) {
    79  		return NewSegment(t.Start, t.Start)
    80  	}
    81  	return NewSegmentPadding(t.Start, t.Stop-l, t.Padding)
    82  }
    83  
    84  // TrimLeftSpace returns a new segment by slicing off all leading
    85  // space characters including padding.
    86  func (t *Segment) TrimLeftSpace(buffer []byte) Segment {
    87  	v := buffer[t.Start:t.Stop]
    88  	l := util.TrimLeftSpaceLength(v)
    89  	return NewSegment(t.Start+l, t.Stop)
    90  }
    91  
    92  // TrimLeftSpaceWidth returns a new segment by slicing off leading space
    93  // characters until the given width.
    94  func (t *Segment) TrimLeftSpaceWidth(width int, buffer []byte) Segment {
    95  	padding := t.Padding
    96  	for ; width > 0; width-- {
    97  		if padding == 0 {
    98  			break
    99  		}
   100  		padding--
   101  	}
   102  	if width == 0 {
   103  		return NewSegmentPadding(t.Start, t.Stop, padding)
   104  	}
   105  	text := buffer[t.Start:t.Stop]
   106  	start := t.Start
   107  	for _, c := range text {
   108  		if start >= t.Stop-1 || width <= 0 {
   109  			break
   110  		}
   111  		if c == ' ' {
   112  			width--
   113  		} else if c == '\t' {
   114  			width -= 4
   115  		} else {
   116  			break
   117  		}
   118  		start++
   119  	}
   120  	if width < 0 {
   121  		padding = width * -1
   122  	}
   123  	return NewSegmentPadding(start, t.Stop, padding)
   124  }
   125  
   126  // WithStart returns a new Segment with same value except Start.
   127  func (t *Segment) WithStart(v int) Segment {
   128  	return NewSegmentPadding(v, t.Stop, t.Padding)
   129  }
   130  
   131  // WithStop returns a new Segment with same value except Stop.
   132  func (t *Segment) WithStop(v int) Segment {
   133  	return NewSegmentPadding(t.Start, v, t.Padding)
   134  }
   135  
   136  // ConcatPadding concats the padding to the given slice.
   137  func (t *Segment) ConcatPadding(v []byte) []byte {
   138  	if t.Padding > 0 {
   139  		return append(v, bytes.Repeat(space, t.Padding)...)
   140  	}
   141  	return v
   142  }
   143  
   144  // Segments is a collection of the Segment.
   145  type Segments struct {
   146  	values []Segment
   147  }
   148  
   149  // NewSegments return a new Segments.
   150  func NewSegments() *Segments {
   151  	return &Segments{
   152  		values: nil,
   153  	}
   154  }
   155  
   156  // Append appends the given segment after the tail of the collection.
   157  func (s *Segments) Append(t Segment) {
   158  	if s.values == nil {
   159  		s.values = make([]Segment, 0, 20)
   160  	}
   161  	s.values = append(s.values, t)
   162  }
   163  
   164  // AppendAll appends all elements of given segments after the tail of the collection.
   165  func (s *Segments) AppendAll(t []Segment) {
   166  	if s.values == nil {
   167  		s.values = make([]Segment, 0, 20)
   168  	}
   169  	s.values = append(s.values, t...)
   170  }
   171  
   172  // Len returns the length of the collection.
   173  func (s *Segments) Len() int {
   174  	if s.values == nil {
   175  		return 0
   176  	}
   177  	return len(s.values)
   178  }
   179  
   180  // At returns a segment at the given index.
   181  func (s *Segments) At(i int) Segment {
   182  	return s.values[i]
   183  }
   184  
   185  // Set sets the given Segment.
   186  func (s *Segments) Set(i int, v Segment) {
   187  	s.values[i] = v
   188  }
   189  
   190  // SetSliced replace the collection with a subsliced value.
   191  func (s *Segments) SetSliced(lo, hi int) {
   192  	s.values = s.values[lo:hi]
   193  }
   194  
   195  // Sliced returns a subslice of the collection.
   196  func (s *Segments) Sliced(lo, hi int) []Segment {
   197  	return s.values[lo:hi]
   198  }
   199  
   200  // Clear delete all element of the collection.
   201  func (s *Segments) Clear() {
   202  	s.values = nil
   203  }
   204  
   205  // Unshift insert the given Segment to head of the collection.
   206  func (s *Segments) Unshift(v Segment) {
   207  	s.values = append(s.values[0:1], s.values[0:]...)
   208  	s.values[0] = v
   209  }
   210  

View as plain text