diff --git a/.gitignore b/.gitignore index 3a93feb..02bc895 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ lib/**/*.elc tmp/ test-runner/ .fpkg/ -/fg42-wm \ No newline at end of file +/fg42-wm +.fpkg-v3 \ No newline at end of file diff --git a/.gitlab/merge_request_templates/contribution.md b/.gitlab/merge_request_templates/contribution.md new file mode 100644 index 0000000..b9f1985 --- /dev/null +++ b/.gitlab/merge_request_templates/contribution.md @@ -0,0 +1,16 @@ +## Summary + + + +### QA + + + +### Checklist + +[ ] Is the linter happy? +[ ] Is the byte compiler happy (no warning) ? +[ ] Is it backward compatible +[ ] Did you document your changes ? +[ ] Did you update the CHANGELOG ? +[ ] Did you actually test your changes ? diff --git a/bin/fbt b/bin/fbt new file mode 100755 index 0000000..c611113 --- /dev/null +++ b/bin/fbt @@ -0,0 +1,137 @@ +:;exec emacs --no-site-file --no-site-lisp -batch -l "$0" -f main "$(cd "$(dirname "$0")/.." >/dev/null 2>&1 ; pwd -P)" "$@" +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;; FG42 Build Tool for FBT for short is a tool on top of Emacs to build +;; FG42. To learn how to use it run it via a shell. +;; +;;; Code: +(defvar FG42-VERSION "3.0.0-snapshot" + "The version number of the current build of FG42.") + +(defconst fbt-usage " +Usage: + +fbt [PARAMS] COMMAND [...] + +COMMANDS: + compile [DIR] - Compiles the given DIR to bytecodes (default: \"core\"). + build - Builds FG42 by compiling the code and installing dependencies. + clean [DIRS] - Clean up the given list of directories (default: \"code\" \"fbt\"). + fpkg [...] - The CLI insterface to FPKG (FG42 Package manager) + lint [DIR] - Run the ELisp linter on the files on the given DIR. + +PARAMS: + :d - Turns on the debug mode. + :e expr - Run the given `expr' before any operation. + +By default FBT loads the `system.el' file from the root path of `FG42' and looks +for a system with the name `FG42' to use it as the source for the build operations. +You can change this behaviour by running following command: + +$ fbt :e '(setq fg42-system 'SOMESYSTEM fg42-system-path \"path/to/a/elisp/file.el\"))' COMMAND... + +This way FBT will load an elisp file at \"path/to/a/elisp/file.el\" and looks for a system +called `SOMESYSTEM' in it as the source system for the build operations. +") + + +(defun read-args (args) + "Parse the given ARGS and return a list of params and args. +The only parameter at the moment is `-e' which basically gets a string +of elisp and eval it before the commant. The return value is a list +which the first element is the string to evaluate and the second one +is the rest of the arguments." + (if (member ":d" args) + (setq debug-on-error t) + (delete ":d" args)) + + (if (string= (car args) ":e") + (list (cadr args) (cddr args)) + (list nil args))) + + +(defun todo (dir) + "Extract the TODO tags from the comments in the given DIR." + (message "TBD")) + + +(defun print-help (command) + "Print out a usage instructions and print out the invalid msg for COMMAND." + (when command + (warn "I don't know about '%s' command.\n" command)) + (message fbt-usage)) + + +(defun main () + "Execute a subcommand by looking into input arguments of the script." + (message (version)) + (message "\nFG42 Build tool v%s\n\n" FG42-VERSION) + + (let* ((fg42-home (car command-line-args-left)) + (parsed-args (read-args (cdr command-line-args-left))) + (eval-string (car parsed-args)) + (command (caadr parsed-args)) + (args (cdadr parsed-args))) + + + ;; FG42 Needs this env var to know where had it been installed + (setenv "FG42_HOME" fg42-home) + (setenv "FG42_VERSION" FG42-VERSION) + + (defvar fg42-system-path (concat (file-name-as-directory fg42-home) "system")) + (defvar fg42-system 'FG42) + + (add-to-list 'load-path (concat (file-name-as-directory fg42-home) "core")) + (add-to-list 'load-path (concat (file-name-as-directory fg42-home) "fbt")) + ;; Load the default system without user configurations + (when eval-string + (eval (car (read-from-string eval-string)))) + + (load fg42-system-path) + + (require 'fbt/utils) + (require 'fbt/compile) + (require 'fbt/lint) + (require 'fbt/fpkg) + (require 'fbt/build) + + + (let ((system (symbol-value fg42-system))) + + ;; Add the fpkg path to the load path. For the sake of `straight.el'. + ;; This way installed packages will be accessable for build tools as well. + (fpt-fpkg/initialize-load-path system) + + (cond + ((string= command "fpkg") (funcall #'fbt-fpkg system args)) + ((string= command "lint") (funcall #'lint (or (car args) "core"))) + ((string= command "compile") (funcall #'fbt-compile/compile (or (car args) "core"))) + ((string= command "clean") (funcall #'fbt-build/clean (or args '("core" "fbt")))) + ((string= command "build") (funcall #'build args)) + (t (print-help command)))))) + +;; Local Variables: +;; mode: emacs-lisp +;; End: +;;; fbt ends here diff --git a/fg42-new b/bin/fg42-new similarity index 79% rename from fg42-new rename to bin/fg42-new index eb9e125..5d6f70f 100755 --- a/fg42-new +++ b/bin/fg42-new @@ -1,6 +1,6 @@ #! /bin/sh -export FG42_HOME="$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)" +export FG42_HOME="$(cd "$(dirname "$0")/.." >/dev/null 2>&1 ; pwd -P)" FG42_WM=false emacs --name FG42 \ --no-site-file --no-site-lisp --no-splash --title FG42 \ diff --git a/fbt b/fbt deleted file mode 100755 index ca27b05..0000000 --- a/fbt +++ /dev/null @@ -1,127 +0,0 @@ -:;exec emacs --no-site-file --no-site-lisp -batch -l "$0" -f main "$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)" "$@" -;;; FGBuildTool --- The build tool for FG42 -;; -;; Copyright (c) 2010-2020 Sameer Rahmani -;; -;; 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 this program. If not, see . -;; -;; -;;; Commentary: -;;; Code: - -(defvar FG42_VERSION "3.0.0-snapshot" - "The version number of the current build of FG42.") - -(defun ->path (dir) - "Return the absolute path to the given DIR with respect to FG42_HOME." - (concat (getenv "FG42_HOME") (format "/%s" dir))) - - -(defun el-files-in (dir) - "Return a list of elisp files in the given DIR." - (split-string (shell-command-to-string - (format "find %s -iname \"*.el\"" (->path dir))) "\n" t)) - - -(defun lint (dir) - "Run linter on all the elisp files in the given DIR." - (let ((files (el-files-in dir))) - (if files - (dolist (file files) - ;; TODO: Setup flycheck here and use it to lint the elisp file. - ;; tried to use flymake but it doesn't let you do it manually - (with-temp-buffer - (insert-file-contents file))) - (error "Couldn't find any elisp files")))) - - -(defun compile (dir) - "Compile all the elisp files in the given DIR regardless of timestamp. -The DIR should be relative to FG42_HOME." - (let ((target (->path dir))) - (message "Compiling '%s'..." target) - (add-to-list 'load-path target) - (byte-recompile-directory target 0 t))) - - -(defun build (&rest params) - "Compile the core and install the dependencies with the given PARAMS." - (compile "core")) - - -(defun todo (dir) - "Extract the TODO tags from the comments in the given DIR." - (message "TBD")) - - -(defun fpkg-init (params) - "Setup fpkg repository with the given PARAMS." - (require 'fg42/fpkg/core) - (fg42-fpkg/initialize FG42)) - -(defun print-fpkg-help (command) - "Print the usage for fpkg and the possible wrong COMMAND." - (message "Usage:\n") - (message "init - Setup the fpkg repository")) - - -(defun fpkg (params) - "The main interface to `fpkg' subcommand and PARAMS." - (let ((subcommand (car args)) - (args (cdr params))) - (cond - ((string= subcommand "init") (funcall #'fpkg-init args)) - (t (print-fpkg-help subcommand))))) - -(defun print-help (command) - "Print out a usage instructions and print out the invalid msg for COMMAND." - (when command - (warn "I don't know about '%s' command.\n" command)) - - (message "Usage:\n") - (message "compile [DIR] - Compiles the given DIR to bytecodes (default: \"core\")") - (message "build - Builds FG42 by compiling the code and installing dependencies.")) - - -(defun main () - "Execute a subcommand by looking into input arguments of the script." - (message (version)) - (message "\nFG42 Build tool v%s\n\n" FG42_VERSION) - - (let ((fg42-home (car command-line-args-left)) - (command (cadr command-line-args-left)) - (args (cddr command-line-args-left))) - - ;; FG42 Needs this env var to know where had it been installed - (setenv "FG42_HOME" fg42-home) - (setenv "FG42_VERSION" FG42_VERSION) - - (add-to-list 'load-path (concat (file-name-as-directory fg42-home) "core")) - (load (concat (file-name-as-directory (getenv "FG42_HOME")) "system")) - - (cond - ((string= command "fpkg") (funcall #'fpkg args)) - ((string= command "lint") (funcall #'lint (or (car args) "core"))) - ((string= command "compile") (funcall #'compile (or (car args) "core"))) - ((string= command "build") (funcall #'build args)) - (t (print-help command))))) - -;; Local Variables: -;; mode: emacs-lisp -;; End: -;;; fbt ends here diff --git a/fbt/fbt/build.el b/fbt/fbt/build.el new file mode 100644 index 0000000..179c00a --- /dev/null +++ b/fbt/fbt/build.el @@ -0,0 +1,52 @@ +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;;; Code: + +(require 'fbt/utils) +(require 'fbt/compile) + + +(defun fbt-build/-clean (dir) + "Clean up all the elc files from the given DIR." + (let ((elcs (elc-files-in dir))) + (when elcs + (message + (shell-command-to-string + (format "rm -v %s" (apply #'concat + (mapcar (lambda (x) (format " %s" x)) elcs)))))))) + + +(defun fbt-build/clean (dirs) + "Clean the given DIRS from elc files." + (mapc #'fbt-build/-clean dirs)) + + +(defun fbt-build/build (&rest params) + "Compile the core and install the dependencies with the given PARAMS." + (fbt-compile/compile "core")) + + + +(provide 'fbt/build) +;;; build.el ends here diff --git a/fbt/fbt/compile.el b/fbt/fbt/compile.el new file mode 100644 index 0000000..deadd3c --- /dev/null +++ b/fbt/fbt/compile.el @@ -0,0 +1,41 @@ +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;;; Code: + +(require 'fbt/utils) + + +(defun fbt-compile/compile (dir) + "Compile all the elisp files in the given DIR regardless of timestamp. +The DIR should be relative to FG42_HOME." + (let ((target (->path dir))) + (message "Compiling '%s'..." target) + (add-to-list 'load-path target) + + (message "Load path:\n%s\n" (apply #'concat (mapcar (lambda (x) (format "%s\n" x)) load-path))) + (byte-recompile-directory target 0 t))) + + +(provide 'fbt/compile) +;;; compile.el ends here diff --git a/fbt/fbt/fpkg.el b/fbt/fbt/fpkg.el new file mode 100644 index 0000000..21ab98a --- /dev/null +++ b/fbt/fbt/fpkg.el @@ -0,0 +1,150 @@ +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;;; Code: +(require 'fg42/system/core) +(require 'fg42/system/api) + +(defvar bootstrap-version nil + "`straight.el' bootstrap version. Set it in the `system' level, not here.") + +(defvar straight-base-dir) +(defvar straight-repository-branch) +(defvar straight-cache-autoloads) +(defvar straight-check-for-modifications) +(defvar straight-enable-package-integration) +(defvar straight-vc-git-default-clone-depth) +(defvar autoload-compute-prefixes) +(defvar straight-fix-org) +(defvar straight-recipe-repositories) +(defvar straight-recipe-overrides) + + +(defun fbt-fpkg/-set-straight-values (system) + "Set the default values for some of `straight.el' vars for the SYSTEM." + (setq straight-base-dir (fg42-system/fpkg-path system) + straight-repository-branch "develop" + ;; Our autoload process is different. + straight-cache-autoloads nil + ;; `straight.el' suppose to be a functional pkg manager but it actually + ;; allows user to edit libraries in place which we don't like it. + ;; We have our own mechanism to allow users extend FG42 so we don't + ;; want `straight.el' to handle it. Frankly it reduces the boot time + ;; by a lot. + straight-check-for-modifications nil + straight-enable-package-integration nil + ;; We don't want `straight.el' to deep clone the dependencies. Some packages + ;; might break this way according to `doom-emacs' + straight-vc-git-default-clone-depth 1 + ;; We have our own autoload system. + autoload-compute-prefixes nil + straight-fix-org nil)) + + +(defun fbt-fpkg/-install-core-dependencies (system) + "Install the core dependencies of the given SYSTEM. +Core dependencies are thoses packages that the system itself is depends on +and not the extensions." + (mapc #'straight-use-recipes (fg42-system/core-dependencies system))) + + +(defun fbt-fpkg/initialize (system) + "Initilize the package manager for the given SYSTEM. +Basically fpkg will bootstrap and `straight.el' repositoryu for the given +SYSTEM by fetching the required values from it. Including the path to the +target directory." + (unless (fboundp 'straight--reset-caches) + (let ((bootstrap-file (concat (fg42-system/fpkg-path system) + "straight/repos/straight.el/bootstrap.el")) + (bootstrap-version (fg42-system/fpkg-backend-version system))) + + (make-directory (fg42-system/fpkg-path system) t) + (fbt-fpkg/-set-straight-values system) + + (or (require 'straight nil t) + (file-readable-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + (format "https://raw.githubusercontent.com/raxod502/straight.el/%s/install.el" + straight-repository-branch) + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp)) + (load bootstrap-file nil t))) + (require 'straight)) + + (straight--reset-caches) + (fbt-fpkg/-install-core-dependencies system) + + (setq straight-recipe-repositories nil + straight-recipe-overrides nil) + + ;; Someday we might have to use our own fork of `straight.el' + (straight-register-package + `(straight :type git :host github + :repo "raxod502/straight.el" + :files ("straight*.el") + :branch ,straight-repository-branch + :no-byte-compile t)) + + (fg42-system/fpkg-initilized! system)) + + +(defun fbt-fpkg/initialize-once (system) + "Initilize FPKG only once for the given SYSTEM." + (when (not (fg42-system/fpkg-initilized-p system)) + (fbt-fpkg/initialize system) + ;; TODO: Install `use-package' + ;; (straight-use-package 'use-package) + )) + + +(defun fbt-fpkg/init (system params) + "Setup fpkg repository with the given PARAMS for the given SYSTEM." + (fbt-fpkg/initialize-once system)) + + +(defun fbt-fpkg/print-help (command) + "Print the usage for fpkg and the possible wrong COMMAND." + (message "Usage:\n") + (message "init - Setup the fpkg repository")) + + +(defun fbt-fpkg (system params) + "The main interface to `fpkg' subcommand and PARAMS for the loaded SYSTEM." + (let ((subcommand (car args)) + (args (cdr params))) + (cond + ((string= subcommand "init") (funcall #'fbt-fpkg/init system args)) + (t (fbt-fpkg/print-help subcommand))))) + + +(defun fpt-fpkg/initialize-load-path (system) + "Setup the required load paths from the given SYSTEM." + (add-to-list 'load-path + (path-join (fg42-system/fpkg-path system) + "straight/repos/straight.el/"))) + + +(provide 'fbt/fpkg) +;;; fpkg.el ends here diff --git a/fbt/fbt/lint.el b/fbt/fbt/lint.el new file mode 100644 index 0000000..01c6967 --- /dev/null +++ b/fbt/fbt/lint.el @@ -0,0 +1,42 @@ +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;;; Code: + +(require 'fbt/utils) + + +(defun lint (dir) + "Run linter on all the elisp files in the given DIR." + (let ((files (el-files-in dir))) + (if files + (dolist (file files) + ;; TODO: Setup flycheck here and use it to lint the elisp file. + ;; tried to use flymake but it doesn't let you do it manually + (with-temp-buffer + (insert-file-contents file))) + (error "Couldn't find any elisp files")))) + + +(provide 'fbt/lint) +;;; lint.el ends here diff --git a/fbt/fbt/utils.el b/fbt/fbt/utils.el new file mode 100644 index 0000000..04269e4 --- /dev/null +++ b/fbt/fbt/utils.el @@ -0,0 +1,57 @@ +;;; FGBuildTool --- The build tool for FG42 +;; +;; Copyright (c) 2010-2020 Sameer Rahmani +;; +;; 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 this program. If not, see . +;; +;; +;;; Commentary: +;;; Code: +(defun ->path (dir) + "Return the absolute path to the given DIR with respect to FG42_HOME." + (concat (getenv "FG42_HOME") (format "/%s" dir))) + + +(defun find-files (dir suffix) + "Find all the files with the given SUFFIX in the given DIR." + (split-string (shell-command-to-string + (format "find %s -iname \"*.%s\"" (->path dir) suffix)) "\n" t)) + + +(defun el-files-in (dir) + "Return a list of elisp files in the given DIR." + (find-files dir "el")) + + +(defun elc-files-in (dir) + "Return a list of elisp files in the given DIR." + (find-files dir "elc")) + + +;; TODO: Merge this into a unified utils module with the one +;; from `fg42/utils' package +(defun path-join (&rest paths) + "Join the given PATHS." + (apply #'concat + (append + (mapcar #'file-name-as-directory (butlast paths)) + (last paths)))) + + +(provide 'fbt/utils) +;;; utils.el ends here