### TODOs
* [ ] Make undef line is deleted
Add new struct invoke\_context so that other macro definition can also contains
contexts.
* [ ] Failed macro stops further evlaution.
- Should it be a feature? or be fixed? I'm not even sure if it is a bug or not.
* [ ] Make syscmd call unsafe and allow only when sudo was given
* [-] Improve modularlity
Define is not basic macro but reserved macro for now, Change this into basic
macro for better readability and maintainability.
Though it has some benefits, I don't think it is necessary to refactor.
* [ ] Err redirection option
Should crate new function, because there is no such standard way to redirect error
* [ ] New basic macros
* [ ] Data macro from data
* [ ] Text format
* [ ] CSV macro
* [ ] csv query
* [ ] csv to markdown table
* [ ] csv to wikitext table
### How one should parse macro invocation?
While it is much easier to parse macro compared to other function definitions,
it is somewhat hard to do with stock libraries by itself since you have to
retain unparsed statements.
I'm thinking of multiple approaches but basic principle is to parse lines not a
whole file.
1. Get file buffer or stdin buffer
2. Iterate by lines
3. Check if line include macro invocation
4. If not, check if line include partial macro invocation
5. Push lines to `chunk` until macro invocation is complete
6. Execute macro invocation and substitue final result.
The main point is 3 and 4. How should I find whether invocation exists or not.
First approach was to utilize regex crate, while this works for partial
definition, it can't find full macro invocation because rust regex cannot find
balanced match (No subregex or recursive match). This is due to the fact that rust
regex crate complies with pure regex standard.
My next approach will be pest. Pest has somewhat unfamailiar syntax but if used only for a line it would be fine.
### DONE
* [-] Is nested parse chunk necessary? Maybe main parser is alreayd expanding all?
It was not... mostly because some macro can make another macro call...
* [x] Change from chunk write to buf writer
Currently every substituted text is saved to a single string variable, which is
problematic when ram size is not sufficient. Use buff writer to write given
string without saving to designated space.
* [x] God damn it, lines() consume all duplicate new lines
I googled a lot and shamlessly copied from stackoverflow, I Felt real needs to
learn rust much more.
* [x] Made defnition line is deleted
* [x] Enable user to override basic macro
* [x] Currently local macro is not released which is a bad idea as a final output.
* [x] Currently local macro is not perperly constructed when same macro invoked in single call
Using usize type level is not a bad idea, however it should be definite where
to add number and not
* [x] Read from file option
* [x] Output option
* [x] Make custom parser and lexor
* [x] print out non macro text
* [ ] Print remainder from lines that contains macro definition
* [x] Complete register logic
* [x] parse define macro's arguments
* [x] Complete invoke logic
* [x] Basic macro works for now
* [x] Single macro in single line works
* [x] Single macro in multiple lines
* [x] Multiple macro in multiple lines
* [x] Multiple macro in multiple fragmented lines
* [x] Make custom macro works
- Invocation should be also another
- Thus "MacroMap"'s evaluation logic should be located in processor not in Macromap itself
* [x] Make nested invocation work
* [x] When definition includes nestedness -> This is evaluated on invocation
* [x] When invocation includes nestedness -> This is evaluated with method name "evaluate"
* [x] Print evaluated macro substitution
* [x] Print failed macro
* [x] Print a line which as multiple macros in a line
* [x] Print a nested macro substitution
* [x] New basic macros
* [x] Syscmd macro
* [x] Time macro
* [x] Undefine macro
- This needs sincere consideration because this binary targets alpine which is not necessarily easy to combine openssl library.
- Thus using using curl command through std::process::Command might be a global choice
* [x] Include macro
* [x] Repeat macro -> Same thing
* [x] Foreach loop
* [x] For loop -> Change by number
* [x] If macro
* [x] If define macro
* [x] Remove extra new lines and spaces (Namely, "chomp" method)
* [x] Random text -> Use lorem lipsum
* [x] Make direct subcommand option
### How r4d handles newline?
R4d reads file or stdin by lines, in both literal meaning and also rust method
lines. Thus empty trailing lines are ignored if not given spcial pre
processing. R4d chose simple solution to add special index after source chunk
of string after remove it after macro expansions.
Therefore, as a result, every newline works as it is.