diff options
Diffstat (limited to 'prompt_info/old/input_overlay.pl')
-rw-r--r-- | prompt_info/old/input_overlay.pl | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/prompt_info/old/input_overlay.pl b/prompt_info/old/input_overlay.pl new file mode 100644 index 0000000..9d2a42b --- /dev/null +++ b/prompt_info/old/input_overlay.pl @@ -0,0 +1,288 @@ + +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 $overlay_active = 0; +my $prompt_len = 5; +my $region_id = 0; + +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 find_region { + my ($pos) = @_; + foreach my $region (@regions) { + next unless $pos > $region->{start}; + return $region if $pos <= $region->{end}; + } + print "failed to find region for pos: $pos"; + return undef; +} + +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 observe_keypress { + my $key = shift; + print "Key " . chr ($key) . " pressed, pos: " . _pos(); + if ($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; + + + my $pos = _pos(); + my $reg = find_region($pos); + + if (defined $reg) { + insert_into_region($key, $reg); + } elsif (not $latest_region->{open}) { + my $style = $overlay_active?'%_':''; + new_region($style, $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); + + setup_bindings(); + + Irssi::signal_add('prompt changed', sub { + print "Updated prompt length: $_[1]"; + $prompt_len = $_[1]; + }); + + Irssi::signal_emit('prompt length request'); + + update_terminal_size(); +} + +sub setup_bindings { + + Irssi::command_bind('region_start', \®ion_toggle); + Irssi::command_bind('region_clear', \®ion_clear); + Irssi::command_bind('region_print', \&print_regions); + + + Irssi::command('/bind ^C /region_start'); + ##Irssi::command('/bind ^D /region_clear'); + Irssi::command('/bind ^D /region_print'); + +} + + +################################################################################ + +sub escape_style { + my ($style) = @_; + $style =~ s/%/%%/g; + + return $style; +} + +sub print_regions { + foreach my $reg (@regions) { + printf("start: %d end: %d style: %s, text: \"%s\", open: %d, draw: %d", + $reg->{start}, $reg->{end}, escape_style($reg->{style}), + $reg->{text}, $reg->{open}, $reg->{draw}); + } +} + +sub new_region { + my ($style, $key) = @_; + + my $new_id = $region_id++; + _debug("Creating new Region: $new_id"); + + my $new_region + = { + id => $region_id++, + text => '', + start => _pos(), + end => _pos(), + style => $style, + open => 1, + draw => 1, + }; + + insert_into_region($key, $new_region); + + push @regions, $new_region; +} + +sub delete_region { + my ($region) = @_; + my $idx = 0; + foreach my $i (0..$#regions) { + if ($regions[$i]->{id} == $region->{id}) { + $idx = $i; + last; + } + } + print "Deleting region: $idx"; + splice(@regions, $idx, 1); # remove the selected region. +} + +sub insert_into_region { + my ($key, $region) = @_; + + my $pos = _pos(); + + if ($key == 127) { # backspace + substr($region->{text}, -1, 1) = ''; + $region->{end}--; + if ($region->{end} <= $region->{start}) { + delete_region($region); + } + } else { + printf("text: '%s', pos: %d, offset: %d", + $region->{text}, $pos, $pos - $region->{start}); + if ( $region->{end} < $pos) { + $region->{text} .= chr $key; + } else { + substr($region->{text}, $pos - $region->{start}, 0) = chr $key; + } + $region->{end}++; + } +} + +sub region_clear { + @regions = (); + Irssi::signal_emit('command redraw'); +} + +sub region_toggle { + $overlay_active = not $overlay_active; + _debug("Region is %sactive", $overlay_active?'':'in'); + #@regions = (); + # terminate the previous region + + my $region = find_region(_pos()); + if (defined $region) { + $region->{open} = 0; + $region->{end} = _pos(); + debug("Region closed: %d-%d", $region->{start}, $region->{end}); + } +} + +sub script_is_loaded { + my $name = shift; + _debug("Checking if $name is loaded"); + no strict 'refs'; + my $retval = %{ "Irssi::Script::${name}::" }; + use strict 'refs'; + + return $retval; +} + +sub _pos { + return Irssi::gui_input_get_pos(); +} + +sub _input { + return Irssi::parse_special('$L'); +} + +sub _debug { + printf @_ if DEBUG(); +} + +init(); + |