tango
: dancing around literate programming@pnkfelix
), Mozillatango
: dancing around literate programming
tango
?tango
:I have been using for tutorial presentations:
(meta: written with tango
; see http://bit.ly/2618VSS
)
http://pnkfelix.github.io/presentations/
reveal.js
+ pandoc
, not tango
pandoc
crate; "just" shells out to pandoc
. (Sorry.)(meta: written with tango
; see http://bit.ly/2618VSS
)
http://pnkfelix.github.io/presentations/
```rust
pub fn main() { println!("Hello post `tango`"); }
```
* What is Literate Programming (LP)?
* What is `tango`'s approach to LP?
% cargo run
Compiling tango-demo v0.1.0 (file:///Users/fklock/Dev/Rust/tango-demo)
Running `target/debug/main`
Hello post `tango`
(cargo
build script pushes tango
onto dance floor.)
```rust
pub fn main() { println!("Hello post `tango`"); }
```
* What is Literate Programming (LP)?
* What is `tango`'s approach to LP?
pub fn main() { println!("Hello post `tango`"); }
//@ * What is Literate Programming (LP)?
//@
//@ * What is `tango`'s approach to LP?
```rust
pub fn main() { println!("Hello post `tango`"); }
```
* What is Literate Programming (LP)?
* What is `tango`'s approach to LP?
pub fn main() { println!("Hello post `tango`"); }
What is Literate Programming (LP)?
What is tango
's approach to LP?
This is Hello World
pub fn hello_world() {
println!
is a macro. It prints things.
println!("Hello World");
Close curly }
ends the scope.
}
That's all folks!
Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
-- Donald Knuth, 1983
http://www.literateprogramming.com/knuthweb.pdf
(Examples include TeX, Metafont, SGB.)
Programmer edits .web
; utils create intermediate source
(WEB tangle
output "write-only"; IMO weave
is too)
Architecture motivated (in part) by language limitations
tango
is neither tangle
nor weave
!
Edit either; tango
regenerates the other
One should cargo build
before switch between .rs
/.md
But: editing both first will not destroy work!
cargo
Cargo.toml:
build = "tango-build.rs"
[build-dependencies]
tango = "0.5.0"
tango-build.rs:
extern crate tango;
fn main() { tango::process_root().unwrap() }
tango
'ingtwo line-oriented state machines [+ timestamp
(72 loc)]
rs2md
(219 loc): rust code ↦ ```rust
-blocks
md2rs
(195 loc): markdown ↦ //@
-prefixed comments
Range of tango
= domain of submap
Edits remain in domain of tango
(usually)
Outside submap: content "adjusted" by tango
...
... but (tango
○ tango
) idempotent
tango
runs in response to cargo build
And tango
updates/creates source files
cargo build
to reprocess and rebuild (every time).Goal: no unnecessary cargo
rebuilds
The trick
(also: timestamp separate file to detect if both modified)
Encoding attributes attached to code blocks (//@@
)
e.g. //@@ { .attribute1 .attribute2 }
Playpen link integration (//@@@
)
e.g. //@@@ playpen link name
//@ You can follow [stripey] to the *playpen*!
//@@ { .stripes }
#[test]
pub fn blinking_code() {
println!("This code does not actually blink");
}
//@@@ stripey
tango
into:You can follow stripey to the playpen!
#[test]
pub fn blinking_code() {
println!("This code does not actually blink");
}
(assuming appropriate CSS definition for .stripes
)
Note that above link works
(meta: written with tango
; see http://bit.ly/2618VSS
)