💾 Archived View for stack.tilde.cafe › code › gemlit › gemlit.gmi captured on 2023-09-08 at 16:26:58. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

gemlit

Literal Programming with gemtext prose

(c) Copyright 2021 StackSmith All Rights Reserverd
Distributed under BSD 3-clause license (attached below)

gemlit supports literate programming using gemtext (and markdown), by

commenting away non-code segments of a source file. The comment string is

specified as an optional second parameter, and defaults to // (for C and C++)

The file may contain arbitrary gemtext, mixed with code which must be enclosed

into one or more pre-format blocks bound by lines starting with ```. Such

files may be transmitted and viewed by any gemini browser, and compiled after

commenting non-code text with this utility.

gcc gemlit.c -o gemlit

Usage

gemlit <file> (<comment-marker>)

The processed file is output to stdout for piping into the compiler.

The logistics of using gemlit depend on your preferences. You may wish to

convert an entire directory of files, renaming them from .c gmi to .c. Another

approach is to create a makefile that processes each file, piping it to the

compiler.

========================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 1024
int main(int argc, char** argv) {
  if ((argc < 2) || (argc > 3)) {
      printf("Usage: gemlit <filename> (<comment-marker>)\n");
      printf("Converts a literal gemtext file to a compilable form\n");
      return EXIT_FAILURE;
  }
  FILE* f;
  char buf[BUFSIZE];
  if(!(f = fopen(argv[1],"r"))) {
    fprintf(stderr,"Could not read file %s\n",argv[1]);
    return EXIT_FAILURE;
  }

We default to C/C++ line comment style using //

  char* comment = (argc==3 ? argv[2] : "//");
  int comment_len = (strlen(comment));
  int code = 0;

Process the gemfile one line at a time

  for(;fgets(buf,BUFSIZE,f);) {
    if(!code) {                       // gemtext mode?

We are in gemtext mode. Each line must be commented, and we shall check for the terminator.

      fprintf(stdout,"%s ",comment);  // start with a comment
      fprintf(stdout,"%s",buf);       // then, text
      if(!strncmp("```",buf,3))       // if ```, flip state
        code = ~code;
    } else {                          // code mode?

We are in code mode. But watch out for the terminating ```, as it must be commented-out!

      if(!strncmp("```",buf,3)) {     // first check for terminating ```
        code = ~code;                 // switch to gemtext mode for later
        fprintf(stdout,"%s ",comment); // but comment out the ````
      }
      fprintf(stdout,"%s",buf);        // and output the linr contents
    }
  }
  fclose(f);
  return EXIT_SUCCESS;
}