gitignore_template_generator/config/
impls.rs1use std::{ffi::OsString, process::exit};
2
3use clap::{CommandFactory, Parser};
4
5use crate::{
6 config::{Args, ArgsParser},
7 constant,
8 http_client::{ErrorKind, ProgramError},
9};
10
11pub struct DefaultArgsParser;
12
13impl DefaultArgsParser {
14 fn parse_global_options(args: &Args) -> Option<ProgramError> {
15 if args.show_help {
16 let mut cmd = Args::command();
17 let rendered_help = cmd.render_help();
18 Some(ProgramError {
19 message: rendered_help.to_string().trim_end().to_string(),
20 exit_status: constant::exit_status::SUCCESS,
21 styled_message: Some(
22 rendered_help.ansi().to_string().trim_end().to_string(),
23 ),
24 error_kind: Some(ErrorKind::HelpInfos),
25 })
26 } else if args.show_version {
27 let cmd = Args::command();
28 let message = match cmd.get_version() {
29 Some(version) => {
30 format!("{} {version}", env!("CARGO_PKG_NAME"))
31 }
32 None => constant::error_messages::VERSION_INFOS_NOT_AVAILABLE
33 .to_string(),
34 };
35
36 Some(ProgramError {
37 message,
38 exit_status: constant::exit_status::SUCCESS,
39 styled_message: None,
40 error_kind: Some(ErrorKind::VersionInfos),
41 })
42 } else if args.show_author {
43 let cmd = Args::command();
44 let message = String::from(match cmd.get_author() {
45 Some(author) => author,
46 None => constant::error_messages::AUTHOR_INFOS_NOT_AVAILABLE,
47 });
48
49 Some(ProgramError {
50 message,
51 exit_status: constant::exit_status::SUCCESS,
52 styled_message: None,
53 error_kind: Some(ErrorKind::AuthorInfos),
54 })
55 } else {
56 None
57 }
58 }
59
60 fn print_error_message(error: &ProgramError, message: &str) {
61 if let Some(kind) = &error.error_kind {
62 match kind {
63 ErrorKind::VersionInfos
64 | ErrorKind::HelpInfos
65 | ErrorKind::AuthorInfos => println!("{message}"),
66 ErrorKind::Other => eprintln!("{message}"),
67 }
68 } else {
69 eprintln!("{message}");
70 }
71 }
72}
73
74impl ArgsParser for DefaultArgsParser {
75 fn parse(args: impl IntoIterator<Item = OsString>) -> Args {
76 match DefaultArgsParser::try_parse(args) {
77 Ok(parsed_args) => parsed_args,
78 Err(error) => {
79 if let Some(value) = &error.styled_message {
80 Self::print_error_message(&error, value);
81 } else {
82 Self::print_error_message(&error, &error.message);
83 }
84
85 exit(error.exit_status);
86 }
87 }
88 }
89
90 fn try_parse(
91 args: impl IntoIterator<Item = OsString>,
92 ) -> Result<Args, ProgramError> {
93 match Args::try_parse_from(args) {
94 Ok(parsed_args) => match Self::parse_global_options(&parsed_args) {
95 Some(error) => Err(error),
96 None => Ok(parsed_args),
97 },
98 Err(error) => Err(ProgramError {
99 message: format!(
100 "{}\nFor more information, try '--help'.",
101 error.render()
102 ),
103 exit_status: error.exit_code(),
104 styled_message: Some(format!(
105 "{}\nFor more information, try '\u{1b}[1m--help\u{1b}[0m'.",
106 error.render().ansi()
107 )),
108 error_kind: Some(ErrorKind::Other),
109 }),
110 }
111 }
112}