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 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}