FG42/lisp/build.el

186 lines
6.2 KiB
EmacsLisp

;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://devheroes.codes/FG42/FG42
;; Version: 4.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 this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;; This is the builder script that takes the config.json from the input
;; (typically provided by Nix). And generates appropriate Elisp file
;; for the main FG42 Elsip code to load and use.
;;
;; Please note that this file runs with Emacs and not FG42.
;;; Code:
(require 'loaddefs-gen)
(when (not (json-available-p))
(error "Error: libjasson support is missing"))
(defvar file-header " ;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://devheroes.codes/FG42/FG42
;; Version: 4.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 this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;; This is the builder script that takes the config.json from the input
;; (typically provided by Nix). And generates appropriate Elisp file
;; for the main FG42 Elsip code to load and use.
;;
;; Please note that this file runs with Emacs and not FG42.
;;; Code:
;; ============================================================================
;; This file is auto generated by FG42. Don't modify it.
;; ============================================================================
;; Since it is deprecated we can easily avoide other packages to use it
(provide 'cl)
(require 'fg42/pre)
")
(defvar file-footer "
(require 'fg42)
(provide 'fg42_init)
;; fg42_init.el ends here
")
(defvar keys-to-skip '("docstrings" "mimeTypes"))
;; Elisp's hashtables are not functional so I have to store the
;; state like this, Ewwwwww!
(defvar vars ()
"Storage for the vars and const forms.")
(defvar requires ()
"Storage for the require forms.")
(defvar build-output (cadr command-line-args-left))
;;; Build related stuff
(defmacro with-json (var &rest body)
"Read the json file from cli arguments, user VAR run the BODY on it."
(declare (indent defun))
`(let ((input-file (car command-line-args-left)))
(message "[build.el]: Reading the input file: %s" input-file)
(with-temp-buffer
(insert-file-contents input-file)
(let ((,var (json-parse-buffer)))
,@body))))
(defun replace-in-string (what with s)
"Replace WHAT in string S with WITH."
(replace-regexp-in-string (regexp-quote what) with s nil 'literal))
(defun generate-compile-time-requires (elisp-pkgs)
"Generate a list of `require' forms of ELISP-PKGS for compile time."
(when (> (length elisp-pkgs) 0)
(add-to-list
'requires
`(eval-when-compile
,@(mapcar (lambda (pkg) `(require ',(intern (replace-in-string "fg42-" "fg42/" pkg)))) elisp-pkgs)))))
(defun generate-generic-vars (k v doc &optional const)
"Generate a list of vars for K and value V with docstring DOC.
Generate a constant if CONST is non-nil."
(add-to-list 'vars `(,(if const 'defconst 'defvar)
,(intern (format "fg42/config/%s" k)) ,v ,doc)))
(defun fg42-config-key-handler (config)
"Generate a lambda to process key/value pairs in CONFIG."
(lambda (k v)
"Handle the FG42 config K and its value V."
(cond
((string= k "requires")
(generate-compile-time-requires v))
((member k keys-to-skip)
(message "[build.el]: Skipping %s..." k))
((and (string= k "vars") (> (length v) 0))
(mapc (lambda (x)
(generate-generic-vars (gethash "name" x)
(gethash "defaultValue" x)
(gethash "docstring" x)))
v))
((and (string= k "consts") (> (length v) 0))
(mapc (lambda (x)
(generate-generic-vars (gethash "name" x)
(gethash "defaultValue" x)
(gethash "docstring" x)
t))
v)))))
(defun fg42-handler (config)
"Handle the CONFIG for FG42.
CONFIG maps to the collective `config' value of Nix modules."
(maphash (fg42-config-key-handler config) config))
(defun handle-conifg-for (k v)
"Find the handler of K and its value V to it."
(funcall (intern (format "%s-handler" k)) v))
(defun handle-top-level (k v)
"Handle the key K and value V form the top level of the JSON data."
(when (not (string= k "fg42"))
(error "Don't know how to handle '%s'" k))
(handle-conifg-for k v))
(with-json j
;; TODO: To make it scale, may be let Nix modules
;; plug into this script. There is a security
;; rist though
(maphash #'handle-top-level j)
(with-temp-file build-output
(insert file-header)
(insert ";; Vars ======")
(mapc (lambda (x) (print x (current-buffer))) vars)
(insert ";; Requires ======")
(mapc (lambda (x) (print x (current-buffer))) requires)
(insert file-footer))
(message "[build.el]: Done!"))
(provide 'build)
;;; build.el ends here