Constructing a suitable gitignore file for a simple inweb project.

§1. This section offers just one function, which constructs a .gitignore file by following a "prototype".

typedef struct gitignore_state {
    struct web *for_web;
    struct text_stream to_gitignore;
    int last_line_was_blank;  used to suppress runs of multiple blank lines
} gitignore_state;

void Git::write_gitignore(web *W, filename *prototype, filename *F) {
    gitignore_state MS;
    MS.for_web = W;
    MS.last_line_was_blank = TRUE;
    text_stream *OUT = &(MS.to_gitignore);
    if (STREAM_OPEN_TO_FILE(OUT, F, ISO_ENC) == FALSE)
        Errors::fatal_with_file("unable to write tangled file", F);
    WRITE("# This gitignore was automatically written by inweb -gitignore\n");
    WRITE("# and is not intended for human editing\n\n");
    TextFiles::read(prototype, FALSE, "can't open prototype file",
        TRUE, Git::copy_gitignore_line, NULL, &MS);
    STREAM_CLOSE(OUT);
    WRITE_TO(STDOUT, "Wrote gitignore file '%f' from script '%f'\n", F, prototype);
}

§2.

void Git::copy_gitignore_line(text_stream *line, text_file_position *tfp, void *X) {
    gitignore_state *MS = (gitignore_state *) X;
    text_stream *OUT = &(MS->to_gitignore);

    match_results mr = Regexp::create_mr();
    if (Regexp::match(&mr, line, L" *#%c*")) { Regexp::dispose_of(&mr); return; }
    if (Regexp::match(&mr, line, L" *{basics} *")) Expand basics2.1;
    Regexp::dispose_of(&mr);

    And otherwise copy the line straight through2.2;
}

§2.1. Expand basics2.1 =

    filename *prototype =
        Filenames::in(path_to_inweb_materials, I"gitignorescript.txt");
    TextFiles::read(prototype, FALSE, "can't open make settings file",
        TRUE, Git::copy_gitignore_line, NULL, MS);
    Regexp::dispose_of(&mr);
    return;

§2.2. And otherwise copy the line straight through2.2 =

    if (Str::len(line) == 0) {
        if (MS->last_line_was_blank == FALSE) WRITE("\n");
        MS->last_line_was_blank = TRUE;
    } else {
        MS->last_line_was_blank = FALSE;
        WRITE("%S\n", line);
    }