Minor fixes and additions

Fix consult, tempel keybind, add benchmark macros, some rust templates
This commit is contained in:
2026-01-26 12:15:56 +09:00
parent 2b65287a62
commit e32b87f921
6 changed files with 189 additions and 3 deletions

View File

@@ -225,8 +225,8 @@
consult-theme :preview-key '(:debounce 0.2 any) consult-theme :preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-file-register consult-source-bookmark consult-source-file-register
consult--source-recent-file consult--source-project-recent-file consult-source-recent-file consult-source-project-recent-file
;; :preview-key "M-." ;; :preview-key "M-."
:preview-key '(:debounce 0.4 any)) :preview-key '(:debounce 0.4 any))
(setq consult-narrow-key "<")) (setq consult-narrow-key "<"))

View File

@@ -170,7 +170,7 @@ control codes are not supported."
;; Configure Tempel ;; Configure Tempel
(use-package tempel (use-package tempel
:bind (("M-+" . tempel-complete) ;; Alternative tempel-expand :bind (("C-S-e" . tempel-complete) ;; Alternative tempel-expand
("M-*" . tempel-insert)) ("M-*" . tempel-insert))
:init :init

View File

@@ -0,0 +1,178 @@
;;; 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

Binary file not shown.

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@
!.config.d/ !.config.d/
!.config.d/* !.config.d/*
!templates !templates
!load/

View File

@@ -1,3 +1,10 @@
emacs-lisp-mode emacs-lisp-mode
(up "(use-package " p n> ":ensure t" n> ":defer t" n ")") (up "(use-package " p n> ":ensure t" n> ":defer t" n ")")
rust-mode
(str "struct " p " {" n> p n> "}")
(imp "impl " p " {" n> p n> "}")
(impf "impl " p " for " p " {" n> p n> "}")
(trt "trait " p " {" n> p n> "}")