From e975bd5b30eb7f3f46cba32e16ca813e110bc497 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 15 Feb 2020 08:35:43 +0200 Subject: Change: require docgen, codegen to fail if document has no title sp-filter already has a test that requires it to work without a title. --- src/ast.rs | 9 +++++++++ src/bin/sp-codegen.rs | 2 ++ src/bin/sp-docgen.rs | 1 + subplot.md | 43 +++++++++++++++++++++++++++++++++++++++++++ subplot.py | 13 +++++++++++-- subplot.yaml | 9 +++++++++ templates/python.py | 6 +++++- 7 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index e6fd5db..f59d9f4 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -109,6 +109,15 @@ impl<'a> Document { self.files.files() } + /// Check that document has a title in its metadata. + pub fn has_title(&self) -> Result<()> { + if self.meta().title().is_empty() { + Err(Error::no_title()) + } else { + Ok(()) + } + } + /// Typeset a Subplot document. pub fn typeset(&mut self) { let mut visitor = TypesettingVisitor::new(&self.meta.bindings); diff --git a/src/bin/sp-codegen.rs b/src/bin/sp-codegen.rs index 3342b97..e15a8e2 100644 --- a/src/bin/sp-codegen.rs +++ b/src/bin/sp-codegen.rs @@ -50,6 +50,8 @@ fn main() -> Result<()> { let scenarios = doc.matched_scenarios()?; let meta = doc.meta(); + doc.has_title()?; + let mut context = Context::new(); context.insert("scenarios", &scenarios); diff --git a/src/bin/sp-docgen.rs b/src/bin/sp-docgen.rs index c9e4879..fc53e47 100644 --- a/src/bin/sp-docgen.rs +++ b/src/bin/sp-docgen.rs @@ -52,6 +52,7 @@ fn main() -> subplot::Result<()> { // file from the AST. pandoc.add_filter(|json| { let mut doc = subplot::Document::from_json(&json).expect("error parsing JSON AST"); + doc.has_title().expect("document has no title"); doc.typeset(); doc.ast().expect("error serializing into JSON AST") }); diff --git a/subplot.md b/subplot.md index 7c72ea8..59e9736 100644 --- a/subplot.md +++ b/subplot.md @@ -736,6 +736,49 @@ given precondition foo ~~~~ +### Document titles + +The document and code generators require a document title, because +it's a common user error to not have one, and Subplot should help make +good documents. The Pandoc filter, however, mustn't require a document +title, because it's used for things like formatting websites using +ikiwiki, and ikiwiki has a different way of specifying page titles. + +#### Document generator gives an error if input document lacks title + +~~~scenario +given file notitle.md +when I try to run sp-docgen notitle.md -o foo.md +then exit code is non-zero +~~~ + +~~~{.file #notitle.md .markdown .numberLines} +--- +bindings: b.yaml +functions: f.py +... + + +# Introduction + +This is a very simple Markdown file without a YAML metadata block, +and thus also no document title. + +```scenario +given precondition foo +when I do bar +then bar was done +~~~ + +#### Code generator gives an error if input document lacks title + +~~~scenario +given file notitle.md +when I try to run sp-codegen --run notitle.md -o test.py +then exit code is non-zero +~~~ + + Using a Pandoc filter ----------------------------------------------------------------------------- diff --git a/subplot.py b/subplot.py index f4549ee..57b0fa5 100644 --- a/subplot.py +++ b/subplot.py @@ -6,15 +6,21 @@ def create_file(ctx, filename=None): with open(filename, 'wb') as f: f.write(get_file(filename)) -def run_docgen(ctx, md=None, output=None): +def try_docgen(ctx, md=None, output=None): docgen = binary('sp-docgen') runcmd(ctx, [docgen, md, '-o', output]) + +def run_docgen(ctx, md=None, output=None): + try_docgen(ctx, md=md, output=output) exit_code_zero(ctx) -def run_codegen(ctx, filename=None): +def try_codegen(ctx, filename=None): codegen = binary('sp-codegen') tmpldir = os.path.join(srcdir, 'templates') runcmd(ctx, [codegen, filename, '-o', 'test.py', '--run', '--templates', tmpldir]) + +def run_codegen(ctx, filename=None): + try_codegen(ctx, filename=filename) exit_code_zero(ctx) def run_meta(ctx, filename=None): @@ -50,6 +56,9 @@ def exit_code_zero(ctx): print('context:', ctx.as_dict()) assert_eq(ctx.get('exit'), 0) +def exit_code_nonzero(ctx): + assert_ne(ctx.get('exit'), 0) + def binary(basename): return os.path.join(srcdir, 'target', 'debug', basename) diff --git a/subplot.yaml b/subplot.yaml index 1f8acb2..e309d78 100644 --- a/subplot.yaml +++ b/subplot.yaml @@ -4,15 +4,24 @@ - when: I run sp-docgen (?P\S+) -o (?P\S+) function: run_docgen +- when: I try to run sp-docgen (?P\S+) -o (?P\S+) + function: try_docgen + - when: I run sp-codegen --run (?P\S+) -o test.py function: run_codegen +- when: I try to run sp-codegen --run (?P\S+) -o test.py + function: try_codegen + - when: I run sp-meta (?P\S+) function: run_meta - when: I run pandoc --filter sp-filter (?P\S+) -o (?P\S+) function: run_pandoc_with_filter +- then: exit code is non-zero + function: exit_code_nonzero + - then: file (?P\S+) exists function: file_exists diff --git a/templates/python.py b/templates/python.py index d8905f1..5768534 100644 --- a/templates/python.py +++ b/templates/python.py @@ -43,10 +43,14 @@ _files['''{{ file.filename }}'''] = '''{{ file.contents | base64 }}''' def get_file(filename): return base64.b64decode(_files[filename]) -# Check two values for equality and give error if they +# Check two values for equality and give error if they are not equal def assert_eq(a, b): assert a == b, 'expected %r == %r' % (a, b) +# Check two values for inequality and give error if they are equal +def assert_ne(a, b): + assert a != b, 'expected %r != %r' % (a, b) + # Remember where we started from. The step functions may need to refer # to files there. srcdir = os.getcwd() -- cgit v1.2.1