summaryrefslogtreecommitdiff
path: root/talk.md
diff options
context:
space:
mode:
Diffstat (limited to 'talk.md')
-rw-r--r--talk.md207
1 files changed, 207 insertions, 0 deletions
diff --git a/talk.md b/talk.md
new file mode 100644
index 0000000..868595f
--- /dev/null
+++ b/talk.md
@@ -0,0 +1,207 @@
+---
+title: Subplot and its implementation in Rust
+author: Lars Wirzenius for the Subplot project
+date: 2019-10-10
+...
+
+ https://subplot.liw.fi/
+
+
+---
+
+Subplot? Let me tell you a story...
+
+---
+
+![](arch.svg)
+
+---
+
+Acceptance criteria are expressed as scenarios (a la Cucumber):
+
+_given_ a system in a specific start state
+_when_ user does some thing
+_then_ system state has changed in the intended way
+_and_ other aspect of state has stayed the same
+
+---
+
+FIXME: Markdown example
+
+---
+
+Currently only docgen exists, codegen will happen soon.
+
+Docgen = Pandoc + Pandoc filter, in Rust
+
+Filter modifies document during typesetting to make document more
+useful for communicating acceptance criteria. Changes how code blocks
+with scenario text are presented.
+
+---
+
+FIXME: Bindings example
+
+---
+
+Bindings connect the scenario step to the code that implements the
+step.
+
+Can extract parts of step to pass to the code as an argument.
+
+Essentially, scenario step is a function call.
+
+---
+
+~~~~rust
+use std::path::PathBuf;
+use structopt::StructOpt;
+
+#[derive(Debug, StructOpt)]
+#[structopt(name = "docgen", about = "...")]
+struct Opt {
+ // One or more input filename.
+ #[structopt(parse(from_os_str))]
+ filenames: Vec<PathBuf>,
+
+ // Set output file name.
+ #[structopt(short="-o", parse(from_os_str))]
+ output: PathBuf,
+}
+
+// in main()
+let opt = Opt::from_args();
+let output = format!("{}", opt.output.display());
+~~~~
+
+---
+
+~~~~rust
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let mut pandoc = pandoc::new();
+
+ ...
+
+ pandoc.add_filter(|json| {
+ pandoc_ast::filter(json, |mut doc| {
+ MyVisitor.walk_pandoc(&mut doc);
+ doc
+ })
+ });
+ pandoc.execute()?;
+
+ ...
+}
+~~~~
+
+---
+
+~~~~rust
+struct MyVisitor;
+
+impl MutVisitor for MyVisitor {
+ fn visit_vec_block(&mut self, blks: &mut Vec<Block>) {
+ for blk in blks {
+ match blk {
+ Block::CodeBlock(attr, s) => {
+ if is_scenario(attr) {
+ *blk = typeset_scenario(s)
+ }
+ }
+ _ => {
+ self.visit_block(blk);
+ }
+ }
+ }
+ }
+}
+~~~~
+
+---
+
+~~~~rust
+// Is a code block marked as a scenario snippet?
+fn is_scenario(attr: &Attr) -> bool {
+ match attr {
+ (_id, classes, _kvpairs) =>
+ classes.iter().any(|s| is_scenario_class(s)),
+ }
+}
+
+fn is_scenario_class(class: &str) -> bool {
+ class == "subplot" || class == "subplot-scenario"
+}
+
+fn typeset_scenario(text: &str) -> Block {
+ Block::LineBlock(
+ text.lines()
+ .map(typeset_scenario_line)
+ .collect())
+}
+~~~~
+
+---
+
+~~~~rust
+fn typeset_scenario_line(line: &str) -> Vec<Inline> {
+ let mut words = line.split_whitespace();
+ let mut inlines = Vec::new();
+
+ if let Some(keyword) = words.next() {
+ typeset_keyword(keyword, &mut inlines);
+ inlines.push(typeset_str(" "));
+ }
+
+ for word in words {
+ inlines.push(typeset_str(word));
+ inlines.push(typeset_str(" "));
+ }
+
+ inlines
+}
+~~~~
+
+---
+
+~~~~rust
+fn typeset_keyword(word: &str, inl: &mut Vec<Inline>) {
+ let word = typeset_str(word);
+ let emph = Inline::Emph(vec![word]);
+ inl.push(emph);
+}
+
+fn typeset_str(s: &str) -> Inline {
+ Inline::Str(s.to_string())
+}
+~~~~
+
+---
+
+The Subplot project is at the very beginning (but Yarn was used for
+six years). Help is welcome.
+
+* What do you think of the concept?
+* What's good?
+* What's less good?
+* Can you see yourself using it?
+* What would it take for you to try it?
+* Do you see Subplot filling a gap for you?
+
+Expect a working version by the end of the year. Patches are welcome,
+but more important now is constructive feedback, especially from
+people who use Subplot, or want to.
+
+---
+
+Free software.
+
+Won't affect the licensing of the outputs. OK to use for proprietary
+systmes.
+
+---
+
+Thank you
+
+---
+
+This talk is licensed CC-BY-SA 4.0 (International)