Skip to content

Instantly share code, notes, and snippets.

@c0rner
Created March 6, 2018 19:20
Show Gist options
  • Save c0rner/3a7a8a321a1470fcba539aeb50446ce8 to your computer and use it in GitHub Desktop.
Save c0rner/3a7a8a321a1470fcba539aeb50446ce8 to your computer and use it in GitHub Desktop.
Literate programming POC

This is documentation

Below is code that is hidden but will be exported to stdout.

The code below is part of the documentation and will not be exported.

#!/bin/sh
ls -l
echo "This is not exported"

Ths code below will be rendered to a new file demo-export.sh

#!/bin/sh
echo "This is a test file"

Literate Programming

This is a proof-of-concept implementation of literate programming.

The idea is to use documentation as the source for scripts, configuration files or other generating output via an external helper program.

Implementation

This implementation was whipped together using shell scripting and implements a few basic concepts for generating code from markdown.

We will be using the bourne shell interpreter

#!/bin/sh

redirect()

The redirect function is used to modify the stdout target file descriptor. Initially this will always point to /dev/stdout (fd1) but can be remapped to any file or device. Remapping output is persistent.

redirect() {
  local file=$1
  exec 3>"${file}"
}

handle_code_block()

The handle_code_block function implements the two current features of this POC literate programming parser.

handle_code_block() {
  set $*
  while [ $# -gt 0 ]; do
    case $1 in

:file target

The :file modifier will redirect output to the specified target.

      :file) shift; redirect "$1";;

:noexport

Setting this modifier on a code block will disable any output rendering of the code. This can thus be used to include example code in documentation that is not to be rendered to file.

      :noexport) redirect /dev/null;;

:stdout

The :stdout modifier will redirect to standard output

      :stdout) redirect /dev/stdout;;
    esac
    shift
  done
}

main()

The main bulk comes here.

declare -i incode=0

redirect /dev/stdout

sed 's/\\/\\\\/g' | while read LINE; do
  case "${incode}${LINE}" in
    "0\`\`\`"*) incode=1;handle_code_block "${LINE}";continue;;
    "1\`\`\`"*) incode=0;;
  esac
  if [ ${incode} -ne 0 ]; then
    echo ${LINE} >&3
  fi
done
#!/bin/sh
redirect() {
local file=$1
exec 3>"${file}"
}
handle_code_block() {
set $*
while [ $# -gt 0 ]; do
case $1 in
:file) shift; redirect "$1";;
:noexport) redirect /dev/null;;
:stdout) redirect /dev/stdout;;
esac
shift
done
}
declare -i incode=0
redirect /dev/stdout
sed 's/\\/\\\\/g' | while read LINE; do
case "${incode}${LINE}" in
"0\`\`\`"*) incode=1;handle_code_block "${LINE}";continue;;
"1\`\`\`"*) incode=0;;
esac
if [ ${incode} -ne 0 ]; then
echo "${LINE}" >&3
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment