To provide for weaving in plain text format, which is not very interesting, but ought to be available.


§1. Creation.

void PlainTextWeaving::create(void) {
    weave_format *wf = WeavingFormats::create_weave_format(I"plain", I".txt");
    METHOD_ADD(wf, RENDER_FOR_MTID, PlainTextWeaving::render);
}

§2. Markdown rendering instructions. While the code in this section renders the weave tree, the actual commentary (along with other fragments, such as comments in code, depending on the conventions used) is stored in Markdown, and needs to be handed over to the code in Markdown Rendering (in foundation).

That needs a set of instructions, to say what kind of Markdown, how we want it rendered, and so on.

markdown_render PlainTextWeaving::Markdown_instructions(weave_order *wv) {
    markdown_render rdr = MDRender::contextual_plain_text(
        WebNotation::commentary_variation(wv->weave_web),
        STORE_POINTER_weave_order(wv));
    return rdr;
}

§3. Rendering. The weave tree will be rendered by traversing it, and rendering each node in its turn.

void PlainTextWeaving::render(weave_format *self, text_stream *OUT, heterogeneous_tree *tree) {
    weave_document_node *C = RETRIEVE_POINTER_weave_document_node(tree->root->content);
    PlainText_render_state prs;
    Initialise the render state3.2;
    Trees::traverse_from(tree->root, &PlainTextWeaving::render_visit, (void *) &prs, 0);
}

§3.1. The following state will be carried through the traverse, though it contains no fluctuating content, just instructions on what to do.

classdef PlainText_render_state {
    struct text_stream *OUT;
    struct weave_order *wv;
    struct markdown_render rdr;
} PlainText_render_state;

§3.2. Initialise the render state3.2 =

    prs.OUT = OUT;
    prs.wv = C->wv;
    prs.rdr = PlainTextWeaving::Markdown_instructions(C->wv);

§4. So, then, the visiting function, called on each node. C does not allow switch statements whose cases are not literal constants, so there's a big contrived if instead. But it is morally a switch.

int PlainTextWeaving::render_visit(tree_node *N, void *state, int L) {
    PlainText_render_state *prs = (PlainText_render_state *) state;
    text_stream *OUT = prs->OUT;

    /* Document superstructure */

         if (N->type == weave_document_node_type) Skip4.1
    else if (N->type == weave_head_node_type) Skip4.1
    else if (N->type == weave_body_node_type) Skip4.1
    else if (N->type == weave_tail_node_type) Skip4.1

    /* Large-scale structure */

    else if (N->type == weave_chapter_node_type) Skip4.1
    else if (N->type == weave_chapter_header_node_type) Render chapter header4.3
    else if (N->type == weave_chapter_footer_node_type) Skip4.1
    else if (N->type == weave_section_node_type) Skip4.1
    else if (N->type == weave_section_header_node_type) Render section header4.4
    else if (N->type == weave_section_footer_node_type) Render section footer4.5
    else if (N->type == weave_section_purpose_node_type) Render section purpose4.6
    else if (N->type == weave_toc_node_type) Skip4.1
    else if (N->type == weave_toc_line_node_type) Skip4.1

    /* Small-scale structure */

    else if (N->type == weave_subheading_node_type) Render subheading4.7
    else if (N->type == weave_subsubheading_node_type) Render subsubheading4.8
    else if (N->type == weave_paragraph_heading_node_type) Render paragraph heading4.9
    else if (N->type == weave_material_node_type) Skip4.1

    /* Code-like material */

    else if (N->type == weave_holon_declaration_node_type) Render holon declaration4.10
    else if (N->type == weave_code_line_node_type) Render code line4.11
    else if (N->type == weave_holon_usage_node_type) Render holon usage4.12
    else if (N->type == weave_tangler_command_node_type) Skip4.1
    else if (N->type == weave_verbatim_node_type) Render verbatim4.13
    else if (N->type == weave_source_code_node_type) Render source code4.14
    else if (N->type == weave_function_defn_node_type) Render function defn4.15
    else if (N->type == weave_function_usage_node_type) Render function usage4.16
    else if (N->type == weave_comment_in_holon_node_type) Render comment in holon4.17
    else if (N->type == weave_defn_node_type) Render defn4.18

    /* Commentary and gadget material */

    else if (N->type == weave_markdown_node_type) Render Markdown4.19
    else if (N->type == weave_audio_node_type) Skip4.1
    else if (N->type == weave_carousel_slide_node_type) Skip4.1
    else if (N->type == weave_download_node_type) Skip4.1
    else if (N->type == weave_embed_node_type) Render embed4.20
    else if (N->type == weave_figure_node_type) Skip4.1
    else if (N->type == weave_raw_HTML_node_type) Skip4.1
    else if (N->type == weave_video_node_type) Skip4.1

    /* Paragraph tail material */

    else if (N->type == weave_index_begins_node_type) Render index begins4.21
    else if (N->type == weave_index_lemma_node_type) Render index lemma4.22
    else if (N->type == weave_index_ends_node_type) Render index ends4.23
    else if (N->type == weave_endnote_node_type) Render endnote4.2
    else if (N->type == weave_locale_node_type) Render locale4.24
    else if (N->type == weave_endnote_text_node_type) Render endnote text4.25

    else internal_error("no HTML rendering for this node type");
    return TRUE;
}

