@@ -61,7 +61,11 @@ fn gen_coreutils_app<T: Args>(util_map: &UtilityMap<T>) -> clap::Command {
6161}
6262
6363/// Generate the manpage for the utility in the first parameter
64- fn gen_manpage < T : Args > ( args : impl Iterator < Item = OsString > , util_map : & UtilityMap < T > ) -> ! {
64+ fn gen_manpage < T : Args > (
65+ tldr : & mut Option < ZipArchive < File > > ,
66+ args : impl Iterator < Item = OsString > ,
67+ util_map : & UtilityMap < T > ,
68+ ) -> ! {
6569 let all_utilities = validation:: get_all_utilities ( util_map) ;
6670
6771 let matches = Command :: new ( "manpage" )
@@ -78,7 +82,13 @@ fn gen_manpage<T: Args>(args: impl Iterator<Item = OsString>, util_map: &Utility
7882 gen_coreutils_app ( util_map)
7983 } else {
8084 validation:: setup_localization_or_exit ( utility) ;
81- util_map. get ( utility) . unwrap ( ) . 1 ( )
85+ let mut cmd = util_map. get ( utility) . unwrap ( ) . 1 ( ) ;
86+ if let Some ( zip) = tldr {
87+ if let Ok ( examples) = write_zip_examples ( zip, utility, false ) {
88+ cmd = cmd. after_help ( examples) ;
89+ }
90+ }
91+ cmd
8292 } ;
8393
8494 let man = Man :: new ( command) ;
@@ -122,19 +132,41 @@ fn gen_completions<T: Args>(args: impl Iterator<Item = OsString>, util_map: &Uti
122132 process:: exit ( 0 ) ;
123133}
124134
135+ /// print tldr error
136+ fn print_tldr_error ( ) {
137+ eprintln ! ( "Warning: No tldr archive found, so the documentation will not include examples." ) ;
138+ eprintln ! (
139+ "To include examples in the documentation, download the tldr archive and put it in the docs/ folder."
140+ ) ;
141+ eprintln ! ( ) ;
142+ eprintln ! ( " curl https://tldr.sh/assets/tldr.zip -o docs/tldr.zip" ) ;
143+ eprintln ! ( ) ;
144+ }
145+
125146/// # Errors
126147/// Returns an error if the writer fails.
127148#[ allow( clippy:: too_many_lines) ]
128149fn main ( ) -> io:: Result < ( ) > {
129150 let args: Vec < OsString > = uucore:: args_os_filtered ( ) . collect ( ) ;
130151
152+ let mut tldr_zip = File :: open ( "docs/tldr.zip" )
153+ . ok ( )
154+ . and_then ( |f| ZipArchive :: new ( f) . ok ( ) ) ;
155+
131156 // Check for manpage/completion commands first
132157 if args. len ( ) > 1 {
133158 let command = args. get ( 1 ) . and_then ( |s| s. to_str ( ) ) . unwrap_or_default ( ) ;
134159 match command {
135160 "manpage" => {
136161 let args_iter = args. into_iter ( ) . skip ( 2 ) ;
137- gen_manpage ( args_iter, & util_map :: < Box < dyn Iterator < Item = OsString > > > ( ) ) ;
162+ if tldr_zip. is_none ( ) {
163+ print_tldr_error ( ) ;
164+ }
165+ gen_manpage (
166+ & mut tldr_zip,
167+ args_iter,
168+ & util_map :: < Box < dyn Iterator < Item = OsString > > > ( ) ,
169+ ) ;
138170 }
139171 "completion" => {
140172 let args_iter = args. into_iter ( ) . skip ( 2 ) ;
@@ -151,20 +183,9 @@ fn main() -> io::Result<()> {
151183 }
152184 }
153185 }
154- let mut tldr_zip = File :: open ( "docs/tldr.zip" )
155- . ok ( )
156- . and_then ( |f| ZipArchive :: new ( f) . ok ( ) ) ;
157-
158186 if tldr_zip. is_none ( ) {
159- println ! ( "Warning: No tldr archive found, so the documentation will not include examples." ) ;
160- println ! (
161- "To include examples in the documentation, download the tldr archive and put it in the docs/ folder."
162- ) ;
163- println ! ( ) ;
164- println ! ( " curl https://tldr.sh/assets/tldr.zip -o docs/tldr.zip" ) ;
165- println ! ( ) ;
187+ print_tldr_error ( ) ;
166188 }
167-
168189 let utils = util_map :: < Box < dyn Iterator < Item = OsString > > > ( ) ;
169190 match std:: fs:: create_dir ( "docs/src/utils/" ) {
170191 Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: AlreadyExists => Ok ( ( ) ) ,
@@ -431,44 +452,9 @@ impl MDWriter<'_, '_> {
431452 /// Returns an error if the writer fails.
432453 fn examples ( & mut self ) -> io:: Result < ( ) > {
433454 if let Some ( zip) = self . tldr_zip {
434- let content = if let Some ( f) =
435- get_zip_content ( zip, & format ! ( "pages/common/{}.md" , self . name) )
436- {
437- f
438- } else if let Some ( f) = get_zip_content ( zip, & format ! ( "pages/linux/{}.md" , self . name) ) {
439- f
440- } else {
441- println ! (
442- "Warning: Could not find tldr examples for page '{}'" ,
443- self . name
444- ) ;
445- return Ok ( ( ) ) ;
446- } ;
447-
448- writeln ! ( self . w, "## Examples" ) ?;
449- writeln ! ( self . w) ?;
450- for line in content. lines ( ) . skip_while ( |l| !l. starts_with ( '-' ) ) {
451- if let Some ( l) = line. strip_prefix ( "- " ) {
452- writeln ! ( self . w, "{l}" ) ?;
453- } else if line. starts_with ( '`' ) {
454- writeln ! ( self . w, "```shell\n {}\n ```" , line. trim_matches( '`' ) ) ?;
455- } else if line. is_empty ( ) {
456- writeln ! ( self . w) ?;
457- } else {
458- println ! ( "Not sure what to do with this line:" ) ;
459- println ! ( "{line}" ) ;
460- }
455+ if let Ok ( examples) = write_zip_examples ( zip, self . name , true ) {
456+ writeln ! ( self . w, "{examples}" ) ?;
461457 }
462- writeln ! ( self . w) ?;
463- writeln ! (
464- self . w,
465- "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
466- ) ?;
467- writeln ! ( self . w, ">" ) ?;
468- writeln ! (
469- self . w,
470- "> Please note that, as uutils is a work in progress, some examples might fail."
471- ) ?;
472458 }
473459 Ok ( ( ) )
474460 }
@@ -548,3 +534,72 @@ fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Op
548534 archive. by_name ( name) . ok ( ) ?. read_to_string ( & mut s) . unwrap ( ) ;
549535 Some ( s)
550536}
537+
538+ /// Extract examples for tldr.zip. The file docs/tldr.zip must exists
539+ ///
540+ /// ```sh
541+ /// curl https://tldr.sh/assets/tldr.zip -o docs/tldr.zip
542+ /// ```
543+ ///
544+ /// # Errors
545+ ///
546+ /// Returns an error if the tldr.zip file cannot be opened or read
547+ fn write_zip_examples (
548+ archive : & mut ZipArchive < impl Read + Seek > ,
549+ name : & str ,
550+ output_markdown : bool ,
551+ ) -> io:: Result < String > {
552+ let content = if let Some ( f) = get_zip_content ( archive, & format ! ( "pages/common/{name}.md" ) ) {
553+ f
554+ } else if let Some ( f) = get_zip_content ( archive, & format ! ( "pages/linux/{name}.md" ) ) {
555+ f
556+ } else {
557+ return Err ( io:: Error :: new (
558+ io:: ErrorKind :: NotFound ,
559+ format ! ( "Could not find tldr examples for {name}" ) ,
560+ ) ) ;
561+ } ;
562+
563+ match format_examples ( content, output_markdown) {
564+ Err ( e) => Err ( std:: io:: Error :: other ( format ! (
565+ "Failed to format the tldr examples of {name}: {e}"
566+ ) ) ) ,
567+ Ok ( s) => Ok ( s) ,
568+ }
569+ }
570+
571+ /// Format examples using std::fmt::Write
572+ fn format_examples ( content : String , output_markdown : bool ) -> Result < String , std:: fmt:: Error > {
573+ use std:: fmt:: Write ;
574+ let mut s = String :: new ( ) ;
575+ writeln ! ( s) ?;
576+ writeln ! ( s, "Examples" ) ?;
577+ writeln ! ( s) ?;
578+ for line in content. lines ( ) . skip_while ( |l| !l. starts_with ( '-' ) ) {
579+ if let Some ( l) = line. strip_prefix ( "- " ) {
580+ writeln ! ( s, "{l}" ) ?;
581+ } else if line. starts_with ( '`' ) {
582+ if output_markdown {
583+ writeln ! ( s, "```shell\n {}\n ```" , line. trim_matches( '`' ) ) ?;
584+ } else {
585+ writeln ! ( s, "{}" , line. trim_matches( '`' ) ) ?;
586+ }
587+ } else if line. is_empty ( ) {
588+ writeln ! ( s) ?;
589+ } else {
590+ // println!("Not sure what to do with this line:");
591+ // println!("{line}");
592+ }
593+ }
594+ writeln ! ( s) ?;
595+ writeln ! (
596+ s,
597+ "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
598+ ) ?;
599+ writeln ! ( s, ">" ) ?;
600+ writeln ! (
601+ s,
602+ "> Please note that, as uutils is a work in progress, some examples might fail."
603+ ) ?;
604+ Ok ( s)
605+ }
0 commit comments