]> git.huck.website - metaforge.git/blob - src/options.rs
0b021e74d0e4a7979ee9b9531d3f72ff8d5fea15
[metaforge.git] / src / options.rs
1 use clap::Parser;
2 use eyre::Result;
3 use std::path::PathBuf;
4
5 #[derive(Parser, Debug)]
6 #[command(author = "huck boles")]
7 #[command(version = "0.1.3")]
8 #[command(about = "customizable template driven static site generator")]
9 #[command(long_about = None)]
10 pub struct Opts {
11 /// root directory [current_dir]
12 #[arg(short, long, value_name = "ROOT_DIR")]
13 pub root: Option<String>,
14 /// source file directory [current_dir/source]
15 #[arg(short, long, value_name = "SOURCE_DIR")]
16 pub source: Option<String>,
17 /// build directory [current_dir/build]
18 #[arg(short, long, value_name = "BUILD_DIR")]
19 pub build: Option<String>,
20 /// pattern directory [current_dir/pattern]
21 #[arg(short, long, value_name = "PATTERN_DIR")]
22 pub pattern: Option<String>,
23 /// builds a single file and outputs on stdout
24 #[arg(short, long, value_name = "FILENAME")]
25 pub file: Option<String>,
26 /// output filetype [html]
27 #[arg(short, long, value_name = "OUTPUT_FILETYPE")]
28 pub output: Option<String>,
29 /// input filetype [markdown]
30 #[arg(short, long, value_name = "INPUT_FILETYPE")]
31 pub input: Option<String>,
32 /// enable extra output. repeated flags give more info
33 #[arg(short, long, action = clap::ArgAction::Count)]
34 pub verbose: u8,
35 /// minimal output [false]
36 #[arg(short, long, default_value_t = false)]
37 pub quiet: bool,
38 /// enable parallel processing [false]
39 #[arg(short = 'l', long, default_value_t = false)]
40 pub parallel: bool,
41 /// create a new skeleton directory [false]
42 #[arg(long, default_value_t = false)]
43 pub new: bool,
44 /// clean build directory before building site [false]
45 #[arg(long, default_value_t = false)]
46 pub clean: bool,
47 /// don't stop on file failure [false]
48 #[arg(long, default_value_t = false)]
49 pub force: bool,
50 /// stop on undefined variables and arrays [false]
51 #[arg(long, default_value_t = false)]
52 pub undefined: bool,
53 /// don't call pandoc on source files
54 #[arg(long, default_value_t = false)]
55 pub no_pandoc: bool,
56 /// don't minify resulting html
57 #[arg(long, default_value_t = false)]
58 pub no_minify: bool,
59 }
60
61 #[derive(Debug, Clone, Default)]
62 pub struct Options {
63 pub root: PathBuf,
64 pub source: PathBuf,
65 pub build: PathBuf,
66 pub pattern: PathBuf,
67 pub file: Option<PathBuf>,
68 pub input: String,
69 pub output: String,
70 pub verbose: u8,
71 pub parallel: bool,
72 pub quiet: bool,
73 pub force: bool,
74 pub undefined: bool,
75 pub clean: bool,
76 pub no_pandoc: bool,
77 pub new: bool,
78 pub minify: bool,
79 }
80
81 impl Options {
82 pub fn new() -> Self {
83 Self {
84 root: PathBuf::new(),
85 source: PathBuf::new(),
86 build: PathBuf::new(),
87 pattern: PathBuf::new(),
88 file: None,
89 input: String::default(),
90 output: String::default(),
91 verbose: 0,
92 parallel: false,
93 quiet: false,
94 force: false,
95 undefined: false,
96 clean: false,
97 no_pandoc: false,
98 new: false,
99 minify: true,
100 }
101 }
102 }
103
104 impl TryFrom<crate::Opts> for Options {
105 type Error = eyre::Error;
106 fn try_from(value: crate::Opts) -> Result<Self, Self::Error> {
107 let mut opts = Options::new();
108
109 opts.verbose = value.verbose;
110 opts.quiet = value.quiet;
111 opts.force = value.force;
112 opts.undefined = value.undefined;
113 opts.clean = value.clean;
114 opts.no_pandoc = value.no_pandoc;
115 opts.new = value.new;
116 opts.parallel = value.parallel;
117 opts.minify = !value.no_minify;
118
119 opts.root = if let Some(root) = value.root.as_deref() {
120 PathBuf::from(root).canonicalize()
121 } else {
122 std::env::current_dir()
123 }?;
124
125 opts.source = if let Some(source) = value.source.as_deref() {
126 PathBuf::from(source).canonicalize()
127 } else {
128 Ok(opts.root.join("source"))
129 }?;
130
131 opts.build = if let Some(build) = value.build.as_deref() {
132 PathBuf::from(build).canonicalize()
133 } else {
134 Ok(opts.root.join("build"))
135 }?;
136
137 opts.pattern = if let Some(pattern) = value.pattern.as_deref() {
138 PathBuf::from(pattern).canonicalize()
139 } else {
140 Ok(opts.root.join("pattern"))
141 }?;
142
143 if let Some(file) = value.file.as_deref() {
144 opts.file = Some(PathBuf::from(file).canonicalize()?);
145 }
146
147 opts.input = if let Some(input) = value.input {
148 input
149 } else {
150 String::from("html")
151 };
152
153 opts.output = if let Some(output) = value.output {
154 output
155 } else {
156 String::from("markdown")
157 };
158
159 Ok(opts)
160 }
161 }