@@ -15,14 +15,12 @@ use std::fs::File;
15
15
use std:: io:: { stdin, stdout, BufRead , BufReader , BufWriter , Read , Write } ;
16
16
use std:: num:: ParseIntError ;
17
17
use uucore:: display:: Quotable ;
18
- use uucore:: error:: { FromIo , UError , UResult } ;
18
+ use uucore:: error:: { FromIo , UError , UResult , UUsageError } ;
19
19
use uucore:: { format_usage, help_about, help_usage} ;
20
20
21
21
const USAGE : & str = help_usage ! ( "ptx.md" ) ;
22
22
const ABOUT : & str = help_about ! ( "ptx.md" ) ;
23
23
24
- const REGEX_CHARCLASS : & str = "^-]\\ " ;
25
-
26
24
#[ derive( Debug ) ]
27
25
enum OutFormat {
28
26
Dumb ,
@@ -71,8 +69,12 @@ fn read_word_filter_file(
71
69
. get_one :: < String > ( option)
72
70
. expect ( "parsing options failed!" )
73
71
. to_string ( ) ;
74
- let file = File :: open ( filename) ?;
75
- let reader = BufReader :: new ( file) ;
72
+ let reader: BufReader < Box < dyn Read > > = BufReader :: new ( if filename == "-" {
73
+ Box :: new ( stdin ( ) )
74
+ } else {
75
+ let file = File :: open ( filename) ?;
76
+ Box :: new ( file)
77
+ } ) ;
76
78
let mut words: HashSet < String > = HashSet :: new ( ) ;
77
79
for word in reader. lines ( ) {
78
80
words. insert ( word?) ;
@@ -88,7 +90,12 @@ fn read_char_filter_file(
88
90
let filename = matches
89
91
. get_one :: < String > ( option)
90
92
. expect ( "parsing options failed!" ) ;
91
- let mut reader = File :: open ( filename) ?;
93
+ let mut reader: Box < dyn Read > = if filename == "-" {
94
+ Box :: new ( stdin ( ) )
95
+ } else {
96
+ let file = File :: open ( filename) ?;
97
+ Box :: new ( file)
98
+ } ;
92
99
let mut buffer = String :: new ( ) ;
93
100
reader. read_to_string ( & mut buffer) ?;
94
101
Ok ( buffer. chars ( ) . collect ( ) )
@@ -155,18 +162,10 @@ impl WordFilter {
155
162
let reg = match arg_reg {
156
163
Some ( arg_reg) => arg_reg,
157
164
None => {
158
- if break_set . is_some ( ) {
165
+ if let Some ( break_set ) = break_set {
159
166
format ! (
160
167
"[^{}]+" ,
161
- break_set
162
- . unwrap( )
163
- . into_iter( )
164
- . map( |c| if REGEX_CHARCLASS . contains( c) {
165
- format!( "\\ {c}" )
166
- } else {
167
- c. to_string( )
168
- } )
169
- . collect:: <String >( )
168
+ regex:: escape( & break_set. into_iter( ) . collect:: <String >( ) )
170
169
)
171
170
} else if config. gnu_ext {
172
171
"\\ w+" . to_owned ( )
@@ -260,10 +259,17 @@ fn get_config(matches: &clap::ArgMatches) -> UResult<Config> {
260
259
. parse ( )
261
260
. map_err ( PtxError :: ParseError ) ?;
262
261
}
263
- if matches. get_flag ( options:: FORMAT_ROFF ) {
262
+ if let Some ( format) = matches. get_one :: < String > ( options:: FORMAT ) {
263
+ config. format = match format. as_str ( ) {
264
+ "roff" => OutFormat :: Roff ,
265
+ "tex" => OutFormat :: Tex ,
266
+ _ => unreachable ! ( "should be caught by clap" ) ,
267
+ } ;
268
+ }
269
+ if matches. get_flag ( options:: format:: ROFF ) {
264
270
config. format = OutFormat :: Roff ;
265
271
}
266
- if matches. get_flag ( options:: FORMAT_TEX ) {
272
+ if matches. get_flag ( options:: format :: TEX ) {
267
273
config. format = OutFormat :: Tex ;
268
274
}
269
275
Ok ( config)
@@ -277,20 +283,10 @@ struct FileContent {
277
283
278
284
type FileMap = HashMap < String , FileContent > ;
279
285
280
- fn read_input ( input_files : & [ String ] , config : & Config ) -> std:: io:: Result < FileMap > {
286
+ fn read_input ( input_files : & [ String ] ) -> std:: io:: Result < FileMap > {
281
287
let mut file_map: FileMap = HashMap :: new ( ) ;
282
- let mut files = Vec :: new ( ) ;
283
- if input_files. is_empty ( ) {
284
- files. push ( "-" ) ;
285
- } else if config. gnu_ext {
286
- for file in input_files {
287
- files. push ( file) ;
288
- }
289
- } else {
290
- files. push ( & input_files[ 0 ] ) ;
291
- }
292
288
let mut offset: usize = 0 ;
293
- for filename in files {
289
+ for filename in input_files {
294
290
let reader: BufReader < Box < dyn Read > > = BufReader :: new ( if filename == "-" {
295
291
Box :: new ( stdin ( ) )
296
292
} else {
@@ -344,7 +340,7 @@ fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) ->
344
340
continue ;
345
341
}
346
342
if config. ignore_case {
347
- word = word. to_lowercase ( ) ;
343
+ word = word. to_uppercase ( ) ;
348
344
}
349
345
word_set. insert ( WordRef {
350
346
word,
@@ -693,15 +689,19 @@ fn write_traditional_output(
693
689
}
694
690
695
691
mod options {
692
+ pub mod format {
693
+ pub static ROFF : & str = "roff" ;
694
+ pub static TEX : & str = "tex" ;
695
+ }
696
+
696
697
pub static FILE : & str = "file" ;
697
698
pub static AUTO_REFERENCE : & str = "auto-reference" ;
698
699
pub static TRADITIONAL : & str = "traditional" ;
699
700
pub static FLAG_TRUNCATION : & str = "flag-truncation" ;
700
701
pub static MACRO_NAME : & str = "macro-name" ;
701
- pub static FORMAT_ROFF : & str = "format=roff " ;
702
+ pub static FORMAT : & str = "format" ;
702
703
pub static RIGHT_SIDE_REFS : & str = "right-side-refs" ;
703
704
pub static SENTENCE_REGEXP : & str = "sentence-regexp" ;
704
- pub static FORMAT_TEX : & str = "format=tex" ;
705
705
pub static WORD_REGEXP : & str = "word-regexp" ;
706
706
pub static BREAK_FILE : & str = "break-file" ;
707
707
pub static IGNORE_CASE : & str = "ignore-case" ;
@@ -715,21 +715,40 @@ mod options {
715
715
#[ uucore:: main]
716
716
pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
717
717
let matches = uu_app ( ) . try_get_matches_from ( args) ?;
718
+ let config = get_config ( & matches) ?;
718
719
719
- let mut input_files: Vec < String > = match & matches. get_many :: < String > ( options:: FILE ) {
720
- Some ( v) => v. clone ( ) . cloned ( ) . collect ( ) ,
721
- None => vec ! [ "-" . to_string( ) ] ,
722
- } ;
720
+ let input_files;
721
+ let output_file;
722
+
723
+ let mut files = matches
724
+ . get_many :: < String > ( options:: FILE )
725
+ . into_iter ( )
726
+ . flatten ( )
727
+ . cloned ( ) ;
728
+
729
+ if !config. gnu_ext {
730
+ input_files = vec ! [ files. next( ) . unwrap_or( "-" . to_string( ) ) ] ;
731
+ output_file = files. next ( ) . unwrap_or ( "-" . to_string ( ) ) ;
732
+ if let Some ( file) = files. next ( ) {
733
+ return Err ( UUsageError :: new (
734
+ 1 ,
735
+ format ! ( "extra operand {}" , file. quote( ) ) ,
736
+ ) ) ;
737
+ }
738
+ } else {
739
+ input_files = {
740
+ let mut files = files. collect :: < Vec < _ > > ( ) ;
741
+ if files. is_empty ( ) {
742
+ files. push ( "-" . to_string ( ) ) ;
743
+ }
744
+ files
745
+ } ;
746
+ output_file = "-" . to_string ( ) ;
747
+ }
723
748
724
- let config = get_config ( & matches) ?;
725
749
let word_filter = WordFilter :: new ( & matches, & config) ?;
726
- let file_map = read_input ( & input_files, & config ) . map_err_context ( String :: new) ?;
750
+ let file_map = read_input ( & input_files) . map_err_context ( String :: new) ?;
727
751
let word_set = create_word_set ( & config, & word_filter, & file_map) ;
728
- let output_file = if !config. gnu_ext && input_files. len ( ) == 2 {
729
- input_files. pop ( ) . unwrap ( )
730
- } else {
731
- "-" . to_string ( )
732
- } ;
733
752
write_traditional_output ( & config, & file_map, & word_set, & output_file)
734
753
}
735
754
@@ -774,10 +793,24 @@ pub fn uu_app() -> Command {
774
793
. value_name ( "STRING" ) ,
775
794
)
776
795
. arg (
777
- Arg :: new ( options:: FORMAT_ROFF )
796
+ Arg :: new ( options:: FORMAT )
797
+ . long ( options:: FORMAT )
798
+ . hide ( true )
799
+ . value_parser ( [ "roff" , "tex" ] )
800
+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] ) ,
801
+ )
802
+ . arg (
803
+ Arg :: new ( options:: format:: ROFF )
778
804
. short ( 'O' )
779
- . long ( options:: FORMAT_ROFF )
780
805
. help ( "generate output as roff directives" )
806
+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] )
807
+ . action ( ArgAction :: SetTrue ) ,
808
+ )
809
+ . arg (
810
+ Arg :: new ( options:: format:: TEX )
811
+ . short ( 'T' )
812
+ . help ( "generate output as TeX directives" )
813
+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] )
781
814
. action ( ArgAction :: SetTrue ) ,
782
815
)
783
816
. arg (
@@ -794,13 +827,6 @@ pub fn uu_app() -> Command {
794
827
. help ( "for end of lines or end of sentences" )
795
828
. value_name ( "REGEXP" ) ,
796
829
)
797
- . arg (
798
- Arg :: new ( options:: FORMAT_TEX )
799
- . short ( 'T' )
800
- . long ( options:: FORMAT_TEX )
801
- . help ( "generate output as TeX directives" )
802
- . action ( ArgAction :: SetTrue ) ,
803
- )
804
830
. arg (
805
831
Arg :: new ( options:: WORD_REGEXP )
806
832
. short ( 'W' )
0 commit comments