;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- ;; ;; Copyright (c) 2010-2024 Sameer Rahmani ;; ;; Author: Sameer Rahmani ;; 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 . ;; ;;; 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 ;; ;; Author: Sameer Rahmani ;; 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 . ;; ;;; 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