rustyphoenixlecture 1.7.0

This project aims to provide a simple a powerfull lecture compilation to generate html web sites
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

use std::path::PathBuf;
use std::collections::HashMap;

use crate::phighlighter::{
	PFileParser,
	PFileParserIter,
	PLocation
};

use crate::pcontent::{
	PIdCounter,
	PLabeler,
	PContentType,
	PVecContent,
	PContentText,
	PContentParagraph
};

use crate::plectureparser::{
	pressourcearchive::PRessourceArchive,
	psearchenvironment::PSearchEnvironment,
};

///Data of the lecture which are parsed
pub struct PLectureData<'a>{
	///Current id of the PContent
	p_id: PIdCounter,
	///Remaning text
	p_text: String,
	///Iterator on the current file to be parsed
	p_file_iter: PFileParserIter<'a>,
	///Map of the labels of corresponding PContent id
	p_map_label: HashMap<String, usize>,
	///Map of the used labels (by reference) in the lecture
	p_map_reference: HashMap<String, PLocation>,
	///Map of the references to other lectures
	p_map_lecture_reference: HashMap<String, HashMap<String, PLocation>>,
	///Map of all archive to be created for the lecture
	p_map_archive: HashMap<PathBuf, PRessourceArchive>,
	///0 if the current paragraph is enabled
	p_is_paragraph_enable: usize,
	///0 if the numbered title are enabled
	p_is_numbered_title_enable: usize,
	///Manager to search and list environments in the lecture
	p_search_environment: PSearchEnvironment,
}

