File Coverage

blib/lib/Term/ReadLine/Zoid/FileBrowse.pm
Criterion Covered Total %
statement 6 116 5.1
branch 0 44 0.0
condition 0 3 0.0
subroutine 2 18 11.1
pod 3 16 18.7
total 11 197 5.5


line stmt bran cond sub pod time code
1             package Term::ReadLine::Zoid::FileBrowse;
2              
3 1     1   2010 use strict;
  1         2  
  1         42  
4 1     1   5 use base 'Term::ReadLine::Zoid';
  1         2  
  1         3961  
5              
6             our $VERSION = 0.01;
7              
8             our %_keymap = ( # maybe inherit from insert ? these could be remapped
9             up => 'select_previous',
10             down => 'select_next',
11             right => 'select_next_col',
12             left => 'select_previous_col',
13             page_up => 'page_up',
14             page_down => 'page_down',
15             return => 'accept_line',
16             ctrl_C => 'return_empty_string',
17             escape => 'switch_mode',
18             '/' => 'fb_mini_buffer',
19             ' ' => 'toggle_mark',
20             '.' => 'toggle_hide_hidden',
21             _default => 'self_insert',
22             _on_switch => 'fb_switch',
23             );
24              
25             sub keymap {
26 0     0 1   my $self = shift;
27 0           for (
28             ['hide_hidden_files', 1],
29             ['fb_prompt', "\e[1;37m -- \%s -- \e[0m"],
30             ) {
31 0 0         $$self{config}{$$_[0]} = $$_[1]
32             unless defined $$self{config}{$$_[0]}
33             }
34 0           return \%_keymap;
35             }
36              
37             # fb_item == item currently selected (pointed at)
38             # fb_marks == marked _numbers_ in current dir
39             # fb_marked == marked _items_ in other dirs
40             # fb_items == items in current dir
41             # fb_dir == current dir
42              
43             sub fb_switch {
44 0     0 0   my $self = shift;
45 0           @$self{qw/fb_item fb_marks fb_marked fb_items/} = (0, [], [], []);
46 0           $self->fb_switch_dir('.');
47             }
48              
49             sub fb_switch_dir { # FIXME FIXME "marked" admisnistrationis contains bugs
50 0     0 0   my ($self, $dir) = @_;
51 0   0       $dir ||= $$self{fb_dir};
52 0           my $pwd;
53 0 0         if ($dir eq '.') { $dir = $ENV{PWD}; $pwd++; }
  0            
  0            
54             else {
55 0           $dir =~ s#^\./#$ENV{PWD}#;
56 0           $dir =~ s#/\.(/|$)|//+#/#g;
57 0           $dir =~ s#(^|/)[^/]*/\.\.(/|$)##g;
58 0           $dir =~ s#/?$#/#;
59             }
60              
61 0 0         opendir DIR, $dir or return $self->bell;
62 0           my (@marks, @marked);
63 0           for ($self->marked()) {
64 0 0         if (m#(.*/)(.*)#) {
    0          
65 0 0         if ($1 eq $dir) { push @marks, $2 }
  0            
66 0           else { push @marked, $_ }
67             }
68 0           elsif ($pwd) { push @marks, $_ }
69 0           else { push @marked, $_ }
70             }
71 0 0         $$self{fb_items} = [ '../',
72 0           map {-d "$dir/$_" ? $_.'/' : $_}
73             $$self{config}{hide_hidden_files}
74 0           ? (sort grep {$_ !~ /^\./ } readdir DIR)
75 0 0         : (sort grep {$_ !~ /^\.\.?$/} readdir DIR)
76             ];
77 0           close DIR;
78 0           $$self{fb_marked} = \@marked;
79 0           $$self{fb_marks} = [];
80 0 0         if (@marks) {
81 0           my $i = 0;
82 0           for my $item (@{$$self{fb_items}}) {
  0            
83 0           push @{$$self{fb_marks}}, $i
  0            
84 0 0         if grep {$_ eq $item} @marks;
85 0           $i++;
86             }
87             }
88 0           @$self{qw/fb_item fb_dir/} = (0, $dir);
89             }
90              
91             sub draw { # Render Fu
92 0     0 0   my $self = shift;
93            
94 0           my @pos = (1, 1);
95 0           my @lines = map " $_", @{$$self{fb_items}};
  0            
96 0           for (@{$$self{fb_marks}}) { $lines[$_] =~ s/^ /*/ }
  0            
  0            
97 0           $lines[ $$self{fb_item} ] =~ s/^(.) /$1>/;
98              
99 0           @lines = $self->col_format( @lines );
100 0           $$self{fb_rows} = scalar @lines;
101 0           $pos[1] += ($$self{fb_item} % $$self{fb_rows}); # assuming +1 offset due to fb_prompt
102              
103 0           unshift @lines, sprintf $$self{config}{fb_prompt}, $$self{fb_dir};
104              
105 0           $self->print(\@lines, \@pos);
106             }
107              
108             sub toggle_hide_hidden {
109 0 0   0 0   $_[0]{config}{hide_hidden_files} =
110             $_[0]{config}{hide_hidden_files} ? 0 : 1 ;
111 0           $_[0]->fb_switch_dir();
112             }
113              
114             sub self_insert {
115 0     0 0   my ($self, $key) = @_;
116 0 0         return $self->bell unless $key =~ /^\d+$/;
117             #$$self{fb_item} .= $key;
118             }
119              
120             sub accept_line {
121 0     0 0   my $self = shift;
122 0           my $dir = $$self{fb_dir}.'/'.$$self{fb_items}[ $$self{fb_item} ];
123 0 0         return $self->fb_switch_dir($dir) if -d $dir;
124              
125 0           push @{$$self{fb_marks}}, $$self{fb_item};
  0            
126 0           my @words = map {s/'/\\'/g; '\''.$_.'\''} $self->marked();
  0            
  0            
127 0           $self->substring(join(' ', @words), $$self{pos});
128 0           $self->switch_mode();
129             }
130              
131             sub fb_mini_buffer {
132 0     0 0   my $self = shift;
133             }
134              
135 0 0   0 0   sub select_next { $_[0]{fb_item}++ if $_[0]{fb_item} < $#{$_[0]{fb_items}} }
  0            
136              
137             sub page_up {
138 0     0 1   my $self = shift;
139 0           my (undef, $higth) = $self->TermSize();
140 0           my $vpos = $$self{fb_item} % $$self{fb_rows};
141 0 0         if ($vpos > $higth) { $$self{fb_item} -= $higth }
  0            
142 0           else { $$self{fb_item} -= $vpos }
143             }
144              
145             sub page_down {
146 0     0 1   my $self = shift;
147 0           my (undef, $higth) = $self->TermSize();
148 0           my $rvpos = $$self{fb_rows} - ($$self{fb_item} % $$self{fb_rows});
149 0 0         if ($rvpos > $higth) { $$self{fb_item} += $higth }
  0            
150 0           else { $$self{fb_item} += $rvpos }
151 0 0         $$self{fb_item} = $#{$$self{fb_items}} if $$self{fb_item} > $#{$$self{fb_items}};
  0            
  0            
152             }
153              
154 0 0   0 0   sub select_previous { $_[0]{fb_item}-- if $_[0]{fb_item} > 0 }
155              
156             sub select_next_col {
157 0           $_[0]{fb_item} += $_[0]{fb_rows}
158 0 0   0 0   unless $_[0]{fb_rows} > $#{$_[0]{fb_items}} - $_[0]{fb_item};
159             }
160              
161             sub select_previous_col {
162 0 0   0 0   $_[0]{fb_item} -= $_[0]{fb_rows}
163             unless $_[0]{fb_rows} > $_[0]{fb_item};
164             }
165              
166             sub toggle_mark { # FIXME should be toggle
167 0     0 0   my $self = shift;
168 0           my $l = scalar @{$$self{fb_marks}};
  0            
169 0           @{$$self{fb_marks}} = grep {$_ != $$self{fb_item}} @{$$self{fb_marks}};
  0            
  0            
  0            
170 0 0         push @{$$self{fb_marks}}, $$self{fb_item} if $l == scalar @{$$self{fb_marks}};
  0            
  0            
171 0           $self->select_next();
172             }
173              
174             sub marked {
175 0     0 0   my $self = shift;
176 0           my $dir = $$self{fb_dir};
177 0           $dir =~ s#^\Q$ENV{PWD}\E/?##;
178 0 0         $dir =~ s#/?$#/# if length $dir;
179 0           return @{$$self{fb_marked}},
  0            
180 0           map $dir.$_, @{$$self{fb_items}}[ @{$$self{fb_marks}} ];
  0            
181             }
182              
183             1;
184              
185             __END__