summaryrefslogtreecommitdiffstats
path: root/scripts/hlscroll.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/hlscroll.pl')
-rw-r--r--scripts/hlscroll.pl83
1 files changed, 83 insertions, 0 deletions
diff --git a/scripts/hlscroll.pl b/scripts/hlscroll.pl
new file mode 100644
index 0000000..47a4066
--- /dev/null
+++ b/scripts/hlscroll.pl
@@ -0,0 +1,83 @@
+use strict;
+use Irssi qw(command_bind MSGLEVEL_HILIGHT);
+use vars qw($VERSION %IRSSI);
+
+# Recommended key bindings: alt+pgup, alt+pgdown:
+# /bind meta2-5;3~ /scrollback hlprev
+# /bind meta2-6;3~ /scrollback hlnext
+
+$VERSION = '0.02';
+%IRSSI = (
+ authors => 'Juerd, Eevee',
+ contact => '#####@juerd.nl',
+ name => 'Scroll to hilights',
+ description => 'Scrolls to previous or next highlight',
+ license => 'Public Domain',
+ url => 'http://juerd.nl/site.plp/irssi',
+ changed => 'Fri Apr 13 05:48 CEST 2012',
+ inspiration => '@eevee on Twitter: "i really want irssi keybindings that will scroll to the next/previous line containing a highlight. why does this not exist"',
+);
+
+sub _hlscroll{
+ my ($direction, $data, $server, $witem) = @_;
+ $witem or return;
+ my $window = $witem->window or return;
+
+ my $view = $window->view;
+ my $line = $view->{buffer}->{cur_line};
+ my $delta = $direction eq 'prev' ? -1 : 1;
+
+ my $linesleft = $view->{ypos} - $view->{height} + 1;
+ my $scrollby = 0; # how many display lines to scroll to the next highlight
+
+ # find the line currently at the bottom of the screen
+ while (1) {
+ my $line_height = $view->get_line_cache($line)->{count};
+
+ if ($linesleft < $line_height) {
+ # found it!
+ if ($direction eq 'prev') {
+ # skip however much of $line is on the screen
+ $scrollby = $linesleft - $line_height;
+ }
+ else {
+ # skip however much of $line is off the screen
+ $scrollby = $linesleft;
+ }
+
+ last;
+ }
+
+ $linesleft -= $line_height;
+
+ last if not $line->prev;
+ $line = $line->prev;
+ }
+
+ while ($line->$direction) {
+ $line = $line->$direction;
+ my $line_height = $view->get_line_cache($line)->{count};
+
+ if ($line->{info}{level} & MSGLEVEL_HILIGHT) {
+ # this algorithm scrolls to the "border" between lines -- if
+ # scrolling down, add in the line's entire height so it's entirely
+ # visible
+ if ($direction eq 'next') {
+ $scrollby += $delta * $line_height;
+ }
+
+ $view->scroll($scrollby);
+ return;
+ }
+
+ $scrollby += $delta * $line_height;
+ }
+
+ if ($direction eq 'next' and not $line->next) {
+ # scroll all the way to the bottom, after the last highlight
+ $view->scroll_line($line);
+ }
+};
+
+command_bind 'scrollback hlprev' => sub { _hlscroll('prev', @_) };
+command_bind 'scrollback hlnext' => sub { _hlscroll('next', @_) };