§4.1. Skip4.1 =

    ;

§4.2.1. By default, the visitor function returns TRUE at each node (see above). This tells the tree-traversing machinery to continue recursing down through that node's children after the node itself has been visited.

Some nodes, however, will want to render something, then recurse downwards, then render something further. They can do this by using the following holon to perform the recursion, but must then explicitly return FALSE, or else the child nodes will end up being visited a second time.

Recurse the renderer through children nodes4.2.1 =

    for (tree_node *M = N->child; M; M = M->next)
        Trees::traverse_from(M, &PlainTextWeaving::render_visit, (void *) prs, L+1);

§4.3. Large-scale structure renderers. Render chapter header4.3 =

    weave_chapter_header_node *C = RETRIEVE_POINTER_weave_chapter_header_node(N->content);
    WRITE("%S\n\n", C->chap->ch_title);
    ls_section *S;
    LOOP_OVER_LINKED_LIST(S, ls_section, C->chap->sections) {
        WRITE("  %S\n    %S\n", S->sect_title, LiterateSource::unit_purpose(S->literate_source));
        WRITE("\n");
    }
    WRITE("\n");

§4.4. Render section header4.4 =

    weave_section_header_node *C = RETRIEVE_POINTER_weave_section_header_node(N->content);
    WRITE("%S\n\n", C->sect->sect_title);

§4.5. Render section footer4.5 =

    WRITE("\n\n");

§4.6. Render section purpose4.6 =

    weave_section_purpose_node *C = RETRIEVE_POINTER_weave_section_purpose_node(N->content);
    MDRender::stream(OUT, &(prs->rdr), C->purpose, 0);
    WRITE("\n");

§4.7. Small-scale structure renderers. Render subheading4.7 =

    weave_subheading_node *C = RETRIEVE_POINTER_weave_subheading_node(N->content);
    WRITE("%S\n\n", C->text);

§4.8. Render subsubheading4.8 =

    weave_subsubheading_node *C = RETRIEVE_POINTER_weave_subsubheading_node(N->content);
    WRITE("%S\n\n", C->text);

§4.9. Render paragraph heading4.9 =

    weave_paragraph_heading_node *C = RETRIEVE_POINTER_weave_paragraph_heading_node(N->content);
    WRITE("\n");
    WRITE("%S%S", LiterateSource::par_ornament(C->para), C->para->paragraph_number);
    text_stream *title = LiterateSource::par_title(C->para);
    if (Str::len(title) > 0) WRITE(" %S", title);
    WRITE(".  ");

§4.10. Code-like material renderers. Render holon declaration4.10 =

    weave_holon_declaration_node *C = RETRIEVE_POINTER_weave_holon_declaration_node(N->content);
    WRITE("<%S (%S)> =",
        C->holon->holon_name, C->holon->corresponding_chunk->owner->paragraph_number);

