# $Id$ package N0i::Xchat::Cat; use strict; use warnings; our $VERSION = sprintf '0.%d.%d', '\$Revision: 1.0 $' =~ /(\d+)\.(\d+)/xm; use English qw( -no_match_vars ); use base qw(N0i::Xchat::Base); use File::Path::Expand (); use Text::Highlight (); sub version { return '0.2.9' } sub new { my ( $class, %o ) = @_; my $self = {%o}; bless $self, $class; $self->register; $self->set_hooks( [ 'command', 'cat', sub { return $self->cat( $_[1]->[1] ); }, { help_text => '/cat [-n] ' } ] ); $self->loaded; return $self; } sub cat { my ( $self, $args ) = @_; if ( !defined $args || $args !~ /\S/ ) { return $self->error(' usage: /cat [-n] '); } # strip "-n" option my $no_numbers = ( $args =~ s{^ \s* -n \s+ }{}xms ); my $file = File::Path::Expand::expand_filename($args); open my $fh, q{<}, $file or return $self->error("Cannot open $file: $OS_ERROR"); my $ln = 1; my @lines = (); my $hl_lang = $self->find_language($file); if ($hl_lang) { # if highlighted, we HAVE TO buffer all file :( @lines = <$fh>; close $fh or return $self->error("Cannot close $file: $OS_ERROR"); undef $fh; @lines = map { s{ \x1B \[ 0 m }{\cO}xmsg; s{ \x1B \[ ([0-9;]+) m }{ $self->ansi_to_mirc($1) }xmesg; $_; } split /\r?\n/, Text::Highlight->new( ansi => 1 )->highlight( $hl_lang, join q{}, @lines ); } # cat every "line" in file while ( my $line = defined $fh ? <$fh> : shift @lines ) { $self->cat_line( $line, $no_numbers ? undef: $ln++ ); } if (defined $fh) { close $fh or return $self->error("Cannot close $file: $OS_ERROR"); } return Xchat::EAT_ALL; } sub cat_line { my ( $self, $line, $number ) = @_; chomp $line; if ( defined $number ) { $line = sprintf "[\cC15%03d\cO] %s", $number, $line; } Xchat::command("say $line"); return Xchat::EAT_ALL; } sub error { my ( $self, $error_msg ) = @_; Xchat::print("\cC04ERROR\cO: $error_msg"); return Xchat::EAT_ALL; } sub find_language { my ( $self, $file_name ) = @_; return 'CPP' if $file_name =~ /\.(?i:c|cc|cpp|h|xs)$/; return 'CSS' if $file_name =~ /\.(?i:css)$/; return 'HTML' if $file_name =~ /\.(?i:htm|html|xml|dtd|xsl|rss|opml)$/; return 'Java' if $file_name =~ /\.(?i:java|js)$/; return 'PHP' if $file_name =~ /\.(?i:php\d?)$/; return 'Perl' if $file_name =~ /\.(?i:pl|pm|t|pod)$/; return 'SQL' if $file_name =~ /\.(?i:sql)$/; return; } sub ansi_to_mirc { my ( $self, $ansi ) = @_; my $ret = q{}; # bold $ansi =~ s{ (?] | <\x02TEXT\x02> > \cC11OPTIONS\cO: -n : no line numbers -f <\x02FILE_PATH\x02> : paste file EOF return Xchat::EAT_ALL; } 1;