This commit is contained in:
ry
2022-01-11 18:05:13 -08:00
parent 2046befee2
commit 8e7b654716
846 changed files with 71287 additions and 4 deletions

View 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 |
| | | |

View 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))

View 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"))))

View 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")))