@@ -15,14 +15,12 @@ use std::fs::File;
1515use std:: io:: { stdin, stdout, BufRead , BufReader , BufWriter , Read , Write } ;
1616use std:: num:: ParseIntError ;
1717use uucore:: display:: Quotable ;
18- use uucore:: error:: { FromIo , UError , UResult } ;
18+ use uucore:: error:: { FromIo , UError , UResult , UUsageError } ;
1919use uucore:: { format_usage, help_about, help_usage} ;
2020
2121const USAGE : & str = help_usage ! ( "ptx.md" ) ;
2222const ABOUT : & str = help_about ! ( "ptx.md" ) ;
2323
24- const REGEX_CHARCLASS : & str = "^-]\\ " ;
25-
2624#[ derive( Debug ) ]
2725enum OutFormat {
2826 Dumb ,
@@ -71,8 +69,12 @@ fn read_word_filter_file(
7169 . get_one :: < String > ( option)
7270 . expect ( "parsing options failed!" )
7371 . 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+ } ) ;
7678 let mut words: HashSet < String > = HashSet :: new ( ) ;
7779 for word in reader. lines ( ) {
7880 words. insert ( word?) ;
@@ -88,7 +90,12 @@ fn read_char_filter_file(
8890 let filename = matches
8991 . get_one :: < String > ( option)
9092 . 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+ } ;
9299 let mut buffer = String :: new ( ) ;
93100 reader. read_to_string ( & mut buffer) ?;
94101 Ok ( buffer. chars ( ) . collect ( ) )
@@ -155,18 +162,10 @@ impl WordFilter {
155162 let reg = match arg_reg {
156163 Some ( arg_reg) => arg_reg,
157164 None => {
158- if break_set . is_some ( ) {
165+ if let Some ( break_set ) = break_set {
159166 format ! (
160167 "[^{}]+" ,
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 >( ) )
170169 )
171170 } else if config. gnu_ext {
172171 "\\ w+" . to_owned ( )
@@ -260,10 +259,17 @@ fn get_config(matches: &clap::ArgMatches) -> UResult<Config> {
260259 . parse ( )
261260 . map_err ( PtxError :: ParseError ) ?;
262261 }
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 ) {
264270 config. format = OutFormat :: Roff ;
265271 }
266- if matches. get_flag ( options:: FORMAT_TEX ) {
272+ if matches. get_flag ( options:: format :: TEX ) {
267273 config. format = OutFormat :: Tex ;
268274 }
269275 Ok ( config)
@@ -277,20 +283,10 @@ struct FileContent {
277283
278284type FileMap = HashMap < String , FileContent > ;
279285
280- fn read_input ( input_files : & [ String ] , config : & Config ) -> std:: io:: Result < FileMap > {
286+ fn read_input ( input_files : & [ String ] ) -> std:: io:: Result < FileMap > {
281287 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- }
292288 let mut offset: usize = 0 ;
293- for filename in files {
289+ for filename in input_files {
294290 let reader: BufReader < Box < dyn Read > > = BufReader :: new ( if filename == "-" {
295291 Box :: new ( stdin ( ) )
296292 } else {
@@ -344,7 +340,7 @@ fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) ->
344340 continue ;
345341 }
346342 if config. ignore_case {
347- word = word. to_lowercase ( ) ;
343+ word = word. to_uppercase ( ) ;
348344 }
349345 word_set. insert ( WordRef {
350346 word,
@@ -693,15 +689,19 @@ fn write_traditional_output(
693689}
694690
695691mod options {
692+ pub mod format {
693+ pub static ROFF : & str = "roff" ;
694+ pub static TEX : & str = "tex" ;
695+ }
696+
696697 pub static FILE : & str = "file" ;
697698 pub static AUTO_REFERENCE : & str = "auto-reference" ;
698699 pub static TRADITIONAL : & str = "traditional" ;
699700 pub static FLAG_TRUNCATION : & str = "flag-truncation" ;
700701 pub static MACRO_NAME : & str = "macro-name" ;
701- pub static FORMAT_ROFF : & str = "format=roff " ;
702+ pub static FORMAT : & str = "format" ;
702703 pub static RIGHT_SIDE_REFS : & str = "right-side-refs" ;
703704 pub static SENTENCE_REGEXP : & str = "sentence-regexp" ;
704- pub static FORMAT_TEX : & str = "format=tex" ;
705705 pub static WORD_REGEXP : & str = "word-regexp" ;
706706 pub static BREAK_FILE : & str = "break-file" ;
707707 pub static IGNORE_CASE : & str = "ignore-case" ;
@@ -715,21 +715,40 @@ mod options {
715715#[ uucore:: main]
716716pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
717717 let matches = uu_app ( ) . try_get_matches_from ( args) ?;
718+ let config = get_config ( & matches) ?;
718719
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+ }
723748
724- let config = get_config ( & matches) ?;
725749 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) ?;
727751 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- } ;
733752 write_traditional_output ( & config, & file_map, & word_set, & output_file)
734753}
735754
@@ -774,10 +793,24 @@ pub fn uu_app() -> Command {
774793 . value_name ( "STRING" ) ,
775794 )
776795 . 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 )
778804 . short ( 'O' )
779- . long ( options:: FORMAT_ROFF )
780805 . 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 ] )
781814 . action ( ArgAction :: SetTrue ) ,
782815 )
783816 . arg (
@@ -794,13 +827,6 @@ pub fn uu_app() -> Command {
794827 . help ( "for end of lines or end of sentences" )
795828 . value_name ( "REGEXP" ) ,
796829 )
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- )
804830 . arg (
805831 Arg :: new ( options:: WORD_REGEXP )
806832 . short ( 'W' )
0 commit comments