aboutsummaryrefslogtreecommitdiff
path: root/doom.d/config/literate.org
diff options
context:
space:
mode:
Diffstat (limited to 'doom.d/config/literate.org')
-rw-r--r--doom.d/config/literate.org107
1 files changed, 107 insertions, 0 deletions
diff --git a/doom.d/config/literate.org b/doom.d/config/literate.org
new file mode 100644
index 0000000..8db8a3d
--- /dev/null
+++ b/doom.d/config/literate.org
@@ -0,0 +1,107 @@
+#+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.
+* Constants
+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" "org/packages.org"
+ "org/config.org" "org/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)
+ "Remove any occurrences of `remove-files' from `files'"
+ (let ((parsed-remove-files (map 'list
+ #'(lambda (i) (expand-file-name (concat doom-private-dir i)))
+ remove-files))) ; Generate a list of all fully expanded files to remove
+ (remove-if #'(lambda (l) (member l parsed-remove-files)) files))) ; remove any files that are in the remove-files
+#+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
+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.
+#+BEGIN_SRC elisp
+(defun oreodave/literate/destination(SRC)
+ "Parse a src.org file to a bin/src.el file"
+ (replace-regexp-in-string ".*/\\(\\w+\\).org"
+ (expand-file-name (concat oreodave/literate/bin-dir "\\1.el")) SRC))
+#+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)
+ "Tangle a source org file into a destination el file using a new emacs instance"
+ (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
+* 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.
+#+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)
+ (file-in-directory-p buffer-file-name (concat doom-private-dir "modules")))
+ (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))
+#+END_SRC
+* 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.
+The location is not set because this function could be easily programmed to use
+multiple /differing/ sources to produce the config. The tangle function is set
+because this is the function we'll be using for tangling all org files to ELisp files.
+#+BEGIN_SRC elisp
+(defun oreodave/literate/tangle-all (&optional location)
+ "Tangle all org files in `location' to el files in the `destination'"
+ (or location (setq location doom-private-dir))
+ (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)))))
+#+END_SRC
+* Load configuration
+Final step of the literate cycle: load the config for the first time.
+Remove the config.el and literate.el files from the load list because:
+1) config.org is preloaded by doom
+2) literate.org is loaded by config.org, thus no need to reload it
+
+#+BEGIN_SRC elisp
+(let ((files (directory-files-recursively "~/.doom.d/org" ".org"))) ; Load
+ (dolist (file (oreodave/literate/remove-mult oreodave/literate/preloaded-files files))
+ (load (oreodave/literate/destination file))))
+#+END_SRC