some updates and fixes

* make it easier to change the displayed text
* try harder to not delete the wrong line when /ignore or other
  line-removing code is in effect
* add trackbar awareness
* correct logic flaw when re-adding joins
* rewrite /quit scanning logic
* move work to print text handler
This commit is contained in:
Ailin Nemui 2016-08-16 22:20:52 +02:00
parent 1096bfec20
commit c3f65a9968

View File

@ -1,9 +1,10 @@
use Irssi;
use strict;
use warnings;
use Irssi;
use Irssi::TextUI;
use vars qw($VERSION %IRSSI);
$VERSION = "0.0.2";
$VERSION = "0.0.5"; # d145a98c82647ab
%IRSSI = (
authors => 'Ryan Freebern',
contact => 'ryan@freebern.org',
@ -18,123 +19,172 @@ $VERSION = "0.0.2";
my %summary_lines;
use constant {
JOINS => +MSGLEVEL_JOINS,
PARTS => +MSGLEVEL_PARTS,
QUITS => +MSGLEVEL_QUITS,
NICKS => +MSGLEVEL_NICKS
};
my %msg_level_text;
# all texts and all separators must be distinguishable and one must
# not be a substring of another!
@msg_level_text{(JOINS, PARTS, QUITS, NICKS)}=qw/Joins Parts Quits Nicks/;
my $level_separator = ' ── ';
my $nick_separator = ', ';
my $type_separator = ': ';
my $new_nick_separator = ' → ';
my %msg_level_constant = reverse %msg_level_text;
sub lrtrim {
for (@_) {
s/^\s+//; s/\s+$//;
}
}
sub summarize {
my ($server, $channel, $nick, $new_nick, $type) = @_;
my ($window, $tag, $channel, $nick, $new_nick, $type) = @_;
my $window = $server->window_find_item($channel);
return if (!$window);
my $view = $window->view();
my $check = $server->{tag} . ':' . $channel;
return unless $window;
my $view = $window->view;
my $check = $tag . ':' . $channel;
my $tb = $view->get_bookmark('trackbar');
$view->set_bookmark_bottom('bottom');
my $last = $view->get_bookmark('bottom');
my $secondlast = $last->prev();
if ($tb && $last->{_irssi} == $tb->{_irssi}) {
$last = $last->prev;
}
my $secondlast = $last ? $last->prev : undef;
if ($tb && $secondlast && $secondlast->{_irssi} == $tb->{_irssi}) {
$secondlast = $secondlast->prev;
}
# Remove the last line, which should have the join/part/quit message.
return unless $last->{info}{level} & $type;
$view->remove_line($last);
# If the second-to-last line is a summary line, parse it.
my %door = ('Joins' => [], 'Parts' => [], 'Quits' => [], 'Nicks' => []);
my %door = (JOINS() => [], PARTS() => [], QUITS() => [], NICKS() => []);
my @summarized = ();
if ($secondlast and %summary_lines and $secondlast->{'_irssi'} == $summary_lines{$check}) {
my $summary = Irssi::strip_codes($secondlast->get_text(1));
@summarized = split(/ -- /, $summary);
if ($secondlast and $summary_lines{$check} and $secondlast->{_irssi} == $summary_lines{$check}) {
my $summary = $secondlast->get_text(0);
lrtrim $summary;
@summarized = split(/\Q$level_separator/, $summary);
lrtrim @summarized;
foreach my $part (@summarized) {
my ($type, $nicks) = split(/: /, $part);
$door{$type} = [ split(/, /, $nicks) ];
my ($type, $nicks) = split(/\Q$type_separator/, $part, 2);
lrtrim $nicks;
$door{$msg_level_constant{$type}} = [ split(/\Q$nick_separator/, $nicks) ];
}
$view->remove_line($secondlast);
}
if ($type eq '__revolving_door_join') { # Join
push(@{$door{'Joins'}}, $nick);
@{$door{'Parts'}} = grep { $_ ne $nick } @{$door{'Parts'}} if (scalar @{$door{'Parts'}});
@{$door{'Quits'}} = grep { $_ ne $nick } @{$door{'Quits'}} if (scalar @{$door{'Quits'}});
} elsif ($type eq '__revolving_door_quit') { # Quit
push(@{$door{'Quits'}}, $nick) if (!grep(/^\Q$nick\E$/, @{$door{'Joins'}}));
@{$door{'Joins'}} = grep { $_ ne $nick } @{$door{'Joins'}} if (scalar @{$door{'Joins'}});
} elsif ($type eq '__revolving_door_part') { # Part
push(@{$door{'Parts'}}, $nick) if (!grep(/^\Q$nick\E$/, @{$door{'Joins'}}));;
@{$door{'Joins'}} = grep { $_ ne $nick } @{$door{'Joins'}} if (scalar @{$door{'Joins'}});;
if ($type == JOINS) { # Join
if (grep { $_ eq $nick } @{$door{+PARTS}}, @{$door{+QUITS}}) {
@{$door{+PARTS}} = grep { $_ ne $nick } @{$door{+PARTS}};
@{$door{+QUITS}} = grep { $_ ne $nick } @{$door{+QUITS}};
} else {
push(@{$door{+JOINS}}, $nick);
}
} elsif ($type == QUITS) { # Quit
if (grep { $_ eq $nick } @{$door{+JOINS}}) {
@{$door{+JOINS}} = grep { $_ ne $nick } @{$door{+JOINS}};
} else {
push @{$door{+QUITS}}, $nick;
}
} elsif ($type == PARTS) { # Part
if (grep { $_ eq $nick } @{$door{+JOINS}}) {
@{$door{+JOINS}} = grep { $_ ne $nick } @{$door{+JOINS}};
} else {
push @{$door{+PARTS}}, $nick;
}
} else { # Nick
my $nick_found = 0;
foreach my $known_nick (@{$door{'Nicks'}}) {
my ($orig_nick, $current_nick) = split(/ -> /, $known_nick);
foreach my $known_nick (@{$door{+NICKS}}) {
my ($orig_nick, $current_nick) = split(/\Q$new_nick_separator/, $known_nick);
if ($new_nick eq $orig_nick) { # Changed nickname back to original.
@{$door{'Nicks'}} = grep { $_ ne "$orig_nick -> $current_nick" } @{$door{'Nicks'}};
@{$door{+NICKS}} = grep { $_ ne $known_nick } @{$door{+NICKS}};
$nick_found = 1;
last;
} elsif ($current_nick eq $nick) {
$_ =~ s/\b\Q$current_nick\E\b/$new_nick/ foreach @{$door{'Nicks'}};
$_ =~ s/\Q$new_nick_separator$current_nick\E$/$new_nick_separator$new_nick/ foreach @{$door{+NICKS}};
$nick_found = 1;
last;
}
}
if (!$nick_found) {
push(@{$door{'Nicks'}}, "$nick -> $new_nick");
push(@{$door{+NICKS}}, "$nick$new_nick_separator$new_nick");
}
# Update nicks in join/part/quit lists.
foreach my $part (qw/Joins Parts Quits/) {
$_ =~ s/\b\Q$nick\E\b/$new_nick/ foreach @{$door{$part}};
foreach my $part (JOINS, PARTS, QUITS) {
$_ =~ s/^\Q$nick\E$/$new_nick/ foreach @{$door{$part}};
}
}
@summarized = ();
foreach my $part (qw/Joins Parts Quits Nicks/) {
if (scalar @{$door{$part}}) {
push @summarized, "\%W$part:\%n " . join(', ', @{$door{$part}});
my $level = MSGLEVEL_NEVER;
foreach my $part (JOINS, PARTS, QUITS, NICKS) {
if (@{$door{$part}}) {
push @summarized, '%I' . $msg_level_text{$part} . $type_separator . '%I'
. join($nick_separator, @{$door{$part}});
$level |= $part;
}
}
my $summary = join(' -- ', @summarized);
$window->print($summary, MSGLEVEL_NEVER);
# Get the line we just printed so we can log its ID.
$view->set_bookmark_bottom('bottom');
$last = $view->get_bookmark('bottom');
$summary_lines{$check} = $last->{'_irssi'};
my $summary = join($level_separator, @summarized);
if (@summarized) {
$window->print(' 'x10 . '%|%w'.$summary, $level);
# Get the line we just printed so we can log its ID.
$view->set_bookmark_bottom('bottom');
$last = $view->get_bookmark('bottom');
$summary_lines{$check} = $last->{_irssi};
} else {
delete $summary_lines{$check};
}
$view->redraw();
}
sub delete_and_summarize {
return unless our @summary;
my ($tag, $channel, $nick, $new_nick, $type) = @summary;
my ($dest) = @_;
return unless $dest->{server} && $dest->{server}{tag} eq $tag;
return if defined $channel && $dest->{target} ne $channel;
&Irssi::signal_continue;
summarize($dest->{window}, $tag, $dest->{target}, $nick, $new_nick, $type);
}
sub summarize_join {
my ($server, $channel, $nick, $address, $reason) = @_;
&summarize($server, $channel, $nick, 0, '__revolving_door_join');
local our @summary = ($server->{tag}, $channel, $nick, undef, JOINS);
&Irssi::signal_continue;
}
sub summarize_quit {
my ($server, $nick, $address, $reason) = @_;
my @channels = $server->channels();
foreach my $channel (@channels) {
my $window = $server->window_find_item($channel->{name});
next if (!$window);
my $view = $window->view();
$view->set_bookmark_bottom('bottom');
my $last = $view->get_bookmark('bottom');
my $last_text = $last->get_text(1);
if ($last_text =~ m/\Q$nick\E.*?has quit/) {
&summarize($server, $channel->{name}, $nick, 0, '__revolving_door_quit');
}
}
local our @summary = ($server->{tag}, undef, $nick, undef, QUITS);
&Irssi::signal_continue;
}
sub summarize_part {
my ($server, $channel, $nick, $address, $reason) = @_;
&summarize($server, $channel, $nick, 0, '__revolving_door_part');
local our @summary = ($server->{tag}, $channel, $nick, undef, PARTS);
&Irssi::signal_continue;
}
sub summarize_nick {
my ($server, $new_nick, $old_nick, $address) = @_;
my @channels = $server->channels();
foreach my $channel (@channels) {
my $channel_nick = $channel->nick_find($new_nick);
if (defined $channel_nick) {
&summarize($server, $channel->{name}, $old_nick, $new_nick, '__revolving_door_nick');
}
}
local our @summary = ($server->{tag}, undef, $old_nick, $new_nick, NICKS);
&Irssi::signal_continue;
}
Irssi::signal_add_priority('message join', \&summarize_join, Irssi::SIGNAL_PRIORITY_LOW + 1);
Irssi::signal_add_priority('message part', \&summarize_part, Irssi::SIGNAL_PRIORITY_LOW + 1);
Irssi::signal_add_priority('message quit', \&summarize_quit, Irssi::SIGNAL_PRIORITY_LOW + 1);
Irssi::signal_add_priority('message nick', \&summarize_nick, Irssi::SIGNAL_PRIORITY_LOW + 1);
Irssi::signal_add('message join', 'summarize_join');
Irssi::signal_add('message part', 'summarize_part');
Irssi::signal_add('message quit', 'summarize_quit');
Irssi::signal_add('message nick', 'summarize_nick');
Irssi::signal_add('print text', 'delete_and_summarize');