line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::PTP::Args; |
2
|
|
|
|
|
|
|
|
3
|
19
|
|
|
19
|
|
67750
|
use 5.022; |
|
19
|
|
|
|
|
70
|
|
4
|
19
|
|
|
19
|
|
80
|
use strict; |
|
19
|
|
|
|
|
29
|
|
|
19
|
|
|
|
|
381
|
|
5
|
19
|
|
|
19
|
|
82
|
use warnings; |
|
19
|
|
|
|
|
29
|
|
|
19
|
|
|
|
|
585
|
|
6
|
|
|
|
|
|
|
|
7
|
19
|
|
|
19
|
|
7874
|
use App::PTP::Commands ':CMD'; |
|
19
|
|
|
|
|
52
|
|
|
19
|
|
|
|
|
4140
|
|
8
|
19
|
|
|
19
|
|
134
|
use App::PTP::Util; |
|
19
|
|
|
|
|
37
|
|
|
19
|
|
|
|
|
474
|
|
9
|
19
|
|
|
|
|
110
|
use Getopt::Long qw(GetOptionsFromArray :config auto_abbrev no_ignore_case |
10
|
19
|
|
|
19
|
|
11583
|
permute auto_version); |
|
19
|
|
|
|
|
198093
|
|
11
|
19
|
|
|
19
|
|
4683
|
use List::Util; |
|
19
|
|
|
|
|
41
|
|
|
19
|
|
|
|
|
922
|
|
12
|
19
|
|
|
19
|
|
8485
|
use Pod::Usage; |
|
19
|
|
|
|
|
801757
|
|
|
19
|
|
|
|
|
2806
|
|
13
|
19
|
|
|
19
|
|
191
|
use Scalar::Util 'looks_like_number'; |
|
19
|
|
|
|
|
43
|
|
|
19
|
|
|
|
|
50999
|
|
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
|
938
|
|
|
938
|
0
|
1756
|
my ($var, $default) = @_; |
40
|
938
|
50
|
|
|
|
2698
|
return $default if $ENV{HARNESS_ACTIVE}; |
41
|
0
|
|
0
|
|
|
0
|
return $ENV{$var} // $default; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_default_modes { |
45
|
134
|
|
|
134
|
0
|
210
|
my %m; |
46
|
134
|
|
|
|
|
367
|
$m{case_sensitive} = not(env(PTP_DEFAULT_CASE_INSENSITIVE => 0)); |
47
|
134
|
|
|
|
|
309
|
$m{quote_regex} = env(PTP_DEFAULT_QUOTE_REGEX => 0); |
48
|
134
|
|
|
|
|
271
|
$m{global_match} = not(env(PTP_DEFAULT_LOCAL_MATCH => 0)); |
49
|
134
|
|
|
|
|
266
|
$m{comparator} = \"default"; |
50
|
134
|
|
|
|
|
279
|
$m{regex_engine} = env(PTP_DEFAULT_REGEX_ENGINE => 'perl'); |
51
|
134
|
|
|
|
|
256
|
$m{fatal_error} = env(PTP_DEFAULT_FATAL_ERROR => 0); |
52
|
134
|
|
|
|
|
240
|
$m{inverse_match} = env(PTP_DEFAULT_INVERSE_MATCH => 0); |
53
|
134
|
|
|
|
|
278
|
$m{input_field} = $default_input_field; |
54
|
134
|
|
|
|
|
253
|
$m{output_field} = $default_output_field; |
55
|
134
|
|
|
|
|
1126
|
return %m; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub get_default_options { |
59
|
134
|
|
|
134
|
0
|
198
|
my %o; |
60
|
134
|
|
|
|
|
298
|
$o{input_encoding} = 'UTF-8'; |
61
|
134
|
|
|
|
|
278
|
$o{output_encoding} = 'UTF-8'; |
62
|
134
|
|
|
|
|
268
|
$o{input_separator} = '\n'; # This will be interpreted in a regex |
63
|
134
|
|
|
|
|
252
|
$o{output_separator} = "\n"; |
64
|
134
|
|
|
|
|
244
|
$o{preserve_eol} = 0; |
65
|
134
|
|
|
|
|
216
|
$o{fix_final_separator} = 0; |
66
|
134
|
|
|
|
|
231
|
$o{recursive} = 0; |
67
|
134
|
|
|
|
|
238
|
$o{input_filter} = undef; |
68
|
134
|
|
|
|
|
217
|
$o{debug_mode} = 0; |
69
|
134
|
|
|
|
|
239
|
$o{merge} = 0; |
70
|
134
|
|
|
|
|
219
|
$o{in_place} = 0; |
71
|
134
|
|
|
|
|
262
|
$o{output} = undef; |
72
|
134
|
|
|
|
|
253
|
$o{append} = 0; |
73
|
134
|
|
|
|
|
193
|
$o{abort} = 0; |
74
|
134
|
|
|
|
|
269
|
$o{preserve_perl_env} = 0; |
75
|
134
|
|
|
|
|
243
|
$o{use_safe} = env(PTP_DEFAULT_SAFE => 0); |
76
|
134
|
|
|
|
|
1124
|
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
|
134
|
|
|
134
|
0
|
290
|
@inputs = (); |
83
|
134
|
|
|
|
|
771
|
@pipeline = (); |
84
|
134
|
|
|
|
|
485
|
%modes = get_default_modes(); |
85
|
134
|
|
|
|
|
477
|
%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
|
|
4268
|
'0' => sub { $options{input_separator} = '\000'; |
113
|
1
|
|
|
|
|
3
|
$options{output_separator} = '' }, |
114
|
1
|
|
|
1
|
|
4046
|
'00' => sub { $options{output_separator} = "\000" }, |
115
|
|
|
|
|
|
|
'preserve-input-separator|eol' => |
116
|
1
|
|
|
1
|
|
4949
|
sub { $options{preserve_eol} = 1; $options{output_separator} = '' }, |
|
1
|
|
|
|
|
7
|
|
117
|
|
|
|
|
|
|
'preserve-perl-env!' => \$options{preserve_perl_env}, |
118
|
36
|
|
|
36
|
|
189744
|
'safe:2' => sub { $options{use_safe} = $_[1] }, |
119
|
135
|
|
|
135
|
0
|
2265
|
)} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub modes_flags {( |
122
|
1
|
|
|
1
|
|
196
|
'case-sensitive|S' => sub { $modes{case_sensitive} = 1 }, |
123
|
3
|
|
|
3
|
|
8762
|
'case-insensitive|I' => sub { $modes{case_sensitive} = 0 }, |
124
|
11
|
|
|
11
|
|
43385
|
'quote-regexp|Q' => sub { $modes{quote_regex} = 1 }, |
125
|
0
|
|
|
0
|
|
0
|
'end-quote-regexp|E' => sub { $modes{quote_regex} = 0 }, |
126
|
1
|
|
|
1
|
|
209
|
'global-match|G' => sub { $modes{global_match} = 1 }, |
127
|
2
|
|
|
2
|
|
8206
|
'local-match|L' => sub { $modes{global_match} = 0 }, |
128
|
1
|
|
|
1
|
|
4311
|
'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
|
|
4909
|
'inverse-match|V' => sub { $modes{inverse_match} = 1 }, |
135
|
0
|
|
|
0
|
|
0
|
'normal-match|N' => sub { $modes{inverse_match} = 0 }, |
136
|
1
|
|
|
1
|
|
4908
|
'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
|
|
4113
|
'bytes' => sub { $modes{input_field} = ''; $modes{output_field} = ''; }, |
|
1
|
|
|
|
|
3
|
|
141
|
1
|
|
|
1
|
|
4213
|
'csv' => sub { $modes{input_field} = '\s*,\s*'; $modes{output_field} = ','; }, |
|
1
|
|
|
|
|
3
|
|
142
|
1
|
|
|
1
|
|
4078
|
'tsv' => sub { $modes{input_field} = '\t'; $modes{output_field} = "\t"; }, |
|
1
|
|
|
|
|
3
|
|
143
|
1
|
|
|
1
|
|
4444
|
'none' => sub { $modes{input_field} = '(?!)' }, |
144
|
135
|
|
|
135
|
0
|
3346
|
)} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub input_flags {( |
147
|
25
|
|
|
25
|
|
33785
|
'<>' => sub { push @inputs, $_[0] }, # Any options not matched otherwise. |
148
|
9
|
|
|
9
|
|
821
|
'' => sub { push @inputs, \$App::PTP::Files::stdin_marker }, # a single '-' |
149
|
135
|
|
|
135
|
0
|
715
|
)} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub is_int { |
152
|
10
|
|
|
10
|
0
|
17
|
my ($str) = @_; |
153
|
10
|
|
33
|
|
|
60
|
return looks_like_number($str) && int($str) == $str; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub validate_cut_spec { |
157
|
5
|
|
|
5
|
0
|
22
|
my ($spec) = @_; |
158
|
5
|
|
|
|
|
32
|
my @fields = split /\s*,\s*/, $spec; |
159
|
5
|
|
|
|
|
14
|
for my $f (@fields) { |
160
|
10
|
50
|
|
|
|
28
|
die "Fields passed to --cut must all be integers: $f\n" unless is_int($f); |
161
|
10
|
50
|
|
|
|
28
|
$f-- if $f > 0; |
162
|
|
|
|
|
|
|
} |
163
|
5
|
|
|
|
|
19
|
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
|
|
36016
|
sub { push @pipeline, ['grep', \&do_grep, {%modes}, $_[1]] }, |
172
|
|
|
|
|
|
|
'substitute|s=s{2}' => |
173
|
38
|
|
|
38
|
|
36722
|
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
|
|
28699
|
sub { push @pipeline, ['perl', \&do_perl, {%modes}, 'perl', $_[1]] }, |
179
|
|
|
|
|
|
|
'n=s' => |
180
|
20
|
|
|
20
|
|
25668
|
sub { push @pipeline, ['n', \&do_perl, {%modes}, 'n', $_[1]] }, |
181
|
|
|
|
|
|
|
'filter|f=s' => |
182
|
6
|
|
|
6
|
|
10883
|
sub { push @pipeline, ['filter', \&do_perl, {%modes}, 'filter', $_[1]] }, |
183
|
|
|
|
|
|
|
'mark-line|ml=s' => |
184
|
7
|
|
|
7
|
|
6527
|
sub { push @pipeline, ['mark-line', \&do_perl, {%modes}, 'mark-line', |
185
|
|
|
|
|
|
|
$_[1]] }, |
186
|
|
|
|
|
|
|
'execute|e=s' => |
187
|
20
|
|
|
20
|
|
25968
|
sub { push @pipeline, ['execute', \&do_execute, {%modes}, 'execute', |
188
|
|
|
|
|
|
|
$_[1]] }, |
189
|
|
|
|
|
|
|
'M=s' => |
190
|
1
|
|
|
1
|
|
5089
|
sub { push @pipeline, ['M', \&do_execute, {%modes}, 'M', $_[1]] }, |
191
|
|
|
|
|
|
|
'load|l=s' => |
192
|
3
|
|
|
3
|
|
802
|
sub { push @pipeline, ['load', \&do_load, {%modes}, $_[1]] }, |
193
|
6
|
|
|
6
|
|
13765
|
'sort' => sub { push @pipeline, ['sort', \&do_sort, {%modes}] }, |
194
|
|
|
|
|
|
|
'numeric-sort|ns' => |
195
|
1
|
|
|
1
|
|
4265
|
sub { my $opt = {%modes, comparator => \"numeric" }; |
196
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
197
|
|
|
|
|
|
|
'locale-sort|ls' => |
198
|
1
|
|
|
1
|
|
4381
|
sub { my $opt = {%modes, comparator => \"locale" }; |
199
|
1
|
|
|
|
|
6
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
200
|
|
|
|
|
|
|
'custom-sort|cs=s' => |
201
|
1
|
|
|
1
|
|
4193
|
sub { my $opt = {%modes, comparator => $_[1] }; |
202
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'custom-sort', \&do_sort, $opt] }, |
203
|
|
|
|
|
|
|
'unique|u' => |
204
|
2
|
|
|
2
|
|
418
|
sub { push @pipeline, ['unique', \&do_list_op, {%modes}, |
205
|
|
|
|
|
|
|
\&App::PTP::Util::uniqstr, 0] }, |
206
|
4
|
|
|
4
|
|
21022
|
'head:i' => sub { push @pipeline, ['head', \&do_head, {%modes}, $_[1]] }, |
207
|
4
|
|
|
4
|
|
16177
|
'tail:i' => sub { push @pipeline, ['tail', \&do_tail, {%modes}, $_[1]] }, |
208
|
|
|
|
|
|
|
'reverse|tac' => |
209
|
|
|
|
|
|
|
sub { push @pipeline, |
210
|
0
|
|
|
0
|
|
0
|
['reverse', \&do_list_op, {%modes}, sub {reverse @_ }, 1] }, |
|
0
|
|
|
|
|
0
|
|
211
|
|
|
|
|
|
|
'shuffle' => |
212
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['shuffle', \&do_list_op, {%modes}, |
213
|
|
|
|
|
|
|
\&List::Util::shuffle, 0] }, |
214
|
1
|
|
|
1
|
|
267
|
'eat' => sub { push @pipeline, ['eat', \&do_eat, {%modes}] }, |
215
|
|
|
|
|
|
|
'delete-marked' => |
216
|
3
|
|
|
3
|
|
750
|
sub { push @pipeline, ['delete-marked', \&do_delete_marked, {%modes}, |
217
|
|
|
|
|
|
|
0] }, |
218
|
|
|
|
|
|
|
'delete-before' => |
219
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-before', \&do_delete_marked, {%modes}, |
220
|
|
|
|
|
|
|
-1] }, |
221
|
|
|
|
|
|
|
'delete-after' => |
222
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-after', \&do_delete_marked, {%modes}, |
223
|
|
|
|
|
|
|
1] }, |
224
|
|
|
|
|
|
|
'delete-at-offset=i' => |
225
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-at-offset', \&do_delete_marked, {%modes}, |
226
|
|
|
|
|
|
|
$_[1]] }, |
227
|
|
|
|
|
|
|
'insert-before=s' => |
228
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-before', \&do_insert_marked, {%modes}, |
229
|
|
|
|
|
|
|
-1, $_[1]] }, |
230
|
|
|
|
|
|
|
'insert-after=s' => |
231
|
3
|
|
|
3
|
|
816
|
sub { push @pipeline, ['insert-after', \&do_insert_marked, {%modes}, |
232
|
|
|
|
|
|
|
0, $_[1]] }, |
233
|
|
|
|
|
|
|
'insert-at-offset=s{2}' => |
234
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-at-offset', \&do_insert_marked, {%modes}, |
235
|
|
|
|
|
|
|
$_[1]] }, |
236
|
|
|
|
|
|
|
'clear-markers' => |
237
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['clear-markers', \&do_set_markers, {%modes}, 0] }, |
238
|
|
|
|
|
|
|
'set-all-markers' => |
239
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['set-all-markers', \&do_set_markers, {%modes}, |
240
|
|
|
|
|
|
|
1] }, |
241
|
5
|
|
|
5
|
|
5205
|
'cut=s' => sub { push @pipeline, ['cut', \&do_cut, {%modes}, |
242
|
|
|
|
|
|
|
validate_cut_spec($_[1])] }, |
243
|
0
|
|
|
0
|
|
0
|
'paste=s' => sub { push @pipeline, ['paste', \&do_paste, {%modes}, $_[1]] }, |
244
|
3
|
|
|
3
|
|
4790
|
'pivot' => sub { push @pipeline, ['pivot', \&do_pivot, {%modes}, 'pivot'] }, |
245
|
1
|
|
|
1
|
|
4378
|
'anti-pivot' => sub { push @pipeline, ['anti-pivot', \&do_pivot, {%modes}, |
246
|
|
|
|
|
|
|
'anti-pivot'] }, |
247
|
2
|
|
|
2
|
|
4286
|
'transpose' => sub { push @pipeline, ['transpose', \&do_pivot, {%modes}, |
248
|
|
|
|
|
|
|
'transpose'] }, |
249
|
|
|
|
|
|
|
'number-lines|nl' => |
250
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['number-lines', \&do_number_lines, {%modes}] }, |
251
|
|
|
|
|
|
|
'file-name|fn' => |
252
|
2
|
|
|
2
|
|
9937
|
sub { push @pipeline, ['file-name', \&do_file_name, {%modes}, 1] }, |
253
|
|
|
|
|
|
|
'prefix-file-name|pfn' => |
254
|
2
|
|
|
2
|
|
5465
|
sub { push @pipeline, ['prefix-file-name', \&do_file_name, {%modes}, 0] }, |
255
|
|
|
|
|
|
|
'line-count|lc' => |
256
|
1
|
|
|
1
|
|
236
|
sub { push @pipeline, ['line-count', \&do_line_count, {%modes}] }, |
257
|
6
|
|
|
6
|
|
1289
|
'tee=s' => sub { push @pipeline, ['tee', \&do_tee, {%modes}, $_[1]] }, |
258
|
6
|
|
|
6
|
|
22820
|
'shell=s' => sub { push @pipeline, ['shell', \&do_shell, {%modes}, 'shell', |
259
|
|
|
|
|
|
|
$_[1]] } |
260
|
135
|
|
|
135
|
0
|
7196
|
)} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub all_args { |
263
|
135
|
|
|
135
|
0
|
79755
|
return (options_flags(), modes_flags(), input_flags(), action_flags()); |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# parse_command_line(\@args) |
267
|
|
|
|
|
|
|
sub parse_command_line { |
268
|
134
|
|
|
134
|
0
|
275
|
my ($args) = @_; |
269
|
134
|
|
|
|
|
408
|
reset_global(); |
270
|
134
|
50
|
|
|
|
431
|
GetOptionsFromArray($args, all_args()) |
271
|
|
|
|
|
|
|
or pod2usage(-exitval => 2, -verbose => 0); |
272
|
|
|
|
|
|
|
|
273
|
134
|
50
|
|
|
|
48817
|
if ($options{debug_mode} > 1) { |
274
|
|
|
|
|
|
|
# When -d is specified multiple times, we add the marker on the final |
275
|
|
|
|
|
|
|
# output. |
276
|
0
|
|
|
|
|
0
|
push @pipeline, ['show-marker', \&do_perl, {%modes}, 'perl', |
277
|
|
|
|
|
|
|
'pf "%s %s", ($m ? "*" : " "), $_'] |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Because of the way the options are processed, each --replace options |
281
|
|
|
|
|
|
|
# (expecting two arguments) is pushed twice in the pipeline sub (once for each |
282
|
|
|
|
|
|
|
# argument). We're fixing this here. |
283
|
134
|
|
|
|
|
543
|
for my $i (0 .. $#pipeline) { |
284
|
194
|
100
|
|
|
|
741
|
if ($pipeline[$i][0] eq 'substitute') { |
|
|
50
|
|
|
|
|
|
285
|
19
|
|
|
|
|
28
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
19
|
|
|
|
|
60
|
|
286
|
19
|
|
|
|
|
48
|
$pipeline[$i+1][0] = 'garbage'; |
287
|
|
|
|
|
|
|
} elsif ($pipeline[$i][0] eq 'insert-at-offset') { |
288
|
0
|
|
|
|
|
0
|
my $o = $pipeline[$i]->[3]; |
289
|
0
|
0
|
|
|
|
0
|
if (!ist_int($o)) { |
290
|
0
|
|
|
|
|
0
|
die "The first argument to --insert-at-offset must be an integer: $o\n"; |
291
|
|
|
|
|
|
|
} |
292
|
0
|
|
|
|
|
0
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
0
|
|
|
|
|
0
|
|
293
|
0
|
|
|
|
|
0
|
$pipeline[$i+1][0] = 'garbage'; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
} |
296
|
134
|
|
|
|
|
309
|
@pipeline = grep { $_->[0] ne 'garbage' } @pipeline; |
|
194
|
|
|
|
|
670
|
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Add any options that were passed after a '--' to the list of inputs. |
299
|
134
|
|
|
|
|
275
|
push @inputs, @$args; |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Add the standard input marker to the inputs if no other input were |
302
|
|
|
|
|
|
|
# specified. |
303
|
134
|
100
|
|
|
|
389
|
push @inputs, \$App::PTP::Files::stdin_marker if not @inputs; |
304
|
|
|
|
|
|
|
|
305
|
134
|
0
|
33
|
|
|
411
|
if ($options{in_place} && $options{merge}) { |
306
|
0
|
|
|
|
|
0
|
die "The --in-place and --merge options are incompatible.\n"; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
134
|
0
|
33
|
|
|
320
|
if ($options{in_place} && $options{output}) { |
310
|
0
|
0
|
|
|
|
0
|
if ($options{append}) { |
311
|
0
|
|
|
|
|
0
|
die "The --in-place and --append options are incompatible.\n"; |
312
|
|
|
|
|
|
|
} else { |
313
|
0
|
|
|
|
|
0
|
die "The --in-place and --output options are incompatible.\n"; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
134
|
50
|
66
|
|
|
394
|
if (defined $options{input_filter} && !$options{recursive}) { |
318
|
0
|
|
|
|
|
0
|
print "WARNING: The --input-filter option is useless unless --recursive is specified too.\n"; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
134
|
|
|
|
|
522
|
return (\@inputs, \@pipeline, \%options); |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
1; |