{"id":22777230,"url":"https://github.com/jingtaozf/literate-lisp","last_synced_at":"2025-04-15T12:27:10.189Z","repository":{"id":49815434,"uuid":"157042297","full_name":"jingtaozf/literate-lisp","owner":"jingtaozf","description":"Load Common Lisp code blocks from Org files","archived":false,"fork":false,"pushed_at":"2023-05-31T03:07:22.000Z","size":1901,"stargazers_count":60,"open_issues_count":1,"forks_count":6,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-05-02T22:12:46.137Z","etag":null,"topics":["emacs","lisp","literate","literate-programming","literate-programs","org","programming"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jingtaozf.png","metadata":{"files":{"readme":"readme.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-11T02:59:41.000Z","updated_at":"2024-04-14T07:59:33.000Z","dependencies_parsed_at":"2024-05-02T11:07:41.355Z","dependency_job_id":"ef8ff581-f195-40d0-ac23-50cee0fed45d","html_url":"https://github.com/jingtaozf/literate-lisp","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingtaozf%2Fliterate-lisp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingtaozf%2Fliterate-lisp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingtaozf%2Fliterate-lisp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingtaozf%2Fliterate-lisp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jingtaozf","download_url":"https://codeload.github.com/jingtaozf/literate-lisp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229277717,"owners_count":18048094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","lisp","literate","literate-programming","literate-programs","org","programming"],"created_at":"2024-12-11T19:13:27.132Z","updated_at":"2024-12-11T19:13:27.939Z","avatar_url":"https://github.com/jingtaozf.png","language":"Common Lisp","funding_links":[],"categories":["Online editors ##"],"sub_categories":["Third-party APIs"],"readme":"# -*- encoding:utf-8 Mode: POLY-ORG;  -*- ---\n#+Startup: noindent\n#+PROPERTY: literate-lang lisp\n#+PROPERTY: literate-load yes\n#+PROPERTY: literate-insert-header no\n\n[[http://quickdocs.org/literate-lisp/][file:http://quickdocs.org/badge/literate-lisp.svg]]\n[[https://github.com/jingtaozf/literate-lisp/actions][file:https://github.com/jingtaozf/literate-lisp/workflows/Continous%20Integration/badge.svg]]\n\n* Table of Contents                                            :TOC:noexport:\n- [[#introduction][Introduction]]\n- [[#tutorial][Tutorial]]\n  - [[#the-restriction-to-the-org-file][The restriction to the Org file]]\n  - [[#install-polymode-in-emacs][install polymode in Emacs]]\n  - [[#how-to-insert-code-block-quickly][how to insert code block quickly]]\n  - [[#a-new-code-block-header-argument-load][a new code block header argument ~load~]]\n  - [[#reference-named-blocks-as-global-parameters][Reference named blocks as global parameters]]\n  - [[#how-to-debug-org-file-in-lispworks-ide][How to debug Org file in LispWorks IDE]]\n  - [[#how-to-integrate-with-namded-readtables][How to integrate with namded-readtables]]\n  - [[#how-to-write-user-initialization-file-with-literate-programming-style][How to write user initialization file with literate programming style]]\n  - [[#how-to-include-org-codes-with-asdf-package-inferred-system-extension][how to include Org code with ASDF package-inferred-system extension]]\n  - [[#how-to-tangle-to-a-bundle-of-lisp-files-from-one-org-file][how to tangle to a bundle of lisp files from one Org file]]\n  - [[#packages-written-by-literate-lisp][packages written by literate-lisp]]\n  - [[#a-demo-literate-application][A demo literate application]]\n    - [[#the-asd-file][The ASD file]]\n    - [[#a-demo-package-for-this-file][a demo package for this file]]\n    - [[#test-cases][Test cases]]\n\n* Introduction\n[[https://github.com/jingtaozf/literate-lisp][literate-lisp]] provides an easy way to use [[http://www.literateprogramming.com/][literal programming]] in Common Lisp language.\nIt extends the Common Lisp [[https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node187.html][reader syntax]]\nso a Common Lisp vendor can read Org files as Common Lisp source files.\n\nBy using this package ([[https://github.com/jingtaozf/literate-lisp][literate-lisp]]), Emacs [[https://orgmode.org/][Org mode]], and Emacs Lisp library [[https://polymode.github.io/][polymode]],\nliterate programming can be very easy, with one Org file containing both documentation and source code,\nand this Org file can interact well with [[https://common-lisp.net/project/slime/][SLIME]].\n\nThe implementation detail of [[https://github.com/jingtaozf/literate-lisp][literate-lisp]] is in file [[./literate-lisp.org]] ([[./literate-lisp.pdf][pdf version]]).\n\nThis library contains the following files:\n- [[./literate-lisp.org]] \\\\\n  The implementation and documentation of literate lisp reader.\n- [[./lisp]] \\\\\n  This directory contains the tangled code of literate lisp reader, generated from [[./literate-lisp.org]]\n- [[./literate-lisp.pdf]] \\\\\n  The weaved documentation, generated from [[./literate-lisp.org]] by Org mode's [[https://orgmode.org/manual/Triggering-publication.html#Triggering-publication][publish feature]].\n- [[./readme.org]] \\\\\n  This file contains introduction and demo code for how to do literate lisp in an Org file.\n- [[./puzzle.org]] \\\\\n  This file contains a puzzle solver to show how to do literate lisp in an Org file.\n- [[./.github/workflows/continuous-integration.yml][continuous-integration.yml]] \\\\\n  The config file used by Web service [[https://github.com/jingtaozf/literate-lisp/actions][GitHub actions]] to test this library.\n- [[./literate-lisp.asd]] \\\\\n  The ASDF definition for literate-lisp project.\n- [[./literate-demo.asd]] \\\\\n  The ASDF definition for literate demo project.\n\n* Tutorial\n** The restriction to the Org file\nThe Org file should start with a comment character and a space character(\"# \"), to drive lisp reader into Org syntax.\nActually it can be a convenient way for us to specify some local variables,\nfor example I often put them in the first line of an Org file:\n#+BEGIN_SRC org\n# -*- encoding:utf-8 Mode: POLY-ORG;  -*- ---\n#+END_SRC\nWhich make Emacs open file with utf-8 encoding and [[https://github.com/polymode/poly-org][poly-org-mode]].\n** Installing polymode in Emacs\nIt's better to edit the Org file with [[https://polymode.github.io/][polymode]], which will make code block use its native file mode.\nThe following Emacs Lisp scripts in .emacs will install it.\n#+BEGIN_SRC elisp\n(use-package poly-org\n    :ensure t)\n#+END_SRC\n** How to insert code block quickly\nPlease have a look of the section [[https://github.com/jingtaozf/literate-elisp/blob/master/literate-elisp.org#how-to-insert-code-block-in-org-file][How to insert code block in Org file]] in library [[https://github.com/jingtaozf/literate-elisp][literate-elisp]].\n\nPlease note that =literate-lisp= now support parsing Org property values ([[https://orgmode.org/manual/Property-Syntax.html][property syntax]]),\nso there is no need to insert =:load no= in header argument now, you can set them as\nOrg properties.\n\nTo disable insertion of unnecessary header argument,\nyou can set Org property =literate-insert-header= to =no=.\n** The ~load~ code block header argument\nPlease have a look of the section [[./literate-lisp.org#new-defined-header-argument-load][new defined header argument load]] in [[./literate-lisp.org]].\n** Reference named blocks as global parameters\nIf a [[https://orgmode.org/manual/Blocks.html][block]] has a named for it, that is, with a =#+NAME:= before it like this:\n#+begin_example\n,#+NAME: js-demo-code\n,#+BEGIN_SRC js\n  document.getElementById(\"demo\").innerHTML = \"Hello JavaScript\";\n,#+END_SRC\n#+end_example\nThen after loading, a global parameter =js-demo-code= will contain the string in above block.\n\nIt is more friendly than write this string in lisp directly,\nbecause =org-mode= can provide syntax for it and =poly-mode= can even enable us edit this code block in =js-mode=.\n\nYou can visit these named blocks by Emacs Lisp function [[https://orgmode.org/worg/orgcard.html#org11fbe72][org-babel-goto-named-src-block]], or by hacking [[https://github.com/joaotavora/sly][sly]] like this:\n#+BEGIN_SRC elisp :load no\n(defun sly-edit-definition-of-named-block (\u0026optional name method)\n  (when (string-prefix-p \"#+END_\" (string-trim (buffer-substring (line-beginning-position) (line-end-position))) t)\n    (let ((case-fold-search t))\n      (search-forward-regexp (format \"#\\\\+NAME:\\s+%s\" name))\n      (forward-line 2)\n      (goto-char (line-beginning-position)))))\n(eval-after-load \"sly\"\n  '(advice-add 'sly-edit-definition :after #'sly-edit-definition-of-named-block))\n#+END_SRC\nYou can hack [[https://common-lisp.net/project/slime/][slime]] the same way.\n\n*NOTE* You have to install literate-lisp to active =*readtable*= in [[https://github.com/joaotavora/sly][sly]] when using SBCL to make above patch work, because\nthe SBCL backend in =sly= will [[https://github.com/joaotavora/sly/blob/master/slynk/backend/sbcl.lisp#L423][read the source code inside file]] when find definitions.\n#+BEGIN_SRC lisp :load no\n(literate-lisp:install-globally)\n#+END_SRC\n** How to debug Org file in LispWorks IDE\nYou have to add the following code in your ~.lispworks~ to enable the debug facility in Lispworks Editor.\n#+BEGIN_SRC lisp :load no\n(defun check-org-mode (buffer truename)\n  (when (and truename (equal (pathname-type truename) \"org\"))\n    (setf (editor:buffer-major-mode buffer) \"Lisp\")))\n(editor:add-global-hook editor::read-file-hook 'check-org-mode)\n#+END_SRC\nThanks for Martin Simmons in [[http://www.lispworks.com/][LispWorks]] to support the above configuration code.\n** How to integrate with namded-readtables\nYou may find that [[https://github.com/melisgl/named-readtables][named-readtables]] is friendly to define the syntax for literate-lisp in your code [[https://github.com/jingtaozf/literate-lisp/issues/12#issuecomment-710256276][like this]]:\n#+BEGIN_SRC lisp :load no\n(named-readtables:defreadtable literate-lisp\n  (:merge :standard)\n  (:dispatch-macro-char #\\# #\\space #'literate-lisp::sharp-space)\n  (:dispatch-macro-char #\\# #\\+ #'literate-lisp::sharp-plus))\n#+END_SRC\n\n** How to write user initialization file with literate programming style\nYou can put all initialization code in an Org source file, all you need is to load ~literate-lisp~ firstly.\nFor example, you can put the following code in file [[http://www.sbcl.org/manual/#Initialization-Files][~$HOME/.sbclrc~]] for SBCL.\n#+BEGIN_SRC lisp :load no\n(require :asdf)\n#-quicklisp\n(let ((quicklisp-init \"~/quicklisp/setup.lisp\")\n      (quicklisp-install \"~/quicklisp.lisp\"))\n  (cond ((probe-file quicklisp-init)\n         (format *terminal-io* \"loading quicklisp...~%\")\n         (load quicklisp-init)\n         (format *terminal-io* \"loading quicklisp...done~%\"))\n        ((probe-file quicklisp-install)\n         (load quicklisp-install)\n         (funcall (intern \"INSTALL\" :quicklisp-quickstart)))))\n\n(load \"~/projects/common-lisp/literate-lisp/literate-lisp.asd\")\n(ql:quickload :literate-lisp)\n(literate-lisp:with-literate-syntax\n  (load \"~/projects/common-lisp/config/init-lisp.org\"))\n#+END_SRC\nI find it useful for various Lisp vendors so all initialization code for them can be in just one file.\n\n** How to include Org code with ASDF package-inferred-system extension\nThe [[https://common-lisp.net/project/asdf/asdf.html#The-package_002dinferred_002dsystem-extension][ASDF package-inferred-system extension]] is wonderful, in which each file is its own system,\nand dependencies are deduced from the defpackage form or its variant, uiop:define-package.\nYou can also use literate-lisp to make a package inferred system by writing an ASD definition like this:\n#+BEGIN_SRC lisp :load no\n(asdf:defsystem literate-libraries\n  :serial t\n  :defsystem-depends-on (:literate-lisp)\n  :default-component-class :org\n  :class :package-inferred-system)\n#+END_SRC\nHere =*:class :package-inferred-system*= enables the package-inferred-system extension, and =*:default-component-class :org*= means\nthat ASDF will look for all Org files to find out a system and load it.\n\nFor example, you can create an Org file in the same directory of above ASD definition file named as *utilities.org* and\ncontains the following code\n#+begin_example\n  # -*- encoding:utf-8 Mode: POLY-ORG;  -*- ---\n  * Create a package for this package inferred system\n  ,#+BEGIN_SRC lisp\n  (defpackage literate-libraries/utilities\n    (:use :cl)\n    (:import-from :flexi-streams :octet :make-flexi-stream)\n    (:import-from :log4cl :log-config)\n    (:documentation \"a utility module.\"))\n  ,#+END_SRC\n  * implementation\n  ... ...\n#+end_example\nAfter loading the above ASD definition file, you can load system *literate-libraries/utilities* in your REPL.\n#+BEGIN_SRC lisp :load no\n(load \"/some/path/literate-libraries.asd\")\n(ql:quickload :literate-libraries/utilities)\n#+END_SRC\n\nPlease upgrade to ASDF 3.3.4.5 or later, it is not supported in earlier ASDF versions.\n\n** How to tangle to a bundle of lisp files from one Org file\nYes, now you can tangle one Org file to a bundle of lisp files, so to share it to team members with more clear interface.\n\nPlease have a look of [[./literate-lisp.org#tangle-to-multiple-files-for-one-org-file][tangle to multiple files for one Org file]]\nor the usage of Org property =LITERATE_EXPORT_PACKAGE= and =LITERATE_EXPORT_NAME= in file [[./literate-lisp.org]].\n\n** Packages written by literate-lisp\n- [[https://github.com/jingtaozf/s-graphviz][s-graphviz]] an S-expression presentation of GraphViz DOT Language\n** A demo literate application\n*** The ASD file\nWe use the original ASD definition file, and extend the ASDF syntax(The documentation of extended ASDF syntax can be found in [[https://github.com/jingtaozf/literate-lisp/blob/master/literate-lsp.org#make-asdf-handle-org-file-correctly][literate-lisp.org]]).\n\nIn a short word, we should load ~literate-lisp~ by ASDF keyword ~:defsystem-depends-on~ and\ndeclare the Org source file with new ASDF keyword ~:org~.\n\nNow let's define the ASDF system file [[./literate-demo.asd]] for this demo package\n#+BEGIN_SRC elisp :load no\n(asdf:defsystem literate-demo\n  :author \"Xu Jingtao \u003cjingtaozf@gmail.com\u003e\"\n  :version \"0.1\"\n  :licence \"MIT\"\n  :serial t\n  :description \"a demo project of literate-lisp\"\n  :defsystem-depends-on (\"literate-lisp\")\n  :depends-on (:iterate #+dev :clgplot)\n  :components ((:module :demo :pathname \"./\"\n                        :components ((:org \"puzzle\")\n                                     (:org \"readme\"))))\n  :properties ((version \"0.1\")))\n#+END_SRC\nWhich will load [[./puzzle.org]] and this file directly as a lisp source file.\n\nThe whole content of ASDF definition file is in [[./literate-demo.asd]].\n*** A demo package for this file\n#+BEGIN_SRC lisp\n(defpackage :literate-demo\n  (:use :cl)\n  (:export ))\n(in-package :literate-demo)\n#+END_SRC\n*** Test cases\n:PROPERTIES:\n:literate-load: test\n:END:\n**** Preparation\nThe [[https://common-lisp.net/project/fiveam/][FiveAM]] library is used to test.\n#+BEGIN_SRC lisp\n(eval-when (:compile-toplevel :load-toplevel :execute)\n  (unless (find-package :fiveam)\n    #+quicklisp (ql:quickload :fiveam)\n    #-quicklisp (asdf:load-system :fiveam)))\n(5am:def-suite literate-demo-suite :description \"The test suite of literate-demo.\")\n(5am:in-suite literate-demo-suite)\n#+END_SRC\n**** test case for named block\nLet's define a named code block for some javascript code:\n#+NAME: js-demo-code-1\n#+begin_src js\n{\n    console.log(\"Hello\");\n}\n#+end_src\nThen try to read it in our test case\n#+BEGIN_SRC lisp\n(5am:test named-block\n  (5am:is (stringp js-demo-code-1))\n  (5am:is (not (null (position #\\\" js-demo-code-1 :test #'char=)))))\n#+END_SRC\n**** run all tests in this library\nThis function is the entry point to run all tests and return true if all test cases pass.\n#+BEGIN_SRC lisp\n(defun run-test ()\n  (5am:run! 'literate-demo-suite))\n#+END_SRC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjingtaozf%2Fliterate-lisp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjingtaozf%2Fliterate-lisp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjingtaozf%2Fliterate-lisp/lists"}