I am trying to twist some code from slime to nrepl. The code is obvious when working with slime. It sends clojure code to evaluate, get the result string and process it as you like. I changed my code so that it can interact with nrepl. That is: creating my own value handler which process the result string and passing it to nrepl-make-response-handler. It works fine until now. But then I found some code which manipulate multiple buffers at once. Since nrepl-make-response-handler accepts only one buffer argument, I was wondering if I could ignore it and invoke my code which process multiple buffers in the value handler. I trid but faild, nothing changed. Any elisp experts there? I really need a help.
My own handler:
(defun nrepl-interactive-eval-read-replace-handler (buffer)
"Make a handler for evaluating and process global replacement."
(nrepl-make-response-handler buffer
(lambda (buffer value)
(let ((sexp (read value)))
(clojure-refactorcng-process-global-replacements sexp)))
'()
(lambda (buffer err)
(message "%s" err))
'()))
The client code:
(defun nrepl-interactive-eval-read-replace (form)
"Evaluate the given FORM and process global replacement"
(let ((buffer (current-buffer)))
(nrepl-send-string form
(nrepl-interactive-eval-read-replace-handler buffer)
nrepl-buffer-ns)))
The code which process the result:
(defun get-from-alist (key alist)
(car (cdr (assoc key alist))))
(defun clojure-refactoring-process-global-replace (replace)
(if (get-from-alist :new-source replace)
(progn
(if (string= (file-truename (buffer-file-name))
(file-truename (get-from-alist :file replace)))
nil
(find-file (get-from-alist :file replace)))
(goto-char (point-min))
(erase-buffer)
(insert (get-from-alist :new-source replace)))))
(defun clojure-refactoring-process-global-replacements (replacements)
(save-window-excursion
(mapcar #'clojure-refactoring-process-global-replace replacements)))
After looking at my code for quite a while, I finally solved this problem. New handler is as follows:
(defun nrepl-interactive-eval-read-replace-handler (buffer)
"Make a handler for evaluating and process global replacement."
(nrepl-make-response-handler buffer
(lambda (buffer value)
(with-current-buffer buffer
(let ((sexp (read value)))
(if sexp
(clojure-refactoring-process-global-replacements sexp)))))
'()
(lambda (buffer err)
(message "%s" err))
'()))
As you see, I added a if condition to exclude the "nil" values returned by nrepl. Also, I added with-current-buffer to specify the buffer I was going to operate on, though, I was not limited to only that buffer. The reason is that in my code below:
(defun clojure-refactoring-process-global-replace (replace)
(if (get-from-alist :new-source replace)
(progn
(if (string= (file-truename (buffer-file-name))
(file-truename (get-from-alist :file replace)))
nil
which buffer I am currently on does matters. I ignored the with-current-buffer before, so buffer-file-name was unaware of the current working buffer which lead to this problem.