line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::PTP::Args; |
2
|
|
|
|
|
|
|
|
3
|
17
|
|
|
17
|
|
68547
|
use 5.022; |
|
17
|
|
|
|
|
67
|
|
4
|
17
|
|
|
17
|
|
81
|
use strict; |
|
17
|
|
|
|
|
30
|
|
|
17
|
|
|
|
|
342
|
|
5
|
17
|
|
|
17
|
|
73
|
use warnings; |
|
17
|
|
|
|
|
28
|
|
|
17
|
|
|
|
|
611
|
|
6
|
|
|
|
|
|
|
|
7
|
17
|
|
|
17
|
|
7980
|
use App::PTP::Commands ':CMD'; |
|
17
|
|
|
|
|
49
|
|
|
17
|
|
|
|
|
3752
|
|
8
|
17
|
|
|
17
|
|
128
|
use App::PTP::Util; |
|
17
|
|
|
|
|
33
|
|
|
17
|
|
|
|
|
460
|
|
9
|
17
|
|
|
|
|
156
|
use Getopt::Long qw(GetOptionsFromArray :config auto_abbrev no_ignore_case |
10
|
17
|
|
|
17
|
|
11936
|
permute auto_version); |
|
17
|
|
|
|
|
196447
|
|
11
|
17
|
|
|
17
|
|
4031
|
use List::Util; |
|
17
|
|
|
|
|
34
|
|
|
17
|
|
|
|
|
838
|
|
12
|
17
|
|
|
17
|
|
8704
|
use Pod::Usage; |
|
17
|
|
|
|
|
796386
|
|
|
17
|
|
|
|
|
2478
|
|
13
|
17
|
|
|
17
|
|
156
|
use Scalar::Util 'looks_like_number'; |
|
17
|
|
|
|
|
72
|
|
|
17
|
|
|
|
|
51007
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Name of files or directory to be processed. This can also contain a reference |
16
|
|
|
|
|
|
|
# to the $stdin_marker variable, to indicate that the standard input needs to be |
17
|
|
|
|
|
|
|
# processed. |
18
|
|
|
|
|
|
|
my @inputs; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# The list of actions applied to the input. This is a list of array reference. |
21
|
|
|
|
|
|
|
# Each of these array will contain the name of the command to run, the coderef |
22
|
|
|
|
|
|
|
# for it, and then its arguments if any. |
23
|
|
|
|
|
|
|
my @pipeline; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# This hash contains options that are used during the pipeline and that can be |
26
|
|
|
|
|
|
|
# set or un-set for each command. |
27
|
|
|
|
|
|
|
my %modes; |
28
|
|
|
|
|
|
|
# This hash contains options that are global for the whole program. |
29
|
|
|
|
|
|
|
my %options; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $default_input_field = '\s*,\s*|\t'; |
32
|
|
|
|
|
|
|
my $default_output_field = "\t"; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# env(foo => default) |
35
|
|
|
|
|
|
|
# Returns the given environment variable or the default value. |
36
|
|
|
|
|
|
|
# Always return the default value if the HARNESS_ACTIVE variable is set (so that |
37
|
|
|
|
|
|
|
# tests are not affected by environment variables). |
38
|
|
|
|
|
|
|
sub env { |
39
|
896
|
|
|
896
|
0
|
1517
|
my ($var, $default) = @_; |
40
|
896
|
50
|
|
|
|
2887
|
return $default if $ENV{HARNESS_ACTIVE}; |
41
|
0
|
|
0
|
|
|
0
|
return $ENV{$var} // $default; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_default_modes { |
45
|
128
|
|
|
128
|
0
|
216
|
my %m; |
46
|
128
|
|
|
|
|
325
|
$m{case_sensitive} = not(env(PTP_DEFAULT_CASE_INSENSITIVE => 0)); |
47
|
128
|
|
|
|
|
303
|
$m{quote_regex} = env(PTP_DEFAULT_QUOTE_REGEX => 0); |
48
|
128
|
|
|
|
|
244
|
$m{global_match} = not(env(PTP_DEFAULT_LOCAL_MATCH => 0)); |
49
|
128
|
|
|
|
|
244
|
$m{comparator} = \"default"; |
50
|
128
|
|
|
|
|
259
|
$m{regex_engine} = env(PTP_DEFAULT_REGEX_ENGINE => 'perl'); |
51
|
128
|
|
|
|
|
235
|
$m{fatal_error} = env(PTP_DEFAULT_FATAL_ERROR => 0); |
52
|
128
|
|
|
|
|
231
|
$m{inverse_match} = env(PTP_DEFAULT_INVERSE_MATCH => 0); |
53
|
128
|
|
|
|
|
268
|
$m{input_field} = $default_input_field; |
54
|
128
|
|
|
|
|
216
|
$m{output_field} = $default_output_field; |
55
|
128
|
|
|
|
|
1111
|
return %m; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub get_default_options { |
59
|
128
|
|
|
128
|
0
|
176
|
my %o; |
60
|
128
|
|
|
|
|
270
|
$o{input_encoding} = 'UTF-8'; |
61
|
128
|
|
|
|
|
268
|
$o{output_encoding} = 'UTF-8'; |
62
|
128
|
|
|
|
|
246
|
$o{input_separator} = '\n'; # This will be interpreted in a regex |
63
|
128
|
|
|
|
|
220
|
$o{output_separator} = "\n"; |
64
|
128
|
|
|
|
|
237
|
$o{preserve_eol} = 0; |
65
|
128
|
|
|
|
|
238
|
$o{fix_final_separator} = 0; |
66
|
128
|
|
|
|
|
288
|
$o{recursive} = 0; |
67
|
128
|
|
|
|
|
226
|
$o{input_filter} = undef; |
68
|
128
|
|
|
|
|
234
|
$o{debug_mode} = 0; |
69
|
128
|
|
|
|
|
305
|
$o{merge} = 0; |
70
|
128
|
|
|
|
|
221
|
$o{in_place} = 0; |
71
|
128
|
|
|
|
|
207
|
$o{output} = undef; |
72
|
128
|
|
|
|
|
228
|
$o{append} = 0; |
73
|
128
|
|
|
|
|
176
|
$o{abort} = 0; |
74
|
128
|
|
|
|
|
199
|
$o{preserve_perl_env} = 0; |
75
|
128
|
|
|
|
|
219
|
$o{use_safe} = env(PTP_DEFAULT_SAFE => 0); |
76
|
128
|
|
|
|
|
1107
|
return %o; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# Resets all the global variables used for the command line parsing. This is |
80
|
|
|
|
|
|
|
# really useful only in tests. |
81
|
|
|
|
|
|
|
sub reset_global { |
82
|
128
|
|
|
128
|
0
|
241
|
@inputs = (); |
83
|
128
|
|
|
|
|
773
|
@pipeline = (); |
84
|
128
|
|
|
|
|
405
|
%modes = get_default_modes(); |
85
|
128
|
|
|
|
|
369
|
%options = get_default_options(); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub set_output { |
89
|
0
|
|
|
0
|
0
|
0
|
my (undef, $f) = @_; |
90
|
0
|
0
|
|
|
|
0
|
if (defined $options{output}) { |
91
|
0
|
|
|
|
|
0
|
die "Only a single occurence of --output or --append is allowed.\n"; |
92
|
|
|
|
|
|
|
} |
93
|
0
|
|
|
|
|
0
|
$options{output} = $f; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub options_flags {( |
97
|
0
|
|
|
0
|
|
0
|
'help|h' => sub { pod2usage(-exitval => 0, -verbose => 2) }, |
98
|
|
|
|
|
|
|
'debug|d+' => \$options{debug_mode}, |
99
|
|
|
|
|
|
|
'merge|m!' => \$options{merge}, |
100
|
|
|
|
|
|
|
'in-place|i!' => \$options{in_place}, |
101
|
|
|
|
|
|
|
'output|o=s' => \&set_output, |
102
|
0
|
|
|
0
|
|
0
|
'append|a=s' => sub { set_output(@_); $options{append} = 1; }, |
|
0
|
|
|
|
|
0
|
|
103
|
|
|
|
|
|
|
'abort!' => \$options{abort}, |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
'recursive|R|r!' => \$options{recursive}, |
106
|
|
|
|
|
|
|
'input-filter=s' => \$options{input_filter}, |
107
|
|
|
|
|
|
|
'input-encoding|in-encoding=s' => \$options{input_encoding}, |
108
|
|
|
|
|
|
|
'output-encoding|out-encoding=s' => \$options{output_encoding}, |
109
|
|
|
|
|
|
|
'input-separator|in-separator=s' => \$options{input_separator}, |
110
|
|
|
|
|
|
|
'output-separator|out-separator=s' => \$options{output_separator}, |
111
|
|
|
|
|
|
|
'fix-final-separator!' => \$options{fix_final_separator}, |
112
|
1
|
|
|
1
|
|
4370
|
'0' => sub { $options{input_separator} = '\000'; |
113
|
1
|
|
|
|
|
3
|
$options{output_separator} = '' }, |
114
|
1
|
|
|
1
|
|
4193
|
'00' => sub { $options{output_separator} = "\000" }, |
115
|
|
|
|
|
|
|
'preserve-input-separator|eol' => |
116
|
1
|
|
|
1
|
|
4914
|
sub { $options{preserve_eol} = 1; $options{output_separator} = '' }, |
|
1
|
|
|
|
|
7
|
|
117
|
|
|
|
|
|
|
'preserve-perl-env!' => \$options{preserve_perl_env}, |
118
|
36
|
|
|
36
|
|
179088
|
'safe:2' => sub { $options{use_safe} = $_[1] }, |
119
|
129
|
|
|
129
|
0
|
2252
|
)} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub modes_flags {( |
122
|
1
|
|
|
1
|
|
194
|
'case-sensitive|S' => sub { $modes{case_sensitive} = 1 }, |
123
|
3
|
|
|
3
|
|
8160
|
'case-insensitive|I' => sub { $modes{case_sensitive} = 0 }, |
124
|
11
|
|
|
11
|
|
45924
|
'quote-regexp|Q' => sub { $modes{quote_regex} = 1 }, |
125
|
0
|
|
|
0
|
|
0
|
'end-quote-regexp|E' => sub { $modes{quote_regex} = 0 }, |
126
|
1
|
|
|
1
|
|
191
|
'global-match|G' => sub { $modes{global_match} = 1 }, |
127
|
2
|
|
|
2
|
|
8139
|
'local-match|L' => sub { $modes{global_match} = 0 }, |
128
|
1
|
|
|
1
|
|
5258
|
'comparator|C=s' => sub { $modes{comparator} = $_[1] }, |
129
|
|
|
|
|
|
|
'regex-engine|re=s' => |
130
|
0
|
0
|
|
0
|
|
0
|
sub { die "Invalid value for --regex-engine: $_[1]\n" if $_[1] !~ /^\w+$/; |
131
|
0
|
|
|
|
|
0
|
$modes{regex_engine} = $_[1] }, |
132
|
0
|
|
|
0
|
|
0
|
'fatal-error|X' => sub { $modes{fatal_error} = 1 }, |
133
|
0
|
|
|
0
|
|
0
|
'ignore-error' => sub { $modes{fatal_error} = 0 }, # Find a short option? |
134
|
1
|
|
|
1
|
|
5019
|
'inverse-match|V' => sub { $modes{inverse_match} = 1 }, |
135
|
0
|
|
|
0
|
|
0
|
'normal-match|N' => sub { $modes{inverse_match} = 0 }, |
136
|
1
|
|
|
1
|
|
4842
|
'input-field-separator|F=s' => sub { $modes{input_field} = $_[1] }, |
137
|
|
|
|
|
|
|
'output-field-separator|P=s' => \$modes{output_field}, |
138
|
0
|
|
|
0
|
|
0
|
'default' => sub { $modes{input_field} = $default_input_field; |
139
|
0
|
|
|
|
|
0
|
$modes{output_field} = $default_output_field; }, |
140
|
1
|
|
|
1
|
|
4939
|
'bytes' => sub { $modes{input_field} = ''; $modes{output_field} = ''; }, |
|
1
|
|
|
|
|
4
|
|
141
|
1
|
|
|
1
|
|
5102
|
'csv' => sub { $modes{input_field} = '\s*,\s*'; $modes{output_field} = ','; }, |
|
1
|
|
|
|
|
5
|
|
142
|
1
|
|
|
1
|
|
4929
|
'tsv' => sub { $modes{input_field} = '\t'; $modes{output_field} = "\t"; }, |
|
1
|
|
|
|
|
4
|
|
143
|
1
|
|
|
1
|
|
4898
|
'none' => sub { $modes{input_field} = '(?!)' }, |
144
|
129
|
|
|
129
|
0
|
3141
|
)} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub input_flags {( |
147
|
22
|
|
|
22
|
|
33611
|
'<>' => sub { push @inputs, $_[0] }, # Any options not matched otherwise. |
148
|
9
|
|
|
9
|
|
810
|
'' => sub { push @inputs, \$App::PTP::Files::stdin_marker }, # a single '-' |
149
|
129
|
|
|
129
|
0
|
638
|
)} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub is_int { |
152
|
10
|
|
|
10
|
0
|
20
|
my ($str) = @_; |
153
|
10
|
|
33
|
|
|
71
|
return looks_like_number($str) && int($str) == $str; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub validate_cut_spec { |
157
|
5
|
|
|
5
|
0
|
16
|
my ($spec) = @_; |
158
|
5
|
|
|
|
|
32
|
my @fields = split /\s*,\s*/, $spec; |
159
|
5
|
|
|
|
|
16
|
for my $f (@fields) { |
160
|
10
|
50
|
|
|
|
24
|
die "Fields passed to --cut must all be integers: $f\n" unless is_int($f); |
161
|
10
|
50
|
|
|
|
44
|
$f-- if $f > 0; |
162
|
|
|
|
|
|
|
} |
163
|
5
|
|
|
|
|
25
|
return \@fields; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# The array associated with each action contains the name of the action, the |
167
|
|
|
|
|
|
|
# method to call for that action, a copy of the current %modes, and all the |
168
|
|
|
|
|
|
|
# other arguments that should be passed to the method. |
169
|
|
|
|
|
|
|
sub action_flags {( |
170
|
|
|
|
|
|
|
'grep|g=s' => |
171
|
27
|
|
|
27
|
|
34441
|
sub { push @pipeline, ['grep', \&do_grep, {%modes}, $_[1]] }, |
172
|
|
|
|
|
|
|
'substitute|s=s{2}' => |
173
|
38
|
|
|
38
|
|
36130
|
sub { push @pipeline, ['substitute', \&do_substitute, {%modes}, |
174
|
|
|
|
|
|
|
$_[1]] }, |
175
|
|
|
|
|
|
|
# All the do_perl below could have the same sub using "$_[0]" instead of the |
176
|
|
|
|
|
|
|
# manually specified name. |
177
|
|
|
|
|
|
|
'perl|p=s' => |
178
|
18
|
|
|
18
|
|
29017
|
sub { push @pipeline, ['perl', \&do_perl, {%modes}, 'perl', $_[1]] }, |
179
|
|
|
|
|
|
|
'n=s' => |
180
|
19
|
|
|
19
|
|
23906
|
sub { push @pipeline, ['n', \&do_perl, {%modes}, 'n', $_[1]] }, |
181
|
|
|
|
|
|
|
'filter|f=s' => |
182
|
6
|
|
|
6
|
|
10751
|
sub { push @pipeline, ['filter', \&do_perl, {%modes}, 'filter', $_[1]] }, |
183
|
|
|
|
|
|
|
'mark-line|ml=s' => |
184
|
7
|
|
|
7
|
|
6353
|
sub { push @pipeline, ['mark-line', \&do_perl, {%modes}, 'mark-line', |
185
|
|
|
|
|
|
|
$_[1]] }, |
186
|
|
|
|
|
|
|
'execute|e=s' => |
187
|
20
|
|
|
20
|
|
27460
|
sub { push @pipeline, ['execute', \&do_execute, {%modes}, $_[1]] }, |
188
|
|
|
|
|
|
|
'load|l=s' => |
189
|
3
|
|
|
3
|
|
780
|
sub { push @pipeline, ['load', \&do_load, {%modes}, $_[1]] }, |
190
|
5
|
|
|
5
|
|
15354
|
'sort' => sub { push @pipeline, ['sort', \&do_sort, {%modes}] }, |
191
|
|
|
|
|
|
|
'numeric-sort|ns' => |
192
|
1
|
|
|
1
|
|
4833
|
sub { my $opt = {%modes, comparator => \"numeric" }; |
193
|
1
|
|
|
|
|
4
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
194
|
|
|
|
|
|
|
'locale-sort|ls' => |
195
|
1
|
|
|
1
|
|
4950
|
sub { my $opt = {%modes, comparator => \"locale" }; |
196
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
197
|
|
|
|
|
|
|
'custom-sort|cs=s' => |
198
|
1
|
|
|
1
|
|
5011
|
sub { my $opt = {%modes, comparator => $_[1] }; |
199
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'custom-sort', \&do_sort, $opt] }, |
200
|
|
|
|
|
|
|
'unique|u' => |
201
|
1
|
|
|
1
|
|
243
|
sub { push @pipeline, ['unique', \&do_list_op, {%modes}, |
202
|
|
|
|
|
|
|
\&App::PTP::Util::uniqstr, 0] }, |
203
|
4
|
|
|
4
|
|
20080
|
'head:i' => sub { push @pipeline, ['head', \&do_head, {%modes}, $_[1]] }, |
204
|
4
|
|
|
4
|
|
20008
|
'tail:i' => sub { push @pipeline, ['tail', \&do_tail, {%modes}, $_[1]] }, |
205
|
|
|
|
|
|
|
'reverse|tac' => |
206
|
|
|
|
|
|
|
sub { push @pipeline, |
207
|
0
|
|
|
0
|
|
0
|
['reverse', \&do_list_op, {%modes}, sub {reverse @_ }, 1] }, |
|
0
|
|
|
|
|
0
|
|
208
|
|
|
|
|
|
|
'shuffle' => |
209
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['shuffle', \&do_list_op, {%modes}, |
210
|
|
|
|
|
|
|
\&List::Util::shuffle, 0] }, |
211
|
1
|
|
|
1
|
|
327
|
'eat' => sub { push @pipeline, ['eat', \&do_eat, {%modes}] }, |
212
|
|
|
|
|
|
|
'delete-marked' => |
213
|
3
|
|
|
3
|
|
798
|
sub { push @pipeline, ['delete-marked', \&do_delete_marked, {%modes}, |
214
|
|
|
|
|
|
|
0] }, |
215
|
|
|
|
|
|
|
'delete-before' => |
216
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-before', \&do_delete_marked, {%modes}, |
217
|
|
|
|
|
|
|
-1] }, |
218
|
|
|
|
|
|
|
'delete-after' => |
219
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-after', \&do_delete_marked, {%modes}, |
220
|
|
|
|
|
|
|
1] }, |
221
|
|
|
|
|
|
|
'delete-at-offset=i' => |
222
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-at-offset', \&do_delete_marked, {%modes}, |
223
|
|
|
|
|
|
|
$_[1]] }, |
224
|
|
|
|
|
|
|
'insert-before=s' => |
225
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-before', \&do_insert_marked, {%modes}, |
226
|
|
|
|
|
|
|
-1, $_[1]] }, |
227
|
|
|
|
|
|
|
'insert-after=s' => |
228
|
3
|
|
|
3
|
|
743
|
sub { push @pipeline, ['insert-after', \&do_insert_marked, {%modes}, |
229
|
|
|
|
|
|
|
0, $_[1]] }, |
230
|
|
|
|
|
|
|
'insert-at-offset=s{2}' => |
231
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-at-offset', \&do_insert_marked, {%modes}, |
232
|
|
|
|
|
|
|
$_[1]] }, |
233
|
|
|
|
|
|
|
'clear-markers' => |
234
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['clear-markers', \&do_set_markers, {%modes}, 0] }, |
235
|
|
|
|
|
|
|
'set-all-markers' => |
236
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['set-all-markers', \&do_set_markers, {%modes}, |
237
|
|
|
|
|
|
|
1] }, |
238
|
5
|
|
|
5
|
|
6292
|
'cut=s' => sub { push @pipeline, ['cut', \&do_cut, {%modes}, |
239
|
|
|
|
|
|
|
validate_cut_spec($_[1])] }, |
240
|
0
|
|
|
0
|
|
0
|
'paste=s' => sub { push @pipeline, ['paste', \&do_paste, {%modes}, $_[1]] }, |
241
|
2
|
|
|
2
|
|
5437
|
'pivot' => sub { push @pipeline, ['pivot', \&do_pivot, {%modes}, 'pivot'] }, |
242
|
1
|
|
|
1
|
|
4869
|
'anti-pivot' => sub { push @pipeline, ['anti-pivot', \&do_pivot, {%modes}, |
243
|
|
|
|
|
|
|
'anti-pivot'] }, |
244
|
2
|
|
|
2
|
|
5199
|
'transpose' => sub { push @pipeline, ['transpose', \&do_pivot, {%modes}, |
245
|
|
|
|
|
|
|
'transpose'] }, |
246
|
|
|
|
|
|
|
'number-lines|nl' => |
247
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['number-lines', \&do_number_lines, {%modes}] }, |
248
|
|
|
|
|
|
|
'file-name|fn' => |
249
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['file-name', \&do_file_name, {%modes}, 1] }, |
250
|
|
|
|
|
|
|
'prefix-file-name|pfn' => |
251
|
1
|
|
|
1
|
|
232
|
sub { push @pipeline, ['prefix-file-name', \&do_file_name, {%modes}, 0] }, |
252
|
|
|
|
|
|
|
'line-count|lc' => |
253
|
1
|
|
|
1
|
|
235
|
sub { push @pipeline, ['line-count', \&do_line_count, {%modes}] }, |
254
|
6
|
|
|
6
|
|
1620
|
'tee=s' => sub { push @pipeline, ['tee', \&do_tee, {%modes}, $_[1]] }, |
255
|
6
|
|
|
6
|
|
23042
|
'shell=s' => sub { push @pipeline, ['shell', \&do_shell, {%modes}, 'shell', |
256
|
|
|
|
|
|
|
$_[1]] } |
257
|
129
|
|
|
129
|
0
|
6648
|
)} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub all_args { |
260
|
129
|
|
|
129
|
0
|
99445
|
return (options_flags(), modes_flags(), input_flags(), action_flags()); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# parse_command_line(\@args) |
264
|
|
|
|
|
|
|
sub parse_command_line { |
265
|
128
|
|
|
128
|
0
|
269
|
my ($args) = @_; |
266
|
128
|
|
|
|
|
437
|
reset_global(); |
267
|
128
|
50
|
|
|
|
403
|
GetOptionsFromArray($args, all_args()) |
268
|
|
|
|
|
|
|
or pod2usage(-exitval => 2, -verbose => 0); |
269
|
|
|
|
|
|
|
|
270
|
128
|
50
|
|
|
|
49928
|
if ($options{debug_mode} > 1) { |
271
|
|
|
|
|
|
|
# When -d is specified multiple times, we add the marker on the final |
272
|
|
|
|
|
|
|
# output. |
273
|
0
|
|
|
|
|
0
|
push @pipeline, ['show-marker', \&do_perl, {%modes}, 'perl', |
274
|
|
|
|
|
|
|
'pf "%s %s", ($m ? "*" : " "), $_'] |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Because of the way the options are processed, each --replace options |
278
|
|
|
|
|
|
|
# (expecting two arguments) is pushed twice in the pipeline sub (once for each |
279
|
|
|
|
|
|
|
# argument). We're fixing this here. |
280
|
128
|
|
|
|
|
524
|
for my $i (0 .. $#pipeline) { |
281
|
186
|
100
|
|
|
|
660
|
if ($pipeline[$i][0] eq 'substitute') { |
|
|
50
|
|
|
|
|
|
282
|
19
|
|
|
|
|
27
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
19
|
|
|
|
|
59
|
|
283
|
19
|
|
|
|
|
78
|
$pipeline[$i+1][0] = 'garbage'; |
284
|
|
|
|
|
|
|
} elsif ($pipeline[$i][0] eq 'insert-at-offset') { |
285
|
0
|
|
|
|
|
0
|
my $o = $pipeline[$i]->[3]; |
286
|
0
|
0
|
|
|
|
0
|
if (!ist_int($o)) { |
287
|
0
|
|
|
|
|
0
|
die "The first argument to --insert-at-offset must be an integer: $o\n"; |
288
|
|
|
|
|
|
|
} |
289
|
0
|
|
|
|
|
0
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
0
|
|
|
|
|
0
|
|
290
|
0
|
|
|
|
|
0
|
$pipeline[$i+1][0] = 'garbage'; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
} |
293
|
128
|
|
|
|
|
325
|
@pipeline = grep { $_->[0] ne 'garbage' } @pipeline; |
|
186
|
|
|
|
|
649
|
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Add any options that were passed after a '--' to the list of inputs. |
296
|
128
|
|
|
|
|
261
|
push @inputs, @$args; |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Add the standard input marker to the inputs if no other input were |
299
|
|
|
|
|
|
|
# specified. |
300
|
128
|
100
|
|
|
|
368
|
push @inputs, \$App::PTP::Files::stdin_marker if not @inputs; |
301
|
|
|
|
|
|
|
|
302
|
128
|
0
|
33
|
|
|
345
|
if ($options{in_place} && $options{merge}) { |
303
|
0
|
|
|
|
|
0
|
die "The --in-place and --merge options are incompatible.\n"; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
128
|
0
|
33
|
|
|
276
|
if ($options{in_place} && $options{output}) { |
307
|
0
|
0
|
|
|
|
0
|
if ($options{append}) { |
308
|
0
|
|
|
|
|
0
|
die "The --in-place and --append options are incompatible.\n"; |
309
|
|
|
|
|
|
|
} else { |
310
|
0
|
|
|
|
|
0
|
die "The --in-place and --output options are incompatible.\n"; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
128
|
50
|
66
|
|
|
371
|
if (defined $options{input_filter} && !$options{recursive}) { |
315
|
0
|
|
|
|
|
0
|
print "WARNING: The --input-filter option is useless unless --recursive is specified too.\n"; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
128
|
|
|
|
|
475
|
return (\@inputs, \@pipeline, \%options); |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
1; |