Klimi's new dotfiles with stow.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
5.1 KiB

  1. ;; An experimental implementation of multiple REPLs multiplexed over a
  2. ;; single Slime socket. M-x slime-new-mrepl creates a new REPL buffer.
  3. ;;
  4. (require 'slime)
  5. (require 'inferior-slime) ; inferior-slime-indent-lime
  6. (require 'cl-lib)
  7. (define-slime-contrib slime-mrepl
  8. "Multiple REPLs."
  9. (:authors "Helmut Eller <heller@common-lisp.net>")
  10. (:license "GPL")
  11. (:swank-dependencies swank-mrepl))
  12. (require 'comint)
  13. (defvar slime-mrepl-remote-channel nil)
  14. (defvar slime-mrepl-expect-sexp nil)
  15. (define-derived-mode slime-mrepl-mode comint-mode "mrepl"
  16. ;; idea lifted from ielm
  17. (unless (get-buffer-process (current-buffer))
  18. (let* ((process-connection-type nil)
  19. (proc (start-process "mrepl (dummy)" (current-buffer) "hexl")))
  20. (set-process-query-on-exit-flag proc nil)))
  21. (set (make-local-variable 'comint-use-prompt-regexp) nil)
  22. (set (make-local-variable 'comint-inhibit-carriage-motion) t)
  23. (set (make-local-variable 'comint-input-sender) 'slime-mrepl-input-sender)
  24. (set (make-local-variable 'comint-output-filter-functions) nil)
  25. (set (make-local-variable 'slime-mrepl-expect-sexp) t)
  26. ;;(set (make-local-variable 'comint-get-old-input) 'ielm-get-old-input)
  27. (set-syntax-table lisp-mode-syntax-table)
  28. )
  29. (slime-define-keys slime-mrepl-mode-map
  30. ((kbd "RET") 'slime-mrepl-return)
  31. ([return] 'slime-mrepl-return)
  32. ;;((kbd "TAB") 'slime-indent-and-complete-symbol)
  33. ((kbd "C-c C-b") 'slime-interrupt)
  34. ((kbd "C-c C-c") 'slime-interrupt))
  35. (defun slime-mrepl-process% () (get-buffer-process (current-buffer))) ;stupid
  36. (defun slime-mrepl-mark () (process-mark (slime-mrepl-process%)))
  37. (defun slime-mrepl-insert (string)
  38. (comint-output-filter (slime-mrepl-process%) string))
  39. (slime-define-channel-type listener)
  40. (slime-define-channel-method listener :prompt (package prompt)
  41. (with-current-buffer (slime-channel-get self 'buffer)
  42. (slime-mrepl-prompt package prompt)))
  43. (defun slime-mrepl-prompt (package prompt)
  44. (setf slime-buffer-package package)
  45. (slime-mrepl-insert (format "%s%s> "
  46. (cl-case (current-column)
  47. (0 "")
  48. (t "\n"))
  49. prompt))
  50. (slime-mrepl-recenter))
  51. (defun slime-mrepl-recenter ()
  52. (when (get-buffer-window)
  53. (recenter -1)))
  54. (slime-define-channel-method listener :write-result (result)
  55. (with-current-buffer (slime-channel-get self 'buffer)
  56. (goto-char (point-max))
  57. (slime-mrepl-insert result)))
  58. (slime-define-channel-method listener :evaluation-aborted ()
  59. (with-current-buffer (slime-channel-get self 'buffer)
  60. (goto-char (point-max))
  61. (slime-mrepl-insert "; Evaluation aborted\n")))
  62. (slime-define-channel-method listener :write-string (string)
  63. (slime-mrepl-write-string self string))
  64. (defun slime-mrepl-write-string (self string)
  65. (with-current-buffer (slime-channel-get self 'buffer)
  66. (goto-char (slime-mrepl-mark))
  67. (slime-mrepl-insert string)))
  68. (slime-define-channel-method listener :set-read-mode (mode)
  69. (with-current-buffer (slime-channel-get self 'buffer)
  70. (cl-ecase mode
  71. (:read (setq slime-mrepl-expect-sexp nil)
  72. (message "[Listener is waiting for input]"))
  73. (:eval (setq slime-mrepl-expect-sexp t)))))
  74. (defun slime-mrepl-return (&optional end-of-input)
  75. (interactive "P")
  76. (slime-check-connected)
  77. (goto-char (point-max))
  78. (cond ((and slime-mrepl-expect-sexp
  79. (or (slime-input-complete-p (slime-mrepl-mark) (point))
  80. end-of-input))
  81. (comint-send-input))
  82. ((not slime-mrepl-expect-sexp)
  83. (unless end-of-input
  84. (insert "\n"))
  85. (comint-send-input t))
  86. (t
  87. (insert "\n")
  88. (inferior-slime-indent-line)
  89. (message "[input not complete]")))
  90. (slime-mrepl-recenter))
  91. (defun slime-mrepl-input-sender (proc string)
  92. (slime-mrepl-send-string (substring-no-properties string)))
  93. (defun slime-mrepl-send-string (string &optional command-string)
  94. (slime-mrepl-send `(:process ,string)))
  95. (defun slime-mrepl-send (msg)
  96. "Send MSG to the remote channel."
  97. (slime-send-to-remote-channel slime-mrepl-remote-channel msg))
  98. (defun slime-new-mrepl ()
  99. "Create a new listener window."
  100. (interactive)
  101. (let ((channel (slime-make-channel slime-listener-channel-methods)))
  102. (slime-eval-async
  103. `(swank-mrepl:create-mrepl ,(slime-channel.id channel))
  104. (slime-rcurry
  105. (lambda (result channel)
  106. (cl-destructuring-bind (remote thread-id package prompt) result
  107. (pop-to-buffer (generate-new-buffer (slime-buffer-name :mrepl)))
  108. (slime-mrepl-mode)
  109. (setq slime-current-thread thread-id)
  110. (setq slime-buffer-connection (slime-connection))
  111. (set (make-local-variable 'slime-mrepl-remote-channel) remote)
  112. (slime-channel-put channel 'buffer (current-buffer))
  113. (slime-channel-send channel `(:prompt ,package ,prompt))))
  114. channel))))
  115. (defun slime-mrepl ()
  116. (let ((conn (slime-connection)))
  117. (cl-find-if (lambda (x)
  118. (with-current-buffer x
  119. (and (eq major-mode 'slime-mrepl-mode)
  120. (eq (slime-current-connection) conn))))
  121. (buffer-list))))
  122. (def-slime-selector-method ?m
  123. "First mrepl-buffer"
  124. (or (slime-mrepl)
  125. (error "No mrepl buffer (%s)" (slime-connection-name))))
  126. (provide 'slime-mrepl)