diff --git a/.config.d/15-lsp.el b/.config.d/15-lsp.el index 45cc223..8715086 100644 --- a/.config.d/15-lsp.el +++ b/.config.d/15-lsp.el @@ -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)))) diff --git a/.config.d/99-external-misc.el b/.config.d/99-external-misc.el deleted file mode 100644 index 200cfbd..0000000 --- a/.config.d/99-external-misc.el +++ /dev/null @@ -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 diff --git a/templates b/templates index 6538397..23c14a3 100644 --- a/templates +++ b/templates @@ -1,3 +1,5 @@ +;;; -*- mode: lisp-data; -*- + emacs-lisp-mode (up "(use-package " p n> ":ensure t" n> ":defer t" n ")")