Breaks a line into a list[str] with maximum limit length per line.
It keeps ongoing ANSI sequences between lines, and inserts a reset sequence
at the end of each style-containing line.
At the moment it splits strings exactly on the limit, and not on word
boundaries. That functionality would be preferred, so it will end up being
implemented at some point.
  Parameters:
  
    
      
        | Name | 
        Type | 
        Description | 
        Default | 
      
    
    
        
          line | 
          
                str
           | 
          
            
              The line to split. May or may not contain ANSI sequences. 
             
           | 
          
              required
           | 
        
        
          limit | 
          
                int
           | 
          
            
              The maximum amount of characters allowed in each line, excluding
non-printing sequences. 
             
           | 
          
              required
           | 
        
        
          non_first_limit | 
          
                int | None
           | 
          
            
              The limit after the first line. If not given, defaults
to limit. 
             
           | 
          
                None
           | 
        
    
  
          
            Source code in pytermgui/helpers.py
             16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113  | def break_line(  # pylint: disable=too-many-branches
    line: str, limit: int, non_first_limit: int | None = None, fill: str | None = None
) -> Iterator[str]:
    """Breaks a line into a `list[str]` with maximum `limit` length per line.
    It keeps ongoing ANSI sequences between lines, and inserts a reset sequence
    at the end of each style-containing line.
    At the moment it splits strings exactly on the limit, and not on word
    boundaries. That functionality would be preferred, so it will end up being
    implemented at some point.
    Args:
        line: The line to split. May or may not contain ANSI sequences.
        limit: The maximum amount of characters allowed in each line, excluding
            non-printing sequences.
        non_first_limit: The limit after the first line. If not given, defaults
            to `limit`.
    """
    if line in ["", "\x1b[0m"]:
        yield ""
        return
    def _pad_and_link(line: str, link: str | None) -> str:
        count = limit - real_length(line)
        if link is not None:
            line = LINK_TEMPLATE.format(uri=link, label=line)
        if fill is None:
            return line
        line += count * fill
        return line
    used = 0
    current = ""
    sequences = ""
    if non_first_limit is None:
        non_first_limit = limit
    parsers = PARSERS
    link = None
    for token in tokenize_ansi(line):
        if token.is_plain():
            for char in token.value:
                if char == "\n" or used >= limit:
                    if sequences != "":
                        current += "\x1b[0m"
                    yield _pad_and_link(current, link)
                    link = None
                    current = sequences
                    used = 0
                    limit = non_first_limit
                if char != "\n":
                    current += char
                    used += 1
            # If the link wasn't yielded along with its token, remove and add it
            # to current manually.
            if link is not None:
                current = current[: -len(token.value)]
                current += LINK_TEMPLATE.format(uri=link, label=token.value)
                link = None
            continue
        if token.value == "/":
            sequences = "\x1b[0m"
            if len(current) > 0:
                current += sequences
            continue
        if token.is_hyperlink():
            link = token.value
            continue
        sequence = parsers[type(token)](token, {}, lambda: line)  # type: ignore
        sequences += sequence
        current += sequence
    if current == "":
        return
    if sequences != "" and not current.endswith("\x1b[0m"):
        current += "\x1b[0m"
    yield _pad_and_link(current, link)
  |