Skip to content
a literate programming tool to write common lisp codes in org mode.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore
.travis.yml
literate-demo.asd
literate-lisp.asd
readme.org
tangle.lisp
tangle.org
tangle.pdf

readme.org

https://travis-ci.com/jingtaozf/literate-lisp.svg?branch=master http://quickdocs.org/badge/literate-lisp.svg

Table of Contents

Introduction

literate-lisp provides an easy way to use literal programming in common lisp language. It extends the common lisp reader syntax so a common lisp vendor can read org files as common lisp source files.

By using this package(literate-lisp), Emacs org mode and elisp library polymode, literate programming can be very easy in one org file containing both documentation and source codes, and this org file can interact well with SLIME.

The implementation detail of literate-lisp is in file ./tangle.org (pdf version).

This library contains the following files:

Tutorial

install polymode in Emacs

It’s better to edit the org file with polymode,which will make code block use its native file mode. The following elisp scripts in .emacs will install it.

(use-package poly-org
    :ensure t)

a new code block header argument load

Please have a look of the section function to handle reader syntax for “# “(# + Space) in ./tangle.org.

A demo lisp package

Prepare the ASD definition file

We use the original ASD definition file, and extend the ASDF syntax(The documentation of extended ASDF syntax can be found in tangle.org).

In a short word,we should load literate-lisp by ASDF keyword :defsystem-depends-on and declare the org source file with new ASDF keyword :org.

Now let’s define the ASDF system file ./literate-demo.asd for this demo package

(asdf:defsystem literate-demo
  :author "Xu Jingtao <jingtaozf@gmail.com>"
  :version "0.1"
  :licence "MIT"
  :serial t
  :description "an demo project of literate-lisp"
  :defsystem-depends-on ("literate-lisp")
  :components ((:module :demo :pathname "./"
                        :components ((:org "readme"))))
  :properties ((version "0.1")))

Which will load this ./readme.org directly as a lisp source file.

The whole content of ASDF definition file is in ./literate-demo.asd.

package definition

Firstly we define a new package for this demo project and switch to it.

(in-package :common-lisp-user)
(defpackage :literate-demo (:use :cl))
(in-package :literate-demo)

a demo function to a recursive assoc implementation

As a demo project, we just show a demo function recursive-assoc here.

The function assoc only find first level item from an association list. When I want to find item from an association list contains a lot of other association list with very deep level, I have to write codes like this which is too long.

(cdr (assoc :b (cdr (assoc :a '((:a . ((:b . c))))))))

To simplify the expression, a macro recursive-assoc to simply to the following form provides:

(recursive-assoc '((:a . ((:b . c)))) :a :b)

A macro function to expand lisp expressions recursively provides firstly.

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun expand-recursive-assoc (alist recursive-properties)
    (if (cdr recursive-properties)
      (expand-recursive-assoc `(cdr (assoc ,(car recursive-properties) ,alist))
                              (cdr recursive-properties))
      `(cdr (assoc ,(car recursive-properties) ,alist)))))

Then the implementation macro is simple(test is here: ref:test-recursive-assoc)

(defmacro recursive-assoc (alist &rest recursive-properties)
  (when recursive-properties
    (expand-recursive-assoc alist recursive-properties)))

For example, you can use it like this,which get :b part of the sub association list which is :a part of the original list.

(equal 'c (recursive-assoc '((:a . ((:b . c)))) :a :b))

Test cases for this demo project

Preparation

Now it’s time to validate some functions. The FiveAM library is used to test.

(eval-when (:compile-toplevel :load-toplevel :execute)
  (unless (find-package :fiveam)
    #+quicklisp (ql:quickload :fiveam)
    #-quicklisp (asdf:load-system :fiveam)))
(5am:def-suite literate-demo-suite :description "The test suite of literate-demo.")
(5am:in-suite literate-demo-suite)

tests for recursive-assoc

label:test-recursive-assoc

(5am:test recursive-assoc 
  (5am:is (equal 'c (recursive-assoc '((:a . ((:b . c)))) :a :b))))

run all tests in this library

This function is the entry point to run all tests and return true if all test cases pass.

(defun run-test ()
  (5am:run! 'literate-demo-suite))

Web service travis ci will load config file ./.travis.yml to run these tests automatically every time there is a new git change.

You can’t perform that action at this time.