-
Notifications
You must be signed in to change notification settings - Fork 6
Jinja Template for Weaving [Completed]
Planned for https://github.com/slott56/py-web-tool/milestone/2
The essence of weaving seems to be rendering the following kinds of chunks
-
Chunk
base class for anonymous chunks of the file -
NamedChunk
class for defined names, created with@d name @{...@}
-
OutputChunk
class for output files, created with@o file @{...@}
-
NamedDocumentChunk
class@d name @[...@]
. A special case of a named chunk. It's only woven when referenced; the definition is silenced. This lets us defined repeated words, phrases or values. They're never tangled into code, and are expanded in-place when weaving.
These define the various "major commands", @d name @{...@}
, @o name @{...@}
, and anonymous text.
Within each Chunk
are a series of commands of the following classes:
-
TextCommand
class to contain a document text block. Woven without change. -
CodeCommand
class to contain a program source code block. Woven with quoting for symbols that might mess up the publication chain. -
ReferenceCommand
class for chunk references. A@<name@>
reference to a@d name @{...@}
block of code or a@d name @[...@]
block of text. Option 1 is to expand these prior to weaving. Option 2 is to use a property for the value which expands at weaving time. -
XrefCommand
superclass for the cross-reference summary commands.-
FileXrefCommand
class for an output file cross-reference. The@f
command. -
MacroXrefCommand
class for a named chunk cross-reference. The@m
command. -
UserIdXrefCommand
class for a user identifier cross-reference. The@u
command.
-
Note that any kind of Chunk
can have a @<...@>
ReferenceCommand
reference in it. There are two cases:
- A
@[...@]
definition is expanded in-line. This can be recursive. Ideally, it's done in advance. Loops -- of course -- are invalid. - A
@{...@}
definition gets a hyperlink reference.
The outline of weaving is (in part) a nested set of {% for %}
and {% if %}
statements.
For the Named Chunks and Output Chunks, we insert a begin_code(chunk)
and code_end(chunk)
to provide the wrapper around a code example.
{% for chunk in web.chunks -%}
{%- if chunk.typeid.OutputChunk or chunk.typeid.NamedChunk -%}{{begin_code(chunk)}}{%- endif -%}
{% for command in chunk.commands -%}
{%- if command.typeid.TextCommand %}{{text(command)}}
{%- elif command.typeid.CodeCommand %}{{code(command)}}
{%- elif command.typeid.ReferenceCommand %}{{ref(command)}}
{%- elif command.typeid.FileXrefCommand %}{{file_xref(command)}}
{%- elif command.typeid.MacroXrefCommand %}{{macro_xref(command)}}
{%- elif command.typeid.UserIdXrefCommand %}{{userid_xref(command)}}
{% endif -%}
{%- endfor %}
{%- if chunk.typeid.OutputChunk or chunk.typeid.NamedChunk -%}{{end_code(chunk)}}{%- endif -%}
{%- endfor %}
The various {{text(command)}}
, {{code(command)}}
, and {{ref(command)}}
, etc., constructs are macros
that are provided by the tool, and can be modified by the user.
{%- macro text(command) -%}
{{command.text}}
{%- endmacro -%}
{% macro code(command) -%}
.. _`{{command.seq}}`::
.. rubric:: {{command.name}} ({{command.seq}}) =
.. parsed-literal::
{% for line in command.lines.splitlines() -%}
{{line | quote_rules}}
{% endfor %}
{% endmacro -%}
{% macro file_xref(command) -%}
{% for file in web.files -%}
:{{file.name}}:
{{ref(file.seq)}}
{%- endfor %}
{%- endmacro -%}
{% macro macro_xref(command) -%}
{% for macro in web.macros -%}
:{{macro.full_name}}:
{{ref_list(macro.seq_list)}}
{%- endfor %}
{%- endmacro -%}
{% macro userid_xref(command) -%}
{% for userid in web.userids -%}
:{{userid.userid}} {{ref(userid.seq)}}:
{{ref_list(userid.used_list)}}
{%- endfor %}
{%- endmacro -%}
{% macro ref(id) -%}
→\ `{{id}}`_
{%- endmacro -%}
{% macro ref_list(refs) -%}
{% for r in refs -%}{{ref(r)}}{% if loop.last %}{% else %}, {% endif %}{%- endfor %}
{%- endmacro -%}
Here's a mock of the Web
-> Chunk
-> Command
structure.
web = SimpleNamespace(
chunks=[
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="Title\n=====\n\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(CodeCommand=True), lines='print("Hello, World!")\n', name="hw.py", seq=1)], # OutputChunk
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="Conclusion...\n\nMore thoughts.\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="Appendices\n==========\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="Files\n-----\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(FileXrefCommand=True))], # Chunk
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="\n\nMacros\n------\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(MacroXrefCommand=True))], # Chunk
[SimpleNamespace(type=SimpleNamespace(TextCommand=True), text="\n\nNames\n------\n\n")], # Chunk
[SimpleNamespace(type=SimpleNamespace(UserIdXrefCommand=True))], # Chunk
],
files=[SimpleNamespace(name="hw.py", seq="1")],
macros=[SimpleNamespace(full_name="example code", seq_list=["2"])],
userids=[SimpleNamespace(userid="print", seq=["2"], used_list=["3", "4"])]
)