line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::PTP::Args; |
2
|
|
|
|
|
|
|
|
3
|
15
|
|
|
15
|
|
67328
|
use 5.022; |
|
15
|
|
|
|
|
61
|
|
4
|
15
|
|
|
15
|
|
66
|
use strict; |
|
15
|
|
|
|
|
21
|
|
|
15
|
|
|
|
|
283
|
|
5
|
15
|
|
|
15
|
|
59
|
use warnings; |
|
15
|
|
|
|
|
26
|
|
|
15
|
|
|
|
|
449
|
|
6
|
|
|
|
|
|
|
|
7
|
15
|
|
|
15
|
|
6277
|
use App::PTP::Commands ':CMD'; |
|
15
|
|
|
|
|
40
|
|
|
15
|
|
|
|
|
2979
|
|
8
|
15
|
|
|
15
|
|
102
|
use App::PTP::Util; |
|
15
|
|
|
|
|
32
|
|
|
15
|
|
|
|
|
355
|
|
9
|
15
|
|
|
|
|
91
|
use Getopt::Long qw(GetOptionsFromArray :config auto_abbrev no_ignore_case |
10
|
15
|
|
|
15
|
|
9161
|
permute auto_version); |
|
15
|
|
|
|
|
155455
|
|
11
|
15
|
|
|
15
|
|
3095
|
use List::Util; |
|
15
|
|
|
|
|
38
|
|
|
15
|
|
|
|
|
678
|
|
12
|
15
|
|
|
15
|
|
6675
|
use Pod::Usage; |
|
15
|
|
|
|
|
634951
|
|
|
15
|
|
|
|
|
1906
|
|
13
|
15
|
|
|
15
|
|
140
|
use Scalar::Util 'looks_like_number'; |
|
15
|
|
|
|
|
35
|
|
|
15
|
|
|
|
|
39018
|
|
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
|
840
|
|
|
840
|
0
|
1127
|
my ($var, $default) = @_; |
40
|
840
|
50
|
|
|
|
1915
|
return $default if $ENV{HARNESS_ACTIVE}; |
41
|
0
|
|
0
|
|
|
0
|
return $ENV{$var} // $default; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_default_modes { |
45
|
120
|
|
|
120
|
0
|
170
|
my %m; |
46
|
120
|
|
|
|
|
239
|
$m{case_sensitive} = not(env(PTP_DEFAULT_CASE_INSENSITIVE => 0)); |
47
|
120
|
|
|
|
|
228
|
$m{quote_regex} = env(PTP_DEFAULT_QUOTE_REGEX => 0); |
48
|
120
|
|
|
|
|
193
|
$m{global_match} = not(env(PTP_DEFAULT_LOCAL_MATCH => 0)); |
49
|
120
|
|
|
|
|
205
|
$m{comparator} = \"default"; |
50
|
120
|
|
|
|
|
189
|
$m{regex_engine} = env(PTP_DEFAULT_REGEX_ENGINE => 'perl'); |
51
|
120
|
|
|
|
|
193
|
$m{fatal_error} = env(PTP_DEFAULT_FATAL_ERROR => 0); |
52
|
120
|
|
|
|
|
197
|
$m{inverse_match} = env(PTP_DEFAULT_INVERSE_MATCH => 0); |
53
|
120
|
|
|
|
|
201
|
$m{input_field} = $default_input_field; |
54
|
120
|
|
|
|
|
176
|
$m{output_field} = $default_output_field; |
55
|
120
|
|
|
|
|
778
|
return %m; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub get_default_options { |
59
|
120
|
|
|
120
|
0
|
164
|
my %o; |
60
|
120
|
|
|
|
|
194
|
$o{input_encoding} = 'UTF-8'; |
61
|
120
|
|
|
|
|
165
|
$o{output_encoding} = 'UTF-8'; |
62
|
120
|
|
|
|
|
177
|
$o{input_separator} = '\n'; # This will be interpreted in a regex |
63
|
120
|
|
|
|
|
195
|
$o{output_separator} = "\n"; |
64
|
120
|
|
|
|
|
162
|
$o{preserve_eol} = 0; |
65
|
120
|
|
|
|
|
157
|
$o{fix_final_separator} = 0; |
66
|
120
|
|
|
|
|
157
|
$o{recursive} = 0; |
67
|
120
|
|
|
|
|
166
|
$o{input_filter} = undef; |
68
|
120
|
|
|
|
|
166
|
$o{debug_mode} = 0; |
69
|
120
|
|
|
|
|
160
|
$o{merge} = 0; |
70
|
120
|
|
|
|
|
150
|
$o{in_place} = 0; |
71
|
120
|
|
|
|
|
157
|
$o{output} = undef; |
72
|
120
|
|
|
|
|
151
|
$o{append} = 0; |
73
|
120
|
|
|
|
|
154
|
$o{abort} = 0; |
74
|
120
|
|
|
|
|
160
|
$o{preserve_perl_env} = 0; |
75
|
120
|
|
|
|
|
180
|
$o{use_safe} = env(PTP_DEFAULT_SAFE => 0); |
76
|
120
|
|
|
|
|
838
|
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
|
120
|
|
|
120
|
0
|
191
|
@inputs = (); |
83
|
120
|
|
|
|
|
399
|
@pipeline = (); |
84
|
120
|
|
|
|
|
304
|
%modes = get_default_modes(); |
85
|
120
|
|
|
|
|
323
|
%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
|
0
|
|
|
0
|
|
0
|
'0' => sub { $options{input_separator} = '\000'; |
113
|
0
|
|
|
|
|
0
|
$options{output_separator} = '' }, |
114
|
|
|
|
|
|
|
'preserve-input-separator|eol' => |
115
|
1
|
|
|
1
|
|
3826
|
sub { $options{preserve_eol} = 1; $options{output_separator} = '' }, |
|
1
|
|
|
|
|
4
|
|
116
|
|
|
|
|
|
|
'preserve-perl-env!' => \$options{preserve_perl_env}, |
117
|
36
|
|
|
36
|
|
138906
|
'safe:2' => sub { $options{use_safe} = $_[1] }, |
118
|
121
|
|
|
121
|
0
|
1345
|
)} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub modes_flags {( |
121
|
1
|
|
|
1
|
|
188
|
'case-sensitive|S' => sub { $modes{case_sensitive} = 1 }, |
122
|
3
|
|
|
3
|
|
7809
|
'case-insensitive|I' => sub { $modes{case_sensitive} = 0 }, |
123
|
10
|
|
|
10
|
|
37987
|
'quote-regexp|Q' => sub { $modes{quote_regex} = 1 }, |
124
|
0
|
|
|
0
|
|
0
|
'end-quote-regexp|E' => sub { $modes{quote_regex} = 0 }, |
125
|
1
|
|
|
1
|
|
187
|
'global-match|G' => sub { $modes{global_match} = 1 }, |
126
|
2
|
|
|
2
|
|
7781
|
'local-match|L' => sub { $modes{global_match} = 0 }, |
127
|
1
|
|
|
1
|
|
4298
|
'comparator|C=s' => sub { $modes{comparator} = $_[1] }, |
128
|
|
|
|
|
|
|
'regex-engine|re=s' => |
129
|
0
|
0
|
|
0
|
|
0
|
sub { die "Invalid value for --regex-engine: $_[1]\n" if $_[1] !~ /^\w+$/; |
130
|
0
|
|
|
|
|
0
|
$modes{regex_engine} = $_[1] }, |
131
|
0
|
|
|
0
|
|
0
|
'fatal-error|X' => sub { $modes{fatal_error} = 1 }, |
132
|
0
|
|
|
0
|
|
0
|
'ignore-error' => sub { $modes{fatal_error} = 0 }, # Find a short option? |
133
|
1
|
|
|
1
|
|
3807
|
'inverse-match|V' => sub { $modes{inverse_match} = 1 }, |
134
|
0
|
|
|
0
|
|
0
|
'normal-match|N' => sub { $modes{inverse_match} = 0 }, |
135
|
1
|
|
|
1
|
|
3884
|
'input-field-separator|F=s' => sub { $modes{input_field} = $_[1] }, |
136
|
|
|
|
|
|
|
'output-field-separator|P=s' => \$modes{output_field}, |
137
|
0
|
|
|
0
|
|
0
|
'default' => sub { $modes{input_field} = $default_input_field; |
138
|
0
|
|
|
|
|
0
|
$modes{output_field} = $default_output_field; }, |
139
|
1
|
|
|
1
|
|
3826
|
'bytes' => sub { $modes{input_field} = ''; $modes{output_field} = ''; }, |
|
1
|
|
|
|
|
3
|
|
140
|
1
|
|
|
1
|
|
3909
|
'csv' => sub { $modes{input_field} = '\s*,\s*'; $modes{output_field} = ','; }, |
|
1
|
|
|
|
|
2
|
|
141
|
1
|
|
|
1
|
|
3865
|
'tsv' => sub { $modes{input_field} = '\t'; $modes{output_field} = "\t"; }, |
|
1
|
|
|
|
|
3
|
|
142
|
1
|
|
|
1
|
|
3920
|
'none' => sub { $modes{input_field} = '(?!)' }, |
143
|
121
|
|
|
121
|
0
|
2078
|
)} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub input_flags {( |
146
|
22
|
|
|
22
|
|
26472
|
'<>' => sub { push @inputs, $_[0] }, # Any options not matched otherwise. |
147
|
9
|
|
|
9
|
|
625
|
'' => sub { push @inputs, \$App::PTP::Files::stdin_marker }, # a single '-' |
148
|
121
|
|
|
121
|
0
|
487
|
)} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub is_int { |
151
|
10
|
|
|
10
|
0
|
13
|
my ($str) = @_; |
152
|
10
|
|
33
|
|
|
53
|
return looks_like_number($str) && int($str) == $str; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub validate_cut_spec { |
156
|
5
|
|
|
5
|
0
|
12
|
my ($spec) = @_; |
157
|
5
|
|
|
|
|
27
|
my @fields = split /\s*,\s*/, $spec; |
158
|
5
|
|
|
|
|
12
|
for my $f (@fields) { |
159
|
10
|
50
|
|
|
|
18
|
die "Fields passed to --cut must all be integers: $f\n" unless is_int($f); |
160
|
10
|
50
|
|
|
|
43
|
$f-- if $f > 0; |
161
|
|
|
|
|
|
|
} |
162
|
5
|
|
|
|
|
23
|
return \@fields; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# The array associated with each action contains the name of the action, the |
166
|
|
|
|
|
|
|
# method to call for that action, a copy of the current %modes, and all the |
167
|
|
|
|
|
|
|
# other arguments that should be passed to the method. |
168
|
|
|
|
|
|
|
sub action_flags {( |
169
|
|
|
|
|
|
|
'grep|g=s' => |
170
|
27
|
|
|
27
|
|
31906
|
sub { push @pipeline, ['grep', \&do_grep, {%modes}, $_[1]] }, |
171
|
|
|
|
|
|
|
'substitute|s=s{2}' => |
172
|
38
|
|
|
38
|
|
34249
|
sub { push @pipeline, ['substitute', \&do_substitute, {%modes}, |
173
|
|
|
|
|
|
|
$_[1]] }, |
174
|
|
|
|
|
|
|
# All the do_perl below could have the same sub using "$_[0]" instead of the |
175
|
|
|
|
|
|
|
# manually specified name. |
176
|
|
|
|
|
|
|
'perl|p=s' => |
177
|
18
|
|
|
18
|
|
22309
|
sub { push @pipeline, ['perl', \&do_perl, {%modes}, 'perl', $_[1]] }, |
178
|
|
|
|
|
|
|
'n=s' => |
179
|
19
|
|
|
19
|
|
19089
|
sub { push @pipeline, ['n', \&do_perl, {%modes}, 'n', $_[1]] }, |
180
|
|
|
|
|
|
|
'filter|f=s' => |
181
|
6
|
|
|
6
|
|
8459
|
sub { push @pipeline, ['filter', \&do_perl, {%modes}, 'filter', $_[1]] }, |
182
|
|
|
|
|
|
|
'mark-line|ml=s' => |
183
|
7
|
|
|
7
|
|
5353
|
sub { push @pipeline, ['mark-line', \&do_perl, {%modes}, 'mark-line', |
184
|
|
|
|
|
|
|
$_[1]] }, |
185
|
|
|
|
|
|
|
'execute|e=s' => |
186
|
19
|
|
|
19
|
|
20341
|
sub { push @pipeline, ['execute', \&do_execute, {%modes}, $_[1]] }, |
187
|
|
|
|
|
|
|
'load|l=s' => |
188
|
3
|
|
|
3
|
|
656
|
sub { push @pipeline, ['load', \&do_load, {%modes}, $_[1]] }, |
189
|
5
|
|
|
5
|
|
12098
|
'sort' => sub { push @pipeline, ['sort', \&do_sort, {%modes}] }, |
190
|
|
|
|
|
|
|
'numeric-sort|ns' => |
191
|
1
|
|
|
1
|
|
3850
|
sub { my $opt = {%modes, comparator => \"numeric" }; |
192
|
1
|
|
|
|
|
4
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
193
|
|
|
|
|
|
|
'locale-sort|ls' => |
194
|
1
|
|
|
1
|
|
3935
|
sub { my $opt = {%modes, comparator => \"locale" }; |
195
|
1
|
|
|
|
|
4
|
push @pipeline, [ 'numeric-sort', \&do_sort, $opt] }, |
196
|
|
|
|
|
|
|
'custom-sort|cs=s' => |
197
|
1
|
|
|
1
|
|
3890
|
sub { my $opt = {%modes, comparator => $_[1] }; |
198
|
1
|
|
|
|
|
5
|
push @pipeline, [ 'custom-sort', \&do_sort, $opt] }, |
199
|
|
|
|
|
|
|
'unique|u' => |
200
|
1
|
|
|
1
|
|
194
|
sub { push @pipeline, ['unique', \&do_list_op, {%modes}, |
201
|
|
|
|
|
|
|
\&App::PTP::Util::uniqstr, 0] }, |
202
|
4
|
|
|
4
|
|
15577
|
'head:i' => sub { push @pipeline, ['head', \&do_head, {%modes}, $_[1]] }, |
203
|
4
|
|
|
4
|
|
15105
|
'tail:i' => sub { push @pipeline, ['tail', \&do_tail, {%modes}, $_[1]] }, |
204
|
|
|
|
|
|
|
'reverse|tac' => |
205
|
|
|
|
|
|
|
sub { push @pipeline, |
206
|
0
|
|
|
0
|
|
0
|
['reverse', \&do_list_op, {%modes}, sub {reverse @_ }, 1] }, |
|
0
|
|
|
|
|
0
|
|
207
|
|
|
|
|
|
|
'shuffle' => |
208
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['shuffle', \&do_list_op, {%modes}, |
209
|
|
|
|
|
|
|
\&List::Util::shuffle, 0] }, |
210
|
|
|
|
|
|
|
'delete-marked' => |
211
|
3
|
|
|
3
|
|
590
|
sub { push @pipeline, ['delete-marked', \&do_delete_marked, {%modes}, |
212
|
|
|
|
|
|
|
0] }, |
213
|
|
|
|
|
|
|
'delete-before' => |
214
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-before', \&do_delete_marked, {%modes}, |
215
|
|
|
|
|
|
|
-1] }, |
216
|
|
|
|
|
|
|
'delete-after' => |
217
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-after', \&do_delete_marked, {%modes}, |
218
|
|
|
|
|
|
|
1] }, |
219
|
|
|
|
|
|
|
'delete-at-offset=i' => |
220
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['delete-at-offset', \&do_delete_marked, {%modes}, |
221
|
|
|
|
|
|
|
$_[1]] }, |
222
|
|
|
|
|
|
|
'insert-before=s' => |
223
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-before', \&do_insert_marked, {%modes}, |
224
|
|
|
|
|
|
|
-1, $_[1]] }, |
225
|
|
|
|
|
|
|
'insert-after=s' => |
226
|
3
|
|
|
3
|
|
602
|
sub { push @pipeline, ['insert-after', \&do_insert_marked, {%modes}, |
227
|
|
|
|
|
|
|
0, $_[1]] }, |
228
|
|
|
|
|
|
|
'insert-at-offset=s{2}' => |
229
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['insert-at-offset', \&do_insert_marked, {%modes}, |
230
|
|
|
|
|
|
|
$_[1]] }, |
231
|
|
|
|
|
|
|
'clear-markers' => |
232
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['clear-markers', \&do_set_markers, {%modes}, 0] }, |
233
|
|
|
|
|
|
|
'set-all-markers' => |
234
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['set-all-markers', \&do_set_markers, {%modes}, |
235
|
|
|
|
|
|
|
1] }, |
236
|
5
|
|
|
5
|
|
5145
|
'cut=s' => sub { push @pipeline, ['cut', \&do_cut, {%modes}, |
237
|
|
|
|
|
|
|
validate_cut_spec($_[1])] }, |
238
|
0
|
|
|
0
|
|
0
|
'paste=s' => sub { push @pipeline, ['paste', \&do_paste, {%modes}, $_[1]] }, |
239
|
2
|
|
|
2
|
|
4249
|
'pivot' => sub { push @pipeline, ['pivot', \&do_pivot, {%modes}, 'pivot'] }, |
240
|
1
|
|
|
1
|
|
3812
|
'anti-pivot' => sub { push @pipeline, ['anti-pivot', \&do_pivot, {%modes}, |
241
|
|
|
|
|
|
|
'anti-pivot'] }, |
242
|
2
|
|
|
2
|
|
4039
|
'transpose' => sub { push @pipeline, ['transpose', \&do_pivot, {%modes}, |
243
|
|
|
|
|
|
|
'transpose'] }, |
244
|
|
|
|
|
|
|
'number-lines|nl' => |
245
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['number-lines', \&do_number_lines, {%modes}] }, |
246
|
|
|
|
|
|
|
'file-name|fn' => |
247
|
0
|
|
|
0
|
|
0
|
sub { push @pipeline, ['file-name', \&do_file_name, {%modes}, 1] }, |
248
|
|
|
|
|
|
|
'prefix-file-name|pfn' => |
249
|
1
|
|
|
1
|
|
184
|
sub { push @pipeline, ['prefix-file-name', \&do_file_name, {%modes}, 0] }, |
250
|
|
|
|
|
|
|
'line-count|lc' => |
251
|
1
|
|
|
1
|
|
182
|
sub { push @pipeline, ['line-count', \&do_line_count, {%modes}] }, |
252
|
6
|
|
|
6
|
|
1590
|
'tee=s' => sub { push @pipeline, ['tee', \&do_tee, {%modes}, $_[1]] } |
253
|
121
|
|
|
121
|
0
|
4294
|
)} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub all_args { |
256
|
121
|
|
|
121
|
0
|
95828
|
return (options_flags(), modes_flags(), input_flags(), action_flags()); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# parse_command_line(\@args) |
260
|
|
|
|
|
|
|
sub parse_command_line { |
261
|
120
|
|
|
120
|
0
|
203
|
my ($args) = @_; |
262
|
120
|
|
|
|
|
273
|
reset_global(); |
263
|
120
|
50
|
|
|
|
330
|
GetOptionsFromArray($args, all_args()) |
264
|
|
|
|
|
|
|
or pod2usage(-exitval => 2, -verbose => 0); |
265
|
|
|
|
|
|
|
|
266
|
120
|
50
|
|
|
|
43059
|
if ($options{debug_mode} > 1) { |
267
|
|
|
|
|
|
|
# When -d is specified multiple times, we add the marker on the final |
268
|
|
|
|
|
|
|
# output. |
269
|
0
|
|
|
|
|
0
|
push @pipeline, ['show-marker', \&do_perl, {%modes}, 'perl', |
270
|
|
|
|
|
|
|
'pf "%s %s", ($m ? "*" : " "), $_'] |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Because of the way the options are processed, each --replace options |
274
|
|
|
|
|
|
|
# (expecting two arguments) is pushed twice in the pipeline sub (once for each |
275
|
|
|
|
|
|
|
# argument). We're fixing this here. |
276
|
120
|
|
|
|
|
385
|
for my $i (0 .. $#pipeline) { |
277
|
178
|
100
|
|
|
|
855
|
if ($pipeline[$i][0] eq 'substitute') { |
|
|
50
|
|
|
|
|
|
278
|
19
|
|
|
|
|
23
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
19
|
|
|
|
|
61
|
|
279
|
19
|
|
|
|
|
41
|
$pipeline[$i+1][0] = 'garbage'; |
280
|
|
|
|
|
|
|
} elsif ($pipeline[$i][0] eq 'insert-at-offset') { |
281
|
0
|
|
|
|
|
0
|
my $o = $pipeline[$i]->[3]; |
282
|
0
|
0
|
|
|
|
0
|
if (!ist_int($o)) { |
283
|
0
|
|
|
|
|
0
|
die "The first argument to --insert-at-offset must be an integer: $o\n"; |
284
|
|
|
|
|
|
|
} |
285
|
0
|
|
|
|
|
0
|
push @{$pipeline[$i]}, $pipeline[$i+1]->[3]; |
|
0
|
|
|
|
|
0
|
|
286
|
0
|
|
|
|
|
0
|
$pipeline[$i+1][0] = 'garbage'; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
120
|
|
|
|
|
227
|
@pipeline = grep { $_->[0] ne 'garbage' } @pipeline; |
|
178
|
|
|
|
|
544
|
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# Add any options that were passed after a '--' to the list of inputs. |
292
|
120
|
|
|
|
|
204
|
push @inputs, @$args; |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Add the standard input marker to the inputs if no other input were |
295
|
|
|
|
|
|
|
# specified. |
296
|
120
|
100
|
|
|
|
315
|
push @inputs, \$App::PTP::Files::stdin_marker if not @inputs; |
297
|
|
|
|
|
|
|
|
298
|
120
|
0
|
33
|
|
|
262
|
if ($options{in_place} && $options{merge}) { |
299
|
0
|
|
|
|
|
0
|
die "The --in-place and --merge options are incompatible.\n"; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
120
|
0
|
33
|
|
|
233
|
if ($options{in_place} && $options{output}) { |
303
|
0
|
0
|
|
|
|
0
|
if ($options{append}) { |
304
|
0
|
|
|
|
|
0
|
die "The --in-place and --append options are incompatible.\n"; |
305
|
|
|
|
|
|
|
} else { |
306
|
0
|
|
|
|
|
0
|
die "The --in-place and --output options are incompatible.\n"; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
120
|
50
|
66
|
|
|
299
|
if (defined $options{input_filter} && !$options{recursive}) { |
311
|
0
|
|
|
|
|
0
|
print "WARNING: The --input-filter option is useless unless --recursive is specified too.\n"; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
120
|
|
|
|
|
392
|
return (\@inputs, \@pipeline, \%options); |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
1; |