diff --git a/flake.nix b/flake.nix index b239fd6..833cf30 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,7 @@ }; fg42 = pkgs.callPackage ./nix/fg42 { + inherit nixpkgs; extraPackages = { noether = inputs.noether.outputs.packages.${system}.default; }; diff --git a/lisp/build.el b/lisp/build.el index 9b49d6c..dd92b15 100644 --- a/lisp/build.el +++ b/lisp/build.el @@ -65,6 +65,7 @@ ;; Since it is deprecated we can easily avoide other packages to use it (provide 'cl) +(require 'fg42/pre) ") (defvar file-footer " @@ -77,11 +78,12 @@ ;; Elisp's hashtables are not functional so I have to store the ;; state like this, Ewwwwww! -(defvar build-state '() - "A list of expressions that will dump in the output at the end.") -(defvar vars ()) -(defvar requires ()) +(defvar vars () + "Storage for the vars and const forms.") + +(defvar requires () + "Storage for the require forms.") (defvar build-output (cadr command-line-args-left)) @@ -98,18 +100,25 @@ ,@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 pkg))) elisp-pkgs))))) + ,@(mapcar (lambda (pkg) `(require ',(intern (replace-in-string "fg42-" "fg42/" pkg)))) elisp-pkgs))))) -(defun generate-generic-vars (k v doc) - "Generate a list of vars for K and value V with docstring DOC." - (add-to-list 'vars `(defvar ,(intern (format "fg42/config/%s" k)) ,v ,doc))) +(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) @@ -123,7 +132,20 @@ ((member k keys-to-skip) (message "[build.el]: Skipping %s..." k)) - (t (generate-generic-vars k v (gethash k (gethash "docstrings" config))))))) + ((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. diff --git a/nix/fg42/default.nix b/nix/fg42/default.nix index 147b62f..e8a1778 100644 --- a/nix/fg42/default.nix +++ b/nix/fg42/default.nix @@ -18,6 +18,7 @@ # from FG42 modules that are structurally the same but used in # different context { pkgs +, nixpkgs , lib ? pkgs.lib , modules ? null , extraModules ? [ ] @@ -37,11 +38,14 @@ let utils = pkgs.callPackage ./utils.nix { }; final = lib.evalModules { - modules = [ ./unit.nix ] ++ fg42Modules ++ extraModules; + # The unit module is mandatory and the bare min + # config that is necessary + modules = [ ../modules/unit ] ++ fg42Modules ++ extraModules; specialArgs = { inherit utils; inherit (utils) makeFG42Drv; inherit extraPackages; + lib = nixpkgs.lib.extend (import ./lib.nix { inherit pkgs; }); }; }; in diff --git a/nix/fg42/derivation.nix b/nix/fg42/derivation.nix index 8e0a715..e81e50e 100644 --- a/nix/fg42/derivation.nix +++ b/nix/fg42/derivation.nix @@ -52,14 +52,18 @@ let configFile = writeTextFile { name = "config.json"; - text = (toJSON config); + text = (toJSON { + fg42 = { + inherit (cfg) vars consts requires; + }; + }); executable = false; }; in stdenv.mkDerivation rec { inherit version; - pname = "FG42"; + pname = builtins.trace ">>> ${configFile}" "FG42"; src = ../../.; diff --git a/nix/fg42/lib.nix b/nix/fg42/lib.nix new file mode 100644 index 0000000..fedaef6 --- /dev/null +++ b/nix/fg42/lib.nix @@ -0,0 +1,44 @@ +# Fg42 - Emacs Editor for advance users +# +# Copyright (c) 2010-2024 Sameer Rahmani +# +# 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, version 2. +# +# 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 . +{ pkgs, ... }: +final: prev: +rec { + defVar = name: defaultValue: docstring: { + inherit name defaultValue docstring; + }; + + defConst = defVar; + + + makeFG42Drv = { pname, version, ... }@args: + (pkgs.emacsPackages.trivialBuild args).overrideAttrs (old: { + pname = "fg42-${pname}"; + + installPhase = '' + runHook preInstall + + LISPDIR=$out/share/emacs/ + install -d $LISPDIR + cp -rv lisp/ $LISPDIR/site-lisp + + emacs --batch -l package --eval "(package-generate-autoloads \"${args.pname}\" \"$LISPDIR/site-lisp\")" + + runHook postInstall + ''; + + }); + +} diff --git a/nix/modules/default.nix b/nix/modules/default.nix index e4958e3..e6d4b5b 100644 --- a/nix/modules/default.nix +++ b/nix/modules/default.nix @@ -31,7 +31,6 @@ let _module.args.baseModules = modules; _module.args.pkgs = lib.mkDefault pkgs; _module.check = true; - #inherit lib; }; }; in diff --git a/nix/modules/editor/default.nix b/nix/modules/editor/default.nix index 38d1908..6277d78 100644 --- a/nix/modules/editor/default.nix +++ b/nix/modules/editor/default.nix @@ -21,6 +21,8 @@ # A list of default FG42 modules to build FG42 with. { lib, config, pkgs, makeFG42Drv, extraPackages, ... }: let + cfg = config.fg42; + deps = (with pkgs.emacsPackages; [ origami @@ -44,9 +46,6 @@ let ctrlf consult marginalia - magit - forge - diff-hl svg-tag-mode all-the-icons org @@ -69,15 +68,17 @@ let }; dicts = pkgs.aspellWithDicts (dicts: with dicts; [ en en-computers en-science ]); + emojifyDocString = "Whether or not to use the `emojify' package."; in { options = (with lib; { - fg42.emojify = mkOption { - type = types.bool; - default = false; - description = "Whether or not to use the `emojify' package."; - }; + fg42.emojify = mkOption + { + type = types.bool; + default = false; + description = emojifyDocString; + }; }); config = { @@ -96,7 +97,9 @@ in ]); fg42.font = lib.mkDefault '''("Fira Mono" 11)''; - fg42.theme = lib.mkDefault "base16-eighties"; - fg42.theme-package-name = lib.mkDefault "base16-theme"; + fg42.requires = [ drv.pname ]; + fg42.vars = [ + (lib.defVar "emojify" cfg.emojify emojifyDocString) + ]; }; } diff --git a/nix/modules/editor/lisp/fg42/editor.el b/nix/modules/editor/lisp/fg42/editor.el index e1ec4c5..0c518e0 100644 --- a/nix/modules/editor/lisp/fg42/editor.el +++ b/nix/modules/editor/lisp/fg42/editor.el @@ -26,7 +26,6 @@ ;; We build this file via the main FG42's Nix derivation. It ;; contains the final Nix configuration of FG42. (require 'fg42/config) - (require 'fg42/themes) ;; ;; Language support ;; (require 'fg42/autocomplete) ;; (require 'fg42/langs/langs) @@ -37,12 +36,13 @@ ;; (require 'fg42/langs/elisp) ;; (require 'fg42/langs/nix) - (require 'fg42/git) + ;;(require 'fg42/git) ;; (require 'fg42/wm) (require 'fg42/organize) - (require 'fg42/minibuffer) - (require 'fg42/graphics) - (require 'fg42/modeline)) + ;;(require 'fg42/minibuffer) + ;;(require 'fg42/graphics) + ;;(require 'fg42/modeline) + ) (require 'server) (require 'fg42/utils) @@ -58,9 +58,6 @@ -(defun fg42/setup-editor () - "Setup the overall functionality of FG42." - (use! origami "A text folding minor mode for Emacs." :bind @@ -202,6 +199,10 @@ contextual information." "Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs." :config (global-flycheck-mode)) + +(defun fg42/setup-editor () + "Setup the overall functionality of FG42." + ;; In the following section we're setting some default behavior of FG42. ;; Most of these configuration are opiniated and I think most of people ;; shared the same opinion or don't care at all. @@ -246,25 +247,26 @@ contextual information." (defalias 'yes-or-no-p 'y-or-n-p) - ;; Hooks --- - (add-hook - 'emacs-startup-hook - (lambda () - ;; It only applies to toolkit=no - (set-mouse-color (get-base16-color-or :base07 "#eeeeec")) - ;; Switch from `dabbrev-expand' to `hippie-expand' - (global-set-key [remap dabbrev-expand] 'hippie-expand) + ;; It only applies to toolkit=no - (column-number-mode t) - (show-paren-mode t) - (electric-pair-mode 1) + (set-mouse-color (get-base16-color-or :base07 "#eeeeec")) - ;; Rectangular select - (cua-selection-mode t) + ;; Switch from `dabbrev-expand' to `hippie-expand' - ;; Yank the region on type - (delete-selection-mode 1))) + (global-set-key [remap dabbrev-expand] 'hippie-expand) + + (column-number-mode t) + (show-paren-mode t) + (electric-pair-mode 1) + + ;; Rectangular select + + (cua-selection-mode t) + + ;; Yank the region on type + + (delete-selection-mode 1) ;; Deletel extra trailing white spaces on save (add-hook 'before-save-hook 'delete-trailing-whitespace) @@ -288,5 +290,7 @@ contextual information." (message "[FG42]: Use `fg42-help' to get help.")) +(add-hook 'fg42/after-user-config-init-hook #'fg42/setup-editor) + (provide 'fg42/editor) ;;; editor.el ends here diff --git a/nix/modules/git/default.nix b/nix/modules/git/default.nix new file mode 100644 index 0000000..849559e --- /dev/null +++ b/nix/modules/git/default.nix @@ -0,0 +1,50 @@ +# Fg42 - Emacs Editor for advance users +# +# Copyright (c) 2010-2024 Sameer Rahmani +# +# 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, version 2. +# +# 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 . + +# This is the home manager module that exposes FG42. It differs +# from FG42 modules that are structurally the same but used in +# different context + +# A list of default FG42 modules to build FG42 with. +{ lib, config, pkgs, makeFG42Drv, ... }: +with lib; +let + cfg = config.fg42.features; + deps = + (with pkgs.emacsPackages; [ + magit + forge + diff-hl + ]); + + drv = makeFG42Drv { + pname = "git"; + version = config.fg42.version; + buildInputs = deps; + src = ./.; + }; +in +{ + options.fg42.features.git = mkEnableOption "git"; + + config = mkIf cfg.enable { + fg42.elispPackages = [ drv ] ++ deps; + + fg42.paths = (with pkgs;[ + git + ]); + }; +} diff --git a/nix/modules/git/lisp/fg42/git.el b/nix/modules/git/lisp/fg42/git.el new file mode 100644 index 0000000..a6a586e --- /dev/null +++ b/nix/modules/git/lisp/fg42/git.el @@ -0,0 +1,61 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; 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: +;;; Code: +(eval-when-compile + (require 'fpkg)) + + +(use! diff-hl + "This package highlights changes to the current buffer in respect to the +VC status of the file. For example if you're using `git' in your project +and you've made some changes to the current buffer that are not commited +yet it will highlihgt them for you. + +For more info check out `https://github.com/dgutov/diff-hl'." + :commands global-diff-hl-mode + :config + (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh) + (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)) + + +(use! magit + "Git magic in FG42. For more info checkout `magit's documentation." + :bind (("C-x g" . magit-status) + ("C-c b" . magit-blame) + ("C-c l" . magit-log)) + + :config + (when (featurep 'diff-hl) + (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh) + (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))) + +(use! forge + "Forge allows you to work with Git forges, such as Github and Gitlab, +from the comfort of Magit and the rest of Emacs. + +For more info: `https://magit.vc/manual/forge/'" + :after magit) + + +(provide 'fg42/git) +;;; git.el ends here diff --git a/nix/fg42/unit.nix b/nix/modules/unit/default.nix similarity index 60% rename from nix/fg42/unit.nix rename to nix/modules/unit/default.nix index 66a5ffd..85a6a3c 100644 --- a/nix/fg42/unit.nix +++ b/nix/modules/unit/default.nix @@ -17,10 +17,19 @@ # This is the home manager module that exposes FG42. It differs # from FG42 modules that are structurally the same but used in # different context -{ lib, pkgs, config, options, ... }: + +# A list of default FG42 modules to build FG42 with. +{ lib, config, pkgs, makeFG42Drv, ... }: with lib; let - nix2elispName = pkg: (builtins.replaceStrings [ "fg42-" ] [ "fg42/" ] pkg.pname); + cfg = config.fg42; + + drv = makeFG42Drv { + pname = "unit"; + version = config.fg42.version; + + src = ./.; + }; in { options = { @@ -89,7 +98,7 @@ in type = types.str; description = '' The theme package name to use with FG42. The package should be added - to `elispPackages` already; + to `elispPackages` already ''; }; @@ -104,6 +113,49 @@ in ''; }; + fg42.vars = mkOption { + type = types.listOf + (types.submodule { + options = { + name = mkOption { + type = types.str; + }; + defaultValue = mkOption { + type = types.anything; + }; + docstring = mkOption { + type = types.str; + }; + }; + }); + default = [ ]; + description = '' + Any element in this list will translate to an Elisp variable and will + be available to the Elisp code via the `fg42/config` interface. + ''; + }; + fg42.consts = mkOption { + type = types.listOf + (types.submodule { + options = { + name = mkOption { + type = types.str; + }; + defaultValue = mkOption { + type = types.anything; + }; + docstring = mkOption { + type = types.str; + }; + }; + }); + default = [ ]; + description = '' + Any element in this list will translate to an Elisp const and will + be available to the Elisp code via the `fg42/config` interface. + ''; + }; + fg42.modeline = mkOption { type = types.enum [ "emacs" "noether" ]; default = "emacs"; @@ -112,36 +164,35 @@ in "noether" to disable Emacs's modeline and replace it by the noether mode. ''; }; - - fg42.docstrings = mkOption { - type = types.attrsOf types.str; - readOnly = true; - description = '' - A list of Emacs packages to preload in compile time. - - In general you want your entry point module in this list - to setup your autoloads, hooks, and everything. - ''; - }; - }; config = { - fg42.version = import ../version.nix { }; + fg42.version = import ../../version.nix { }; + fg42.elispPackages = [ drv ]; + fg42.theme = lib.mkDefault "base16-eighties"; + fg42.theme-package-name = lib.mkDefault "base16-theme"; + fg42.vars = [ + (lib.defVar "theme" cfg.theme "The default font for FG42") + (lib.defVar "theme-package-name" cfg.theme-package-name '' + The theme package name to use with FG42. The package should be added to `elispPackages` already. + '') + ]; + # Extract the package pname's to pass to elisp to `require` them in the init # file, while compiling. - fg42.requires = map nix2elispName config.fg42.elispPackages; - fg42.docstrings = (with builtins; - let - desc = opt: - if hasAttr "description" opt - then opt.description - else ""; + # fg42.requires = map nix2elispName config.fg42.elispPackages; + # fg42.docstrings = (with builtins; + # let + # desc = opt: + # if hasAttr "description" opt + # then opt.description + # else ""; - in - lib.concatMapAttrs - (k: v: { ${k} = desc v; }) - options.fg42); + # in + # lib.concatMapAttrs + # (k: v: { ${k} = desc v; }) + # options.fg42); }; + } diff --git a/nix/modules/editor/lisp/fg42.el b/nix/modules/unit/lisp/fg42.el similarity index 76% rename from nix/modules/editor/lisp/fg42.el rename to nix/modules/unit/lisp/fg42.el index 68a9dbc..9fc4c24 100644 --- a/nix/modules/editor/lisp/fg42.el +++ b/nix/modules/unit/lisp/fg42.el @@ -21,43 +21,13 @@ ;; ;;; Commentary: ;;; Code: -(require 'fg42/utils) + (eval-when-compile + (require 'fg42/utils) + (require 'fg42/pre) (defvar package-archives) (defvar use-package-ensure-function)) -;; ============================================================================ -;; Basic inital configuration for FG42's operations -;; ============================================================================ -(defgroup fg42 nil - "Customize your FG42 instance via this group of configurations." - :group :editor) - -(defvar fg42/disabled-features nil - "List of features to disable.") - -(defvar fg42/after-init-hook nil - "The hook tha runs when FG42 finished running the user configuration.") - -(defvar fg42/debug? nil - "It is t If FG42 is running in debug mode and nil otherwise.") - -(defvar fg42/-gc-cons-threshold 16777216 - "Value of GC threshold of FG42.") - -(defvar fg42/initialized nil - "A variable that indicates whether FG42 is passed initialization.") - - -(defconst fg42/cache-dir (or (getenv "FG42_CACHE_DIR") - (path-join (or (getenv "XDG_CACHE_HOME") "~/.cache") - "fg42"))) - - -(defconst fg42/config-dir (or (getenv "FG42_CONFIG_DIR") - (path-join (or (getenv "XDG_CONFIG_HOME") "~/.config") - "fg42"))) - (defun defer-garbage-collection () "Disable garbage collection." @@ -106,17 +76,17 @@ (defun fg42/initialize () "Initialize FG42 after the Emacs window is rendered by loading the user init file." ;; (fg42/-startup-optimization) + (run-hooks 'fg42/before-user-config-init-hook) - (require 'fg42/editor) - ;; Since the editor module imports all the submodules - ;; on compile time we should be good to assume - ;; everything that needed to be loaded or autoloaded - ;; are there already. + (require 'fg42/themes) + (when (file-exists-p user-init-file) (load user-init-file)) + (run-hooks 'fg42/after-user-config-init-hook) + (fg42/setup-theme!) - (fg42/setup-editor) + ;; (fg42/setup-editor) (add-hook 'emacs-startup-hook (lambda () diff --git a/nix/modules/editor/lisp/fg42/config.el b/nix/modules/unit/lisp/fg42/config.el similarity index 100% rename from nix/modules/editor/lisp/fg42/config.el rename to nix/modules/unit/lisp/fg42/config.el diff --git a/nix/modules/unit/lisp/fg42/pre.el b/nix/modules/unit/lisp/fg42/pre.el new file mode 100644 index 0000000..c6a0ea9 --- /dev/null +++ b/nix/modules/unit/lisp/fg42/pre.el @@ -0,0 +1,66 @@ +;;; 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: +;;; Code: +;; ============================================================================ +;; Basic inital configuration for FG42's operations +;; ============================================================================ +(require 'fg42/utils) + +(defgroup fg42 nil + "Customize your FG42 instance via this group of configurations." + :group :editor) + +(defvar fg42/disabled-features nil + "List of features to disable.") + +(defvar fg42/after-init-hook nil + "The hook tha runs when FG42 finished running the user configuration.") + +(defvar fg42/debug? nil + "It is t If FG42 is running in debug mode and nil otherwise.") + +(defvar fg42/-gc-cons-threshold 16777216 + "Value of GC threshold of FG42.") + +(defvar fg42/initialized nil + "A variable that indicates whether FG42 is passed initialization.") + + +(defconst fg42/cache-dir (or (getenv "FG42_CACHE_DIR") + (path-join (or (getenv "XDG_CACHE_HOME") "~/.cache") + "fg42"))) + + +(defconst fg42/config-dir (or (getenv "FG42_CONFIG_DIR") + (path-join (or (getenv "XDG_CONFIG_HOME") "~/.config") + "fg42"))) + +(defvar fg42/before-user-config-init-hook nil + "A hook that runs before loading user's configuration.") + +(defvar fg42/after-user-config-init-hook nil + "A hook that runs after loading user's configuration.") + + +(provide 'fg42/pre) +;;; pre.el ends here diff --git a/nix/modules/editor/lisp/fg42/themes.el b/nix/modules/unit/lisp/fg42/themes.el similarity index 100% rename from nix/modules/editor/lisp/fg42/themes.el rename to nix/modules/unit/lisp/fg42/themes.el diff --git a/nix/modules/editor/lisp/fg42/utils.el b/nix/modules/unit/lisp/fg42/utils.el similarity index 100% rename from nix/modules/editor/lisp/fg42/utils.el rename to nix/modules/unit/lisp/fg42/utils.el diff --git a/nix/modules/editor/lisp/fpkg.el b/nix/modules/unit/lisp/fpkg.el similarity index 100% rename from nix/modules/editor/lisp/fpkg.el rename to nix/modules/unit/lisp/fpkg.el