;;; extension --- Extension library of FG42 ;; ;; Copyright (c) 2010-2020 Sameer Rahmani ;; ;; Author: Sameer Rahmani ;; URL: https://gitlab.com/FG42/FG42 ;; Version: 0.1.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: ;; This library is heavily inspired by Kite mini library. Kudos Tung Dao ;; for his great work. ;; ;;; Commentary: ;;; Code: ;; This library provides some basic means to create a new FG42 extensions (require 'cl-lib) ;; Variables ----------------------------- (defvar activated-extensions () "A list of all activated extensions.") (defvar disabled-abilities (make-hash-table) "A hash of all the disabled abilities.") ;; Structures ----------------------------- (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 ;; 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) ;; Callbacks (on-initialize nil) (on-load) (on-unload)) ;; Functions ------------------------------ (defun active-ability? (name) "Return t if ability with the given NAME was not in disabled-abilities." (if (gethash name disabled-abilities) nil t)) (defun disable (&rest abilities) "Add the given ABILITIES to disabled-abilities hash." (dolist (abl abilities) (puthash abl t disabled-abilities))) ;; Macros --------------------------------- (defmacro ability (name deps &rest body) "Define an ability with the given NAME, DEPS, and BODY. *deps* should be a list of abilities with the defined ability dependens to them. *body* is a block of code which will run as the ability initializer code." (declare (doc-string 2) (indent 0)) `(if (active-ability? (intern ,(symbol-name name))) (when (null (delq t (mapcar 'active-ability? (quote ,deps)))) ,@body))) (defmacro extension (name &rest args) "A simple DSL to define new fg42 extension by given NAME and ARGS." ;(declare (doc-string 1) (indent 1)) `(setq ,name (apply 'make-fg42-extension :name ,(symbol-name name) (quote ,args)))) (defmacro with-ability (name &rest body) "If the ability with the given NAME is not disabled, Run the BODY." `(when (active-ability? (intern ,(symbol-name name))) ,@body)) (defun describe-extension (extension) "Show the doc-string of the EXTENSION." (interactive) (let ((doc-file (fg42-extension-docs (symbol-value extension))) (b (get-buffer-create (concat "*" (symbol-name extension) " docs*")))) (set-buffer b) (insert-file-contents (concat fg42-home "/" doc-file)) (read-only-mode t) (switch-to-buffer b) (org-mode))) (provide 'fg42/extension) ;;; extension ends here