code_generator/
setup.rs

1use std::fmt;
2
3#[derive(Clone, Copy, Debug)]
4
5pub enum IndentationStyle {
6    Allman,
7    GNU,
8    Whitesmiths,
9    KnR,
10    Ratliff,
11    Horstmann,
12    Pico,
13    Lisp,
14    None,
15}
16
17#[derive(Clone, Copy, Debug)]
18pub enum CaseType {
19    FlatCase,
20    ScreamingCase,
21    CamelCase,
22    PascalCase,
23    SnakeCase,
24    ScreamingSnakeCase,
25}
26
27#[derive(Copy, Clone)]
28pub enum IndentationType {
29    Spaces,
30    Tabs,
31}
32
33#[derive(Clone, Copy)]
34pub enum NewLineType {
35    Cr,
36    Nl,
37    CrNl,
38    None,
39}
40
41#[derive(Clone, Copy, Debug)]
42pub enum CodeStyle {
43    Allman,
44    GNU,
45    Whitesmiths,
46    KnR,
47    Ratliff,
48    Horstmann,
49    Pico,
50    Lisp,
51    Minimal,
52    Default,
53}
54
55#[derive(Copy, Clone, PartialEq)]
56pub enum GeneratorContext {
57    If,
58    While,
59    ForLoop,
60    Function,
61    File,
62    Struct,
63    Enum,
64    Other,
65}
66
67#[derive(Copy, Clone)]
68pub struct CaseTypes {
69    pub const_define_case: CaseType,
70    pub function_name_case: CaseType,
71    pub member_name_case: CaseType,
72    pub type_name_case: CaseType,
73    pub file_name_case: CaseType,
74    pub default_case: CaseType,
75}
76
77impl CaseTypes {
78    pub fn new() -> CaseTypes {
79        CaseTypes {
80            const_define_case: CaseType::ScreamingSnakeCase,
81            function_name_case: CaseType::SnakeCase,
82            member_name_case: CaseType::SnakeCase,
83            type_name_case: CaseType::PascalCase,
84            file_name_case: CaseType::PascalCase,
85            default_case: CaseType::SnakeCase
86        }
87    }
88
89    pub fn with_const_define(mut self, case_type: CaseType) -> Self {
90        self.const_define_case = case_type;
91        self
92    }
93
94    pub fn with_function_name(mut self, case_type: CaseType) -> Self {
95        self.function_name_case = case_type;
96        self
97    }
98
99    pub fn with_member_name(mut self, case_type: CaseType) -> Self {
100        self.member_name_case = case_type;
101        self
102    }
103
104    pub fn with_type_name(mut self, case_type: CaseType) -> Self {
105        self.type_name_case = case_type;
106        self
107    }
108
109    pub fn with_file_name(mut self, case_type: CaseType) -> Self {
110        self.file_name_case = case_type;
111        self
112    }
113
114    pub fn with_default(mut self, case_type: CaseType) -> Self {
115        self.default_case = case_type;
116        self
117    }
118}
119
120#[derive(Copy, Clone)]
121pub struct CodeGenerationInfo {
122    pub indent_level: usize,
123    pub indent_type:  IndentationType,
124    pub indent_amount: usize,
125    pub indent_style: IndentationStyle,
126    pub new_line_type: NewLineType,
127    pub context: GeneratorContext,
128    pub case_types: CaseTypes,
129}
130
131pub struct DisplayHandler<'a> {
132    generator: &'a dyn CodeGenerate,
133    info: CodeGenerationInfo,
134}
135
136impl<'a> DisplayHandler<'a> {
137    pub fn new(gen: &'a dyn CodeGenerate, info: CodeGenerationInfo) -> DisplayHandler<'a> {
138        DisplayHandler { generator: gen, info: info }
139    }
140}
141
142impl fmt::Display for DisplayHandler<'_> {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        self.generator.generate(f, self.info)
145    }
146}
147
148impl CodeGenerationInfo {
149    pub fn new() -> CodeGenerationInfo {
150        CodeGenerationInfo {
151            indent_level: 0,
152            indent_amount: 4,
153            indent_type: IndentationType::Spaces,
154            indent_style: IndentationStyle::Allman,
155            new_line_type: NewLineType::CrNl,
156            context: GeneratorContext::File,
157            case_types: CaseTypes::new(),
158        }
159    }
160
161    pub fn with_ident_style(mut self, style: IndentationStyle) -> Self {
162        self.indent_style = style;
163        self
164    }
165
166    pub fn with_ident_amount(mut self, amount: usize) -> Self {
167        self.indent_amount = amount;
168        self
169    }
170
171    pub fn with_indent_type(mut self, indent_type: IndentationType) -> Self {
172        self.indent_type = indent_type;
173        self
174    }
175
176    pub fn with_new_line_type(mut self, new_line_type: NewLineType) -> Self {
177        self.new_line_type = new_line_type;
178        self
179    }
180
181    pub fn with_case_types(mut self, case_types: CaseTypes) -> Self {
182        self.case_types = case_types;
183        self
184    }
185
186    pub fn from_style(code_style: CodeStyle) -> CodeGenerationInfo {
187        match code_style {
188            CodeStyle::Allman => CodeGenerationInfo {
189                indent_level: 0,
190                indent_amount: 4,
191                indent_type: IndentationType::Spaces,
192                indent_style: IndentationStyle::Allman,
193                new_line_type: NewLineType::CrNl,
194                context: GeneratorContext::File,
195                case_types: CaseTypes::new(),
196            },
197            CodeStyle::GNU => CodeGenerationInfo {
198                indent_level: 0,
199                indent_amount: 2,
200                indent_type: IndentationType::Spaces,
201                indent_style: IndentationStyle::GNU,
202                new_line_type: NewLineType::CrNl,
203                context: GeneratorContext::File,
204                case_types: CaseTypes::new(),
205            },
206            CodeStyle::Horstmann => CodeGenerationInfo {
207                indent_level: 0,
208                indent_amount: 4,
209                indent_type: IndentationType::Spaces,
210                indent_style: IndentationStyle::Horstmann,
211                new_line_type: NewLineType::CrNl,
212                context: GeneratorContext::File,
213                case_types: CaseTypes::new(),
214            },
215            CodeStyle::KnR => CodeGenerationInfo {
216                indent_level: 0,
217                indent_amount: 4,
218                indent_type: IndentationType::Spaces,
219                indent_style: IndentationStyle::KnR,
220                new_line_type: NewLineType::CrNl,
221                context: GeneratorContext::File,
222                case_types: CaseTypes::new(),
223            },
224            CodeStyle::Lisp => CodeGenerationInfo {
225                indent_level: 0,
226                indent_amount: 4,
227                indent_type: IndentationType::Spaces,
228                indent_style: IndentationStyle::Lisp,
229                new_line_type: NewLineType::CrNl,
230                context: GeneratorContext::File,
231                case_types: CaseTypes::new(),
232            },
233            CodeStyle::Minimal => CodeGenerationInfo {
234                indent_level: 0,
235                indent_amount: 0,
236                indent_type: IndentationType::Spaces,
237                indent_style: IndentationStyle::None,
238                new_line_type: NewLineType::None,
239                context: GeneratorContext::File,
240                case_types: CaseTypes::new(),
241            },
242            CodeStyle::Pico => CodeGenerationInfo {
243                indent_level: 0,
244                indent_amount: 4,
245                indent_type: IndentationType::Spaces,
246                indent_style: IndentationStyle::Pico,
247                new_line_type: NewLineType::CrNl,
248                context: GeneratorContext::File,
249                case_types: CaseTypes::new(),
250            },
251            CodeStyle::Ratliff => CodeGenerationInfo {
252                indent_level: 0,
253                indent_amount: 4,
254                indent_type: IndentationType::Spaces,
255                indent_style: IndentationStyle::Ratliff,
256                new_line_type: NewLineType::CrNl,
257                context: GeneratorContext::File,
258                case_types: CaseTypes::new(),
259            },
260            CodeStyle::Whitesmiths => CodeGenerationInfo {
261                indent_level: 0,
262                indent_amount: 4,
263                indent_type: IndentationType::Spaces,
264                indent_style: IndentationStyle::Whitesmiths,
265                new_line_type: NewLineType::CrNl,
266                context: GeneratorContext::File,
267                case_types: CaseTypes::new(),
268            },
269            CodeStyle::Default => CodeGenerationInfo {
270                indent_level: 0,
271                indent_amount: 4,
272                indent_type: IndentationType::Tabs,
273                indent_style: IndentationStyle::KnR,
274                new_line_type: NewLineType::CrNl,
275                context: GeneratorContext::File,
276                case_types: CaseTypes::new(),
277            },
278        }
279    }
280
281    pub fn indent(&self) -> CodeGenerationInfo {
282        let mut info = *self;
283        info.indent_level += 1;
284
285        info
286    }
287
288    pub fn with_context(&mut self, context: GeneratorContext) -> CodeGenerationInfo {
289        let mut info = *self;
290        info.context = context;
291
292        info
293    }
294
295    pub fn set_new_line_type(&mut self, new_line_type: NewLineType) {
296        self.new_line_type = new_line_type;
297    }
298}
299
300pub trait CodeGenerate {
301    /// Trait function which allows the generation of code with context
302    /// 
303    /// # Example Implementation
304    ///
305    /// ```
306    /// # use code_generator::CodeStyle;
307    /// # use code_generator::CodeGenerationInfo;
308    /// # use code_generator::Indentation;
309    /// # use code_generator::DisplayExt;
310    /// # use code_generator::CodeGenerate;
311    /// # use std::fmt;
312    /// #
313    /// struct Example {
314    ///     a: u32,
315    /// }
316    /// 
317    /// impl CodeGenerate for Example {
318    ///     fn generate(&self, f: &mut fmt::Formatter<'_>, info: CodeGenerationInfo) -> fmt::Result {
319    ///         write!(f, "{}", self.a)
320    ///     }
321    /// }
322    /// 
323    /// let example = Example {a: 69};
324    /// let info = CodeGenerationInfo::from_style(CodeStyle::KnR);
325    /// assert_eq!("69", format!("{}", example.display(info)));
326    /// ```
327    fn generate(&self, f: &mut fmt::Formatter<'_>, info: CodeGenerationInfo) -> fmt::Result;
328}
329
330impl<T: CodeGenerate> CodeGenerate for &T {
331    fn generate(&self, f: &mut fmt::Formatter<'_>, info: CodeGenerationInfo) -> fmt::Result {
332        (*self).generate(f, info)
333    }
334}
335
336pub trait DisplayExt {
337    fn display(self: &Self, info: CodeGenerationInfo) -> DisplayHandler;
338}
339
340impl<T> DisplayExt for T
341where T: CodeGenerate {
342    fn display(self: &Self, info: CodeGenerationInfo) -> DisplayHandler {
343        DisplayHandler::new(self, info)
344    }
345}