--- ISelect.pm 2007/10/25 17:24:33 14 +++ ISelect.pm 2007/10/25 21:14:33 22 @@ -18,7 +18,7 @@ / ); -our $VERSION = '0.01'; +our $VERSION = '0.02'; =head1 NAME @@ -64,6 +64,8 @@ my $selectable_line; +my $nr_lines = 0; + =head2 full_line Returns line padded up to screen width @@ -78,6 +80,9 @@ my $cols = $self->screen->cols; my $t = shift; + + $t =~ s/{s}//; + $t = '' unless defined $t; $t = substr($t,0,$cols) if length($t) > $cols; return $t . (" " x ($cols - length($t))); @@ -110,7 +115,8 @@ sub redraw_screen { my $self = shift; - my @lines = $self->lines; + my @lines = @{ $self->lines }; + $nr_lines = $#lines; for my $l (0 .. $self->screen->rows - $status_lines) { my $line = $lines[ $l + $top_screen_line ]; $self->redraw_line( $l, $line ); @@ -130,64 +136,68 @@ sub redraw_statusline { my $self = shift; - my @lines = $self->lines; - - my $pcnt = int(($pos || 0) * 100 / ( $#lines || 1)); - my $pos_txt = sprintf('%d, %d%% ',$pos,$pcnt); + my $pcnt = int(($pos || 0) * 100 / ( $nr_lines || 1 ) ); + my $pos_txt = sprintf('%d/%s, %d%% ',$pos,$nr_lines,$pcnt); my $scr = $self->screen || confess "need screen"; + my $status_text = sprintf("pos: %-3d sel_pos: %-3d top_screen_line: %-3d", $pos, $sel_pos, $top_screen_line ); + + $status_text .= ' ' . $self->status_text if $self->status_text; + $scr->at($scr->rows - $status_lines + 1,0)->reverse()->puts( - sprintf(' %-'.($scr->cols - length($pos_txt) - 2).'s ',$self->status_text) - .$pos_txt)->normal() if $self->status_text; + sprintf(' %-'.($scr->cols - length($pos_txt) - 2).'s ',$status_text) + .$pos_txt)->normal(); $scr->at($scr->rows - $status_lines + 2,0)->puts( - sprintf('%-'.$scr->cols.'s', $self->error_text) + sprintf('%-'.$scr->cols.'s', $self->error_text ) ) if $self->error_text; } =head2 selected -Move selection (or refresh it) +Move selection to some line of document - $iselect->selected( +1 ); - $iselect->selected( -1 ); - $iselect->selected( 0 ); + $iselect->selected( 42 ); =cut sub selected { my $self = shift; - my $d = shift || 0; + my $new_pos = shift; - my $screen_line = $pos - $top_screen_line; + if ( defined $new_pos ) { - $self->redraw_line( $screen_line, ($self->lines)[$pos] ); + my $screen_line = $pos - $top_screen_line; + $self->redraw_line( $screen_line, $self->lines->[$pos] ); - my $last_screen_line = $self->screen->rows - $status_lines; + my $last_screen_line = $self->screen->rows - $status_lines; - if ( $d < 0 && $screen_line == 0 ) { - if ( $pos > 0 ) { - $top_screen_line--; - $pos--; - } else { - $self->error_text( "Already at Begin." ); - } - $self->redraw_screen; - } elsif ( $d > 0 && $screen_line == $last_screen_line ) { - if ( $pos < scalar($self->lines) ) { - $top_screen_line++; - $pos++; + if ( $new_pos < $pos && $screen_line == 0 ) { + if ( $pos > 0 ) { + $top_screen_line--; + $pos--; + $self->screen->at(0,0)->il; + $self->error_text( ' ' ); + } else { + $self->error_text( "Already at Begin." ); + } + } elsif ( $new_pos > $pos && $screen_line == $last_screen_line ) { + if ( $pos < $nr_lines ) { + $top_screen_line++; + $pos++; + $self->screen->at(0,0)->dl; + } else { + $self->error_text( "Already at End." ); + } } else { - $self->error_text( "Already at End." ); + $pos = $new_pos; } - $self->redraw_screen; - } else { - $pos += $d; + } - my $line = ($self->lines)[$pos]; + my $line = $self->lines->[$pos]; if ( defined $selectable_line->{ $pos } ) { $self->screen->at($pos - $top_screen_line,0)->reverse->bold()->puts( $self->full_line( $line ) )->normal(); $sel_pos = $pos; @@ -216,11 +226,11 @@ my $callback = shift; confess "expect callback as first arg" unless ref($callback) eq 'CODE'; - my @lines = $self->lines; + my @lines = @{ $self->lines }; # find which lines are selectable in input file for my $l (0 .. $#lines) { - if ($lines[$l] =~ s/^{s}//) { + if ($lines[$l] =~ m/^{s}/) { $selectable_line->{$l}++; } } @@ -237,14 +247,16 @@ $self->redraw_screen; $self->selected; + my $lines_on_screen = $self->screen->rows - $status_lines; + while(my $key = $self->screen->getch()) { - my $lines_on_screen = $self->screen->rows - $status_lines; + $self->error_text(''); if ($key eq 'ku') { - $self->selected( -1 ); + $self->selected( $pos - 1 ); } elsif ($key eq 'kd') { - $self->selected( +1 ); + $self->selected( $pos + 1 ); } elsif ($key eq 'pgup' ) { # first line on screen? if ( $pos == $top_screen_line ) { @@ -252,24 +264,47 @@ $top_screen_line = 0 if $top_screen_line < 0; $self->redraw_screen; } - $self->selected( -( $pos - $top_screen_line ) ); + if ( $pos == $top_screen_line ) { + $self->error_text( "Already at top." ); + } else { + $self->selected( $top_screen_line ); + } } elsif ($key eq 'pgdn' ) { # last line on screen? if ( $pos - $top_screen_line == $lines_on_screen ) { $top_screen_line += $lines_on_screen; - $top_screen_line = $#lines - $lines_on_screen if $top_screen_line >= $#lines - $lines_on_screen; + + my $max_top_screen_line = + $nr_lines > $lines_on_screen ? $nr_lines - $lines_on_screen : 0; + + $top_screen_line = $max_top_screen_line if $top_screen_line > $max_top_screen_line; + warn "max_top_screen_line = $max_top_screen_line top_screen_line = $top_screen_line\n"; + $self->redraw_screen; + } + if ( $pos == $nr_lines ) { + $self->error_text( "Already at bottom." ); + } else { + $self->selected( $top_screen_line + $lines_on_screen ); + } + } elsif ($key eq 'g' ) { + if ( $top_screen_line == 0 ) { + if ( $pos == 0 ) { + $self->error_text( "Already at top." ); + } else { + $self->selected( 0 ); + } + } else { + $top_screen_line = 0; + $pos = 0; $self->redraw_screen; } - $self->selected( $top_screen_line + $lines_on_screen - $pos ); } - my $status_text = sprintf("pos: %-3d sel_pos: %-3d top_screen_line: %-3d", $pos, $sel_pos, $top_screen_line ); if ( length($key) > 1 ) { - $status_text .= " key: $key"; + $self->status_text("key: $key"); } else { - $status_text .= sprintf("key: %s [%03d][%02x]", $key =~ m/\w/ ? $key : '?' , ord($key), ord($key) ); + $self->status_text( sprintf("key: %s [%03d][%02x]", $key =~ m/\w/ ? $key : '?' , ord($key), ord($key) ) ); } - $self->status_text( $status_text ); # CTRL+L $self->redraw_screen if ord($key) eq 0x0c;