use std::fmt::{self, Display, Formatter};
use conch_parser::ast::{AtomicTopLevelCommand, TopLevelCommand};
use enum_map::EnumMap;
use linked_hash_map::LinkedHashMap;
use crate::parser::RunscriptLocation;
#[derive(Clone, Debug)]
pub struct Runscript {
pub name: String,
pub source: String,
pub includes: Vec<RunscriptInclude>,
pub scripts: Scripts,
pub options: Vec<String>,
}
#[derive(Clone, Debug)]
pub struct RunscriptInclude {
pub runscript: Runscript,
pub location: RunscriptLocation,
}
#[derive(Clone, Debug)]
pub struct Scripts {
pub targets: LinkedHashMap<String, EnumMap<ScriptPhase, Option<Script>>>,
}
#[derive(Debug, PartialEq, Hash, Eq, Clone, Copy, enum_map::Enum)]
pub enum ScriptPhase {
BuildOnly, Build, BuildAndRun, Run, RunOnly, }
#[derive(Clone, Debug)]
pub struct Script {
pub commands: Vec<AtomicTopLevelCommand<String>>,
pub location: RunscriptLocation,
}
impl Runscript {
pub fn unwind_fileid(&self, id: &[usize]) -> Option<&Runscript> {
if id.is_empty() {
Some(&self)
} else {
let mut file_ref = self;
for index in id {
file_ref = &file_ref.includes.get(*index)?.runscript;
}
Some(file_ref)
}
}
pub fn get_target(&self, target: &str) -> Option<&EnumMap<ScriptPhase, Option<Script>>> {
match self.scripts.targets.get(target).as_ref() {
Some(map) if map.values().any(Option::is_some) => Some(map),
_ => {
for include in &self.includes {
match include.runscript.scripts.targets.get(target) {
Some(map) if map.values().any(Option::is_some) => {
return Some(map);
}
_ => {}
}
}
None
}
}
}
}
impl Display for ScriptPhase {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
ScriptPhase::BuildOnly => "Build!",
ScriptPhase::Build => "Build",
ScriptPhase::BuildAndRun => "Build & Run",
ScriptPhase::Run => "Run",
ScriptPhase::RunOnly => "Run!",
}
)
}
}