<commit_before><?php
namespace CLIFramework\Component\Table;
use InvalidArgumentException;

use CLIFramework\Component\Table\TableStyle;
use CLIFramework\Component\Table\MarkdownTableStyle;

interface Separator { }

/**
 * RowSeparator is a slight separator for separating distinct rows...
 */
class RowSeparator implements Separator { }

/**
 * TableSeparator is more likely a section separator, the style is customizable.
 */
class TableSeparator implements Separator { }

/**
 * Feature:
 * 
 * - Support column wrapping if the cell text is too long.
 * - Table style
 */
class Table
{



    /**
     * @var string[] the rows are expanded by lines
     */
    protected $rows = array();

    /**
     * @var inteager[] contains the real row index
     */
    protected $rowIndex = array();

    protected $columnWidths = array();

    protected $headers = array();

    protected $style;

    protected $numberOfColumns;

    protected $maxColumnWidth = 50;

    protected $predefinedStyles = array();

    /**
     * Save the mapping of column index => cell attributes
     *
     * [ column index => cell attributes, ... ]
     */
    protected $columnCellAttributes = array();


    /**
     * The default cell attribute
     */
    protected $defaultCellAttribute;


    /**
     * @var bool strip the white spaces from the begining of a 
     * string and the end of a string.
     */
    protected $trimSpaces = true;

    protected $trimLeadingSpaces = false;

    protected $trimTrailingSpaces = false;

    protected $footer;

    public function __construct() {
        $this->style = new TableStyle;
        $this->defaultCellAttribute = new CellAttribute;
    }

    public function setHeaders(array $headers) {
        $this->headers = $headers;
        return $this;
    }

    public function setFooter($footer)
    {
        $this->footer = $footer;
        return $this;
    }

    public function setColumnCellAttribute($colIndex, CellAttribute $cellAttribute)
    {
        $this->columnCellAttributes[$colIndex] = $cellAttribute;
    }

    public function getColumnCellAttribute($colIndex)
    {
        if (isset($this->columnCellAttributes[$colIndex])) {
            return $this->columnCellAttributes[$colIndex];
        }
    }

    public function getDefaultCellAttribute()
    {
        return $this->defaultCellAttribute;
    }

    public function setMaxColumnWidth($width)
    {
        $this->maxColumnWidth = $width;
    }

    /**
     * Gets number of columns for this table.
     *
     * @return int
     */
    private function getNumberOfColumns()
    {
        if (null !== $this->numberOfColumns) {
            return $this->numberOfColumns;
        }

        $columns = array(count($this->headers));
        foreach ($this->rows as $row) {
            $columns[] = count($row);
        }
        return $this->numberOfColumns = max($columns);
    }

    public function addRow($row) {
        $this->rows[] = $row;

        // $keys = array_keys($this->rows);
        $lastRowIdx = count($this->rows) - 1;

        $this->rowIndex[$lastRowIdx] = 1;

        $cells = array_values($row);
        foreach ($cells as $col => $cell) {
            $attribute = $this->defaultCellAttribute;

            $customAttribute = false;
            if (is_array($cell)) {
                list($cell, $attribute) = $cell;
                $customAttribute = true;
            } elseif (isset($this->columnCellAttributes[$col])) {
                $attribute = $this->columnCellAttributes[$col];
            }

            $lines = $attribute->handleTextOverflow($cell, $this->maxColumnWidth);

            if (count($lines) == 1) {
                $lines[0] = $attribute->format($lines[0]);
            }

            // Handle extra lines
            $extraRowIdx = $lastRowIdx;
            foreach($lines as $line) {
                // trim the leading space
                if ($this->trimSpaces) {
                    $line = trim($line);
                } else {
                    if ($this->trimLeadingSpaces) {
                        $line = ltrim($line);
                    }
                    if ($this->trimTrailingSpaces) {
                        $line = rtrim($line);
                    }
                }

                if (isset($this->rows[$extraRowIdx])) {
                    $this->rows[$extraRowIdx][ $col ] = $customAttribute ? [$line, $attribute] : $line;
                } else {
                    $this->rows[$extraRowIdx] = array($col => $customAttribute ? [$line, $attribute] : $line);
                }
                $extraRowIdx++;
            }
        }
        return $this;
    }

