diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4e32ab6..2bfb9fc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,10 +6,26 @@ stages: stage: build before_script: - apt update && apt install -y make wget git emacs sudo - - git clone -b fpkg-v2 https://gitlab.com/FG42/FG42 ~/.fg42/ && cd ~/.fg42/ && make install && + - git clone -b $CI_COMMIT_REF_NAME https://gitlab.com/FG42/FG42 ~/.fg42/ && cd ~/.fg42/ && make install && script: - cd ~/.fg42/ && fg42 -nw --script build.el +.build-v3: + image: debian:stable-slim + stage: build + before_script: + - apt update && apt install -y make wget git emacs sudo + - git clone -b $CI_COMMIT_REF_NAME https://gitlab.com/FG42/FG42 ~/.fg42/ + script: + - cd ~/.fg42/ && ./fbt build + +build-branches-v3: + extends: .build-v3 + only: + - branches + except: + - tags + build-branches: extends: .build only: diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..4d788cc --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,17 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] +### Added + - `System` implementation (`core/fg42/system.el`) + - New `extensions` implementation (`core/fg42/extensions.el`) + - New approach to launching fg42 + - New `compiler` target to Makefile +### Changed + - Changed the main package path to `/core` + - Changed the extensions path to `/extensions` + - We don't load `fg42-config.el` anymore + - We don't load anything from `/lib` anymore diff --git a/CONTRIBUTE b/CONTRIBUTE new file mode 100644 index 0000000..e7100b7 --- /dev/null +++ b/CONTRIBUTE @@ -0,0 +1,148 @@ +# Contribution Guidelines +*FG42* is a free software and a community of Emacs developers who like to share +their ideas and tools. We encourage you to join us. The community is what matters +to us. Here is a brief overview of contribution guidelines, which we ask all +contributors to follow. + +## Asking for help +If you want to ask an usage question, first make sure to read the `README.md` file +and the documents of *FG42*. If you still need help feel free to join us via +[out gitter channel](https://gitter.im/FG42/FG42). + +## Reporting issues +Issues have to be reported on our [issues tracker](https://gitlab.com/FG42/FG42/issues). Please: + +- Check that the issue has not already been reported. + - This can be achieved by searching keywords on the [issues tracker](https://gitlab.com/FG42/FG42/issues). +- Try to use a clear title, and describe your problem with complete sentences. + - Include your emacs version and `~/.fg42.el` file as well. + - If possible, try to include details on how to reproduce it, like a step by + step guide. + +## Contributing code +Code contributions are welcome. Please read the following sections carefully. In +any case, feel free to join us on [out gitter channel](https://gitter.im/FG42/FG42) to ask questions about +contributing! + +### General contribution + +#### License +The license is *GPLv2* for all parts specific to *FG42*, this includes: +- The initialization and core files +- All the built-in extensions. + +For files not belonging to FG42 like local packages and libraries, refer +to the header file. Those files should not have an empty header, we may not +accept code without a proper header file. + +#### Conventions +We follow these simple rules: + +* Make elisp linter happy +* Make byte compiler happy `make compile` +* Follow functional patterns and avoid huge functions +* Seperate each root level expression by two new lines (e.g function definitions) +* Put `(comment ...)` expression after each macro/function to demonstrate the usage. +* Write good docstrings +* Choose meaningful names +* Follow the indentation guides made in FG42 +* Prefix the functions with a prefix to differentiate them from other functions. + for example `fg42-namespace/functoin-name`. +* use `/-` for private/internal function names +* use `/` to categorize functions into namespaces (air quote) + +#### Pull-Request +Submit your contribution against the `master` branch. The `stable` branch +is going to be our last stable version only. + +Please make one PR per feature. Keep your PRs as small as possible so we can review them +easily. Don't forget to make the byte compiler and the linter happy. There should not +be any build error or warning on `make compile`. We like how [Linus Torvalds thinks +about build warnings](https://linuxreviews.org/Linus_Torvalds#On_Build-Testing). + +Write commit messages according to adapted [this article](https://chris.beams.io/posts/git-commit/): + +- Include the extension or library name in the title inside square brackets +- Use present tense and write in the imperative: “Fix bug”, not “fixed bug” or + “fixes bug”. +- Start with a capitalized, short (72 characters or less) summary, followed by a + blank line. +- If necessary, add one or more paragraphs with details, wrapped at 72 + characters. +- Separate paragraphs by blank lines. + +This is a model commit message: + +``` +[FPKG] Capitalized, short (72 chars or less) summary + +More detailed explanatory text, if necessary. Wrap it to about 72 +characters or so. In some contexts, the first line is treated as the +subject of an email and the rest of the text as the body. The blank +line separating the summary from the body is critical (unless you omit +the body entirely); tools like rebase can get confused if you run the +two together. + +Write your commit message in the imperative: "Fix bug" and not "Fixed bug" +or "Fixes bug." This convention matches up with commit messages generated +by commands like git merge and git revert. + +Further paragraphs come after blank lines. + +- Bullet points are okay, too + + - Typically a hyphen or asterisk is used for the bullet, followed by a + single space, with blank lines in between, but conventions vary here + + - Use a hanging indent +``` + +[[https://github.com/magit/magit/][Git Commit]] and [[https://github.com/magit/magit/][Magit]] provide Emacs mode +for Git commit messages, which helps you to comply to these guidelines. + +### Contributing an extension +Technical aspects TBD + +Each file should be GPL compliant and contain the following header: + +```lisp +;;; FILENAME --- SHORT DESCRIPTION +;; +;; Copyright (c) 2010-2020 Sameer Rahmani & Contributors +;; +;; Author: YOUR FULL NAME +;; URL: https://gitlab.com/FG42/FG42 +;; Version: VERSION +;; +;; 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: +;; THE COMMENTARY ON THE MOST IMPORTANT ASPECT OF THE EXTENSION +;; +;;; Code: +``` + +You should replace `FILENAME` by the name of the file (e.g. `packages.el`). +Don't forget to replace `YOUR FULL NAME` and `YOUR EMAIL` also. + +#### Contribute to an existing extension +If you are contributing to an already existing extension, you should not modify any +header file. + +* Credits + +This `CONTRIBUTING` file is partially based on the [Rails Contribution +guidelines](https://github.com/rails/rails/blob/master/CONTRIBUTING.md) +and [Flycheck Contribution guidelines](https://github.com/flycheck/flycheck/blob/master/CONTRIBUTING.md) +and [Spacemacs Contribution guidelines](https://raw.githubusercontent.com/syl20bnr/spacemacs/master/CONTRIBUTING.org). diff --git a/Makefile b/Makefile index 99c3911..b82ba64 100644 --- a/Makefile +++ b/Makefile @@ -51,3 +51,12 @@ install: install-fonts: @mkdir -p ~/.fonts/ @cp -rv ./share/fonts/vazir/* ~/.fonts/ + +.PHONY: compile +compile: + @$(PWD)/fg42-new --script scripts/compiler.el + +.PHONY: clean +clean: + @rm -rf $(shell find `pwd` -iname "*~") + @rm -rf $(shell find `pwd`/core -iname "*.elc") diff --git a/core/fg42.el b/core/fg42.el new file mode 100644 index 0000000..3f0bbf9 --- /dev/null +++ b/core/fg42.el @@ -0,0 +1,39 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; 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/utils) + +(autoload 'fg42-system/start "fg42/system" + "Starts the given SYSTEM.") + + +(defun fg42/start! (system) + "Start the given SYSTEM description." + (fg42-system/set-system! system) + + (add-hook 'window-setup-hook + (lambda () (fg42-system/start)))) + + +(provide 'fg42) +;;; fg42.el ends here diff --git a/core/fg42/extensions.el b/core/fg42/extensions.el new file mode 100644 index 0000000..c8faea6 --- /dev/null +++ b/core/fg42/extensions.el @@ -0,0 +1,91 @@ +;;; extensions --- Extension library of FG42 -*- lexical-binding: t; -*- +;; +;; 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: + +;; This library provides some basic means to create a new FG42 extensions +(require 'fg42/utils) +(require 'fg42/extensions/core) + + +(defun fg42-extensions/load-index (_system ext-name ext-path) + "Load the extension EXT-NAME which is in EXT-PATH using SYSTEM. +It will load the main file of the extension and return the `fg42-extension' +instance of the extension and nil otherwise." + (let ((is-loaded? (require ext-name ext-path t))) + (when is-loaded? + (symbol-value ext-name)))) + + +(defun fg42-extensions/load-extension (system ext) + "Setup the given extension EXT against the given SYSTEM. +At this stage we will install/load the main file of the extensions +and call the `on-initialize'function of extensions in order to setup +the autoloads and hooks." + (cond + ((symbolp ext) + (fg42-extensions/load-index system ext (fg42-extensions/path system ext))) + + ((listp ext) + (fg42-extensions/load-index system (car ext) (cadr ext))) + (t + ;; TODO: instead of throwing and error, inject the error into the system + (throw 'load-extension-failed + (format "Can't load extension %s" (->str ext)))))) + + +(defun fg42-extensions/load-system-extensions (system) + "Load the extensions defined in the given SYSTEM. + +SYSTEM should be an instance of `fg42-system' which contains a list +of extension names on the `extensions' field. This function finds and +loads the index file of those extensions and returns a new system +containing the `fg42-extension' instances." + (let ((exts (mapcar (lambda (ext) + (fg42-extensions/load-extension system ext)) + (fg42-system-extensions system)))) + (setf (fg42-system-extensions system) + exts)) + system) + + +(defun fg42-extensions/initialize (system ext) + "Initialize the given extension EXT aginst the given SYSTEM." + (funcall (fg42-extension-on-initialize ext) system)) + + +(defun fg42-extensions/initialize-extensions (system) + "Initialize the extensions within SYSTEM and return a new system." + (mapc + (lambda (ext) (fg42-extensions/initialize system ext)) + (fg42-system-extensions system)) + system) + + +(defun fg42-setup-extensions (system) + "Setup the preloads for the given SYSTEM." + (funcall (comp #'fg42-extensions/initialize-extensions + #'fg42-extensions/load-system-extensions) system)) + + +(provide 'fg42/extensions) +;;; extensions.el ends here diff --git a/core/fg42/extensions/core.el b/core/fg42/extensions/core.el new file mode 100644 index 0000000..6a5a530 --- /dev/null +++ b/core/fg42/extensions/core.el @@ -0,0 +1,91 @@ +;;; extensions --- Extension library of FG42 -*- lexical-binding: t; -*- +;; +;; 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 'cl-lib) +(require 'fg42/system/core) + + +(cl-defstruct fg42-extension + "Each FG42 extension should implement a copy of this structure." + name + + ;; Let's keep this field for backward compatiblity for a while + docs + + ;; Each extension should expose a info page. + doc-index + ;; To be used with `describe-extension' + (docstring nil) + ;; Projectile provides a project type that we can use to + ;; activate/load the extensions based on their registered + ;; type. + project-types + + (version nil) + + ;; An instance of fg42-actions structure that describe the + ;; different actions of the given extension + (actions nil) + (path nil) + ;; Callbacks + (on-initialize nil) + (on-load) + (on-unload)) + + +(defun fg42-extensions/build-path (system ext) + "Build a path for the given EXT name (symbol) via SYSTEM info." + ;; TODO: should we extract variables such as `fg42-home' to their + ;; dedicated ns in order to avoid the warning ? + (let ((ext-name (symbol-name ext))) + (concat (fg42-system-root system) + "/extensions/" ext-name "/" ext-name ".el"))) + + +(defun fg42-extensions/path (system ext) + "Return the path to the given extension EXT in the given SYSTEM." + (cond + ((symbolp ext) (fg42-extensions/build-path system ext)) + ((fg42-extension-p ext) + (or (fg42-extension-path ext) + (fg42-extensions/build-path system + (intern (fg42-extension-name ext))))))) + + +(defmacro defextension (name docstring &rest args) + "A simple DSL to define new fg42 extension by given NAME, DOCSTRING and ARGS." + (declare (doc-string 2) (indent 1)) + ;; TODO: Inject the docstring to the current `system' in order + ;; to collect it later for `describe-extension' function. + (when (not (stringp docstring)) + (throw 'extention-error + "`docstring' is mandatory and it should be a string.")) + `(setq ,name (apply 'make-fg42-extension + :name ,(symbol-name name) + :docstring ,docstring + (quote ,args)))) + + +(provide 'fg42/extensions/core) +;;; core.el ends here diff --git a/core/fg42/system.el b/core/fg42/system.el new file mode 100644 index 0000000..ac87e53 --- /dev/null +++ b/core/fg42/system.el @@ -0,0 +1,41 @@ +;;; system --- System library of FG42 -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2020 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 this program. If not, see . +;; +;;; Commentary: +;; `System' is just a state monad which holds the state of the editor. +;; Each system has to have a `start' function to start the setup process. +;; +;;; Code: + +;;;###autoload +(defun fg42-system/start () + "Start the system from `fg42-get-current-system'." + (require 'fg42/utils) + (require 'fg42/system/core) + (require 'fg42/system/utils) + + (debug-message "Starting the default system.") + (let ((sys (fg42-system/get-active-system))) + (funcall (fg42-system-start sys) sys))) + + +(provide 'fg42/system) +;;; system.el ends here diff --git a/core/fg42/system/core.el b/core/fg42/system/core.el new file mode 100644 index 0000000..a16c5ef --- /dev/null +++ b/core/fg42/system/core.el @@ -0,0 +1,71 @@ +;;; system --- System library of FG42 -*- lexical-binding: t; -*- +;; +;; 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: +;; `System' is just a state monad which holds the state of the editor. +;; Each system has to have a `start' function to start the setup process. +;; +;;; Code: + +(require 'cl-lib) +(require 'fg42/utils) + + +(cl-defstruct fg42-system + "A `system' describes a FG42 instance. Everything that is needed +to load FG42." + name + + ;; We will use this value for `describe-system' as a short + ;; documentation. + docstring + + ;; TODO: guess the system root based on the `name' field + ;; as the default value + (root (concat (getenv "HOME") "/.fg42")) + + ;; The directory to store all sort of temporary files including + ;; backups, flycheck temps and stuff like that. + (tmp-path "~/.tmp") + + ;; ;; A list of preloads to setup extensions which are not loaded yet. + ;; ;; For more information on preloads checkout `fg42/extension' + ;; (preloads '()) + + (extensions '()) + (abilities '()) + ;; A function which takes the `system' and starts it. + (start (lambda (system) system)) + (stop nil)) + + +(defmacro defsystem (name &optional docstring &rest body) + "Define a system with the given NAME, DOCSTRING and BODY." + (declare (doc-string 2) (indent 1)) + (let ((form (if (boundp (intern (format "%s" name))) 'setq 'defvar))) + `(,form ,name (make-fg42-system + :name ,(symbol-name name) + :docstring ,docstring + ,@body)))) + + +(provide 'fg42/system/core) +;;; core.el ends here diff --git a/core/fg42/system/utils.el b/core/fg42/system/utils.el new file mode 100644 index 0000000..2805b46 --- /dev/null +++ b/core/fg42/system/utils.el @@ -0,0 +1,47 @@ +;;; system --- System library of FG42 -*- lexical-binding: t; -*- +;; +;; 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: +;; `System' is just a state monad which holds the state of the editor. +;; Each system has to have a `start' function to start the setup process. +;; +;;; Code: + +(defvar fg42-system/active--system nil + "A private variable to store the active system. +Use `fg42-get-current-system' instead") + + +(defun fg42-system/get-active-system () + "Return the current active system of FG42." + fg42-system/active--system) + + +(defun fg42-system/set-system! (system) + "Set the current system to the given SYSTEM." + ;; TODO: In the future when we moved to parallel boot + ;; we need to make sure that this funciton + ;; sets the state safely. + (setq fg42-system/active--system system)) + + +(provide 'fg42/system/utils) +;;; utils.el ends here diff --git a/core/fg42/utils.el b/core/fg42/utils.el new file mode 100644 index 0000000..35bce53 --- /dev/null +++ b/core/fg42/utils.el @@ -0,0 +1,125 @@ +;;; Utils --- Utils library of FG42 -*- lexical-binding: t; -*- +;; +;; 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: +;; `System' is just a state monad which holds the state of the editor. +;; Each system has to have a `start' function to start the setup process. +;; +;;; Code: + +(require 'cl-lib) + +(autoload 'seq-partition "seq") +(autoload 'cl-reduce "cl-seq") + + +(defun buffer-mode (buffer-or-string) + "Return the major mode associated with a the given BUFFER-OR-STRING." + (with-current-buffer buffer-or-string + major-mode)) + + +(defun ->buffer (buffer-name data &optional fn) + "Insert the given DATA into the given buffer provided by BUFFER-NAME. + +It will create a the buffer if it doesn't exist. It will call the given FN +at the end in context of the buffer. This function accepts only one argument +with is the buffer." + (let ((buf (get-buffer-create buffer-name))) + (with-current-buffer buf + (insert data) + (when fn + (funcall fn buf))))) + + +(defun ->str (&rest args) + "Convert the given ARGS into string." + (funcall #'pp-to-string args)) + + +(defmacro inspect-expression (&rest body) + "Pretty prints the result of the given BODY." + `(pp-display-expression ,@body (get-buffer-create fg42/inspect-buffer))) + + +(defun inspect-data-append (data) + "Append the given DATA to the inspection buffer with padding." + ;; TODO: Move 'fg42/inspect-buffer' to the somewhere propriate + ;; possiblly the system. + (->buffer + "fg42/inspect-buffer" + (format + "\n;; START ======================================================\n%s%s" + (pp-to-string data) + ";; END.\n"))) + + +(defun apply-face (face-symbol text) + "Apply the given FACE-SYMBOL to the given TEXT." + (put-text-property 0 (length text) 'face face-symbol text)) + + +(defmacro comment (&rest _body) + "A macro similar to Clojure's comment macro that ignore the BODY." + (declare (indent 0)) + `nil) + + +(defmacro debug-message (&rest params) + "Print out the given PARAMS only if debug mode is on." + (if debug-on-error + `(message ,@params) + nil)) + + +(defmacro deprecated (msg &rest form) + "Mark the given FORM as deprecated with the given MSG." + (declare (indent 0)) + `(progn + (warn (format "[DEPRECATED]: %s" ,msg)) + ,@form)) + + +;; TODO: A good candidate for an inline function +(defun find-value-for (lst key) + "Return the value of the given KEY in the given LST. +For example for a list like (list :x 4 :y 5) we can find the value of +`:x' by doing `(get-value-for lst :x)'." + (let ((pairs (seq-partition lst 2))) + (let ((pair (assq key pairs))) + (when pair + (cadr pair))))) + + +(defun comp (&rest fns) + "Compose the given list of FNS into one function that accepts multiple values. +For example: + (funcall (compose (lambda (x) (+ 1 x)) (lambda (x) (* x s))) 5) +or + (funcall (compose #'some-fn #'message) some-value)" + (lambda (&rest values) + (cl-reduce 'funcall (butlast fns) + :from-end t + :initial-value (apply (car (last fns)) values)))) + + +(provide 'fg42/utils) +;;; utils.el ends here diff --git a/extensions/fg42-elisp b/extensions/fg42-elisp new file mode 160000 index 0000000..721da6e --- /dev/null +++ b/extensions/fg42-elisp @@ -0,0 +1 @@ +Subproject commit 721da6e0a242eb6630dd476f2d8e1146d67d2e40 diff --git a/fbt b/fbt new file mode 100755 index 0000000..d3171a1 --- /dev/null +++ b/fbt @@ -0,0 +1,98 @@ +:;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 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) + + (cond + ((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/fg42-new b/fg42-new new file mode 100755 index 0000000..eb9e125 --- /dev/null +++ b/fg42-new @@ -0,0 +1,10 @@ +#! /bin/sh + +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 \ + -L $FG42_HOME/core \ + -L $FG42_HOME/extensions \ + -l $FG42_HOME/core/fg42.el \ + -l ~/.v3.el "$@" diff --git a/system.el b/system.el new file mode 100644 index 0000000..9d289dd --- /dev/null +++ b/system.el @@ -0,0 +1,39 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; 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 . +;; +;;; Acknoledgement: +;; Thanks to all the people who contributed to FG42. +;; +;;; Commentary: +;;; Code: + +(require 'fg42) +(require 'fg42/system/core) + + +(defsystem FG42 + "FG42 implemented in term of systems and this is the default system." + :start (lambda (system) (message "hooray!")) + :extensions '(fg42-elisp)) + + +(provide 'system) +;;; system.el ends here