line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::PTP::Args; |
2
|
|
|
|
|
|
|
|
3
|
20
|
|
|
20
|
|
68136
|
use 5.022; |
|
20
|
|
|
|
|
84
|
|
4
|
20
|
|
|
20
|
|
97
|
use strict; |
|
20
|
|
|
|
|
32
|
|
|
20
|
|
|
|
|
391
|
|
5
|
20
|
|
|
20
|
|
99
|
use warnings; |
|
20
|
|
|
|
|
41
|
|
|
20
|
|
|
|
|
687
|
|
6
|
|
|
|
|
|
|
|
7
|
20
|
|
|
20
|
|
9576
|
use App::PTP::Commands ':CMD'; |
|
20
|
|
|
|
|
71
|
|
|
20
|
|
|
|
|
4393
|
|
8
|
20
|
|
|
20
|
|
149
|
use App::PTP::Util; |
|
20
|
|
|
|
|
54
|
|
|
20
|
|
|
|
|
534
|
|
9
|
20
|
|
|
|
|
124
|
use Getopt::Long qw(GetOptionsFromArray :config auto_abbrev no_ignore_case |
10
|
20
|
|
|
20
|
|
14079
|
permute auto_version); |
|
20
|
|
|
|
|
239325
|
|
11
|
20
|
|
|
20
|
|
4605
|
use List::Util; |
|
20
|
|
|
|
|
46
|
|
|
20
|
|
|
|
|
1040
|
|
12
|
20
|
|
|
20
|
|
10478
|
use Pod::Usage; |
|
20
|
|
|
|
|
964024
|
|
|
20
|
|
|
|
|
3145
|
|
13
|
20
|
|
|
20
|
|
203
|
use Scalar::Util 'looks_like_number'; |
|
20
|
|
|
|
|
42
|
|
|
20
|
|
|
|
|
62949
|
|
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
|
966
|
|
|
966
|
0
|
1669
|
my ($var, $default) = @_; |
40
|
966
|
50
|
|
|
|
2889
|
return $default if $ENV{HARNESS_ACTIVE}; |
41
|
0
|
|
0
|
|
|
0
|
return $ENV{$var} // $default; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_default_modes { |
45
|
138
|
|
|
138
|
0
|
242
|
my %m; |
46
|
138
|
|
|
|
|
340
|
$m{case_sensitive} = not(env(PTP_DEFAULT_CASE_INSENSITIVE => 0)); |
47
|
138
|
|
|
|
|
321
|
$m{quote_regex} = env(PTP_DEFAULT_QUOTE_REGEX => 0); |
48
|
138
|
|
|
|
|
290
|
$m{global_match} = not(env(PTP_DEFAULT_LOCAL_MATCH => 0)); |
49
|
138
|
|
|
|
|
310
|
$m{comparator} = \"default"; |
50
|
138
|
|
|
|
|
309
|
$m{regex_engine} = env(PTP_DEFAULT_REGEX_ENGINE => 'perl'); |
51
|
138
|
|
|
|
|
288
|
$m{fatal_error} = env(PTP_DEFAULT_FATAL_ERROR => 0); |
52
|
138
|
|
|
|
|
300
|
$m{inverse_match} = env(PTP_DEFAULT_INVERSE_MATCH => 0); |
53
|
138
|
|
|
|
|
320
|
$m{input_field} = $default_input_field; |
54
|
138
|
|
|
|
|
611
|
$m{output_field} = $default_output_field; |
55
|
138
|
|
|
|
|
1183
|
return %m; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub get_default_options { |
59
|
138
|
|
|
138
|
0
|
216
|
my %o; |
60
|
138
|
|
|
|
|
308
|
$o{input_encoding} = 'UTF-8'; |
61
|
138
|
|
|
|
|
298
|
$o{output_encoding} = 'UTF-8'; |
62
|
138
|
|
|
|
|
285
|
$o{input_separator} = '\n'; # This will be interpreted in a regex |
63
|
138
|
|
|
|
|
281
|
$o{output_separator} = "\n"; |
64
|
138
|
|
|
|
|
298
|
$o{preserve_eol} = 0; |
65
|
138
|
|
|
|
|
239
|
$o{fix_final_separator} = 0; |
66
|
138
|
|
|
|
|
271
|
$o{recursive} = 0; |
67
|
138
|
|
|
|
|
237
|
$o{input_filter} = undef; |
68
|
138
|
|
|
|
|
258
|
$o{debug_mode} = 0; |
69
|
138
|
|
|
|
|
258
|
$o{merge} = 0; |
70
|
138
|
|
|
|
|
266
|
$o{in_place} = 0; |
71
|
138
|
|
|
|
|
247
|
$o{output} = undef; |
72
|
138
|
|
|
|
|
254
|
$o{append} = 0; |
73
|
138
|
|
|
|
|
229
|
$o{abort} = 0; |
74
|
138
|
|
|
|
|
252
|
$o{preserve_perl_env} = 0; |
75
|
138
|
|
|
|
|
246
|
$o{use_safe} = env(PTP_DEFAULT_SAFE => 0); |
76
|
138
|
|
|
|
|
1215
|
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
|
138
|
|
|
138
|
0
|
335
|
@inputs = (); |
83
|
138
|
|
|
|
|
803
|
@pipeline = (); |
84
|
138
|
|
|
|
|
483
|
%modes = get_default_modes(); |
85
|
138
|
|
|
|
|
434
|
%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
|
|
5449
|
'0' => sub { $options{input_separator} = '\000'; |
113
|
1
|
|
|
|
|
3
|
$options{output_separator} = '' }, |
114
|
1
|
|
|
1
|
|
5063
|
'00' => sub { $options{output_separator} = "\000" }, |
115
|
|
|
|
|
|
|
'preserve-input-separator|eol' => |
116
|
1
|
|
|
1
|
|
5078
|
sub { $options{preserve_eol} = 1; $options{output_separator} = '' }, |
|
1
|
|
|
|
|
6
|
|
117
|
|
|
|
|
|
|
'preserve-perl-env!' => \$options{preserve_perl_env}, |
118
|
36
|
|
|
36
|
|
182659
|
'safe:2' => sub { $options{use_safe} = $_[1] }, |
119
|
139
|
|
|
139
|
0
|
2387
|
)} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub modes_flags {( |
122
|
1
|
|
|
1
|
|
240
|
'case-sensitive|S' => sub { $modes{case_sensitive} = 1 }, |
123
|
3
|
|
|
3
|
|
10424
|
'case-insensitive|I' => sub { $modes{case_sensitive} = 0 }, |
124
|
11
|
|
|
11
|
|
52601
|
'quote-regexp|Q' => sub { $modes{quote_regex} = 1 }, |
125
|
0
|
|
|
0
|
|
0
|
'end-quote-regexp|E' => sub { $modes{quote_regex} = 0 }, |
126
|
1
|
|
|
1
|
|
254
|
'global-match|G' => sub { $modes{global_match} = 1 }, |
127
|
2
|
|
|
2
|
|
10531
|
'local-match|L' => sub { $modes{global_match} = 0 }, |
128
|
1
|
|
|
1
|
|
5027
|
'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
|
|
5056
|
'inverse-match|V' => sub { $modes{inverse_match} = 1 }, |
135
|
0
|
|
|
0
|
|
0
|
'normal-match|N' => sub { $modes{inverse_match} = 0 }, |
136
|
1
|
|
|
1
|
|
5012
|
'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
|
|
5172
|
'bytes' => sub { $modes{input_field} = ''; $modes{output_field} = ''; }, |
|
1
|
|
|
|
|
3
|
|
141
|
1
|
|
|
1
|
|
5164
|
'csv' => sub { $modes{input_field} = '\s*,\s*'; $modes{output_field} = ','; }, |
|
1
|
|
|
|
|
3
|
|
142
|
1
|
|
|
1
|
|
5065
|
'tsv' => sub { $modes{input_field} = '\t'; $modes{output_field} = "\t"; }, |
|
1
|
|
|
|
|
3
|
|
143
|
1
|
|
|
1
|
|
5019
|
'none' => sub { $modes{input_field} = '(?!)' }, |
144
|
139
|
|
|
139
|
0
|
3395
|
)} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub input_flags {( |
147
|
25
|
|
|
25
|
|
40673
|
'<>' => sub { push @inputs, $_[0] }, # Any options not matched otherwise. |
148
|
9
|
|
|
9
|
|
779
|
'' => sub { push @inputs, \$App::PTP::Files::stdin_marker }, # a single '-' |
149
|
139
|
|
|
139
|
0
|
791
|
)} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub is_int { |
152
|
10
|
|
|
10
|
0
|
20
|
my ($str) = @_; |
153
|
10
|
|
33
|
|
|
72
|
return looks_like_number($str) && int($str) == $str; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub validate_cut_spec { |
157
|
5
|
|
|
5
|
0
|
25
|
my ($spec) = @_; |
158
|
5
|
|
|
|
|
33
|
my @fields = split /\s*,\s*/, $spec; |
159
|
5
|
|
|
|
|
17
|
for my $f (@fields) { |
160
|
10
|
50
|
|
|
|
20
|
die "Fields passed to --cut must all be integers: $f\n" unless is_int($f); |
161
|
10
|
50
|
|
|
|
40
|
$f-- if $f > 0; |
162
|
|
|
|
|
|
|
} |
163
|
5
|
|
|
|
|
23
|
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
|
|
42244
|
sub { push @pipeline, ['grep', \&do_grep, {%modes}, $_[1]] }, |
172
|
|
|
|
|
|
|
'substitute|s=s{2}' => |
173
|
38
|
|
|
38
|
|
46261
|
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
|
19
|
|
|
19
|
|
34347
|
sub { push @pipeline, ['perl', \&do_perl, {%modes}, 'perl', $_[1]] }, |
179
|
|
|
|
|
|
|
'n=s' => |
180
|
21
|
|
|
21
|
|
25845
|
sub { push @pipeline, ['n', \&do_perl, {%modes}, 'n', $_[1]] }, |
181
|
|
|
|
|
|
|
'filter|f=s' => |
182
|
6
|
|
|
6
|
|
11174
|
sub { push @pipeline, ['filter', \&do_perl, {%modes}, 'filter', $_[1]] }, |
183
|
|
|
|
|
|
|
'mark-line|ml=s' => |
184
|
7
|
|
|
7
|
|
6650
|
sub { push @pipeline, ['mark-line', \&do_perl, {%modes}, 'mark-line', |
185
|
|
|
|
|
|
|
$_[1]] }, |
186
|
|
|
|
|
|
|
'execute|e=s' => |
187
|
20
|
|
|
20
|
|
31734
|
sub { push @pipeline, ['execute', \&do_execute, {%modes}, 'execute', |
188
|
|
|
|
|
|
|
$_[1]] }, |
189
|
|
|
|
|
|
|
'M=s' => |
190
|
1
|
|
|
1
|
|
5034
|
sub { push @pipeline, ['M', \&do_execute, {%modes}, 'M', $_[1]] }, |
191
|
|
|
|
|
|
|
'load|l=s' => |
192
|
3
|
|
|
3
|
|
795
|
sub { push @pipeline, ['load', \&do_load, {%modes}, $_[1]] }, |
193
|
7
|
|
|
7
|
|
21430
|
'sort' => sub { push @pipeline, ['sort', \&do_sort, {%modes}] }, |
194
|
|
|
|
|
|
|
'numeric-sort|ns' => |
195
|
1
|
|
|
1
|
|
5054
|
sub { my $opt = {%modes, comparator => \"numeric" }; |
196
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
197
|
|
|
|
|
|
|
'locale-sort|ls' => |
198
|
1
|
|
|
1
|
|
5073
|
sub { my $opt = {%modes, comparator => \"locale" }; |
199
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
200
|
|
|
|
|
|
|
'custom-sort|cs=s' => |
201
|
1
|
|
|
1
|
|
5033
|
sub { my $opt = {%modes, comparator => $_[1] }; |
202
|
1
|
|
|
|
|
6
|
push @pipeline, [ 'custom-sort', \&do_sort, $opt] }, |
203
|
|
|
|
|
|
|
'unique|uniq|u' => |
204
|
4
|
|
|
4
|
|
6309
|
sub { push @pipeline, ['unique', \&do_list_op, {%modes}, |
205
|
|
|
|
|
|
|
\&App::PTP::Util::uniqstr, 'together'] }, |
206
|
|
|
|
|
|
|
'global-unique|guniq|gu' => |
207
|
2
|
|
|
2
|
|
5197
|
sub { push @pipeline, ['global-unique', \&do_list_op, {%modes}, |
208
|
|
|
|
|
|
|
\&App::PTP::Util::globaluniqstr, 'together'] }, |
209
|
4
|
|
|
4
|
|
20207
|
'head:i' => sub { push @pipeline, ['head', \&do_head, {%modes}, $_[1]] }, |
210
|
4
|
|
|
4
|
|
19900
|
'tail:i' => sub { push @pipeline, ['tail', \&do_tail, {%modes}, $_[1]] }, |
211
|
|
|
|
|
|
|
'reverse|tac' => |
212
|
|
|
|
|
|
|
sub { push @pipeline, |
213
|
0
|
|
|
0
|
|
0
|
['reverse', \&do_list_op, {%modes}, sub {reverse @_ }, 'same'] }, |
|
0
|
|
|
|
|
0
|
|
214
|
|
|
|
|
|
|
'shuffle' => |
215
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['shuffle', \&do_list_op, {%modes}, |
216
|
|
|
|
|
|
|
\&List::Util::shuffle, 'none'] }, |
217
|
1
|
|
|
1
|
|
279
|
'eat' => sub { push @pipeline, ['eat', \&do_eat, {%modes}] }, |
218
|
|
|
|
|
|
|
'delete-marked' => |
219
|
3
|
|
|
3
|
|
760
|
sub { push @pipeline, ['delete-marked', \&do_delete_marked, {%modes}, |
220
|
|
|
|
|
|
|
0] }, |
221
|
|
|
|
|
|
|
'delete-before' => |
222
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-before', \&do_delete_marked, {%modes}, |
223
|
|
|
|
|
|
|
-1] }, |
224
|
|
|
|
|
|
|
'delete-after' => |
225
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-after', \&do_delete_marked, {%modes}, |
226
|
|
|
|
|
|
|
1] }, |
227
|
|
|
|
|
|
|
'delete-at-offset=i' => |
228
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-at-offset', \&do_delete_marked, {%modes}, |
229
|
|
|
|
|
|
|
$_[1]] }, |
230
|
|
|
|
|
|
|
'insert-before=s' => |
231
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-before', \&do_insert_marked, {%modes}, |
232
|
|
|
|
|
|
|
-1, $_[1]] }, |
233
|
|
|
|
|
|
|
'insert-after=s' => |
234
|
3
|
|
|
3
|
|
765
|
sub { push @pipeline, ['insert-after', \&do_insert_marked, {%modes}, |
235
|
|
|
|
|
|
|
0, $_[1]] }, |
236
|
|
|
|
|
|
|
'insert-at-offset=s{2}' => |
237
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-at-offset', \&do_insert_marked, {%modes}, |
238
|
|
|
|
|
|
|
$_[1]] }, |
239
|
|
|
|
|
|
|
'clear-markers' => |
240
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['clear-markers', \&do_set_markers, {%modes}, 0] }, |
241
|
|
|
|
|
|
|
'set-all-markers' => |
242
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['set-all-markers', \&do_set_markers, {%modes}, |
243
|
|
|
|
|
|
|
1] }, |
244
|
5
|
|
|
5
|
|
6442
|
'cut=s' => sub { push @pipeline, ['cut', \&do_cut, {%modes}, |
245
|
|
|
|
|
|
|
validate_cut_spec($_[1])] }, |
246
|
0
|
|
|
0
|
|
0
|
'paste=s' => sub { push @pipeline, ['paste', \&do_paste, {%modes}, $_[1]] }, |
247
|
3
|
|
|
3
|
|
5696
|
'pivot' => sub { push @pipeline, ['pivot', \&do_pivot, {%modes}, 'pivot'] }, |
248
|
1
|
|
|
1
|
|
4933
|
'anti-pivot' => sub { push @pipeline, ['anti-pivot', \&do_pivot, {%modes}, |
249
|
|
|
|
|
|
|
'anti-pivot'] }, |
250
|
2
|
|
|
2
|
|
5274
|
'transpose' => sub { push @pipeline, ['transpose', \&do_pivot, {%modes}, |
251
|
|
|
|
|
|
|
'transpose'] }, |
252
|
|
|
|
|
|
|
'number-lines|nl' => |
253
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['number-lines', \&do_number_lines, {%modes}] }, |
254
|
|
|
|
|
|
|
'file-name|fn' => |
255
|
2
|
|
|
2
|
|
9967
|
sub { push @pipeline, ['file-name', \&do_file_name, {%modes}, 1] }, |
256
|
|
|
|
|
|
|
'prefix-file-name|pfn' => |
257
|
2
|
|
|
2
|
|
5626
|
sub { push @pipeline, ['prefix-file-name', \&do_file_name, {%modes}, 0] }, |
258
|
|
|
|
|
|
|
'line-count|lc' => |
259
|
1
|
|
|
1
|
|
291
|
sub { push @pipeline, ['line-count', \&do_line_count, {%modes}] }, |
260
|
6
|
|
|
6
|
|
1561
|
'tee=s' => sub { push @pipeline, ['tee', \&do_tee, {%modes}, $_[1]] }, |
261
|
6
|
|
|
6
|
|
23519
|
'shell=s' => sub { push @pipeline, ['shell', \&do_shell, {%modes}, 'shell', |
262
|
|
|
|
|
|
|
$_[1]] } |
263
|
139
|
|
|
139
|
0
|
7745
|
)} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub all_args { |
266
|
139
|
|
|
139
|
0
|
101830
|
return (options_flags(), modes_flags(), input_flags(), action_flags()); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# parse_command_line(\@args) |
270
|
|
|
|
|
|
|
sub parse_command_line { |
271
|
138
|
|
|
138
|
0
|
315
|
my ($args) = @_; |
272
|
138
|
|
|
|
|
457
|
reset_global(); |
273
|
138
|
50
|
|
|
|
447
|
GetOptionsFromArray($args, all_args()) |
274
|
|
|
|
|
|
|
or pod2usage(-exitval => 2, -verbose => 0); |
275
|
|
|
|
|
|
|
|
276
|
138
|
50
|
|
|
|
59137
|
if ($options{debug_mode} > 1) { |
277
|
|
|
|
|
|
|
# When -d is specified multiple times, we add the marker on the final |
278
|
|
|
|
|
|
|
# output. |
279
|
0
|
|
|
|
|
0
|
push @pipeline, ['show-marker', \&do_perl, {%modes}, 'perl', |
280
|
|
|
|
|
|
|
'pf "%s %s", ($m ? "*" : " "), $_'] |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# Because of the way the options are processed, each --replace options |
284
|
|
|
|
|
|
|
# (expecting two arguments) is pushed twice in the pipeline sub (once for each |
285
|
|
|
|
|
|
|
# argument). We're fixing this here. |
286
|
138
|
|
|
|
|
588
|
for my $i (0 .. $#pipeline) { |
287
|
201
|
100
|
|
|
|
753
|
if ($pipeline[$i][0] eq 'substitute') { |
|
|
50
|
|
|
|
|
|
288
|
19
|
|
|
|
|
41
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
19
|
|
|
|
|
70
|
|
289
|
19
|
|
|
|
|
53
|
$pipeline[$i+1][0] = 'garbage'; |
290
|
|
|
|
|
|
|
} elsif ($pipeline[$i][0] eq 'insert-at-offset') { |
291
|
0
|
|
|
|
|
0
|
my $o = $pipeline[$i]->[3]; |
292
|
0
|
0
|
|
|
|
0
|
if (!ist_int($o)) { |
293
|
0
|
|
|
|
|
0
|
die "The first argument to --insert-at-offset must be an integer: $o\n"; |
294
|
|
|
|
|
|
|
} |
295
|
0
|
|
|
|
|
0
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
0
|
|
|
|
|
0
|
|
296
|
0
|
|
|
|
|
0
|
$pipeline[$i+1][0] = 'garbage'; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
} |
299
|
138
|
|
|
|
|
326
|
@pipeline = grep { $_->[0] ne 'garbage' } @pipeline; |
|
201
|
|
|
|
|
719
|
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Add any options that were passed after a '--' to the list of inputs. |
302
|
138
|
|
|
|
|
296
|
push @inputs, @$args; |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# Add the standard input marker to the inputs if no other input were |
305
|
|
|
|
|
|
|
# specified. |
306
|
138
|
100
|
|
|
|
419
|
push @inputs, \$App::PTP::Files::stdin_marker if not @inputs; |
307
|
|
|
|
|
|
|
|
308
|
138
|
0
|
33
|
|
|
401
|
if ($options{in_place} && $options{merge}) { |
309
|
0
|
|
|
|
|
0
|
die "The --in-place and --merge options are incompatible.\n"; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
138
|
0
|
33
|
|
|
343
|
if ($options{in_place} && $options{output}) { |
313
|
0
|
0
|
|
|
|
0
|
if ($options{append}) { |
314
|
0
|
|
|
|
|
0
|
die "The --in-place and --append options are incompatible.\n"; |
315
|
|
|
|
|
|
|
} else { |
316
|
0
|
|
|
|
|
0
|
die "The --in-place and --output options are incompatible.\n"; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
138
|
50
|
66
|
|
|
397
|
if (defined $options{input_filter} && !$options{recursive}) { |
321
|
0
|
|
|
|
|
0
|
print "WARNING: The --input-filter option is useless unless --recursive is specified too.\n"; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
138
|
|
|
|
|
549
|
return (\@inputs, \@pipeline, \%options); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
1; |