Add Umph::Prompt version
[umph.git] / bin / umph
blob96d2e7afb57555908079edaa14ff2af60d2cd87d
1 #!/usr/bin/perl
3 # umph
4 # Copyright (C) 2010-2011 Toni Gundogdu <legatvs@gmail.com>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 use feature 'say';
22 use warnings;
23 use strict;
25 binmode STDOUT, ":utf8";
26 binmode STDERR, ":utf8";
28 use version 0.77 (); our $VERSION = version->declare("0.2.0");
30 use Getopt::ArgvFile(home => 1, startupFilename => [qw(.umphrc)]);
31 use Getopt::Long qw(:config bundling);
32 use Carp qw(croak);
34 exit main();
36 sub print_version
38 eval "require Umph::Prompt";
39 my $p = $@ ? "" : ", Umph::Prompt version $Umph::Prompt::VERSION";
40 say "umph version $VERSION$p
41 Copyright (C) 2010-2011 Toni Gundogdu
42 This is free software; see the source for copying conditions. There is NO
43 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.";
44 exit 0;
47 sub print_help
49 require Pod::Usage;
50 Pod::Usage::pod2usage(-exitstatus => 0, -verbose => 1);
53 use constant MAX_RESULTS_LIMIT => 50; # Refer to http://is.gd/OcSjwU
54 my %config;
56 sub check_max_results_value
58 if ($config{max_results} > MAX_RESULTS_LIMIT)
60 say STDERR
61 "WARNING --max-results exceeds max. accepted value, using "
62 . MAX_RESULTS_LIMIT
63 . " instead";
64 $config{max_results} = MAX_RESULTS_LIMIT;
68 sub check_umph_prompt
70 if ($config{'interactive'} and not eval 'require Umph::Prompt')
72 say STDERR
73 qq/WARNING Umph::Prompt not found, ignoring --interactive option/;
74 $config{interactive} = 0;
78 sub init
80 GetOptions(
81 \%config,
82 'type|t=s',
83 'start_index|start-index|s=i',
84 'max_results|max-results|m=i',
85 'interactive|i',
86 'all|a',
87 'json',
88 'csv',
89 'proxy=s',
90 'no_proxy|no-proxy',
91 'quiet|q',
92 'version' => \&print_version,
93 'help' => \&print_help,
94 ) or exit 1;
96 print_help if scalar @ARGV == 0;
98 $config{type} ||= 'p'; # Default to "playlist".
99 $config{start_index} ||= 1; # Default to 1.
100 $config{max_results} ||= 25; # Default 25.
102 check_max_results_value;
103 check_umph_prompt;
106 sub spew_qe {print STDERR @_ unless $config{quiet}}
108 my @items;
110 sub main
112 init;
113 spew_qe "Checking ... ";
115 require LWP;
116 my $a = new LWP::UserAgent;
117 $a->env_proxy; # http://search.cpan.org/perldoc?LWP::UserAgent
118 $a->proxy('http', $config{proxy}) if $config{proxy};
119 $a->no_proxy('') if $config{no_proxy};
121 require XML::DOM;
122 my $p = new XML::DOM::Parser(LWP_UserAgent => $a);
123 my $s = $config{start_index};
124 my $m = $config{all} ? MAX_RESULTS_LIMIT : $config{max_results};
126 while (1)
128 my $doc = $p->parsefile(from_arg($ARGV[0], $s, $m));
129 my $root = $doc->getDocumentElement;
130 my $n = 0;
131 for my $entry ($root->getElementsByTagName("entry"))
133 my $t = to_item($entry, "title")->getFirstChild->getNodeValue;
134 my $l =
135 to_item($entry, "link")->getAttributeNode("href")->getValue;
136 my %data = (title => $t, url => $l, selected => 1);
137 push @items, \%data;
138 spew_qe((++$n % 5 == 0) ? " " : ".");
139 ++$s;
141 $doc->dispose;
143 last if $n == 0 or not $config{all};
146 spew_qe "done.\n";
148 croak "error: nothing found\n" if scalar @items == 0;
150 open_prompt() if $config{interactive};
152 say qq/{\n "video": [/ if $config{json};
154 my $i = 0;
156 foreach (@items)
158 if ($_->{selected} or not $config{interactive})
160 ++$i;
162 my $t = $_->{title} || "";
163 $t =~ s/"/\\"/g;
165 if ($config{json})
167 say "," if $i > 1;
168 say " {";
169 say qq/ "title": "$t",/;
170 say qq/ "url": "$_->{url}"/;
171 print " }";
173 elsif ($config{csv}) {say qq/"$t","$_->{url}"/}
174 else {say "$_->{url}"}
178 say "\n ]\n}" if $config{json};
182 use constant GURL => "http://gdata.youtube.com/feeds/api";
184 sub from_arg
186 my ($arg0, $s, $m) = @_;
188 my $u;
189 if ($config{type} eq "u" or $config{type} eq "uploads")
191 $u = GURL . "/users/$arg0/uploads?v=2";
193 elsif ($config{type} eq "f" or $config{type} eq "favorites")
195 $u = GURL . "/users/$arg0/favorites?v=2";
197 else
199 $u = GURL . "/playlists/$arg0?v=2";
202 $u .= "&start-index=$s";
203 $u .= "&max-results=$m";
206 sub to_item
208 my ($entry, $name) = @_;
209 $entry->getElementsByTagName($name)->item(0);
212 sub open_prompt
214 my $p = new Umph::Prompt(
216 # Commands.
217 commands => {
218 q => sub {
219 my ($p, $args) = @_;
220 $p->exit(\@items, $args);
222 d => sub {
223 my ($p, $args) = @_;
224 $p->display(\@items, $args);
226 m => sub {
227 my ($p, $args) = @_;
228 $p->max_shown_items(@{$args});
230 s => sub {
231 my ($p, $args) = @_;
232 $p->select(\@items, $args);
234 h => sub {
235 my ($p, $args) = @_;
236 my @a;
237 push @a,
238 {cmd => 'normal', desc => 'print results in default format'};
239 push @a, {cmd => 'json', desc => 'print results in json'};
240 push @a, {cmd => 'csv', desc => 'print results in csv'};
241 $p->help(\@a);
243 n => sub {
244 $config{json} = 0;
245 $config{csv} = 0;
246 say STDERR "=> print in default format";
248 j => sub {
249 $config{json} = 1;
250 $config{csv} = 0;
251 say STDERR "=> print in json";
253 c => sub {
254 $config{json} = 0;
255 $config{csv} = 1;
256 say STDERR "=> print in csv";
260 # Callbacks. All of these are optional.
261 ontoggle => sub {
262 my ($p, $args) = @_;
263 $p->toggle(\@items, $args);
265 onitems => sub {return \@items},
266 onloaded => sub {
267 my ($p, $args) = @_;
268 $p->display(\@items, $args);
271 # Other (required) settings
272 total_items => scalar @items,
273 prompt_msg => 'umph',
274 max_shown_items => 20
277 say STDERR qq/Enter prompt. Type "help" to get a list of commands./;
278 $p->exec;
281 __END__
283 =head1 SYNOPSIS
285 umph [-q] [-i] [-a] [--csv | --json] [-t E<lt>typeE<gt>]
286 [--proxy E<lt>addrE<gt> | --no-proxy]
287 [E<lt>playlist_idE<gt> | E<lt>usernameE<gt>]
289 =head2 OPTIONS
291 --help Print help and exit
292 --version Print version and exit
293 -q, --quiet Be quiet
294 -i, --interactive Run in interactive mode
295 -t, --type arg (=p) Get feed type
296 -s, --start-index arg (=1) Index of first matching result
297 -m, --max-results arg (=25) Max number of results included
298 -a, --all Get all items
299 --json Print details in JSON
300 --csv Print details in CSV
301 --proxy arg (=http_proxy) Use proxy for HTTP connections
302 --no-proxy Disable use of HTTP proxy
304 =cut
306 # vim: set ts=2 sw=2 tw=72 expandtab: