feat: Progress towards comfortable Lisp editing

This commit is contained in:
Madeleine Sydney
2025-02-02 14:51:04 -07:00
parent a345b5a72d
commit fc14c41edd
11 changed files with 623 additions and 39 deletions

View File

@@ -3,6 +3,7 @@
(require 'syd-handle-repl)
(require 'syd-handle-lookup)
(require 'syd-handle-eval)
(require 'syd-lisp-lib)
;; (require 'handle)
;; Don't `use-package' `ielm', since it's loaded by Emacs. You'll get weird
@@ -12,6 +13,7 @@
:custom ((ielm-history-file-name ; Stay out of my config dir!
(file-name-concat syd-cache-dir "ielm-history.eld"))))
;;;###autoload
(defun syd/open-emacs-lisp-repl ()
(interactive)
(pop-to-buffer
@@ -23,21 +25,19 @@
(bury-buffer b)
b)))))
;;;###autoload
(defun syd-emacs-lisp-lookup-documentation (identifier)
"Lookup IDENTIFIER with `describe-symbol'"
;; HACK: Much to my frustration, `describe-symbol' has no defined
;; return value. To test if the call was successful or not, we
;; check if any window is displaying the help buffer. This probably
;; breaks if `syd-emacs-lisp-lookup-documentation' is called while
;; the help buffer is already open.
;; HACK: Much to my frustration, `describe-symbol' has no defined return
;; value. To test if the call was successful or not, we check if any window
;; is displaying the help buffer. This probably breaks if
;; `syd-emacs-lisp-lookup-documentation' is called while the help buffer is
;; already open.
(describe-symbol (intern identifier))
(let ((buffer (get-buffer (help-buffer))))
(and (get-buffer-window-list buffer)
buffer)))
(set-repl-handler! 'emacs-lisp-mode
#'syd/open-emacs-lisp-repl)
;;;###autoload
(defun syd-emacs-lisp-eval (beg end)
"Evaluate a region and print it to the echo area (if one line long), otherwise
@@ -60,13 +60,35 @@ to a pop up buffer."
:source-buffer (current-buffer)
:force-popup current-prefix-arg))
(set-repl-handler! 'emacs-lisp-mode
#'syd/open-emacs-lisp-repl)
(set-eval-handler! 'emacs-lisp-mode
#'syd-emacs-lisp-eval)
(defun syd-emacs-set-handlers ()
(add-hook 'emacs-lisp-mode-hook #'syd-lisp-mode)
(defun syd-emacs-set-handlers-h ()
(setq-local syd-lookup-documentation-handlers
(list #'syd-emacs-lisp-lookup-documentation)))
(add-hook 'emacs-lisp-mode-hook #'syd-emacs-set-handlers)
(add-hook 'emacs-lisp-mode-hook #'syd-emacs-set-handlers-h)
(add-hook 'help-mode-hook #'syd-emacs-set-handlers-h)
;; Semantic highlighting for Elisp.
(use-package highlight-defined
:hook (emacs-lisp-mode-hook . highlight-defined-mode))
;; Automatically and inteligently expand abbreviations. E.g. `wcb` will be
;; expanded to `(with-current-buffer)`, but only where it makes sense for a
;; function/macro call to be.
(use-package sotlisp
:straight (:host github
:repo "Malabarba/speed-of-thought-lisp")
:hook (emacs-lisp-mode . speed-of-thought-mode))
;; Give different pairs of delimiters different colours.
(use-package rainbow-delimiters
:hook (emacs-lisp-mode . rainbow-delimiters-mode))
(provide 'syd-lang-emacs-lisp)

View File

@@ -0,0 +1,11 @@
;;; syd-editing.el -*- lexical-binding: t; -*-
(use-package emacs
:hook ((on-init-ui-hook . whitespace-mode))
:custom ((fill-column 80)
(indent-tabs-mode nil)
(whitespace-style '(face tabs tab-mark))
;; Disable synchronization between the kill ring and clipboard.
(select-enable-clipboard nil)))
(provide 'syd-editing)

View File

@@ -1,5 +1,8 @@
;;; syd-eshell.el -*- lexical-binding: t; -*-
(require 'ring)
(require 'cl-lib)
(defvar eshell-buffer-name "*eshell*")
(defvar syd-eshell-buffers (make-ring 25)
@@ -72,7 +75,11 @@
(eshell-kill-processes-on-exit t)
(eshell-hist-ignoredups t)
(eshell-glob-case-insensitive t)
(eshell-error-if-no-glob t))
(eshell-error-if-no-glob t)
(eshell-history-file-name (file-name-concat
syd-data-dir "eshell" "history"))
(eshell-last-dir-ring-file-name (file-name-concat
syd-data-dir "eshell" "lastdir")))
:general
(:keymaps 'syd-leader-open-map
"e" #'syd-eshell/toggle)
@@ -80,6 +87,7 @@
:states '(normal insert)
"C-j" #'eshell-next-matching-input-from-input
"C-k" #'eshell-previous-matching-input-from-input)
:config
(require 'syd-buffers)

View File

@@ -1,5 +1,9 @@
;;; syd-evil.el -*- lexical-binding: t; -*-
;; More sensible undo functionality. Emacs' default is very weird, not
;; maintaining a proper history.
(use-package undo-fu)
;; Vim emulation.
(use-package evil
:preface
@@ -60,18 +64,24 @@ Otherwise, nil."
nil)))
(add-hook 'syd-escape-hook #'syd-evil-nohl-h)
(general-def
:states 'motion
"/" #'evil-ex-search-forward
"?" #'evil-ex-search-backward
"n" #'evil-ex-search-next
"N" #'evil-ex-search-previous
"*" #'evil-ex-search-word-forward)
(evil-mode 1))
(defvar evil-collection-key-blacklist)
;; A large, community-sourced collection of preconfigured Evil-mode
;; integrations.
(use-package evil-collection
:after evil
:defer t
;; :after evil
;; :defer t
:custom (evil-collection-setup-minibuffer t)
:config
:preface
(defvar evil-collection-key-blacklist)
(unless noninteractive
(defvar syd-evil-collection-disabled-list
'(anaconda-mode buff-menu calc comint company custom eldoc elisp-mode ert
@@ -314,4 +324,29 @@ modules."
:bind (:map evil-visual-state-map
("*" . evil-visualstar/begin-search-forward)))
(defvar syd-evil-last-eval-expression-register ?e
"An Evil-mode register in which the last expression evaluated with an
interactive call to `eval-expression' is stored.")
(with-eval-after-load 'evil
(defun syd-set-eval-expression-register-a (expr &rest _)
"If called interactively, set the register
`syd-evil-last-eval-expression-register' to a printed form of EXPR."
(when (called-interactively-p 'interactive)
(->> (pp-to-string expr)
(string-remove-suffix "\n")
(evil-set-register syd-evil-last-eval-expression-register))))
(advice-add #'eval-expression
:after #'syd-set-eval-expression-register-a))
;; HACK: '=' unpredictably moves the cursor when it really doesn't need to.
(defun syd-evil-dont-move-point-a (fn &rest args)
"Used as :around advice on Evil operators to avoid moving the point."
;; We don't use `save-excursion', as we /only/ want to restore the point.
(save-excursion (apply fn args)))
(with-eval-after-load 'evil
(advice-add #'evil-indent
:around #'syd-evil-dont-move-point-a))
(provide 'syd-evil)

View File

@@ -108,13 +108,6 @@ all hooks after it are ignored.")
(global-set-key [remap keyboard-quit] #'syd/escape)
(general-def
:states 'motion
"/" #'evil-ex-search-forward
"?" #'evil-ex-search-backward
"n" #'evil-ex-search-next
"N" #'evil-ex-search-previous)
;; Buffer
(require 'syd-buffers)
(general-def