    public function getColumnWidth($col) {
        $lengths = array();
        foreach($this->rows as $row) {
            if (isset($row[$col])) {
                if (is_array($row[$col])) {
                    $lengths[] = mb_strlen($row[$col][0]);
                } else {
                    $lengths[] = mb_strlen($row[$col]);
                }<commit_msg>Rename $customAttibute to $expandAttribute<commit_after><?php
namespace CLIFramework\Component\Table;
use InvalidArgumentException;

use CLIFramework\Component\Table\TableStyle;
use CLIFramework\Component\Table\MarkdownTableStyle;

interface Separator { }

/**
 * RowSeparator is a slight separator for separating distinct rows...
 */
class RowSeparator implements Separator { }

/**
 * TableSeparator is more likely a section separator, the style is customizable.
 */
class TableSeparator implements Separator { }

/**
 * Feature:
 * 
 * - Support column wrapping if the cell text is too long.
 * - Table style
 */
class Table
{



    /**
     * @var string[] the rows are expanded by lines
     */
    protected $rows = array();

    /**
     * @var inteager[] contains the real row index
     */
    protected $rowIndex = array();

    protected $columnWidths = array();

    protected $headers = array();

    protected $style;

    protected $numberOfColumns;

    protected $maxColumnWidth = 50;

    protected $predefinedStyles = array();

    /**
     * Save the mapping of column index => cell attributes
     *
     * [ column index => cell attributes, ... ]
     */
    protected $columnCellAttributes = array();


    /**
     * The default cell attribute
     */
    protected $defaultCellAttribute;


    /**
     * @var bool strip the white spaces from the begining of a 
     * string and the end of a string.
     */
    protected $trimSpaces = true;

    protected $trimLeadingSpaces = false;

    protected $trimTrailingSpaces = false;

    protected $footer;

    public function __construct() {
        $this->style = new TableStyle;
        $this->defaultCellAttribute = new CellAttribute;
    }

    public function setHeaders(array $headers) {
        $this->headers = $headers;
        return $this;
    }

    public function setFooter($footer)
    {
        $this->footer = $footer;
        return $this;
    }

    public function setColumnCellAttribute($colIndex, CellAttribute $cellAttribute)
    {
        $this->columnCellAttributes[$colIndex] = $cellAttribute;
    }

    public function getColumnCellAttribute($colIndex)
    {
        if (isset($this->columnCellAttributes[$colIndex])) {
            return $this->columnCellAttributes[$colIndex];
        }
    }

    public function getDefaultCellAttribute()
    {
        return $this->defaultCellAttribute;
    }

    public function setMaxColumnWidth($width)
    {
        $this->maxColumnWidth = $width;
    }

    /**
     * Gets number of columns for this table.
     *
     * @return int
     */
    private function getNumberOfColumns()
    {
        if (null !== $this->numberOfColumns) {
            return $this->numberOfColumns;
        }

        $columns = array(count($this->headers));
        foreach ($this->rows as $row) {
            $columns[] = count($row);
        }
        return $this->numberOfColumns = max($columns);
    }

    public function addRow($row) {
        $this->rows[] = $row;

        // $keys = array_keys($this->rows);
        $lastRowIdx = count($this->rows) - 1;

        $this->rowIndex[$lastRowIdx] = 1;

        $cells = array_values($row);
        foreach ($cells as $col => $cell) {
            $attribute = $this->defaultCellAttribute;

            $expandAttribute = false;
            if (is_array($cell)) {
                list($cell, $attribute) = $cell;
                $expandAttribute = true;
            } elseif (isset($this->columnCellAttributes[$col])) {
                $attribute = $this->columnCellAttributes[$col];
            }

            $lines = $attribute->handleTextOverflow($cell, $this->maxColumnWidth);

            if (count($lines) == 1) {
                $lines[0] = $attribute->format($lines[0]);
            }

            // Handle extra lines
            $extraRowIdx = $lastRowIdx;
            foreach($lines as $line) {
                // trim the leading space
                if ($this->trimSpaces) {
                    $line = trim($line);
                } else {
                    if ($this->trimLeadingSpaces) {
                        $line = ltrim($line);
                    }
                    if ($this->trimTrailingSpaces) {
                        $line = rtrim($line);
                    }
                }

                if (isset($this->rows[$extraRowIdx])) {
                    $this->rows[$extraRowIdx][ $col ] = $expandAttribute ? [$line, $attribute] : $line;
                } else {
                    $this->rows[$extraRowIdx] = array($col => $expandAttribute ? [$line, $attribute] : $line);
                }
                $extraRowIdx++;
            }
        }
        return $this;
    }

    public function getColumnWidth($col) {
        $lengths = array();
        foreach($this->rows as $row) {
            if (isset($row[$col])) {
                if (is_array($row[$col])) {
                    $lengths[] = mb_strlen($row[$col][0]);
                } else {
                    $lengths[] = mb_strlen($row[$col]);
                }
{'fraction_non_alphanumeric': 0.12580741329623374, 'fraction_numerical': 0.0015899831064294942, 'mean_word_length': 1.8836676217765043, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6190750', 'n_tokens_mistral': 2773, 'n_tokens_neox': 2643, 'n_words': 641}