@@ -5,61 +5,14 @@ use std::path::PathBuf;
55use colored:: * ;
66
77mod cmd_line;
8+ mod module;
89
9- // Load the AsciiDoc templates at build time
10- const ASSEMBLY_TEMPLATE : & str = include_str ! ( "../templates/assembly.adoc" ) ;
11- const CONCEPT_TEMPLATE : & str = include_str ! ( "../templates/concept.adoc" ) ;
12- const PROCEDURE_TEMPLATE : & str = include_str ! ( "../templates/procedure.adoc" ) ;
13- const REFERENCE_TEMPLATE : & str = include_str ! ( "../templates/reference.adoc" ) ;
10+ use module:: { Module , ModuleType } ;
1411
15- /// All possible types of the AsciiDoc module
16- #[ derive( Debug ) ]
17- enum ModuleType {
18- Assembly ,
19- Concept ,
20- Procedure ,
21- Reference ,
22- }
23-
24- /// A representation of the module with all its metadata and the generated AsciiDoc content
25- #[ derive( Debug ) ]
26- struct Module {
27- mod_type : ModuleType ,
28- title : String ,
29- id : String ,
30- file_name : String ,
31- include_statement : String ,
32- text : String ,
33- }
34-
35- impl Module {
36- /// The constructor for the Module struct
37- pub fn new (
38- mod_type : ModuleType ,
39- title : & str ,
40- includes : Option < & [ String ] > ,
41- options : & Options ,
42- ) -> Module {
43- let title = String :: from ( title) ;
44- let id = Module :: convert_title_to_id ( & title) ;
45- let file_name = Module :: compose_file_name ( & id, & mod_type, & options) ;
46- let include_statement = Module :: compose_include_statement ( & file_name) ;
47- let text = Module :: compose_text ( & title, & id, & mod_type, includes, & options) ;
48-
49- Module {
50- mod_type,
51- title,
52- id,
53- file_name,
54- include_statement,
55- text,
56- }
57- }
58- }
5912
6013/// This struct stores options based on the command-line arguments,
6114/// and is passed to various functions across the program.
62- struct Options {
15+ pub struct Options {
6316 comments : bool ,
6417 prefixes : bool ,
6518 target_dir : String ,
@@ -149,171 +102,6 @@ fn process_module_type(titles: clap::Values, module_type_str: &str, options: &Op
149102 modules_from_type
150103}
151104
152- impl Module {
153- /// Create an ID string that is derived from the human-readable title. The ID is usable as:
154- ///
155- /// * An AsciiDoc section ID
156- /// * A DocBook section ID
157- /// * A file name
158- ///
159- /// ## Examples
160- ///
161- /// ```
162- /// let title = "Testing newdoc";
163- /// assert_eq!(String::from("testing-newdoc"), Module::convert_title_to_id(title));
164- /// ```
165- fn convert_title_to_id ( title : & str ) -> String {
166- // The ID is all lower-case
167- let mut title_with_replacements = String :: from ( title) . to_lowercase ( ) ;
168-
169- // Replace characters that aren't allowed in the ID, usually with a dash or an empty string
170- let substitutions = [
171- ( " " , "-" ) ,
172- ( "(" , "" ) ,
173- ( ")" , "" ) ,
174- ( "?" , "" ) ,
175- ( "!" , "" ) ,
176- ( "'" , "" ) ,
177- ( "\" " , "" ) ,
178- ( "#" , "" ) ,
179- ( "%" , "" ) ,
180- ( "&" , "" ) ,
181- ( "*" , "" ) ,
182- ( "," , "" ) ,
183- ( "." , "-" ) ,
184- ( "/" , "-" ) ,
185- ( ":" , "-" ) ,
186- ( ";" , "" ) ,
187- ( "@" , "-at-" ) ,
188- ( "\\ " , "" ) ,
189- ( "`" , "" ) ,
190- ( "$" , "" ) ,
191- ( "^" , "" ) ,
192- ( "|" , "" ) ,
193- // Remove known semantic markup from the ID:
194- ( "[package]" , "" ) ,
195- ( "[option]" , "" ) ,
196- ( "[parameter]" , "" ) ,
197- ( "[variable]" , "" ) ,
198- ( "[command]" , "" ) ,
199- ( "[replaceable]" , "" ) ,
200- ( "[filename]" , "" ) ,
201- ( "[literal]" , "" ) ,
202- ( "[systemitem]" , "" ) ,
203- ( "[application]" , "" ) ,
204- ( "[function]" , "" ) ,
205- ( "[gui]" , "" ) ,
206- // Remove square brackets only after semantic markup:
207- ( "[" , "" ) ,
208- ( "]" , "" ) ,
209- // TODO: Curly braces shouldn't appear in the title in the first place.
210- // They'd be interpreted as attributes there.
211- // Print an error in that case? Escape them with AciiDoc escapes?
212- ( "{" , "" ) ,
213- ( "}" , "" ) ,
214- ] ;
215-
216- // Perform all the defined replacements on the title
217- for ( old, new) in substitutions. iter ( ) {
218- title_with_replacements = title_with_replacements. replace ( old, new) ;
219- }
220-
221- // Make sure the converted ID doesn't contain double dashes ("--"), because
222- // that breaks references to the ID
223- while title_with_replacements. contains ( "--" ) {
224- title_with_replacements = title_with_replacements. replace ( "--" , "-" ) ;
225- }
226-
227- title_with_replacements
228- }
229-
230- /// Perform string replacements in the modular template that matches the `ModuleType`.
231- /// Return the template text with all replacements.
232- fn compose_text (
233- title : & str ,
234- module_id : & str ,
235- module_type : & ModuleType ,
236- includes : Option < & [ String ] > ,
237- options : & Options ,
238- ) -> String {
239- // TODO: Add a comment in the generated file with a pre-filled include statement
240-
241- // Pick the right template
242- let current_template = match module_type {
243- ModuleType :: Assembly => ASSEMBLY_TEMPLATE ,
244- ModuleType :: Concept => CONCEPT_TEMPLATE ,
245- ModuleType :: Procedure => PROCEDURE_TEMPLATE ,
246- ModuleType :: Reference => REFERENCE_TEMPLATE ,
247- } ;
248-
249- // Define the strings that will be replaced in the template
250- let replacements = [ ( "${module_title}" , title) , ( "${module_id}" , module_id) ] ;
251-
252- // Perform substitutions in the template
253- // TODO: Create a separate function to perform a replacement
254- let mut template_with_replacements = String :: from ( current_template) ;
255-
256- for ( old, new) in replacements. iter ( ) {
257- template_with_replacements = template_with_replacements. replace ( old, new) ;
258- }
259-
260- if let Some ( includes) = includes {
261- // The includes should never be empty thanks to the required group in clap
262- assert ! ( !includes. is_empty( ) ) ;
263- // Join the includes into a block of text, with blank lines in between to prevent
264- // the AsciiDoc syntax to blend between modules
265- let includes_text = includes. join ( "\n \n " ) ;
266-
267- template_with_replacements =
268- template_with_replacements. replace ( "${include_statements}" , & includes_text) ;
269- } else {
270- template_with_replacements = template_with_replacements
271- . replace ( "${include_statements}" , "Include modules here." ) ;
272- }
273-
274- // If comments are disabled via an option, delete comment lines from the content
275- // TODO: This doesn't handle AsciiDoc comment blocks at all
276- if !options. comments {
277- // Filter out comment lines in an iterator
278- let lines = template_with_replacements
279- . lines ( )
280- . filter ( |line| !line. starts_with ( "//" ) ) ;
281- // Connect the iterator back into a String, connecting with newlines
282- template_with_replacements = lines. collect :: < Vec < & str > > ( ) . join ( "\n " ) ;
283- // Add a final newline at the end of the file
284- template_with_replacements. push ( '\n' ) ;
285- }
286-
287- template_with_replacements
288- }
289-
290- /// Prepare the file name for the generated file.
291- ///
292- /// The file name is based on the module ID, with the `.adoc` extension and an optional prefix.
293- fn compose_file_name ( module_id : & str , module_type : & ModuleType , options : & Options ) -> String {
294- let prefix = if options. prefixes {
295- // If prefixes are enabled, pick the right file prefix
296- match module_type {
297- ModuleType :: Assembly => "assembly_" ,
298- ModuleType :: Concept => "con_" ,
299- ModuleType :: Procedure => "proc_" ,
300- ModuleType :: Reference => "ref_" ,
301- }
302- } else {
303- // If prefixes are disabled, use an empty string for the prefix
304- ""
305- } ;
306-
307- let suffix = ".adoc" ;
308-
309- [ prefix, module_id, suffix] . join ( "" )
310- }
311-
312- /// Prepare an include statement that can be used to include the generated file from elsewhere.
313- fn compose_include_statement ( file_name : & str ) -> String {
314- format ! ( "include::<path>/{}[leveloffset=+1]" , file_name)
315- }
316- }
317105
318106/// Write the generated module content to the path specified in `options` with the set file name.
319107// fn write_module(file_name: &str, content: &str, options: &Options) {
@@ -367,3 +155,4 @@ fn write_module(module: &Module, options: &Options) {
367155 }
368156 }
369157}
158+
0 commit comments