irongit

A rust macro that allows regular expression creation through independent files. Allows fully typed named groups.

400 lines7.8 KBMarkdown
1# regex_macro
2
3Allows for named groups in regular expressions to be generated from special files ending in `.re`.
4
5---
6
7## Usage
8
9### Initialization
10
11- Call the `load_regex_files!` macro on the directory that contains regex files.
12- Each file is loaded with the `m` and `x` flags
13 - `m` (multiline): `^` and `$` match the start and end of lines, not just the entire input.
14 - `x` (extended): allows whitespace and comments starting with `#` inside the regex.
15
16### Each regex file is a structure with 4 main implementations
17
181. `from_str(text: &str)` Finds a single match within the given string.
192. `from_file(filename: &str)` Finds a single match after opening the given filename.
203. `vec_from_str(text: &str)` Extracts all the matches in a given string.
214. `vec_from_file(filename: &str)` Extracts all the matches after opening the given filename.
22
23The abstract structure for matches within the regex_macro library contains `start_pos`, `end_pos`, and public fields for each named group inside of the `.re` file. Each field then contains a `start_pos`, `end_pos`, and `val` field.
24
25### Tips
26
27- Use struct style naming convention for `.re` files. i.e. `Event.re` rather than `event.re`
28
29### Benefits
30
31- Files load automatically into precompiled code with macros which allows rust-analyzer to use provide type hints.
32- Regular expressions can be split over multiple lines and use comments to improve readability for regular expressions.
33
34---
35
36## The events example
37
38### event.rs
39
40```rust
41use regex_macro::load_regex_files;
42
43fn main() {
44 load_regex_files!("tests/regex");
45 let events = Event::vec_from_file("tests/samples/events.txt").unwrap();
46 println!("{}", serde_json::to_string_pretty(&events).unwrap());
47}
48```
49
50### events.txt
51
52```text
53๐Ÿง  Focused Dev + Growth Schedule
54
55Time Activity
567:30โ€“8:00 AM Wake up + hydrate + light stretch
578:00โ€“8:45 AM Gym (weights or intervals)
589:00โ€“9:30 AM Breakfast + cooldown + planning
599:30โ€“12:00PM Deep coding (core project)
6012:00โ€“12:45PM Lunch + decompress
6112:45โ€“2:30PM Coding or meetings if needed
622:30โ€“3:00 PM Break or walk
633:00โ€“5:00 PM Learning block (Rust, AI, etc)
645:00โ€“6:00 PM Chill / side project / cleanup
656:00โ€“7:00 PM Dinner + relax
667:00โ€“9:00 PM Optional: build/test/hack ideas
679:00โ€“10:00 PM Wind down (read, steam room, etc)
6810:00โ€“10:30PM Journal + sleep prep
69```
70
71### Event.re
72
73```text
74(?<start>\d{1,2}:\d{1,2})
75.
76(?<end>\d{1,2}:\d{1,2})
77\s{0,2}
78(?<ampm>[AMPM]{2})
79.
80(?<activity>.+)
81```
82
83### Parsed items
84
85```json
86[
87 {
88 "start_pos": 50,
89 "end_pos": 98,
90 "start": {
91 "start_pos": 50,
92 "end_pos": 54,
93 "val": "7:30"
94 },
95 "end": {
96 "start_pos": 57,
97 "end_pos": 61,
98 "val": "8:00"
99 },
100 "ampm": {
101 "start_pos": 62,
102 "end_pos": 64,
103 "val": "AM"
104 },
105 "activity": {
106 "start_pos": 65,
107 "end_pos": 98,
108 "val": "Wake up + hydrate + light stretch"
109 }
110 },
111 {
112 "start_pos": 99,
113 "end_pos": 140,
114 "start": {
115 "start_pos": 99,
116 "end_pos": 103,
117 "val": "8:00"
118 },
119 "end": {
120 "start_pos": 106,
121 "end_pos": 110,
122 "val": "8:45"
123 },
124 "ampm": {
125 "start_pos": 111,
126 "end_pos": 113,
127 "val": "AM"
128 },
129 "activity": {
130 "start_pos": 114,
131 "end_pos": 140,
132 "val": "Gym (weights or intervals)"
133 }
134 },
135 {
136 "start_pos": 141,
137 "end_pos": 187,
138 "start": {
139 "start_pos": 141,
140 "end_pos": 145,
141 "val": "9:00"
142 },
143 "end": {
144 "start_pos": 148,
145 "end_pos": 152,
146 "val": "9:30"
147 },
148 "ampm": {
149 "start_pos": 153,
150 "end_pos": 155,
151 "val": "AM"
152 },
153 "activity": {
154 "start_pos": 156,
155 "end_pos": 187,
156 "val": "Breakfast + cooldown + planning"
157 }
158 },
159 {
160 "start_pos": 188,
161 "end_pos": 229,
162 "start": {
163 "start_pos": 188,
164 "end_pos": 192,
165 "val": "9:30"
166 },
167 "end": {
168 "start_pos": 195,
169 "end_pos": 200,
170 "val": "12:00"
171 },
172 "ampm": {
173 "start_pos": 200,
174 "end_pos": 202,
175 "val": "PM"
176 },
177 "activity": {
178 "start_pos": 203,
179 "end_pos": 229,
180 "val": "Deep coding (core project)"
181 }
182 },
183 {
184 "start_pos": 230,
185 "end_pos": 264,
186 "start": {
187 "start_pos": 230,
188 "end_pos": 235,
189 "val": "12:00"
190 },
191 "end": {
192 "start_pos": 238,
193 "end_pos": 243,
194 "val": "12:45"
195 },
196 "ampm": {
197 "start_pos": 243,
198 "end_pos": 245,
199 "val": "PM"
200 },
201 "activity": {
202 "start_pos": 246,
203 "end_pos": 264,
204 "val": "Lunch + decompress"
205 }
206 },
207 {
208 "start_pos": 265,
209 "end_pos": 308,
210 "start": {
211 "start_pos": 265,
212 "end_pos": 270,
213 "val": "12:45"
214 },
215 "end": {
216 "start_pos": 273,
217 "end_pos": 277,
218 "val": "2:30"
219 },
220 "ampm": {
221 "start_pos": 277,
222 "end_pos": 279,
223 "val": "PM"
224 },
225 "activity": {
226 "start_pos": 280,
227 "end_pos": 308,
228 "val": "Coding or meetings if needed"
229 }
230 },
231 {
232 "start_pos": 309,
233 "end_pos": 337,
234 "start": {
235 "start_pos": 309,
236 "end_pos": 313,
237 "val": "2:30"
238 },
239 "end": {
240 "start_pos": 316,
241 "end_pos": 320,
242 "val": "3:00"
243 },
244 "ampm": {
245 "start_pos": 321,
246 "end_pos": 323,
247 "val": "PM"
248 },
249 "activity": {
250 "start_pos": 324,
251 "end_pos": 337,
252 "val": "Break or walk"
253 }
254 },
255 {
256 "start_pos": 338,
257 "end_pos": 383,
258 "start": {
259 "start_pos": 338,
260 "end_pos": 342,
261 "val": "3:00"
262 },
263 "end": {
264 "start_pos": 345,
265 "end_pos": 349,
266 "val": "5:00"
267 },
268 "ampm": {
269 "start_pos": 350,
270 "end_pos": 352,
271 "val": "PM"
272 },
273 "activity": {
274 "start_pos": 353,
275 "end_pos": 383,
276 "val": "Learning block (Rust, AI, etc)"
277 }
278 },
279 {
280 "start_pos": 384,
281 "end_pos": 429,
282 "start": {
283 "start_pos": 384,
284 "end_pos": 388,
285 "val": "5:00"
286 },
287 "end": {
288 "start_pos": 391,
289 "end_pos": 395,
290 "val": "6:00"
291 },
292 "ampm": {
293 "start_pos": 396,
294 "end_pos": 398,
295 "val": "PM"
296 },
297 "activity": {
298 "start_pos": 399,
299 "end_pos": 429,
300 "val": "Chill / side project / cleanup"
301 }
302 },
303 {
304 "start_pos": 430,
305 "end_pos": 459,
306 "start": {
307 "start_pos": 430,
308 "end_pos": 434,
309 "val": "6:00"
310 },
311 "end": {
312 "start_pos": 437,
313 "end_pos": 441,
314 "val": "7:00"
315 },
316 "ampm": {
317 "start_pos": 442,
318 "end_pos": 444,
319 "val": "PM"
320 },
321 "activity": {
322 "start_pos": 445,
323 "end_pos": 459,
324 "val": "Dinner + relax"
325 }
326 },
327 {
328 "start_pos": 460,
329 "end_pos": 506,
330 "start": {
331 "start_pos": 460,
332 "end_pos": 464,
333 "val": "7:00"
334 },
335 "end": {
336 "start_pos": 467,
337 "end_pos": 471,
338 "val": "9:00"
339 },
340 "ampm": {
341 "start_pos": 472,
342 "end_pos": 474,
343 "val": "PM"
344 },
345 "activity": {
346 "start_pos": 475,
347 "end_pos": 506,
348 "val": "Optional: build/test/hack ideas"
349 }
350 },
351 {
352 "start_pos": 507,
353 "end_pos": 556,
354 "start": {
355 "start_pos": 507,
356 "end_pos": 511,
357 "val": "9:00"
358 },
359 "end": {
360 "start_pos": 514,
361 "end_pos": 519,
362 "val": "10:00"
363 },
364 "ampm": {
365 "start_pos": 520,
366 "end_pos": 522,
367 "val": "PM"
368 },
369 "activity": {
370 "start_pos": 523,
371 "end_pos": 556,
372 "val": "Wind down (read, steam room, etc)"
373 }
374 },
375 {
376 "start_pos": 557,
377 "end_pos": 593,
378 "start": {
379 "start_pos": 557,
380 "end_pos": 562,
381 "val": "10:00"
382 },
383 "end": {
384 "start_pos": 565,
385 "end_pos": 570,
386 "val": "10:30"
387 },
388 "ampm": {
389 "start_pos": 570,
390 "end_pos": 572,
391 "val": "PM"
392 },
393 "activity": {
394 "start_pos": 573,
395 "end_pos": 593,
396 "val": "Journal + sleep prep"
397 }
398 }
399]
400```