github.com/charmbracelet/glamour@v0.7.0/ansi/blockstack.go (about)

     1  package ansi
     2  
     3  import (
     4  	"bytes"
     5  )
     6  
     7  // BlockStack is a stack of block elements, used to calculate the current
     8  // indentation & margin level during the rendering process.
     9  type BlockStack []BlockElement
    10  
    11  // Len returns the length of the stack.
    12  func (s *BlockStack) Len() int {
    13  	return len(*s)
    14  }
    15  
    16  // Push appends an item to the stack.
    17  func (s *BlockStack) Push(e BlockElement) {
    18  	*s = append(*s, e)
    19  }
    20  
    21  // Pop removes the last item on the stack.
    22  func (s *BlockStack) Pop() {
    23  	stack := *s
    24  	if len(stack) == 0 {
    25  		return
    26  	}
    27  
    28  	stack = stack[0 : len(stack)-1]
    29  	*s = stack
    30  }
    31  
    32  // Indent returns the current indentation level of all elements in the stack.
    33  func (s BlockStack) Indent() uint {
    34  	var i uint
    35  
    36  	for _, v := range s {
    37  		if v.Style.Indent == nil {
    38  			continue
    39  		}
    40  		i += *v.Style.Indent
    41  	}
    42  
    43  	return i
    44  }
    45  
    46  // Margin returns the current margin level of all elements in the stack.
    47  func (s BlockStack) Margin() uint {
    48  	var i uint
    49  
    50  	for _, v := range s {
    51  		if v.Style.Margin == nil {
    52  			continue
    53  		}
    54  		i += *v.Style.Margin
    55  	}
    56  
    57  	return i
    58  }
    59  
    60  // Width returns the available rendering width.
    61  func (s BlockStack) Width(ctx RenderContext) uint {
    62  	if s.Indent()+s.Margin()*2 > uint(ctx.options.WordWrap) {
    63  		return 0
    64  	}
    65  	return uint(ctx.options.WordWrap) - s.Indent() - s.Margin()*2
    66  }
    67  
    68  // Parent returns the current BlockElement's parent.
    69  func (s BlockStack) Parent() BlockElement {
    70  	if len(s) == 1 {
    71  		return BlockElement{
    72  			Block: &bytes.Buffer{},
    73  		}
    74  	}
    75  
    76  	return s[len(s)-2]
    77  }
    78  
    79  // Current returns the current BlockElement.
    80  func (s BlockStack) Current() BlockElement {
    81  	if len(s) == 0 {
    82  		return BlockElement{
    83  			Block: &bytes.Buffer{},
    84  		}
    85  	}
    86  
    87  	return s[len(s)-1]
    88  }
    89  
    90  // With returns a StylePrimitive that inherits the current BlockElement's style.
    91  func (s BlockStack) With(child StylePrimitive) StylePrimitive {
    92  	sb := StyleBlock{}
    93  	sb.StylePrimitive = child
    94  	return cascadeStyle(s.Current().Style, sb, false).StylePrimitive
    95  }