html/log2ansi.pl


   1 #! /usr/bin/perl
   2 #
   3 #    $Id: log2ansi,v 1.9 2004/03/08 21:31:26 peder Exp $
   4 #
   5 # Copyright (C) 2002, 2003 by Peder Stray <peder@ninja.no>
   6 #
   7 #    This is a standalone perl program and not intended to run within
   8 #    irssi, it will complain if you try to...
   9 
  10 use strict;
  11 use Getopt::Long;
  12 use vars qw(%ansi %base %attr %old);
  13 use vars qw(@bols @nums @mirc @irssi @mc @mh @ic @ih);
  14 
  15 use vars qw{$VERSION %IRSSI};
  16 ($VERSION) = '$Revision: 1.9 $' =~ / (\d+\.\d+) /;
  17 %IRSSI = (
  18           name        => 'log2ansi',
  19           authors     => 'Peder Stray',
  20           contact     => 'peder@ninja.no',
  21           url         => 'http://ninja.no/irssi/log2ansi',
  22           license     => 'GPL',
  23           description => 'convert mirc color and irssi interal formatting to ansi colors, useful for log filtering',
  24          );
  25 
  26 if (__PACKAGE__ =~ /^Irssi/) {
  27     # we are within irssi... die!
  28     Irssi::print("%RWarning:%n log2ansi is should not run from within irssi");
  29     die "Suicide to prevent loading\n";
  30 }
  31 
  32 my $clear = 0;
  33 
  34 GetOptions(
  35 	   '--clear!' => \$clear,
  36 	  );
  37 
  38 for (@ARGV) {
  39     if (/\.bz2$/) {
  40 	$_ = "bunzip2 < '$_' |";
  41     } elsif (/\.gz$/) {
  42         $_ = "gunzip < '$_' |";
  43     }
  44 }
  45 
  46 my($n) = 0;
  47 %ansi = map { $_ => $n++ } split //, 'krgybmcw';
  48 
  49 @bols = qw(bold underline blink reverse fgh bgh);
  50 @nums = qw(fgc bgc);
  51 
  52 @base{@bols} = qw(1 4 5 7 1 5);
  53 @base{@nums} = qw(30 40);
  54 
  55 @mirc  = split //, 'WkbgRrmyYGcCBMKw';
  56 @irssi = split //, 'kbgcrmywKBGCRMYW';
  57 
  58 @mc = map {$ansi{lc $_}} @mirc;
  59 @mh = map {$_ eq uc $_} @mirc;
  60 
  61 @ic = map {$ansi{lc $_}} @irssi;
  62 @ih = map {$_ eq uc $_} @irssi;
  63 
  64 sub defc {
  65     my($attr) = shift || \%attr;
  66     $attr->{fgc} = $attr->{bgc} = -1;
  67     $attr->{fgh} = $attr->{bgh} = 0;
  68 }
  69 
  70 sub defm {
  71     my($attr) = shift || \%attr;
  72     $attr->{bold} = $attr->{underline} = 
  73       $attr->{blink} = $attr->{reverse} = 0;
  74 }
  75 
  76 sub def {
  77     my($attr) = shift || \%attr;
  78     defc($attr);
  79     defm($attr);
  80 }
  81 
  82 sub setold {
  83     %old = %attr;
  84 }
  85 
  86 sub emit {
  87     my($str) = @_;
  88     my(%elem,@elem);
  89 
  90     my(@clear) = ( (grep { $old{$_} > $attr{$_} } @bols),
  91 		   (grep { $old{$_}>=0 && $attr{$_}<0 } @nums)
  92 		 );
  93 
  94     $elem{0}++ if @clear;
  95 
  96     for (@bols) {
  97 	$elem{$base{$_}}++ 
  98 	  if $attr{$_} && ($old{$_} != $attr{$_} || $elem{0});
  99     }
 100 
 101     for (@nums) {
 102 	$elem{$base{$_}+$attr{$_}}++
 103 	  if $attr{$_} >= 0 && ($old{$_} != $attr{$_} || $elem{0});
 104     }
 105 
 106     @elem = sort {$a<=>$b} keys %elem;
 107 
 108     if (@elem) {
 109 	@elem = () if @elem == 1 && !$elem[0];
 110 	printf "\e[%sm", join ";", @elem
 111 	  unless $clear;
 112     }
 113 
 114     print $str;
 115 
 116     setold;
 117 }
 118 
 119 while (<>) {
 120     chomp;
 121     def;
 122     setold;
 123 
 124     while (length) {
 125 	if (s/^\cB//) {
 126 	    # toggle bold
 127 	    $attr{bold} = !$attr{bold};
 128 	
 129 	} elsif (s/^\cC//) {
 130 	    # mirc colors
 131 
 132 	    if (/^[^\d,]/) {
 133 		defc;
 134 	    } else {
 135 		
 136 		if (s/^(\d\d?)//) {
 137 		    $attr{fgc} = $mc[$1 % 16];
 138 		    $attr{fgh} = $mh[$1 % 16];
 139 		}
 140 
 141 		if (s/^,//) {
 142 		    if (s/^(\d\d?)//) {
 143 			$attr{bgc} = $mc[$1 % 16];
 144 			$attr{bgh} = $mh[$1 % 16];
 145 		    } else {
 146 			$attr{bgc} = -1;
 147 			$attr{bgh} = 0;
 148 		    }
 149 		}
 150 	    }
 151 
 152 	} elsif (s/^\cD//) {
 153 	    # irssi format
 154 
 155 	    if (s/^a//) {
 156 		$attr{blink} = !$attr{blink};
 157 	    } elsif (s/^b//) {
 158 		$attr{underline} = !$attr{underline};
 159 	    } elsif (s/^c//) {
 160 		$attr{bold} = !$attr{bold};
 161 	    } elsif (s/^d//) {
 162 		$attr{reverse} = !$attr{reverse};
 163 	    } elsif (s/^e//) {
 164 		# indent
 165 	    } elsif (s/^f([^,]*),//) {
 166 		# indent_func
 167 	    } elsif (s/^g//) {
 168 		def;
 169 	    } elsif (s/^h//) {
 170 		# cleol
 171 	    } elsif (s/^i//) {
 172 		# monospace
 173 	    } else {
 174 		s/^(.)(.)//;
 175 		my($f,$b) = map { ord($_)-ord('0') } $1, $2;
 176 		if ($f<0) {
 177 #		    $attr{fgc} = -1; $attr{fgh} = 0;
 178 		} else {
 179 		    # c>7 => bold, c -= 8 if c>8
 180 		    $attr{fgc} = $ic[$f];
 181 		    $attr{fgh} = $ih[$f];
 182 		}
 183 		if ($b<0) {
 184 #		    $attr{bgc} = -1; $attr{bgh} = 0;
 185 		} else {
 186 		    # c>7 => blink, c -= 8
 187 		    $attr{bgc} = $ic[$b];
 188 		    $attr{bgh} = $ih[$b];
 189 		}
 190 	    }
 191 
 192 	} elsif (s/^\cF//) {
 193 	    # blink
 194 	    $attr{blink} = !$attr{blink};
 195 
 196 	} elsif (s/^\cO//) {
 197 	    def;
 198 
 199 	} elsif (s/^\cV//) {
 200 	    $attr{reverse} = !$attr{reverse};
 201 
 202 	} elsif (s/^\c[\[([^m]*)m//) {
 203 	    my(@ansi) = split ";", $1;
 204 	    my(%a);
 205 
 206 	    push @ansi, 0 unless @ansi;
 207 
 208 	    for my $code (@ansi) {
 209 		if ($code == 0) {
 210 		    def(\%a);
 211 		} elsif ($code == $base{bold}) {
 212 		    $a{bold} = 1;
 213 		} elsif ($code == $base{underline}) {
 214 		    $a{underline} = 1;
 215 		} elsif ($code == $base{blink}) {
 216 		    $a{underline} = 1;
 217 		} elsif ($code == $base{reverse}) {
 218 		    $a{reverse} = 1;
 219 		} elsif ($code => 30 && $code <= 37) {
 220 		    $a{fgc} = $code - 30;
 221 		} elsif ($code => 40 && $code <= 47) {
 222 		    $a{bgc} = $code - 40;
 223 		} else {
 224 		    $a{$code} = 1;
 225 		}
 226 	    }
 227 
 228 	    if ($a{fgc} >= 0 && $a{bold}) {
 229 		$a{fgh} = 1;
 230 		$a{bold} = 0;
 231 	    }
 232 
 233 	    if ($a{bgc} >= 0 && $a{blink}) {
 234 		$a{bgh} = 1;
 235 		$a{blink} = 0;
 236 	    }
 237 
 238 	    for my $key (keys %a) {
 239 		$attr{$key} = $a{$key};
 240 	    }
 241 
 242 	} elsif (s/^\c_//) {
 243 	    $attr{underline} = !$attr{underline};
 244 
 245 	} else {
 246 	    s/^(.[^\cB\cC\cD\cF\cO\cV\c[\c_]*)//;
 247 	    emit $1;
 248 	}
 249     }
 250 
 251     def;
 252     emit "\n";
 253 }