Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rework command layout #9

Merged
merged 1 commit into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 140 additions & 54 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,157 @@
use std::fs::read_to_string;

use anyhow::Context;
use clap::{Arg, Command};

#[derive(serde::Serialize, serde::Deserialize)]
pub enum TemplateKind {
Builtin,
FromLua(String),
FromTemplate(String),
}

impl Default for TemplateKind {
fn default() -> Self {
Self::Builtin
}
}

#[derive(serde::Serialize, serde::Deserialize)]
pub struct Config {
template: TemplateKind,
page_root: String,
store_in: String,
name: String,
}
impl Default for Config {
fn default() -> Self {
Self {
template: Default::default(),
page_root: Default::default(),
store_in: "pages".into(),
name: "Your_API".into(),
}
}
}

pub(crate) struct Paths {
pub(crate) json: String,
pub(crate) name: String,
pub(crate) root: String,
pub(crate) build_dir: String,
pub(crate) template_kind: TemplateKind,
}

pub(crate) enum Modes {
Credits,
GenerateDocs(Paths),
SelfDocs {
build_dir: String,
},
GenFile {
file: String,
location: &'static str,
},
Nothing,
}

pub(crate) fn get_paths() -> Modes {
let matches = clap::App::new("tealr doc gen")
.arg(
clap::Arg::new("json")
.long("json")
.short('j')
.takes_value(true)
.help("Path to the json file")
.required_unless_present("credits"),
)
.arg(
clap::Arg::new("name")
.long("name")
.short('n')
.takes_value(true)
.help("Name of the library")
.required_unless_present("credits"),
)
.arg(
clap::Arg::new("root")
.long("root")
.short('r')
.takes_value(true)
.help("The root that the pages link to.")
.default_value("./")
.default_missing_value("./"),
)
.arg(
clap::Arg::new("build_folder")
.long("build_folder")
.short('b')
.takes_value(true)
.help("In which folder to store the generated pages")
.default_value("./pages")
.default_missing_value("./pages"),
)
.arg(
clap::Arg::new("credits")
.long("credits")
.takes_value(false)
.help("Displays the credits"),
)
.get_matches();
pub(crate) fn get_paths() -> Result<Modes, anyhow::Error> {
let matches =
clap::App::new("tealr doc gen")
.subcommand(
Command::new("run")
.alias("gen")
.about("Generates the documentation pages"),
)
.subcommand(
Command::new("gen_self")
.about("Generates files used to add custom behavior to tealr_doc_gen")
.arg(Arg::new("lua_docs").long("lua_docs").help(
"Generates the documentation for the lua api exposed by tealr_doc_gen.",
))
.arg(
Arg::new("config")
.long("config")
.help("Generates a new config file"),
)
.arg(Arg::new("doc_template").long("doc_template").help(
"Generates the default template used to generate the documentation pages",
))
.arg(
Arg::new("doc_lua_kickstart")
.long("doc_lua_kickstart")
.help("Generates the lua code used to build the template"),
)
.arg(
Arg::new("print")
.long("print")
.short('p')
.help("Prints the file instead of writing it directly to a file"),
),
)
.arg(
Arg::new("credits")
.long("credits")
.short('c')
.help("Shows who worked on tealr_doc_gen"),
)
.get_matches();
if matches.contains_id("credits") {
return Modes::Credits;
return Ok(Modes::Credits);
}

let json = matches.value_of("json").unwrap().to_owned();
let name = matches.value_of("name").unwrap().to_owned();
let root = matches.value_of("root").unwrap().to_owned();
let build_dir = matches.value_of("build_folder").unwrap().to_owned();
if matches.subcommand_matches("run").is_some() {
let config: Config = read_config()?;
return Ok(Modes::GenerateDocs(Paths {
json: config.name.clone() + ".json",
build_dir: config.store_in,
name: config.name,
root: config.page_root,
template_kind: config.template,
}));
}
if let Some(x) = matches.subcommand_matches("gen_self") {
return Ok(if x.contains_id("lua_docs") {
let config = read_config()?;
Modes::SelfDocs {
build_dir: config.store_in,
}
} else {
let (text, location) = if x.contains_id("config") {
(
serde_json::to_string_pretty(&Config::default())?,
"./tealr_doc_gen_config.json",
)
} else if x.contains_id("doc_template") {
(
include_str!("../base_template.etlua").into(),
"./template.etlua",
)
} else if x.contains_id("doc_lua_kickstart") {
(
include_str!("../base_run_template.lua").into(),
"./run_template.lua",
)
} else {
return Err(anyhow::anyhow!("Missing argument"));
};
if x.contains_id("print") {
println!("{}", text);
Modes::Nothing
} else {
Modes::GenFile {
file: text,
location,
}
}
});
};
Ok(Modes::Nothing)
}

Modes::GenerateDocs(Paths {
name,
root,
json,
build_dir,
})
fn read_config() -> Result<Config, anyhow::Error> {
serde_json::from_str(
&read_to_string("./tealr_doc_gen_config.json")
.context("Could not read tealr_doc_gen_config.json in current directory. Maybe generate one using `tealr_doc_gen gen_self --config`?")?
).context("Error while parsing the config file. Use `tealr_doc_gen gen_self --config` to generate an example")
}
27 changes: 24 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use app::Paths;
use run_template::generate_self;

use crate::app::get_paths;

mod app;
Expand All @@ -7,14 +10,32 @@ mod doc_gen;
mod markdown;
mod run_template;
fn main() -> anyhow::Result<()> {
match get_paths() {
match get_paths()? {
app::Modes::Credits => {
credits::show_credits();
Ok(())
}
app::Modes::GenerateDocs(x) => {
//generate_docs::generate_docs(x)
run_template::run_template(x)
run_template::run_template(x)?;
}
app::Modes::SelfDocs { build_dir } => {
let walker = generate_self()?;
run_template::run_from_walker(
Paths {
json: "{}".into(),
name: "tealr_doc_gen".into(),
root: "".into(),
build_dir,
template_kind: app::TemplateKind::Builtin,
},
walker,
)?;
}
app::Modes::GenFile { file, location } => {
//std::fs::create_dir_all(location)?;
std::fs::write(location, file)?;
}
app::Modes::Nothing => (),
}
Ok(())
}
45 changes: 31 additions & 14 deletions src/run_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ use std::{
path::{Path, PathBuf},
};

use anyhow::Context;
use tealr::{
mlu::{ExportInstances, FromToLua, TealData},
EnumGenerator, GlobalInstance, NameContainer, RecordGenerator, TypeGenerator, TypeName,
TypeWalker,
};

use crate::{
app::Paths,
app::{Paths, TemplateKind},
doc_gen::{get_type_name, type_should_be_inlined},
};

Expand Down Expand Up @@ -134,10 +136,7 @@ impl ExportInstances for GlobalInstances {
}
}

pub(crate) fn run_template(paths: Paths) -> Result<(), anyhow::Error> {
let json = read_to_string(paths.json)?;
let type_defs: tealr::TypeWalker = serde_json::from_str(&json)?;

pub(crate) fn run_from_walker(paths: Paths, type_defs: TypeWalker) -> Result<(), anyhow::Error> {
let link_path = Path::new("/").join(&paths.root);

let sidebar: Vec<SideBar> = type_defs
Expand Down Expand Up @@ -212,6 +211,7 @@ pub(crate) fn run_template(paths: Paths) -> Result<(), anyhow::Error> {
None,
None,
link_path.clone(),
&paths.template_kind,
)?;
}
run_and_write(
Expand All @@ -221,26 +221,47 @@ pub(crate) fn run_template(paths: Paths) -> Result<(), anyhow::Error> {
Some(type_defs.global_instances_off),
Some(type_defs.given_types),
link_path,
&paths.template_kind,
)?;
Ok(())
}

pub(crate) fn run_template(paths: Paths) -> Result<(), anyhow::Error> {
let json = read_to_string(&paths.json)?;
let type_defs: tealr::TypeWalker = serde_json::from_str(&json)?;
run_from_walker(paths, type_defs)
}

fn run_and_write(
sidebar: Vec<SideBar>,
type_def: &TypeGenerator,
write_path: &Path,
global_instances: Option<Vec<tealr::GlobalInstance>>,
all_types: Option<Vec<TypeGenerator>>,
link_path: PathBuf,
template_kind: &TemplateKind,
) -> Result<(), anyhow::Error> {
let type_name = if type_should_be_inlined(type_def) {
"index".into()
} else {
get_type_name(type_def)
};
let base_template = include_str!("../base_template.etlua");
let base_runner = include_str!("../base_run_template.lua");
let (template, template_runner) = match template_kind {
TemplateKind::Builtin => (base_template.to_string(), base_runner.to_string()),
TemplateKind::FromLua(x) => (
base_template.to_string(),
std::fs::read_to_string(x)
.with_context(|| format!("Could not load doc template runner. File {x}"))?,
),
TemplateKind::FromTemplate(x) => (
std::fs::read_to_string(x)
.with_context(|| format!("Could not load doc template. File {x}"))?,
base_runner.to_string(),
),
};
let etlua = include_str!("../etlua.lua").to_string();
let template = include_str!("../base_template.etlua").to_string();
let template_runner = include_str!("../base_run_template.lua");
let lua = unsafe { tealr::mlu::mlua::Lua::unsafe_new() };
let instance_setter = GlobalInstances {
side_bar: sidebar,
Expand All @@ -255,17 +276,15 @@ fn run_and_write(
tealr::mlu::set_global_env(instance_setter, &lua)?;

let document: tealr::mlu::mlua::String = lua
.load(template_runner)
.load(&template_runner)
.set_name("template_runner")?
.call(())?;
let page_path = write_path.join(format!("{type_name}.html"));
std::fs::write(page_path, document.as_bytes())?;
Ok(())
}

//will be used later :)
#[allow(dead_code)]
fn generate_self() -> Result<(), Box<dyn std::error::Error>> {
pub fn generate_self() -> Result<TypeWalker, anyhow::Error> {
let x = tealr::TypeWalker::new()
.process_type::<tealr::EnumGenerator>()
.process_type::<tealr::ExportedFunction>()
Expand All @@ -282,7 +301,5 @@ fn generate_self() -> Result<(), Box<dyn std::error::Error>> {
.process_type::<TestDocs>()
.process_type_inline::<TestDocs>()
.document_global_instance::<GlobalInstances>()?;
std::fs::write("./self.json", serde_json::to_string_pretty(&x)?)?;
std::fs::write("./self.d.tl", x.generate_global("tealr_doc_gen")?)?;
Ok(())
Ok(x)
}