line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=encoding utf8 |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
subst - Greple module for text search and substitution |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 VERSION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Version 2.32 |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 SYNOPSIS |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
greple -Msubst --dict I<dictionary> [ options ] |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Dictionary: |
16
|
|
|
|
|
|
|
--dict dictionary file |
17
|
|
|
|
|
|
|
--dictdata dictionary data |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Check: |
20
|
|
|
|
|
|
|
--check=[ng,ok,any,outstand,all,none] |
21
|
|
|
|
|
|
|
--select=N |
22
|
|
|
|
|
|
|
--linefold |
23
|
|
|
|
|
|
|
--stat |
24
|
|
|
|
|
|
|
--with-stat |
25
|
|
|
|
|
|
|
--stat-style=[default,dict] |
26
|
|
|
|
|
|
|
--stat-item={match,expect,number,ok,ng,dict}=[0,1] |
27
|
|
|
|
|
|
|
--subst |
28
|
|
|
|
|
|
|
--[no-]warn-overlap |
29
|
|
|
|
|
|
|
--[no-]warn-include |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
File Update: |
32
|
|
|
|
|
|
|
--diff |
33
|
|
|
|
|
|
|
--diffcmd command |
34
|
|
|
|
|
|
|
--create |
35
|
|
|
|
|
|
|
--replace |
36
|
|
|
|
|
|
|
--overwrite |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 DESCRIPTION |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
This B<greple> module supports check and substitution of text files |
41
|
|
|
|
|
|
|
based on dictionary data. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Dictionary file is given by B<--dict> option and each line contains |
44
|
|
|
|
|
|
|
matching pattern and expected string pairs. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
greple -Msubst --dict DICT |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
If the dictionary file contains following data: |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
colou?r color |
51
|
|
|
|
|
|
|
cent(er|re) center |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
above command finds the first pattern which does not match the second |
54
|
|
|
|
|
|
|
string, that is "colour" and "centre" in this case. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Field C<//> in dictionary data is ignored, so this file can be written |
57
|
|
|
|
|
|
|
like this: |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
colou?r // color |
60
|
|
|
|
|
|
|
cent(er|re) // center |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
You can use same file by B<greple>'s B<-f> option and string after |
63
|
|
|
|
|
|
|
C<//> is ignored as a comment in that case. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
greple -f DICT ... |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Option B<--dictdata> can be used to provide dictionary data in command |
68
|
|
|
|
|
|
|
line. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
greple --dictdata $'colou?r color\ncent(er|re) center\n' |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Dictionary entry starting with a sharp sign (C<#>) is a comment and |
73
|
|
|
|
|
|
|
ignored. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head2 Overlapped pattern |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
When the matched string is same or shorter than previously matched |
78
|
|
|
|
|
|
|
string by another pattern, it is simply ignored (B<--no-warn-include> |
79
|
|
|
|
|
|
|
by default). So, if you have to declare conflicted patterns, place |
80
|
|
|
|
|
|
|
the longer pattern earlier. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
If the matched string overlaps with previously matched string, it is |
83
|
|
|
|
|
|
|
warned (B<--warn-overlap> by default) and ignored. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 Terminal color |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This version uses L<Getopt::EX::termcolor> module. It sets option |
88
|
|
|
|
|
|
|
B<--light-screen> or B<--dark-screen> depending on the terminal on |
89
|
|
|
|
|
|
|
which the command run, or B<TERM_BGCOLOR> environment variable. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
Some terminals (eg: "Apple_Terminal" or "iTerm") are detected |
92
|
|
|
|
|
|
|
automatically and no action is required. Otherwise set |
93
|
|
|
|
|
|
|
B<TERM_BGCOLOR> environment to #000000 (black) to #FFFFFF (white) |
94
|
|
|
|
|
|
|
digit depending on terminal background color. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head1 OPTIONS |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=over 7 |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=item B<--dict>=I<file> |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Specify dictionary file. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=item B<--dictdata>=I<data> |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Specify dictionary data by text. |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=item B<--check>=C<outstand>|C<ng>|C<ok>|C<any>|C<all>|C<none> |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Option B<--check> takes argument from C<ng>, C<ok>, C<any>, |
111
|
|
|
|
|
|
|
C<outstand>, C<all> and C<none>. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
With default value C<outstand>, command will show information about |
114
|
|
|
|
|
|
|
both expected and unexpected words only when unexpected word was found |
115
|
|
|
|
|
|
|
in the same file. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
With value C<ng>, command will show information about unexpected |
118
|
|
|
|
|
|
|
words. With value C<ok>, you will get information about expected |
119
|
|
|
|
|
|
|
words. Both with value C<any>. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Value C<all> and C<none> make sense only when used with B<--stat> |
122
|
|
|
|
|
|
|
option, and display information about never matched pattern. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item B<--select>=I<N> |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Select I<N>th entry from the dictionary. Argument is interpreted by |
127
|
|
|
|
|
|
|
L<Getopt::EX::Numbers> module. Range can be defined like |
128
|
|
|
|
|
|
|
B<--select>=C<1:3,7:9>. You can get numbers by B<--stat> option. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=item B<--linefold> |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
If the target data is folded in the middle of text, use B<--linefold> |
133
|
|
|
|
|
|
|
option. It creates regex patterns which matches string spread across |
134
|
|
|
|
|
|
|
lines. Substituted text does not include newline, though. Because it |
135
|
|
|
|
|
|
|
confuses regex behavior somewhat, avoid to use if possible. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item B<--stat> |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=item B<--with-stat> |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Print statistical information. Works with B<--check> option. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Option B<--with-stat> print statistics after normal output, while |
144
|
|
|
|
|
|
|
B<--stat> print only statistics. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item B<--stat-style>=C<default>|C<dict> |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Using B<--stat-style=dict> option with B<--stat> and B<--check=any>, |
149
|
|
|
|
|
|
|
you can get dictionary style output for your working document. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item B<--stat-item> I<item>=[0,1] |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Specify which item is shown up in stat information. Default values |
154
|
|
|
|
|
|
|
are: |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
match=1 |
157
|
|
|
|
|
|
|
expect=1 |
158
|
|
|
|
|
|
|
number=1 |
159
|
|
|
|
|
|
|
ng=1 |
160
|
|
|
|
|
|
|
ok=1 |
161
|
|
|
|
|
|
|
dict=0 |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
If you don't need to see pattern field, use like this: |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
--stat-item match=0 |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Multiple parameters can be set at once: |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
--stat-item match=number=0,ng=1,ok=1 |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item B<--subst> |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Substitute unexpected matched pattern to expected string. Newline |
174
|
|
|
|
|
|
|
character in the matched string is ignored. Pattern without |
175
|
|
|
|
|
|
|
replacement string is not changed. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=item B<--[no-]warn-overlap> |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Warn overlapped pattern. |
180
|
|
|
|
|
|
|
Default on. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item B<--[no-]warn-include> |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Warn included pattern. |
185
|
|
|
|
|
|
|
Default off. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=back |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head2 FILE UPDATE OPTIONS |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=over 7 |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item B<--diff> |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item B<--diffcmd>=I<command> |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Option B<--diff> produce diff output of original and converted text. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Specify diff command name used by B<--diff> option. Default is "diff |
200
|
|
|
|
|
|
|
-u". |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item B<--create> |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Create new file and write the result. Suffix ".new" is appended to |
205
|
|
|
|
|
|
|
original filename. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item B<--replace> |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Replace the target file by converted result. Original file is renamed |
210
|
|
|
|
|
|
|
to backup name with ".bak" suffix. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=item B<--overwrite> |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Overwrite the target file by converted result with no backup. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=back |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head1 DICTIONARY |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
This module includes example dictionaries. They are installed share |
221
|
|
|
|
|
|
|
directory and accessed by B<--exdict> option. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
greple -Msubst --exdict jtca-katakana-guide-3.dict |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=over 7 |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item B<--exdict> I<dictionary> |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Use I<dictionary> flie in the distribution as a dictionary file. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item B<--exdictdir> |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Show dictionary directory. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=item B<--exdict> jtca-katakana-guide-3.dict |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item B<--jtca-katakana-guide> |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Created from following guideline document. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
外来語(カタカナ)表記ガイドライン 第3版 |
242
|
|
|
|
|
|
|
制定:2015年8月 |
243
|
|
|
|
|
|
|
発行:2015年9月 |
244
|
|
|
|
|
|
|
一般財団法人テクニカルコミュニケーター協会 |
245
|
|
|
|
|
|
|
Japan Technical Communicators Association |
246
|
|
|
|
|
|
|
https://www.jtca.org/standardization/katakana_guide_3_20171222.pdf |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=item B<--jtca> |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Customized B<--jtca-katakana-guide>. Original dictionary is |
251
|
|
|
|
|
|
|
automatically generated from published data. This dictionary is |
252
|
|
|
|
|
|
|
customized for practical use. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item B<--exdict> jtf-style-guide-3.dict |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=item B<--jtf-style-guide> |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Created from following guideline document. |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
JTF日本語標準スタイルガイド(翻訳用) |
261
|
|
|
|
|
|
|
第3.0版 |
262
|
|
|
|
|
|
|
2019年8月20日 |
263
|
|
|
|
|
|
|
一般社団法人 日本翻訳連盟(JTF) |
264
|
|
|
|
|
|
|
翻訳品質委員会 |
265
|
|
|
|
|
|
|
https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=item B<--jtf> |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Customized B<--jtf-style-guide>. Original dictionary is automatically |
270
|
|
|
|
|
|
|
generated from published data. This dictionary is customized for |
271
|
|
|
|
|
|
|
practical use. |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=item B<--exdict> sccc2.dict |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=item B<--sccc2> |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Dictionary used for "C/C++ セキュアコーディング 第2版" published in |
278
|
|
|
|
|
|
|
2014. |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
https://www.jpcert.or.jp/securecoding_book_2nd.html |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item B<--exdict> ms-style-guide.dict |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item B<--ms-style-guide> |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Dictionary generated from Microsoft localization style guide. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
https://www.microsoft.com/ja-jp/language/styleguides |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
Data is generated from this article: |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
https://www.atmarkit.co.jp/news/200807/25/microsoft.html |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=item B<--microsoft> |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
Customized B<--ms-style-guide>. Original dictionary is automatically |
297
|
|
|
|
|
|
|
generated from published data. This dictionary is customized for |
298
|
|
|
|
|
|
|
practical use. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
Amendment dictionary can be found |
301
|
|
|
|
|
|
|
L<here|https://github.com/kaz-utashiro/greple-subst/blob/master/share/ms-amend.dict>. |
302
|
|
|
|
|
|
|
Please raise an issue or send a pull-request if you have request to update. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=back |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head1 JAPANESE |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
This module is originaly made for Japanese text editing support. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head2 KATAKANA |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Japanese KATAKANA word have a lot of variants to describe same word, |
313
|
|
|
|
|
|
|
so unification is important but it's quite tiresome work. In the next |
314
|
|
|
|
|
|
|
example, |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
イ[エー]ハトー?([ヴブボ]ォ?) // イーハトーヴォ |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
left pattern matches all following words. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
イエハトブ |
321
|
|
|
|
|
|
|
イーハトヴ |
322
|
|
|
|
|
|
|
イーハトーヴ |
323
|
|
|
|
|
|
|
イーハトーヴォ |
324
|
|
|
|
|
|
|
イーハトーボ |
325
|
|
|
|
|
|
|
イーハトーブ |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
This module helps to detect and correct them. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head1 INSTALL |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head2 CPANMINUS |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
$ cpanm App::Greple::subst |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head1 SEE ALSO |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
L<https://github.com/kaz-utashiro/greple> |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
L<https://github.com/kaz-utashiro/greple-subst> |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
L<https://github.com/kaz-utashiro/greple-update> |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
L<https://www.jtca.org/standardization/katakana_guide_3_20171222.pdf> |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
L<https://www.jtf.jp/jp/style_guide/styleguide_top.html>, |
346
|
|
|
|
|
|
|
L<https://www.jtf.jp/jp/style_guide/pdf/jtf_style_guide.pdf> |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
L<https://www.microsoft.com/ja-jp/language/styleguides>, |
349
|
|
|
|
|
|
|
L<https://www.atmarkit.co.jp/news/200807/25/microsoft.html> |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
L<文化庁 国語施策・日本語教育 国語施策情報 内閣告示・内閣訓令 外来語の表記|https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kijun/naikaku/gairai/index.html> |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
L<https://qiita.com/kaz-utashiro/items/85add653a71a7e01c415> |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
L<イーハトーブ|https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%BC%E3%83%8F%E3%83%88%E3%83%BC%E3%83%96> |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head1 AUTHOR |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
Kazumasa Utashiro |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=head1 LICENSE |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
Copyright 2017-2023 Kazumasa Utashiro. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
366
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=cut |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
|
371
|
1
|
|
|
1
|
|
940
|
use v5.14; |
|
1
|
|
|
|
|
4
|
|
372
|
|
|
|
|
|
|
package App::Greple::subst; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
our $VERSION = '2.32'; |
375
|
|
|
|
|
|
|
|
376
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
377
|
1
|
|
|
1
|
|
650
|
use utf8; |
|
1
|
|
|
|
|
15
|
|
|
1
|
|
|
|
|
4
|
|
378
|
1
|
|
|
1
|
|
569
|
use open IO => ':utf8'; |
|
1
|
|
|
|
|
1258
|
|
|
1
|
|
|
|
|
5
|
|
379
|
|
|
|
|
|
|
|
380
|
1
|
|
|
1
|
|
98
|
use Exporter 'import'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
107
|
|
381
|
|
|
|
|
|
|
our @EXPORT = qw( |
382
|
|
|
|
|
|
|
&subst_initialize |
383
|
|
|
|
|
|
|
&subst_begin |
384
|
|
|
|
|
|
|
&subst_diff |
385
|
|
|
|
|
|
|
&subst_divert |
386
|
|
|
|
|
|
|
&subst_update |
387
|
|
|
|
|
|
|
&subst_show_stat |
388
|
|
|
|
|
|
|
&subst_search |
389
|
|
|
|
|
|
|
); |
390
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( ); |
391
|
|
|
|
|
|
|
our @EXPORT_OK = qw(); |
392
|
|
|
|
|
|
|
|
393
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
60
|
|
394
|
1
|
|
|
1
|
|
712
|
use Data::Dumper; |
|
1
|
|
|
|
|
6987
|
|
|
1
|
|
|
|
|
65
|
|
395
|
1
|
|
|
1
|
|
500
|
use Text::ParseWords qw(shellwords); |
|
1
|
|
|
|
|
1407
|
|
|
1
|
|
|
|
|
58
|
|
396
|
1
|
|
|
1
|
|
643
|
use Encode; |
|
1
|
|
|
|
|
10161
|
|
|
1
|
|
|
|
|
77
|
|
397
|
1
|
|
|
1
|
|
534
|
use Getopt::EX::Colormap qw(colorize); |
|
1
|
|
|
|
|
20850
|
|
|
1
|
|
|
|
|
78
|
|
398
|
1
|
|
|
1
|
|
8
|
use Getopt::EX::LabeledParam; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
399
|
1
|
|
|
1
|
|
512
|
use App::Greple::Common; |
|
1
|
|
|
|
|
382
|
|
|
1
|
|
|
|
|
98
|
|
400
|
1
|
|
|
1
|
|
460
|
use App::Greple::Pattern; |
|
1
|
|
|
|
|
22624
|
|
|
1
|
|
|
|
|
94
|
|
401
|
1
|
|
|
1
|
|
481
|
use App::Greple::subst::Dict; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
43
|
|
402
|
|
|
|
|
|
|
|
403
|
1
|
|
|
1
|
|
440
|
use File::Share qw(:all); |
|
1
|
|
|
|
|
26294
|
|
|
1
|
|
|
|
|
1146
|
|
404
|
|
|
|
|
|
|
$ENV{GREPLE_SUBST_DICT} //= dist_dir 'App-Greple-subst'; |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
our $debug = 0; |
407
|
|
|
|
|
|
|
our $remember_data = 1; |
408
|
|
|
|
|
|
|
our $opt_subst = 0; |
409
|
|
|
|
|
|
|
our @opt_subst_from; |
410
|
|
|
|
|
|
|
our @opt_subst_to; |
411
|
|
|
|
|
|
|
our @opt_dictfile; |
412
|
|
|
|
|
|
|
our @opt_dictdata; |
413
|
|
|
|
|
|
|
our $opt_printdict; |
414
|
|
|
|
|
|
|
our $opt_dictname; |
415
|
|
|
|
|
|
|
our $opt_check = 'outstand'; |
416
|
|
|
|
|
|
|
our @opt_format; |
417
|
|
|
|
|
|
|
our @default_opt_format = ( '%s' ); |
418
|
|
|
|
|
|
|
our $opt_subst_select; |
419
|
|
|
|
|
|
|
our $opt_linefold; |
420
|
|
|
|
|
|
|
our $opt_ignore_space = 1; |
421
|
|
|
|
|
|
|
our $opt_warn_overlap = 1; |
422
|
|
|
|
|
|
|
our $opt_warn_include = 0; |
423
|
|
|
|
|
|
|
our $opt_stat_style = "default"; |
424
|
|
|
|
|
|
|
our @opt_stat_item; |
425
|
|
|
|
|
|
|
our %opt_stat_item = ( |
426
|
|
|
|
|
|
|
map( { $_ => 1 } qw(match expect number ng ok) ), |
427
|
|
|
|
|
|
|
map( { $_ => 0 } qw(dict) ), |
428
|
|
|
|
|
|
|
); |
429
|
|
|
|
|
|
|
our $opt_show_comment = 0; |
430
|
|
|
|
|
|
|
our $opt_show_numbers = 1; |
431
|
|
|
|
|
|
|
my %stat; |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
my $current_file; |
434
|
|
|
|
|
|
|
my $contents; |
435
|
|
|
|
|
|
|
my $ignorechar_re; |
436
|
|
|
|
|
|
|
my @dicts; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub debug { |
439
|
0
|
|
|
0
|
0
|
|
$debug = 1; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
sub subst_initialize { |
443
|
|
|
|
|
|
|
|
444
|
0
|
0
|
|
0
|
0
|
|
state $once_called++ and return; |
445
|
|
|
|
|
|
|
|
446
|
0
|
|
|
|
|
|
Getopt::EX::LabeledParam |
447
|
|
|
|
|
|
|
->new(HASH => \%opt_stat_item) |
448
|
|
|
|
|
|
|
->load_params(@opt_stat_item); |
449
|
|
|
|
|
|
|
|
450
|
0
|
0
|
|
|
|
|
@opt_format = @default_opt_format if @opt_format == 0; |
451
|
|
|
|
|
|
|
|
452
|
0
|
0
|
|
|
|
|
$ignorechar_re = $opt_ignore_space ? qr/\s+/ : qr/\R+/; |
453
|
|
|
|
|
|
|
|
454
|
0
|
|
|
|
|
|
my $config = { linefold => $opt_linefold, |
455
|
|
|
|
|
|
|
dictname => $opt_dictname, |
456
|
|
|
|
|
|
|
printdict => $opt_printdict }; |
457
|
0
|
|
|
|
|
|
for my $data (@opt_dictdata) { |
458
|
0
|
|
|
|
|
|
push @dicts, App::Greple::subst::Dict->new( |
459
|
|
|
|
|
|
|
DATA => $data, |
460
|
|
|
|
|
|
|
CONFIG => $config, |
461
|
|
|
|
|
|
|
); |
462
|
|
|
|
|
|
|
} |
463
|
0
|
|
|
|
|
|
for my $file (@opt_dictfile) { |
464
|
0
|
0
|
|
|
|
|
if (-d $file) { |
465
|
0
|
|
|
|
|
|
warn "$file is directory\n"; |
466
|
0
|
|
|
|
|
|
next; |
467
|
|
|
|
|
|
|
} |
468
|
0
|
|
|
|
|
|
push @dicts, App::Greple::subst::Dict->new( |
469
|
|
|
|
|
|
|
FILE => $file, |
470
|
|
|
|
|
|
|
CONFIG => $config, |
471
|
|
|
|
|
|
|
); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
0
|
0
|
|
|
|
|
if (@dicts == 0) { |
475
|
0
|
|
|
|
|
|
warn "Module -Msubst requires dictionary data.\n"; |
476
|
0
|
|
|
|
|
|
main::usage(); |
477
|
0
|
|
|
|
|
|
die; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub subst_begin { |
482
|
0
|
|
|
0
|
0
|
|
my %arg = @_; |
483
|
0
|
0
|
|
|
|
|
$current_file = delete $arg{&FILELABEL} or die; |
484
|
0
|
0
|
|
|
|
|
$contents = $_ if $remember_data; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# |
488
|
|
|
|
|
|
|
# define &divert_stdout and &recover_stdout |
489
|
|
|
|
|
|
|
# |
490
|
|
|
|
|
|
|
{ |
491
|
|
|
|
|
|
|
my $diverted = 0; |
492
|
|
|
|
|
|
|
my $buffer; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub divert_stdout { |
495
|
0
|
0
|
|
0
|
0
|
|
$buffer = @_ ? shift : '/dev/null'; |
496
|
0
|
0
|
|
|
|
|
$diverted = $diverted == 0 ? 1 : return; |
497
|
0
|
0
|
|
|
|
|
open SUBST_STDOUT, '>&', \*STDOUT or die "open: $!"; |
498
|
0
|
|
|
|
|
|
close STDOUT; |
499
|
0
|
0
|
|
|
|
|
open STDOUT, '>', $buffer or die "open: $!"; |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
sub recover_stdout { |
503
|
0
|
0
|
|
0
|
0
|
|
$diverted = $diverted == 1 ? 0 : return; |
504
|
0
|
|
|
|
|
|
close STDOUT; |
505
|
0
|
0
|
|
|
|
|
open STDOUT, '>&', \*SUBST_STDOUT or die "open: $!"; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
1
|
|
|
1
|
|
9
|
use Text::VisualWidth::PP; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
69
|
|
510
|
1
|
|
|
1
|
|
7
|
use Text::VisualPrintf qw(vprintf vsprintf); |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
70
|
|
511
|
1
|
|
|
1
|
|
8
|
use List::Util qw(max any sum first); |
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
599
|
|
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
sub vwidth { |
514
|
0
|
0
|
0
|
0
|
0
|
|
if (not defined $_[0] or length $_[0] == 0) { |
515
|
0
|
|
|
|
|
|
return 0; |
516
|
|
|
|
|
|
|
} |
517
|
0
|
|
|
|
|
|
Text::VisualWidth::PP::width $_[0]; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
my @match_list; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
sub subst_show_stat { |
523
|
0
|
|
|
0
|
0
|
|
my %arg = @_; |
524
|
0
|
|
|
|
|
|
my($from_max, $to_max) = (0, 0); |
525
|
0
|
|
|
|
|
|
my $i = -1; |
526
|
0
|
|
|
|
|
|
my @show_list; |
527
|
0
|
|
|
|
|
|
for my $dict (@dicts) { |
528
|
0
|
|
|
|
|
|
my @fromto = $dict->words; |
529
|
0
|
|
|
|
|
|
my @show; |
530
|
0
|
|
|
|
|
|
for my $p (@fromto) { |
531
|
0
|
|
|
|
|
|
$i++; |
532
|
0
|
|
0
|
|
|
|
$p // die; |
533
|
0
|
0
|
|
|
|
|
if ($p->is_comment) { |
534
|
0
|
0
|
|
|
|
|
push @show, [ $i, $p, {} ] if $opt_show_comment; |
535
|
0
|
|
|
|
|
|
next; |
536
|
|
|
|
|
|
|
} |
537
|
0
|
|
0
|
|
|
|
my($from_re, $to) = ($p->string, $p->correct // ''); |
538
|
0
|
|
0
|
|
|
|
my $hash = $match_list[$i] // {}; |
539
|
0
|
|
|
|
|
|
my @keys = keys %{$hash}; |
|
0
|
|
|
|
|
|
|
540
|
0
|
|
|
|
|
|
my @ng = grep { $_ ne $to } @keys; |
|
0
|
|
|
|
|
|
|
541
|
0
|
|
|
|
|
|
my @ok = grep { $_ eq $to } @keys; |
|
0
|
|
|
|
|
|
|
542
|
0
|
0
|
|
|
|
|
if ($opt_check eq 'none' ) { next if @keys != 0 } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
543
|
0
|
0
|
|
|
|
|
elsif ($opt_check eq 'any' ) { next if @keys == 0 } |
544
|
0
|
0
|
|
|
|
|
elsif ($opt_check eq 'ok' ) { next if @ok == 0 } |
545
|
0
|
0
|
|
|
|
|
elsif ($opt_check eq 'ng' ) { next if @ng == 0 } |
546
|
0
|
0
|
|
|
|
|
elsif ($opt_check eq 'outstand') { next if @ng == 0 } |
547
|
|
|
|
|
|
|
elsif ($opt_check eq 'all') { } |
548
|
0
|
|
|
|
|
|
else { die } |
549
|
0
|
|
|
|
|
|
$from_max = max $from_max, vwidth $from_re; |
550
|
0
|
|
|
|
|
|
$to_max = max $to_max , vwidth $to; |
551
|
0
|
|
|
|
|
|
push @show, [ $i, $p, $hash ]; |
552
|
|
|
|
|
|
|
} |
553
|
0
|
|
|
|
|
|
push @show_list, [ $dict => \@show ]; |
554
|
|
|
|
|
|
|
} |
555
|
0
|
0
|
|
|
|
|
if ($opt_show_numbers) { |
556
|
1
|
|
|
1
|
|
8
|
no warnings 'uninitialized'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
684
|
|
557
|
|
|
|
|
|
|
printf "HIT_PATTERN=%d/%d NG=%d, OK=%d, TOTAL=%d\n", |
558
|
|
|
|
|
|
|
$stat{hit}, $stat{total}, |
559
|
0
|
|
|
|
|
|
$stat{ng}, $stat{ok}, $stat{ng} + $stat{ok}; |
560
|
|
|
|
|
|
|
} |
561
|
0
|
|
|
|
|
|
for my $show_list (@show_list) { |
562
|
0
|
|
|
|
|
|
my($dict, $show) = @{$show_list}; |
|
0
|
|
|
|
|
|
|
563
|
0
|
0
|
|
|
|
|
next if @$show == 0; |
564
|
0
|
|
|
|
|
|
my $dict_format = ">>> %s <<<\n"; |
565
|
0
|
0
|
|
|
|
|
if ($opt_stat_item{dict}) { |
566
|
0
|
|
|
|
|
|
print colorize('000/L24E', sprintf($dict_format, $dict->NAME)); |
567
|
|
|
|
|
|
|
} |
568
|
0
|
|
|
|
|
|
for my $item (@$show) { |
569
|
0
|
|
|
|
|
|
my($i, $p, $hash) = @$item; |
570
|
0
|
0
|
|
|
|
|
if ($p->is_comment) { |
571
|
0
|
0
|
|
|
|
|
say $p->comment if $opt_show_comment; |
572
|
0
|
|
|
|
|
|
next; |
573
|
|
|
|
|
|
|
} |
574
|
0
|
|
0
|
|
|
|
my($from_re, $to) = ($p->string, $p->correct // ''); |
575
|
0
|
|
|
|
|
|
my @keys = keys %{$hash}; |
|
0
|
|
|
|
|
|
|
576
|
0
|
0
|
|
|
|
|
if ($opt_stat_style eq 'dict') { |
577
|
0
|
|
0
|
|
|
|
vprintf("%-${from_max}s // %s", $from_re // '', $to // ''); |
|
|
|
0
|
|
|
|
|
578
|
|
|
|
|
|
|
} else { |
579
|
0
|
|
|
|
|
|
my @ng = sort { $hash->{$b} <=> $hash->{$a} } grep { $_ ne $to } @keys |
|
0
|
|
|
|
|
|
|
580
|
0
|
0
|
|
|
|
|
if $opt_stat_item{ng}; |
581
|
0
|
|
|
|
|
|
my @ok = grep { $_ eq $to } @keys |
582
|
0
|
0
|
|
|
|
|
if $opt_stat_item{ok}; |
583
|
0
|
0
|
0
|
|
|
|
vprintf("%${from_max}s => ", $from_re // '') if $opt_stat_item{match}; |
584
|
0
|
0
|
0
|
|
|
|
vprintf("%-${to_max}s", $to // '') if $opt_stat_item{expect}; |
585
|
0
|
0
|
|
|
|
|
vprintf(" %4d:", $i + 1) if $opt_stat_item{number}; |
586
|
0
|
|
|
|
|
|
for my $key (@ng, @ok) { |
587
|
0
|
0
|
|
|
|
|
my $index = $key eq $to ? $i * 2 + 1 : $i * 2; |
588
|
|
|
|
|
|
|
printf(" %s(%s)", |
589
|
|
|
|
|
|
|
main::index_color($index, $key), |
590
|
0
|
0
|
|
|
|
|
colorize($key eq $to ? 'DB' : 'DR', $hash->{$key}) |
591
|
|
|
|
|
|
|
); |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
} |
594
|
0
|
|
|
|
|
|
print "\n"; |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
} |
597
|
0
|
|
|
|
|
|
$_ = ""; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
1
|
|
|
1
|
|
493
|
use App::Greple::Regions qw(match_regions merge_regions filter_regions); |
|
1
|
|
|
|
|
2557
|
|
|
1
|
|
|
|
|
887
|
|
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
sub subst_search { |
603
|
0
|
|
|
0
|
0
|
|
my $text = $_; |
604
|
0
|
|
|
|
|
|
my %arg = @_; |
605
|
0
|
0
|
|
|
|
|
$current_file = delete $arg{&FILELABEL} or die; |
606
|
|
|
|
|
|
|
|
607
|
0
|
|
|
|
|
|
my @matched; |
608
|
0
|
|
|
|
|
|
my $index = -1; |
609
|
0
|
|
|
|
|
|
my @effective; |
610
|
0
|
|
|
|
|
|
my $ng = {ng=>1, any=>1, all=>1, none=>1}->{$opt_check} ; |
611
|
0
|
|
|
|
|
|
my $ok = { ok=>1, any=>1, all=>1, none=>1}->{$opt_check} ; |
612
|
0
|
|
|
|
|
|
my $outstand = $opt_check eq 'outstand'; |
613
|
0
|
|
|
|
|
|
for my $dict (@dicts) { |
614
|
0
|
|
|
|
|
|
for my $p ($dict->words) { |
615
|
0
|
|
|
|
|
|
$index++; |
616
|
0
|
|
0
|
|
|
|
$p // next; |
617
|
0
|
0
|
|
|
|
|
next if $p->is_comment; |
618
|
0
|
|
0
|
|
|
|
my($from_re, $to) = ($p->string, $p->correct // ''); |
619
|
0
|
|
|
|
|
|
my @match = match_regions pattern => $p->regex; |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
## |
622
|
|
|
|
|
|
|
## Remove all overlapped matches. |
623
|
|
|
|
|
|
|
## |
624
|
0
|
|
|
|
|
|
my($in, $over, $out, $im, $om) = filter_regions \@match, \@matched; |
625
|
0
|
|
|
|
|
|
@match = @$out; |
626
|
0
|
|
|
|
|
|
for my $warn ( |
627
|
|
|
|
|
|
|
[ "Include", $in, $im, $opt_warn_include ], |
628
|
|
|
|
|
|
|
[ "Overlap", $over, $om, $opt_warn_overlap ], |
629
|
|
|
|
|
|
|
) { |
630
|
0
|
|
|
|
|
|
my($kind, $list, $match, $show) = @$warn; |
631
|
0
|
0
|
0
|
|
|
|
$show and @$list or next; |
632
|
0
|
|
|
|
|
|
for my $i (0 .. @$list - 1) { |
633
|
0
|
|
|
|
|
|
my($a, $b) = ($list->[$i], $match->[$i]); |
634
|
0
|
|
|
|
|
|
warn sprintf("%s \"%s\" with \"%s\" by #%d /%s/ in %s at %d\n", |
635
|
|
|
|
|
|
|
$kind, |
636
|
|
|
|
|
|
|
substr($_, $a->[0], $a->[1] - $a->[0]), |
637
|
|
|
|
|
|
|
substr($_, $b->[0], $b->[1] - $b->[0]), |
638
|
|
|
|
|
|
|
$index + 1, $p->string, |
639
|
|
|
|
|
|
|
$current_file, |
640
|
|
|
|
|
|
|
$a->[0], |
641
|
|
|
|
|
|
|
); |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
0
|
|
|
|
|
|
$stat{total}++; |
646
|
0
|
0
|
|
|
|
|
$stat{hit}++ if @match; |
647
|
0
|
0
|
0
|
|
|
|
next if @match == 0 and $opt_check ne 'all'; |
648
|
|
|
|
|
|
|
|
649
|
0
|
|
0
|
|
|
|
my $hash = $match_list[$index] //= {}; |
650
|
|
|
|
|
|
|
my $callback = sub { |
651
|
0
|
|
|
0
|
|
|
my($ms, $me, $i, $matched) = @_; |
652
|
0
|
0
|
|
|
|
|
$stat{$i % 2 ? 'ok' : 'ng'}++; |
653
|
0
|
|
|
|
|
|
my $s = $matched =~ s/$ignorechar_re//gr; |
654
|
0
|
|
|
|
|
|
$hash->{$s}++; |
655
|
0
|
|
|
|
|
|
my $format = @opt_format[ $i % @opt_format ]; |
656
|
0
|
0
|
0
|
|
|
|
sprintf($format, |
657
|
|
|
|
|
|
|
($opt_subst && $to ne '' && $s ne $to) ? |
658
|
|
|
|
|
|
|
$to : $matched); |
659
|
0
|
|
|
|
|
|
}; |
660
|
0
|
|
|
|
|
|
my(@ok, @ng); |
661
|
0
|
|
|
|
|
|
for (@match) { |
662
|
0
|
|
|
|
|
|
my $matched = substr $text, $_->[0], $_->[1] - $_->[0]; |
663
|
0
|
0
|
|
|
|
|
if ($matched =~ s/$ignorechar_re//gr ne $to) { |
664
|
0
|
|
|
|
|
|
$_->[2] = $index * 2; |
665
|
0
|
|
|
|
|
|
push @ng, $_; |
666
|
|
|
|
|
|
|
} else { |
667
|
0
|
|
|
|
|
|
$_->[2] = $index * 2 + 1; |
668
|
0
|
|
|
|
|
|
push @ok, $_; |
669
|
|
|
|
|
|
|
} |
670
|
0
|
|
|
|
|
|
$_->[3] = $callback; |
671
|
|
|
|
|
|
|
} |
672
|
0
|
0
|
0
|
|
|
|
$effective[ $index * 2 ] = 1 if $ng || ( @ng && $outstand ); |
|
|
|
0
|
|
|
|
|
673
|
0
|
0
|
0
|
|
|
|
$effective[ $index * 2 + 1 ] = 1 if $ok || ( @ng && $outstand ); |
|
|
|
0
|
|
|
|
|
674
|
|
|
|
|
|
|
|
675
|
0
|
|
|
|
|
|
@matched = merge_regions { nojoin => 1 }, @matched, @match; |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
## |
679
|
|
|
|
|
|
|
## --select |
680
|
|
|
|
|
|
|
## |
681
|
0
|
0
|
|
|
|
|
if (my $select = $opt_subst_select) { |
682
|
0
|
|
|
|
|
|
my $max = sum map { int $_->words } @dicts; |
|
0
|
|
|
|
|
|
|
683
|
1
|
|
|
1
|
|
8
|
use Getopt::EX::Numbers; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
392
|
|
684
|
0
|
|
|
|
|
|
my $numbers = Getopt::EX::Numbers->new(min => 1, max => $max); |
685
|
0
|
|
|
|
|
|
my @select; |
686
|
0
|
|
|
|
|
|
for (my @select_index = do { |
687
|
0
|
|
|
|
|
|
map { $_ * 2, $_ * 2 + 1 } |
688
|
0
|
|
|
|
|
|
map { $_ - 1 } |
689
|
0
|
|
|
|
|
|
grep { $_ <= $max } |
690
|
0
|
|
|
|
|
|
map { $numbers->parse($_)->sequence } |
|
0
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
split /,/, $select; |
692
|
|
|
|
|
|
|
}) { |
693
|
0
|
|
|
|
|
|
$select[$_] = 1; |
694
|
|
|
|
|
|
|
} |
695
|
0
|
|
|
|
|
|
@matched = grep $select[$_->[2]], @matched; |
696
|
|
|
|
|
|
|
} |
697
|
0
|
|
|
|
|
|
grep $effective[$_->[2]], @matched; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
my $divert_buffer; |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
sub subst_divert { |
703
|
0
|
|
|
0
|
0
|
|
my %arg = @_; |
704
|
0
|
|
|
|
|
|
my $filename = delete $arg{&FILELABEL}; |
705
|
|
|
|
|
|
|
|
706
|
0
|
|
|
|
|
|
$divert_buffer = ''; |
707
|
0
|
|
|
|
|
|
divert_stdout(\$divert_buffer); |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
1; |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
__DATA__ |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
builtin dict=s @opt_dictfile |
715
|
|
|
|
|
|
|
builtin dictdata=s @opt_dictdata |
716
|
|
|
|
|
|
|
builtin stat-style=s $opt_stat_style |
717
|
|
|
|
|
|
|
builtin stat-item=s @opt_stat_item |
718
|
|
|
|
|
|
|
builtin printdict! $opt_printdict |
719
|
|
|
|
|
|
|
builtin dictname! $opt_dictname |
720
|
|
|
|
|
|
|
builtin subst-format=s @opt_format |
721
|
|
|
|
|
|
|
builtin subst! $opt_subst |
722
|
|
|
|
|
|
|
builtin check=s $opt_check |
723
|
|
|
|
|
|
|
builtin select=s $opt_subst_select |
724
|
|
|
|
|
|
|
builtin linefold! $opt_linefold |
725
|
|
|
|
|
|
|
builtin remember! $remember_data |
726
|
|
|
|
|
|
|
builtin warn-overlap! $opt_warn_overlap |
727
|
|
|
|
|
|
|
builtin warn-include! $opt_warn_include |
728
|
|
|
|
|
|
|
builtin ignore-space! $opt_ignore_space |
729
|
|
|
|
|
|
|
builtin show-comment! $opt_show_comment |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
option default \ |
732
|
|
|
|
|
|
|
-Mtermcolor::bg(default=100,light=--subst-color-light,dark=--subst-color-dark) \ |
733
|
|
|
|
|
|
|
--prologue subst_initialize \ |
734
|
|
|
|
|
|
|
--begin subst_begin \ |
735
|
|
|
|
|
|
|
--le +&subst_search --no-regioncolor |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
## |
738
|
|
|
|
|
|
|
## Now these options are implemented by -Mupdate module |
739
|
|
|
|
|
|
|
## --diffcmd, -U are built-in options |
740
|
|
|
|
|
|
|
## |
741
|
|
|
|
|
|
|
autoload -Mupdate --update::diff --update::create --update::update |
742
|
|
|
|
|
|
|
option --diff --subst --update::diff |
743
|
|
|
|
|
|
|
option --create --subst --update::create |
744
|
|
|
|
|
|
|
option --replace --subst --update::update --with-backup |
745
|
|
|
|
|
|
|
option --overwrite --subst --update::update |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
option --divert-stdout --prologue __PACKAGE__::divert_stdout \ |
748
|
|
|
|
|
|
|
--epilogue __PACKAGE__::recover_stdout |
749
|
|
|
|
|
|
|
option --with-stat --epilogue subst_show_stat |
750
|
|
|
|
|
|
|
option --stat --divert-stdout --with-stat |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
autoload -Msubst::dyncmap --dyncmap |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
help --subst-color-light light terminal color |
755
|
|
|
|
|
|
|
option --subst-color-light --colormap --dyncmap \ |
756
|
|
|
|
|
|
|
range=0-2,except=000:111:222,shift=3,even="555D/%s",odd="IU;000/%s" |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
help --subst-color-dark dark terminal color |
759
|
|
|
|
|
|
|
option --subst-color-dark --colormap --dyncmap \ |
760
|
|
|
|
|
|
|
range=2-4,except=222:333:444,shift=1,even="D;L01/%s",odd="IU;%s/L01" |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
## |
763
|
|
|
|
|
|
|
## Handle included sample dictionaries. |
764
|
|
|
|
|
|
|
## |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
option --exdict --dict $ENV{GREPLE_SUBST_DICT}/$<shift> |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
option --exdictdir --prologue 'sub{ say "$ENV{GREPLE_SUBST_DICT}"; exit }' |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
option --jtca-katakana-guide --exdict jtca-katakana-guide-3.dict |
771
|
|
|
|
|
|
|
option --jtf-style-guide --exdict jtf-style-guide-3.dict |
772
|
|
|
|
|
|
|
option --ms-style-guide --exdict ms-style-guide.dict |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
option --sccc2 --exdict sccc2.dict |
775
|
|
|
|
|
|
|
option --jtca --exdict jtca.dict |
776
|
|
|
|
|
|
|
option --jtf --exdict jtf.dict |
777
|
|
|
|
|
|
|
option --microsoft --exdict ms-amend.dict --exdict ms-style-guide.dict |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
# deprecated. don't use. |
780
|
|
|
|
|
|
|
option --ms --microsoft |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
option --all-sample-dict --jtf --jtca --microsoft |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
option --all-katakana --exdict all-katakana.dict |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
option --dumpdict --printdict --prologue 'sub{exit}' |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# LocalWords: subst Greple greple ng ok outstand linefold dict diff |
789
|
|
|
|
|
|
|
# LocalWords: regex Kazumasa Utashiro |