rustyphoenixlecture 1.7.2

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::collections::HashMap;

use crate::{phighlighter::PLocation, pcontent::{PContentTitle, PContentType, PVecContent, PContent, PContentParagraph, PLabeler}};

///Manage the environment list call
struct PEnvListCall{
	///Location of the call in the lecture markdown
	p_location: PLocation,
	///Index of the call in the main PVecContent
	p_call_index: usize,
}

///Manage the search of environments in the lecture
pub struct PSearchEnvironment{
	///List of the environments to search (key: environment name, value: call of the PContentEnvList in the main PVecContent)
	p_map_env_to_search: HashMap<String, PEnvListCall>,
}

impl PSearchEnvironment {
	///Constructor of PSearchEnvironment
	pub fn new() -> Self{
		PSearchEnvironment {
			p_map_env_to_search: Default::default(),
		}
	}
	///Add an environement to search
	/// # Parameters
	/// - `env_name` : name of the environement to be searched
	/// - `index_call` : index of the PContentEnvList in the main PVecContent
	/// - `location` : location of the PContentEnvList in the lecture in markdown
	/// # Errors
	/// The function will panic if the is already a search for the given environment. We allow only one search per lecture otherwise this is too horible to handle.
	pub fn add_env(&mut self, env_name: &String, index_call: usize, location: &PLocation){
		match self.p_map_env_to_search.get(env_name) {
			Some(already_defined) => {
				panic!("PSearchEnvironment::add_env : Error at {}\n\tCannot add search for environment {}\n\tAlready defined at {}", location, env_name, already_defined.p_location);
			},
			None => {
				self.p_map_env_to_search.insert(env_name.clone(), PEnvListCall { p_location: location.clone(), p_call_index: index_call });
			}
		}
	}
	///Append a PSearchEnvironment in the current PSearchEnvironment
	/// # Parameters
	/// - `search_env` : PSearchEnvironment to be append
	pub fn append(&mut self, search_env: &PSearchEnvironment){
		for (name, env) in search_env.p_map_env_to_search.iter() {
			self.add_env(name, env.p_call_index, &env.p_location);
		}
	}
	///Update the list call of the environment
	/// # Parameters
	/// - `vec_content` : vector of PContent to be udpated
	pub fn update_env_list(&self, vec_content: &mut PVecContent){
		if self.p_map_env_to_search.len() == 0 {
			return;	//Nothing to search, we stop
		}
		//First we create the map of PContent to be updated
		let mut map_content: HashMap<String, PContent> = self.create_map_content();
		let mut current_output_file = String::from("");
		//We iterate on all content to fine the environment we want
		update_map_content(&mut map_content, &mut current_output_file, vec_content);
		
		for (env_name, content) in map_content.iter() {
			let list_env_index = self.p_map_env_to_search.get(env_name).unwrap().p_call_index;
			match vec_content.get_vec_child_mut().get_mut(list_env_index) {
				Some(list_env_labeler) => {
					match list_env_labeler {
						PContentType::EnvList(list_env) => {
							*list_env.get_data_mut().get_content_mut() = content.get_content().clone();
						},
						_ => panic!("PSearchEnvironment::update_env_list : PContent at {} is not a PContentType::EnvList", list_env_index)
					}
				},
				None => panic!("PSearchEnvironment::update_env_list : wrong list_env_index = {}", list_env_index)
			}
		}
	}
	///Create the map of PContent
	/// # Returns
	/// Map of the PContent of the current PSearchEnvironment
	fn create_map_content(&self) -> HashMap<String, PContent> {
		let mut map_content: HashMap<String, PContent> = Default::default();
		for (i, (name, _)) in self.p_map_env_to_search.iter().enumerate() {
			let mut content = PContent::new();
			let mut title = PContentTitle::new(2, false, &Default::default());
			title.get_title_mut().add_child(&PContentType::from_text(50000000 + i, &String::from(format!("List of {} environments", name))));
			
			content.get_content_mut().add_child(&PContentType::Title(PLabeler::new(40000000 + i, &title)));
			
			map_content.insert(name.clone(), content);
		}
		return map_content;
	}
}

///Update the map of PContent
/// # Parameters
/// - `map_content` : map of content to be updated
/// - `current_output_file` : current output file to be updated
/// - `vec_content` : vector of content to be analysed
fn update_map_content(map_content: &mut HashMap<String, PContent>, current_output_file: &mut String, vec_content: &PVecContent){
	//We iterate on all content to fine the environment we want
	for content in vec_content.get_vec_child().iter() {
		match &content {
			//If we find a Title we update the current output file
			PContentType::Title(title) => {
				if title.get_data().is_enumerated() {
					*current_output_file = title.get_data().get_output_filename().clone();
				}
			},
			PContentType::Environment(environement) => {
				//If we find an environment we check its name
				let env_name = environement.get_data().get_name();
				match map_content.get_mut(env_name) {
					Some(env_content) => {
						let id = environement.get_id();
						let mut paragraph = PContentParagraph::new();
						paragraph.get_content_mut().add_child(&PContentType::from_url(1000000000 + id,
							&String::from(format!("{} {}.", env_name, environement.get_id())),
							&String::from(format!("{}#{}", current_output_file, id))));
						paragraph.get_content_mut().add_child(&PContentType::from_text(1000000000 + id, &String::from(format!(" Defined at <b>{}</b>", environement.get_data().get_location()))));
						
						env_content.get_content_mut().add_child(&PContentType::Paragraph(PLabeler::new(2000000000 + id, &paragraph)));
						env_content.get_content_mut().add_child(&PContentType::Environment(environement.clone()));
					},
					None => {}
				}
			},
			//If we find a table, we look inside
			PContentType::Table(table) => {
				for row in table.get_data().get_vec_row().iter() {
					for col in row.get_vec_cell().iter() {
						update_map_content(map_content, current_output_file, col.get_content());
					}
				}
			},
			_ => {}
		}
	}
}