.emacs.d

the most bloated Emacs config on this planet
git clone https://git.trogloxene.org/.emacs.d.git
Log | Files | Refs

init-elisp.el (5566B)


      1 ;;; init-elisp.el --- elisp tools -*- lexical-binding: t -*-
      2 
      3 ;;; Commentary:
      4 
      5 ;;; Code:
      6 
      7 ;; find the source of elisp symbol
      8 (use-package consult-symbol
      9   :straight
     10   (consult-symbol :type git
     11                   :host nil
     12                   :repo "https://git.trogloxene.org/consult-symbol.git")
     13   :init
     14   (defun my-consult-symbol-hack (fun)
     15     (let ((find-file-visit-truename t))
     16       (funcall fun)))
     17   (advice-add #'consult-symbol :around #'my-consult-symbol-hack))
     18 
     19 ;; from Purcell's Emacs configuration
     20 ;; enable some features for lisp files
     21 (defun my-maybe-set-readonly ()
     22   "If this elisp appears to be part of Emacs, then disallow editing."
     23   (when-let* ((file (buffer-file-name))
     24               (part-of-emacs-p (or (string-match-p "\\.el\\.gz\\'" file)
     25                                    (string-match-p find-function-C-source-directory file))))
     26     (read-only-mode 1)))
     27 (add-hook 'find-file-hook #'my-maybe-set-readonly)
     28 
     29 (defun my-enable-check-parens-on-save ()
     30   "Run `check-parens' when the current buffer is saved."
     31   (add-hook 'after-save-hook #'check-parens nil t))
     32 
     33 (defvar my-lispy-modes-hook
     34   '(my-enable-check-parens-on-save)
     35   "Hook run in all Lisp modes.")
     36 
     37 (defun my-lisp-setup ()
     38   "Enable features useful in any Lisp mode."
     39   (run-hooks 'my-lispy-modes-hook))
     40 
     41 (dolist (hook '(emacs-lisp-mode-hook
     42                 ielm-mode-hook lisp-mode-hook
     43                 inferior-lisp-mode-hook lisp-interaction-mode-hook))
     44   (add-hook hook 'my-lisp-setup))
     45 (when (boundp 'eval-expression-minibuffer-setup-hook)
     46   (add-hook 'eval-expression-minibuffer-setup-hook #'eldoc-mode))
     47 
     48 ;; from Purcell's Emacs configuration
     49 (my-use-package ielm
     50   :straight nil
     51   :init
     52   ;; jump between ielm and elisp file
     53   (defvar-local my-repl-original-buffer nil
     54     "Buffer from which we jumped to this REPL.")
     55 
     56   (defvar my-repl-switch-function 'switch-to-buffer)
     57 
     58   (defun my-switch-to-ielm ()
     59     (interactive)
     60     (let ((orig-buffer (current-buffer)))
     61       (if (get-buffer "*ielm*")
     62           (funcall my-repl-switch-function "*ielm*")
     63         (ielm))
     64       (setq my-repl-original-buffer orig-buffer)))
     65 
     66   (defun my-repl-switch-back ()
     67     "Switch back to the buffer from which we reached this REPL."
     68     (interactive)
     69     (if my-repl-original-buffer
     70         (funcall my-repl-switch-function my-repl-original-buffer)
     71       (error "No original buffer"))))
     72 
     73 ;; from Purcell's Emacs configuration
     74 (defun my-elisp-headerise ()
     75   "Add minimal header and footer to an elisp buffer in order to placate flycheck."
     76   (interactive)
     77   (let ((fname (if (buffer-file-name)
     78                    (file-name-nondirectory (buffer-file-name))
     79                  (error "This buffer is not visiting a file"))))
     80     (save-excursion
     81       (goto-char (point-min))
     82       (insert ";;; " fname
     83               (format " --- %s -*- lexical-binding: t -*-\n\n" (file-name-base fname))
     84               ";;; Commentary:\n\n"
     85               ";;; Code:\n\n")
     86       (goto-char (point-max))
     87       (insert "\n;;; " fname " ends here\n"))))
     88 
     89 (defun my-elisp-load-this-file ()
     90   "Load the current file or buffer.
     91 The current directory is temporarily added to `load-path'.  When there
     92 is no current file, eval the current buffer."
     93   (interactive)
     94   (let ((load-path (cons default-directory load-path))
     95         (file (buffer-file-name)))
     96     (if file
     97         (progn
     98           (let ((buf (current-buffer)))
     99             (save-some-buffers nil (lambda () (eq (current-buffer) buf))))
    100           (load-file (buffer-file-name))
    101           (message "Loaded %s" file))
    102       (eval-buffer)
    103       (message "Evaluated %s" (current-buffer)))))
    104 
    105 ;; from Protesilaos's Emacs configuration
    106 (defun my-elisp-eval-and-print-last-sexp ()
    107   "Evaluate and print expression before point like `eval-print-last-sexp'.
    108 Prepend a comment to the return value.  Also copy the return value to
    109 the `kill-ring' and set the mark to where point was before inserting the
    110 return value."
    111   (declare (interactive-only t))
    112   (interactive)
    113   (if-let* ((string (thing-at-point 'sexp :no-properties))
    114             (_ (not (string-prefix-p ";" string)))
    115             (expression (read string)))
    116       (let ((return-value (eval expression)))
    117         (kill-new (format "%S" return-value))
    118         (message "Copied: `%S'" return-value)
    119         (push-mark (point))
    120         (insert (format "\n%S\n" return-value))
    121         (string-insert-rectangle (+ (mark) 1) (- (point) 1) ";; => "))
    122     (user-error "No expression at point")))
    123 
    124 (defvar-keymap my-elisp-macroexpand-mode-map
    125   :doc "keymap for `my-elisp-macroexpand-mode'."
    126   :parent special-mode-map
    127   "C-c C-l p" #'my-elisp-pp-macroexpand-last-sexp)
    128 
    129 (define-derived-mode my-elisp-macroexpand-mode emacs-lisp-mode "MacroExpand"
    130   "Like `emacs-lisp-mode' but for macroexpanded forms."
    131   :interactive nil
    132   (read-only-mode 1)
    133   (display-line-numbers-mode 1))
    134 
    135 (defun my-elisp-pp-macroexpand-last-sexp ()
    136   "Like `pp-macroexpand-last-sexp' but with a generic `display-buffer'.
    137 Now use `display-buffer-alist' like the Lisp gods intended."
    138   (declare (interactive-only t))
    139   (interactive)
    140   (if-let* ((thing (thing-at-point 'sexp :no-properties))
    141             (expression (read thing))
    142             (buffer (get-buffer-create "*my-elisp-macroexpand*"))
    143             (inhibit-read-only t))
    144       (progn
    145         (with-current-buffer buffer
    146           (erase-buffer)
    147           (insert (format "%S" (macroexpand-1 expression)))
    148           (my-elisp-macroexpand-mode)
    149           (pp-buffer))
    150         (display-buffer buffer))
    151     (user-error "No expression to macroexpand")))
    152 
    153 (provide 'init-elisp)
    154 ;;; init-elisp.el ends here