private static function tabular(array $data, array $widths, array $align = null, $glue = ' ', $pad = ' ', $marker = '…') { $out = []; if (empty($align)) { $align = []; } foreach ($widths as $i => $w) { switch (get($align, $i, 'L')) { case 'L': $align[$i] = STR_PAD_RIGHT; break; case 'R': $align[$i] = STR_PAD_LEFT; break; case 'C': $align[$i] = STR_PAD_BOTH; break; default: throw new InvalidArgumentException("Invalid value for align: {$align[$i]}"); } } foreach ($widths as $i => $w) { $s = strval(get($data, $i)); $l = taggedStrLen($s); if ($l > $w) { $out[] = taggedStrCrop($s, $w, $marker); // echo taggedStrLen (taggedStrCrop ($s, $w - mb_strlen ($overflow, 'UTF-8')) . $overflow); } else { $out[] = taggedStrPad($s, $w, $align[$i], $pad); } } return implode($glue, $out); }
/** * Performs cropping on strings having embedded tags. * * This is specially useful when used with color-tagged strings meant for terminal output. * > Ex: `"<color-name>text</color-name>"` * * @param string $str * @param int $width The desired minimum width, in characters. * @param string $marker The overflow marker. * @return string */ function taggedStrCrop($str, $width, $marker = '') { $w = taggedStrLen($str); if ($w <= $width) { return $str; } $o = ''; $tags = []; $curLen = 0; $markLen = mb_strlen($marker, 'UTF-8'); while (strlen($str)) { if (!preg_match('/<(.*?)>/u', $str, $m, PREG_OFFSET_CAPTURE)) { return $o . mb_substr($str, 0, $width - $curLen - $markLen) . $marker; } list($tag, $ofs) = $m[0]; $tagName = $m[1][0]; $seg = mb_substr($str, 0, $ofs); $str = mb_substr($str, $ofs + mb_strlen($tag, 'UTF-8')); $segLen = mb_strlen($seg, 'UTF-8'); $curLen += $segLen; if ($curLen >= $width) { $o .= mb_substr($seg, 0, $width - $curLen - $markLen) . $marker; break; } else { $o .= $seg; } if ($tag[1] == '/') { array_pop($tags); } else { $tags[] = $tagName; } $o .= "{$tag}"; } while ($tags) { $o .= '</' . array_pop($tags) . '>'; } return $o; }