Skip to content

Commit f9a7bea

Browse files
committed
bug #35 Handle multiple codes in sequences (jacklul)
This PR was squashed before being merged into the master branch. Discussion ---------- Handle multiple codes in sequences This PR adds support for handling multiple sequences of ansi codes - preserving the styling until reset code is found. This addresses #17 ### Current: ![sequences current](https://github.com/user-attachments/assets/9ba757d8-cc92-4e44-8a68-c5dfff22469e) ### With this PR: ![sequences pr](https://github.com/user-attachments/assets/fdc5fb5e-1d92-4683-8543-0673441b360b) Like in my other PR, PHPUnit passes once the test class is fixed. ## TODO: ~~ANSI codes 22-29 should disable appropriate styling, currently it will not work because of `in_array` checks on 1-9, might need to remove values directly in `tokenize` or rewrite the styling code into something else **I have an idea how to approach this, will update on that soon**~~ Done Commits ------- de5ed7a Handle style reset sequences 62572d1 Handle multiple codes in sequences
2 parents d58ef55 + de5ed7a commit f9a7bea

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

SensioLabs/AnsiConverter/AnsiToHtmlConverter.php

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ protected function convertAnsiToColor($ansi)
101101
if ('0' != $ansi && '' != $ansi) {
102102
$options = explode(';', $ansi);
103103

104-
foreach ($options as $option) {
104+
foreach ($options as $key => $option) {
105105
if ($option >= 30 && $option < 38) {
106106
$fg = $option - 30;
107107
} elseif ($option >= 40 && $option < 48) {
@@ -115,6 +115,22 @@ protected function convertAnsiToColor($ansi)
115115
$fg = 7;
116116
} elseif (49 == $option) {
117117
$bg = 0;
118+
} elseif ($option >= 22 && $option < 30) { // 21 has varying effects, best to ignored it
119+
$unset = $option - 20;
120+
121+
foreach ($options as $i => $v) {
122+
if ($v == $unset) {
123+
unset($options[$i]);
124+
}
125+
126+
if (2 == $unset && 1 == $v) { // 22 also unsets bold
127+
unset($options[$i]);
128+
}
129+
130+
if ($i >= $key) { // do not unset options after current position in parent loop
131+
break;
132+
}
133+
}
118134
}
119135
}
120136

@@ -162,14 +178,30 @@ protected function tokenize($text)
162178
$tokens = array();
163179
preg_match_all("/(?:\e\[(.*?)m|(\x08))/", $text, $matches, PREG_OFFSET_CAPTURE);
164180

181+
$codes = array();
165182
$offset = 0;
166183
foreach ($matches[0] as $i => $match) {
167184
if ($match[1] - $offset > 0) {
168185
$tokens[] = array('text', substr($text, $offset, $match[1] - $offset));
169186
}
170-
$tokens[] = array("\x08" == $match[0] ? 'backspace' : 'color', $matches[1][$i][0]);
187+
188+
foreach (explode(';', $matches[1][$i][0]) as $code) {
189+
if ('0' == $code || '' == $code) {
190+
$codes = array();
191+
} else {
192+
// remove existing occurrence to avoid processing duplicate styles
193+
if (in_array($code, $codes) && ($key = array_search($code, $codes)) !== false) {
194+
unset($codes[$key]);
195+
}
196+
}
197+
198+
$codes[] = $code;
199+
}
200+
201+
$tokens[] = array("\x08" == $match[0] ? 'backspace' : 'color', implode(';', $codes));
171202
$offset = $match[1] + strlen($match[0]);
172203
}
204+
173205
if ($offset < strlen($text)) {
174206
$tokens[] = array('text', substr($text, $offset));
175207
}

SensioLabs/AnsiConverter/Tests/AnsiToHtmlConverterTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public function getConvertData()
7575

7676
// non valid unicode codepoints substitution (only available with PHP >= 5.4)
7777
PHP_VERSION_ID < 50400 ?: array('<span style="background-color: black; color: white">foo '."\xEF\xBF\xBD".'</span>', "foo \xF4\xFF\xFF\xFF"),
78+
79+
// codes in sequence - remember enabled styling like bold, italic, etc. (until we hit a reset)
80+
array('<span style="background-color: black; color: lightgreen">foo</span><span style="background-color: black; color: lightgreen">bar</span><span style="background-color: black; color: white">foo</span>', "\e[1;32mfoo\e[32mbar\e[mfoo"),
7881
);
7982
}
8083
}

0 commit comments

Comments
 (0)