I'm writting a program that generate C# code using Rust, For example I have:
namespace Generated
{
public partial class Generated1
{
// things
}
public partial class Generated2
{
// things
}
}
Since Generated1 and Generated2 are complex, there is a single function that generate classes like Generated*, which yields the class without indent:
// println!("{}", generating(1)) yields:
public partial class Generated1
{
// things
}
I wonder is there some technique that allow formatting the generated items with extra indent. Since writting indent in the generating function seems a lot of chaos:
// with indent
format!(
r#"{space:width$}public partial class Generated1
{space:width$}{{
{space:width_plus_1$}// things
{space:width$}}}"#, space = "", width = indent_level * 4, width_plus_1 = indent_level * 4);
// without indent
format!(
r#"public partial class Generated1
{{
// things
}}"#, space = "", width = indent_level * 4, width_plus_1 = indent_level * 4);
Is there some technique to format items with extra indent available in Rust?
When I must generate source code, I usually do that from a Vec<String> because it's easier to build.
Then I use something like this to generate the final source from all the parts (which is why it's a collection of Vec<String>). This one isn't really optimized, but that gives you an idea. Another advantages is that it can fix a few issues with strings, like the OS-specific line ending (not done here, except it breaks multiline strings that may include Windows EOLs), trimming, etc. If you're comparing the source code in your unit tests as I do, it's more robust.
pub fn indent_source(parts: Vec<Vec<String>>, indent: usize) -> String {
let indent_str = String::from_utf8(vec![32; indent]).unwrap();
let mut source = String::new();
let mut first = true;
for part in parts {
if !first {
source.push('\n');
}
first = false;
for string in part {
for line in string.split("\n") {
let cured_line = line.trim_end();
if cured_line.len() > 0 {
source.push_str(&indent_str);
}
source.push_str(cured_line);
source.push('\n');
}
}
}
source
}