use strict;
use warnings;
use Irssi;
use Irssi::TextUI; # for sbar_items_redraw
use Data::Dumper;
# TODO: maybe eval { use Term::Size } and use tthat if poss.
our $VERSION = "0.2";
our %IRSSI =
(
authors => "shabble",
contact => 'shabble+irssi@metavore.org, shabble@#irssi/Freenode',
name => "overlays",
description => "Library script for drawing overlays on irssi UI",
license => "MIT",
changed => "24/7/2010"
);
# overlay := { $num1 => line1, $num2 => line2 }
# line := [ region, region, region ]
# region := { start => x, end => y, ...? }
my @regions;
my ($term_w, $term_h) = (0, 0);
my $key_capture = 0;
my $prompt_len = 5;
sub DEBUG () { 1 }
sub update_terminal_size {
my @stty_data = qx/stty -a/;
my $line = $stty_data[0];
# linux
# speed 38400 baud; rows 36; columns 126; line = 0;
if ($line =~ m/rows (\d+); columns (\d+);/) {
$term_h = $1;
$term_w = $2;
# osx
# speed 9600 baud; 40 rows; 235 columns;
} elsif ($line =~ m/(\d+) rows; (\d+) columns;/) {
$term_h = $1;
$term_w = $2;
} else {
# guess?
$term_h = 24;
$term_w = 80;
}
print "Terminal detected as $term_w cols by $term_h rows" if DEBUG;
}
sub redraw_overlay {
# TODO: we can't assume the active win is the only one with overlays.
#Irssi::active_win->view->redraw();
foreach my $region (@regions) {
if ($region->{draw}) {
my $str = $region->{style} . $region->{text} . '%n';
my $x_offset = $region->{start} + $prompt_len;
Irssi::gui_printtext($x_offset, $term_h, $str);
}
}
# my $inp = Irssi::parse_special('$L');
# Irssi::gui_input_set($inp . '');
}
sub augment_redraw {
#print "Redraw called" if DEBUG;
#redraw_overlay();
Irssi::timeout_add_once(20, \&redraw_overlay, 0);
}
sub intercept_keypress {
my $key = shift;
# intercept C-l for redraw, and force it to call
# /redraw instead of the internal function.
if ($key == 12) { # C-L
print "C-l pressed" if DEBUG;
Irssi::command("redraw");
Irssi::signal_stop;
}
}
sub new_region {
my $key = shift;
print "Creating new Region";
my $new_region
= {
text => '',
start => _pos() -1,
style => '%_',
open => 1,
draw => 1,
};
insert_into_region($key, $new_region);
push @regions, $new_region;
}
sub insert_into_region {
my ($key, $region) = @_;
# if ($key == 127) { # backspace
# substr($region->{text}, -1, 1) = '';
# } else {
# $region->{text} .= chr $key;
# }
my $input = Irssi::parse_special('$L');
my $len = _pos() - $region->{start};
# print "Input: $input, len: $len" if DEBUG;
my $str = substr($input, $region->{start} , $len);
# print "Str: $str" if DEBUG;
$region->{text} = $str;
# printf("region [%d-%d] now contains '%s'",
# $region->{start}, _pos(),
# $region->{text}) if DEBUG;
}
sub observe_keypress {
my $key = shift;
if ($key_capture && $key > 31 && $key <= 127) {
# see if we're still appending to the last region:
#print "Observed printable key: " . chr($key) if DEBUG;
#print '';
my $latest_region = $regions[-1];
$latest_region = {} unless defined $latest_region;
if (not $latest_region->{open}) {
new_region($key);
} else {
insert_into_region($key, $latest_region);
}
#Irssi::signal_stop;
# TODO: if the cursor pos is inside a region, handle it
# extend the region on addition?
redraw_overlay();
}
}
sub init {
die "This script requires uberprompt.pl"
unless script_is_loaded('uberprompt');
Irssi::signal_add_last ('command redraw', \&augment_redraw);
Irssi::signal_add_first('gui key pressed', \&intercept_keypress);
Irssi::signal_add_last ('gui key pressed', \&observe_keypress);
Irssi::signal_add ('terminal resized', \&update_terminal_size);
Irssi::signal_add_first('gui print text finished', \&augment_redraw);
Irssi::command_bind('region_start', \®ion_toggle);
Irssi::command('/bind ^C /region_start');
Irssi::signal_add('prompt changed', sub {
print "Updated prompt length: $_[1]";
$prompt_len = $_[1];
});
Irssi::signal_emit('prompt length request');
update_terminal_size();
}
sub region_toggle {
$key_capture = not $key_capture;
printf("Region is %sactive", $key_capture?'':'in');
#@regions = ();
# terminate the previous region
my $latest_region = $regions[-1];
if (defined $latest_region) {
$latest_region->{open} = 0;
}
}
sub script_is_loaded {
my $name = shift;
print "Checking if $name is loaded" if DEBUG;
no strict 'refs';
my $retval = defined %{ "Irssi::Script::${name}::" };
use strict 'refs';
return $retval;
}
sub _pos {
return Irssi::gui_input_get_pos();
}
init();