diff options
-rw-r--r-- | prompt_info/input_overlay.pl | 188 |
1 files changed, 137 insertions, 51 deletions
diff --git a/prompt_info/input_overlay.pl b/prompt_info/input_overlay.pl index 7a8dd9d..9d2a42b 100644 --- a/prompt_info/input_overlay.pl +++ b/prompt_info/input_overlay.pl @@ -27,8 +27,9 @@ my @regions; my ($term_w, $term_h) = (0, 0); -my $key_capture = 0; +my $overlay_active = 0; my $prompt_len = 5; +my $region_id = 0; sub DEBUG () { 1 } @@ -56,6 +57,16 @@ sub update_terminal_size { 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(); @@ -90,55 +101,25 @@ sub intercept_keypress { } -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) { + 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; - if (not $latest_region->{open}) { - new_region($key); + + 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); } @@ -148,6 +129,7 @@ sub observe_keypress { redraw_overlay(); } } + sub init { die "This script requires uberprompt.pl" @@ -160,8 +142,7 @@ sub init { 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'); + setup_bindings(); Irssi::signal_add('prompt changed', sub { print "Updated prompt length: $_[1]"; @@ -173,22 +154,119 @@ sub init { 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 { - $key_capture = not $key_capture; - printf("Region is %sactive", $key_capture?'':'in'); + $overlay_active = not $overlay_active; + _debug("Region is %sactive", $overlay_active?'':'in'); #@regions = (); # terminate the previous region - my $latest_region = $regions[-1]; - if (defined $latest_region) { - $latest_region->{open} = 0; + + 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; - print "Checking if $name is loaded" if DEBUG; + _debug("Checking if $name is loaded"); no strict 'refs'; - my $retval = defined %{ "Irssi::Script::${name}::" }; + my $retval = %{ "Irssi::Script::${name}::" }; use strict 'refs'; return $retval; @@ -198,5 +276,13 @@ sub _pos { return Irssi::gui_input_get_pos(); } +sub _input { + return Irssi::parse_special('$L'); +} + +sub _debug { + printf @_ if DEBUG(); +} + init(); |