2 ;;; distel-ie - an interactive erlang shell
4 ;;; Some of the code has shamelessly been stolen from Luke Gorrie
5 ;;; [luke@bluetail.com] - ripped from its elegance and replaced by bugs.
6 ;;; It just goes to show that you can't trust anyone these days. And
7 ;;; as if that wasn't enough, I'll even blame Luke: "He _made_ me do it!"
9 ;;; So, without any remorse, I hereby declare this code to be:
11 ;;; copyright (c) 2002 david wallin [david.wallin@ul.ie].
13 ;;; (it's probably going to be released onto an unexpecting public under
14 ;;; some sort of BSD license).
16 (eval-when-compile (require 'cl
))
20 (make-variable-buffer-local
21 (defvar erl-ie-node nil
22 "Erlang node that the session is hosted on."))
27 (defun erl-ie-session (node)
28 "Return the erl-ie-session for NODE, creating it if necessary."
29 (interactive (list (erl-ie-read-nodename)))
31 (or (get-buffer (erl-ie-buffer-name node
))
32 (erl-ie-create-session node
)))
34 (defun erl-ie-create-session (node)
35 (with-current-buffer (get-buffer-create (erl-ie-buffer-name node
))
37 %%% Welcome to the Distel Interactive Erlang Shell.
39 %% C-j evaluates an expression and prints the result in-line.
40 %% C-M-x evaluates a whole function definition.
46 (erl-session-minor-mode 1)
47 (setq erl-ie-node node
)
49 ;; hiijack stdin/stdout :
50 (let ((output-buffer (current-buffer)))
51 (setq erl-group-leader
52 (erl-spawn (&erl-ie-group-leader-loop output-buffer
))))
54 (erl-ie-ensure-registered node
)
58 (defun erl-ie-read-nodename ()
59 "Get the node for the session, either from buffer state or from the user."
60 (or erl-ie-node
(erl-target-node)))
62 (defun erl-ie-buffer-name (node)
63 (format "*ie session <%S>*" node
))
66 ;; erl-ie-ensure-registered
68 (defun erl-ie-ensure-registered (node)
69 (interactive (list (erl-ie-read-nodename)))
71 (erl-send-rpc node
'distel_ie
'ensure_registered
'())))
74 (defun erl-ie-eval-expression (node)
75 (interactive (list (erl-ie-read-nodename)))
76 (erl-ie-read-nodename)
79 (loop do
(re-search-backward "\\(\\`\\|^\\<\\)")
80 while
(looking-at "end"))
82 (erl-ie-evaluate beg end node t
)))
84 (defun erl-ie-eval-defun (node)
85 (interactive (list (erl-ie-read-nodename)))
86 (erl-ie-read-nodename)
87 (let* ((beg (save-excursion (erlang-beginning-of-function)
89 (end (save-excursion (goto-char beg
)
90 (erlang-end-of-function)
92 (erl-ie-evaluate beg end node
)))
97 ;; this is doomed to fail, can end be the smaller value ?
98 ;; want to change to (interactive "r") somehow ...
100 (defun erl-ie-evaluate (start end node
&optional inline
)
101 "Evaluate region START to END on NODE.
102 The marked region can be a function definition, a function call or an expression."
106 (erl-ie-read-nodename)))
108 (let* ((string (buffer-substring-no-properties start end
))
109 (buffer (current-buffer)))
111 (erl-send (tuple 'distel_ie node
)
112 (tuple 'evaluate erl-self string
))
114 (message "Sent eval request..")
116 ;; move cursor to after the marked region
117 (goto-char (min (point-max) (1+ end
)))
118 (erl-receive (buffer inline
)
121 (with-current-buffer buffer
122 ;; Clear "Sent eval request.." message
125 (unless (looking-at "^")
130 ;; Insert value, indent all lines of it 4 places,
131 ;; then draw a " => " at the start.
133 (save-excursion (indent-rigidly beg
(point) 5)
135 (delete-region (point) (+ (point) 5))
138 (push-mark (point) t
))
139 (display-message-or-view (format "Result: %s" value
)
140 "*Evaluation Result*")))
143 (with-current-buffer buffer
147 (with-current-buffer buffer
149 ;; TODO: should check the buffer for first non-whitespace
152 (insert "Error: ") (insert reason
) (newline 1)))
155 (message "Unexpected: %S" other
)))))))
158 (defun erl-ie-xor (a b
)
159 "Boolean exclusive or of A and B."
164 ;; &erl-ie-group-leader-loop
166 (defun &erl-ie-group-leader-loop
(buf)
169 (with-current-buffer buf
171 (&erl-ie-group-leader-loop buf
)))
175 ;; erl-ie-show-session
177 (defun erl-ie-show-session (node)
178 "Show the session for NODE, creating if necessary."
179 (interactive (list (erl-ie-read-nodename)))
180 (switch-to-buffer (erl-ie-session node
)))
183 ;; erl-ie-copy-buffer-to-session
185 (defun erl-ie-copy-buffer-to-session (node)
186 "Open a distel_ie session on NODE with the content of the current buffer.
187 The content is pasted at the end of the session buffer. This can be useful
188 for debugging a file without ruining the content by mistake."
189 (interactive (list (erl-ie-read-nodename)))
190 (let ((cloned-buffer (buffer-string)))
192 (with-current-buffer (erl-ie-session node
)
193 (goto-char (point-max))
194 (insert cloned-buffer
))
195 (erl-ie-popup-buffer node
)))
198 ;; erl-ie-copy-region-to-session
200 (defun erl-ie-copy-region-to-session (start end node
)
201 "Open a distel_ie session on NODE with the content of the region.
202 The content is pasted at the end of the session buffer. This can be useful
203 for debugging a file without ruining the content by mistake."
207 (erl-ie-read-nodename)))
208 (let ((cloned-region (buffer-substring-no-properties start end
)))
210 (with-current-buffer (erl-ie-session node
)
211 (goto-char (point-max))
212 (set-mark (point)) ; so the region will be right
213 (insert cloned-region
))
214 (erl-ie-popup-buffer node
)))
217 (defun erl-ie-popup-buffer (node)
218 (switch-to-buffer (erl-ie-session node
)))
220 ;; ------------------------------------------------------------
221 ;; Session minor mode.
223 (define-minor-mode erl-session-minor-mode
224 "Minor mode for Distel Interactive Sessions."
227 '(("\C-j" . erl-ie-eval-expression
)
228 ("\C-\M-x" . erl-ie-eval-defun
)))