aboutsummaryrefslogtreecommitdiff
path: root/doom.d/modules/literate.org
blob: dba59b09906fe5356ae0b9990cd521b24d98f499 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#+TITLE: Literate 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
#+BEGIN_SRC elisp
(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"))
#+END_SRC
* 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.
#+BEGIN_SRC elisp
(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)))
#+END_SRC
* 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.
#+BEGIN_SRC elisp
(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))))))
#+END_SRC
* 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
#+BEGIN_SRC elisp
(defun oreodave/literate/destination(SRC)
  (replace-regexp-in-string ".*/\\(\\w+\\).org" (expand-file-name (concat oreodave/literate/bin-dir "\\1.el")) SRC))
#+END_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
We need a procedure that parses all the org files in the doom-private-dir and
modules directory into Emacs lisp files, using the parser function we've made.
Assume all org files in the private directory contribute to the config.
#+BEGIN_SRC elisp
(defun oreodave/literate/tangle-all ()
  (interactive)
  (message "Starting compilation process")
  (let ((files (directory-files-recursively "~/.doom.d/" ".org")))
    (dolist (file files)
      (message "Compiling and parsing %s" file)
      (oreodave/literate/tangle file (oreodave/literate/destination file)))))
#+END_SRC
* Hook on save
Now we need to make a hook that, when the current buffer is an org file in the
doom directory, will run the literate config procedure from above.
#+BEGIN_SRC elisp
(defun oreodave/literate/compile-hook ()
  (when (and (eq major-mode 'org-mode)
             (or (file-in-directory-p buffer-file-name doom-private-dir)))
    (oreodave/literate/tangle-all)))
#+END_SRC
* Add hook to org-mode
#+BEGIN_SRC elisp
(after! org
  (add-hook 'after-save-hook #'oreodave/literate/compile-hook))
#+END_SRC
* Config run
Parse all Emacs lisp files. Then load them.
#+BEGIN_SRC elisp
(oreodave/literate/tangle-all) ; Parse
(let ((files (directory-files-recursively "~/.doom.d/" ".org"))) ; Load
      (load! (replace-regexp-in-string ".org" ".el" file))))
    (dolist (file (oreodave/literate/remove-mult oreodave/literate/preloaded-files files))
#+END_SRC