From e32b87f92122e31d8c89758dab3e3251967fdf6e Mon Sep 17 00:00:00 2001 From: Vladislav Slobodenyuk Date: Mon, 26 Jan 2026 12:15:56 +0900 Subject: [PATCH] Minor fixes and additions Fix consult, tempel keybind, add benchmark macros, some rust templates --- .config.d/10-completion.el | 4 +- .config.d/15-lsp.el | 2 +- .config.d/99-external-misc.el | 178 +++++++++++++++++++++++++++++++++ .config.d/99-external-misc.elc | Bin 0 -> 5319 bytes .gitignore | 1 + templates | 7 ++ 6 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 .config.d/99-external-misc.el create mode 100644 .config.d/99-external-misc.elc diff --git a/.config.d/10-completion.el b/.config.d/10-completion.el index 8aefc72..3c41292 100644 --- a/.config.d/10-completion.el +++ b/.config.d/10-completion.el @@ -225,8 +225,8 @@ consult-theme :preview-key '(:debounce 0.2 any) consult-ripgrep consult-git-grep consult-grep consult-bookmark consult-recent-file consult-xref - consult--source-bookmark consult--source-file-register - consult--source-recent-file consult--source-project-recent-file + consult-source-bookmark consult-source-file-register + consult-source-recent-file consult-source-project-recent-file ;; :preview-key "M-." :preview-key '(:debounce 0.4 any)) (setq consult-narrow-key "<")) diff --git a/.config.d/15-lsp.el b/.config.d/15-lsp.el index 6121b88..45cc223 100644 --- a/.config.d/15-lsp.el +++ b/.config.d/15-lsp.el @@ -170,7 +170,7 @@ control codes are not supported." ;; Configure Tempel (use-package tempel - :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand + :bind (("C-S-e" . tempel-complete) ;; Alternative tempel-expand ("M-*" . tempel-insert)) :init diff --git a/.config.d/99-external-misc.el b/.config.d/99-external-misc.el new file mode 100644 index 0000000..200cfbd --- /dev/null +++ b/.config.d/99-external-misc.el @@ -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 diff --git a/.config.d/99-external-misc.elc b/.config.d/99-external-misc.elc new file mode 100644 index 0000000000000000000000000000000000000000..e75bdf852b29b3a8c1ba67d86e335a846110e7e3 GIT binary patch literal 5319 zcmcIo`)}LG5td&}qTmvs=nr=VdN-lZ5t*6>xzxjF-vPE`*$A36sO>a3Lb@qiGHmAd$N}J3H@hR=e%jFMq65D%IWHU3!@gM^P+8HHZ>w4})G# zpJbLtX+plY&DjkRf#?_DSkNB4&B7P(@k|KBZBJt>dI%Qu!Ij^UGz)_j(ZZ29!t{ zP7i>q;3@Xdb9P^v1Tk4!CC}xLP0uq4Em+~(4pi2mnuWl~Quu29gD1ANC*czRy9)bs zX}=?yV!0#g0+ZrNr32&R>)|W#_3^Fa+rYPJ82I&!M+fbrcIj0u1dX!vG9jx}1g=ol zv9*C~mU)&I5FB1Y1WJ?4bxQkm{4&R@UOIj`UA3t;fGOdCh3-8k&nx3dG+PKidws9v zZPSVJs&b%qCxST80;o8ca)bZ#aa`oe-$!px-kfe#PsT}3>RkuTynuN>7meDpA&G&|sEl5aa84keSEQoRh zSJdatHw2=jR?vm~I1b|47QIsQQ>Iw1=2(NlWUkK(qkdmv7YDK|t|jCHry=vs2kCX9 z^sHWBmop=+O;kDAfB&Th!S(dOewGfa_Zo>+(@DlEBzYl&kR1*MIlq*9s+@Z`uGFL- zWe8#!%b`pPMa%9{;s%r#8Pa4ENnFcm%yxlqp-q)ZFcr$YmqjW)aGWx?^0qUCpChOA z_b#Q_lU>8Gn~Hf}WkHkiunR+l#5$1+kq&f5%K*tZ5dxvRNf&qGyT&%+#Frtqok}?= z9ULVAB;{fuKL^86EJ2{M_zK>fB(PnE!mYr8={b+PH-$tVg%TNiCneX_gf7MXanj?m z;EcwFP8bgPkrO2$4CzdkVIsVqQ~g%4o-@*dI>A+#^Sy)O?=~NDWe|V>OfTcd@0fb9 zf0w|6W<% zTSm1JzRw$0jfdL|K6MvFO%y9vysj)Q9q^W=6;;7jm(I#U<_a5?t=VKgV9>%TC}186 zn8$)(EL`IOej$et#v{y4rBTx1z%?aRM>PD(ni6bn#dr!JgM^xufbgQehM$J<7vl$g zmT166qG>!bI(@vf4h|q8s;CgHiqT2h?e?+~d3jBVY^*4eS8*sRE`$JW0?{$j;@4UH zgO2aJ2M33T-~fuoFYt*E(S5-aJ`Cjh(9ef{KJ-)iVh*PA>maKOje~gRl<5 zItc49gx@s2Z)-_slMUDSp`65{0Uiz5r@`LBmIhcfz@h;b4UC&Or^)ANcF(Y-3348S z(K-)tG+W{pDb_mX94#dIc}Ckl}aC(ouG zt_?Zu$RrwvED+6&eh`1ZnhnxjyEL zUW!mwn9ss0{tDxukMk(NK)-cud|2r?O-CABetEt~|Ozb3C`gLd-$zOcIbTa2{AsLkNS4Xn9R+|qsi;sn4| zkPT>LI6KA|1(~rB$Xk9_4dXp3oS#=#jR)Hb;Z_;C#cw>j!B7wIaTTEH)*mx1;{nR% zHY0iqFMGgpfQhM4afQ18lxjvYtTFMT z*~LEGXqo0GK8)AhW$1**%08Y`8YX!$PXfKM8(WB9a2+mh%D-~h$2T+#MyN68)I{f& zbQ0C|sVmz4$?>Ueo}=J%**B-Tz&H{VWNvJUzKJrT?%fzQG1B*GeLu#{r&->7fbAT; z>wB>FBzmW(9Bz_aI)JHm<7ONBKvksPckh z&p5@s_ax(|nfd%{+w0l?9CPwIrE>qTW?1LPtp<3~n(`CPOxd13HJ%tx(7JfWpAI<- z9`KLB&5Y1ZC5PR&^(MM&u-L7Ra;t@K>mmGf(=eMi7Z}DdZ8EoHY%&I+5CW=nr?ZF_ z9s@ln`TFh57|-5tHI!&eO#GeYykLC46 ":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> "}")