@@ -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)
@@ -344,7 +350,7 @@ fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) ->
344350 continue ;
345351 }
346352 if config. ignore_case {
347- word = word. to_lowercase ( ) ;
353+ word = word. to_uppercase ( ) ;
348354 }
349355 word_set. insert ( WordRef {
350356 word,
@@ -693,15 +699,19 @@ fn write_traditional_output(
693699}
694700
695701mod options {
702+ pub mod format {
703+ pub static ROFF : & str = "roff" ;
704+ pub static TEX : & str = "tex" ;
705+ }
706+
696707 pub static FILE : & str = "file" ;
697708 pub static AUTO_REFERENCE : & str = "auto-reference" ;
698709 pub static TRADITIONAL : & str = "traditional" ;
699710 pub static FLAG_TRUNCATION : & str = "flag-truncation" ;
700711 pub static MACRO_NAME : & str = "macro-name" ;
701- pub static FORMAT_ROFF : & str = "format=roff " ;
712+ pub static FORMAT : & str = "format" ;
702713 pub static RIGHT_SIDE_REFS : & str = "right-side-refs" ;
703714 pub static SENTENCE_REGEXP : & str = "sentence-regexp" ;
704- pub static FORMAT_TEX : & str = "format=tex" ;
705715 pub static WORD_REGEXP : & str = "word-regexp" ;
706716 pub static BREAK_FILE : & str = "break-file" ;
707717 pub static IGNORE_CASE : & str = "ignore-case" ;
@@ -715,21 +725,34 @@ mod options {
715725#[ uucore:: main]
716726pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
717727 let matches = uu_app ( ) . try_get_matches_from ( args) ?;
728+ let config = get_config ( & matches) ?;
718729
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- } ;
730+ let input_files;
731+ let output_file;
732+
733+ let mut files = matches
734+ . get_many :: < String > ( options:: FILE )
735+ . into_iter ( )
736+ . flatten ( )
737+ . cloned ( ) ;
738+
739+ if !config. gnu_ext {
740+ input_files = vec ! [ files. next( ) . unwrap_or( "-" . to_string( ) ) ] ;
741+ output_file = files. next ( ) . unwrap_or ( "-" . to_string ( ) ) ;
742+ if let Some ( file) = files. next ( ) {
743+ return Err ( UUsageError :: new (
744+ 1 ,
745+ format ! ( "extra operand {}" , file. quote( ) ) ,
746+ ) ) ;
747+ }
748+ } else {
749+ input_files = files. collect :: < Vec < _ > > ( ) ;
750+ output_file = "-" . to_string ( ) ;
751+ }
723752
724- let config = get_config ( & matches) ?;
725753 let word_filter = WordFilter :: new ( & matches, & config) ?;
726754 let file_map = read_input ( & input_files, & config) . map_err_context ( String :: new) ?;
727755 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- } ;
733756 write_traditional_output ( & config, & file_map, & word_set, & output_file)
734757}
735758
@@ -774,10 +797,24 @@ pub fn uu_app() -> Command {
774797 . value_name ( "STRING" ) ,
775798 )
776799 . arg (
777- Arg :: new ( options:: FORMAT_ROFF )
800+ Arg :: new ( options:: FORMAT )
801+ . long ( options:: FORMAT )
802+ . hide ( true )
803+ . value_parser ( [ "roff" , "tex" ] )
804+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] ) ,
805+ )
806+ . arg (
807+ Arg :: new ( options:: format:: ROFF )
778808 . short ( 'O' )
779- . long ( options:: FORMAT_ROFF )
780809 . help ( "generate output as roff directives" )
810+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] )
811+ . action ( ArgAction :: SetTrue ) ,
812+ )
813+ . arg (
814+ Arg :: new ( options:: format:: TEX )
815+ . short ( 'T' )
816+ . help ( "generate output as TeX directives" )
817+ . overrides_with_all ( [ options:: FORMAT , options:: format:: ROFF , options:: format:: TEX ] )
781818 . action ( ArgAction :: SetTrue ) ,
782819 )
783820 . arg (
@@ -794,13 +831,6 @@ pub fn uu_app() -> Command {
794831 . help ( "for end of lines or end of sentences" )
795832 . value_name ( "REGEXP" ) ,
796833 )
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- )
804834 . arg (
805835 Arg :: new ( options:: WORD_REGEXP )
806836 . short ( 'W' )
0 commit comments