Decode a line containing ansi codes. Args: line (str): A line of terminal output. Returns: Text: A Text instance marked up according to ansi codes.
(self, line: str)
| 136 | yield self.decode_line(line.rstrip("\n")) |
| 137 | |
| 138 | def decode_line(self, line: str) -> Text: |
| 139 | """Decode a line containing ansi codes. |
| 140 | |
| 141 | Args: |
| 142 | line (str): A line of terminal output. |
| 143 | |
| 144 | Returns: |
| 145 | Text: A Text instance marked up according to ansi codes. |
| 146 | """ |
| 147 | from_ansi = Color.from_ansi |
| 148 | from_rgb = Color.from_rgb |
| 149 | _Style = Style |
| 150 | text = Text() |
| 151 | append = text.append |
| 152 | line = line.rsplit("\r", 1)[-1] |
| 153 | for plain_text, sgr, osc in _ansi_tokenize(line): |
| 154 | if plain_text: |
| 155 | append(plain_text, self.style or None) |
| 156 | elif osc is not None: |
| 157 | if osc.startswith("8;"): |
| 158 | _params, semicolon, link = osc[2:].partition(";") |
| 159 | if semicolon: |
| 160 | self.style = self.style.update_link(link or None) |
| 161 | elif sgr is not None: |
| 162 | # Translate in to semi-colon separated codes |
| 163 | # Ignore invalid codes, because we want to be lenient |
| 164 | codes = [ |
| 165 | min(255, int(_code) if _code else 0) |
| 166 | for _code in sgr.split(";") |
| 167 | if _code.isdigit() or _code == "" |
| 168 | ] |
| 169 | iter_codes = iter(codes) |
| 170 | for code in iter_codes: |
| 171 | if code == 0: |
| 172 | # reset |
| 173 | self.style = _Style.null() |
| 174 | elif code in SGR_STYLE_MAP: |
| 175 | # styles |
| 176 | self.style += _Style.parse(SGR_STYLE_MAP[code]) |
| 177 | elif code == 38: |
| 178 | # Foreground |
| 179 | with suppress(StopIteration): |
| 180 | color_type = next(iter_codes) |
| 181 | if color_type == 5: |
| 182 | self.style += _Style.from_color( |
| 183 | from_ansi(next(iter_codes)) |
| 184 | ) |
| 185 | elif color_type == 2: |
| 186 | self.style += _Style.from_color( |
| 187 | from_rgb( |
| 188 | next(iter_codes), |
| 189 | next(iter_codes), |
| 190 | next(iter_codes), |
| 191 | ) |
| 192 | ) |
| 193 | elif code == 48: |
| 194 | # Background |
| 195 | with suppress(StopIteration): |
no test coverage detected