Skip to content

Commit

Permalink
feat: Display submodules in module documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Dec 26, 2018
1 parent 1193d72 commit fdab790
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 131 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ repository = "https://github.com/gluon-lang/gluon"
documentation = "https://docs.rs/gluon"

[dependencies]
collect-mac = "0.1.0"
clap = "2.22.0"
env_logger = "0.6"
failure = { version = "0.1", features = ["backtrace"] }
Expand Down
45 changes: 0 additions & 45 deletions doc/src/doc/index.html

This file was deleted.

16 changes: 16 additions & 0 deletions doc/src/doc/module.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@
<main class="col-md-9 ml-sm-auto cl-lg-10 pt-3 px-4" role="main">
<h1 class="pb-3 mb-4 border-bottom">{{name}}</h1>

<h2>Modules</h2>

<table class="table-sm">
<tbody>
{{#each sub_modules}}
<tr>
<td>
<a href="{{module_link name}}">{{name}}</a>
</td>
<td valign="middle">
{{markdown_first_paragraph comment}}
</td>
</tr>
{{/each}}
</table>

<div class="docblock">{{markdown comment}}</div>

{{#if record.types}}
Expand Down
157 changes: 72 additions & 85 deletions doc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#[macro_use]
extern crate clap;
#[macro_use]
extern crate collect_mac;
extern crate failure;
extern crate handlebars;
extern crate itertools;
Expand All @@ -21,11 +23,13 @@ extern crate log;

extern crate gluon;

use std::collections::BTreeMap;
use std::fs::{create_dir_all, File};
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use std::result::Result as StdResult;
use std::{
collections::{btree_map, BTreeMap},
fs::{create_dir_all, File},
io::{self, Read, Write},
path::{Path, PathBuf},
result::Result as StdResult,
};

use failure::ResultExt;

Expand Down Expand Up @@ -208,10 +212,10 @@ pub struct TemplateModule<'a> {
pub name: &'a str,
pub comment: &'a str,
pub record: &'a Record,
pub sub_modules: Vec<&'a Module>,
pub sibling_modules: Vec<&'a str>,
}

const INDEX_TEMPLATE: &str = "index";
const MODULE_TEMPLATE: &str = "module";

fn symbol_link(index: bool, current_module: &str, param: &str) -> String {
Expand All @@ -232,44 +236,30 @@ fn symbol_link(index: bool, current_module: &str, param: &str) -> String {
)
}

fn module_link(index: bool, directory_module: bool, current_module: &str, param: &str) -> String {
let skipped = if index { 0 } else { 1 };
fn module_link(current_module: &str, param: &str) -> String {
format!(
"{}{}{}.html",
current_module
.split('.')
.skip(skipped)
.map(|_| "../")
.format(""),
"{}{}.html",
current_module.split('.').skip(1).map(|_| "../").format(""),
param.replace(".", "/"),
if directory_module { "/index" } else { "" }
)
}

fn handlebars() -> Result<Handlebars> {
let mut reg = Handlebars::new();

reg.register_template_string(INDEX_TEMPLATE, include_str!("doc/index.html"))?;
reg.register_template_string(MODULE_TEMPLATE, include_str!("doc/module.html"))?;

fn module_link_helper(
h: &Helper,
_: &Handlebars,
context: &Context,
rc: &mut RenderContext,
_rc: &mut RenderContext,
out: &mut Output,
) -> ::std::result::Result<(), RenderError> {
let current_module = &context.data()["name"].as_str().expect("name").to_string();

let param = String::deserialize(h.param(0).unwrap().value())?;
let index = rc.get_root_template_name().map(|s| &s[..]) == Some(INDEX_TEMPLATE);
let directory_module = h.param(1).is_some();
out.write(&module_link(
index,
directory_module,
current_module,
&param,
))?;
out.write(&module_link(current_module, &param))?;
Ok(())
}
reg.register_helper("module_link", Box::new(module_link_helper));
Expand All @@ -278,16 +268,11 @@ fn handlebars() -> Result<Handlebars> {
h: &Helper,
_: &Handlebars,
context: &Context,
rc: &mut RenderContext,
_rc: &mut RenderContext,
out: &mut Output,
) -> ::std::result::Result<(), RenderError> {
let current_module_level = &context.data()["name"]
.as_str()
.expect("name")
.split('.')
.count();
let index = rc.get_root_template_name().map(|s| &s[..]) == Some(INDEX_TEMPLATE);
let index_offset = if index { 1 } else { 2 };
let current_module = context.data()["name"].as_str().expect("name");
let current_module_level = current_module.split('.').count();

let param = String::deserialize(h.param(0).unwrap().value())?;
let parts: Vec<_> = param.split(".").collect();
Expand All @@ -298,12 +283,13 @@ fn handlebars() -> Result<Handlebars> {
if i + 1 == parts.len() {
handlebars::html_escape(&part)
} else {
let path = (0..(current_module_level - i - index_offset))
let path = (0..(current_module_level - i - 1))
.map(|_| "../")
.format("");
format!(
r##"<a href="{}index.html">{}</a>"##,
r##"<a href="{}{}.html">{}</a>"##,
path,
current_module.split('.').rev().nth(1).unwrap_or(""),
handlebars::html_escape(&part)
)
},
Expand Down Expand Up @@ -413,17 +399,46 @@ where
}

pub fn generate_for_path_(thread: &Thread, path: &Path, out_path: &Path) -> Result<()> {
let mut directories = BTreeMap::new();
let mut directories = BTreeMap::<_, BTreeMap<_, Module>>::new();
let mut content = String::new();

for entry in walkdir::WalkDir::new(path) {
let entry = entry?;
if !entry.file_type().is_file()
|| entry.path().extension().and_then(|ext| ext.to_str()) != Some("glu")
{
if entry.file_type().is_dir() {
directories.insert(entry.path().to_owned(), BTreeMap::new());
if !directories.contains_key(&entry.path().with_extension("glu")) {
// Generate a directory module
debug!("Indexing directory, no module: {}", entry.path().display());
let name = filename_to_module(
entry
.path()
.to_str()
.ok_or_else(|| failure::err_msg("Non-UTF-8 filename"))?,
);
directories
.entry(entry.path().parent().expect("Parent dir").to_owned())
.or_default()
.insert(
name.clone(),
Module {
name,
comment: "".into(),
record: Record::default(),
},
);
} else {
debug!(
"Indexing directory with existing module: {}",
entry.path().display()
);
directories.insert(entry.path().to_owned(), BTreeMap::new());
}
}
continue;
}
debug!("Indexing module: {}", entry.path().display());

let mut input = File::open(&*entry.path()).with_context(|err| {
format!(
Expand All @@ -432,7 +447,7 @@ pub fn generate_for_path_(thread: &Thread, path: &Path, out_path: &Path) -> Resu
err
)
})?;
let mut content = String::new();
content.clear();
input.read_to_string(&mut content)?;

let name = filename_to_module(
Expand Down Expand Up @@ -464,25 +479,24 @@ pub fn generate_for_path_(thread: &Thread, path: &Path, out_path: &Path) -> Resu
comment,
};

directories
.get_mut(entry.path().parent().expect("Parent path"))
.expect("Directory before this file")
.insert(module.name.clone(), module);
}

#[derive(Serialize)]
struct Index<'a> {
name: String,
directories: &'a [String],
modules: &'a [&'a Module],
match directories.entry(entry.path().parent().expect("Parent path").to_owned()) {
btree_map::Entry::Occupied(entry) => {
entry.into_mut().insert(module.name.clone(), module);
}
btree_map::Entry::Vacant(entry) => {
entry.insert(collect![(module.name.clone(), module)]);
}
}
}

let reg = handlebars()?;

for (path, modules) in &directories {
for modules in directories.values() {
for module in modules.values() {
let out_path =
out_path.join(PathBuf::from(module.name.replace(".", "/")).with_extension("html"));
debug!("Documenting {}", module.name);

let module_path = PathBuf::from(module.name.replace(".", "/"));
let out_path = out_path.join(&module_path).with_extension("html");
let mut doc_file = File::create(&*out_path).with_context(|err| {
format!(
"Unable to open output file `{}`: {}",
Expand All @@ -498,42 +512,15 @@ pub fn generate_for_path_(thread: &Thread, path: &Path, out_path: &Path) -> Resu
name: &module.name,
comment: &module.comment,
record: &module.record,
sibling_modules: modules.keys().map(|s| &**s).collect(),
sub_modules: directories
.get(&module_path)
.iter()
.flat_map(|sub_modules| sub_modules.values())
.collect(),
sibling_modules: modules.keys().map(|s| s as &str).collect(),
},
)?;
}

let index_path = out_path.join(&*path).join("index.html");
trace!("Rendering index: {}", index_path.display());
let mut doc_file = File::create(&*index_path).with_context(|err| {
format!(
"Unable to open output file `{}`: {}",
index_path.display(),
err
)
})?;

let name = filename_to_module(
path.to_str()
.ok_or_else(|| failure::err_msg("Non-UTF-8 filename"))?,
);

let directory_modules: Vec<_> = directories
.keys()
.filter(|dir_path| Some(&**path) == dir_path.parent())
.map(|dir_path| filename_to_module(dir_path.to_str().unwrap()))
.collect();

reg.render_to_write(
INDEX_TEMPLATE,
&Index {
name,
directories: &directory_modules,
modules: &modules.values().collect::<Vec<_>>(),
},
&mut doc_file,
)
.with_context(|err| format!("Unable to render index {}: {}", index_path.display(), err))?;
}

let mut style_sheet = File::create(out_path.join("style.css"))?;
Expand Down
4 changes: 3 additions & 1 deletion doc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ fn main_() -> Result<(), failure::Error> {
gluon_doc::generate_for_path(&gluon::new_vm(), &opt.input, &opt.output)?;

if opt.open {
let path = Path::new(&opt.output).join(&opt.input).join("index.html");
let path = Path::new(&opt.output)
.join(&opt.input)
.with_extension("html");
eprintln!("Opening {}", path.display());
opener::open(path)?;
}
Expand Down

0 comments on commit fdab790

Please sign in to comment.