11use crate :: Options ;
22
33/// All possible types of the AsciiDoc module
4- #[ derive( Debug ) ]
4+ #[ derive( Debug , Clone ) ]
55pub enum ModuleType {
66 Assembly ,
77 Concept ,
88 Procedure ,
99 Reference ,
1010}
1111
12+ /// An initial representation of the module with input data, used to construct the `Module` struct
13+ #[ derive( Debug ) ]
14+ pub struct Input {
15+ mod_type : ModuleType ,
16+ title : String ,
17+ options : & ' static Options ,
18+ includes : Option < Vec < String > > ,
19+ }
20+
1221/// A representation of the module with all its metadata and the generated AsciiDoc content
1322#[ derive( Debug ) ]
1423pub struct Module {
@@ -17,7 +26,8 @@ pub struct Module {
1726 id : String ,
1827 pub file_name : String ,
1928 pub include_statement : String ,
20- included : Option < Vec < String > > ,
29+ includes : Option < Vec < String > > ,
30+ pub text : String ,
2131}
2232
2333// Load the AsciiDoc templates at build time
@@ -26,27 +36,22 @@ const CONCEPT_TEMPLATE: &str = include_str!("../templates/concept.adoc");
2636const PROCEDURE_TEMPLATE : & str = include_str ! ( "../templates/procedure.adoc" ) ;
2737const REFERENCE_TEMPLATE : & str = include_str ! ( "../templates/reference.adoc" ) ;
2838
29- impl Module {
30- /// The constructor for the Module struct
31- pub fn new ( mod_type : ModuleType , title : & str , options : & Options ) -> Module {
39+
40+ impl Input {
41+ pub fn new ( mod_type : ModuleType , title : & str , options : & ' static Options ) -> Input {
3242 let title = String :: from ( title) ;
33- let id = Module :: convert_title_to_id ( & title) ;
34- let file_name = Module :: compose_file_name ( & id, & mod_type, & options) ;
35- let include_statement = Module :: compose_include_statement ( & file_name) ;
3643
37- Module {
44+ Input {
3845 mod_type,
3946 title,
40- id,
41- file_name,
42- include_statement,
43- included : None ,
47+ options,
48+ includes : None ,
4449 }
4550 }
4651
4752 /// Set the optional include statements for files that this assembly includes
48- pub fn includes ( mut self , include_statements : Vec < String > ) -> Self {
49- self . included = Some ( include_statements) ;
53+ pub fn include ( mut self , include_statements : Vec < String > ) -> Self {
54+ self . includes = Some ( include_statements) ;
5055 self
5156 }
5257
@@ -55,14 +60,8 @@ impl Module {
5560 /// * An AsciiDoc section ID
5661 /// * A DocBook section ID
5762 /// * A file name
58- ///
59- /// ## Examples
60- ///
61- /// ```
62- /// let title = "Testing newdoc";
63- /// assert_eq!(String::from("testing-newdoc"), Module::convert_title_to_id(title));
64- /// ```
65- fn convert_title_to_id ( title : & str ) -> String {
63+ pub fn id ( & self ) -> String {
64+ let title = & self . title ;
6665 // The ID is all lower-case
6766 let mut title_with_replacements = String :: from ( title) . to_lowercase ( ) ;
6867
@@ -127,9 +126,36 @@ impl Module {
127126 title_with_replacements
128127 }
129128
129+ /// Prepare the file name for the generated file.
130+ ///
131+ /// The file name is based on the module ID, with the `.adoc` extension and an optional prefix.
132+ pub fn file_name ( & self ) -> String {
133+ let prefix = if self . options . prefixes {
134+ // If prefixes are enabled, pick the right file prefix
135+ match self . mod_type {
136+ ModuleType :: Assembly => "assembly_" ,
137+ ModuleType :: Concept => "con_" ,
138+ ModuleType :: Procedure => "proc_" ,
139+ ModuleType :: Reference => "ref_" ,
140+ }
141+ } else {
142+ // If prefixes are disabled, use an empty string for the prefix
143+ ""
144+ } ;
145+
146+ let suffix = ".adoc" ;
147+
148+ [ prefix, & self . id ( ) , suffix] . join ( "" )
149+ }
150+
151+ /// Prepare an include statement that can be used to include the generated file from elsewhere.
152+ fn include_statement ( & self ) -> String {
153+ format ! ( "include::<path>/{}[leveloffset=+1]" , & self . file_name( ) )
154+ }
155+
130156 /// Perform string replacements in the modular template that matches the `ModuleType`.
131157 /// Return the template text with all replacements.
132- pub fn compose_text ( & self , options : & Options ) -> String {
158+ pub fn text ( & self ) -> String {
133159 // TODO: Add a comment in the generated file with a pre-filled include statement
134160
135161 // Pick the right template
@@ -141,7 +167,7 @@ impl Module {
141167 } ;
142168
143169 // Define the strings that will be replaced in the template
144- let replacements = [ ( "${module_title}" , & self . title ) , ( "${module_id}" , & self . id ) ] ;
170+ let replacements = [ ( "${module_title}" , & self . title ) , ( "${module_id}" , & self . id ( ) ) ] ;
145171
146172 // Perform substitutions in the template
147173 // TODO: Create a separate function to perform a replacement
@@ -151,7 +177,7 @@ impl Module {
151177 template_with_replacements = template_with_replacements. replace ( old, new) ;
152178 }
153179
154- if let Some ( include_statements) = & self . included {
180+ if let Some ( include_statements) = & self . includes {
155181 // The includes should never be empty thanks to the required group in clap
156182 assert ! ( !include_statements. is_empty( ) ) ;
157183 // Join the includes into a block of text, with blank lines in between to prevent
@@ -167,7 +193,7 @@ impl Module {
167193
168194 // If comments are disabled via an option, delete comment lines from the content
169195 // TODO: This doesn't handle AsciiDoc comment blocks at all
170- if !options. comments {
196+ if !self . options . comments {
171197 // Filter out comment lines in an iterator
172198 let lines = template_with_replacements
173199 . lines ( )
@@ -180,31 +206,38 @@ impl Module {
180206
181207 template_with_replacements
182208 }
209+ }
183210
184- /// Prepare the file name for the generated file.
185- ///
186- /// The file name is based on the module ID, with the `.adoc` extension and an optional prefix.
187- fn compose_file_name ( module_id : & str , module_type : & ModuleType , options : & Options ) -> String {
188- let prefix = if options. prefixes {
189- // If prefixes are enabled, pick the right file prefix
190- match module_type {
191- ModuleType :: Assembly => "assembly_" ,
192- ModuleType :: Concept => "con_" ,
193- ModuleType :: Procedure => "proc_" ,
194- ModuleType :: Reference => "ref_" ,
195- }
196- } else {
197- // If prefixes are disabled, use an empty string for the prefix
198- ""
199- } ;
200211
201- let suffix = ".adoc" ;
212+ impl From < Input > for Module {
213+ fn from ( input : Input ) -> Self {
214+ // TODO: I suspect that these `clone` calls aren't really necessary, but I don't know Rust
215+ // well enough to figure out the proper solution now.
216+ let mod_type = input. mod_type . clone ( ) ;
217+ let title = input. title . clone ( ) ;
218+ let id = input. id ( ) . clone ( ) ;
219+ let file_name = input. file_name ( ) . clone ( ) ;
220+ let include_statement = input. include_statement ( ) ;
221+ let includes = input. includes . clone ( ) ;
222+ let text = input. text ( ) . clone ( ) ;
202223
203- [ prefix, module_id, suffix] . join ( "" )
224+ Module {
225+ mod_type,
226+ title,
227+ id,
228+ file_name,
229+ include_statement,
230+ includes,
231+ text,
232+ }
204233 }
234+ }
205235
206- /// Prepare an include statement that can be used to include the generated file from elsewhere.
207- fn compose_include_statement ( file_name : & str ) -> String {
208- format ! ( "include::<path>/{}[leveloffset=+1]" , file_name)
236+
237+ impl Module {
238+ /// The constructor for the Module struct
239+ pub fn new ( mod_type : ModuleType , title : & str , options : & ' static Options ) -> Module {
240+ let input = Input :: new ( mod_type, title, options) ;
241+ input. into ( )
209242 }
210243}
0 commit comments