Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shown

Code in documentation, taken from the tests that run it.

A doc example that is not compiled rots, and one that is compiled as a doctest runs in a crate of its own, where proc macros that name the crate they expand in get it wrong. shown keeps examples in ordinary tests and copies them into the pages that show them.

In a test

#[test]
fn a_store_over_a_file() -> anyhow::Result<()> {
    //@show a store over a file
    let store = StoreBuilder::new("./app").build()?;
    //@hide
    let dir = tempfile::tempdir()?;
    //@unhide
    store.port().set(9090)?;
    //@show-end
    Ok(())
}

//@show name .. //@show-end is what a page may show; //@hide .. //@unhide is what it runs but does not show. The common indent comes off.

On a page

Markdown, or a doc comment at any indent. In a .rs file only the doc comments are the page; the code around them is not read.

<!-- shown: a store over a file -->
<!-- /shown -->
/// <!-- shown: a store over a file -->
/// <!-- /shown -->
pub struct Store;

Everything between the two comments is replaced on each fill. Other kinds of region - <!-- printed: .. -->, whatever a project needs - go through the same function, answered by the caller.

In a driver

The library is the grammar; each project keeps its own cargo xtask that says which files are tests and which are pages, which fence a block gets, and whether to write or only check.

let mut marks = shown::Marks::new();
for test in tests {
    marks.read(&test, &fs::read_to_string(&test)?)?;
}

for page in pages {
    let text = fs::read_to_string(&page)?;
    let fence = if page.extension() == Some("rs".as_ref()) { "rust,ignore" } else { "rust" };

    let filled = shown::fill(&page, &text, &["shown"], |asked| marks.block(&asked.arg, fence))?;

    for asked in &filled.unanswered {
        eprintln!("{}:{}: nothing is marked `{}`", page.display(), asked.line, asked.arg);
    }

    if filled.text == text {
        continue;
    }
    if check {
        bail!("{} is out of date; run `cargo xtask docs`", page.display());
    }
    fs::write(&page, filled.text)?;
}

A doc comment wants rust,ignore or text: a plain rust fence there is a doctest again.

Errors name the file and line: a name marked twice, a //@show never closed, a //@show-end closing nothing, a region with no end, a fence left open to the end of its page or its doc comment - which would otherwise turn every region after it into text.

License

MIT or Apache-2.0, at your option.

About

Code in documentation, taken from the tests that run it

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages