This section aims to provide the minimal steps required to get literate programming in org-mode working for GNU Guile.
We will use GNU Guix to create a reproducible environment, in which we will run Emacs, install Emacs packages and configure Emacs using Elisp code.
cat < manifest.scm (specifications->manifest '("gnutls" "guile" "bash" "emacs")) EOT
cat manifest.scm
:results: (specifications->manifest '("gnutls" "guile" "bash" "emacs")) :end:
guix describe --format='channels' > 'channels.scm' cat 'channels.scm'
:results:
(list (channel
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(branch "master")
(commit
"22d6e36005
")
(introduction
(make-channel-introduction
"9edb3f66fd
"
(openpgp-fingerprint
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
:end:
command -V guile ls -al $(command -V guile)
# compare to guile installed in the environment created via guix shell:
guix time-machine \ --channels="channels.scm" -- \ shell \ --cores=8 \ --manifest="manifest.scm" -- \ which guile && ls -al $(which guile)
:results: guile is home/xiaolong.guix-profile/bin/guile lrwxrwxrwx 1 root root 65 Jan 1 1970 home/xiaolong.guix-profile/bin/guile -> gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/bin/guile /gnu/store/abw05ikf9q0by8xp7g19hd7d7hj40cvi-profile/bin/guile lrwxrwxrwx 1 root root 65 Jan 1 1970 /home/xiaolong.guix-profile/bin/guile -> /gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/bin/guile :end:
guix time-machine \ --channels="channels.scm" -- \ shell \ --cores=8 \ --pure \ --container \ --network \ --no-cwd \ --preserve='TERM' \ --manifest="manifest.scm" -- \ emacs \ --no-init-file \ --no-site-file \ --no-site-lisp \ --no-splash \ --no-x-resources \ --no-desktop \ --no-loadup \ --no-window-system
Or with graphical window:
guix time-machine \ --channels="channels.scm" -- \ shell \ --cores=8 \ --pure \ --container \ --network \ --no-cwd \ --share=/tmp/.X11-unix \ --preserve='DISPLAY' \ --preserve='TERM' \ --manifest="manifest.scm" -- \ emacs \ --no-init-file \ --no-site-file \ --no-site-lisp \ --no-splash \ --no-x-resources \ --no-desktop \ --no-loadup
To install geiser, we need to add the package repository, from which we can pull it.
Run the following elisp code:
(require 'package) ;; (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t) (package-initialize)
org
is already installed. Not sure how to tell Emacs, that it should instead install org
from GNU Elpa, so do this manually:
M-x list-pack RET
org
from GNU Elpaorg
As Elisp code:
(package-install 'geiser-guile)
The following Elisp code needs to be evaluated, to be able to evaluate org source blocks of Scheme code using GNU Guile:
;; Tell Emacs to use the command `guile` to evaluate Scheme ;; code. (setq scheme-program-name "guile")
;; The following enables source blocks of specific ;; programming languages to be executed. By default only ;; elisp is allowed to be executed. First we define an ;; association list of languages to booleans, which enable ;; or disable support for a language. (setq org-babel-load-languages '((scheme . t)))
;; Then we use org-babel-do-load-languages to actually tell ;; org babel, that the languages should be supported. (org-babel-do-load-languages 'org-babel-load-languages '((scheme . t)))
;; The following defines a procedure, which determins, which ;; source blocks of programming languages can be run without ;; confirmation, depending on the language. The procedure ;; can then be used as org-confirm-babel-evaluate value. (defun xiaolong/org-confirm-babel-evaluate (lang body) (not (or (string= lang "scheme"))))
;; Set a procedure predicate for org babel, to determin, which languages can ;; be run without confirmation. (setq org-confirm-babel-evaluate 'xiaolong/org-confirm-babel-evaluate)
Run geiser-guile using the following command:
M-x run-geiser RET
Since only geiser-guile
is installed, this should start a Geiser Guile REPL.
Now we should be all set to try some literate programming in Scheme.
Here is an example document:
cat example.org
,#+NAME: defmember ,#+begin_src scheme :noweb yes :results none :exports code :eval never-export :language guile (define member? (λ (a lat) (cond [(null? lat) #f] [else (or (eq? a (car lat)) (member? a (cdr lat)))]))) ,#+end_src
Lets test it:
,#+NAME: usemember ,#+begin_src scheme :noweb yes :results output :exports both :eval never-export <>
(display (simple-format #f "(member? 1 '(3 2 1)) -> ~a\n" (member? 1 '(3 2 1))))
(display (simple-format #f "(member? 1 '(3 2 4)) -> ~a\n" (member? 1 '(3 2 4)))) ,#+end_src
example.org
document into the buffer of the =.org= file.usemember
source block.C-c C-c
to evaluate the source block.The above does not seem to work. The result of the example source block is merely the following:
Geiser Interpreter produced no output