#! /usr/bin/perl # # $Id: log2ansi,v 1.9 2004/03/08 21:31:26 peder Exp $ # # Copyright (C) 2002, 2003 by Peder Stray # # This is a standalone perl program and not intended to run within # irssi, it will complain if you try to... use strict; use Getopt::Long; use vars qw(%ansi %base %attr %old); use vars qw(@bols @nums @mirc @irssi @mc @mh @ic @ih); use vars qw{$VERSION %IRSSI}; ($VERSION) = '$Revision: 1.9 $' =~ / (\d+\.\d+) /; %IRSSI = ( name => 'log2ansi', authors => 'Peder Stray', contact => 'peder@ninja.no', url => 'http://ninja.no/irssi/log2ansi', license => 'GPL', description => 'convert mirc color and irssi interal formatting to ansi colors, useful for log filtering', ); if (__PACKAGE__ =~ /^Irssi/) { # we are within irssi... die! Irssi::print("%RWarning:%n log2ansi is should not run from within irssi"); die "Suicide to prevent loading\n"; } my $clear = 0; GetOptions( '--clear!' => \$clear, ); for (@ARGV) { if (/\.bz2$/) { $_ = "bunzip2 < '$_' |"; } elsif (/\.gz$/) { $_ = "gunzip < '$_' |"; } } my($n) = 0; %ansi = map { $_ => $n++ } split //, 'krgybmcw'; @bols = qw(bold underline blink reverse fgh bgh); @nums = qw(fgc bgc); @base{@bols} = qw(1 4 5 7 1 5); @base{@nums} = qw(30 40); @mirc = split //, 'WkbgRrmyYGcCBMKw'; @irssi = split //, 'kbgcrmywKBGCRMYW'; @mc = map {$ansi{lc $_}} @mirc; @mh = map {$_ eq uc $_} @mirc; @ic = map {$ansi{lc $_}} @irssi; @ih = map {$_ eq uc $_} @irssi; sub defc { my($attr) = shift || \%attr; $attr->{fgc} = $attr->{bgc} = -1; $attr->{fgh} = $attr->{bgh} = 0; } sub defm { my($attr) = shift || \%attr; $attr->{bold} = $attr->{underline} = $attr->{blink} = $attr->{reverse} = 0; } sub def { my($attr) = shift || \%attr; defc($attr); defm($attr); } sub setold { %old = %attr; } sub emit { my($str) = @_; my(%elem,@elem); my(@clear) = ( (grep { $old{$_} > $attr{$_} } @bols), (grep { $old{$_}>=0 && $attr{$_}<0 } @nums) ); $elem{0}++ if @clear; for (@bols) { $elem{$base{$_}}++ if $attr{$_} && ($old{$_} != $attr{$_} || $elem{0}); } for (@nums) { $elem{$base{$_}+$attr{$_}}++ if $attr{$_} >= 0 && ($old{$_} != $attr{$_} || $elem{0}); } @elem = sort {$a<=>$b} keys %elem; if (@elem) { @elem = () if @elem == 1 && !$elem[0]; printf "\e[%sm", join ";", @elem unless $clear; } print $str; setold; } while (<>) { chomp; def; setold; while (length) { if (s/^\cB//) { # toggle bold $attr{bold} = !$attr{bold}; } elsif (s/^\cC//) { # mirc colors if (/^[^\d,]/) { defc; } else { if (s/^(\d\d?)//) { $attr{fgc} = $mc[$1 % 16]; $attr{fgh} = $mh[$1 % 16]; } if (s/^,//) { if (s/^(\d\d?)//) { $attr{bgc} = $mc[$1 % 16]; $attr{bgh} = $mh[$1 % 16]; } else { $attr{bgc} = -1; $attr{bgh} = 0; } } } } elsif (s/^\cD//) { # irssi format if (s/^a//) { $attr{blink} = !$attr{blink}; } elsif (s/^b//) { $attr{underline} = !$attr{underline}; } elsif (s/^c//) { $attr{bold} = !$attr{bold}; } elsif (s/^d//) { $attr{reverse} = !$attr{reverse}; } elsif (s/^e//) { # indent } elsif (s/^f([^,]*),//) { # indent_func } elsif (s/^g//) { def; } elsif (s/^h//) { # cleol } elsif (s/^i//) { # monospace } else { s/^(.)(.)//; my($f,$b) = map { ord($_)-ord('0') } $1, $2; if ($f<0) { # $attr{fgc} = -1; $attr{fgh} = 0; } else { # c>7 => bold, c -= 8 if c>8 $attr{fgc} = $ic[$f]; $attr{fgh} = $ih[$f]; } if ($b<0) { # $attr{bgc} = -1; $attr{bgh} = 0; } else { # c>7 => blink, c -= 8 $attr{bgc} = $ic[$b]; $attr{bgh} = $ih[$b]; } } } elsif (s/^\cF//) { # blink $attr{blink} = !$attr{blink}; } elsif (s/^\cO//) { def; } elsif (s/^\cV//) { $attr{reverse} = !$attr{reverse}; } elsif (s/^\c[\[([^m]*)m//) { my(@ansi) = split ";", $1; my(%a); push @ansi, 0 unless @ansi; for my $code (@ansi) { if ($code == 0) { def(\%a); } elsif ($code == $base{bold}) { $a{bold} = 1; } elsif ($code == $base{underline}) { $a{underline} = 1; } elsif ($code == $base{blink}) { $a{underline} = 1; } elsif ($code == $base{reverse}) { $a{reverse} = 1; } elsif ($code => 30 && $code <= 37) { $a{fgc} = $code - 30; } elsif ($code => 40 && $code <= 47) { $a{bgc} = $code - 40; } else { $a{$code} = 1; } } if ($a{fgc} >= 0 && $a{bold}) { $a{fgh} = 1; $a{bold} = 0; } if ($a{bgc} >= 0 && $a{blink}) { $a{bgh} = 1; $a{blink} = 0; } for my $key (keys %a) { $attr{$key} = $a{$key}; } } elsif (s/^\c_//) { $attr{underline} = !$attr{underline}; } else { s/^(.[^\cB\cC\cD\cF\cO\cV\c[\c_]*)//; emit $1; } } def; emit "\n"; }