Add racket lisp package

This commit is contained in:
2026-03-05 17:40:40 +09:00
parent cb26403326
commit 6f2f3b6bcd
3 changed files with 21 additions and 182 deletions

View File

@@ -132,15 +132,30 @@ control codes are not supported."
:init
(setq inferior-lisp-program "sbcl"))
;; Racket lisp
(use-package racket-mode
:ensure t
:defer t
:commands (racket-mode racket-xp-mode)
:hook ((racket-mode . racket-xp-mode))
:bind (("C-c C-n" . racket-run-and-switch-to-repl))
:config
(setq racket-xp-eldoc-level 'summary))
(defun racket-restart ()
"Restarts the backend and reinitializes the mode to cope with the
consequences of direnv activating after racket-mode(-s)."
(interactive)
(when (eq major-mode 'racket-mode)
(racket-stop-back-end)
(racket-start-back-end)
(racket-mode)))
;; Markdown
(use-package markdown-mode
:ensure t
:defer t)
;; Lispy provides structural editing to lisp modes.
(use-package lispy
:defer t)
(if (memq 'lispy-autoloads features)
(add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1))))

View File

@@ -1,178 +0,0 @@
;;; 99-external-misc.el --- Miscellaneous functions made by others -*- lexical-binding: t -*-
;; This file is not part of GNU Emacs
;;; Commentary:
;; This file contains various useful functions and macros that I definitely
;; didn't write and took from somewhere as-is.
;;; Code:
(defun second (item)
(nth 1 item))
(defun third (item)
(nth 2 item))
(defun fourth (item)
(nth 3 item))
;; Source: https://phillord.github.io/m-buffer-el/#sec-5-1-2
;;;###autoload
(cl-defmacro bench (&optional (times 100000) &rest body)
"Call `benchmark-run-compiled' on BODY with TIMES iterations, returning list suitable for Org source block evaluation.
Garbage is collected before calling `benchmark-run-compiled' to
avoid counting existing garbage which needs collection."
(declare (indent defun))
`(progn
(garbage-collect)
(list '("Total runtime" "# of GCs" "Total GC runtime")
'hline
(benchmark-run-compiled ,times
(progn
,@body)))))
;; Source: alphapapa.github.io/emacs-package-dev-handbook/#outline-container-bench-multi-macros
;;;###autoload
(cl-defmacro bench-multi (&key (times 1) forms ensure-equal raw)
"Return Org table as a list with benchmark results for FORMS.
Runs FORMS with `benchmark-run-compiled' for TIMES iterations.
When ENSURE-EQUAL is non-nil, the results of FORMS are compared,
and an error is raised if they aren't `equal'. If the results are
sequences, the difference between them is shown with
`seq-difference'.
When RAW is non-nil, the raw results from
`benchmark-run-compiled' are returned instead of an Org table
list.
If the first element of a form is a string, it's used as the
form's description in the bench-multi-results; otherwise, forms
are numbered from 0.
Before each form is run, `garbage-collect' is called.
See source for a usage example."
;; MAYBE: Since `bench-multi-lexical' byte-compiles the file, I'm not sure if
;; `benchmark-run-compiled' is necessary over `benchmark-run', or if it matters.
(declare (indent defun))
(let*((keys (gensym "keys"))
(result-times (gensym "result-times"))
(header '(("Form" "x fastest" "Total runtime" "# of GCs" "Total GC runtime")
hline))
;; Copy forms so that a subsequent call of the macro will get the original forms.
(forms (cl-copy-list forms))
(descriptions (cl-loop for form in forms
for i from 0
collect (if (stringp (car form))
(prog1 (car form)
(setf (nth i forms) (cadr (nth i forms))))
i))))
`(unwind-protect
(progn
(defvar bench-multi-results nil)
(let* ((bench-multi-results (make-hash-table))
(,result-times (sort (list ,@(cl-loop for form in forms
for i from 0
for description = (nth i descriptions)
collect `(progn
(garbage-collect)
(cons ,description
(benchmark-run-compiled ,times
,(if ensure-equal
`(puthash ,description ,form bench-multi-results)
form))))))
(lambda (a b)
(< (nth 1 a) (nth 1 b))))))
,(when ensure-equal
`(cl-loop with ,keys = (hash-table-keys bench-multi-results)
for i from 0 to (- (length ,keys) 2)
unless (equal (gethash (nth i ,keys) bench-multi-results)
(gethash (nth (1+ i) ,keys) bench-multi-results))
do (if (sequencep (gethash (car (hash-table-keys bench-multi-results)) bench-multi-results))
(let* ((k1) (k2)
;; If the difference in one order is nil, try in other order.
(difference (or (setq k1 (nth i ,keys)
k2 (nth (1+ i) ,keys)
difference (seq-difference (gethash k1 bench-multi-results)
(gethash k2 bench-multi-results)))
(setq k1 (nth (1+ i) ,keys)
k2 (nth i ,keys)
difference (seq-difference (gethash k1 bench-multi-results)
(gethash k2 bench-multi-results))))))
(user-error "Forms' bench-multi-results not equal: difference (%s - %s): %S"
k1 k2 difference))
;; Not a sequence
(user-error "Forms' bench-multi-results not equal: %s:%S %s:%S"
(nth i ,keys) (nth (1+ i) ,keys)
(gethash (nth i ,keys) bench-multi-results)
(gethash (nth (1+ i) ,keys) bench-multi-results)))))
;; Add factors to times and return table
(if ,raw
,result-times
(append ',header
(bench-multi-process-results ,result-times)))))
(unintern 'bench-multi-results nil))))
;; Use like this:
;; (bench-multi
;; :forms (("org-map-entries" (sort (org-map-entries (lambda ()
;; (nth 4 (org-heading-components)))
;; "/+MAYBE" 'agenda)
;; #'string<))
;; ("regexp" (sort (-flatten
;; (-non-nil
;; (mapcar (lambda (file)
;; (let ((case-fold-search t))
;; (with-current-buffer (find-buffer-visiting file)
;; (org-with-wide-buffer
;; (goto-char (point-min))
;; (cl-loop with regexp = (format org-heading-keyword-regexp-format "MAYBE")
;; while (re-search-forward regexp nil t)
;; collect (nth 4 (org-heading-components)))))))
;; (org-agenda-files))))
;; #'string<))))
(defun bench-multi-process-results (results)
"Return sorted RESULTS with factors added."
(setq results (sort results (-on #'< #'second)))
(cl-loop with length = (length results)
for i from 0 below length
for description = (car (nth i results))
for factor = (pcase i
(0 "fastest")
(_ (format "%.2f" (/ (second (nth i results))
(second (nth 0 results))))))
collect (append (list description factor)
(list (format "%.6f" (second (nth i results)))
(third (nth i results))
(if (> (fourth (nth i results)) 0)
(format "%.6f" (fourth (nth i results)))
0)))))
;;;###autoload
(cl-defmacro bench-multi-lexical (&key (times 1) forms ensure-equal raw)
"Return Org table as a list with benchmark results for FORMS.
Runs FORMS from a byte-compiled temp file with `lexical-binding'
enabled, using `bench-multi', which see.
Afterward, the temp file is deleted and the function used to run
the benchmark is uninterned."
(declare (indent defun))
`(let* ((temp-file (concat (make-temp-file "bench-multi-lexical-") ".el"))
(fn (gensym "bench-multi-lexical-run-")))
(with-temp-file temp-file
(insert ";; -*- lexical-binding: t; -*-" "\n\n"
"(defvar bench-multi-results)" "\n\n"
(format "(defun %s () (bench-multi :times %d :ensure-equal %s :raw %s :forms %S))"
fn ,times ,ensure-equal ,raw ',forms)))
(unwind-protect
(if (byte-compile-file temp-file 'load)
(funcall (intern (symbol-name fn)))
(user-error "Error byte-compiling and loading temp file"))
(delete-file temp-file)
(unintern (symbol-name fn) nil))))
;;; 99-external-misc.el ends here

View File

@@ -1,3 +1,5 @@
;;; -*- mode: lisp-data; -*-
emacs-lisp-mode
(up "(use-package " p n> ":ensure t" n> ":defer t" n ")")