File Coverage

blib/lib/CPANPLUS/Shell/Curses.pm
Criterion Covered Total %
statement 15 17 88.2
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 21 23 91.3


line stmt bran cond sub pod time code
1             ##################################################
2             ### CPANPLUS/Shell/Curses.pm ###
3             ### Module to provide a shell to the CPAN++ ###
4             ### 2003-2004 (c) by Marcus Thiesen ###
5             ### marcus@cpan.org ###
6             ##################################################
7              
8             ### Curses.pm ###
9              
10             package CPANPLUS::Shell::Curses;
11 1     1   1089 use strict;
  1         2  
  1         38  
12 1     1   6 use warnings;
  1         3  
  1         48  
13              
14             BEGIN {
15 1     1   16 use vars qw( $VERSION @ISA);
  1         2  
  1         97  
16 1     1   17 @ISA = qw( CPANPLUS::Shell::_Base );
17 1         21 $VERSION = '0.07'; #go with the CP minor number
18             }
19              
20 1     1   1104 use CPANPLUS::Backend;
  1         591915  
  1         36  
21 1     1   453 use CPANPLUS::I18N;
  0            
  0            
22              
23             use Curses;
24             use Curses::UI 0.93;
25             use Pod::Text;
26             use File::Spec;
27             use File::chdir;
28             use Cwd;
29             use Module::ScanDeps;
30              
31             ###
32             ### Key Bindings
33             ### Most of them are default shell compatible
34             ###
35             my $default_mode = {
36             a => "_search_author_init",
37             b => "_write_bundle",
38             c => "_show_reports_init",
39             d => "_fetch",
40             e => "_expand_inc_init",
41             f => "_search_dist_init",
42             g => "_draw",
43             h => "_pod_help",
44             i => "_install_install_init", # target => install
45             j => "_show_all",
46             k => "_display_installed",
47             l => "_goto_list",
48             m => "_search_module_init",
49             # n reserved for next in search
50             o => "_uptodate",
51             p => "_print_stack",
52             q => "_quit", # also called on EOF and abnormal exits
53             r => "_readme",
54             s => "_set_conf",
55             t => "_install_test_init", # target => test
56             u => "_uninstall",
57             v => "_show_banner",
58             w => "_show_cache",
59             x => "_reload_indices",
60             y => "_show_perldoc",
61             z => "_open_prompt",
62              
63             '!' => "_eval_expr_init",
64             '%' => "_eval_shell_init",
65             # '?' reserver for backward search
66             # '/' reserver for search
67              
68             1 => "_fetch",
69             2 => "_extract",
70             3 => "_install_all_init", #target = all
71             4 => "_install_test_init",
72             5 => "_install_install_init",
73              
74             A => "_search_module_author",
75             B => "_select_all",
76             # C => "",
77             D => "_show_deps",
78             # E => "",
79             # F => "",
80             # G => "",
81             # H => "",
82             I => "_install_params_init",
83             # J => "",
84             # K => "",
85             # L => "",
86             M => "_search_namespace_module",
87             N => "_search_namespace_module2",
88             # O => "",
89             # P => "",
90             # Q => "",
91             R => "_show_installed",
92             S => "_show_stats"
93             # T => "",
94             # U => "",
95             # V => "",
96             # W => "",
97             # X => "",
98             # Y => "",
99             # Z => "",
100             };
101              
102             sub new {
103             my $proto = shift;
104             my $class = ref($proto) || $proto;
105              
106             ### Will call the _init constructor in Internals.pm ###
107             my $self = $class->SUPER::_init( brand => loc('CPAN Terminal') );
108              
109             return $self;
110             }
111              
112             ### The CPAN Curses Interface
113             my $mainw;
114             my $cpanp;
115             my $data;
116             my %install_params;
117             my %updated;
118             sub shell {
119             ### Init CPANPLUS
120             $cpanp = new CPANPLUS::Backend;
121             my $config = $cpanp->configure_object();
122             my $err = $cpanp->error_object();
123              
124             $config->set_conf('verbose' => 1); ### Be quiet
125              
126             $data = $cpanp->module_tree();
127              
128             $config->set_conf('verbose' => 0); ### Speak!
129              
130             if (not defined $data) {
131             die loc("FATAL: Couldn't get module list!\n") . $err->stack();
132             }
133              
134             ### Init all the Curses...
135             my $self = shift;
136             $mainw = new Curses::UI('-clear_on_exit' => 1,
137             '-mouse_support' => 0,
138             '-color_support' => 1,);
139              
140             $self->init_screen();
141              
142             my $list = $mainw->getobj('listw')->getobj('list');
143              
144             $mainw->draw();
145             $mainw->status(-message => loc("Loading..."),
146             -fg => "blue",
147             -bfg => "blue");
148            
149             ### Apply the keybindings
150             $list->set_routine("_quit", \&_quit );
151             $list->set_routine("_show_banner", \&_show_banner);
152             $list->set_routine("_help", \&_help);
153             $list->set_routine("_search_author_init", \&_search_author_init);
154             $list->set_routine("_search_module_init", \&_search_module_init);
155             $list->set_routine("_goto_list", \&_goto_list);
156             $list->set_routine("_install_install_init", \&_install_install_init);
157             $list->set_routine("_install_test_init", \&_install_test_init);
158             $list->set_routine("_readme", \&_readme);
159             $list->set_routine("_draw", \&_draw);
160             $list->set_routine("_search_dist_init", \&_search_dist_init);
161             $list->set_routine("_fetch", \&_fetch);
162             $list->set_routine("_uninstall", \&_uninstall);
163             $list->set_routine("_display_installed", \&_display_installed);
164             $list->set_routine("_show_all", \&_show_all);
165             $list->set_routine("_expand_inc_init", \&_expand_inc_init);
166             $list->set_routine("_uptodate", \&_uptodate);
167             $list->set_routine("_set_conf", \&_set_conf);
168             $list->set_routine("_eval_expr_init", \&_eval_expr_init);
169             $list->set_routine("_show_cache", \&_show_cache);
170             $list->set_routine("_pod_help", \&_pod_help);
171             $list->set_routine("_show_perldoc", \&_show_perldoc);
172             $list->set_routine("_print_stack", \&_print_stack);
173             $list->set_routine("_reload_indices", \&_reload_indices);
174             $list->set_routine("_open_prompt", \&_open_prompt);
175             $list->set_routine("_write_bundle", \&_write_bundle);
176             $list->set_routine("_show_reports_init", \&_show_reports_init);
177             $list->set_routine("_extract_file", \&_extract_file);
178             $list->set_routine("_eval_shell_init", \&_eval_shell_init);
179             $list->set_routine("_install_all_init", \&_install_all_init);
180             $list->set_routine("_search_module_author", \&_search_module_author);
181             $list->set_routine("_search_namespace_module", \&_search_namespace_module);
182             $list->set_routine("_search_namespace_module2", \&_search_namespace_module2);
183             $list->set_routine("_extract", \&_extract);
184             $list->set_routine("_show_installed", \&_show_installed);
185             $list->set_routine("_show_deps", \&_show_deps);
186             $list->set_routine("_show_stats", \&_show_stats);
187             $list->set_routine("_select_all", \&_select_all);
188             $list->set_routine("_install_params_init", \&_install_params_init);
189              
190             foreach my $key (keys %$default_mode) {
191             $list->set_binding($default_mode->{$key}, $key);
192             }
193              
194             ### Make the update check at the beginning
195             _look_for_updates();
196            
197             _display_results($data);
198             _show_installed();
199             _goto_list();
200              
201             ###
202             ### Main Loop
203             ###
204             $mainw->MainLoop;
205             }
206              
207             sub leave_curses{ def_prog_mode(); endwin();}
208             sub reset_curses{ reset_prog_mode(); }
209              
210             sub init_screen{
211             my ($self, @args) = @_;
212             my ($max_x, $max_y);
213              
214             $max_x = $mainw->height();
215             $max_y = $mainw->width();
216            
217             my $top_height = 3;
218             my $display_height = 7;
219             my $listw_height =$max_x - $top_height - $display_height;
220              
221             my $topw = $mainw->add('topw',
222             'Window',
223             '-height' => $top_height,
224             '-border' => 1,
225             '-title' => loc('CPANPLUS::Shell::Curses') . " $VERSION",
226             '-tfg' => "green",
227             '-tbg' => "white",
228             '-bfg' => "red",
229             '-fg' => "green",
230             );
231              
232             my $listw = $mainw->add('listw',
233             'Window',
234             '-height' => $listw_height,
235             '-border' => 1,
236             '-y'=> $top_height,
237             '-bfg' => "red",
238             '-fg' => "green",
239             );
240            
241             my $displayw = $mainw->add('displayw',
242             'Window',
243             '-height' => $display_height,
244             '-border' => 1,
245             '-y'=> $top_height + $listw_height,
246             '-bfg' => "red",
247             '-fg' => "green",
248             );
249              
250             ### Some error checking
251             $topw or warn "Couldn't create top window";
252             $displayw or warn "Couldn't create display window";
253             $listw or warn "Couldn't create listw window";
254              
255             my $talk = $topw->add('talk','Label', -fg => "green");
256              
257             my $display = $displayw->add('display',
258             'TextViewer',
259             '-wrapping' => 1,
260             '-fg' => "green");
261              
262             my $list = $listw->add('list',
263             'Listbox',
264             'vscrollbar' => 'right',
265             '-multi' => 1,
266             '-fg' => "green",
267             '-htmltext' => 1,
268             );
269              
270             $list->set_routine('_display_module_details',\&_display_module_details);
271             $list->set_binding('_display_module_details', $list->KEY_ENTER());
272             $list->onSelectionChange(\&_display_module_details);
273              
274             $talk or warn "Couldn't create talk label";
275              
276             $topw->focus();
277             }
278              
279             ### Ok, that's quite ugly, but blame Curses::UI
280             ### We need sub to call from hotkey and one to
281             ### get the input
282              
283             sub _search_author_init{
284             my $topw = $mainw->getobj('topw');
285              
286             my $text = loc("Author: ");
287              
288             $topw->getobj('talk')->text($text);
289             $topw->add('input','TextEntry',
290             '-x' => length($text),
291             -fg => "green");
292              
293             $topw->getobj('input')->set_routine("loose-focus", \&_search_author);
294             $topw->getobj('input')->set_binding("loose-focus", $mainw->KEY_ENTER());
295             $topw->getobj('input')->set_routine("abort", \&_input_cleanup);
296             $topw->getobj('input')->set_binding("abort", $mainw->CUI_ESCAPE());
297             $topw->getobj('input')->focus();
298             }
299              
300             sub _search_author{
301             my $input = shift;
302             if (my $string = $input->get()) {
303             my $regex = qr/$string/i;
304             $mainw->status(-message => loc("Searching..."),-fg => "blue",
305             -bfg => "blue");
306             $data = $cpanp->search(type => 'author', list=> [$regex], 'data' => $data);
307             if (defined($data) && (int keys %{$data} > 0)) {
308             _display_results($data);
309             _show_installed();
310             } else {
311             $mainw->status(-message => loc("Nothing found!"));
312             }
313             }
314             _input_cleanup();
315             }
316              
317             sub _search_module_init{
318             my $topw = $mainw->getobj('topw');
319              
320             my $text = loc("Module: ");
321              
322             $topw->getobj('talk')->text($text);
323             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
324             $topw->getobj('input')->set_routine("loose-focus", \&_search_module);
325             $topw->getobj('input')->set_binding("loose-focus",
326             $mainw->KEY_ENTER(),
327             $mainw->CUI_ESCAPE(),
328             );
329             $topw->getobj('input')->focus();
330             }
331              
332             sub _search_module{
333             my $input = shift;
334              
335             if (my $string = $input->get()) {
336             my $regex = qr/$string/i;
337             $mainw->status(-message => loc("Searching..."),-fg => "blue",
338             -bfg => "blue");
339             $data = $cpanp->search(type => 'module', list=> [$regex], 'data' => $data);
340             if (defined($data) && (int keys %{$data} > 0)) {
341             _display_results($data);
342             _show_installed();
343             } else {
344             $mainw->error(-message => loc("Nothing found!"));
345             }
346             }
347             _input_cleanup();
348             }
349              
350             sub _search_dist_init{
351             my $topw = $mainw->getobj('topw');
352              
353             my $text = loc("Distribution: ");
354              
355             $topw->getobj('talk')->text($text);
356             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
357             $topw->getobj('input')->set_routine("loose-focus", \&_search_dist);
358             $topw->getobj('input')->set_binding("loose-focus", $mainw->KEY_ENTER());
359             $topw->getobj('input')->set_routine("abort", \&_input_cleanup);
360             $topw->getobj('input')->set_binding("abort", $mainw->CUI_ESCAPE());
361             $topw->getobj('input')->focus();
362             }
363              
364             sub _search_dist{
365             my $input = shift;
366             if (my $string = $input->get()) {
367             my $regex = qr/$string/i;
368             $mainw->status(-message => loc("Searching..."),-fg => "blue",
369             -bfg => "blue");
370             my $results = $cpanp->search(type => 'distribution', list=> [$regex]);
371             if (defined($results) && (int keys %{$data} > 0)) {
372             _display_results($results);
373             } else {
374             $mainw->error(-message => loc("Nothing found!"));
375             }
376             _input_cleanup(); }
377             }
378              
379              
380             sub _readme{
381             my $list = $mainw->getobj('listw')->getobj('list');
382             my $current_module = _strip_name($list->get_active_value());
383             my $err = $cpanp->error_object();
384              
385             $mainw->status(-message => loc('Getting readme for ') . $current_module,-fg => "blue",
386             -bfg => "blue");
387              
388             my $readme = $cpanp->readme('modules' => [$current_module]);
389              
390             unless ($readme->ok()) {
391             _draw();
392             $mainw->error(-message => loc("Could not get readme: ") . $err->stack());
393             return;
394             }
395              
396             my $text = $readme->rv()->{$current_module};
397              
398             return unless defined $text;
399             return if ref $text;
400              
401             my $display = $mainw->add('readmew','Window');
402            
403             my $viewer = $display->add('viewer','TextViewer',
404             '-border' => 1,
405             '-title' => loc("Readme for ") . $current_module,
406             '-bfg' => "red",
407             '-fg' => "green",);
408              
409             $viewer->text($text);
410             $viewer->set_routine('_end_readme', \&_end_readme);
411             $viewer->set_binding('_end_readme', "q" , " ");
412             $viewer->draw();
413             $viewer->focus();
414             }
415              
416             sub _end_readme{
417             my $display = $mainw->getobj('readmew');
418             my $viewer = $display->getobj('viewer');
419             my $list = $mainw->getobj('listw')->getobj('list');
420              
421             $display->delete('viewer');
422             $mainw->delete('readmew');
423            
424             $mainw->draw();
425             $list->focus();
426             }
427              
428             sub _show_installed{
429             my $list = $mainw->getobj('listw')->getobj('list');
430              
431             ### Tell the user what lasts that long ;-)
432             $mainw->status(-message => loc('Loading installed...'), -fg => "blue",
433             -bfg => "blue" );
434             $list->clear_selection();
435              
436             ### First, get a sorted array of all installed mods
437             my $installed = $cpanp->installed();
438             my $mods = $installed->{'rv'};
439             my %looktbl;
440             foreach my $mod (keys %$mods) { $looktbl{$mod}++; }
441              
442             ### Create an ordered list of all displayed modules
443             my @all_modlist = sort { uc($a) cmp uc($b) } keys %$data;
444              
445             my $index = 0;
446              
447             foreach my $imod (@all_modlist) {
448             $list->set_selection($index) if defined $looktbl{$imod};
449             $index++;
450             }
451             }
452              
453             sub _fetch{
454             my $list = $mainw->getobj('listw')->getobj('list');
455             my $installed = $cpanp->installed();
456             my $mods = $installed->{'rv'};
457             my @instmods = sort { uc($a) cmp uc($b) } keys %$mods;
458             my $current_module = _strip_name($list->get_active_value());
459             my @selection = map _strip_name($_), $list->get();
460              
461             my %look_tbl;
462             my @to_fetch;
463              
464             foreach my $item (@instmods) {$look_tbl{$item} = 1; }
465             foreach my $item (@selection) {
466             unless ($look_tbl{$item}) {
467             push @to_fetch, $item;
468             }}
469              
470             my $err = $cpanp->error_object();
471              
472             push @to_fetch, $current_module unless (@to_fetch > 0);
473             my @endmessage;
474              
475             foreach my $mod (@to_fetch) {
476             $mainw->status(-message => loc('Currently fetching ') . $mod, -fg => "blue",
477             -bfg => "blue");
478             my $iresult = $cpanp->fetch(modules => [$mod]);
479             if ($iresult->ok()) {
480             _draw();
481             push @endmessage, $mod . loc(" fetched successfully");
482             } else {
483             _draw();
484             push @endmessage, loc("Error fetching ") . $mod . "\n" . $err->stack();
485             }
486             _draw();
487             }
488             $mainw->dialog(-message => join("\n",@endmessage),-fg => "blue",
489             -bfg => "blue");
490             _show_installed();
491             }
492              
493             sub _extract {
494             my $list = $mainw->getobj('listw')->getobj('list');
495             my $installed = $cpanp->installed();
496             my $mods = $installed->{'rv'};
497             my @instmods = sort { uc($a) cmp uc($b) } keys %$mods;
498             my $current_module = _strip_name($list->get_active_value());
499              
500             my @selection = map _strip_name($_), $list->get();
501              
502             my %look_tbl;
503             my @to_fetch;
504              
505             foreach my $item (@instmods) {$look_tbl{$item} = 1; }
506             foreach my $item (@selection) {
507             unless ($look_tbl{$item}) {
508             push @to_fetch, $item;
509             }}
510              
511             my $err = $cpanp->error_object();
512             push @to_fetch, $current_module unless (@to_fetch > 0);
513             my @endmessage;
514             foreach my $mod (@to_fetch) {
515             $mainw->status(-message => loc('Currently fetching ') . $mod ,-fg => "blue",
516             -bfg => "blue");
517             my $iresult = $cpanp->fetch(modules => [$mod]);
518             if ($iresult->ok()) {
519             _draw();
520             $mainw->status(-message => loc('Currently extracting ') . $mod,-fg => "blue",
521             -bfg => "blue");
522             $data->{$mod}->extract();
523             } else {
524             _draw();
525             push @endmessage,loc("Error extracting ") . $mod . "\n" . $err->stack();
526             }
527             _draw();
528             }
529             _show_installed();
530             $mainw->dialog( -message => join("\n",@endmessage),-fg => "blue",
531             -bfg => "blue") if (@endmessage > 0);
532             }
533              
534             sub _install_install_init{
535             _install("install");
536             }
537              
538             sub _install_test_init{
539             _install("test");
540             }
541              
542             sub _install_all_init{
543             _install("all");
544             }
545              
546             sub _fetch_modules{
547             my @modules = shift;
548              
549             foreach my $module (@modules) {
550             print "Fetching module $module...\n";
551             $cpanp->fetch( modules => [$module]);
552             print "\tDONE\n";
553             }
554             }
555              
556             sub _install{
557             my $target = shift;
558             my $list = $mainw->getobj('listw')->getobj('list');
559             my $installed = $cpanp->installed();
560             my $mods = $installed->{'rv'};
561             my $current_module = _strip_name($list->get_active_value());
562             my @instmods = sort { uc($a) cmp uc($b) } keys %$mods;
563              
564             my @selection = map _strip_name($_),$list->get();
565              
566             my %look_tbl;
567             my @to_install;
568              
569             map $look_tbl{$_}++, @instmods;
570              
571             for (@selection) {
572             push @to_install, $_ unless $look_tbl{$_};
573             }
574              
575             my $err = $cpanp->error_object();
576             ###
577             ### Here follows some bad magic in order to try to get the input
578             ### any install script may want from us:
579             my @endmessage;
580              
581             push @to_install, $current_module unless (@to_install > 0);
582            
583             leave_curses();
584              
585             print loc("Went back to shell to install: ") . "\n" . join("\n", @to_install);
586             print "\n";
587              
588             _fetch_modules(@to_install);
589             print "Installing...\n";
590              
591             my $iresult = $cpanp->install(modules => \@to_install,
592             'target' => $target,
593             %install_params);
594              
595             if ($iresult->ok()) {
596             push @endmessage, loc("All modules installed successfully");
597             } else {
598             @endmessage = $err->stack();
599             }
600              
601             _show_installed();
602             _draw();
603             reset_curses();
604             $mainw->dialog( -message => join("\n", @endmessage),-fg => "blue",
605             -bfg => "blue");
606             }
607              
608             sub _uninstall{
609             my $list = $mainw->getobj('listw')->getobj('list');
610             my $installed = $cpanp->installed();
611             my $mods = $installed->{'rv'};
612             my @instmods = sort { uc($a) cmp uc($b) } keys %$mods;
613             my $current_module = _strip_name($list->get_active_value());
614             my @selection = map _strip_name($_),$list->get();
615              
616              
617             my %look_tbl;
618             my @to_uninstall;
619              
620             foreach my $item (@selection) {
621             $look_tbl{$item}++;
622             }
623            
624             foreach my $item (@instmods) {
625             if ((!defined($look_tbl{$item})) && (defined($data->{$item}))) {
626             push @to_uninstall, $item;
627             }
628             }
629              
630             my $err = $cpanp->error_object();
631              
632             push @to_uninstall, $current_module unless (@to_uninstall > 0);
633              
634             _draw();
635             my @warning = (
636             loc('Note that uninstall only uninstalls the module you ask for '),
637             loc('It does not track prerequisites for you, nor will it warn you if'),
638             loc('you uninstall a module another module depends on!'),
639             loc('Are you sure that you want to uninstall the following module(s):')
640             );
641              
642             my $yes = $mainw->dialog('-message' => join("\n", (@warning, @to_uninstall)),
643             '-buttons' => [ 'yes','no'],
644             '-values' => [1, 0],
645             '-title' => loc('Warning'),
646             -fg => "blue",
647             -bfg => "blue",);
648              
649             if ($yes == 0) {
650             $list->clear_selection();
651             _show_installed();
652             return;
653             }
654              
655             my @endmessage;
656            
657             my $iresult = $cpanp->uninstall(modules => \@to_uninstall);
658              
659             if ($iresult->ok()) {
660             push @endmessage, loc("All modules uninstalled successfully");
661             } else {
662             @endmessage = $err->stack();
663             }
664              
665             _show_installed();
666             _draw();
667             $mainw->dialog(join("\n", @endmessage),-fg => "blue",
668             -bfg => "blue");
669              
670             }
671              
672             sub _display_installed{
673             my $installed = $cpanp->installed();
674             my $instmods = $installed->{'rv'};
675             my %newdata;
676             foreach my $module (keys %$instmods) {
677             $newdata{$module} = $data->{$module};
678             }
679             $data = \%newdata;
680             _display_results();
681             _show_installed();
682             }
683              
684             sub _show_all{
685             $data = $cpanp->module_tree();
686             _display_results();
687             _show_installed();
688             }
689              
690             sub _expand_inc_init{
691             my $topw = $mainw->getobj('topw');
692              
693             my $text = loc("Path to add:");
694              
695             $topw->getobj('talk')->text($text);
696             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
697             $topw->getobj('input')->set_routine("loose-focus", \&_expand_inc);
698             $topw->getobj('input')->set_binding("loose-focus",
699             $mainw->KEY_ENTER(),
700             $mainw->CUI_ESCAPE() );
701             $topw->getobj('input')->focus();
702             }
703              
704             sub _expand_inc{
705             my $input = shift;
706              
707             push @INC, $input->get() if defined $input->get();
708             _input_cleanup();
709             }
710              
711             ###
712             ### This is rather ugly, but we need to know which packages
713             ### where scheduled for update
714              
715             sub _uptodate{
716             $data = \%updated;
717            
718             my $list = $mainw->getobj('listw')->getobj('list');
719            
720             $list->set_routine('leave-update', \&leave_update);
721             $list->set_binding('leave-update', 'i', 'u');
722             $list->set_routine('abort-update', \&abort_update);
723             $list->set_binding('abort-update', 'q', $mainw->CUI_ESCAPE());
724             $list->set_binding('_select_all' , 'B');
725              
726             my @message = (
727             loc('Select all packages you want to update, then hit i to install updates'),
728             loc('To abort, press q')
729             );
730             _draw();
731             $mainw->dialog( -message => join("\n",@message),-fg => "blue",
732             -bfg => "blue");
733              
734             _display_results();
735             $list->clear_selection();
736             }
737              
738             sub leave_update{
739             my $list = $mainw->getobj('listw')->getobj('list');
740             my @selection = map _strip_name($_), $list->get();
741             my $err = $cpanp->error_object();
742             leave_curses();
743             print loc("Went back to shell to update ") . "\n";
744             print join "\n", @selection;
745             print "\n";
746              
747             my @endmessage;
748              
749             _fetch_modules(@selection);
750             print "Installing...\n";
751              
752             foreach my $module (@selection) {
753             print "\t$module...\n";
754              
755             my $iresult = $cpanp->install(modules => [$module],
756             target => 'install');
757             if ($iresult->ok()) {
758             push @endmessage, loc("$module updated successfully");
759             delete $data->{$module}
760             if (defined $data->{$module});
761             } else {
762             push @endmessage, loc("$module failed update");
763             }
764             }
765              
766             #Reset default bindings
767             foreach my $key (keys %$default_mode) {
768             $list->set_binding($default_mode->{$key}, $key);
769             }
770             _show_all();
771             _show_installed();
772             reset_curses();
773             $mainw->dialog( -message => join("\n", @endmessage),-fg => "blue",
774             -bfg => "blue");
775             }
776              
777             sub abort_update{
778             my $list = $mainw->getobj('listw')->getobj('list');
779             _show_all();
780              
781             foreach my $key (keys %$default_mode) {
782             $list->set_binding($default_mode->{$key}, $key);
783             }
784             }
785              
786             sub _eval_expr_init{
787             my $topw = $mainw->getobj('topw');
788              
789             my $text = loc("Perl Expression: ");
790              
791             $topw->getobj('talk')->text($text);
792             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
793             $topw->getobj('input')->set_routine("loose-focus", \&_eval_expr);
794             $topw->getobj('input')->set_binding("loose-focus",
795             $mainw->KEY_ENTER(),
796             $mainw->CUI_ESCAPE(),
797             );
798             $topw->getobj('input')->focus();
799             }
800              
801             sub _eval_expr{
802             my $input = shift;
803             my $expr = $input->get();
804             return unless defined $expr;
805              
806             $mainw->status(-message => loc("Executing..."),-fg => "blue",
807             -bfg => "blue");
808             eval($expr);
809             $mainw->error(-message => $@ . "\n" . $!) if ($@) or ($!);
810             _input_cleanup();
811             _draw();
812             }
813              
814             sub _install_params_init{
815             my $topw = $mainw->getobj('topw');
816              
817             my $text = loc("Install params: ");
818              
819             my $preset;
820             foreach my $key (keys %install_params) {
821             $preset .= " $key => $install_params{$key}, ";
822             }
823              
824             $topw->getobj('talk')->text($text);
825             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
826             $topw->getobj('input')->text($preset);
827             $topw->getobj('input')->set_routine("loose-focus", \&_install_params);
828             $topw->getobj('input')->set_binding("loose-focus",
829             $mainw->KEY_ENTER(),
830             $mainw->CUI_ESCAPE() );
831             $topw->getobj('input')->focus();
832             }
833              
834             sub _install_params{
835             my $input = shift;
836             my $params = $input->get();
837              
838             return unless defined $params;
839             %install_params = ();
840              
841             my @params = split ",", $params;
842             foreach my $param (@params) {
843             my ($key, $value) = split /=>?/, $param;
844             if (defined($key) and ($value)) {
845             $install_params{$key} = $value;
846             }
847             }
848              
849             _input_cleanup();
850             _draw();
851             }
852              
853             sub _eval_shell_init{
854             my $topw = $mainw->getobj('topw');
855              
856             my $text = loc("Shell Expression: ");
857              
858             $topw->getobj('talk')->text($text);
859             $topw->add('input','TextEntry','-x' => length($text), -fg => "green");
860             $topw->getobj('input')->set_routine("loose-focus", \&_eval_shell);
861             $topw->getobj('input')->set_binding("loose-focus",
862             $mainw->KEY_ENTER(),
863             $mainw->CUI_ESCAPE(),
864             );
865             $topw->getobj('input')->focus();
866             }
867              
868             sub _eval_shell{
869             my $input = shift;
870             my $expr = $input->get();
871             return unless defined $expr;
872             leave_curses();
873             system($expr);
874              
875             reset_curses();
876             _input_cleanup();
877             _draw();
878             }
879              
880             sub _show_cache{
881             _display_results();
882             _show_installed();
883             }
884              
885             sub _quit{
886             $mainw->status(-message => loc("Exiting..."),-fg => "blue",
887             -bfg => "blue");
888             exit 0;
889             }
890              
891             sub _display_results{
892             my $values = (shift || $data);
893             my @displaymod = sort { uc($a) cmp uc($b) }(keys(%$values));
894              
895             my @newdisplaymod;
896             my %seen;
897              
898             ### filter for same package and underline updated:
899             foreach my $module (@displaymod) {
900              
901             my $details = $data->{$module};
902             if (defined $details->{'package'} and $seen{$details->{'package'}}) {
903             delete $values->{$module};
904             next;
905             };
906             $seen{$details->{'package'}}++ if defined $details->{'package'};
907              
908             $module = "$module"
909             if $updated{$module};
910              
911             push @newdisplaymod, $module;
912             }
913              
914             ### Show all the stuff:
915             $mainw->getobj('listw')->getobj('list')->values(\@newdisplaymod);
916             $mainw->getobj('listw')->getobj('list')->draw();
917             }
918              
919             sub _input_cleanup{
920             my $topw = $mainw->getobj('topw');
921              
922             $topw->getobj('input')->loose_focus();
923             $topw->delete('input');
924             $topw->getobj('talk')->text("");
925             $mainw->getobj('listw')->getobj('list')->focus;
926             }
927              
928             sub _goto_list{
929             $mainw->getobj('listw')->getobj('list')->focus();
930             }
931              
932             sub _display_module_details{
933             my $list = $mainw->getobj('listw')->getobj('list');
934              
935             my $current_module = _strip_name($list->get_active_value());
936             return unless defined $current_module;
937              
938             my $details = $data->{$current_module};
939             return unless defined $details;
940              
941             my @text;
942             push @text, loc("Name: ") . $current_module;
943             push @text, loc("Version: ") . $details->{'version'}
944             if defined $details->{'version'};
945             push @text, loc("Author: ") . $details->{'author'}
946             if defined $details->{'author'};
947             push @text, loc("Path: ") . $details->{'path'}
948             if defined $details->{'path'};
949             push @text, loc("Package: ") . $details->{'package'}
950             if defined $details->{'package'};
951            
952             $mainw->getobj('displayw')->getobj('display')->text(join("\n", @text));
953             $mainw->getobj('displayw')->getobj('display')->draw;
954             }
955              
956             sub _set_conf{
957             my $config = $cpanp->configure_object();
958              
959             my @conf_options = $config->subtypes('conf');
960              
961             ### Build us a nice config window
962             my $max_x = $mainw->height();
963             my $max_y = $mainw->width();
964             my $height = $max_x-1;
965             my $width = int $max_y / 2;
966             $height = @conf_options unless @conf_options > $max_x -2;
967             $height+=2;
968              
969             my $configw = $mainw->add('configw','Window','-border' => 1, '-width' => $width,
970             '-height' => $height, '-centered' => 1,
971             '-title' => loc('CPANPLUS Configuration')
972             );
973             my $posy = 0;
974             my $posx = 0;
975             # Find which option has the lonest name
976             foreach my $opt (@conf_options) {
977             $posx = length($opt) unless length($opt) <= $posx
978             }
979             $posx++;
980              
981             foreach my $opt (@conf_options) {
982             $configw->add($opt . 'l', 'Label', '-y' => $posy,
983             '-text' => "\u$opt:");
984              
985              
986             if (ref $config->get_conf($opt) eq "HASH") {
987             my $hashref = $config->get_conf($opt);
988             my @keys = keys %$hashref;
989             my @values = values %$hashref;
990             my $text;
991             foreach my $key (@keys) {
992             $text .= $key . "=" . $hashref->{$key} . ":";
993             }
994             $configw->add($opt . 'hl', 'Label', '-y' => $posy,
995             '-x' => 3);
996              
997             my $entry = $configw->add($opt . 'he', 'TextEntry',
998             '-y' => $posy,
999             '-x' => $posx);
1000             $entry->text($text);
1001             $entry->set_routine('_store_conf', \&_store_conf);
1002             $entry->set_binding('_store_conf', $mainw->KEY_ENTER() );
1003             }
1004             elsif (ref $config->get_conf($opt) eq "ARRAY") {
1005             my $arrayref = $config->get_conf($opt);
1006             my $text = join (":", @$arrayref);
1007             my $entry = $configw->add($opt . 'ae', 'TextEntry',
1008             '-y' => $posy,
1009             '-x' => $posx);
1010             $entry->text($text);
1011             $entry->set_routine('_store_conf', \&_store_conf);
1012             $entry->set_binding('_store_conf', $mainw->KEY_ENTER() );
1013             }
1014             else {
1015             my $entry = $configw->add($opt . 'e', 'TextEntry', '-y' => $posy,
1016             '-x' => $posx);
1017              
1018             my $text = $config->get_conf($opt);
1019             if (defined($text)) {
1020             if ($text eq "1") { $text = 'Y' }
1021             if ($text eq "0") { $text = 'N' }
1022             $entry->text($text);
1023             }
1024             $entry->set_routine('_store_conf', \&_store_conf);
1025             $entry->set_binding('_store_conf', $mainw->KEY_ENTER() );
1026             $entry->set_routine('_abort_conf', \&_abort_conf);
1027             $entry->set_binding('_abort_conf', $mainw->CUI_ESCAPE() );
1028             }
1029             $posy++;
1030             }
1031             $configw->focus();
1032             }
1033              
1034             sub _store_conf{
1035             my $configw = $mainw->getobj('configw');
1036             my $config = $cpanp->configure_object();
1037              
1038             my @conf_options = $config->subtypes('conf');
1039             foreach my $opt (@conf_options) {
1040             my $entry = $configw->getobj($opt . 'e');
1041             if (defined $entry) {
1042             my $text = $entry->get();
1043             next unless defined $text;
1044             $opt = "\l$opt";
1045              
1046             $text =~ s/^Y.*/1/i;
1047             $text =~ s/^N.*/0/i;
1048             $config->set_conf($opt => $text); }
1049             else {
1050             my $entry = $configw->getobj($opt . 'ae');
1051             if (defined $entry) {
1052             my @values = split(":", $entry->get());
1053             $config->set_conf($opt => \@values);
1054             }
1055             else {
1056             my $entry = $configw->getobj($opt . 'he');
1057             if (defined $entry) {
1058             my @values = split(":", $entry->get());
1059             my %hash_values;
1060             foreach my $value (@values) {
1061             my ($key, $value) = split "=", $value;
1062             $hash_values{$key} = $value;
1063             }
1064             $config->set_conf($opt => \%hash_values);
1065             }
1066             }
1067             }
1068             }
1069             my $filename = $ENV{'PERL5_CPANPLUS_CONFIG'};
1070              
1071             my $yes = $mainw->dialog('-message' => loc("Do you want to store the settings to " . $filename . "?"),
1072             '-buttons' => [ 'yes','no'],
1073             '-values' => [1, 0],
1074             '-title' => loc('Qustion'),
1075             -fg => "blue",
1076             -bfg => "blue");
1077              
1078             ### There is a bug in current Configure.pm and the docs,
1079             ### it doesn't save the config as it was meant to.
1080             unless ($config->can_save($filename)) {
1081             _draw();
1082             $mainw->error(-message => loc("You are not allowed to write to ")
1083             . $filename . "\n" .
1084             loc("Config will be discared after exit"));
1085             } else {
1086              
1087             $config->save($filename) if ($yes);
1088             }
1089              
1090             $mainw->getobj('configw')->loose_focus();
1091             $mainw->delete('configw');
1092             $mainw->getobj('listw')->getobj('list')->focus();
1093              
1094             ###
1095             ### Somewhere here something odd happens, the cursor
1096             ### appears in the list. No workaround till now,
1097             ### maybe a bug in Curses::UI
1098             }
1099              
1100             sub _abort_conf{
1101             $mainw->getobj('configw')->loose_focus();
1102             $mainw->delete('configw');
1103             $mainw->getobj('listw')->getobj('list')->focus();
1104             }
1105              
1106             sub _draw{
1107             ### This is some bad curses magic in order to
1108             ### get my screen back
1109             $mainw->add('dummy','Window');
1110             $mainw->getobj('dummy')->draw();
1111             $mainw->delete('dummy');
1112              
1113             $mainw->getobj('topw')->draw();
1114             $mainw->getobj('displayw')->draw();
1115             $mainw->getobj('listw')->draw();
1116             $mainw->draw();
1117             }
1118              
1119             ###
1120             ### Help and version info
1121             ###
1122             sub _pod_help{
1123             my $podparser = Pod::Text->new(sentence => 0);
1124              
1125             my $filename;
1126              
1127             ### Find myself
1128             foreach my $mod (keys %INC) {
1129             $filename = $INC{$mod} if ($mod =~ /CPAN.+Curses\.pm/);
1130             }
1131              
1132             my $text = `pod2text $filename`;
1133              
1134             my $display = $mainw->add('readmew','Window');
1135             my $viewer = $display->add('viewer','TextViewer', -fg => "green");
1136              
1137              
1138             $viewer->text($text);
1139             $viewer->set_routine('_end_readme', \&_end_podhelp);
1140             $viewer->set_binding('_end_readme', "q" , " ");
1141             $viewer->draw();
1142             $viewer->focus();
1143             }
1144              
1145             sub _end_podhelp{
1146             my $display = $mainw->getobj('readmew');
1147             my $viewer = $display->getobj('viewer');
1148             my $list = $mainw->getobj('listw')->getobj('list');
1149              
1150             $display->delete('viewer');
1151             $mainw->delete('readmew');
1152              
1153             $mainw->draw();
1154             $list->focus();
1155             }
1156              
1157             sub _print_stack{
1158             my $err = $cpanp->error_object();
1159             my @errors = $err->stack();
1160              
1161             if (@errors == 0) {
1162             push @errors, loc("No errors occured yet");
1163             }
1164             _draw();
1165             $mainw->dialog( -message => join("\n",@errors),-fg => "blue",
1166             -bfg => "blue" );
1167             }
1168              
1169             sub _show_perldoc{
1170             my $list = $mainw->getobj('listw')->getobj('list');
1171             my $current_module = _strip_name($list->get_active_value());
1172             my $err = $cpanp->error_object();
1173              
1174             my $installed = $cpanp->installed();
1175             my $instmods = $installed->{'rv'};
1176              
1177             return unless defined $instmods->{$current_module};
1178              
1179              
1180             my $text = `pod2text $instmods->{$current_module}`;
1181              
1182             my $display = $mainw->add('readmew','Window');
1183             my $viewer = $display->add('viewer','TextViewer',
1184             '-border' => 1,
1185             '-title' => loc("Perldoc for ") . $current_module,
1186             '-bfg' => "red",
1187             '-fg' => "green");
1188              
1189             return unless defined $text;
1190              
1191             $viewer->text($text);
1192             $viewer->set_routine('_end_readme', \&_end_podhelp);
1193             $viewer->set_binding('_end_readme', "q" , " ");
1194             $viewer->draw();
1195             $viewer->focus();
1196             }
1197              
1198             sub _reload_indices{
1199             $mainw->status(-message => loc('Reloading CPAN indices...'),-fg => "blue",
1200             -bfg => "blue");
1201             my $err = $cpanp->error_object();
1202              
1203             my $result = $cpanp->reload_indices('update_source' => 1);
1204             _draw();
1205             if ($result) {
1206             $mainw->dialog(-message => loc('Successfully reloaded CPAN indices!'),-fg => "blue", -bfg => "blue");
1207             } else {
1208             $mainw->error( -message => loc('An error occured during reload: ') ."\n" . $err->stack());
1209             }
1210             _look_for_updates();
1211             $data = $cpanp->module_tree();
1212             _display_results($data);
1213             _show_installed();
1214             }
1215              
1216             sub _open_prompt{
1217             my $config = $cpanp->configure_object();
1218              
1219             my $shell = $config->get_conf('prompt') || $ENV{'SHELL'} || "/bin/sh";
1220              
1221             my $list = $mainw->getobj('listw')->getobj('list');
1222              
1223             my $current_module = _strip_name($list->get_active_value());
1224             return unless defined $current_module;
1225              
1226             my $details = $data->{$current_module};
1227             return unless defined $details;
1228              
1229             $mainw->status(-message => loc('Extracting ') . $current_module,-fg => "blue",
1230             -bfg => "blue");
1231             local $CWD = $details->extract();
1232             $mainw->nostatus();
1233             if ($shell) {
1234             leave_curses();
1235             my $oldps1 = $ENV{PS1};
1236             $ENV{PS1} = "CPANPLUS::Shell::Curses\$ ";
1237              
1238             print loc("Type exit to return to CPANPLUS::Shell::Curses\n");
1239             print loc("You are in $CWD\n");
1240             system ($ENV{SHELL});
1241              
1242             reset_curses();
1243             $ENV{PS1} = $oldps1;
1244             }
1245             }
1246              
1247             sub _write_bundle{
1248             my $err = $cpanp->error_object();
1249             $mainw->status(-message => loc('Writing a autobundle...'),-fg => "blue",
1250             -bfg => "blue");
1251              
1252             my $rv = $cpanp->autobundle();
1253             _draw();
1254             if ($rv->ok()) {
1255             my $name = $rv->rv();
1256             $mainw->dialog(-message => loc("Auobundle ") . $name . loc(" successfully written"), -fg => "blue",
1257             -bfg => "blue");
1258             } else {
1259             $mainw->error(-message => loc('An error occured during bundling: ') ."\n" . $err->stack());
1260             }
1261             }
1262              
1263             sub _show_reports_init{
1264             my $list = $mainw->getobj('listw')->getobj('list');
1265             my $current_module = _strip_name($list->get_active_value());
1266             my $err = $cpanp->error_object();
1267              
1268             next unless $current_module;
1269              
1270             $mainw->status(-message => loc('Getting reports for ') . $current_module,-fg => "blue",
1271             -bfg => "blue");
1272              
1273             my $reports = $cpanp->reports('modules' => [$current_module]);
1274              
1275             unless ($reports->ok()) {
1276             _draw();
1277             $mainw->error(-message => loc("Could not get report: ") . $err->stack());
1278             return;
1279             }
1280             my @text;
1281             my $rvref = $reports->rv();
1282             return unless $rvref;
1283             my $arrayref = $rvref->{$current_module};
1284             return unless $arrayref;
1285             foreach my $hashref (@$arrayref) {
1286             foreach my $key (keys %$hashref) {
1287             push @text, "\u$key: " . $hashref->{$key};
1288             }
1289             push @text, " ";
1290             }
1291              
1292             $mainw->dialog(message => join("\n",@text),
1293             title => loc("Test results for ") . $current_module , -fg => "blue",
1294             -bfg => "blue");
1295             }
1296              
1297             sub _extract_files{
1298             my $list = $mainw->getobj('listw')->getobj('list');
1299             my $installed = $cpanp->installed();
1300             my $mods = $installed->{'rv'};
1301             my @instmods = sort { uc($a) cmp uc($b) } keys %$mods;
1302            
1303             my @selection = $list->get();
1304              
1305             my %look_tbl;
1306             my @to_extract;
1307              
1308             foreach my $item (@instmods) {$look_tbl{$item} = 1; }
1309             foreach my $item (@selection) {
1310             unless ($look_tbl{$item}) {
1311             push @to_extract, $item;
1312             }}
1313              
1314             my $err = $cpanp->error_object();
1315              
1316             foreach my $mod (@to_extract) {
1317             $mainw->status(-message => loc('Currently extracting') . $mod,-fg => "blue",
1318             -bfg => "blue");
1319             my $iresult = $cpanp->extract(modules => [$mod]);
1320             if ($iresult->ok()) {
1321             _draw();
1322             $mainw->dialog(-message => $mod . loc(" extracted successfully"),-fg => "blue",
1323             -bfg => "blue");
1324             } else {
1325             _draw();
1326             $mainw->error(-message => loc("Error extracting ") . $mod . "\n" . $err->stack());
1327             }
1328             _draw();
1329             }
1330              
1331              
1332             }
1333              
1334             sub _show_banner{
1335             my $bversion = $CPANPLUS::Backend::VERSION;
1336              
1337             my @text = (
1338             loc(' CPANPLUS::SHELL::Curses '),
1339             ' ' . $VERSION ,
1340             loc(' Visual CPAN exploration and module installation '),
1341             loc(' Please report bugs to . '),
1342             loc(' Using CPANPLUS::Backend v'.$bversion.' '),
1343             );
1344             _draw();
1345             $mainw->dialog(-message => join("\n",@text),-fg => "blue",
1346             -bfg => "blue");
1347             }
1348              
1349              
1350             sub _search_module_author{
1351             $mainw->status(-message => loc("Searching..."),-fg => "blue",
1352             -bfg => "blue");
1353             my $list = $mainw->getobj('listw')->getobj('list');
1354              
1355             my $current_module = _strip_name($list->get_active_value());
1356             return unless defined $current_module;
1357              
1358             my $details = $data->{$current_module};
1359             return unless defined $details;
1360              
1361             my $author = $details->{'author'};
1362             return unless defined $author;
1363             $mainw->status(-message => loc("Searching for ") . $author,-fg => "blue",
1364             -bfg => "blue" );
1365              
1366             $data = $cpanp->search(type => 'author', list=> [$author]);
1367             if (defined($data)) {
1368             _display_results($data);
1369             _show_installed();
1370             } else {
1371             $mainw->error(-message => loc("Nothing found!"));
1372             }
1373             }
1374              
1375             sub _search_namespace_module{
1376             $mainw->status(-message => loc("Searching..."),-fg => "blue",
1377             -bfg => "blue");
1378             my $list = $mainw->getobj('listw')->getobj('list');
1379              
1380             my $current_module = _strip_name($list->get_active_value());
1381             return unless defined $current_module;
1382              
1383             if ($current_module =~ /(\w+)/) {
1384             my $namespace = $1;
1385             $mainw->status(-message => loc("Searching in Namespace ") . $namespace,-fg => "blue",
1386             -bfg => "blue");
1387             $data = $cpanp->search(type => 'module', list=> ["^$namespace"]);
1388             if (defined($data)) {
1389             _display_results($data);
1390             _show_installed();
1391             } else {
1392             $mainw->error(-message => loc("Nothing found!"));
1393             }
1394             }
1395             $mainw->nostatus();
1396             }
1397              
1398             sub _search_namespace_module2{
1399             $mainw->status(-message => loc("Searching..."),-fg => "blue",
1400             -bfg => "blue");
1401             my $list = $mainw->getobj('listw')->getobj('list');
1402              
1403             my $current_module = _strip_name($list->get_active_value());
1404             return unless defined $current_module;
1405              
1406             if ($current_module =~ /(\w+::\w+)/) {
1407             my $namespace = $1;
1408             $mainw->status(-message => loc("Searching in Namespace ") . $namespace,-fg => "blue",
1409             -bfg => "blue");
1410             $data = $cpanp->search(type => 'module', list=> ["^$namespace"]);
1411             if (defined($data)) {
1412             _display_results($data);
1413             _show_installed();
1414             } else {
1415             $mainw->error(-message => loc("Nothing found!"));
1416             }
1417             }
1418             $mainw->nostatus();
1419             }
1420              
1421             sub _show_deps{
1422             my $list = $mainw->getobj('listw')->getobj('list');
1423             my $current_module = _strip_name($list->get_active_value());
1424             my $err = $cpanp->error_object();
1425              
1426             my $installed = $cpanp->installed();
1427             my $instmods = $installed->{'rv'};
1428              
1429             return unless defined $instmods->{$current_module};
1430              
1431             $mainw->status(-message => loc("Searching dependencies for ") . $current_module,-fg => "blue",
1432             -bfg => "blue");
1433              
1434             my $hashref = Module::ScanDeps::scan_deps($instmods->{$current_module});
1435              
1436             my @modules = keys %$hashref;
1437             my @names;
1438              
1439             foreach my $module (@modules) {
1440             $module =~ s|/|::|g;
1441             $module =~ s/\.pm|\.ix|\.al|\.ld|\.so|\.bs//g;
1442             push @names, $module;
1443             }
1444             @names = sort { uc($a) cmp uc($b) } @names;
1445             $mainw->dialog(-message => join("\n",@names),
1446             -title => loc("Dependencies for ") . $current_module,-fg => "blue",
1447             -bfg => "blue");
1448             }
1449              
1450             sub _show_stats{
1451             $mainw->status(-message => loc("Gathering statistical information..."),-fg => "blue",
1452             -bfg => "blue");
1453             my $installed = $cpanp->installed();
1454             my $instmods = $installed->{'rv'};
1455             my $modules = $cpanp->module_tree();
1456             my $authors = $cpanp->author_tree();
1457             my $number_outdated = 0;
1458             foreach my $module (keys %$instmods) {
1459             my $uptodate = $cpanp->uptodate('modules' => [$module]);
1460             next unless defined $uptodate;
1461             next if $uptodate->rv()->{$module}->{uptodate};
1462             $number_outdated++;
1463             }
1464              
1465             my $number_installed = keys %{$instmods};
1466             my $number_total = keys %{$modules};
1467             my $number_authors = keys %{$authors};
1468              
1469             $mainw->dialog( -message => loc('Installed Modules: ') . $number_installed . "\n"
1470             .loc('Outdated Modules: ') . $number_outdated . "\n\n"
1471             .loc('Modules on CPAN: ') . $number_total . "\n"
1472             .loc('Registered Authors: ') . $number_authors . "\n\n"
1473             .loc('PID: ') . $$ . "\n"
1474             .loc('OS: ') . $^O . "\n"
1475             .loc('Perl Version: ') . $] . "\n"
1476             ,-fg => "blue",
1477             -bfg => "blue");
1478             }
1479              
1480             sub _select_all{
1481             my $list = $mainw->getobj('listw')->getobj('list');
1482              
1483             for my $i (0..keys %{$data}) {
1484             $list->set_selection($i);
1485             }
1486             }
1487              
1488             sub _look_for_updates{
1489             $mainw->status(-message => loc('Looking for updated modules...'),-fg => "blue",
1490             -bfg => "blue");
1491             my $installed = $cpanp->installed();
1492             my $instmods = $installed->{'rv'};
1493             foreach my $module (keys %$instmods) {
1494             my $uptodate = $cpanp->uptodate('modules' => [$module]);
1495             next unless defined $uptodate;
1496             next if $uptodate->rv()->{$module}->{uptodate};
1497             $updated{$module} = $data->{$module};
1498             }
1499             }
1500              
1501             sub _strip_name{
1502             my $module = shift;
1503             return unless defined $module;
1504             if ($module =~ />([^<]+)
1505             return $1;
1506             }
1507             return $module;
1508             }
1509              
1510              
1511             1;
1512              
1513             __END__