§4.11. Render code line4.11 =

    for (tree_node *M = N->child; M; M = M->next)
        Trees::traverse_from(M, &PlainTextWeaving::render_visit, (void *) prs, L+1);
    WRITE("\n");
    return FALSE;

§4.12. Render holon usage4.12 =

    weave_holon_usage_node *C = RETRIEVE_POINTER_weave_holon_usage_node(N->content);
    WRITE("<%S (%S)>",
        (C->holon)?(C->holon->holon_name):NULL, C->holon->corresponding_chunk->owner->paragraph_number);

§4.13. Render verbatim4.13 =

    weave_verbatim_node *C = RETRIEVE_POINTER_weave_verbatim_node(N->content);
    WRITE("%S", C->content);

§4.14. Render source code4.14 =

    weave_source_code_node *C = RETRIEVE_POINTER_weave_source_code_node(N->content);
    WRITE("%S", C->matter);

§4.15. Render function defn4.15 =

    weave_function_defn_node *C = RETRIEVE_POINTER_weave_function_defn_node(N->content);
    WRITE("%S", C->fn->function_name);
    return TRUE;

§4.16. Render function usage4.16 =

    weave_function_usage_node *C = RETRIEVE_POINTER_weave_function_usage_node(N->content);
    WRITE("%S", C->fn->function_name);

§4.17. Render comment in holon4.17 =

    weave_comment_in_holon_node *C = RETRIEVE_POINTER_weave_comment_in_holon_node(N->content);
    WRITE("%S", C->comment_open);
    WRITE("%S", C->raw);
    WRITE("%S", C->comment_close);

§4.18. Render defn4.18 =

    weave_defn_node *C = RETRIEVE_POINTER_weave_defn_node(N->content);
    WRITE("%S ", C->keyword);

§4.19. Commentary and gadget material renderers. Render Markdown4.19 =

    weave_markdown_node *C = RETRIEVE_POINTER_weave_markdown_node(N->content);
    MDRender::render(OUT, &(prs->rdr), C->content);

§4.20. Render embed4.20 =

    weave_embed_node *C = RETRIEVE_POINTER_weave_embed_node(N->content);
    WRITE("[See %S video with ID %S.]\n", C->service, C->ID);

§4.21. Paragraph tail material renderers. Render index begins4.21 =

    WRITE("\nIndex:\n\n");

§4.22. Render index lemma4.22 =

    weave_index_lemma_node *C = RETRIEVE_POINTER_weave_index_lemma_node(N->content);
    ls_index_lemma *lemma = C->lemma;
    for (ls_index_lemma *l2 = lemma->parent; l2; l2 = l2->parent) WRITE("  ");
    if (lemma->style == 2) WRITE("`");
    if (lemma->style == 3) WRITE("/");
    WRITE("%S", lemma->text);
    if (lemma->style == 2) WRITE("`");
    if (lemma->style == 3) WRITE("/");
    ls_index_mark *mark; int c = 0;
    LOOP_OVER_LINKED_LIST(mark, ls_index_mark, lemma->marks) {
        if (c++ > 0) WRITE(", "); else WRITE("  ");
        if (mark->important) WRITE("_");
        WRITE("%S", mark->at->paragraph_number);
        if (mark->important) WRITE("_");
    }
    WRITE("\n");

§4.23. Render index ends4.23 =

    WRITE("\n");

§4.2. Render endnote4.2 =

    Recurse the renderer through children nodes4.2.1;
    WRITE("\n");
    return FALSE;

§4.24. Render locale4.24 =

    weave_locale_node *C = RETRIEVE_POINTER_weave_locale_node(N->content);
    WRITE("%S%S", LiterateSource::par_ornament(C->par1), C->par1->paragraph_number);
    if (C->par2) WRITE("-%S", C->par2->paragraph_number);

§4.25. Render endnote text4.25 =

    weave_endnote_text_node *C = RETRIEVE_POINTER_weave_endnote_text_node(N->content);
    WRITE("%S", C->text);