summaryrefslogtreecommitdiffstats
path: root/scripts/hideshow.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/hideshow.pl')
-rw-r--r--scripts/hideshow.pl319
1 files changed, 319 insertions, 0 deletions
diff --git a/scripts/hideshow.pl b/scripts/hideshow.pl
new file mode 100644
index 0000000..fac376d
--- /dev/null
+++ b/scripts/hideshow.pl
@@ -0,0 +1,319 @@
+use strict;
+use warnings;
+
+our $VERSION = '0.4.6'; # 4cc7adcb14932da
+our %IRSSI = (
+ authors => 'Nei',
+ contact => 'Nei @ anti@conference.jabber.teamidiot.de',
+ url => "http://anti.teamidiot.de/",
+ name => 'hideshow',
+ description => 'Removes and re-adds lines to the Irssi buffer view.',
+ license => 'GNU GPLv2 or later',
+ );
+
+# Usage
+# =====
+# Use this script to hide and re-add lines into your Irssi view. You
+# can grab a custom-modified recentdepart.pl to hide smart-filtered
+# messages instead of ignore, if you do
+#
+# /set recdep_use_hideshow ON
+#
+# You can use trigger.pl with:
+#
+# /trigger add ... -command 'script exec $$Irssi::scripts::hideshow::hide_next = 1'
+#
+# instead of -stop
+
+# Options
+# =======
+# /set hideshow_level <levels>
+# * list of levels that should be hidden from view
+#
+# /set hideshow_hide <ON|OFF>
+# * if hiding is currently enabled or not. make a key binding to
+# conveniently toggle this setting (see below)
+
+# Commands
+# ========
+# you can use this key binding:
+#
+# /bind meta-= command ^toggle hideshow_hide
+#
+# /scrollback status hidden
+# * like /scrollback status, but for the hidden part (some statistics)
+
+no warnings 'redefine';
+use constant IN_IRSSI => __PACKAGE__ ne 'main' || $ENV{IRSSI_MOCK};
+use Irssi;
+use Irssi::TextUI;
+use Encode;
+use version;
+
+my $irssi_version = qv('v'.Irssi::parse_special('$J') =~ s/[^.\d].*//r);
+
+sub setc () {
+ $IRSSI{name}
+}
+
+sub set ($) {
+ setc . '_' . $_[0]
+}
+
+my (%hidden);
+
+my $DEST;
+
+my $HIDE;
+my $hide_level;
+my $ext_hidden_level = MSGLEVEL_LASTLOG << 1;
+
+
+sub show_win_lines {
+ my $win = shift;
+ my $view = $win->view;
+ my $vid = $view->{_irssi};
+ my $hl = delete $hidden{$vid};
+ return unless $hl && %$hl;
+ my $redraw;
+ my $bottom = $view->{bottom};
+ for (my $lp = $view->{buffer}{cur_line}; $lp; $lp = $lp->prev) {
+ my $nl = delete $hl->{ $lp->{_irssi} };
+ next unless $nl;
+ my $ll = $lp;
+ for my $i (@$nl) {
+ $win->gui_printtext_after($ll, $i->[1] | MSGLEVEL_NEVER, "${$i}[0]\n", $i->[2]);
+ $ll = $win->last_line_insert;
+ $redraw = 1;
+ }
+ }
+ if ($redraw) {
+ $win->command('^scrollback end') if $bottom && !$win->view->{bottom};
+ $view->redraw;
+ }
+ delete $hidden{$vid};
+}
+sub show_lines {
+ for my $win (Irssi::windows) {
+ show_win_lines($win);
+ }
+ %hidden=();
+}
+
+sub hide_win_lines {
+ my $win = shift;
+ my $view = $win->view;
+ my $vid = $view->{_irssi};
+ my $bottom = $view->{bottom};
+ my $redraw;
+ my $prev;
+ my $lid;
+ for (my $lp = $view->{buffer}{cur_line}; $lp; $lp = $prev) {
+ $prev = $lp->prev;
+ if ($prev && $lp->{info}{level} & ($hide_level | $ext_hidden_level)) {
+ push @{ $hidden{ $vid }
+ { $prev->{_irssi} }
+ }, [ $lp->get_text(1), $lp->{info}{level}, $lp->{info}{time} ],
+ $hidden{$vid}{ $lp->{_irssi } } ? @{ (delete $hidden{$vid}{ $lp->{_irssi } }) } : ();
+ $view->remove_line($lp);
+ $redraw = 1;
+ }
+ }
+ if ($redraw) {
+ $win->command('^scrollback end') if $bottom && !$win->view->{bottom};
+ $view->redraw;
+ }
+}
+
+my %hideshow_timed;
+sub show_one_timed {
+ my $hide = shift;
+ for my $win (Irssi::windows) {
+ next if $hideshow_timed{ $win->{_irssi} };
+ if ($hide) {
+ Irssi::signal_remove('gui textbuffer line removed' => 'fix_lines');
+ hide_win_lines($win);
+ Irssi::signal_add_last('gui textbuffer line removed' => 'fix_lines');
+ }
+ else {
+ show_win_lines($win);
+ }
+ $hideshow_timed{$win->{_irssi}} = 1;
+ $hideshow_timed{_timer} = Irssi::timeout_add_once(10 + int rand 10, 'show_one_timed', $hide);
+ return;
+ }
+ unless ($hide) {
+ show_lines();
+ }
+ %hideshow_timed = ();
+ hideshow() if !!$hide != !!$HIDE;
+ return 1;
+}
+sub hideshow {
+ if ($irssi_version >= v1.1.0) {
+ if ($HIDE) {
+ my $level = Irssi::bits2level($hide_level | $ext_hidden_level);
+ Irssi::command("^foreach window ^window hidelevel $level");
+ } else {
+ Irssi::command('^foreach window ^window hidelevel -all -hidden');
+ }
+ return;
+ }
+
+ # Horrible Pre Irssi 1.1 Code follows
+ if (exists $hideshow_timed{_timer}) {
+ Irssi::timeout_remove(delete $hideshow_timed{_timer});
+ }
+ %hideshow_timed = ();
+ $hideshow_timed{_timer} = Irssi::timeout_add_once(10 + int rand 10, 'show_one_timed', !!$HIDE);
+}
+
+sub setup_changed {
+ my $old_level = $hide_level;
+ $hide_level = Irssi::settings_get_level( set 'level' );
+ my $old_hidden = $HIDE;
+ $HIDE = Irssi::settings_get_bool( set 'hide' );
+ if (!defined $old_hidden || $HIDE != $old_hidden || $old_level != $hide_level) {
+ hideshow();
+ }
+}
+
+sub init_hideshow {
+ setup_changed();
+ $Irssi::scripts::hideshow::hide_next = undef;
+}
+
+sub UNLOAD {
+ if ($irssi_version >= v1.1.0) {
+ if ($irssi_version >= v1.2.0) {
+ $hide_level = Irssi::settings_get_level('window_default_hidelevel');
+ my $level = Irssi::bits2level($hide_level);
+ Irssi::command('^foreach window ^window hidelevel -all -hidden');
+ Irssi::command("^foreach window ^window hidelevel $level");
+ } else {
+ Irssi::command('^foreach window ^window hidelevel -all hidden');
+ }
+ return;
+ }
+
+ show_lines();
+}
+
+my $multi_msgs_last;
+
+sub prt_text_issue {
+ $DEST = $_[0];
+ my $stripd = $_[2];
+ if (ref $DEST && $Irssi::scripts::hideshow::hide_next) {
+ $multi_msgs_last = undef;
+ $DEST->{hide} = 1;
+ if ($DEST->{level} & (MSGLEVEL_QUITS|MSGLEVEL_NICKS)) {
+ $multi_msgs_last = $stripd;
+ }
+ }
+ elsif (ref $DEST && $DEST->{level} & (MSGLEVEL_QUITS|MSGLEVEL_NICKS)
+ && defined $multi_msgs_last && $multi_msgs_last eq $stripd) {
+ $DEST->{hide} = 1;
+ }
+ else {
+ $multi_msgs_last = undef;
+ }
+ $Irssi::scripts::hideshow::hide_next = undef;
+
+ if ($irssi_version >= v1.1.0 && ref $DEST && $DEST->{hide}) {
+ $_[0] = Irssi::Server::format_create_dest($DEST->{server}, $DEST->{target}, $DEST->{level} | $ext_hidden_level, $DEST->{window});
+ &Irssi::signal_continue;
+ }
+}
+
+sub prt_text_ref {
+ return unless ref $DEST;
+ my ($win) = @_;
+ if ($HIDE) {
+ my $view = $win->view;
+ my $vid = $view->{_irssi};
+ my $lp = $view->{buffer}{cur_line};
+ my $prev = $lp->prev;
+ if ($prev && ($DEST->{hide} || $lp->{info}{level} & $hide_level)) {
+ my $level = $lp->{info}{level};
+ $level |= $ext_hidden_level if $DEST->{hide};
+ push @{ $hidden{ $vid }
+ { $prev->{_irssi} }
+ }, [ $lp->get_text(1), $level, $lp->{info}{time} ];
+ $view->remove_line($lp);
+ delete @{ $hidden{ $vid } }
+ { (grep {
+ $view->{buffer}{first_line}{info}{time} > $hidden{$vid}{$_}[-1][2]
+ } keys %{$hidden{$vid}}) };
+ $view->redraw;
+ }
+ }
+ $DEST = undef;
+}
+
+sub fix_lines {
+ my ($view, $rem_line, $prev_line) = @_;
+ my $vid = $view->{_irssi};
+ my $nl = delete $hidden{$vid}{ $rem_line->{_irssi} };
+ if ($nl && $prev_line) {
+ push @{ $hidden{$vid} { $prev_line->{_irssi} } }, @$nl
+ }
+}
+
+sub win_del {
+ my ($win) = @_;
+ delete $hidden{ $win->view->{_irssi} };
+}
+Irssi::signal_register({
+ 'gui textbuffer line removed' => [ qw/Irssi::TextUI::TextBufferView Irssi::TextUI::Line Irssi::TextUI::Line/ ]
+});
+
+Irssi::signal_add_last({
+ 'setup changed' => 'setup_changed',
+});
+Irssi::signal_add({
+ 'print text' => 'prt_text_issue',
+});
+
+Irssi::settings_add_level( setc, set 'level', '' );
+Irssi::settings_add_bool( setc, set 'hide', 1 );
+
+
+unless ($irssi_version >= v1.1.0) {
+ Irssi::signal_add_last({
+ 'gui print text finished' => 'prt_text_ref',
+ 'gui textbuffer line removed' => 'fix_lines',
+ });
+ Irssi::signal_add({
+ 'window destroyed' => 'win_del',
+ });
+
+ Irssi::command_bind({
+ 'scrollback status' => sub {
+ if ($_[0] =~ /\S/) {
+ &Irssi::command_runsub('scrollback status', @_);
+ Irssi::signal_stop;
+ }
+ },
+ 'scrollback status hidden' => sub {
+ my %vw = map { ($_->view->{_irssi}, $_->{refnum}) } Irssi::windows;
+ my ($tl, $ta, $td) = (0, 0, 0);
+ for my $v (keys %hidden) {
+ my $hl = $hidden{$v};
+ my ($lc, $dc, $ac) = (0, 0, scalar keys %$hl);
+ for my $k (keys %$hl) {
+ my $ls = $hl->{$k};
+ $lc += @$ls;
+ $dc += 16 + length $_->[0] for @$ls;
+ }
+ $tl += $lc; $ta += $ac; $td += $dc;
+ print CLIENTCRAP sprintf "Window %d: %d lines hidden, %d anchors, %dkB of data", ($vw{$v}//"??"), $lc, $ac, int($dc/1024);
+ }
+ print CLIENTCRAP sprintf "Total: %d lines hidden, %d anchors, %dkB of data", $tl, $ta, int($td/1024);
+ }
+ });
+}
+
+init_hideshow();
+
+{ package Irssi::Nick }