src/config.lisp (4225 bytes)
1 (in-package :coleslaw) 2 3 (defclass blog () 4 ((author :initarg :author :reader author) 5 (charset :initarg :charset :reader charset) 6 (deploy-dir :initarg :deploy-dir :reader deploy-dir) 7 (domain :initarg :domain :reader domain) 8 (excerpt-sep :initarg :excerpt-sep :reader excerpt-sep) 9 (feeds :initarg :feeds :reader feeds) 10 (name-fn :initarg :name-fn :reader name-fn) 11 (lang :initarg :lang :reader lang) 12 (license :initarg :license :reader license) 13 (page-ext :initarg :page-ext :reader page-ext) 14 (plugins :initarg :plugins :reader plugins) 15 (repo :initarg :repo :accessor repo-dir) 16 (routing :initarg :routing :reader routing) 17 (separator :initarg :separator :reader separator) 18 (sitenav :initarg :sitenav :reader sitenav) 19 (staging-dir :initarg :staging-dir :reader staging-dir) 20 (theme :initarg :theme :reader theme) 21 (title :initarg :title :reader title)) 22 (:default-initargs 23 :feeds nil 24 :license nil 25 :plugins '((rsync "-avz" "--delete" "--exclude" ".git/" "--exclude" ".gitignore" "--copy-links")) 26 :sitenav nil 27 :excerpt-sep "<!--more-->" 28 :name-fn 'identity 29 :charset "UTF-8" 30 :lang "en" 31 :page-ext "html" 32 :separator ";;;;;" 33 :staging-dir "/tmp/coleslaw")) 34 35 (defun dir-slot-reader (config name) 36 "Take CONFIG and NAME, and return a directory pathname for the matching SLOT." 37 (ensure-directory-pathname (slot-value config name))) 38 39 (defmethod deploy-dir ((config blog)) (dir-slot-reader config 'deploy-dir)) 40 (defmethod repo-dir ((config blog)) (dir-slot-reader config 'repo)) 41 (defmethod staging-dir ((config blog)) (dir-slot-reader config 'staging-dir)) 42 43 (defparameter *config* nil 44 "A variable to store the blog configuration and plugin settings.") 45 46 (define-condition plugin-conf-error () 47 ((plugin :initarg :plugin :reader plugin) 48 (message :initarg :message :reader message)) 49 (:report (lambda (condition stream) 50 (format stream "~A: ~A" (plugin condition) (message condition)))) 51 (:documentation "Condition to signal when the plugin is misconfigured.")) 52 53 (defun enable-plugin (name args) 54 "Given a plugin, NAME, compile+load it and call its ENABLE function with ARGS." 55 (flet ((plugin-path (sym) 56 (if (probe-file (repo-path "plugins/~(~A~).lisp" sym)) 57 (repo-path "plugins/~(~A~)" sym) 58 (app-path "plugins/~(~A~)" sym))) 59 (plugin-package (sym) 60 (format nil "~:@(coleslaw-~A~)" sym))) 61 (let ((file (plugin-path name))) 62 (multiple-value-bind (output-file error) 63 (ignore-errors (compile-file file :verbose nil :print nil)) 64 (when error 65 (warn "Error while compiling plugin ~A: ~A.~%" name error)) 66 (load (or output-file file) :verbose t))) 67 (let ((package (find-package (plugin-package name)))) 68 (apply (find-symbol "ENABLE" package) args)))) 69 70 (defun load-plugins (plugins) 71 "Compile and load the listed PLUGINS. It is expected that matching *.lisp files 72 are in the plugins folder in coleslaw's source directory." 73 (setf *injections* nil) 74 (dolist (plugin plugins) 75 (destructuring-bind (name &rest args) plugin 76 (enable-plugin name args)))) 77 78 (defun discover-config-path (repo-path) 79 "Check the supplied REPO-PATH for a .coleslawrc and if one 80 doesn't exist, use the .coleslawrc in the home directory." 81 (let ((repo-config (rel-path repo-path ".coleslawrc"))) 82 (if (file-exists-p repo-config) 83 repo-config 84 (rel-path (user-homedir-pathname) ".coleslawrc")))) 85 86 (defun load-config (&optional (repo-dir "")) 87 "Find and load the coleslaw configuration from .coleslawrc. REPO-DIR will be 88 preferred over the home directory if provided." 89 (with-open-file (in (discover-config-path repo-dir) :external-format :utf-8) 90 (let ((config-form (read in))) 91 (setf *config* (construct 'blog config-form) 92 (repo-dir *config*) repo-dir))) 93 (load-plugins (plugins *config*)))