yeet
This commit is contained in:
60
.config/emacs/modules/lang/scheme/README.org
Normal file
60
.config/emacs/modules/lang/scheme/README.org
Normal file
@@ -0,0 +1,60 @@
|
||||
#+TITLE: lang/scheme
|
||||
#+DATE: July 23, 2019
|
||||
#+SINCE: v2.0.9
|
||||
#+STARTUP: inlineimages
|
||||
|
||||
* Table of Contents :TOC_3:noexport:
|
||||
- [[#description][Description]]
|
||||
- [[#module-flags][Module Flags]]
|
||||
- [[#plugins][Plugins]]
|
||||
- [[#prerequisites][Prerequisites]]
|
||||
- [[#features][Features]]
|
||||
- [[#commands][Commands]]
|
||||
- [[#geiser][Geiser]]
|
||||
|
||||
* Description
|
||||
This module provides an environment for hacking and having fun in scheme. It is
|
||||
powered by [[https://www.nongnu.org/geiser/geiser_1.html#introduction][geiser]].
|
||||
|
||||
** Module Flags
|
||||
+ =+chez=
|
||||
+ =+chibi=
|
||||
+ =+chicken=
|
||||
+ =+gambit=
|
||||
+ =+gauche=
|
||||
+ =+guile=
|
||||
+ =+kawa=
|
||||
+ =+mit=
|
||||
+ =+racket=
|
||||
|
||||
** Plugins
|
||||
+ [[https://gitlab.com/jaor/geiser][geiser]]
|
||||
+ [[https://github.com/nbfalcon/macrostep-geiser][macrostep-geiser]]
|
||||
+ [[https://gitlab.com/emacs-geiser/chez][geiser-chez]] (if =+chez=)
|
||||
+ [[https://gitlab.com/emacs-geiser/chibi][geiser-chibi]] (if =+chibi=)
|
||||
+ [[https://gitlab.com/emacs-geiser/chicken][geiser-chicken]] (if =+chicken=)
|
||||
+ [[https://gitlab.com/emacs-geiser/gambit][geiser-gambit]] (if =+gambit=)
|
||||
+ [[https://gitlab.com/emacs-geiser/gauche][geiser-gauche]] (if =+gauche=)
|
||||
+ [[https://gitlab.com/emacs-geiser/guile][geiser-guile]] (if =+guile=)
|
||||
+ [[https://github.com/flatwhatson/flycheck-guile][flycheck-guile]] (if =+guile= and =:checkers syntax=)
|
||||
+ [[https://gitlab.com/emacs-geiser/kawa][geiser-kawa]] (if =+kawa=)
|
||||
+ [[https://gitlab.com/emacs-geiser/mit][geiser-mit]] (if =+mit=)
|
||||
+ [[https://gitlab.com/emacs-geiser/racket][geiser-racket]] (if =+racket=)
|
||||
|
||||
* Prerequisites
|
||||
This module requires you to have at least one of the supported schemes, namely:
|
||||
- [[https://www.gnu.org/software/guile][Guile]] 2.2.0 or better
|
||||
- [[https://call-cc.org][Chicken]] 4.8.0 or better
|
||||
- [[https://www.gnu.org/software/mit-scheme][MIT/GNU Scheme]] 9.1.1 or better
|
||||
- [[https://synthcode.com/scheme/chibi][Chibi Scheme]] 0.7.3 or better
|
||||
- [[https://www.scheme.com][Chez Scheme]] 9.4 or better
|
||||
|
||||
Their executables must be present in your path for geiser to work properly.
|
||||
|
||||
* Features
|
||||
** Commands
|
||||
*** Geiser
|
||||
| command | key / ex command | description |
|
||||
|---------------------+------------------+----------------------|
|
||||
| ~+scheme/open-repl~ | =:repl= | Open the Scheme Repl |
|
||||
| | | |
|
||||
73
.config/emacs/modules/lang/scheme/autoload.el
Normal file
73
.config/emacs/modules/lang/scheme/autoload.el
Normal file
@@ -0,0 +1,73 @@
|
||||
;;; lang/scheme/autoload.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; HACK `geiser' has poor autoload etiquette. It calls
|
||||
;; `geiser-activate-implementation' and `geiser-implementation-extension'
|
||||
;; in their autoloads files. Sure, these functions are autoloaded, but this
|
||||
;; needlessly (and unavoidably) pulls in the `geiser-impl' package (et co)
|
||||
;; when geiser-X's autoloads are read (i.e. at startup).
|
||||
;;
|
||||
;; I rectify this by inlining calls to these two functions (and the
|
||||
;; `geiser-impl--add-to-alist' sub-call in
|
||||
;; `geiser-implementation-extension'), and autoloading the two variables
|
||||
;; they operate on. I do this from our autoloads file (which is
|
||||
;; byte-compiled and read at startup before package autoloads).
|
||||
;; TODO At some point, PR this behavior upstream (but not verbatim!)
|
||||
;;;###autoload (defvar geiser-active-implementations ())
|
||||
;;;###autoload (defvar geiser-implementations-alist ())
|
||||
;;;###autoload (eval-and-compile (dolist (sym '(geiser-impl--add-to-alist geiser-activate-implementation geiser-implementation-extension)) (put sym 'byte-optimizer 'byte-compile-inline-expand)))
|
||||
|
||||
|
||||
(defvar calculate-lisp-indent-last-sexp)
|
||||
;; Adapted from https://github.com/alezost/emacs-config/blob/master/utils/al-scheme.el#L76-L123
|
||||
;;;###autoload
|
||||
(defun +scheme-indent-function-a (indent-point state)
|
||||
"Advice to replace `scheme-indent-function'.
|
||||
|
||||
This function is the same as `scheme-indent-function' except it properly indents
|
||||
property lists and names starting with 'default'."
|
||||
(let ((normal-indent (current-column)))
|
||||
(goto-char (1+ (elt state 1)))
|
||||
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
|
||||
(if (and (elt state 2)
|
||||
;; NOTE looking-at -> looking-at-p
|
||||
(not (looking-at-p "\\sw\\|\\s_")))
|
||||
(progn
|
||||
;; NOTE (if (not ...) (progn ...)) -> (unless ... ...)
|
||||
(unless (> (save-excursion (forward-line 1) (point))
|
||||
calculate-lisp-indent-last-sexp)
|
||||
(goto-char calculate-lisp-indent-last-sexp)
|
||||
(beginning-of-line)
|
||||
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t))
|
||||
(backward-prefix-chars)
|
||||
(current-column))
|
||||
;; NOTE let -> let* & moved `method' def into let bindings
|
||||
(let* ((function (buffer-substring
|
||||
(point) (progn (forward-sexp 1) (point))))
|
||||
(method (or (get (intern-soft function) 'scheme-indent-function)
|
||||
(get (intern-soft function) 'scheme-indent-hook))))
|
||||
(cond ((or (eq method 'defun)
|
||||
(and (null method)
|
||||
(> (length function) 3)
|
||||
;; NOTE string-match -> string-match-p
|
||||
;; NOTE The original regexp is "\\`def" but it will mess
|
||||
;; up indentation with such names as 'default-...'.
|
||||
(string-match-p "\\`def" function)))
|
||||
(lisp-indent-defform state indent-point))
|
||||
;; NOTE Added this clause to handle alignment of keyword symbols
|
||||
((and (null method)
|
||||
(> (length function) 1)
|
||||
;; NOTE string-match -> string-match-p
|
||||
(string-match-p "\\`:" function))
|
||||
(let ((lisp-body-indent 1))
|
||||
(lisp-indent-defform state indent-point)))
|
||||
((integerp method)
|
||||
(lisp-indent-specform method state indent-point normal-indent))
|
||||
(method
|
||||
(funcall method state indent-point normal-indent)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +scheme/open-repl ()
|
||||
"Open the Scheme REPL."
|
||||
(interactive)
|
||||
(call-interactively #'switch-to-geiser)
|
||||
(current-buffer))
|
||||
80
.config/emacs/modules/lang/scheme/config.el
Normal file
80
.config/emacs/modules/lang/scheme/config.el
Normal file
@@ -0,0 +1,80 @@
|
||||
;;; lang/scheme/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(use-package! scheme
|
||||
:hook (scheme-mode . rainbow-delimiters-mode)
|
||||
:config (advice-add #'scheme-indent-function :override #'+scheme-indent-function-a))
|
||||
|
||||
|
||||
(use-package! geiser
|
||||
:defer t
|
||||
:init
|
||||
(setq geiser-autodoc-identifier-format "%s → %s"
|
||||
geiser-repl-current-project-function #'doom-project-root)
|
||||
|
||||
(after! scheme ; built-in
|
||||
(set-repl-handler! 'scheme-mode #'+scheme/open-repl)
|
||||
(set-eval-handler! 'scheme-mode #'geiser-eval-region)
|
||||
(set-lookup-handlers! '(scheme-mode geiser-repl-mode)
|
||||
:definition #'geiser-edit-symbol-at-point
|
||||
:documentation #'geiser-doc-symbol-at-point))
|
||||
:config
|
||||
(set-popup-rules!
|
||||
'(("^\\*[gG]eiser \\(dbg\\|xref\\|messages\\)\\*$" :slot 1 :vslot -1)
|
||||
("^\\*Geiser documentation\\*$" :slot 2 :vslot 2 :select t :size 0.35)
|
||||
("^\\* [A-Za-z0-9_-]+ REPL \\*" :size 0.3 :quit nil :ttl nil)))
|
||||
|
||||
(map! :localleader
|
||||
(:map (scheme-mode-map geiser-repl-mode-map)
|
||||
:desc "Toggle REPL" "'" #'switch-to-geiser
|
||||
:desc "Connect to external Scheme" "\"" #'geiser-connect
|
||||
:desc "Toggle type of brackets" "[" #'geiser-squarify
|
||||
:desc "Insert lambda" "\\" #'geiser-insert-lambda
|
||||
:desc "Set Scheme implementation" "s" #'geiser-set-scheme
|
||||
:desc "Reload Geiser buffers+REPLs" "R" #'geiser-reload
|
||||
(:prefix ("h" . "help")
|
||||
:desc "Show callers of <point>" "<" #'geiser-xref-callers
|
||||
:desc "Show callees of <point>" ">" #'geiser-xref-callees
|
||||
:desc "Toggle autodoc mode" "a" #'geiser-autodoc-mode
|
||||
:desc "Show autodoc of <point>" "s" #'geiser-autodoc-show
|
||||
:desc "Search manual for <point>" "m" #'geiser-doc-look-up-manual
|
||||
:desc "Show docstring of <point>" "." #'geiser-doc-symbol-at-point)
|
||||
(:prefix ("r" . "repl")
|
||||
:desc "Load file into REPL" "f" #'geiser-load-file
|
||||
:desc "Restart REPL" "r" #'geiser-restart-repl))
|
||||
(:map scheme-mode-map
|
||||
(:prefix ("e" . "eval")
|
||||
:desc "Eval buffer" "b" #'geiser-eval-buffer
|
||||
:desc "Eval buffer and go to REPL" "B" #'geiser-eval-buffer-and-go
|
||||
:desc "Eval last sexp" "e" #'geiser-eval-last-sexp
|
||||
:desc "Eval definition" "d" #'geiser-eval-definition
|
||||
:desc "Eval defn. and go to REPL" "D" #'geiser-eval-definition-and-go
|
||||
:desc "Eval region" "r" #'geiser-eval-region
|
||||
:desc "Eval region and go to REPL" "R" #'geiser-eval-region-and-go)
|
||||
(:prefix ("r" . "repl")
|
||||
:desc "Load current buffer in REPL" "b" #'geiser-load-current-buffer))
|
||||
(:map geiser-repl-mode-map
|
||||
:desc "Clear REPL buffer" "c" #'geiser-repl-clear-buffer
|
||||
:desc "Quit REPL" "q" #'geiser-repl-exit)))
|
||||
|
||||
|
||||
(use-package! macrostep-geiser
|
||||
:hook (geiser-mode . macrostep-geiser-setup)
|
||||
:hook (geiser-repl-mode . macrostep-geiser-setup)
|
||||
:init
|
||||
(map! :after geiser
|
||||
:localleader
|
||||
:map (scheme-mode-map geiser-repl-mode-map)
|
||||
:desc "Expand macro by one step" "m" #'macrostep-expand
|
||||
:desc "Recursively expand macro" "M" #'macrostep-geiser-expand-all))
|
||||
|
||||
|
||||
(use-package! flycheck-guile
|
||||
:when (featurep! +guile)
|
||||
:when (featurep! :checkers syntax)
|
||||
:after geiser)
|
||||
|
||||
;; Add Guix channels to Guile load path
|
||||
(when (and (featurep! +guile) (executable-find "guix"))
|
||||
(after! geiser-guile
|
||||
(add-to-list 'geiser-guile-load-path
|
||||
(expand-file-name "~/.config/guix/current/share/guile/site/3.0"))))
|
||||
27
.config/emacs/modules/lang/scheme/packages.el
Normal file
27
.config/emacs/modules/lang/scheme/packages.el
Normal file
@@ -0,0 +1,27 @@
|
||||
;; -*- no-byte-compile: t; -*-
|
||||
;;; lang/scheme/packages.el
|
||||
|
||||
(when (package! geiser :pin "327ff01e5b9c6e019fdd0cb710a4c19082249345")
|
||||
(package! macrostep-geiser :pin "f6a2d5bb96ade4f23df557649af87ebd0cc45125")
|
||||
(when (featurep! +chez)
|
||||
(package! geiser-chez :pin "03da1c17253856d8713bc5a25140cb5002c9c188"))
|
||||
(when (featurep! +chibi)
|
||||
(package! geiser-chibi :pin "6f59291d8d1dc92ffd3f53f919d8cab4bf50b7d3"))
|
||||
(when (featurep! +chicken)
|
||||
(package! geiser-chicken :pin "ceab39c89607f55cba88e5606ba5eb37c7df5260"))
|
||||
(when (featurep! +gambit)
|
||||
(package! geiser-gambit :pin "3294c944d1c3b79db44ed14b133129fec454bd60"))
|
||||
(when (featurep! +gauche)
|
||||
(package! geiser-gauche :pin "fd52cbaed9b0a0d0f10e87674b5747e5ee44ebc9"))
|
||||
(when (featurep! +guile)
|
||||
(package! geiser-guile :pin "8dda28f4f1758221f84f5cb5dc5b5ca5fd56caa9")
|
||||
(when (featurep! :checkers syntax)
|
||||
(package! flycheck-guile
|
||||
:recipe (:host github :repo "flatwhatson/flycheck-guile")
|
||||
:pin "e46d6e5453dd7471309fae6549445c48e6d8f340")))
|
||||
(when (featurep! +kawa)
|
||||
(package! geiser-kawa :pin "3d999a33deedd62dae60f3f7cedfbdb715587ea7"))
|
||||
(when (featurep! +mit)
|
||||
(package! geiser-mit :pin "d17394f577aaa2854a74a1a0039cb8f73378b400"))
|
||||
(when (featurep! +racket)
|
||||
(package! geiser-racket :pin "22e56ce80389544d3872cf4beb4008fb514b2218")))
|
||||
Reference in New Issue
Block a user