;;; Buid --- The builder for FG42 -*- lexical-binding: t; -*- ;; ;; Copyright (c) 2010-2022 Sameer Rahmani & Contributors ;; ;; Author: Sameer Rahmani ;; URL: https://gitlab.com/FG42/FG42 ;; Version: 3.0.0 ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with thnis program. If not, see . ;; ;;; Commentary: ;; Cubes are the building blocks of any `FG42' editor. Each `cube' is a ;; unit which defines different abilities in a deterministic and idempotent ;; way. Cubes are composable and a composition of cubes creates an editor. ;; ;;; Code: (require 'seq) (defvar fg42/build-project-name "FG42" "The name to be uesd with in the output as as the project name") (defvar fg42/build-project-root nil "Root directory of the website source code.") (defvar fg42/build-debug-mode nil) (defvar fg42/build-author-name "Sameer Rahmani") (defvar fg42/build-author-email "lxsameer@gnu.org") (defvar fg42/build-docs-root "/docs/site" "Where to find the docs. It sould be relative to the project root.") (defvar fg42/build-dev-base-url "http://localhost:3003" "The base url to use with the docs for dev.") (defvar fg42/build-prod-base-url "https://fg42.org" "The base url to use with the docs for production.") (defvar fg42/build-docs-pages-dir "/pages" "Where to find the pages (relative to docs dir)") (defvar fg42/build-docs-ignore-category-check nil "A list of files that should be ignored by category/tag checks") (defvar fg42/build-docs-actions nil "Set of actions to run before building the main docs.") (defvar fg42/build-output-dir "/build" "The path to the build directory.") (defvar fg42/build-docs-title "FG42" "Title of the generated docs. Like the website title") (defvar fg42/build-docs-desc "The ultimate editor for true believers" "Description of the generated docs. Like the website description") (defvar fg42/build-usage "./builder.el SUBCOMMAND" "Title of the generated docs. Like the website title") (defmacro defproject (prject-name &rest details) "Create a project with the given DETAILS. The build system will consum these details for various purposes." (declare (indent defun)) (cons 'progn (cons `(setq fg42/bulid-project-name ,(symbol-name prject-name)) (seq-reduce (lambda (forms pair) (let* ((varname (intern (format "fg42/build-%s" (car pair)))) (val (cadr pair)) (form `(setq ,varname ,val))) (cons form forms))) (seq-partition details 2) nil)))) (defmacro command-> (command-var args-var &rest body) (declare (indent defun)) `(defun main () "The entry point to the build script." (message (fg42/version)) (message "\nFG42 Build tool v%s\n\n" (fg42/version)) ;; UTF-8 as default encoding (prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (let* ((fg42-home (car command-line-args-left)) (build-dir (from-root ,fg42/build-output-dir)) (parsed-args (read-args (cdr command-line-args-left))) (eval-string (plist-get (car parsed-args) :e)) (,command-var (caadr parsed-args)) (,args-var (cdadr parsed-args))) ;; Evaluate the expression provided by :e (when eval-string (eval (car (read-from-string eval-string)))) (setq fg42/build-debug-mode (plist-get (car parsed-args) :d)) (cond ,@body (t (print-help ,command-var)))))) (defun print-help (_) "Print out the usage for the build script" (message fg42/build-usage)) (defun from-root (path) "Return the full path of the given PATH in the project root." (concat fg42/build-project-root path)) (defun from-docs (path) "Return the full path of the given PATH in the docs root." (concat (from-root fg42/build-docs-root) path)) (defun prod-p () "Return non-nil if debug mode is turned off" (not fg42/build-debug-mode)) (defun read-args (args) "Parse the give ARGS list and return a list in the following format: (FLAGS (COMMAND ARGES))" (seq-reduce (lambda (acc arg) (let ((flags (car acc)) (commands (cadr acc)) (i (caddr acc)) (skip (cadddr acc))) (if skip (list flags commands (1+ i) ()) (progn (cond ((string= arg ":d") (plist-put flags :d t)) ((string= arg ":e") (progn (plist-put flags :e (nth (1+ i) args)) (setq skip (1+ i)))) (t (push arg commands))) (list flags commands (1+ i) skip))))) args '((:d () :e ()) () 0 ()))) (defun replace-in-buffer (str replacement) "Replace the given STR with its REPLACEMENT in current buffer." (with-current-buffer (current-buffer) (goto-char (point-min)) (while (search-forward str nil t) (replace-match replacement)))) (defun copy-template (src dest context) "Replace the placeholder in SRC with list of pairs given in CONTEXT and write it to DEST." (make-directory (file-name-directory dest) t) (message "Copy template: '%s' -> '%s'" src dest) (with-temp-file dest (insert-file-contents src) (dolist (pair context) (replace-in-buffer (format "<<<%s>>>" (car pair)) (cdr pair))))) (defmacro do-command (&rest body) "Run the BODY after loading FG42." `(progn (require 'fg42) (fg42/before-initialize) ,@body)) (provide 'fg42/build/core) ;;; core.el ends here