App-sdview-Output-Tickit

 view release on metacpan or  search on metacpan

lib/App/sdview/Output/Tickit.pm  view on Meta::CPAN

entry will jump directly to it, dismissing the view.

Typing text with the outline view open will filter it to just those headings
matching the typed text. Pressing the C<< <Enter> >> key will jump directly to
the first highlighted heading, again dismissing the view.

=head2 Regexp Searching

Typing into the main search box enters text that forms a (perl) regexp pattern
to be tested against the body text of the document. Each paragraph is tested
individually and all matches are highlighted. Pressing C<< <Enter> >> will
select the first match. Use the C<< <n> >> and C<< <p> >> keys to jump between
them. Press C<< <Escape> >> to clear the highlights. Press C<< <Alt-i> >> to
toggle case-insensitivity. Press C<< <Alt-w> >> to toggle whole-word matching.

=cut

# Override default output format
require App::sdview;
$App::sdview::DEFAULT_OUTPUT = "tickit"
   if $App::sdview::DEFAULT_OUTPUT eq "terminal" and -t STDOUT;

my @HIGHLIGHT_PEN = (
   fg => 16, # avoid bold-black
   bg => "magenta",
   b  => 1,
);

my @SELECT_PEN = (
   bg => "green",
);

field $t;
field $scroller;
field $outlinetree;
field @items;

# Related to searching
field $matchposstatic;
field $matchidx;
field @matches;

ADJUST
{
   # Lazy load all the Tickit modules in here

   require Tickit;
   require Tickit::Utils;

   $t = Tickit->new;
   $t->term->await_started( 0.050 );

   $t->bind_key( q => sub { $t->stop; } );

   require Tickit::Widget::Scroller;
   Tickit::Widget::Scroller->VERSION( '0.33' );
   $scroller = Tickit::Widget::Scroller->new;

   $scroller->set_gen_bottom_indicator(
      sub ( $scroller ) {
         # It feels better for progress if we claim the percentage of ofscreen
         # lines that are above the screen.
         my $lines_above = $scroller->lines_above;
         my $lines_total = $lines_above + $scroller->lines_below;
         return "" if $lines_total < 1;
         return sprintf( "%d of %d (%d%%)",
            $lines_above, $lines_total, 100 * $lines_above / $lines_total );
      }
   );

   # Ugh
   $scroller->set_style(
      '<Home>'      => "scroll_to_top",
      '<Space>'     => "scroll_down_page",
      '<Backspace>' => "scroll_up_page",
      '<End>'       => "scroll_to_bottom",
      '<<>'         => "scroll_to_top",
      '<>>'         => "scroll_to_bottom",
   );

   $outlinetree = App::sdview::Output::Tickit::_OutlineTree->new;
}

method output ( @paragraphs )
{
   require Tickit::Widget::Scroller::Item::Text;

   foreach my $para ( @paragraphs ) {
      my $code = $self->can( "output_" . ( $para->type =~ s/-/_/gr ) )
         or die "TODO: Unhandled paragraph type " . $para->type;

      $self->$code( $para );
   }

   require Tickit::Widget::FloatBox;

   $t->set_root_widget( my $fb = Tickit::Widget::FloatBox->new
      ->set_base_child( $scroller )
   );

   my $outlinefloat = $fb->add_float(
      child => $outlinetree,
      hidden => 1, # initially hidden
      top => 0, bottom => -1,
      left => 0, right => 25, # ideally we want to set "30%" or somesuch here
   );

   $t->bind_key(
      'F9' => sub { $outlinefloat->is_visible ? $outlinefloat->hide : $outlinefloat->show },
   );
   $t->bind_key(
      ']' => sub {
         my $item = $outlinetree->next_item( +1 );
         $scroller->scroll_to( 0, $item->itemidx, 0 ) if $item;
      }
   );
   $t->bind_key(
      '[' => sub {
         my $item = $outlinetree->current_item;
         # Scroll back up to that item if it's not visible
         my ( undef, $offscreen ) = $scroller->item2line( $item->itemidx, 0 );



( run in 0.715 second using v1.01-cache-2.11-cpan-39bf76dae61 )