Update textviewer.pl
[claws.git] / tools / textviewer.pl
1 #!/usr/bin/perl
2
3 # COPYRIGHT AND LICENSE
4 #        Copyright (C) 2005-2018 H.Merijn Brand
5 #
6 #        This script is free software; you can redistribute it and/or modify it
7 #        under the same terms as Perl and/or Claws Mail itself. (GPL)
8
9 use 5.14.1;
10 use warnings;
11
12 our $VERSION = "1.01 - 2018-10-08";
13 our $CMD = $0 =~ s{.*/}{}r;
14
15 sub usage {
16     my ($err, $str) = (@_, "");
17     $err and select STDERR;
18     say "usage: $CMD [--html] [--type=<type>] file\n",
19         "       --html    Generate HTML (if supported)\n",
20         "       --type=X  X as mimetype (msword => doc)\n",
21         "  $CMD --list will show all implemented conversions";
22     $str and say $str;
23     exit $err;
24     } # usage
25
26 use Getopt::Long qw(:config bundling nopermute);
27 my $opt_v = 0;
28 my $opt_h = "text";
29 GetOptions (
30     "help|?"            => sub { usage (0); },
31     "V|version"         => sub { say "$CMD [$VERSION]"; exit 0; },
32
33     "v|verbose:1"       => \$opt_v,
34     "t|type|mimetype=s" => \my $opt_t,
35     "h|html"            => sub { $opt_h = "html" },
36     "l|list!"           => \my $opt_l,
37     ) or usage (1);
38
39 $opt_v and say "$0 @ARGV";
40
41 # anon-list contains all possible commands to show content
42 # plain text is a reference to same type (alias)
43 # %f will be replaced with file. If no %f, file will be the last arg
44 my %fh = (
45     text => {
46         bin     => [ "strings"          ], # fallback for binary files
47
48         txt     => [ "cat"              ], # Plain text
49
50         html    => [ "htm2txt",
51                      "html2text"        ], # HTML
52
53         msword  => "doc",
54         doc     => [ "catdoc -x -dutf-8",
55                      "wvText",
56                      "antiword -w 72"   ], # M$ Word
57         "vnd.ms-excel" => "xls",
58         "ms-excel"     => "xls",
59         docx    => [ "unoconv -f text --stdout" ], # MS Word
60         xlsx    => "xls",
61         xls     => [ "xlscat -L",
62                      "catdoc -x -dutf-8",
63                      "wvText"           ], # M$ Excel
64 #       ppt     => [ "ppthtml"          ], # M$ PowerPoint
65 #                       ppthtml "$1" | html2text
66         csv     => "xls",                  # Comma Separated Values
67
68         ics     => [ "ics2txt"          ], # ICS calendar request
69
70         rtf     => [ "rtf2text",
71                      "unrtf -t text"    ], # RTF
72         pdf     => [ "pdftotext %f -"   ], # Adobe PDF
73
74         ods     => "xls",                  # OpenOffice spreadsheet
75         sxc     => "xls",                  # OpenOffice spreadsheet
76         odt     => [ "oo2pod %f | pod2text",
77                      "ooo2txt"          ], # OpenOffice writer
78         rtf     => [ "rtf2text"         ], # RTF
79
80         pl      => [ "perltidy -st -se",
81                      "cat"              ], # Perl
82         pm      => "pl",
83
84         jsn     => [ "json_pp"          ], # JSON
85         json    => "jsn",
86
87         xml     => [ "xml_pp"           ], # XML
88
89         ( map { $_ => "txt" } qw(
90             patch diff
91             c h ic ec cc
92             sh sed awk
93             plain
94             yml yaml
95             )),
96
97         bz2     => [ "bzip2 -d < %f | strings" ],
98
99         zip     => [ "unzip -l %f"      ], # ZIP
100
101         test    => [ \&test             ], # Internal
102
103         tgz     => [ "tar tvf"          ], # Tar     uncompressed
104         tgz     => [ "tar tzvf"         ], # Tar GZ    compressed
105         tbz     => [ "tar tjvf"         ], # Tar BZip2 compressed
106         txz     => [ "tar tJvf"         ], # Tar XZ    compressed
107
108         rar     => [ "unrar l"          ], # RAR
109         },
110
111     html => {
112         rtf     => [ "rtf2html"         ],
113         },
114     );
115
116 if ($opt_l) {
117     my %tc = %{$fh{text}};
118     foreach my $ext (sort keys %tc) {
119         my $exe = $tc{$ext};
120         ref $exe or $exe = $tc{$exe};
121         printf "  .%-12s %s\n", $ext, $_ for @$exe;
122         }
123     exit 0;
124     }
125
126 my $file = shift or usage (1, "File argument is missing");
127 -f $file         or usage (1, "File argument is not a plain file");
128 -r $file         or usage (1, "File argument is not a readable file");
129 -s $file         or usage (1, "File argument is an empty file");
130
131 my $ext = $file =~ m/\.(\w+)$/ ? lc $1 : "";
132 $opt_t && exists $fh{text}{lc $opt_t} and $ext = lc$opt_t;
133 unless (exists $fh{text}{$ext}) {
134     my $ftype = `file --brief $file`;
135     $ext =
136         $ftype =~ m/^pdf doc/i                                  ? "pdf" :
137         $ftype =~ m/^ascii( english)? text/i                    ? "txt" :
138         $ftype =~ m/^(utf-8 unicode|iso-\d+)( english)? text/i  ? "txt" :
139         $ftype =~ m/^xml doc/i                                  ? "xml" :
140         $ftype =~ m/^\w+ compress/i                             ? "bin" :
141                                                                   "bin" ;
142     # \w+ archive
143     # \w+ image
144     # ...
145     }
146 $ext ||= "txt";
147 exists $fh{$opt_h}{$ext} or $opt_h = "text";
148 exists $fh{$opt_h}{$ext} or $ext   = "txt";
149 my          $ref = $fh{$opt_h}{$ext};
150 ref $ref or $ref = $fh{$opt_h}{$ref};
151
152 $opt_v and warn "[ @$ref ] $file\n";
153
154 sub which {
155     (my $cmd = shift) =~ s/\s.*//; # Only the command. Discard arguments here
156     foreach my $path (split m/:+/, $ENV{PATH}) {
157         -x "$path/$cmd" and return "$path/$cmd";
158         }
159     return 0;
160     } # which
161
162 my $cmd = "cat -ve";
163 foreach my $c (@$ref) {
164     if (ref $c) {
165         $c->($file);
166         exit;
167         }
168
169     my $cp = which ($c) or next;
170     $cmd = $c;
171     last;
172     }
173
174 my @cmd = split m/ +/ => $cmd;
175 grep { s/%f\b/$file/ } @cmd or push @cmd, $file;
176 #$cmd =~ s/%f\b/$file/g or $cmd .= " $file";
177 $opt_v and say "@cmd";
178 exec @cmd;