impl<'a> PLectureData<'a>{
	///Constructor of the PLectureData
	/// # Parameters
	/// - `current_id` : current if where to start indexing of PContent
	/// - `file_parser` : PFileParser of the current file to be parsed
	/// # Returns
	/// Initialised PLectureData
	pub fn new(current_id: usize, file_parser: &'a PFileParser) -> Self{
		PLectureData{
			p_id: PIdCounter::new(current_id),
			p_text: String::from(""),
			p_file_iter: file_parser.iter(false),
			p_map_label: Default::default(),
			p_map_reference: Default::default(),
			p_map_lecture_reference: Default::default(),
			p_map_archive: Default::default(),
			p_is_paragraph_enable: 0,
			p_is_numbered_title_enable: 0,
			p_search_environment: PSearchEnvironment::new(),
		}
	}
	///Set the current id of the PLectureData
	/// # Parameters
	/// - `current_id` : current if of the PLectureData
	pub fn set_current_id(&mut self, current_id: usize){
		self.p_id.set_id(current_id);
	}
	///Get the current id
	/// # Returns
	/// Current id of the PContent to be created
	pub fn get_current_id(&mut self) -> usize{
		return self.p_id.get_id();
	}
	///Get the PIdCounter
	/// # Returns
	/// Muttable reference of the PIdCounter
	pub fn get_id_mut(&mut self) -> &mut PIdCounter{
		&mut self.p_id
	}
	///Get the PSearchEnvironment
	/// # Returns
	/// Muttable reference of the PSearchEnvironment
	pub fn get_search_environment(&self) -> &PSearchEnvironment{
		&self.p_search_environment
	}
	///Get the PSearchEnvironment
	/// # Returns
	/// Muttable reference of the PSearchEnvironment
	pub fn get_search_environment_mut(&mut self) -> &mut PSearchEnvironment{
		&mut self.p_search_environment
	}
	///Get the file iterator
	/// # Return
	/// File iterator of the PLectureData
	pub fn get_file_iter(&mut self) -> &mut PFileParserIter<'a>{
		&mut self.p_file_iter
	}
	///Increment the current character to parse
	pub fn increment_current_char(&mut self){
		match self.p_file_iter.get_current_char() {
			Some(ch) => self.p_text += &String::from(ch as char),
			None => {}
		};
		self.p_file_iter.next();
	}
	///Add text which will be played at some point
	/// # Parameters
	/// - `vec_content` : PVecContent result of the parsing
	/// - `text` : text to be added
	pub fn add_text(&mut self, vec_content: &mut PVecContent, text: &String){
		self.p_text += text;
		if self.is_paragraph_enable() {
			let time_to_flush_paragraph = self.p_text.ends_with("\n\n");
			if time_to_flush_paragraph {
				// println!("PLectureData::play_text : This is time to flush");
				//We just have to create a new PContentParagraph before flushing the text
				vec_content.add_child(&PContentType::Paragraph(PLabeler::new(self.get_current_id(), &PContentParagraph::new())));
				self.play_text(vec_content);
			}else{
				//Then we can add the text as usual
				if vec_content.add_text(&mut self.p_id, &self.p_text.clone()) {
					//Since we just flushed, we clear the p_text
					self.p_text = String::from("");
				}
			}
		}
	}
	///Play the current text into the content
	/// # Parameters
	/// - `content` : PVecContent result of the parsing
	pub fn play_text(&mut self, content: &mut PVecContent){
		// let time_to_flush_paragraph = self.p_text.ends_with("\n\n");
		// We need to add all the text, even with only white characters to not loose spacing
		// println!("PLectureData::play_text : p_text = '{}'", self.p_text);
		let trim_text = String::from(self.p_text.trim_matches('\n'));
		if !trim_text.is_empty() {
			if self.is_paragraph_enable() {
				//Here we have to check how to append the current text in the content
				// self.play_text_paragraph(content, &trim_text);
				content.add_text(&mut self.p_id, &trim_text);
				// self.p_current_paragraph.get_content_mut().add_child(&text);
			}else{
				let text = PContentType::Text(PLabeler::new(self.get_current_id(), &PContentText::new(&trim_text)));
				content.add_child(&text);
			}
		}
		self.p_text = String::from("");
	}
	///Say if the paragraph mode is enabled or disabled
	/// # Returns
	/// True if the paragraph mode is enabled, false if it is disabled
	pub fn is_paragraph_enable(&self) -> bool{
		self.p_is_paragraph_enable == 0
	}
	///Enable the paragraph
	pub fn enable_paragraph(&mut self){
		if self.p_is_paragraph_enable > 0 {
			self.p_is_paragraph_enable -= 1;
		}
	}
	///Disable the paragraph
	pub fn disable_paragraph(&mut self){
		self.p_is_paragraph_enable += 1;
	}
	///Say if the numbered title mode is enabled or disabled
	/// # Returns
	/// True if the numbered title mode is enabled, false if it is disabled
	pub fn is_numbered_title_enable(&self) -> bool{
		self.p_is_numbered_title_enable == 0
	}
	///Enable the numbered title
	pub fn enable_numbered_title(&mut self){
		if self.p_is_numbered_title_enable > 0 {
			self.p_is_numbered_title_enable -= 1;
		}
	}
	///Disable the numbered title
	pub fn disable_numbered_title(&mut self){
		self.p_is_numbered_title_enable += 1;
	}
	///Add a PContentType in the PVecContent
	/// # Parameters
	/// - `vec_content` : PVecContent result of the parsing
	/// - `content_type` : content to be added
	pub fn add_child(&mut self, vec_content: &mut PVecContent, content_type: &PContentType){
		let is_paragraph_enabled: bool = self.is_paragraph_enable();
		vec_content.add_content(&mut self.p_id, content_type, is_paragraph_enabled);
		
		// if !self.is_paragraph_enable() {
		// 	vec_content.add_child(content_type);
		// 	return;
		// }
		// if content_type.is_inlinable() {
		// 	self.add_child_in_last_item_or_paragraph(vec_content, content_type);
		// }else{
		// 	//If the content_type is a paragraph, maybe we have to add it in the last item list too
		// 	match content_type {
		// 		PContentType::Paragraph(_) => self.add_child_in_last_item(vec_content, content_type),
		// 		PContentType::ListItem(listitem) => {
		// 			self.add_item_to_vec_content(vec_content, listitem);
		// 		}
		// 		//For blocked content (title, parser, environement, wip, etc)
		// 		_ => vec_content.add_child(content_type)
		// 	}
		// }
	}
	///Add a label
	/// # Parameters
	/// - `content` : content to get the id of the labelized PContent
	/// - `label` : name of the label of the last PContent
	/// # Returns
	/// True on success, false otherwise
	pub fn add_label(&mut self, content: &mut PVecContent, label: &String) -> bool{
		match content.get_vec_child_mut().last_mut() {
			Some(last_child) => {
				match last_child {
					PContentType::ListItem(listitem) => {
						self.add_label(listitem.get_data_mut().get_content_mut(), label)
					},
					PContentType::Paragraph(last_paragraph) => {
						self.add_label(last_paragraph.get_data_mut().get_content_mut(), label)
					},
					other => {
						// println!("PLectureData::add_label : Add label '{}' for id = {}", label.clone(), data.get_id());
						self.p_map_label.insert(label.clone(), other.get_id());
						//let's add a label to data
						other.set_label(label);
						true
					}
				}
			},
			None => false
		}
	}
	///Add a reference we will need to update later
	/// # Parameters
	/// - `reference_name` : name of the reference to be added
	/// - `location` : location where the reference is defined
	pub fn add_reference(&mut self, reference_name: &String, location: &PLocation){
		// println!("PLectureData::add_reference : Add Reference '{}' for location = {}", reference_name.clone(), location);
		self.p_map_reference.insert(reference_name.clone(), location.clone());
	}
	///Add a reference we will need to update later
	/// # Parameters
	/// - `lecture_name` : name of the lecture we referenced
	/// - `reference_name` : name of the reference to be added
	/// - `location` : location where the reference is defined
	pub fn add_lecture_reference(&mut self, lecture_name: &String, reference_name: &String, location: &PLocation){
		// println!("PLectureData::add_reference : Add Reference '{}' for location = {}", reference_name.clone(), location);
		match self.p_map_lecture_reference.get_mut(lecture_name) {
			Some(mut_lecture_ref) => {
				mut_lecture_ref.insert(reference_name.clone(), location.clone());
			},
			None => {	//If the lecture is not cited yet, we add it
				let mut lecture_ref: HashMap<String, PLocation> = Default::default();
				lecture_ref.insert(reference_name.clone(), location.clone());
				self.p_map_lecture_reference.insert(lecture_name.clone(), lecture_ref.clone());
			}
		}
	}
	///Add an archive to the PLectureParser
	/// # Parameters
	/// - `archive` : archive file to be managed
	pub fn add_archive(&mut self, archive: &PRessourceArchive){
		self.p_map_archive.insert(archive.get_absolute_output_archive_file().clone(), archive.clone());
	}
	///Get the location of the current PLectureData
	/// # Returns
	/// Location of the PLectureData
	pub fn get_parser_location(&self) -> &PLocation {
		&self.p_file_iter.get_location()
	}
	///Get the map of labels of the PLectureData
	/// # Returns
	/// Map of labels of the PLectureData
	pub fn get_map_label(&self) -> &HashMap<String, usize> {
		&self.p_map_label
	}
	///Get the map of references of the PLectureData
	/// # Returns
	/// Map of references of the PLectureData
	pub fn get_map_reference(&self) -> &HashMap<String, PLocation> {
		&self.p_map_reference
	}
	///Get the map of lecture references of the PLectureData
	/// # Returns
	/// Map of references of the PLectureData
	pub fn get_map_lecture_reference(&self) -> &HashMap<String, HashMap<String, PLocation>> {
		&self.p_map_lecture_reference
	}
	///Get the map of the archive of the PLectureData
	/// # Returns
	/// Map of the archive of the PLectureData
	pub fn get_map_archive(&self) -> &HashMap<PathBuf, PRessourceArchive>{
		&self.p_map_archive
	}
	///Flush and return the current text of the PLectureData
	/// # Returns
	/// Current text of the PLectureData
	pub fn flush_text(&mut self) -> String{
		let text = self.p_text.clone();
		self.p_text = String::from("");
		return text;
	}
}