Merge branch 'pu'
[jungerl.git] / lib / distel / elisp / distel-ie.el
bloba554ad3072ce7c8e080ecef248d260067bb5778d
1 ;;;
2 ;;; distel-ie - an interactive erlang shell
3 ;;;
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!"
8 ;;;
9 ;;; So, without any remorse, I hereby declare this code to be:
10 ;;;
11 ;;; copyright (c) 2002 david wallin [david.wallin@ul.ie].
12 ;;;
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))
17 (require 'erlang)
18 (require 'erl)
20 (make-variable-buffer-local
21 (defvar erl-ie-node nil
22 "Erlang node that the session is hosted on."))
25 ;; erl-ie-session
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))
36 (insert "\
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.
43 (push-mark (point) t)
45 (erlang-mode)
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)
56 (current-buffer)))
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)))
70 (erl-spawn
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)
77 (let ((end (point))
78 (beg (save-excursion
79 (loop do (re-search-backward "\\(\\`\\|^\\<\\)")
80 while (looking-at "end"))
81 (point))))
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)
88 (point)))
89 (end (save-excursion (goto-char beg)
90 (erlang-end-of-function)
91 (point))))
92 (erl-ie-evaluate beg end node)))
95 ;; erl-ie-evaluate
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."
103 (interactive (list
104 (region-beginning)
105 (region-end)
106 (erl-ie-read-nodename)))
108 (let* ((string (buffer-substring-no-properties start end))
109 (buffer (current-buffer)))
110 (erl-spawn
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)
119 ((['ok value]
120 (if inline
121 (with-current-buffer buffer
122 ;; Clear "Sent eval request.." message
123 (message "")
125 (unless (looking-at "^")
126 (end-of-line)
127 (insert "\n"))
129 (let ((beg (point)))
130 ;; Insert value, indent all lines of it 4 places,
131 ;; then draw a " => " at the start.
132 (insert value)
133 (save-excursion (indent-rigidly beg (point) 5)
134 (goto-char beg)
135 (delete-region (point) (+ (point) 5))
136 (insert " --> ")))
137 (insert "\n\n")
138 (push-mark (point) t))
139 (display-message-or-view (format "Result: %s" value)
140 "*Evaluation Result*")))
142 (['msg msg]
143 (with-current-buffer buffer
144 (message msg)))
146 (['error reason]
147 (with-current-buffer buffer
149 ;; TODO: should check the buffer for first non-whitespace
150 ;; before we do:
151 (newline 1)
152 (insert "Error: ") (insert reason) (newline 1)))
154 (other
155 (message "Unexpected: %S" other)))))))
158 (defun erl-ie-xor (a b)
159 "Boolean exclusive or of A and B."
160 (or (and a (not b))
161 (and b (not a))))
164 ;; &erl-ie-group-leader-loop
166 (defun &erl-ie-group-leader-loop (buf)
167 (erl-receive (buf)
168 ((['put_chars s]
169 (with-current-buffer buf
170 (insert s))))
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."
204 (interactive (list
205 (region-beginning)
206 (region-end)
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)))
230 (provide 'distel-ie)