Skip to content

Commit

Permalink
Improving the concept of FileSection
Browse files Browse the repository at this point in the history
  • Loading branch information
notdanilo committed Nov 9, 2023
1 parent a15334d commit 07a9d1a
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 44 deletions.
4 changes: 2 additions & 2 deletions ecosystem/rust/importer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl LibraryGenerator {
let file = file_set.entry(PathBuf::from("Cargo.toml"));
let mut template = Template::new();
template.register_template("project", include_str!("templates/Cargo.hbs"))?;
let template = template.render("project", &library)?;
let template = template.render("project", library)?;
let root = file.section("root");
root.write(template);
Ok(())
Expand All @@ -26,7 +26,7 @@ impl LibraryGenerator {
pub fn generate_lib_file(&self, library: &Library, file_set: &mut FileSet) -> Result<()> {
let file = file_set.entry(PathBuf::from("src").join("lib.rs"));
let section = file.section("documentation");
section.writeln(library.metadata.description.split("\n").map(|s| format!("//! {}", s)).collect::<Vec<String>>().join("\n"));
section.writeln(library.metadata.description.split('\n').map(|s| format!("//! {}", s)).collect::<Vec<String>>().join("\n"));
Ok(())
}

Expand Down
184 changes: 142 additions & 42 deletions ligen/generator/src/generator/file_generator/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,38 @@ use ligen_utils::fs::write_file;
use std::path::{Path, PathBuf};
use std::collections::{HashMap, BTreeMap};

/// Structure representing a file path and its content.
#[derive(Debug, Clone, PartialEq, Shrinkwrap)]
#[shrinkwrap(mutable)]
pub struct File {
/// File path.
pub path: PathBuf,
/// File Section.
#[shrinkwrap(main_field)]
pub section: FileSection
}

impl File {
/// Creates a new file with the specified path and content.
pub fn new(path: impl AsRef<std::path::Path>) -> Self {
let path = path.as_ref().to_path_buf();
let section = Default::default();
Self { path, section }
}

/// Saves the file.
pub fn save(&self) -> Result<()> {
write_file(&self.path, self.content())
}
}


#[derive(Default, Debug, Clone, PartialEq)]
pub struct FileSection {
/// File section content.
pub content: String
content: Vec<String>,
sections: BTreeMap<String, FileSection>,
order: Vec<String>
}

impl FileSection {
Expand All @@ -17,37 +45,34 @@ impl FileSection {
Self::default()
}

/// Writes the content to the file buffer.
pub fn write<S: AsRef<str>>(&mut self, content: S) {
self.content.push_str(content.as_ref());
/// Creates a new FileSection from a template.
pub fn from_template(template: impl AsRef<str>) -> Result<Self> {
let mut section = Self::new();
let template = template.as_ref();
const SECTION_START: &str = "[section(";
const SECTION_END: &str = ")]";
for (index, _) in template.match_indices(SECTION_START) {
let index = index + SECTION_START.len();
let index_end = template[index..]
.find(SECTION_END)
.ok_or_else(|| Error::Message("Failed to parse template: missing section end.".to_string()))? + index;
let section_name = &template[index..index_end];
section.section(section_name);
}
Ok(section)
}

/// Writes the content to the file buffer and adds a new line.
pub fn writeln<S: AsRef<str>>(&mut self, content: S) {
self.content.push_str(content.as_ref());
self.content.push('\n');
}
}

/// Structure representing a file path and its content.
#[derive(Debug, Clone, PartialEq)]
pub struct File {
/// File path.
pub path: PathBuf,
/// File sections.
pub sections: BTreeMap<String, FileSection>,
order: Vec<String>
}

impl File {
/// Creates a new file with the specified path and content.
pub fn new(path: impl AsRef<std::path::Path>) -> Self {
let sections = Default::default();
let path = path.as_ref().to_path_buf();
let order = Default::default();
Self { path, sections, order }
/// Gets content.
pub fn content(&self) -> String {
let mut content = self.content.join("");
for section in &self.order {
if let Some(section) = self.sections.get(section) {
content.push_str(&section.content());
}
}
content
}

/// Gets or creates a new section with the specified name.
pub fn section(&mut self, name: impl AsRef<str>) -> &mut FileSection {
self
Expand All @@ -59,21 +84,29 @@ impl File {
})
}

/// Gets content.
pub fn content(&self) -> String {
let mut content = String::new();
for section in &self.order {
if let Some(section) = self.sections.get(section) {
content.push_str(&section.content);
}
}
content
/// Writes the content to the file section at the specified index.
pub fn indexed_write<S: AsRef<str>>(&mut self, index: usize, content: S) {
self.content.insert(index, content.as_ref().to_string())
}

/// Saves the file.
pub fn save(&self) -> Result<()> {
write_file(&self.path, self.content())
/// Writes the content to the file section at the specified index and adds a new line.
pub fn indexed_writeln<S: AsRef<str>>(&mut self, index: usize, content: S) {
let mut string = content.as_ref().to_string();
string.push('\n');
self.indexed_write(index, string);
}

/// Writes the content to the file buffer.
pub fn write<S: AsRef<str>>(&mut self, content: S) {
self.content.push(content.as_ref().to_string());
}

/// Writes the content to the file buffer and adds a new line.
pub fn writeln<S: AsRef<str>>(&mut self, content: S) {
let mut string = content.as_ref().to_string();
string.push('\n');
self.content.push(string);
}
}

/// Structure representing all the file set to be generated.
Expand Down Expand Up @@ -101,6 +134,9 @@ impl FileSet {

#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::file_generator::FileSection;

use super::File;

#[test]
Expand All @@ -110,4 +146,68 @@ mod tests {
file.section("a").write("A");
assert_eq!(file.content(), "BA");
}
}

#[test]
fn section() {
let mut section = FileSection::new();
section.writeln("//! This is a Rust");
section.writeln("//! documentation.");
section.section("sub1").write("//! This is a sub-section and ");
section.section("sub2").writeln("//! This is another sub-section.");
section.section("sub1").writeln("we can add to it later.");
assert_eq!(section.content(), "//! This is a Rust\n//! documentation.\n//! This is a sub-section and we can add to it later.\n//! This is another sub-section.\n");
}

#[test]
fn deep_section() {
let mut section = FileSection::new();
section.section("attribute::begin").write("#[ligen(");
section.section("attribute::parameters").write("name = \"test\"");
section.section("attribute::parameters").write(", truth = true");
section.section("attribute::end").writeln(")]");
assert_eq!(section.content(), "#[ligen(name = \"test\", truth = true)]\n");

let mut section = FileSection::new();
for name in ["attribute::begin", "attribute::parameters", "attribute::end"] {
section.section(name);
}
section.section("attribute::begin").write("#[ligen(");
section.section("attribute::end").writeln(")]");
section.section("attribute::parameters").write("name = \"test\"");
section.section("attribute::parameters").write(", truth = true");
assert_eq!(section.content(), "#[ligen(name = \"test\", truth = true)]\n");
}

#[test]
fn template() -> Result<()> {
let template = "[section(attribute::begin)][section(attribute::parameters)][section(attribute::end)]";
let mut section = FileSection::from_template(template)?;
assert_eq!(section.order, vec!["attribute::begin", "attribute::parameters", "attribute::end"]);
section.section("attribute::begin").write("#[ligen(");
section.section("attribute::end").writeln(")]");
section.section("attribute::parameters").write("name = \"test\"");
section.section("attribute::parameters").write(", truth = true");
assert_eq!(section.content(), "#[ligen(name = \"test\", truth = true)]\n");
Ok(())
}

// #[test]
// fn template_with_content() -> Result<()> {
// let template = "before[section(begin)]content[section(end)]after";
// let mut section = FileSection::from_template(template)?;
// assert_eq!(section.order, vec!["begin", "end"]);
// section.section("begin").write("-begin-");
// section.section("end").write("-end-");
// assert_eq!(section.content(), "before-begin-content-end-after");
// Ok(())
// }

#[test]
fn indexed_section() {
let mut section = FileSection::new();
section.indexed_write(0, "First");
section.indexed_write(1, ", Third");
section.indexed_write(1, ", Second");
assert_eq!(section.content(), "First, Second, Third");
}
}

0 comments on commit 07a9d1a

Please sign in to comment.