Initial commit
This commit is contained in:
150
elpa/slime-20171102.1213/contrib/slime-mrepl.el
Normal file
150
elpa/slime-20171102.1213/contrib/slime-mrepl.el
Normal file
@@ -0,0 +1,150 @@
|
||||
;; An experimental implementation of multiple REPLs multiplexed over a
|
||||
;; single Slime socket. M-x slime-new-mrepl creates a new REPL buffer.
|
||||
;;
|
||||
(require 'slime)
|
||||
(require 'inferior-slime) ; inferior-slime-indent-lime
|
||||
(require 'cl-lib)
|
||||
|
||||
(define-slime-contrib slime-mrepl
|
||||
"Multiple REPLs."
|
||||
(:authors "Helmut Eller <heller@common-lisp.net>")
|
||||
(:license "GPL")
|
||||
(:swank-dependencies swank-mrepl))
|
||||
|
||||
(require 'comint)
|
||||
|
||||
(defvar slime-mrepl-remote-channel nil)
|
||||
(defvar slime-mrepl-expect-sexp nil)
|
||||
|
||||
(define-derived-mode slime-mrepl-mode comint-mode "mrepl"
|
||||
;; idea lifted from ielm
|
||||
(unless (get-buffer-process (current-buffer))
|
||||
(let* ((process-connection-type nil)
|
||||
(proc (start-process "mrepl (dummy)" (current-buffer) "hexl")))
|
||||
(set-process-query-on-exit-flag proc nil)))
|
||||
(set (make-local-variable 'comint-use-prompt-regexp) nil)
|
||||
(set (make-local-variable 'comint-inhibit-carriage-motion) t)
|
||||
(set (make-local-variable 'comint-input-sender) 'slime-mrepl-input-sender)
|
||||
(set (make-local-variable 'comint-output-filter-functions) nil)
|
||||
(set (make-local-variable 'slime-mrepl-expect-sexp) t)
|
||||
;;(set (make-local-variable 'comint-get-old-input) 'ielm-get-old-input)
|
||||
(set-syntax-table lisp-mode-syntax-table)
|
||||
)
|
||||
|
||||
(slime-define-keys slime-mrepl-mode-map
|
||||
((kbd "RET") 'slime-mrepl-return)
|
||||
([return] 'slime-mrepl-return)
|
||||
;;((kbd "TAB") 'slime-indent-and-complete-symbol)
|
||||
((kbd "C-c C-b") 'slime-interrupt)
|
||||
((kbd "C-c C-c") 'slime-interrupt))
|
||||
|
||||
(defun slime-mrepl-process% () (get-buffer-process (current-buffer))) ;stupid
|
||||
(defun slime-mrepl-mark () (process-mark (slime-mrepl-process%)))
|
||||
|
||||
(defun slime-mrepl-insert (string)
|
||||
(comint-output-filter (slime-mrepl-process%) string))
|
||||
|
||||
(slime-define-channel-type listener)
|
||||
|
||||
(slime-define-channel-method listener :prompt (package prompt)
|
||||
(with-current-buffer (slime-channel-get self 'buffer)
|
||||
(slime-mrepl-prompt package prompt)))
|
||||
|
||||
(defun slime-mrepl-prompt (package prompt)
|
||||
(setf slime-buffer-package package)
|
||||
(slime-mrepl-insert (format "%s%s> "
|
||||
(cl-case (current-column)
|
||||
(0 "")
|
||||
(t "\n"))
|
||||
prompt))
|
||||
(slime-mrepl-recenter))
|
||||
|
||||
(defun slime-mrepl-recenter ()
|
||||
(when (get-buffer-window)
|
||||
(recenter -1)))
|
||||
|
||||
(slime-define-channel-method listener :write-result (result)
|
||||
(with-current-buffer (slime-channel-get self 'buffer)
|
||||
(goto-char (point-max))
|
||||
(slime-mrepl-insert result)))
|
||||
|
||||
(slime-define-channel-method listener :evaluation-aborted ()
|
||||
(with-current-buffer (slime-channel-get self 'buffer)
|
||||
(goto-char (point-max))
|
||||
(slime-mrepl-insert "; Evaluation aborted\n")))
|
||||
|
||||
(slime-define-channel-method listener :write-string (string)
|
||||
(slime-mrepl-write-string self string))
|
||||
|
||||
(defun slime-mrepl-write-string (self string)
|
||||
(with-current-buffer (slime-channel-get self 'buffer)
|
||||
(goto-char (slime-mrepl-mark))
|
||||
(slime-mrepl-insert string)))
|
||||
|
||||
(slime-define-channel-method listener :set-read-mode (mode)
|
||||
(with-current-buffer (slime-channel-get self 'buffer)
|
||||
(cl-ecase mode
|
||||
(:read (setq slime-mrepl-expect-sexp nil)
|
||||
(message "[Listener is waiting for input]"))
|
||||
(:eval (setq slime-mrepl-expect-sexp t)))))
|
||||
|
||||
(defun slime-mrepl-return (&optional end-of-input)
|
||||
(interactive "P")
|
||||
(slime-check-connected)
|
||||
(goto-char (point-max))
|
||||
(cond ((and slime-mrepl-expect-sexp
|
||||
(or (slime-input-complete-p (slime-mrepl-mark) (point))
|
||||
end-of-input))
|
||||
(comint-send-input))
|
||||
((not slime-mrepl-expect-sexp)
|
||||
(unless end-of-input
|
||||
(insert "\n"))
|
||||
(comint-send-input t))
|
||||
(t
|
||||
(insert "\n")
|
||||
(inferior-slime-indent-line)
|
||||
(message "[input not complete]")))
|
||||
(slime-mrepl-recenter))
|
||||
|
||||
(defun slime-mrepl-input-sender (proc string)
|
||||
(slime-mrepl-send-string (substring-no-properties string)))
|
||||
|
||||
(defun slime-mrepl-send-string (string &optional command-string)
|
||||
(slime-mrepl-send `(:process ,string)))
|
||||
|
||||
(defun slime-mrepl-send (msg)
|
||||
"Send MSG to the remote channel."
|
||||
(slime-send-to-remote-channel slime-mrepl-remote-channel msg))
|
||||
|
||||
(defun slime-new-mrepl ()
|
||||
"Create a new listener window."
|
||||
(interactive)
|
||||
(let ((channel (slime-make-channel slime-listener-channel-methods)))
|
||||
(slime-eval-async
|
||||
`(swank-mrepl:create-mrepl ,(slime-channel.id channel))
|
||||
(slime-rcurry
|
||||
(lambda (result channel)
|
||||
(cl-destructuring-bind (remote thread-id package prompt) result
|
||||
(pop-to-buffer (generate-new-buffer (slime-buffer-name :mrepl)))
|
||||
(slime-mrepl-mode)
|
||||
(setq slime-current-thread thread-id)
|
||||
(setq slime-buffer-connection (slime-connection))
|
||||
(set (make-local-variable 'slime-mrepl-remote-channel) remote)
|
||||
(slime-channel-put channel 'buffer (current-buffer))
|
||||
(slime-channel-send channel `(:prompt ,package ,prompt))))
|
||||
channel))))
|
||||
|
||||
(defun slime-mrepl ()
|
||||
(let ((conn (slime-connection)))
|
||||
(cl-find-if (lambda (x)
|
||||
(with-current-buffer x
|
||||
(and (eq major-mode 'slime-mrepl-mode)
|
||||
(eq (slime-current-connection) conn))))
|
||||
(buffer-list))))
|
||||
|
||||
(def-slime-selector-method ?m
|
||||
"First mrepl-buffer"
|
||||
(or (slime-mrepl)
|
||||
(error "No mrepl buffer (%s)" (slime-connection-name))))
|
||||
|
||||
(provide 'slime-mrepl)
|
||||
Reference in New Issue
Block a user