File Coverage

blib/lib/TiddlyWeb/Wikrad.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package TiddlyWeb::Wikrad;
2 1     1   23237 use strict;
  1         3  
  1         38  
3 1     1   6 use warnings;
  1         2  
  1         30  
4 1     1   432 use Curses::UI;
  0            
  0            
5             use Carp qw/croak/;
6             use File::Path qw/mkpath/;
7             use base 'Exporter';
8             our @EXPORT_OK = qw/$App/;
9              
10             our $VERSION = '0.9';
11              
12             =head1 NAME
13              
14             TiddlyWeb::Wikrad - efficient wiki browsing and editing
15              
16             =head1 SYNOPSIS
17              
18             my $app = TiddlyWeb::Wikrad->new(rester => $rester);
19             $app->set_page( $starting_page );
20             $app->run;
21              
22             =cut
23              
24             our $App;
25              
26             sub new {
27             my $class = shift;
28             $App = {
29             history => [],
30             save_dir => "$ENV{HOME}/wikrad",
31             @_ ,
32             };
33             die 'rester is mandatory' unless $App->{rester};
34             $App->{rester}->agent_string("wikrad/$VERSION");
35             bless $App, $class;
36             $App->_setup_ui;
37             return $App;
38             }
39              
40             sub run {
41             my $self = shift;
42              
43             my $quitter = sub { exit };
44             $self->{cui}->set_binding( $quitter, "\cq");
45             $self->{cui}->set_binding( $quitter, "\cc");
46             $self->{win}{viewer}->set_binding( $quitter, 'q');
47              
48             $self->{cui}->reset_curses;
49             $self->{cui}->mainloop;
50             }
51              
52             sub save_dir {
53             my $self = shift;
54             my $dir = $self->{save_dir};
55             unless (-d $dir) {
56             mkpath $dir or die "Can't mkpath $dir: $!";
57             }
58             return $dir;
59             }
60              
61             sub set_page {
62             my $self = shift;
63             my $page = shift;
64             my $workspace = shift;
65             my $no_history = shift;
66              
67             my $pb = $self->{win}{page_box};
68             my $wksp = $self->{win}{workspace_box};
69              
70             unless ($no_history) {
71             push @{ $self->{history} }, {
72             page => $pb->text,
73             wksp => $wksp->text,
74             pos => $self->{win}{viewer}{-pos},
75             };
76             }
77             $self->set_workspace($workspace) if $workspace;
78             $pb->text($page);
79             $self->load_page;
80             }
81              
82             sub download {
83             my $self = shift;
84             my $current_page = $self->{win}{page_box}->text;
85             $self->{cui}->leave_curses;
86              
87             my $r = $self->{rester};
88            
89             my $dir = $self->_unique_filename($current_page);
90             mkdir $dir or die "Error creating directory $dir: $!";
91              
92             my %ct = (
93             html => 'text/html',
94             wiki => 'text/plain',
95             );
96              
97             while (my ($ext, $ct) = each %ct) {
98             $r->accept($ct);
99             my $file = "$dir/content.$ext";
100             open my $fh, ">$file" or die "Can't open $file: $!";
101             print $fh $r->get_page($current_page);
102             close $fh or die "Can't open $file: $!";
103             }
104             }
105              
106             sub _unique_filename {
107             my $self = shift;
108             my $original = shift;
109             my $filename = $original;
110             my $i = 0;
111             while (-e $filename) {
112             $i++;
113             $filename = "$original.$i";
114             }
115             return $filename;
116             }
117              
118             sub set_workspace {
119             my $self = shift;
120             my $wksp = shift;
121             $self->{win}{workspace_box}->text($wksp);
122             $self->{rester}->workspace($wksp);
123             }
124              
125             sub go_back {
126             my $self = shift;
127             my $prev = pop @{ $self->{history} };
128             if ($prev) {
129             $self->set_page($prev->{page}, $prev->{wksp}, 1);
130             $self->{win}{viewer}{-pos} = $prev->{pos};
131             }
132             }
133              
134             sub get_page {
135             return $App->{win}{page_box}->text;
136             }
137              
138             sub load_page {
139             my $self = shift;
140             my $current_page = $self->{win}{page_box}->text;
141              
142             if (! $current_page) {
143             $self->{cui}->status('Fetching list of pages ...');
144             $self->{rester}->accept('text/plain');
145             $self->{rester}->count(250);
146             $self->{rester}->order('-modified');
147             my @pages = $self->{rester}->get_pages;
148             $self->{rester}->count(0);
149             $self->{rester}->order('');
150             $self->{cui}->nostatus;
151             $App->{win}->listbox(
152             -title => 'Choose a page',
153             -values => \@pages,
154             change_cb => sub {
155             my $page = shift;
156             $App->set_page($page) if $page;
157             },
158             );
159             return;
160             }
161              
162             $self->{cui}->status("Loading page $current_page ...");
163             $self->{rester}->accept('perl_hash');
164             my $page = $self->{rester}->get_page($current_page);
165             $self->{cui}->nostatus;
166             $self->{win}{tag_box}->text(join(', ', @{$page->{tags}}));
167             $self->{win}{modified_box}->text($page->{modified});
168             $self->{win}{modifier_box}->text($page->{modifier});
169             $self->{win}{viewer}->text($page->{text});
170             $self->{win}{viewer}->cursor_to_home;
171             }
172              
173             sub _setup_ui {
174             my $self = shift;
175             $self->{cui} = Curses::UI->new( -color_support => 1 );
176             $self->{win} = $self->{cui}->add('main', 'TiddlyWeb::Wikrad::Window');
177             $self->{cui}->leave_curses;
178             }
179              
180             1;