]> git.earman.xyz Git - emacsinit.git/commitdiff
Auto-Balance parens with ']' in REPLs
authorrearman <rearman@r717.net>
Fri, 28 Jun 2024 21:11:31 +0000 (17:11 -0400)
committerrearman <rearman@r717.net>
Fri, 28 Jun 2024 21:11:31 +0000 (17:11 -0400)
re/re-bindings.el
re/re-repl-defuns.el

index cf1b137232d61e4055f5f20768671c6b596c2c5d..1dd9b125fac52bf24935574122b92a7992b32926 100644 (file)
 (keymap-global-set "C-M-S-q" (lambda ()
                                (interactive)
                                (indent-pp-sexp t)))
+(defvar *re/lisp-mode-hooks*
+  '(emacs-lisp-mode-hook
+    lisp-mode-hook
+    slime-mode-hook
+    scheme-mode-hook))
+
+(dolist (hook *re/lisp-mode-hooks*)
+  (add-hook hook
+            (lambda ()
+              (keymap-set lisp-mode-shared-map "]" (re/balance-and-eval-sexp #'newline)))))
+
+(add-hook 'lisp-interaction-mode-hook
+          (lambda ()
+            (keymap-set lisp-interaction-mode-map "]" (re/balance-and-eval-sexp #'eval-print-last-sexp))))
 
 ;; IELM
 (keymap-global-set "C-c i" #'ielm)
@@ -72,7 +86,7 @@
           (lambda ()
             (keymap-set inferior-emacs-lisp-mode-map "C-l" #'comint-clear-buffer)
             (keymap-set inferior-emacs-lisp-mode-map ")" (re/send-on-close-paren #'ielm-send-input))
-            (keymap-set inferior-emacs-lisp-mode-map "]" #'re/insert-all-parens)))
+            (keymap-set inferior-emacs-lisp-mode-map "]" (re/balance-and-eval-sexp #'ielm-send-input))))
 
 ;; Eshell
 (keymap-global-set "C-c e" #'eshell)
           (lambda ()
             (keymap-set eshell-mode-map "C-d" #'eshell-quit-or-delete-char)
             (keymap-set eshell-mode-map ")" (re/send-on-close-paren #'eshell-send-input))
-            (keymap-set eshell-mode-map "]" #'re/insert-all-parens)))
+            (keymap-set eshell-mode-map "]" (re/balance-and-eval-sexp #'eshell-send-input))))
 
 ;; SLIME REPL
 (add-hook 'slime-repl-mode-hook
           (lambda ()
             (keymap-set slime-repl-mode-map ")" (re/send-on-close-paren #'slime-repl-return))
-            (keymap-set slime-repl-mode-map "]" #'re/insert-all-parens)))
+            (keymap-set slime-repl-mode-map "]" (re/balance-and-eval-sexp #'slime-repl-return))))
 
 ;; Org Starters
 (keymap-global-set "C-c l" #'org-store-link)
index 30c6e40668abe6ac26e215e54f32afeb909785c4..5d3aae382e1e6a2332c11981feb5e11fd682bb6b 100644 (file)
@@ -6,21 +6,44 @@
 ;; Any Lisp Repl
 (defmacro re/send-on-close-paren (executor)
   "Generalizes sending an execute on close paren.
-When a sexp is complete - that is when parens balance as you type - execute it.
-Use this macro as a direct binding"
+ Interactively call `executor'.  For `executor', use whatever
+ function is called by `<RET>' in the applicable REPL.  For a
+ non-repl, use `newline' or similar."
+  `(lambda (&optional arg)
+     (interactive "p")
+     (insert-char 41 arg)
+     (call-interactively ,executor)))
+
+(defun re/sexp-drop-paren-p ()
+  "Returns t if sexp needs fewer parens to balance."
+  (<0 (car (syntax-ppss))))
+
+(defun re/sexp-need-paren-p ()
+  "Returns t if sexp needs more parens to balance."
+  (>0 (car (syntax-ppss))))
+
+(defun re/sexp-unbalanced-count ()
+  "Returns distance from balanced sexp."
+  (abs (car (syntax-ppss))))
+
+(defun re/balance-sexp ()
+  "Balance the sexp before point.
+Either delete or add as many ')' as needed."
+  (let ((distance (re/sexp-unbalanced-count)))
+    (cond
+     ((re/sexp-need-paren-p) (insert-char 41 distance))
+     ((re/sexp-drop-paren-p) (backward-delete-char distance)))))
+
+(defmacro re/balance-and-eval-sexp (executor)
+  "Balance the sexp before point, then call `executor'.
+Call `re/balance-sexp', then interactively call `executor'.  Bind
+this to ']' for the interlisp experience.  For `executor', use
+whatever function is called by `<RET>' in the applicable REPL.
+For a non-repl, use `newline' or similar."
   `(lambda ()
      (interactive)
-     (insert-char 41)
-     (when (= 0 (car (syntax-ppss)))
-       (call-interactively ,executor))))
-
-(defun re/insert-all-parens ()
-  "Inserts all the parens needed to balance a sexp.
-If multiple parens are needed at the end to balance a sexp, insert them.
-Bind this to ']' for the interlisp experience."
-  (interactive)
-  (while (>0 (car (syntax-ppss)))
-    (insert-char 41)))
+     (re/balance-sexp)
+     (call-interactively ,executor)))
 
 ;; Eshell
 (defun eshell-quit-or-delete-char (arg)