-
Notifications
You must be signed in to change notification settings - Fork 234
/
Copy pathhlscroll.pl
84 lines (68 loc) · 2.59 KB
/
hlscroll.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use strict;
use Irssi qw(command_bind MSGLEVEL_HILIGHT);
use Irssi::TextUI;
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.03';
%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 => 'Thu Feb 15 10:35 CEST 2018',
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', @_) };