;;; build-core.el --- Build bootstrap and logging -*- lexical-binding: t; -*- ;;; Code: (require 'package) (defconst z/colour-reset "\033[0m") (defconst z/colour-bold "\033[1m") (defconst z/colour-dim "\033[2m") (defconst z/colour-green "\033[32m") (defconst z/colour-yellow "\033[33m") (defconst z/colour-cyan "\033[36m") (defconst z/colour-red "\033[31m") (defconst z/colour-blue "\033[34m") (defconst z/colour-magenta "\033[35m") (defun z/log (level fmt &rest args) "Emit a coloured build-log line. LEVEL is one of: info warn error step metric done. FMT and ARGS are passed to `format'." (let* ((msg (apply #'format fmt args)) (prefix (pcase level ('info (concat z/colour-cyan " INFO " z/colour-reset)) ('warn (concat z/colour-yellow " WARN " z/colour-reset)) ('error (concat z/colour-red " ERROR " z/colour-reset)) ('step (concat z/colour-blue z/colour-bold " ---- " z/colour-reset)) ('metric (concat z/colour-magenta " * " z/colour-reset)) ('done (concat z/colour-green z/colour-bold " OK " z/colour-reset)) (_ " ")))) (message "%s%s" prefix msg))) (defun z/log-separator (&optional label) "Print a separator line, optionally with LABEL." (if label (message "%s%s-- %s %s%s" z/colour-dim z/colour-bold label (make-string (max 0 (- 60 (length label))) ?-) z/colour-reset) (message "%s%s%s" z/colour-dim (make-string 66 ?-) z/colour-reset))) (defmacro z/with-timing (label &rest body) "Execute BODY, then log elapsed seconds under LABEL." (declare (indent 1)) (let ((t0 (gensym "t0"))) `(let ((,t0 (float-time))) (prog1 (progn ,@body) (z/log 'metric "%s took %.2fs" ,label (- (float-time) ,t0)))))) (defun z/bootstrap-packages () "Set up Emacs packages required by the build." (z/log-separator "Package setup") (setq package-user-dir (site-path ".packages")) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("elpa" . "https://elpa.gnu.org/packages/"))) (package-initialize) (z/with-timing "Package archive refresh" (unless package-archive-contents (z/log 'info "Refreshing package archive contents...") (condition-case err (package-refresh-contents) (error (z/log 'warn "Could not refresh archives: %s" (error-message-string err)))))) (z/with-timing "htmlize install" (unless (package-installed-p 'htmlize) (z/log 'info "Installing htmlize...") (condition-case err (package-install 'htmlize) (error (z/log 'error "htmlize install failed: %s" (error-message-string err)) (error "Cannot continue without htmlize"))))) (require 'htmlize)) (defun z/configure-org () "Load Org export libraries and configure shared Org settings." (require 'ox-publish) (require 'cl-lib) (require 'json) (require 'org) (require 'ox) (require 'ox-html) (require 'ox-md) (setq org-publish-timestamp-directory (site-path ".org-timestamps/")) (setq org-html-htmlize-output-type 'css)) (defun z/require-local (library) "Require local build LIBRARY with consistent error reporting." (condition-case err (progn (require library) (z/log 'done "Loaded %s" library)) (error (z/log 'error "Failed to load %s: %s" library (error-message-string err)) (error "Aborting: required library %s missing" library)))) (provide 'build-core) ;;; build-core.el ends here