Skip to content

adam-ard/literate-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 

Repository files navigation

EmacsConf Demo

Description

This project demonstrates how to use literate programming inside of Emacs. Using this README.org as the source, you can generate markdown documentation as well as source code. This strategy has several advantages.

  1. It keeps documentation and source code always in sync. Source code is never edited separately from the documentation. They are tightly coupled.
  2. It allows you to present your code in a way that better suits human understanding. Source can be rearranged when it is generated to accommodate a compiler or interpreter.
  3. It allows you to take advantage of all the other features of org-mode that naturally enhance your documentation (embedding diagrams, running code snippets inline, embedding TODO items, time-tracking, and much more)
  4. Since Org-mode is very easy to customize, it allows you to further specialize your personal workflow.
  5. Is allows you to reuse code and reduce code duplication in ways that can be difficult directly in source code.

This document demonstrates many of these benefits and is hopefully a useful starting point for your own literate programming projects.

Tangling and Weaving

When Donald Knuth presented literate programming in 1984, he described two fundamental transformations that can be applied to a literate source document, a tangle and a weave. A tangle generates source code documents in the format appropriate for a compiler or interpreter. A weave produces well formatted documentation with embedded code snippets.

A literate source document, therefore, contains all the source and documentation necessary for these two transformations. For this document, Donald Knuth uses a hybrid of latex and source code. As you would expect, his exported documents are beautifully typeset.

I opted for a little less intensive solution (one day I’ll learn latex) that uses org-mode for my literate source document. Org-mode is well suited to this because it allows prose and code snippets to naturally co-exist. Most importantly, it already has built-in support for basic weaving and tangling.

Below is a diagram illustrating my basic approach. From your README.org file, you “tangle” all your source code, and “weave” your documentation. When I collaborate with people not using Emacs, I typically commit my markdown file and source code, versioning my org file separately in a system of my own–and no one’s the wiser ;)

digraph G {
	
  A -> B [label="tangle"];
  A -> C [label="weave"];

  A [label="README.org"];
	B [label="source code"];
	C [label="README.md"];
}

literate.png

Tangle

To tangle the current file (in other words, to generate the source code), run the following elisp command:

(org-babel-tangle)

The keyboard shortcut for this command is C-c C-v t. To tangle only the file where the cursor is located use the prefix command C-u. So the full command would be C-u C-c C-v t.

To tangle a file into another buffer and not to a file on disk, run C-c C-v C-v with your cursor on the section you would like to tangle. This is a handy way to check how your file will be arranged.

Weave

To weave the current file (in other words, to generate documentation), run the following command:

(org-gfm-export-to-markdown)

Golang installation instructions

To install golang follow these instructions for your operating system.d

https://golang.org/doc/install

Build instructions

The following command will build your project and deposit a executable file called demo in the current directory.

go build

Run

To run a built project, execute the following. After following the steps outlined in “Build Instructions” above:

./demo

Test

To run tests for this project:

go test

Static Analysis

The go vet command can report additional potential problems that the compiler will not catch:

go vet

For more information and options refer to the go documentation.

Formatting

The go fmt will format your source code in a standard way. It is like a linter that actually corrects the problems it finds automatically.

go fmt .

lit-file Snippet

Add a snippet file, to make adding literate programming files easier.

file:~/.emacs.d/snippets/org-mode/lit-file

# -*- mode: snippet -*-
# name: add literate file
# key: lit-file
# --
file:$1
#+begin_src $2 :tangle $1 :noweb no-export
$0
#+end_src

After tangling the above file, run the following to make it available:

(yas-reload-all)

lit-sec Snippet

Add a snippet file, to make adding literate programming sections easier.

file:~/.emacs.d/snippets/org-mode/lit-sec

# -*- mode: snippet -*-
# name: add literate section
# key: lit-sec
# --
$1+=
#+begin_src $2 :noweb no-export :noweb-ref $1
$0
#+end_src

After tangling the above file, run the following to make it available:

(yas-reload-all)

Main

Below is the framework for the main file

file:main.go.m4

package main

import (
	<<imports>>
)

<<functions>>

func main() {
	<<main>>
}

Main code

In main, we say hello and then give you a random number

main+=

SayHello()
GiveRandomNumber()

SayHello()

Say Hello needs to import fmt to be able to print to stdout.

imports+=

"fmt"

SayHello, says hello to you.

functions+=

func SayHello() {
	__("SayHello()")
}

GiveRandomNumber()

Go provides a library for random numbers.

imports+=

"math/rand"
"time"

Print a non-negative number from 0-n

functions+=

func GiveRandomNumber() {
	rand.Seed(time.Now().UnixNano())
	__(rand.Intn(100))
}

Generate Macros

Tangle is effectively a light-weight preprocessor. But, sometimes it is nice to use a macro language that is a little more powerful than the tangling features available in org-mode. In that case, it is simple to use a preprocessor like m4 in concert with the regular literate programming features demonstrated above. If you find yourself wanting to pass an argument to a noweb section, this is what you can do instead.

Run the following to execute m4 on your source file using the m4 macro file defined below:

m4 macros.m4 main.go.m4 > main.go

Macro file

Define a macro that allows you to replace fmt.Printf with a simple symbol __ that is illegal in golang itself. This is not a very useful macro in and of itself, but demonstrates the ability to do even more advanced preprocessing than tangle provides, when needed.

file:macros.m4

define(`__', `fmt.Println($1, time.Now().String())')

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published