Rebrand Perl plugin to HexChat,
Add /pl and plugin_pref Add help messages
This commit is contained in:
556
plugins/perl/lib/HexChat.pm
Normal file
556
plugins/perl/lib/HexChat.pm
Normal file
@@ -0,0 +1,556 @@
|
||||
$SIG{__WARN__} = sub {
|
||||
my $message = shift @_;
|
||||
my ($package) = caller;
|
||||
|
||||
# redirect Gtk/Glib errors and warnings back to STDERR
|
||||
my $message_levels = qr/ERROR|CRITICAL|WARNING|MESSAGE|INFO|DEBUG/i;
|
||||
if( $message =~ /^(?:Gtk|GLib|Gdk)(?:-\w+)?-$message_levels/i ) {
|
||||
print STDERR $message;
|
||||
} else {
|
||||
|
||||
if( defined &HexChat::Internal::print ) {
|
||||
HexChat::print( $message );
|
||||
} else {
|
||||
warn $message;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
use File::Spec ();
|
||||
use File::Basename ();
|
||||
use File::Glob ();
|
||||
use List::Util ();
|
||||
use Symbol();
|
||||
use Time::HiRes ();
|
||||
use Carp ();
|
||||
|
||||
package HexChat;
|
||||
use base qw(Exporter);
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub PRI_HIGHEST ();
|
||||
sub PRI_HIGH ();
|
||||
sub PRI_NORM ();
|
||||
sub PRI_LOW ();
|
||||
sub PRI_LOWEST ();
|
||||
|
||||
sub EAT_NONE ();
|
||||
sub EAT_HEXCHAT ();
|
||||
sub EAT_PLUGIN ();
|
||||
sub EAT_ALL ();
|
||||
|
||||
sub KEEP ();
|
||||
sub REMOVE ();
|
||||
sub FD_READ ();
|
||||
sub FD_WRITE ();
|
||||
sub FD_EXCEPTION ();
|
||||
sub FD_NOTSOCKET ();
|
||||
|
||||
sub get_context;
|
||||
sub HexChat::Internal::context_info;
|
||||
sub HexChat::Internal::print;
|
||||
|
||||
#keep compability with Xchat scripts
|
||||
sub EAT_XCHAT ();
|
||||
BEGIN {
|
||||
*Xchat:: = *HexChat::;
|
||||
}
|
||||
|
||||
our %EXPORT_TAGS = (
|
||||
constants => [
|
||||
qw(PRI_HIGHEST PRI_HIGH PRI_NORM PRI_LOW PRI_LOWEST), # priorities
|
||||
qw(EAT_NONE EAT_HEXCHAT EAT_XCHAT EAT_PLUGIN EAT_ALL), # callback return values
|
||||
qw(FD_READ FD_WRITE FD_EXCEPTION FD_NOTSOCKET), # fd flags
|
||||
qw(KEEP REMOVE), # timers
|
||||
],
|
||||
hooks => [
|
||||
qw(hook_server hook_command hook_print hook_timer hook_fd unhook),
|
||||
],
|
||||
util => [
|
||||
qw(register nickcmp strip_code send_modes), # misc
|
||||
qw(print prnt printf prntf command commandf emit_print), # output
|
||||
qw(find_context get_context set_context), # context
|
||||
qw(get_info get_prefs get_list context_info user_info), # input
|
||||
qw(plugin_pref_set plugin_pref_get plugin_pref_delete plugin_pref_list), #settings
|
||||
],
|
||||
);
|
||||
|
||||
$EXPORT_TAGS{all} = [ map { @{$_} } @EXPORT_TAGS{qw(constants hooks util)}];
|
||||
our @EXPORT = @{$EXPORT_TAGS{constants}};
|
||||
our @EXPORT_OK = @{$EXPORT_TAGS{all}};
|
||||
|
||||
sub register {
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $filename = $pkg_info->{filename};
|
||||
my ($name, $version, $description, $callback) = @_;
|
||||
|
||||
if( defined $pkg_info->{gui_entry} ) {
|
||||
HexChat::print( "HexChat::register called more than once in "
|
||||
. $pkg_info->{filename} );
|
||||
return ();
|
||||
}
|
||||
|
||||
$description = "" unless defined $description;
|
||||
if( $callback ) {
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
}
|
||||
$pkg_info->{shutdown} = $callback;
|
||||
unless( $name && $name =~ /[[:print:]\w]/ ) {
|
||||
$name = "Not supplied";
|
||||
}
|
||||
unless( $version && $version =~ /\d+(?:\.\d+)?/ ) {
|
||||
$version = "NaN";
|
||||
}
|
||||
$pkg_info->{gui_entry} =
|
||||
HexChat::Internal::register( $name, $version, $description, $filename );
|
||||
# keep with old behavior
|
||||
return ();
|
||||
}
|
||||
|
||||
sub _process_hook_options {
|
||||
my ($options, $keys, $store) = @_;
|
||||
|
||||
unless( @$keys == @$store ) {
|
||||
die 'Number of keys must match the size of the store';
|
||||
}
|
||||
|
||||
my @results;
|
||||
|
||||
if( ref( $options ) eq 'HASH' ) {
|
||||
for my $index ( 0 .. @$keys - 1 ) {
|
||||
my $key = $keys->[$index];
|
||||
if( exists( $options->{ $key } ) && defined( $options->{ $key } ) ) {
|
||||
${$store->[$index]} = $options->{ $key };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub hook_server {
|
||||
return undef unless @_ >= 2;
|
||||
my $message = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $data) = ( HexChat::PRI_NORM, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority data)],
|
||||
[\($priority, $data)],
|
||||
);
|
||||
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $hook = HexChat::Internal::hook_server(
|
||||
$message, $priority, $callback, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_command {
|
||||
return undef unless @_ >= 2;
|
||||
my $command = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $help_text, $data) = ( HexChat::PRI_NORM, undef, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority help_text data)],
|
||||
[\($priority, $help_text, $data)],
|
||||
);
|
||||
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $hook = HexChat::Internal::hook_command(
|
||||
$command, $priority, $callback, $help_text, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_print {
|
||||
return undef unless @_ >= 2;
|
||||
my $event = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $run_after, $filter, $data) = ( HexChat::PRI_NORM, 0, 0, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority run_after_event filter data)],
|
||||
[\($priority, $run_after, $filter, $data)],
|
||||
);
|
||||
|
||||
if( $run_after and $filter ) {
|
||||
Carp::carp( "HexChat::hook_print's run_after_event and filter options are mutually exclusive, you can only use of them at a time per hook" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( $run_after ) {
|
||||
my $cb = $callback;
|
||||
$callback = sub {
|
||||
my @args = @_;
|
||||
hook_timer( 0, sub {
|
||||
$cb->( @args );
|
||||
|
||||
if( ref $run_after eq 'CODE' ) {
|
||||
$run_after->( @args );
|
||||
}
|
||||
return REMOVE;
|
||||
});
|
||||
return EAT_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
if( $filter ) {
|
||||
my $cb = $callback;
|
||||
$callback = sub {
|
||||
my @args = @{$_[0]};
|
||||
my $event_data = $_[1];
|
||||
my $event_name = $event;
|
||||
my $last_arg = @args - 1;
|
||||
|
||||
my @new = $cb->( \@args, $event_data, $event_name );
|
||||
|
||||
# allow changing event by returning the new value
|
||||
if( @new > @args ) {
|
||||
$event_name = pop @new;
|
||||
}
|
||||
|
||||
# a filter can either return the new results or it can modify
|
||||
# @_ in place.
|
||||
if( @new == @args ) {
|
||||
emit_print( $event_name, @new[ 0 .. $last_arg ] );
|
||||
return EAT_ALL;
|
||||
} elsif(
|
||||
join( "\0", @{$_[0]} ) ne join( "\0", @args[ 0 .. $last_arg ] )
|
||||
) {
|
||||
emit_print( $event_name, @args[ 0 .. $last_arg ] );
|
||||
return EAT_ALL;
|
||||
}
|
||||
|
||||
return EAT_NONE;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $hook = HexChat::Internal::hook_print(
|
||||
$event, $priority, $callback, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_timer {
|
||||
return undef unless @_ >= 2;
|
||||
my ($timeout, $callback, $data) = @_;
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
if(
|
||||
ref( $data ) eq 'HASH' && exists( $data->{data} )
|
||||
&& defined( $data->{data} )
|
||||
) {
|
||||
$data = $data->{data};
|
||||
}
|
||||
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $hook = HexChat::Internal::hook_timer( $timeout, $callback, $data, $package );
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_fd {
|
||||
return undef unless @_ >= 2;
|
||||
my ($fd, $callback, $options) = @_;
|
||||
return undef unless defined $fd && defined $callback;
|
||||
|
||||
my $fileno = fileno $fd;
|
||||
return undef unless defined $fileno; # no underlying fd for this handle
|
||||
|
||||
my ($package, $calling_package) = HexChat::Embed::find_pkg();
|
||||
$callback = HexChat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($flags, $data) = (HexChat::FD_READ, undef);
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(flags data)],
|
||||
[\($flags, $data)],
|
||||
);
|
||||
|
||||
my $cb = sub {
|
||||
my $userdata = shift;
|
||||
return $userdata->{CB}->(
|
||||
$userdata->{FD}, $userdata->{FLAGS}, $userdata->{DATA},
|
||||
);
|
||||
};
|
||||
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
my $hook = HexChat::Internal::hook_fd(
|
||||
$fileno, $cb, $flags, {
|
||||
DATA => $data, FD => $fd, CB => $callback, FLAGS => $flags,
|
||||
},
|
||||
$package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub unhook {
|
||||
my $hook = shift @_;
|
||||
my $package = shift @_;
|
||||
($package) = caller unless $package;
|
||||
my $pkg_info = HexChat::Embed::pkg_info( $package );
|
||||
|
||||
if( defined( $hook )
|
||||
&& $hook =~ /^\d+$/
|
||||
&& grep { $_ == $hook } @{$pkg_info->{hooks}} ) {
|
||||
$pkg_info->{hooks} = [grep { $_ != $hook } @{$pkg_info->{hooks}}];
|
||||
return HexChat::Internal::unhook( $hook );
|
||||
}
|
||||
return ();
|
||||
}
|
||||
|
||||
sub _do_for_each {
|
||||
my ($cb, $channels, $servers) = @_;
|
||||
|
||||
# not specifying any channels or servers is not the same as specifying
|
||||
# undef for both
|
||||
# - not specifying either results in calling the callback inthe current ctx
|
||||
# - specifying undef for for both results in calling the callback in the
|
||||
# front/currently selected tab
|
||||
if( @_ == 3 && !($channels || $servers) ) {
|
||||
$channels = [ undef ];
|
||||
$servers = [ undef ];
|
||||
} elsif( !($channels || $servers) ) {
|
||||
$cb->();
|
||||
return 1;
|
||||
}
|
||||
|
||||
$channels = [ $channels ] unless ref( $channels ) eq 'ARRAY';
|
||||
|
||||
if( $servers ) {
|
||||
$servers = [ $servers ] unless ref( $servers ) eq 'ARRAY';
|
||||
} else {
|
||||
$servers = [ undef ];
|
||||
}
|
||||
|
||||
my $num_done = 0;
|
||||
my $old_ctx = HexChat::get_context();
|
||||
for my $server ( @$servers ) {
|
||||
for my $channel ( @$channels ) {
|
||||
if( HexChat::set_context( $channel, $server ) ) {
|
||||
$cb->();
|
||||
$num_done++
|
||||
}
|
||||
}
|
||||
}
|
||||
HexChat::set_context( $old_ctx );
|
||||
return $num_done;
|
||||
}
|
||||
|
||||
sub print {
|
||||
my $text = shift @_;
|
||||
return "" unless defined $text;
|
||||
if( ref( $text ) eq 'ARRAY' ) {
|
||||
if( $, ) {
|
||||
$text = join $, , @$text;
|
||||
} else {
|
||||
$text = join "", @$text;
|
||||
}
|
||||
}
|
||||
|
||||
return _do_for_each(
|
||||
sub { HexChat::Internal::print( $text ); },
|
||||
@_
|
||||
);
|
||||
}
|
||||
|
||||
sub printf {
|
||||
my $format = shift;
|
||||
HexChat::print( sprintf( $format, @_ ) );
|
||||
}
|
||||
|
||||
# make HexChat::prnt() and HexChat::prntf() as aliases for HexChat::print() and
|
||||
# HexChat::printf(), mainly useful when these functions are exported
|
||||
sub prnt {
|
||||
goto &HexChat::print;
|
||||
}
|
||||
|
||||
sub prntf {
|
||||
goto &HexChat::printf;
|
||||
}
|
||||
|
||||
sub command {
|
||||
my $command = shift;
|
||||
return "" unless defined $command;
|
||||
my @commands;
|
||||
|
||||
if( ref( $command ) eq 'ARRAY' ) {
|
||||
@commands = @$command;
|
||||
} else {
|
||||
@commands = ($command);
|
||||
}
|
||||
|
||||
return _do_for_each(
|
||||
sub { HexChat::Internal::command( $_ ) foreach @commands },
|
||||
@_
|
||||
);
|
||||
}
|
||||
|
||||
sub commandf {
|
||||
my $format = shift;
|
||||
HexChat::command( sprintf( $format, @_ ) );
|
||||
}
|
||||
|
||||
sub plugin_pref_set {
|
||||
my $setting = shift // return 0;
|
||||
my $value = shift // return 0;
|
||||
|
||||
return HexChat::Internal::plugin_pref_set($setting, $value);
|
||||
}
|
||||
|
||||
sub plugin_pref_get {
|
||||
my $setting = shift // return 0;
|
||||
|
||||
return HexChat::Internal::plugin_pref_get($setting);
|
||||
}
|
||||
|
||||
sub plugin_pref_delete {
|
||||
my $setting = shift // return 0;
|
||||
|
||||
return HexChat::Internal::plugin_pref_delete($setting);
|
||||
}
|
||||
|
||||
sub plugin_pref_list {
|
||||
my %list = HexChat::Internal::plugin_pref_list();
|
||||
|
||||
return \%list;
|
||||
}
|
||||
|
||||
sub set_context {
|
||||
my $context;
|
||||
if( @_ == 2 ) {
|
||||
my ($channel, $server) = @_;
|
||||
$context = HexChat::find_context( $channel, $server );
|
||||
} elsif( @_ == 1 ) {
|
||||
if( defined $_[0] && $_[0] =~ /^\d+$/ ) {
|
||||
$context = $_[0];
|
||||
} else {
|
||||
$context = HexChat::find_context( $_[0] );
|
||||
}
|
||||
} elsif( @_ == 0 ) {
|
||||
$context = HexChat::find_context();
|
||||
}
|
||||
return $context ? HexChat::Internal::set_context( $context ) : 0;
|
||||
}
|
||||
|
||||
sub get_info {
|
||||
my $id = shift;
|
||||
my $info;
|
||||
|
||||
if( defined( $id ) ) {
|
||||
if( grep { $id eq $_ } qw(state_cursor id) ) {
|
||||
$info = HexChat::get_prefs( $id );
|
||||
} else {
|
||||
$info = HexChat::Internal::get_info( $id );
|
||||
}
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
sub user_info {
|
||||
my $nick = HexChat::strip_code(shift @_ || HexChat::get_info( "nick" ));
|
||||
my $user;
|
||||
for (HexChat::get_list( "users" ) ) {
|
||||
if ( HexChat::nickcmp( $_->{nick}, $nick ) == 0 ) {
|
||||
$user = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
sub context_info {
|
||||
my $ctx = shift @_ || HexChat::get_context;
|
||||
my $old_ctx = HexChat::get_context;
|
||||
my @fields = (
|
||||
qw(away channel charset host id inputbox libdirfs modes network),
|
||||
qw(nick nickserv server topic version win_ptr win_status),
|
||||
qw(configdir xchatdir xchatdirfs state_cursor),
|
||||
);
|
||||
|
||||
if( HexChat::set_context( $ctx ) ) {
|
||||
my %info;
|
||||
for my $field ( @fields ) {
|
||||
$info{$field} = HexChat::get_info( $field );
|
||||
}
|
||||
|
||||
my $ctx_info = HexChat::Internal::context_info;
|
||||
@info{keys %$ctx_info} = values %$ctx_info;
|
||||
|
||||
HexChat::set_context( $old_ctx );
|
||||
return \%info;
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_list {
|
||||
unless( grep { $_[0] eq $_ } qw(channels dcc ignore notify users networks) ) {
|
||||
Carp::carp( "'$_[0]' does not appear to be a valid list name" );
|
||||
}
|
||||
if( $_[0] eq 'networks' ) {
|
||||
return HexChat::List::Network->get();
|
||||
} else {
|
||||
return HexChat::Internal::get_list( $_[0] );
|
||||
}
|
||||
}
|
||||
|
||||
sub strip_code {
|
||||
my $pattern = qr<
|
||||
\cB| #Bold
|
||||
\cC\d{0,2}(?:,\d{1,2})?| #Color
|
||||
\e\[(?:\d{1,2}(?:;\d{1,2})*)?m| # ANSI color code
|
||||
\cG| #Beep
|
||||
\cO| #Reset
|
||||
\cV| #Reverse
|
||||
\c_ #Underline
|
||||
>x;
|
||||
|
||||
if( defined wantarray ) {
|
||||
my $msg = shift;
|
||||
$msg =~ s/$pattern//g;
|
||||
return $msg;
|
||||
} else {
|
||||
$_[0] =~ s/$pattern//g if defined $_[0];
|
||||
}
|
||||
}
|
||||
|
||||
1
|
@@ -1,6 +1,7 @@
|
||||
package Xchat::Embed;
|
||||
package HexChat::Embed;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
# list of loaded scripts keyed by their package names
|
||||
# The package names are generated from the filename of the script using
|
||||
# the file2pkg() function.
|
||||
@@ -42,11 +43,11 @@ sub load {
|
||||
if( exists $scripts{$package} ) {
|
||||
my $pkg_info = pkg_info( $package );
|
||||
my $filename = File::Basename::basename( $pkg_info->{filename} );
|
||||
Xchat::printf(
|
||||
HexChat::printf(
|
||||
qq{'%s' already loaded from '%s'.\n},
|
||||
$filename, $pkg_info->{filename}
|
||||
);
|
||||
Xchat::print(
|
||||
HexChat::print(
|
||||
'If this is a different script then it rename and try '.
|
||||
'loading it again.'
|
||||
);
|
||||
@@ -60,7 +61,7 @@ sub load {
|
||||
$source =~ s/^__END__.*//ms;
|
||||
|
||||
# this must come before the eval or the filename will not be found in
|
||||
# Xchat::register
|
||||
# HexChat::register
|
||||
$scripts{$package}{filename} = $file;
|
||||
$scripts{$package}{loaded_at} = Time::HiRes::time();
|
||||
|
||||
@@ -93,7 +94,7 @@ sub load {
|
||||
$error_message .= " $conflict_package already defined in " .
|
||||
pkg_info($owner_package{ $conflict_package })->{filename}."\n";
|
||||
}
|
||||
Xchat::print( $error_message );
|
||||
HexChat::print( $error_message );
|
||||
|
||||
return 2;
|
||||
}
|
||||
@@ -114,7 +115,7 @@ sub load {
|
||||
|
||||
unless( exists $scripts{$package}{gui_entry} ) {
|
||||
$scripts{$package}{gui_entry} =
|
||||
Xchat::Internal::register(
|
||||
HexChat::Internal::register(
|
||||
"", "unknown", "", $file
|
||||
);
|
||||
}
|
||||
@@ -122,13 +123,13 @@ sub load {
|
||||
if( $@ ) {
|
||||
# something went wrong
|
||||
$@ =~ s/\(eval \d+\)/$file/g;
|
||||
Xchat::print( "Error loading '$file':\n$@\n" );
|
||||
HexChat::print( "Error loading '$file':\n$@\n" );
|
||||
# make sure the script list doesn't contain false information
|
||||
unload( $scripts{$package}{filename} );
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
Xchat::print( "Error opening '$file': $!\n" );
|
||||
HexChat::print( "Error opening '$file': $!\n" );
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -162,7 +163,7 @@ sub unload {
|
||||
|
||||
if( exists $pkg_info->{hooks} ) {
|
||||
for my $hook ( @{$pkg_info->{hooks}} ) {
|
||||
Xchat::unhook( $hook, $package );
|
||||
HexChat::unhook( $hook, $package );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +177,10 @@ sub unload {
|
||||
}
|
||||
Symbol::delete_package( $package );
|
||||
delete $scripts{$package};
|
||||
return Xchat::EAT_ALL;
|
||||
return HexChat::EAT_ALL;
|
||||
} else {
|
||||
Xchat::print( qq{"$file" is not loaded.\n} );
|
||||
return Xchat::EAT_NONE;
|
||||
HexChat::print( qq{"$file" is not loaded.\n} );
|
||||
return HexChat::EAT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +189,7 @@ sub unload_all {
|
||||
unload( $scripts{$package}->{filename} );
|
||||
}
|
||||
|
||||
return Xchat::EAT_ALL;
|
||||
return HexChat::EAT_ALL;
|
||||
}
|
||||
|
||||
sub reload {
|
||||
@@ -203,11 +204,11 @@ sub reload {
|
||||
}
|
||||
|
||||
load( $fullpath );
|
||||
return Xchat::EAT_ALL;
|
||||
return HexChat::EAT_ALL;
|
||||
}
|
||||
|
||||
sub reload_all {
|
||||
my @dirs = Xchat::get_info( "configdir" );
|
||||
my @dirs = HexChat::get_info( "configdir" );
|
||||
push @dirs, File::Spec->catdir( $dirs[0], "plugins" );
|
||||
for my $dir ( @dirs ) {
|
||||
my $auto_load_glob = File::Spec->catfile( $dir, "*.pl" );
|
||||
@@ -227,6 +228,28 @@ sub reload_all {
|
||||
}
|
||||
}
|
||||
|
||||
sub evaluate {
|
||||
my ($code) = @_;
|
||||
|
||||
my @results = eval $code;
|
||||
HexChat::print $@ if $@; #print warnings
|
||||
|
||||
local $Data::Dumper::Sortkeys = 1;
|
||||
local $Data::Dumper::Terse = 1;
|
||||
|
||||
if (@results > 1) {
|
||||
HexChat::print Dumper \@results;
|
||||
}
|
||||
elsif (ref $results[0] || !$results[0]) {
|
||||
HexChat::print Dumper $results[0];
|
||||
}
|
||||
else {
|
||||
HexChat::print $results[0];
|
||||
}
|
||||
|
||||
return HexChat::EAT_HEXCHAT;
|
||||
};
|
||||
|
||||
sub expand_homedir {
|
||||
my $file = shift @_;
|
||||
|
||||
@@ -244,7 +267,7 @@ sub file2pkg {
|
||||
my $string = File::Basename::basename( shift @_ );
|
||||
$string =~ s/\.pl$//i;
|
||||
$string =~ s|([^A-Za-z0-9/])|'_'.unpack("H*",$1)|eg;
|
||||
return "Xchat::Script::" . $string;
|
||||
return "HexChat::Script::" . $string;
|
||||
}
|
||||
|
||||
sub pkg_info {
|
||||
@@ -256,7 +279,7 @@ sub find_external_pkg {
|
||||
my $level = 1;
|
||||
|
||||
while( my @frame = caller( $level ) ) {
|
||||
return @frame if $frame[0] !~ /(?:^IRC$|^Xchat)/;
|
||||
return @frame if $frame[0] !~ /(?:^IRC$|^HexChat)/;
|
||||
$level++;
|
||||
}
|
||||
return;
|
||||
@@ -266,7 +289,7 @@ sub find_pkg {
|
||||
my $level = 1;
|
||||
|
||||
while( my ($package, $file, $line) = caller( $level ) ) {
|
||||
return $package if $package =~ /^Xchat::Script::/;
|
||||
return $package if $package =~ /^HexChat::Script::/;
|
||||
$level++;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package Xchat::List::Network;
|
||||
package HexChat::List::Network;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Storable qw(dclone);
|
||||
@@ -6,7 +6,7 @@ my $last_modified;
|
||||
my @servers;
|
||||
|
||||
sub get {
|
||||
my $server_file = Xchat::get_info( "configdir" ) . "/servlist.conf";
|
||||
my $server_file = HexChat::get_info( "configdir" ) . "/servlist.conf";
|
||||
|
||||
# recreate the list only if the server list file has changed
|
||||
if( -f $server_file &&
|
||||
@@ -19,7 +19,7 @@ sub get {
|
||||
while( my $record = <$fh> ) {
|
||||
chomp $record;
|
||||
next if $record =~ /^v=/; # skip the version line
|
||||
push @servers, Xchat::List::Network::Entry::parse( $record );
|
||||
push @servers, HexChat::List::Network::Entry::parse( $record );
|
||||
}
|
||||
} else {
|
||||
warn "Unable to open '$server_file': $!";
|
@@ -1,4 +1,4 @@
|
||||
package Xchat::List::Network::AutoJoin;
|
||||
package HexChat::List::Network::AutoJoin;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package Xchat::List::Network::Entry;
|
||||
package HexChat::List::Network::Entry;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
@@ -26,7 +26,7 @@ sub parse {
|
||||
|
||||
# the order of the channels need to be maintained
|
||||
# list of { channel => .., key => ... }
|
||||
autojoins => Xchat::List::Network::AutoJoin->new( '' ),
|
||||
autojoins => HexChat::List::Network::AutoJoin->new( '' ),
|
||||
connect_commands => [],
|
||||
flags => {},
|
||||
selected => undef,
|
||||
@@ -39,7 +39,7 @@ sub parse {
|
||||
my @fields = split /\n/, $data;
|
||||
chomp @fields;
|
||||
|
||||
$entry->{ autojoins } = Xchat::List::Network::AutoJoin->new();
|
||||
$entry->{ autojoins } = HexChat::List::Network::AutoJoin->new();
|
||||
|
||||
for my $field ( @fields ) {
|
||||
SWITCH: for ( $field ) {
|
@@ -1,525 +1 @@
|
||||
$SIG{__WARN__} = sub {
|
||||
my $message = shift @_;
|
||||
my ($package) = caller;
|
||||
|
||||
# redirect Gtk/Glib errors and warnings back to STDERR
|
||||
my $message_levels = qr/ERROR|CRITICAL|WARNING|MESSAGE|INFO|DEBUG/i;
|
||||
if( $message =~ /^(?:Gtk|GLib|Gdk)(?:-\w+)?-$message_levels/i ) {
|
||||
print STDERR $message;
|
||||
} else {
|
||||
|
||||
if( defined &Xchat::Internal::print ) {
|
||||
Xchat::print( $message );
|
||||
} else {
|
||||
warn $message;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
use File::Spec ();
|
||||
use File::Basename ();
|
||||
use File::Glob ();
|
||||
use List::Util ();
|
||||
use Symbol();
|
||||
use Time::HiRes ();
|
||||
use Carp ();
|
||||
|
||||
package Xchat;
|
||||
use base qw(Exporter);
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub PRI_HIGHEST ();
|
||||
sub PRI_HIGH ();
|
||||
sub PRI_NORM ();
|
||||
sub PRI_LOW ();
|
||||
sub PRI_LOWEST ();
|
||||
|
||||
sub EAT_NONE ();
|
||||
sub EAT_XCHAT ();
|
||||
sub EAT_PLUIN ();
|
||||
sub EAT_ALL ();
|
||||
|
||||
sub KEEP ();
|
||||
sub REMOVE ();
|
||||
sub FD_READ ();
|
||||
sub FD_WRITE ();
|
||||
sub FD_EXCEPTION ();
|
||||
sub FD_NOTSOCKET ();
|
||||
|
||||
sub get_context;
|
||||
sub Xchat::Internal::context_info;
|
||||
sub Xchat::Internal::print;
|
||||
|
||||
our %EXPORT_TAGS = (
|
||||
constants => [
|
||||
qw(PRI_HIGHEST PRI_HIGH PRI_NORM PRI_LOW PRI_LOWEST), # priorities
|
||||
qw(EAT_NONE EAT_XCHAT EAT_PLUGIN EAT_ALL), # callback return values
|
||||
qw(FD_READ FD_WRITE FD_EXCEPTION FD_NOTSOCKET), # fd flags
|
||||
qw(KEEP REMOVE), # timers
|
||||
],
|
||||
hooks => [
|
||||
qw(hook_server hook_command hook_print hook_timer hook_fd unhook),
|
||||
],
|
||||
util => [
|
||||
qw(register nickcmp strip_code send_modes), # misc
|
||||
qw(print prnt printf prntf command commandf emit_print), # output
|
||||
qw(find_context get_context set_context), # context
|
||||
qw(get_info get_prefs get_list context_info user_info), # input
|
||||
],
|
||||
);
|
||||
|
||||
$EXPORT_TAGS{all} = [ map { @{$_} } @EXPORT_TAGS{qw(constants hooks util)}];
|
||||
our @EXPORT = @{$EXPORT_TAGS{constants}};
|
||||
our @EXPORT_OK = @{$EXPORT_TAGS{all}};
|
||||
|
||||
sub register {
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $filename = $pkg_info->{filename};
|
||||
my ($name, $version, $description, $callback) = @_;
|
||||
|
||||
if( defined $pkg_info->{gui_entry} ) {
|
||||
Xchat::print( "Xchat::register called more than once in "
|
||||
. $pkg_info->{filename} );
|
||||
return ();
|
||||
}
|
||||
|
||||
$description = "" unless defined $description;
|
||||
if( $callback ) {
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
}
|
||||
$pkg_info->{shutdown} = $callback;
|
||||
unless( $name && $name =~ /[[:print:]\w]/ ) {
|
||||
$name = "Not supplied";
|
||||
}
|
||||
unless( $version && $version =~ /\d+(?:\.\d+)?/ ) {
|
||||
$version = "NaN";
|
||||
}
|
||||
$pkg_info->{gui_entry} =
|
||||
Xchat::Internal::register( $name, $version, $description, $filename );
|
||||
# keep with old behavior
|
||||
return ();
|
||||
}
|
||||
|
||||
sub _process_hook_options {
|
||||
my ($options, $keys, $store) = @_;
|
||||
|
||||
unless( @$keys == @$store ) {
|
||||
die 'Number of keys must match the size of the store';
|
||||
}
|
||||
|
||||
my @results;
|
||||
|
||||
if( ref( $options ) eq 'HASH' ) {
|
||||
for my $index ( 0 .. @$keys - 1 ) {
|
||||
my $key = $keys->[$index];
|
||||
if( exists( $options->{ $key } ) && defined( $options->{ $key } ) ) {
|
||||
${$store->[$index]} = $options->{ $key };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub hook_server {
|
||||
return undef unless @_ >= 2;
|
||||
my $message = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $data) = ( Xchat::PRI_NORM, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority data)],
|
||||
[\($priority, $data)],
|
||||
);
|
||||
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $hook = Xchat::Internal::hook_server(
|
||||
$message, $priority, $callback, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_command {
|
||||
return undef unless @_ >= 2;
|
||||
my $command = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $help_text, $data) = ( Xchat::PRI_NORM, undef, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority help_text data)],
|
||||
[\($priority, $help_text, $data)],
|
||||
);
|
||||
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $hook = Xchat::Internal::hook_command(
|
||||
$command, $priority, $callback, $help_text, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_print {
|
||||
return undef unless @_ >= 2;
|
||||
my $event = shift;
|
||||
my $callback = shift;
|
||||
my $options = shift;
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($priority, $run_after, $filter, $data) = ( Xchat::PRI_NORM, 0, 0, undef );
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(priority run_after_event filter data)],
|
||||
[\($priority, $run_after, $filter, $data)],
|
||||
);
|
||||
|
||||
if( $run_after and $filter ) {
|
||||
Carp::carp( "Xchat::hook_print's run_after_event and filter options are mutually exclusive, you can only use of them at a time per hook" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( $run_after ) {
|
||||
my $cb = $callback;
|
||||
$callback = sub {
|
||||
my @args = @_;
|
||||
hook_timer( 0, sub {
|
||||
$cb->( @args );
|
||||
|
||||
if( ref $run_after eq 'CODE' ) {
|
||||
$run_after->( @args );
|
||||
}
|
||||
return REMOVE;
|
||||
});
|
||||
return EAT_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
if( $filter ) {
|
||||
my $cb = $callback;
|
||||
$callback = sub {
|
||||
my @args = @{$_[0]};
|
||||
my $event_data = $_[1];
|
||||
my $event_name = $event;
|
||||
my $last_arg = @args - 1;
|
||||
|
||||
my @new = $cb->( \@args, $event_data, $event_name );
|
||||
|
||||
# allow changing event by returning the new value
|
||||
if( @new > @args ) {
|
||||
$event_name = pop @new;
|
||||
}
|
||||
|
||||
# a filter can either return the new results or it can modify
|
||||
# @_ in place.
|
||||
if( @new == @args ) {
|
||||
emit_print( $event_name, @new[ 0 .. $last_arg ] );
|
||||
return EAT_ALL;
|
||||
} elsif(
|
||||
join( "\0", @{$_[0]} ) ne join( "\0", @args[ 0 .. $last_arg ] )
|
||||
) {
|
||||
emit_print( $event_name, @args[ 0 .. $last_arg ] );
|
||||
return EAT_ALL;
|
||||
}
|
||||
|
||||
return EAT_NONE;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $hook = Xchat::Internal::hook_print(
|
||||
$event, $priority, $callback, $data, $package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_timer {
|
||||
return undef unless @_ >= 2;
|
||||
my ($timeout, $callback, $data) = @_;
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
if(
|
||||
ref( $data ) eq 'HASH' && exists( $data->{data} )
|
||||
&& defined( $data->{data} )
|
||||
) {
|
||||
$data = $data->{data};
|
||||
}
|
||||
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $hook = Xchat::Internal::hook_timer( $timeout, $callback, $data, $package );
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub hook_fd {
|
||||
return undef unless @_ >= 2;
|
||||
my ($fd, $callback, $options) = @_;
|
||||
return undef unless defined $fd && defined $callback;
|
||||
|
||||
my $fileno = fileno $fd;
|
||||
return undef unless defined $fileno; # no underlying fd for this handle
|
||||
|
||||
my ($package, $calling_package) = Xchat::Embed::find_pkg();
|
||||
$callback = Xchat::Embed::fix_callback(
|
||||
$package, $calling_package, $callback
|
||||
);
|
||||
|
||||
my ($flags, $data) = (Xchat::FD_READ, undef);
|
||||
_process_hook_options(
|
||||
$options,
|
||||
[qw(flags data)],
|
||||
[\($flags, $data)],
|
||||
);
|
||||
|
||||
my $cb = sub {
|
||||
my $userdata = shift;
|
||||
return $userdata->{CB}->(
|
||||
$userdata->{FD}, $userdata->{FLAGS}, $userdata->{DATA},
|
||||
);
|
||||
};
|
||||
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
my $hook = Xchat::Internal::hook_fd(
|
||||
$fileno, $cb, $flags, {
|
||||
DATA => $data, FD => $fd, CB => $callback, FLAGS => $flags,
|
||||
},
|
||||
$package
|
||||
);
|
||||
push @{$pkg_info->{hooks}}, $hook if defined $hook;
|
||||
return $hook;
|
||||
}
|
||||
|
||||
sub unhook {
|
||||
my $hook = shift @_;
|
||||
my $package = shift @_;
|
||||
($package) = caller unless $package;
|
||||
my $pkg_info = Xchat::Embed::pkg_info( $package );
|
||||
|
||||
if( defined( $hook )
|
||||
&& $hook =~ /^\d+$/
|
||||
&& grep { $_ == $hook } @{$pkg_info->{hooks}} ) {
|
||||
$pkg_info->{hooks} = [grep { $_ != $hook } @{$pkg_info->{hooks}}];
|
||||
return Xchat::Internal::unhook( $hook );
|
||||
}
|
||||
return ();
|
||||
}
|
||||
|
||||
sub _do_for_each {
|
||||
my ($cb, $channels, $servers) = @_;
|
||||
|
||||
# not specifying any channels or servers is not the same as specifying
|
||||
# undef for both
|
||||
# - not specifying either results in calling the callback inthe current ctx
|
||||
# - specifying undef for for both results in calling the callback in the
|
||||
# front/currently selected tab
|
||||
if( @_ == 3 && !($channels || $servers) ) {
|
||||
$channels = [ undef ];
|
||||
$servers = [ undef ];
|
||||
} elsif( !($channels || $servers) ) {
|
||||
$cb->();
|
||||
return 1;
|
||||
}
|
||||
|
||||
$channels = [ $channels ] unless ref( $channels ) eq 'ARRAY';
|
||||
|
||||
if( $servers ) {
|
||||
$servers = [ $servers ] unless ref( $servers ) eq 'ARRAY';
|
||||
} else {
|
||||
$servers = [ undef ];
|
||||
}
|
||||
|
||||
my $num_done = 0;
|
||||
my $old_ctx = Xchat::get_context();
|
||||
for my $server ( @$servers ) {
|
||||
for my $channel ( @$channels ) {
|
||||
if( Xchat::set_context( $channel, $server ) ) {
|
||||
$cb->();
|
||||
$num_done++
|
||||
}
|
||||
}
|
||||
}
|
||||
Xchat::set_context( $old_ctx );
|
||||
return $num_done;
|
||||
}
|
||||
|
||||
sub print {
|
||||
my $text = shift @_;
|
||||
return "" unless defined $text;
|
||||
if( ref( $text ) eq 'ARRAY' ) {
|
||||
if( $, ) {
|
||||
$text = join $, , @$text;
|
||||
} else {
|
||||
$text = join "", @$text;
|
||||
}
|
||||
}
|
||||
|
||||
return _do_for_each(
|
||||
sub { Xchat::Internal::print( $text ); },
|
||||
@_
|
||||
);
|
||||
}
|
||||
|
||||
sub printf {
|
||||
my $format = shift;
|
||||
Xchat::print( sprintf( $format, @_ ) );
|
||||
}
|
||||
|
||||
# make Xchat::prnt() and Xchat::prntf() as aliases for Xchat::print() and
|
||||
# Xchat::printf(), mainly useful when these functions are exported
|
||||
sub prnt {
|
||||
goto &Xchat::print;
|
||||
}
|
||||
|
||||
sub prntf {
|
||||
goto &Xchat::printf;
|
||||
}
|
||||
|
||||
sub command {
|
||||
my $command = shift;
|
||||
return "" unless defined $command;
|
||||
my @commands;
|
||||
|
||||
if( ref( $command ) eq 'ARRAY' ) {
|
||||
@commands = @$command;
|
||||
} else {
|
||||
@commands = ($command);
|
||||
}
|
||||
|
||||
return _do_for_each(
|
||||
sub { Xchat::Internal::command( $_ ) foreach @commands },
|
||||
@_
|
||||
);
|
||||
}
|
||||
|
||||
sub commandf {
|
||||
my $format = shift;
|
||||
Xchat::command( sprintf( $format, @_ ) );
|
||||
}
|
||||
|
||||
sub set_context {
|
||||
my $context;
|
||||
if( @_ == 2 ) {
|
||||
my ($channel, $server) = @_;
|
||||
$context = Xchat::find_context( $channel, $server );
|
||||
} elsif( @_ == 1 ) {
|
||||
if( defined $_[0] && $_[0] =~ /^\d+$/ ) {
|
||||
$context = $_[0];
|
||||
} else {
|
||||
$context = Xchat::find_context( $_[0] );
|
||||
}
|
||||
} elsif( @_ == 0 ) {
|
||||
$context = Xchat::find_context();
|
||||
}
|
||||
return $context ? Xchat::Internal::set_context( $context ) : 0;
|
||||
}
|
||||
|
||||
sub get_info {
|
||||
my $id = shift;
|
||||
my $info;
|
||||
|
||||
if( defined( $id ) ) {
|
||||
if( grep { $id eq $_ } qw(state_cursor id) ) {
|
||||
$info = Xchat::get_prefs( $id );
|
||||
} else {
|
||||
$info = Xchat::Internal::get_info( $id );
|
||||
}
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
sub user_info {
|
||||
my $nick = Xchat::strip_code(shift @_ || Xchat::get_info( "nick" ));
|
||||
my $user;
|
||||
for (Xchat::get_list( "users" ) ) {
|
||||
if ( Xchat::nickcmp( $_->{nick}, $nick ) == 0 ) {
|
||||
$user = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
sub context_info {
|
||||
my $ctx = shift @_ || Xchat::get_context;
|
||||
my $old_ctx = Xchat::get_context;
|
||||
my @fields = (
|
||||
qw(away channel charset host id inputbox libdirfs modes network),
|
||||
qw(nick nickserv server topic version win_ptr win_status),
|
||||
qw(configdir xchatdir xchatdirfs state_cursor),
|
||||
);
|
||||
|
||||
if( Xchat::set_context( $ctx ) ) {
|
||||
my %info;
|
||||
for my $field ( @fields ) {
|
||||
$info{$field} = Xchat::get_info( $field );
|
||||
}
|
||||
|
||||
my $ctx_info = Xchat::Internal::context_info;
|
||||
@info{keys %$ctx_info} = values %$ctx_info;
|
||||
|
||||
Xchat::set_context( $old_ctx );
|
||||
return %info if wantarray;
|
||||
return \%info;
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_list {
|
||||
unless( grep { $_[0] eq $_ } qw(channels dcc ignore notify users networks) ) {
|
||||
Carp::carp( "'$_[0]' does not appear to be a valid list name" );
|
||||
}
|
||||
if( $_[0] eq 'networks' ) {
|
||||
return Xchat::List::Network->get();
|
||||
} else {
|
||||
return Xchat::Internal::get_list( $_[0] );
|
||||
}
|
||||
}
|
||||
|
||||
sub strip_code {
|
||||
my $pattern = qr<
|
||||
\cB| #Bold
|
||||
\cC\d{0,2}(?:,\d{1,2})?| #Color
|
||||
\e\[(?:\d{1,2}(?:;\d{1,2})*)?m| # ANSI color code
|
||||
\cG| #Beep
|
||||
\cO| #Reset
|
||||
\cV| #Reverse
|
||||
\c_ #Underline
|
||||
>x;
|
||||
|
||||
if( defined wantarray ) {
|
||||
my $msg = shift;
|
||||
$msg =~ s/$pattern//g;
|
||||
return $msg;
|
||||
} else {
|
||||
$_[0] =~ s/$pattern//g if defined $_[0];
|
||||
}
|
||||
}
|
||||
|
||||
1
|
||||
require HexChat;
|
||||
|
Reference in New Issue
Block a user