clojure-mode with clojure-lsp as eglot backend
Add eglot-format to before-save-hook Reformat all the nix files using nixpkgs-fmt Redesign the WM mode modeline Disable exwm mode. Posframe issue Disable noether mode on WM until we fix the issue Add the time unit to the modeline Make eglot work with clojure-lsp
This commit is contained in:
parent
980566ea70
commit
209358c70d
23
flake.nix
23
flake.nix
|
@ -36,13 +36,14 @@
|
||||||
runtimeInputs = [ pkgs.xorg.xorgserver ];
|
runtimeInputs = [ pkgs.xorg.xorgserver ];
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
${pkgs.xorg.xorgserver.out}/bin/Xephyr -br -ac -noreset -screen 800x600 :1
|
${pkgs.xorg.xorgserver.out}/bin/Xephyr -br -ac -noreset -screen 800x600 :1
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
noether = inputs.noether.outputs.packages.${system}.default;
|
noether = inputs.noether.outputs.packages.${system}.default;
|
||||||
factory = params: pkgs.callPackage ./nix/factory.nix ({ inherit noether; } // params);
|
factory = params: pkgs.callPackage ./nix/factory.nix ({ inherit noether; } // params);
|
||||||
default = (factory {});
|
default = (factory { });
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
packages = {
|
packages = {
|
||||||
default = default.fg42;
|
default = default.fg42;
|
||||||
} // (pkgs.lib.optionalAttrs (system == "x86_64-linux") {
|
} // (pkgs.lib.optionalAttrs (system == "x86_64-linux") {
|
||||||
|
@ -58,7 +59,21 @@
|
||||||
nativeBuildInputs = [ default.fg42 pkgs.fish test-x default.run-test-wm ];
|
nativeBuildInputs = [ default.fg42 pkgs.fish test-x default.run-test-wm ];
|
||||||
buildInputs = [ default.fg42 ];
|
buildInputs = [ default.fg42 ];
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
apps.wm = {
|
||||||
|
type = "app";
|
||||||
|
program = "${default.run-test-wm}/bin/run-test-wm";
|
||||||
|
};
|
||||||
|
|
||||||
|
apps.x = {
|
||||||
|
type = "app";
|
||||||
|
program = "${test-x}/bin/test-x";
|
||||||
|
};
|
||||||
|
apps.default = {
|
||||||
|
type = "app";
|
||||||
|
program = "${default.fg42}/bin/fg42";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
gdscript-mode
|
gdscript-mode
|
||||||
meson-mode
|
meson-mode
|
||||||
lsp-scheme
|
lsp-scheme
|
||||||
clojure-mode
|
|
||||||
cider
|
cider
|
||||||
aggressive-indent
|
aggressive-indent
|
||||||
graphviz-dot-mode
|
graphviz-dot-mode
|
||||||
|
@ -90,6 +89,10 @@
|
||||||
org-ql
|
org-ql
|
||||||
ctrlf
|
ctrlf
|
||||||
badwolf-theme
|
badwolf-theme
|
||||||
|
clojure-mode
|
||||||
|
clojure-ts-mode
|
||||||
|
cider
|
||||||
|
flycheck-clj-kondo
|
||||||
ace-window
|
ace-window
|
||||||
avy
|
avy
|
||||||
paredit
|
paredit
|
||||||
|
@ -122,7 +125,8 @@
|
||||||
forge
|
forge
|
||||||
svg-tag-mode
|
svg-tag-mode
|
||||||
base16-theme
|
base16-theme
|
||||||
consult)
|
consult
|
||||||
|
nerd-icons-completion)
|
||||||
|
|
||||||
(provide 'fg42/deps)
|
(provide 'fg42/deps)
|
||||||
;;; deps.el ends here
|
;;; deps.el ends here
|
||||||
|
|
|
@ -26,11 +26,13 @@
|
||||||
;; Language support
|
;; Language support
|
||||||
(require 'fg42/autocomplete)
|
(require 'fg42/autocomplete)
|
||||||
(require 'fg42/langs/langs)
|
(require 'fg42/langs/langs)
|
||||||
|
(require 'fg42/eglot)
|
||||||
(require 'fg42/langs/cpp)
|
(require 'fg42/langs/cpp)
|
||||||
(require 'fg42/langs/verilog)
|
(require 'fg42/langs/verilog)
|
||||||
(require 'fg42/langs/python)
|
(require 'fg42/langs/python)
|
||||||
(require 'fg42/langs/elisp)
|
(require 'fg42/langs/elisp)
|
||||||
(require 'fg42/langs/nix)
|
(require 'fg42/langs/nix)
|
||||||
|
(require 'fg42/langs/clojure)
|
||||||
|
|
||||||
(require 'fg42/git)
|
(require 'fg42/git)
|
||||||
(require 'fg42/wm)
|
(require 'fg42/wm)
|
||||||
|
@ -197,12 +199,6 @@ contextual information."
|
||||||
"Yasnippet's snippets."
|
"Yasnippet's snippets."
|
||||||
:after yasnippet)
|
:after yasnippet)
|
||||||
|
|
||||||
;; Language Servers and friends
|
|
||||||
(use! eglot
|
|
||||||
"Eglot is a minimalistic yet powerful LSP replacement
|
|
||||||
shipped with Emacs."
|
|
||||||
:commands eglot
|
|
||||||
:autoload eglot-ensure)
|
|
||||||
|
|
||||||
(use! flycheck
|
(use! flycheck
|
||||||
"Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs."
|
"Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs."
|
||||||
|
@ -270,7 +266,7 @@ shipped with Emacs."
|
||||||
;; git changes in the fringe
|
;; git changes in the fringe
|
||||||
(global-diff-hl-mode)
|
(global-diff-hl-mode)
|
||||||
|
|
||||||
;; Modeline replacement
|
;; Modeline replacement
|
||||||
(noether-global-mode)
|
(noether-global-mode)
|
||||||
|
|
||||||
;; Rectangular select
|
;; Rectangular select
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors
|
||||||
|
;;
|
||||||
|
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
;; 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 <http://www.gnu.org/licenses/>.
|
||||||
|
;;
|
||||||
|
;;; Commentary:
|
||||||
|
;;; Code:
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'fpkg))
|
||||||
|
|
||||||
|
|
||||||
|
;; Language Servers and friends
|
||||||
|
(use! eglot
|
||||||
|
"Eglot is a minimalistic yet powerful LSP replacement
|
||||||
|
shipped with Emacs."
|
||||||
|
:hook
|
||||||
|
(prog-mode . eglot-ensure)
|
||||||
|
(prog-mode . (lambda ()
|
||||||
|
(add-hook 'before-save-hook 'eglot-format nil t))))
|
||||||
|
|
||||||
|
|
||||||
|
(provide 'fg42/eglot)
|
||||||
|
;;; eglot.el ends here
|
|
@ -0,0 +1,57 @@
|
||||||
|
;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors
|
||||||
|
;;
|
||||||
|
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
;; 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 <http://www.gnu.org/licenses/>.
|
||||||
|
;;
|
||||||
|
;;; Commentary:
|
||||||
|
;;; Code:
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'fpkg))
|
||||||
|
|
||||||
|
|
||||||
|
(use! flycheck-clj-kondo
|
||||||
|
"flycheck linter for clojure using `clj-konda'"
|
||||||
|
:defer t)
|
||||||
|
|
||||||
|
;; (defun fg42/clojure-ts-mode-setup ()
|
||||||
|
;; "A hook handler to setup cpp related configurations."
|
||||||
|
;; ;; We set eglot's autoload command to `eglot-ensure'
|
||||||
|
;; (eglot-ensure))
|
||||||
|
|
||||||
|
(use! clojure-ts-mode
|
||||||
|
"Clojure mode"
|
||||||
|
;; :init
|
||||||
|
;; (add-to-list 'major-mode-remap-alist '(clojure-mode . clojure-ts-mode))
|
||||||
|
:mode (("\\.clj\\'" . clojure-ts-mode)
|
||||||
|
("\\.cljs\\'" . clojure-ts-mode)
|
||||||
|
("\\.cljc\\'" . clojure-ts-mode))
|
||||||
|
:config
|
||||||
|
(with-eval-after-load 'eglot
|
||||||
|
;; Force nil to use nixpkgs-fmt for formatting
|
||||||
|
(let ((clojure-lsp '(clojure-ts-mode . clojure-mode)))
|
||||||
|
(require 'flycheck-clj-kondo)
|
||||||
|
(add-to-list 'eglot-server-programs clojure-lsp)))
|
||||||
|
|
||||||
|
:hook
|
||||||
|
(clojure-ts-mode . company-mode)
|
||||||
|
(clojure-ts-mode . cider)
|
||||||
|
(clojure-ts-mode . eglot-ensure))
|
||||||
|
|
||||||
|
(provide 'fg42/langs/clojure)
|
||||||
|
;;; clojure.el ends here
|
|
@ -24,13 +24,26 @@
|
||||||
(eval-when-compile
|
(eval-when-compile
|
||||||
(require 'fpkg))
|
(require 'fpkg))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(use! nix-mode
|
(use! nix-mode
|
||||||
"Nix language support for Emacs."
|
"Nix language support for Emacs."
|
||||||
:mode "\\.nix\\'"
|
:mode "\\.nix\\'"
|
||||||
|
|
||||||
:hook
|
:hook
|
||||||
(nix-mode . eglot-ensure)
|
(nix-mode . eglot-ensure)
|
||||||
(nix-mode . company-mode)
|
(nix-mode . company-mode)
|
||||||
(nix-mode . flyspell-prog-mode))
|
(nix-mode . flyspell-prog-mode)
|
||||||
|
|
||||||
|
:init
|
||||||
|
:config
|
||||||
|
(with-eval-after-load 'eglot
|
||||||
|
;; Force nil to use nixpkgs-fmt for formatting
|
||||||
|
(let ((nil-lsp '(nix-mode . ("nil"
|
||||||
|
:initializationOptions
|
||||||
|
(:formatting (:command ["nixpkgs-fmt"]))))))
|
||||||
|
(add-to-list 'eglot-server-programs nil-lsp))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'fg42/langs/nix)
|
(provide 'fg42/langs/nix)
|
||||||
;;; nix.el ends here
|
;;; nix.el ends here
|
||||||
|
|
|
@ -196,5 +196,14 @@ match all of the components in any order."
|
||||||
:bind (("M-g e" . consult-compile-error)))
|
:bind (("M-g e" . consult-compile-error)))
|
||||||
|
|
||||||
|
|
||||||
|
(use! nerd-icons-completion
|
||||||
|
"Nerd icons in marginalia"
|
||||||
|
:after marginalia
|
||||||
|
:config
|
||||||
|
(nerd-icons-completion-mode)
|
||||||
|
(add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(provide 'fg42/minibuffer)
|
(provide 'fg42/minibuffer)
|
||||||
;;; minibuffer.el ends here
|
;;; minibuffer.el ends here
|
||||||
|
|
|
@ -58,6 +58,7 @@ to Emacs modeline."
|
||||||
:commands noether-global-mode
|
:commands noether-global-mode
|
||||||
:config
|
:config
|
||||||
(require 'noether-views)
|
(require 'noether-views)
|
||||||
|
(require 'fg42/modeline/views)
|
||||||
|
|
||||||
(let ((active-border (get-base16-color-or :base0A "#bd93f9"))
|
(let ((active-border (get-base16-color-or :base0A "#bd93f9"))
|
||||||
(inactive-border (get-base16-color-or :base03 "#44475a")))
|
(inactive-border (get-base16-color-or :base03 "#44475a")))
|
||||||
|
@ -73,14 +74,11 @@ to Emacs modeline."
|
||||||
(if fg42/modeline-inactive-face fg42/modeline-inactive-face 'fg42/-disabled-modeline-dective-border)
|
(if fg42/modeline-inactive-face fg42/modeline-inactive-face 'fg42/-disabled-modeline-dective-border)
|
||||||
(default-value 'face-remapping-alist) face-remaps))
|
(default-value 'face-remapping-alist) face-remaps))
|
||||||
|
|
||||||
|
;; Setup modelines
|
||||||
(when-not-wm
|
(when-not-wm
|
||||||
(require 'fg42/modeline/views)
|
(setq-default noether-views (list fg42/modeline)))
|
||||||
|
|
||||||
(when-not-wm
|
|
||||||
(setq-default noether-views (list fg42/modeline))))
|
|
||||||
|
|
||||||
(when-wm
|
(when-wm
|
||||||
(setq-default noether-views (list fg42/minimal-exwm))))
|
(setq-default noether-views nil)))
|
||||||
|
|
||||||
(provide 'fg42/modeline)
|
(provide 'fg42/modeline)
|
||||||
;;; modeline.el ends here
|
;;; modeline.el ends here
|
||||||
|
|
|
@ -64,9 +64,12 @@
|
||||||
"Set the EXWM input mode for the current buffer."
|
"Set the EXWM input mode for the current buffer."
|
||||||
(setq fg42/-exwm-input-mode (format "%s" exwm--input-mode)))
|
(setq fg42/-exwm-input-mode (format "%s" exwm--input-mode)))
|
||||||
|
|
||||||
|
|
||||||
(defun fg42/-format-exwm-input-mode (_ v _ _)
|
(defun fg42/-format-exwm-input-mode (_ v _ _)
|
||||||
"Just return the input mode name V."
|
"Just return the input mode name V."
|
||||||
v)
|
(if (=string v "line")
|
||||||
|
(propertize "L" 'font-lock-face `(:foreground ,(get-base16-color-or :base07 "eeeeec")))
|
||||||
|
(propertize "C" 'font-lock-face `(:foreground ,(get-base16-color-or :base0A "eeeeec")))))
|
||||||
|
|
||||||
|
|
||||||
(noether-defunit fg42/exwm-input-mode-unit
|
(noether-defunit fg42/exwm-input-mode-unit
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
"Keep the modeline at bottom right by using the data from INFO."
|
"Keep the modeline at bottom right by using the data from INFO."
|
||||||
(cons -1 -1))
|
(cons -1 -1))
|
||||||
|
|
||||||
|
(defun fg42/--bottom-right-padded (info)
|
||||||
|
"Keep the modeline at bottom right by using the data from INFO."
|
||||||
|
(cons -70 -1))
|
||||||
|
|
||||||
|
|
||||||
(defun fg42/adjust-modeline (view)
|
(defun fg42/adjust-modeline (view)
|
||||||
"Adjust the VIEW after parent frame resize."
|
"Adjust the VIEW after parent frame resize."
|
||||||
|
@ -58,7 +62,6 @@
|
||||||
(buffer-name-unit
|
(buffer-name-unit
|
||||||
:label (format "%s " (nerd-icons-codicon "nf-cod-layers"))
|
:label (format "%s " (nerd-icons-codicon "nf-cod-layers"))
|
||||||
:len 20)
|
:len 20)
|
||||||
;; (mode-name-unit :label " " :len 4)
|
|
||||||
(projectile-project-unit
|
(projectile-project-unit
|
||||||
:label (format "%s " (nerd-icons-octicon "nf-oct-project"))
|
:label (format "%s " (nerd-icons-octicon "nf-oct-project"))
|
||||||
:len 20)
|
:len 20)
|
||||||
|
@ -66,31 +69,33 @@
|
||||||
:label (format "%s " (nerd-icons-devicon "nf-dev-git_branch"))
|
:label (format "%s " (nerd-icons-devicon "nf-dev-git_branch"))
|
||||||
:len 20)
|
:len 20)
|
||||||
(fg42/mode-icon)
|
(fg42/mode-icon)
|
||||||
(line-unit :label (format "%s " (nerd-icons-codicon "nf-cod-location")))))
|
(line-unit :label (format "%s " (nerd-icons-codicon "nf-cod-location")))
|
||||||
|
(time-unit :label (format " %s " (nerd-icons-mdicon "nf-md-clock_time_three")))))
|
||||||
|
|
||||||
|
|
||||||
(when-wm
|
(noether-defview fg42/minimal-exwm
|
||||||
(noether-defview fg42/minimal-exwm
|
"A super simple bar containing the line number and column number that
|
||||||
"A super simple bar containing the line number and column number that
|
|
||||||
Appears on the center of the current window."
|
Appears on the center of the current window."
|
||||||
:managed? t
|
:managed? t
|
||||||
:buffer "*exwm-status*"
|
:buffer "*exwm-status*"
|
||||||
:binding (kbd "C-c 3")
|
:binding (kbd "C-c 1")
|
||||||
:separator "|"
|
:separator " | "
|
||||||
:frame
|
|
||||||
(list
|
|
||||||
;; Such a big numbers for X and Y will cause the frame to appear on the
|
|
||||||
;; bottom right corner and covering the minibuffer
|
|
||||||
:position '(-30 . -1)
|
|
||||||
:border-width 0
|
|
||||||
:timeout 5
|
|
||||||
:border-color "#bd93f9")
|
|
||||||
|
|
||||||
:units
|
:timeout 10
|
||||||
(list
|
:frame
|
||||||
(fg42/exwm-input-mode-unit :label "")
|
(list
|
||||||
(buffer-name-unit :label "")
|
:poshandler #'fg42/--bottom-right-padded
|
||||||
(time-unit :label ""))))
|
:border-width 0
|
||||||
|
:border-color "#bd93f9")
|
||||||
|
|
||||||
|
:units
|
||||||
|
(list
|
||||||
|
(fg42/exwm-input-mode-unit :label (format "%s " (nerd-icons-faicon "nf-fa-linux")))
|
||||||
|
(buffer-name-unit
|
||||||
|
:label (format "%s " (nerd-icons-codicon "nf-cod-layers"))
|
||||||
|
:len 30)
|
||||||
|
|
||||||
|
(time-unit :label (format "%s " (nerd-icons-mdicon "nf-md-clock_time_three")))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'fg42/modeline/views)
|
(provide 'fg42/modeline/views)
|
||||||
|
|
11
nix/deps.nix
11
nix/deps.nix
|
@ -13,14 +13,15 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
{ pkgs, lib, elispDepsFile }:
|
{ pkgs, lib, elispDepsFile }:
|
||||||
with builtins;
|
with builtins;
|
||||||
let
|
let
|
||||||
reader = import ./elisp_reader.nix { inherit lib; };
|
reader = import ./elisp_reader.nix { inherit lib; };
|
||||||
elispAst = reader.fromElisp (builtins.readFile elispDepsFile);
|
elispAst = reader.fromElisp (builtins.readFile elispDepsFile);
|
||||||
dependsOnForm = filter (x: head x == "depends-on") elispAst;
|
dependsOnForm = filter (x: head x == "depends-on") elispAst;
|
||||||
elispPkgs = if length dependsOnForm == 0
|
elispPkgs =
|
||||||
then throw "Can't find the form 'depends-on' on 'deps.el'"
|
if length dependsOnForm == 0
|
||||||
else tail (head dependsOnForm);
|
then throw "Can't find the form 'depends-on' on 'deps.el'"
|
||||||
in elispPkgs
|
else tail (head dependsOnForm);
|
||||||
|
in
|
||||||
|
elispPkgs
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
# Fg42 - Emacs Editor for advance users
|
|
||||||
#
|
|
||||||
# Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
|
||||||
#
|
|
||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
{ pkgs, fg42, version }:
|
|
||||||
{
|
|
||||||
desktop = pkgs.writeText "FG42.desktop" ''
|
|
||||||
[Desktop Entry]
|
|
||||||
Encoding=UTF-8
|
|
||||||
Name=FG42
|
|
||||||
GenericName=FG42
|
|
||||||
Comment=Emacs Editor for advance users
|
|
||||||
MimeType=text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-java;application/x-shellscript;text/x-c;text/x-c++;text/x-ruby;text/x-python;text/x-clojure;text/css;text/html;text/x-javascript;
|
|
||||||
Type=Application
|
|
||||||
Terminal=false
|
|
||||||
Categories=Development;TextEditor;
|
|
||||||
StartupWMClass=FG42
|
|
||||||
Exec=${fg42} %F
|
|
||||||
Icon=fg42
|
|
||||||
Version=${version}
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -25,18 +25,18 @@ let
|
||||||
# but only as far in as specified by maxLength.
|
# but only as far in as specified by maxLength.
|
||||||
mkMatcher = regex: maxLength:
|
mkMatcher = regex: maxLength:
|
||||||
string:
|
string:
|
||||||
let
|
let
|
||||||
substr = substring 0 maxLength string;
|
substr = substring 0 maxLength string;
|
||||||
matched = match regex substr;
|
matched = match regex substr;
|
||||||
in
|
in
|
||||||
if matched != null then head matched else null;
|
if matched != null then head matched else null;
|
||||||
|
|
||||||
removeStrings = stringsToRemove: string:
|
removeStrings = stringsToRemove: string:
|
||||||
let
|
let
|
||||||
len = length stringsToRemove;
|
len = length stringsToRemove;
|
||||||
listOfNullStrings = genList (const "") len;
|
listOfNullStrings = genList (const "") len;
|
||||||
in
|
in
|
||||||
replaceStrings stringsToRemove listOfNullStrings string;
|
replaceStrings stringsToRemove listOfNullStrings string;
|
||||||
|
|
||||||
# Split a string of elisp into individual tokens and add useful
|
# Split a string of elisp into individual tokens and add useful
|
||||||
# metadata.
|
# metadata.
|
||||||
|
@ -73,7 +73,8 @@ let
|
||||||
matchSymbol =
|
matchSymbol =
|
||||||
let
|
let
|
||||||
symbolChar = ''([^${notInSymbol}]|\\.)'';
|
symbolChar = ''([^${notInSymbol}]|\\.)'';
|
||||||
in mkMatcher ''(${symbolChar}+)([${notInSymbol}]|$).*'' symbolMaxLength;
|
in
|
||||||
|
mkMatcher ''(${symbolChar}+)([${notInSymbol}]|$).*'' symbolMaxLength;
|
||||||
|
|
||||||
maxTokenLength = foldl' max 0 [
|
maxTokenLength = foldl' max 0 [
|
||||||
commentMaxLength
|
commentMaxLength
|
||||||
|
@ -125,173 +126,174 @@ let
|
||||||
dot = matchDot rest;
|
dot = matchDot rest;
|
||||||
symbol = matchSymbol rest;
|
symbol = matchSymbol rest;
|
||||||
in
|
in
|
||||||
if state.skip > 0 then
|
if state.skip > 0 then
|
||||||
state // {
|
state // {
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = state.skip - 1;
|
||||||
|
line = if char == "\n" then state.line + 1 else state.line;
|
||||||
|
}
|
||||||
|
else if char == "\n" then
|
||||||
|
let
|
||||||
|
mod = state.line / 1000;
|
||||||
|
newState = {
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
skip = state.skip - 1;
|
line = state.line + 1;
|
||||||
line = if char == "\n" then state.line + 1 else state.line;
|
inherit mod;
|
||||||
}
|
};
|
||||||
else if char == "\n" then
|
in
|
||||||
let
|
state // (
|
||||||
mod = state.line / 1000;
|
# Force evaluation of old state every 1000 lines. Nix
|
||||||
newState = {
|
# doesn't have a modulo builtin, so we have to save
|
||||||
pos = state.pos + 1;
|
# the result of an integer division and compare
|
||||||
line = state.line + 1;
|
# between runs.
|
||||||
inherit mod;
|
if mod > state.mod then
|
||||||
};
|
seq state.acc newState
|
||||||
in
|
|
||||||
state // (
|
|
||||||
# Force evaluation of old state every 1000 lines. Nix
|
|
||||||
# doesn't have a modulo builtin, so we have to save
|
|
||||||
# the result of an integer division and compare
|
|
||||||
# between runs.
|
|
||||||
if mod > state.mod then
|
|
||||||
seq state.acc newState
|
|
||||||
else
|
|
||||||
newState
|
|
||||||
)
|
|
||||||
else if elem char [ " " "\t" "\r" ] then
|
|
||||||
state // {
|
|
||||||
pos = state.pos + 1;
|
|
||||||
inherit (state) line;
|
|
||||||
}
|
|
||||||
else if char == ";" then
|
|
||||||
if comment != null then
|
|
||||||
state // {
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength comment) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if char == "(" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "openParen"; value = "("; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == ")" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "closeParen"; value = ")"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == "[" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "openBracket"; value = "["; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == "]" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "closeBracket"; value = "]"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == "'" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "quote"; value = "'"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == ''"'' then
|
|
||||||
if string != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "string"; value = string; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength string) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if char == "#" then
|
|
||||||
let nextChar = substring 1 1 rest;
|
|
||||||
in
|
|
||||||
if nextChar == "'" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "function"; value = "#'"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = 1;
|
|
||||||
}
|
|
||||||
else if nextChar == "&" then
|
|
||||||
if boolVector != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "boolVector"; value = boolVector; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength boolVector) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if nextChar == "s" then
|
|
||||||
if substring 2 1 rest == "(" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "record"; value = "#s"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = 1;
|
|
||||||
}
|
|
||||||
else throw "List must follow #s in record on line ${toString state.line}: ${rest}"
|
|
||||||
else if nextChar == "[" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "byteCode"; value = "#"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if nonBase10Integer != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "nonBase10Integer"; value = nonBase10Integer; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength nonBase10Integer) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if elem char [ "+" "-" "." "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ] then
|
|
||||||
if integer != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "integer"; value = integer; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength integer) - 1;
|
|
||||||
}
|
|
||||||
else if float != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "float"; value = float; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength float) - 1;
|
|
||||||
}
|
|
||||||
else if dot != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "dot"; value = dot; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength dot) - 1;
|
|
||||||
}
|
|
||||||
else if symbol != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength symbol) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if char == "?" then
|
|
||||||
if character != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "character"; value = character; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength character) - 1;
|
|
||||||
}
|
|
||||||
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
|
||||||
else if char == "`" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "backquote"; value = "`"; inherit (state) line; }];
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else if char == "," then
|
|
||||||
if substring 1 1 rest == "@" then
|
|
||||||
state // {
|
|
||||||
acc = state.acc ++ [{ type = "slice"; value = ",@"; inherit (state) line; }];
|
|
||||||
skip = 1;
|
|
||||||
pos = state.pos + 1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
newState
|
||||||
|
)
|
||||||
|
else if elem char [ " " "\t" "\r" ] then
|
||||||
|
state // {
|
||||||
|
pos = state.pos + 1;
|
||||||
|
inherit (state) line;
|
||||||
|
}
|
||||||
|
else if char == ";" then
|
||||||
|
if comment != null then
|
||||||
|
state // {
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength comment) - 1;
|
||||||
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if char == "(" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "openParen"; value = "("; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == ")" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "closeParen"; value = ")"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == "[" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "openBracket"; value = "["; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == "]" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "closeBracket"; value = "]"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == "'" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "quote"; value = "'"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == ''"'' then
|
||||||
|
if string != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "string"; value = string; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength string) - 1;
|
||||||
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if char == "#" then
|
||||||
|
let nextChar = substring 1 1 rest;
|
||||||
|
in
|
||||||
|
if nextChar == "'" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "function"; value = "#'"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
else if nextChar == "&" then
|
||||||
|
if boolVector != null then
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [{ type = "expand"; value = ","; inherit (state) line; }];
|
acc = state.acc ++ [{ type = "boolVector"; value = boolVector; inherit (state) line; }];
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength boolVector) - 1;
|
||||||
}
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if nextChar == "s" then
|
||||||
|
if substring 2 1 rest == "(" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "record"; value = "#s"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
else throw "List must follow #s in record on line ${toString state.line}: ${rest}"
|
||||||
|
else if nextChar == "[" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "byteCode"; value = "#"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if nonBase10Integer != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "nonBase10Integer"; value = nonBase10Integer; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength nonBase10Integer) - 1;
|
||||||
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if elem char [ "+" "-" "." "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ] then
|
||||||
|
if integer != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "integer"; value = integer; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength integer) - 1;
|
||||||
|
}
|
||||||
|
else if float != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "float"; value = float; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength float) - 1;
|
||||||
|
}
|
||||||
|
else if dot != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "dot"; value = dot; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength dot) - 1;
|
||||||
|
}
|
||||||
else if symbol != null then
|
else if symbol != null then
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }];
|
acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }];
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
skip = (stringLength symbol) - 1;
|
skip = (stringLength symbol) - 1;
|
||||||
}
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if char == "?" then
|
||||||
|
if character != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "character"; value = character; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength character) - 1;
|
||||||
|
}
|
||||||
|
else throw "Unrecognized token on line ${toString state.line}: ${rest}"
|
||||||
|
else if char == "`" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "backquote"; value = "`"; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if char == "," then
|
||||||
|
if substring 1 1 rest == "@" then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "slice"; value = ",@"; inherit (state) line; }];
|
||||||
|
skip = 1;
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw "Unrecognized token on line ${toString state.line}: ${rest}";
|
state // {
|
||||||
in (builtins.foldl' readToken { acc = []; pos = 0; skip = 0; line = startLineNumber; mod = 0; } (stringToCharacters elisp)).acc;
|
acc = state.acc ++ [{ type = "expand"; value = ","; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
}
|
||||||
|
else if symbol != null then
|
||||||
|
state // {
|
||||||
|
acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }];
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength symbol) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw "Unrecognized token on line ${toString state.line}: ${rest}";
|
||||||
|
in
|
||||||
|
(builtins.foldl' readToken { acc = [ ]; pos = 0; skip = 0; line = startLineNumber; mod = 0; } (stringToCharacters elisp)).acc;
|
||||||
|
|
||||||
tokenizeElisp = elisp:
|
tokenizeElisp = elisp:
|
||||||
tokenizeElisp' { inherit elisp; };
|
tokenizeElisp' { inherit elisp; };
|
||||||
|
@ -302,41 +304,43 @@ let
|
||||||
# Convert literal value tokens in a flat list to their
|
# Convert literal value tokens in a flat list to their
|
||||||
# corresponding nix representation.
|
# corresponding nix representation.
|
||||||
parseValues = tokens:
|
parseValues = tokens:
|
||||||
map (token:
|
map
|
||||||
if token.type == "string" then
|
(token:
|
||||||
token // {
|
if token.type == "string" then
|
||||||
value = substring 1 (stringLength token.value - 2) token.value;
|
token // {
|
||||||
}
|
value = substring 1 (stringLength token.value - 2) token.value;
|
||||||
else if token.type == "integer" then
|
}
|
||||||
token // {
|
else if token.type == "integer" then
|
||||||
value = fromJSON (removeStrings ["+" "."] token.value);
|
token // {
|
||||||
}
|
value = fromJSON (removeStrings [ "+" "." ] token.value);
|
||||||
else if token.type == "symbol" && token.value == "t" then
|
}
|
||||||
token // {
|
else if token.type == "symbol" && token.value == "t" then
|
||||||
value = true;
|
token // {
|
||||||
}
|
value = true;
|
||||||
else if token.type == "float" then
|
}
|
||||||
let
|
else if token.type == "float" then
|
||||||
initial = head (match "([+-]?([[:digit:]]*[.])?[[:digit:]]+(e([+-]?[[:digit:]]+|[+](INF|NaN)))?)" token.value);
|
let
|
||||||
isSpecial = (match "(.+(e[+](INF|NaN)))" initial) != null;
|
initial = head (match "([+-]?([[:digit:]]*[.])?[[:digit:]]+(e([+-]?[[:digit:]]+|[+](INF|NaN)))?)" token.value);
|
||||||
withoutPlus = removeStrings ["+"] initial;
|
isSpecial = (match "(.+(e[+](INF|NaN)))" initial) != null;
|
||||||
withPrefix =
|
withoutPlus = removeStrings [ "+" ] initial;
|
||||||
if substring 0 1 withoutPlus == "." then
|
withPrefix =
|
||||||
"0" + withoutPlus
|
if substring 0 1 withoutPlus == "." then
|
||||||
else if substring 0 2 withoutPlus == "-." then
|
"0" + withoutPlus
|
||||||
"-0" + removeStrings ["-"] withoutPlus
|
else if substring 0 2 withoutPlus == "-." then
|
||||||
else
|
"-0" + removeStrings [ "-" ] withoutPlus
|
||||||
withoutPlus;
|
else
|
||||||
in
|
withoutPlus;
|
||||||
|
in
|
||||||
if !isSpecial && withPrefix != null then
|
if !isSpecial && withPrefix != null then
|
||||||
token // {
|
token // {
|
||||||
value = fromJSON withPrefix;
|
value = fromJSON withPrefix;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
token
|
token
|
||||||
else
|
else
|
||||||
token
|
token
|
||||||
) tokens;
|
)
|
||||||
|
tokens;
|
||||||
|
|
||||||
# Convert pairs of opening and closing tokens to their
|
# Convert pairs of opening and closing tokens to their
|
||||||
# respective collection types, i.e. lists and vectors. Also,
|
# respective collection types, i.e. lists and vectors. Also,
|
||||||
|
@ -363,52 +367,52 @@ let
|
||||||
openColl = if token.type == "openParen" then "list" else if token.type == "openBracket" then "vector" else null;
|
openColl = if token.type == "openParen" then "list" else if token.type == "openBracket" then "vector" else null;
|
||||||
closeColl = if token.type == "closeParen" then "list" else if token.type == "closeBracket" then "vector" else null;
|
closeColl = if token.type == "closeParen" then "list" else if token.type == "closeBracket" then "vector" else null;
|
||||||
in
|
in
|
||||||
if openColl != null then
|
if openColl != null then
|
||||||
state // {
|
state // {
|
||||||
acc = [ [] ] ++ seq (head state.acc) state.acc;
|
acc = [ [ ] ] ++ seq (head state.acc) state.acc;
|
||||||
inColl = [ openColl ] ++ state.inColl;
|
inColl = [ openColl ] ++ state.inColl;
|
||||||
depth = state.depth + 1;
|
depth = state.depth + 1;
|
||||||
line = [ token.line ] ++ state.line;
|
line = [ token.line ] ++ state.line;
|
||||||
}
|
}
|
||||||
else if closeColl != null then
|
else if closeColl != null then
|
||||||
if (head state.inColl) == closeColl then
|
if (head state.inColl) == closeColl then
|
||||||
let
|
|
||||||
outerColl = elemAt state.acc 1;
|
|
||||||
currColl = {
|
|
||||||
type = closeColl;
|
|
||||||
value = head state.acc;
|
|
||||||
line = head state.line;
|
|
||||||
inherit (state) depth;
|
|
||||||
};
|
|
||||||
rest = tail (tail state.acc);
|
|
||||||
in
|
|
||||||
state // seq state.acc {
|
|
||||||
acc = [ (outerColl ++ [ currColl ]) ] ++ rest;
|
|
||||||
inColl = tail state.inColl;
|
|
||||||
depth = state.depth - 1;
|
|
||||||
line = tail state.line;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw "Unmatched ${token.type} on line ${toString token.line}"
|
|
||||||
else if token.type == "symbol" && token.value == "nil" then
|
|
||||||
let
|
let
|
||||||
currColl = head state.acc;
|
outerColl = elemAt state.acc 1;
|
||||||
rest = tail state.acc;
|
currColl = {
|
||||||
emptyList = {
|
type = closeColl;
|
||||||
type = "list";
|
value = head state.acc;
|
||||||
depth = state.depth + 1;
|
line = head state.line;
|
||||||
value = [];
|
inherit (state) depth;
|
||||||
};
|
};
|
||||||
|
rest = tail (tail state.acc);
|
||||||
in
|
in
|
||||||
state // seq currColl { acc = [ (currColl ++ [ emptyList ]) ] ++ rest; }
|
state // seq state.acc {
|
||||||
|
acc = [ (outerColl ++ [ currColl ]) ] ++ rest;
|
||||||
|
inColl = tail state.inColl;
|
||||||
|
depth = state.depth - 1;
|
||||||
|
line = tail state.line;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
let
|
throw "Unmatched ${token.type} on line ${toString token.line}"
|
||||||
currColl = head state.acc;
|
else if token.type == "symbol" && token.value == "nil" then
|
||||||
rest = tail state.acc;
|
let
|
||||||
in
|
currColl = head state.acc;
|
||||||
state // seq currColl { acc = [ (currColl ++ [ token ]) ] ++ rest; };
|
rest = tail state.acc;
|
||||||
|
emptyList = {
|
||||||
|
type = "list";
|
||||||
|
depth = state.depth + 1;
|
||||||
|
value = [ ];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
state // seq currColl { acc = [ (currColl ++ [ emptyList ]) ] ++ rest; }
|
||||||
|
else
|
||||||
|
let
|
||||||
|
currColl = head state.acc;
|
||||||
|
rest = tail state.acc;
|
||||||
|
in
|
||||||
|
state // seq currColl { acc = [ (currColl ++ [ token ]) ] ++ rest; };
|
||||||
in
|
in
|
||||||
head (builtins.foldl' parseToken { acc = [ [] ]; inColl = [ null ]; depth = -1; line = []; } tokens).acc;
|
head (builtins.foldl' parseToken { acc = [ [ ] ]; inColl = [ null ]; depth = -1; line = [ ]; } tokens).acc;
|
||||||
|
|
||||||
# Handle dotted pair notation, a syntax where the car and cdr
|
# Handle dotted pair notation, a syntax where the car and cdr
|
||||||
# are represented explicitly. See
|
# are represented explicitly. See
|
||||||
|
@ -434,33 +438,35 @@ let
|
||||||
throw ''"Dotted pair notation"-dot outside list on line ${toString token.line}''
|
throw ''"Dotted pair notation"-dot outside list on line ${toString token.line}''
|
||||||
else if isList token.value then
|
else if isList token.value then
|
||||||
let
|
let
|
||||||
collectionContents = foldl' parseToken {
|
collectionContents = foldl' parseToken
|
||||||
acc = [];
|
{
|
||||||
dotted = false;
|
acc = [ ];
|
||||||
inList = token.type == "list";
|
dotted = false;
|
||||||
inherit (state) depthReduction;
|
inList = token.type == "list";
|
||||||
} token.value;
|
inherit (state) depthReduction;
|
||||||
|
}
|
||||||
|
token.value;
|
||||||
in
|
in
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ (
|
acc = state.acc ++ (
|
||||||
if state.dotted then
|
if state.dotted then
|
||||||
collectionContents.acc
|
collectionContents.acc
|
||||||
else
|
else
|
||||||
[
|
[
|
||||||
(token // {
|
(token // {
|
||||||
value = collectionContents.acc;
|
value = collectionContents.acc;
|
||||||
depth = token.depth - state.depthReduction;
|
depth = token.depth - state.depthReduction;
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
dotted = false;
|
dotted = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [token];
|
acc = state.acc ++ [ token ];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
(foldl' parseToken { acc = []; dotted = false; inList = false; depthReduction = 0; } tokens).acc;
|
(foldl' parseToken { acc = [ ]; dotted = false; inList = false; depthReduction = 0; } tokens).acc;
|
||||||
|
|
||||||
parseQuotes = tokens:
|
parseQuotes = tokens:
|
||||||
let
|
let
|
||||||
|
@ -469,35 +475,35 @@ let
|
||||||
token =
|
token =
|
||||||
if isList token'.value then
|
if isList token'.value then
|
||||||
token' // {
|
token' // {
|
||||||
value = (foldl' parseToken { acc = []; quotes = []; } token'.value).acc;
|
value = (foldl' parseToken { acc = [ ]; quotes = [ ]; } token'.value).acc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
token';
|
token';
|
||||||
in
|
in
|
||||||
if elem token.type [ "quote" "expand" "slice" "backquote" "function" "record" "byteCode" ] then
|
if elem token.type [ "quote" "expand" "slice" "backquote" "function" "record" "byteCode" ] then
|
||||||
state // {
|
state // {
|
||||||
quotes = [ token ] ++ state.quotes;
|
quotes = [ token ] ++ state.quotes;
|
||||||
}
|
}
|
||||||
else if state.quotes != [] then
|
else if state.quotes != [ ] then
|
||||||
let
|
let
|
||||||
quote = value: token:
|
quote = value: token:
|
||||||
token // {
|
token // {
|
||||||
inherit value;
|
inherit value;
|
||||||
};
|
};
|
||||||
quotedValue = foldl' quote token state.quotes;
|
quotedValue = foldl' quote token state.quotes;
|
||||||
in
|
in
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [ quotedValue ];
|
acc = state.acc ++ [ quotedValue ];
|
||||||
quotes = [];
|
quotes = [ ];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [ token ];
|
acc = state.acc ++ [ token ];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
(foldl' parseToken { acc = []; quotes = []; } tokens).acc;
|
(foldl' parseToken { acc = [ ]; quotes = [ ]; } tokens).acc;
|
||||||
in
|
in
|
||||||
parseQuotes (parseDots (parseCollections (parseValues tokens)));
|
parseQuotes (parseDots (parseCollections (parseValues tokens)));
|
||||||
|
|
||||||
parseElisp = elisp:
|
parseElisp = elisp:
|
||||||
parseElisp' (tokenizeElisp elisp);
|
parseElisp' (tokenizeElisp elisp);
|
||||||
|
@ -508,23 +514,23 @@ let
|
||||||
if isList object.value then
|
if isList object.value then
|
||||||
map readObject object.value
|
map readObject object.value
|
||||||
else if object.type == "quote" then
|
else if object.type == "quote" then
|
||||||
["quote" (readObject object.value)]
|
[ "quote" (readObject object.value) ]
|
||||||
else if object.type == "backquote" then
|
else if object.type == "backquote" then
|
||||||
["`" (readObject object.value)]
|
[ "`" (readObject object.value) ]
|
||||||
else if object.type == "expand" then
|
else if object.type == "expand" then
|
||||||
["," (readObject object.value)]
|
[ "," (readObject object.value) ]
|
||||||
else if object.type == "slice" then
|
else if object.type == "slice" then
|
||||||
[",@" (readObject object.value)]
|
[ ",@" (readObject object.value) ]
|
||||||
else if object.type == "function" then
|
else if object.type == "function" then
|
||||||
["#'" (readObject object.value)]
|
[ "#'" (readObject object.value) ]
|
||||||
else if object.type == "byteCode" then
|
else if object.type == "byteCode" then
|
||||||
["#"] ++ (readObject object.value)
|
[ "#" ] ++ (readObject object.value)
|
||||||
else if object.type == "record" then
|
else if object.type == "record" then
|
||||||
["#s"] ++ (readObject object.value)
|
[ "#s" ] ++ (readObject object.value)
|
||||||
else
|
else
|
||||||
object.value;
|
object.value;
|
||||||
in
|
in
|
||||||
map readObject ast;
|
map readObject ast;
|
||||||
|
|
||||||
fromElisp = elisp:
|
fromElisp = elisp:
|
||||||
fromElisp' (parseElisp elisp);
|
fromElisp' (parseElisp elisp);
|
||||||
|
@ -570,135 +576,137 @@ let
|
||||||
|
|
||||||
force = expr: seq state.pos (seq state.line expr);
|
force = expr: seq state.pos (seq state.line expr);
|
||||||
in
|
in
|
||||||
if state.skip > 0 then
|
if state.skip > 0 then
|
||||||
state // force {
|
state // force {
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
skip = state.skip - 1;
|
skip = state.skip - 1;
|
||||||
line = if char == "\n" then state.line + 1 else state.line;
|
line = if char == "\n" then state.line + 1 else state.line;
|
||||||
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
||||||
}
|
}
|
||||||
else if char == "#" && state.leadingWhitespace && !state.readBody && beginCodeBlock != null then
|
else if char == "#" && state.leadingWhitespace && !state.readBody && beginCodeBlock != null then
|
||||||
|
state // {
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength beginCodeBlock) - 1;
|
||||||
|
leadingWhitespace = false;
|
||||||
|
readLanguage = true;
|
||||||
|
}
|
||||||
|
else if char == "#" && state.leadingWhitespace && !state.readBody && header != null then
|
||||||
|
state // {
|
||||||
|
pos = state.pos + 1;
|
||||||
|
skip = (stringLength header) - 1;
|
||||||
|
leadingWhitespace = false;
|
||||||
|
readFlags = true;
|
||||||
|
}
|
||||||
|
else if state.readLanguage then
|
||||||
|
if language != null then
|
||||||
state // {
|
state // {
|
||||||
|
block = state.block // {
|
||||||
|
language = elemAt language 1;
|
||||||
|
};
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
skip = (stringLength beginCodeBlock) - 1;
|
skip = (foldl' (total: string: total + (stringLength string)) 0 language) - 1;
|
||||||
leadingWhitespace = false;
|
|
||||||
readLanguage = true;
|
|
||||||
}
|
|
||||||
else if char == "#" && state.leadingWhitespace && !state.readBody && header != null then
|
|
||||||
state // {
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength header) - 1;
|
|
||||||
leadingWhitespace = false;
|
leadingWhitespace = false;
|
||||||
|
readLanguage = false;
|
||||||
readFlags = true;
|
readFlags = true;
|
||||||
|
readBody = true;
|
||||||
}
|
}
|
||||||
else if state.readLanguage then
|
else throw "Language missing or invalid for code block on line ${toString state.line}!"
|
||||||
if language != null then
|
else if state.readFlags then
|
||||||
state // {
|
if flags != null then
|
||||||
block = state.block // {
|
let
|
||||||
language = elemAt language 1;
|
parseFlag = state: item:
|
||||||
};
|
let
|
||||||
pos = state.pos + 1;
|
prefix = if isString item then substring 0 1 item else null;
|
||||||
skip = (foldl' (total: string: total + (stringLength string)) 0 language) - 1;
|
in
|
||||||
leadingWhitespace = false;
|
if elem prefix [ ":" "-" "+" ] then
|
||||||
readLanguage = false;
|
state // {
|
||||||
readFlags = true;
|
acc = state.acc // { ${item} = true; };
|
||||||
readBody = true;
|
flag = item;
|
||||||
}
|
}
|
||||||
else throw "Language missing or invalid for code block on line ${toString state.line}!"
|
else if state.flag != null then
|
||||||
else if state.readFlags then
|
state // {
|
||||||
if flags != null then
|
acc = state.acc // { ${state.flag} = item; };
|
||||||
let
|
flag = null;
|
||||||
parseFlag = state: item:
|
}
|
||||||
let
|
else
|
||||||
prefix = if isString item then substring 0 1 item else null;
|
state;
|
||||||
in
|
in
|
||||||
if elem prefix [ ":" "-" "+" ] then
|
|
||||||
state // {
|
|
||||||
acc = state.acc // { ${item} = true; };
|
|
||||||
flag = item;
|
|
||||||
}
|
|
||||||
else if state.flag != null then
|
|
||||||
state // {
|
|
||||||
acc = state.acc // { ${state.flag} = item; };
|
|
||||||
flag = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
state;
|
|
||||||
in
|
|
||||||
state // {
|
|
||||||
block = state.block // {
|
|
||||||
flags =
|
|
||||||
(foldl'
|
|
||||||
parseFlag
|
|
||||||
{ acc = state.block.flags;
|
|
||||||
flag = null;
|
|
||||||
inherit (state) line;
|
|
||||||
}
|
|
||||||
(fromElisp flags)).acc;
|
|
||||||
startLineNumber = state.line + 1;
|
|
||||||
};
|
|
||||||
pos = state.pos + 1;
|
|
||||||
skip = (stringLength flags) - 1;
|
|
||||||
line = if char == "\n" then state.line + 1 else state.line;
|
|
||||||
leadingWhitespace = char == "\n";
|
|
||||||
readFlags = false;
|
|
||||||
}
|
|
||||||
else throw "Arguments malformed for code block on line ${toString state.line}!"
|
|
||||||
else if char == "#" && state.leadingWhitespace && endCodeBlock != null then
|
|
||||||
state // {
|
state // {
|
||||||
acc = state.acc ++ [ state.block ];
|
block = state.block // {
|
||||||
block = {
|
flags =
|
||||||
language = null;
|
(foldl'
|
||||||
body = "";
|
parseFlag
|
||||||
flags = {};
|
{
|
||||||
|
acc = state.block.flags;
|
||||||
|
flag = null;
|
||||||
|
inherit (state) line;
|
||||||
|
}
|
||||||
|
(fromElisp flags)).acc;
|
||||||
|
startLineNumber = state.line + 1;
|
||||||
};
|
};
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
skip = (stringLength endCodeBlock) - 1;
|
skip = (stringLength flags) - 1;
|
||||||
leadingWhitespace = false;
|
line = if char == "\n" then state.line + 1 else state.line;
|
||||||
readBody = false;
|
leadingWhitespace = char == "\n";
|
||||||
|
readFlags = false;
|
||||||
}
|
}
|
||||||
else if state.readBody then
|
else throw "Arguments malformed for code block on line ${toString state.line}!"
|
||||||
let
|
else if char == "#" && state.leadingWhitespace && endCodeBlock != null then
|
||||||
mod = state.pos / 100;
|
state // {
|
||||||
newState = {
|
acc = state.acc ++ [ state.block ];
|
||||||
block = state.block // {
|
block = {
|
||||||
body = state.block.body + char;
|
language = null;
|
||||||
};
|
body = "";
|
||||||
inherit mod;
|
flags = { };
|
||||||
pos = state.pos + 1;
|
};
|
||||||
line = if char == "\n" then state.line + 1 else state.line;
|
pos = state.pos + 1;
|
||||||
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
skip = (stringLength endCodeBlock) - 1;
|
||||||
|
leadingWhitespace = false;
|
||||||
|
readBody = false;
|
||||||
|
}
|
||||||
|
else if state.readBody then
|
||||||
|
let
|
||||||
|
mod = state.pos / 100;
|
||||||
|
newState = {
|
||||||
|
block = state.block // {
|
||||||
|
body = state.block.body + char;
|
||||||
};
|
};
|
||||||
in
|
inherit mod;
|
||||||
if mod > state.mod then
|
|
||||||
state // seq state.block.body (force newState)
|
|
||||||
else
|
|
||||||
state // newState
|
|
||||||
else
|
|
||||||
state // force {
|
|
||||||
pos = state.pos + 1;
|
pos = state.pos + 1;
|
||||||
line = if char == "\n" then state.line + 1 else state.line;
|
line = if char == "\n" then state.line + 1 else state.line;
|
||||||
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
(foldl'
|
if mod > state.mod then
|
||||||
parseToken
|
state // seq state.block.body (force newState)
|
||||||
{ acc = [];
|
else
|
||||||
mod = 0;
|
state // newState
|
||||||
pos = 0;
|
else
|
||||||
skip = 0;
|
state // force {
|
||||||
line = 1;
|
pos = state.pos + 1;
|
||||||
block = {
|
line = if char == "\n" then state.line + 1 else state.line;
|
||||||
language = null;
|
leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]);
|
||||||
body = "";
|
|
||||||
flags = {};
|
|
||||||
};
|
};
|
||||||
leadingWhitespace = true;
|
in
|
||||||
readLanguage = false;
|
(foldl'
|
||||||
readFlags = false;
|
parseToken
|
||||||
readBody = false;
|
{
|
||||||
}
|
acc = [ ];
|
||||||
(stringToCharacters text)).acc;
|
mod = 0;
|
||||||
|
pos = 0;
|
||||||
|
skip = 0;
|
||||||
|
line = 1;
|
||||||
|
block = {
|
||||||
|
language = null;
|
||||||
|
body = "";
|
||||||
|
flags = { };
|
||||||
|
};
|
||||||
|
leadingWhitespace = true;
|
||||||
|
readLanguage = false;
|
||||||
|
readFlags = false;
|
||||||
|
readBody = false;
|
||||||
|
}
|
||||||
|
(stringToCharacters text)).acc;
|
||||||
|
|
||||||
# Run tokenizeElisp' on all Elisp code blocks (with `:tangle yes`
|
# Run tokenizeElisp' on all Elisp code blocks (with `:tangle yes`
|
||||||
# set) from an Org mode babel text. If the block doesn't have a
|
# set) from an Org mode babel text. If the block doesn't have a
|
||||||
|
@ -712,19 +720,19 @@ let
|
||||||
tangle = toLower (block.flags.":tangle" or defaultArgs.":tangle" or "no");
|
tangle = toLower (block.flags.":tangle" or defaultArgs.":tangle" or "no");
|
||||||
language = toLower block.language;
|
language = toLower block.language;
|
||||||
in
|
in
|
||||||
elem language [ "elisp" "emacs-lisp" ]
|
elem language [ "elisp" "emacs-lisp" ]
|
||||||
&& elem tangle [ "yes" ''"yes"'' ])
|
&& elem tangle [ "yes" ''"yes"'' ])
|
||||||
(parseOrgModeBabel text);
|
(parseOrgModeBabel text);
|
||||||
in
|
in
|
||||||
foldl'
|
foldl'
|
||||||
(result: codeBlock:
|
(result: codeBlock:
|
||||||
result ++ (tokenizeElisp' {
|
result ++ (tokenizeElisp' {
|
||||||
elisp = codeBlock.body;
|
elisp = codeBlock.body;
|
||||||
inherit (codeBlock) startLineNumber;
|
inherit (codeBlock) startLineNumber;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
[]
|
[ ]
|
||||||
codeBlocks;
|
codeBlocks;
|
||||||
|
|
||||||
tokenizeOrgModeBabelElisp =
|
tokenizeOrgModeBabelElisp =
|
||||||
tokenizeOrgModeBabelElisp' {
|
tokenizeOrgModeBabelElisp' {
|
||||||
|
|
|
@ -13,10 +13,15 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
{ lib, stdenv, emacs29, callPackage, writeShellApplication, noether
|
{ lib
|
||||||
, emacsParams ? {},
|
, stdenv
|
||||||
fg42Params ? {}
|
, emacs29
|
||||||
} :
|
, callPackage
|
||||||
|
, writeShellApplication
|
||||||
|
, noether
|
||||||
|
, emacsParams ? { }
|
||||||
|
, fg42Params ? { }
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
lemacs = emacs29.override ({
|
lemacs = emacs29.override ({
|
||||||
withTreeSitter = true;
|
withTreeSitter = true;
|
||||||
|
@ -44,7 +49,8 @@ let
|
||||||
runtimeInputs = [ fg42 ];
|
runtimeInputs = [ fg42 ];
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
DISPLAY=:1 ${fg42}/bin/fg42-wm
|
DISPLAY=:1 ${fg42}/bin/fg42-wm
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in { inherit fg42 run-test-wm; }
|
in
|
||||||
|
{ inherit fg42 run-test-wm; }
|
||||||
|
|
72
nix/fg42.nix
72
nix/fg42.nix
|
@ -13,22 +13,51 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
{ lib, stdenv, elispPkgs, srcDir, emacsPackagesFor, ourPackages, direnv
|
{ lib
|
||||||
, makeFontsConf, nix
|
, stdenv
|
||||||
|
, elispPkgs
|
||||||
, nil, # nix lsp server
|
, srcDir
|
||||||
|
, emacsPackagesFor
|
||||||
|
, ourPackages
|
||||||
|
, direnv
|
||||||
|
, makeFontsConf
|
||||||
|
, nix
|
||||||
|
, nixpkgs-fmt
|
||||||
|
, nil
|
||||||
|
, # nix lsp server
|
||||||
|
|
||||||
# python deps
|
# python deps
|
||||||
python311, python3Packages,
|
python311
|
||||||
# This is a set of system tools required for FG42
|
, python3Packages
|
||||||
|
, # This is a set of system tools required for FG42
|
||||||
# to work.
|
# to work.
|
||||||
pyright, emacs, ripgrep, git, texinfo, vazir-fonts, fira-code, nerdfonts
|
pyright
|
||||||
, fira-mono, noto-fonts, gcc, ltex-ls, bash, tree-sitter, fd
|
, emacs
|
||||||
, aspellWithDicts,
|
, ripgrep
|
||||||
|
, git
|
||||||
supportWM ? true, xorg, slock,
|
, texinfo
|
||||||
|
, vazir-fonts
|
||||||
supportPython ? true, supportVerilog ? true, svls, verilator, }:
|
, fira-code
|
||||||
|
, nerdfonts
|
||||||
|
, fira-mono
|
||||||
|
, noto-fonts
|
||||||
|
, gcc
|
||||||
|
, ltex-ls
|
||||||
|
, bash
|
||||||
|
, tree-sitter
|
||||||
|
, fd
|
||||||
|
, aspellWithDicts
|
||||||
|
, supportWM ? true
|
||||||
|
, xorg
|
||||||
|
, slock
|
||||||
|
, supportPython ? true
|
||||||
|
, supportVerilog ? true
|
||||||
|
, supportClojure ? true
|
||||||
|
, svls
|
||||||
|
, verilator
|
||||||
|
, clojure-lsp
|
||||||
|
,
|
||||||
|
}:
|
||||||
with builtins;
|
with builtins;
|
||||||
let
|
let
|
||||||
version = "4.0.0";
|
version = "4.0.0";
|
||||||
|
@ -44,7 +73,15 @@ let
|
||||||
dicts = aspellWithDicts (dicts: with dicts; [ en en-computers en-science ]);
|
dicts = aspellWithDicts (dicts: with dicts; [ en en-computers en-science ]);
|
||||||
|
|
||||||
runtimeBins = [
|
runtimeBins = [
|
||||||
ripgrep git tree-sitter direnv nix nil dicts fd
|
ripgrep
|
||||||
|
git
|
||||||
|
tree-sitter
|
||||||
|
direnv
|
||||||
|
nix
|
||||||
|
nil
|
||||||
|
dicts
|
||||||
|
fd
|
||||||
|
nixpkgs-fmt
|
||||||
]
|
]
|
||||||
++ (lib.optional (!stdenv.buildPlatform.isRiscV) [
|
++ (lib.optional (!stdenv.buildPlatform.isRiscV) [
|
||||||
# Not supported on Risc-V
|
# Not supported on Risc-V
|
||||||
|
@ -64,12 +101,14 @@ let
|
||||||
# SystemC is required by verilator that at the
|
# SystemC is required by verilator that at the
|
||||||
# moment is only available on Linux
|
# moment is only available on Linux
|
||||||
verilator
|
verilator
|
||||||
]) ++ (lib.optional (supportWM && stdenv.isLinux) [
|
]) ++ (lib.optional (supportClojure) [ clojure-lsp ])
|
||||||
|
++ (lib.optional (supportWM && stdenv.isLinux) [
|
||||||
# Window manager supports works on Linux only
|
# Window manager supports works on Linux only
|
||||||
xorg.xhost
|
xorg.xhost
|
||||||
slock
|
slock
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
paths = map (x: "${x}/bin/") (lib.lists.flatten runtimeBins);
|
paths = map (x: "${x}/bin/") (lib.lists.flatten runtimeBins);
|
||||||
pathsStr = lib.strings.concatStrings (lib.strings.intersperse ":" paths);
|
pathsStr = lib.strings.concatStrings (lib.strings.intersperse ":" paths);
|
||||||
|
|
||||||
|
@ -84,7 +123,8 @@ let
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
in stdenv.mkDerivation (final: rec {
|
in
|
||||||
|
stdenv.mkDerivation (final: rec {
|
||||||
inherit version;
|
inherit version;
|
||||||
pname = "fg42";
|
pname = "fg42";
|
||||||
src = srcDir;
|
src = srcDir;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
lxsameer = {
|
lxsameer = {
|
||||||
email = "lxsameer@lxsameer.com";
|
email = "lxsameer@lxsameer.com";
|
||||||
github = "lxsameer";
|
github = "lxsameer";
|
||||||
git = "lxsameer";
|
git = "lxsameer";
|
||||||
matrix = "@lxsameer:matrix.org";
|
matrix = "@lxsameer:matrix.org";
|
||||||
name = "Sameer Rahmani";
|
name = "Sameer Rahmani";
|
||||||
keys = [{
|
keys = [{
|
||||||
|
|
133
nix/parse.nix
133
nix/parse.nix
|
@ -22,76 +22,77 @@ let
|
||||||
(x: builtins.typeOf x == "string")
|
(x: builtins.typeOf x == "string")
|
||||||
(builtins.split _sep _s);
|
(builtins.split _sep _s);
|
||||||
|
|
||||||
in {
|
in
|
||||||
elispStr
|
{ elispStr
|
||||||
, alwaysEnsure ? false
|
, alwaysEnsure ? false
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (import ./elisp_reader.nix { inherit lib; }) fromElisp;
|
inherit (import ./elisp_reader.nix { inherit lib; }) fromElisp;
|
||||||
|
|
||||||
readFunction = fromElisp;
|
readFunction = fromElisp;
|
||||||
find = item: list:
|
find = item: list:
|
||||||
if list == [] then [] else
|
if list == [ ] then [ ] else
|
||||||
if builtins.head list == item then
|
if builtins.head list == item then
|
||||||
list
|
list
|
||||||
else
|
else
|
||||||
find item (builtins.tail list);
|
find item (builtins.tail list);
|
||||||
|
|
||||||
getKeywordValue = keyword: list:
|
getKeywordValue = keyword: list:
|
||||||
|
let
|
||||||
|
keywordList = find keyword list;
|
||||||
|
in
|
||||||
|
if keywordList != [ ] then
|
||||||
let
|
let
|
||||||
keywordList = find keyword list;
|
keywordValue = builtins.tail keywordList;
|
||||||
in
|
in
|
||||||
if keywordList != [] then
|
if keywordValue != [ ] then
|
||||||
let
|
builtins.head keywordValue
|
||||||
keywordValue = builtins.tail keywordList;
|
|
||||||
in
|
|
||||||
if keywordValue != [] then
|
|
||||||
builtins.head keywordValue
|
|
||||||
else
|
|
||||||
true
|
|
||||||
else
|
|
||||||
null;
|
|
||||||
|
|
||||||
isDisabled = item:
|
|
||||||
let
|
|
||||||
disabledValue = getKeywordValue ":disabled" item;
|
|
||||||
in
|
|
||||||
if disabledValue == [] then
|
|
||||||
false
|
|
||||||
else if builtins.isBool disabledValue then
|
|
||||||
disabledValue
|
|
||||||
else if builtins.isString disabledValue then
|
|
||||||
true
|
|
||||||
else
|
|
||||||
false;
|
|
||||||
|
|
||||||
getName = item:
|
|
||||||
let
|
|
||||||
ensureValue = getKeywordValue ":ensure" item;
|
|
||||||
usePackageName = builtins.head (builtins.tail item);
|
|
||||||
in
|
|
||||||
if builtins.isString ensureValue then
|
|
||||||
if lib.hasPrefix ":" ensureValue then
|
|
||||||
usePackageName
|
|
||||||
else
|
|
||||||
ensureValue
|
|
||||||
else if ensureValue == true || (ensureValue == null && alwaysEnsure) then
|
|
||||||
usePackageName
|
|
||||||
else
|
|
||||||
[];
|
|
||||||
|
|
||||||
recurse = item:
|
|
||||||
if builtins.isList item && item != [] then
|
|
||||||
let
|
|
||||||
packageManager = builtins.head item;
|
|
||||||
in
|
|
||||||
if builtins.elem packageManager [ "depends-on" ] then
|
|
||||||
if !(isDisabled item) then
|
|
||||||
[ packageManager (getName item) ] ++ map recurse item
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
else
|
|
||||||
map recurse item
|
|
||||||
else
|
else
|
||||||
[];
|
true
|
||||||
in lib.flatten (map recurse (readFunction elispStr))
|
else
|
||||||
|
null;
|
||||||
|
|
||||||
|
isDisabled = item:
|
||||||
|
let
|
||||||
|
disabledValue = getKeywordValue ":disabled" item;
|
||||||
|
in
|
||||||
|
if disabledValue == [ ] then
|
||||||
|
false
|
||||||
|
else if builtins.isBool disabledValue then
|
||||||
|
disabledValue
|
||||||
|
else if builtins.isString disabledValue then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false;
|
||||||
|
|
||||||
|
getName = item:
|
||||||
|
let
|
||||||
|
ensureValue = getKeywordValue ":ensure" item;
|
||||||
|
usePackageName = builtins.head (builtins.tail item);
|
||||||
|
in
|
||||||
|
if builtins.isString ensureValue then
|
||||||
|
if lib.hasPrefix ":" ensureValue then
|
||||||
|
usePackageName
|
||||||
|
else
|
||||||
|
ensureValue
|
||||||
|
else if ensureValue == true || (ensureValue == null && alwaysEnsure) then
|
||||||
|
usePackageName
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
|
|
||||||
|
recurse = item:
|
||||||
|
if builtins.isList item && item != [ ] then
|
||||||
|
let
|
||||||
|
packageManager = builtins.head item;
|
||||||
|
in
|
||||||
|
if builtins.elem packageManager [ "depends-on" ] then
|
||||||
|
if !(isDisabled item) then
|
||||||
|
[ packageManager (getName item) ] ++ map recurse item
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
else
|
||||||
|
map recurse item
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
|
in
|
||||||
|
lib.flatten (map recurse (readFunction elispStr))
|
||||||
|
|
Loading…
Reference in New Issue