#!/usr/bin/php
<?php
new CHL;
class 
CHL {
    protected 
$colors = array(
        
"start"        => "0",
        
"stop"        => "0",
        
"comment"    => "33;47",
        
"default"    => "30;47",
        
"html"        => "32;47",
        
"keyword"    => "34;47",
        
"string"    => "31;47",
    );
    protected 
$encoding "UTF-8";
    protected 
$tabstops;
    private 
$formats;
    
    public function 
__construct() {
        if (
$files $this->setup()) {
            foreach (
$files as $file) {
                
$this->highlight(file_get_contents($file), $file);
            }
        } else {
            
$this->highlight(file_get_contents("php://stdin"), "<STDIN>");
        }
    }
    
    public function 
__destruct() {
        if (
$this->tabstops) {
            echo 
"\033[3g";
            
$this->tabstops 8;
            
$this->tabstops();
        }
    }
    
    protected function 
usage() {
        
printf("Usage:\n");
        
printf("\n");
        
printf(" %s [-e ENC] [-t TAB] [-f FILE, ...] [-c TOKEN=COLOR, ...]\n"basename($_SERVER["argv"][0]));
        
printf("\n");
        
printf(" -e ENC              specify the character set of the highlighted code\n");
        
printf(" -t TAB              specify the tab with\n");
        
printf(" -f FILE             specify one or more files to highlight, STDIN if omitted\n");
        
printf(" -c TOKEN=COLOR      specify the color code for the type of token\n");
        
printf("    possible tokens: %s\n"implode(", ",array_keys($this->colors)));
        
printf("\n");
        exit;
    }
    
    protected function 
setup() {
        
$files = array();
        foreach (
getopt("c:e:f:t:h") as $key => $val) {
            switch (
$key) {
                case 
"h":
                    
$this->usage();
                    break;
                case 
"c":
                    foreach ((array)
$val as $col) {
                        list(
$type$color) = explode("="$col);
                        
$this->colors[$type] = $color;
                    }
                    break;
                case 
"e":
                    
$this->encoding current(array_reverse((array)$val));
                    break;
                case 
"t":
                    if (
$tabstops = (int) current(array_reverse((array)$val))) {
                        
$this->tabstops $tabstops;
                    }
                    break;
                case 
"f":
                    
$files = (array) $val;
                    break;
            }
        }
        
$this->tabstops && $this->tabstops();
        
ini_set("highlight.comment""comment");
        
ini_set("highlight.default""default");
        
ini_set("highlight.html""html");
        
ini_set("highlight.keyword""keyword");
        
ini_set("highlight.string""string");
        
$this->formats = array(
            
// get rid of html
            
"/\n/"            => "",
            
"/<br \/>/"        => "\n",
            
"/<\/span>/"    => "",
            
"/(&nbsp;){4}/"    => "\t",
            
"/&nbsp;/"        => " ",
            
"/<code>/"        => $this->color("start"),
            
"/<\/code>/"    => $this->color("stop""""\n"),
            
// convert colors
            
"/<span style=\"color: comment\">/"    => $this->color("comment"),
            
"/<span style=\"color: default\">/"    => $this->color("default"),
            
"/<span style=\"color: html\">/"    => $this->color("html"),
            
"/<span style=\"color: keyword\">/"    => $this->color("keyword"),
            
"/<span style=\"color: string\">/"    => $this->color("string"),
        );
        return 
$files;
    }
    
    protected function 
tabstops() {
        if (!
$colw getenv("COLUMNS")) {
            if (
preg_match("/columns (\d+)/"shell_exec("stty -a"), $m)) {
                
$colw $m[1];
            } else {
                
$colw 80;
            }
        }
        
$tabs str_repeat(" "$this->tabstops) . "\033H";
        
$tabs str_repeat($tabs$colw/$this->tabstops);
        echo 
$tabs "\r";
    }
    
    protected function 
color($type$prepend ""$append "") {
        return 
$prepend "\033[" $this->colors[$type] . "m" $append;
    }
    
    protected function 
highlight($code$name) {
        echo 
"## Syntax highlighted code of $name:\n";
        echo 
html_entity_decode(
            
preg_replace(
                
array_keys($this->formats),
                
array_values($this->formats),
                
highlight_string($codetrue)
            ), 
            
ENT_QUOTES
            
$this->encoding
        
);
    }
}