4.5 KiB
Literate configuration
- Preclude
- Variables
- Remove function
- Parser
- Destination for parser
- Procedure for all files
- Hook on save
- Load configuration
Preclude
My setup to produce a literate configuration. Allows me to write org files all around the doom-private-dir and access them. Also shaved like 0.2s off my loading time.
Variables
Initialise some basic constants for where stuff is
(setq oreodave/literate/bin-dir (expand-file-name (concat doom-private-dir "bin/")))
(setq oreodave/literate/preloaded-files (list "README.org" "modules/config.org" "modules/literate.org"))
Remove function
When loading the lisp, we need to load everything excluding "config.el" (preloaded by doom) and "literate.el" (loaded by "config.el"). We'll make a very specific remove function that will remove entries from a given list and return the new list, given the fact that the files variable will be a list of fully expanded file names.
(defun oreodave/literate/remove-mult (remove-files files)
(let ((parsed-remove-files (map 'list #'(lambda (i) (expand-file-name (concat doom-private-dir i))) remove-files)))
(remove-if-not #'(lambda (l) (not (member l parsed-remove-files))) files)))
Parser
First we need to get some sort of parser which can, given a source org file and a destination, parse and produce an Emacs lisp file. We'll copy this from the literate module of doom.
(defun oreodave/literate/tangle (SRC DEST)
(let ((default-directory doom-private-dir))
(when (file-newer-than-file-p SRC DEST)
(let ((output (get-buffer-create "*org-tangle*")))
(unwind-protect
(or (and (zerop (call-process
"emacs" nil output nil
"-q" "--batch"
"-l" "ob-tangle"
"--eval" (format "(org-babel-tangle-file %S %S)"
SRC DEST)))
(with-current-buffer output
(message "%s" (buffer-string))
t))
(warn (format "Problem with tanging %S to %S" SRC DEST)))
(kill-buffer output))))))
Destination for parser
Generate the destination for a literate config org file to parse to, in this case the bin folder in the private directory
(defun oreodave/literate/destination(SRC)
(replace-regexp-in-string ".*/\\(\\w+\\).org" (expand-file-name (concat oreodave/literate/bin-dir "\\1.el")) SRC))
This is not fitted onto the parser because the parser could be fitted to multiple differing outputs easily if it isn't specified a destination.
Procedure for all files
A procedure that parses all the org files in a given directory into Emacs lisp files, using the parser function made. Assume all org files in the "location" directory contribute to the config.
(defun oreodave/literate/tangle-all (location)
(interactive)
(message "Starting compilation process")
(let ((files (directory-files-recursively location ".org")))
(dolist (file files)
(message "Compiling and parsing %s" file)
(oreodave/literate/tangle file (oreodave/literate/destination file)))))
The location is not set because this function could be easily programmed to use multiple differing sources to produce the config.
Hook on save
Now we need to make a hook function that, when the current buffer is an org file in the doom directory, will run the literate config procedure from above. Use this hook function and add it to the after-save-hook once org mode has been loaded. README.org has been added as an exception because it doesn't contain literate contents.
(defun oreodave/literate/compile-hook ()
(when (and (eq major-mode 'org-mode)
(file-in-directory-p buffer-file-name doom-private-dir)
(not (string= buffer-file-name (expand-file-name (concat doom-private-dir "README.org")))))
(oreodave/literate/tangle buffer-file-name (oreodave/literate/destination buffer-file-name))))
(after! org
(add-hook 'after-save-hook #'oreodave/literate/compile-hook))
Load configuration
Final step of the literate cycle: load the config for the first time.
(let ((files (directory-files-recursively "~/.doom.d/" ".org"))) ; Load
(dolist (file (oreodave/literate/remove-mult oreodave/literate/preloaded-files files))
(load! (oreodave/literate/destination file))))
Remove the config.el and literate.el files from the load list because:
- config.org is preloaded by doom
- literate.org is loaded by config.org, thus no need to reload it