Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/contrib/slime-mrepl.el
990 views
1
;; An experimental implementation of multiple REPLs multiplexed over a
2
;; single Slime socket. M-x slime-open-listener creates a new REPL
3
;; buffer.
4
;;
5
;; Some copy&pasting from slime-repl.el
6
7
(define-slime-contrib slime-mrepl
8
"Multiple REPLs."
9
(:authors "Helmut Eller <[email protected]>")
10
(:license "GPL")
11
(:slime-dependencies slime-repl))
12
13
(slime-define-channel-type listener)
14
15
(slime-define-channel-method listener :prompt (package prompt)
16
(with-current-buffer (slime-channel-get self 'buffer)
17
(setf slime-buffer-package package)
18
(letf (((slime-lisp-package-prompt-string) prompt))
19
(slime-repl-insert-prompt))))
20
21
(slime-define-channel-method listener :write-result (result)
22
(letf (((slime-connection-output-buffer) (slime-channel-get self 'buffer)))
23
(slime-repl-emit-result result t)))
24
25
(slime-define-channel-method listener :evaluation-aborted (package prompt)
26
(with-current-buffer (slime-channel-get self 'buffer)
27
(setq slime-buffer-package package)
28
(letf (((slime-connection-output-buffer) (current-buffer))
29
((slime-lisp-package-prompt-string) prompt))
30
(slime-repl-show-abort))))
31
32
(slime-define-channel-method listener :write-string (string)
33
(slime-mrepl-write-string self string))
34
35
(defun slime-mrepl-write-string (self string)
36
(letf (((slime-connection-output-buffer) (slime-channel-get self 'buffer)))
37
(slime-repl-emit string)))
38
39
(byte-compile 'slime-mrepl-write-string)
40
41
(slime-define-channel-method listener :read-string (thread tag)
42
(letf (((slime-connection-output-buffer) (slime-channel-get self 'buffer)))
43
(slime-repl-read-string thread tag)))
44
45
(define-derived-mode slime-mrepl-mode slime-repl-mode "mrepl")
46
47
(slime-define-keys slime-mrepl-mode-map
48
((kbd "RET") 'slime-mrepl-return)
49
([return] 'slime-mrepl-return))
50
51
(defun slime-mrepl-return (&optional end-of-input)
52
"Evaluate the current input string, or insert a newline.
53
Send the current input ony if a whole expression has been entered,
54
i.e. the parenthesis are matched.
55
56
With prefix argument send the input even if the parenthesis are not
57
balanced."
58
(interactive "P")
59
(slime-check-connected)
60
(cond (end-of-input
61
(slime-mrepl-send-input))
62
(slime-repl-read-mode ; bad style?
63
(slime-mrepl-send-input t))
64
((and (get-text-property (point) 'slime-repl-old-input)
65
(< (point) slime-repl-input-start-mark))
66
(slime-repl-grab-old-input end-of-input)
67
(slime-repl-recenter-if-needed))
68
((slime-input-complete-p slime-repl-input-start-mark (point-max))
69
(slime-mrepl-send-input t))
70
(t
71
(slime-repl-newline-and-indent)
72
(message "[input not complete]"))))
73
74
(defun slime-mrepl-send-input (&optional newline)
75
"Goto to the end of the input and send the current input.
76
If NEWLINE is true then add a newline at the end of the input."
77
(unless (slime-repl-in-input-area-p)
78
(error "No input at point."))
79
(goto-char (point-max))
80
(let ((end (point))) ; end of input, without the newline
81
(slime-repl-add-to-input-history
82
(buffer-substring slime-repl-input-start-mark end))
83
(when newline
84
(insert "\n")
85
(slime-repl-show-maximum-output))
86
(let ((inhibit-modification-hooks t))
87
(add-text-properties slime-repl-input-start-mark
88
(point)
89
`(slime-repl-old-input
90
,(incf slime-repl-old-input-counter))))
91
(let ((overlay (make-overlay slime-repl-input-start-mark end)))
92
;; These properties are on an overlay so that they won't be taken
93
;; by kill/yank.
94
(overlay-put overlay 'read-only t)
95
(overlay-put overlay 'face 'slime-repl-input-face)))
96
(let ((input (slime-repl-current-input)))
97
(goto-char (point-max))
98
(slime-mark-input-start)
99
(slime-mark-output-start)
100
(slime-mrepl-send-string input)))
101
102
(defun slime-mrepl-send-string (string &optional command-string)
103
(cond (slime-repl-read-mode
104
(slime-repl-return-string string))
105
(t (slime-mrepl-send `(:eval ,string)))))
106
107
(defun slime-mrepl-send (msg)
108
"Send MSG to the remote channel."
109
(slime-send-to-remote-channel slime-mrepl-remote-channel msg))
110
111
(defun slime-open-listener ()
112
"Create a new listener window."
113
(interactive)
114
(let ((channel (slime-make-channel slime-listener-channel-methods)))
115
(slime-eval-async
116
`(swank:create-listener ,(slime-channel.id channel))
117
(slime-rcurry
118
(lambda (result channel)
119
(destructuring-bind (remote thread-id package prompt) result
120
(pop-to-buffer (generate-new-buffer (slime-buffer-name :listener)))
121
(slime-mrepl-mode)
122
(setq slime-current-thread thread-id)
123
(setq slime-buffer-connection (slime-connection))
124
(set (make-local-variable 'slime-mrepl-remote-channel) remote)
125
(slime-channel-put channel 'buffer (current-buffer))
126
(slime-reset-repl-markers)
127
(slime-channel-send channel `(:prompt ,package ,prompt))
128
(slime-repl-show-maximum-output)))
129
channel))))
130
131
(provide 'slime-mrepl)
132
133