-
Notifications
You must be signed in to change notification settings - Fork 0
/
electric-paren.el
114 lines (88 loc) · 3.92 KB
/
electric-paren.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
;;; electric-paren.el --- Evaluate lisp expressions when they are complete -*- lexical-binding: t; -*-
;; Copyright (C) 2020-2021 Robert Church
;; Author: Robert Church <chrchr@gmail.com>
;; Created: 2019-02-14
;; Version: 0.1
;; Package-Requires: ((emacs "24.1"))
;; Homepage: https://github.com/chrchr/electric-paren
;;; Commentary:
;; In ielm, eshell, slime repl, and inferior Lisp mode, this package
;; causes instant evaluation of complete expressions when a closing
;; parenthesis is typed.
;;; Code:
(declare-function sly-mrepl-return "sly")
(declare-function sly-mrepl--mark "sly")
(declare-function sly-input-complete-p "sly")
(declare-function slime-repl-send-input "slime")
(declare-function slime-input-complete-p "slime")
(defvar slime-repl-input-start-mark)
(defvar slime-repl-mode-map)
(defvar sly-mrepl-mode-map)
(defvar inferior-lisp-mode-map)
(defun electric-paren-complete-sexp-p (min max)
"Determine whether the text between locations MIN and MAX represent a complete Lisp expression."
(let ((state
(save-excursion
(end-of-line)
(parse-partial-sexp min max))))
(and (= (car state) 0) (not (nth 3 state)))))
(defun electric-paren-ielm-paren (arg)
"Handle close paren keypresses for ielm. ARG is a character to insert."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(when (electric-paren-complete-sexp-p (ielm-pm) (point))
(ielm-send-input t)))
(defun electric-paren-inferior-lisp-paren (arg)
"Handle close paren keypresses for inferior-lisp-mode. ARG is a character to insert."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(when (electric-paren-complete-sexp-p
(process-mark (get-buffer-process (current-buffer))) (point))
(comint-send-input)))
(defun electric-paren-eshell-paren (arg)
"Handle close paren keypresses for eshell. ARG is a character to insert."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(when (electric-paren-complete-sexp-p eshell-last-output-end (point))
(eshell-send-input)))
(defun electric-paren-eshell-set-keys ()
"Configure the eshell keymap for electric-parens."
(define-key eshell-mode-map (kbd ")") #'electric-paren-eshell-paren))
(defun electric-paren-slime-repl-paren (arg)
"Handle close paren keypresses for slime-repl. ARG is a character to insert."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
;; slime has its own function to determine whether an expression is complete, so use that instead of
;; electric-paren-complete-sexp-p.
(when (slime-input-complete-p slime-repl-input-start-mark (point-max))
(slime-repl-send-input t)))
(defun electric-paren-sly-mrepl-paren (arg)
"Handle close paren keypresses for sly-mrepl. ARG is a character to insert."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
;; sly has its own function to determine whether an expression is complete, so use that instead of
;; electric-paren-complete-sexp-p.
(when (sly-input-complete-p (sly-mrepl--mark) (point-max))
(sly-mrepl-return)))
;;;##autoload
(defun electric-paren-enable ()
"Enable electric-paren in eshell, slime-repl, inferior-lisp-mode, and ielm."
(add-hook 'eshell-first-time-mode-hook #'electric-paren-eshell-set-keys)
(add-hook 'slime-repl-mode-hook
(lambda ()
(define-key slime-repl-mode-map (kbd ")")
#'electric-paren-slime-repl-paren)))
(add-hook 'sly-mrepl-mode-hook
(lambda ()
(define-key sly-mrepl-mode-map (kbd ")")
#'electric-paren-sly-mrepl-paren)))
(add-hook 'inferior-lisp-mode-hook
(lambda ()
(define-key inferior-lisp-mode-map (kbd ")")
#'electric-paren-inferior-lisp-paren)))
(add-hook 'ielm-mode-hook
(lambda ()
(define-key ielm-map (kbd ")")
#'electric-paren-ielm-paren))))
(provide 'electric-paren)
;;; electric-paren.el ends here