Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
16 KiB

4 years ago
  1. ;;; swank-repl.lisp --- Server side part of the Lisp listener.
  2. ;;
  3. ;; License: public domain
  4. (in-package swank)
  5. (defpackage swank-repl
  6. (:use cl swank/backend)
  7. (:export *send-repl-results-function*)
  8. (:import-from
  9. swank
  10. *default-worker-thread-bindings*
  11. *loopback-interface*
  12. add-hook
  13. *connection-closed-hook*
  14. eval-region
  15. with-buffer-syntax
  16. connection
  17. connection.socket-io
  18. connection.repl-results
  19. connection.user-input
  20. connection.user-output
  21. connection.user-io
  22. connection.trace-output
  23. connection.dedicated-output
  24. connection.env
  25. multithreaded-connection
  26. mconn.active-threads
  27. mconn.repl-thread
  28. mconn.auto-flush-thread
  29. use-threads-p
  30. *emacs-connection*
  31. default-connection
  32. with-connection
  33. send-to-emacs
  34. *communication-style*
  35. handle-requests
  36. wait-for-event
  37. make-tag
  38. thread-for-evaluation
  39. socket-quest
  40. authenticate-client
  41. encode-message
  42. auto-flush-loop
  43. clear-user-input
  44. current-thread-id
  45. cat
  46. with-struct*
  47. with-retry-restart
  48. with-bindings
  49. package-string-for-prompt
  50. find-external-format-or-lose
  51. defslimefun
  52. ;; FIXME: those should be exported from swank-repl only, but how to
  53. ;; do that whithout breaking init files?
  54. *use-dedicated-output-stream*
  55. *dedicated-output-stream-port*
  56. *globally-redirect-io*))
  57. (in-package swank-repl)
  58. (defvar *use-dedicated-output-stream* nil
  59. "When T swank will attempt to create a second connection to Emacs
  60. which is used just to send output.")
  61. (defvar *dedicated-output-stream-port* 0
  62. "Which port we should use for the dedicated output stream.")
  63. (defvar *dedicated-output-stream-buffering*
  64. (if (eq *communication-style* :spawn) t nil)
  65. "The buffering scheme that should be used for the output stream.
  66. Valid values are nil, t, :line")
  67. (defvar *globally-redirect-io* :started-from-emacs
  68. "When T globally redirect all standard streams to Emacs.
  69. When :STARTED-FROM-EMACS redirect when launched by M-x slime")
  70. (defun globally-redirect-io-p ()
  71. (case *globally-redirect-io*
  72. ((t) t)
  73. (:started-from-emacs swank-loader:*started-from-emacs*)))
  74. (defun open-streams (connection properties)
  75. "Return the 5 streams for IO redirection:
  76. DEDICATED-OUTPUT INPUT OUTPUT IO REPL-RESULTS"
  77. (let* ((input-fn
  78. (lambda ()
  79. (with-connection (connection)
  80. (with-simple-restart (abort-read
  81. "Abort reading input from Emacs.")
  82. (read-user-input-from-emacs)))))
  83. (dedicated-output (if *use-dedicated-output-stream*
  84. (open-dedicated-output-stream
  85. connection
  86. (getf properties :coding-system))))
  87. (in (make-input-stream input-fn))
  88. (out (or dedicated-output
  89. (make-output-stream (make-output-function connection))))
  90. (io (make-two-way-stream in out))
  91. (repl-results (swank:make-output-stream-for-target connection
  92. :repl-result)))
  93. (typecase connection
  94. (multithreaded-connection
  95. (setf (mconn.auto-flush-thread connection)
  96. (make-auto-flush-thread out))))
  97. (values dedicated-output in out io repl-results)))
  98. (defun make-output-function (connection)
  99. "Create function to send user output to Emacs."
  100. (lambda (string)
  101. (with-connection (connection)
  102. (send-to-emacs `(:write-string ,string)))))
  103. (defun open-dedicated-output-stream (connection coding-system)
  104. "Open a dedicated output connection to the Emacs on SOCKET-IO.
  105. Return an output stream suitable for writing program output.
  106. This is an optimized way for Lisp to deliver output to Emacs."
  107. (let ((socket (socket-quest *dedicated-output-stream-port* nil))
  108. (ef (find-external-format-or-lose coding-system)))
  109. (unwind-protect
  110. (let ((port (local-port socket)))
  111. (encode-message `(:open-dedicated-output-stream ,port
  112. ,coding-system)
  113. (connection.socket-io connection))
  114. (let ((dedicated (accept-connection
  115. socket
  116. :external-format ef
  117. :buffering *dedicated-output-stream-buffering*
  118. :timeout 30)))
  119. (authenticate-client dedicated)
  120. (close-socket socket)
  121. (setf socket nil)
  122. dedicated))
  123. (when socket
  124. (close-socket socket)))))
  125. (defmethod thread-for-evaluation ((connection multithreaded-connection)
  126. (id (eql :find-existing)))
  127. (or (car (mconn.active-threads connection))
  128. (find-repl-thread connection)))
  129. (defmethod thread-for-evaluation ((connection multithreaded-connection)
  130. (id (eql :repl-thread)))
  131. (find-repl-thread connection))
  132. (defun find-repl-thread (connection)
  133. (cond ((not (use-threads-p))
  134. (current-thread))
  135. (t
  136. (let ((thread (mconn.repl-thread connection)))
  137. (cond ((not thread) nil)
  138. ((thread-alive-p thread) thread)
  139. (t
  140. (setf (mconn.repl-thread connection)
  141. (spawn-repl-thread connection "new-repl-thread"))))))))
  142. (defun spawn-repl-thread (connection name)
  143. (spawn (lambda ()
  144. (with-bindings *default-worker-thread-bindings*
  145. (repl-loop connection)))
  146. :name name))
  147. (defun repl-loop (connection)
  148. (handle-requests connection))
  149. ;;;;; Redirection during requests
  150. ;;;
  151. ;;; We always redirect the standard streams to Emacs while evaluating
  152. ;;; an RPC. This is done with simple dynamic bindings.
  153. (defslimefun create-repl (target &key coding-system)
  154. (assert (eq target nil))
  155. (let ((conn *emacs-connection*))
  156. (initialize-streams-for-connection conn `(:coding-system ,coding-system))
  157. (with-struct* (connection. @ conn)
  158. (setf (@ env)
  159. `((*standard-input* . ,(@ user-input))
  160. ,@(unless (globally-redirect-io-p)
  161. `((*standard-output* . ,(@ user-output))
  162. (*trace-output* . ,(or (@ trace-output) (@ user-output)))
  163. (*error-output* . ,(@ user-output))
  164. (*debug-io* . ,(@ user-io))
  165. (*query-io* . ,(@ user-io))
  166. (*terminal-io* . ,(@ user-io))))))
  167. (maybe-redirect-global-io conn)
  168. (add-hook *connection-closed-hook* 'update-redirection-after-close)
  169. (typecase conn
  170. (multithreaded-connection
  171. (setf (mconn.repl-thread conn)
  172. (spawn-repl-thread conn "repl-thread"))))
  173. (list (package-name *package*)
  174. (package-string-for-prompt *package*)))))
  175. (defun initialize-streams-for-connection (connection properties)
  176. (multiple-value-bind (dedicated in out io repl-results)
  177. (open-streams connection properties)
  178. (setf (connection.dedicated-output connection) dedicated
  179. (connection.user-io connection) io
  180. (connection.user-output connection) out
  181. (connection.user-input connection) in
  182. (connection.repl-results connection) repl-results)
  183. connection))
  184. (defun read-user-input-from-emacs ()
  185. (let ((tag (make-tag)))
  186. (force-output)
  187. (send-to-emacs `(:read-string ,(current-thread-id) ,tag))
  188. (let ((ok nil))
  189. (unwind-protect
  190. (prog1 (caddr (wait-for-event `(:emacs-return-string ,tag value)))
  191. (setq ok t))
  192. (unless ok
  193. (send-to-emacs `(:read-aborted ,(current-thread-id) ,tag)))))))
  194. ;;;;; Listener eval
  195. (defvar *listener-eval-function* 'repl-eval)
  196. (defvar *listener-saved-value* nil)
  197. (defslimefun listener-save-value (slimefun &rest args)
  198. "Apply SLIMEFUN to ARGS and save the value.
  199. The saved value should be visible to all threads and retrieved via
  200. LISTENER-GET-VALUE."
  201. (setq *listener-saved-value* (apply slimefun args))
  202. t)
  203. (defslimefun listener-get-value ()
  204. "Get the last value saved by LISTENER-SAVE-VALUE.
  205. The value should be produced as if it were requested through
  206. LISTENER-EVAL directly, so that spacial variables *, etc are set."
  207. (listener-eval (let ((*package* (find-package :keyword)))
  208. (write-to-string '*listener-saved-value*))))
  209. (defslimefun listener-eval (string &key (window-width nil window-width-p))
  210. (if window-width-p
  211. (let ((*print-right-margin* window-width))
  212. (funcall *listener-eval-function* string))
  213. (funcall *listener-eval-function* string)))
  214. (defslimefun clear-repl-variables ()
  215. (let ((variables '(*** ** * /// // / +++ ++ +)))
  216. (loop for variable in variables
  217. do (setf (symbol-value variable) nil))))
  218. (defvar *send-repl-results-function* 'send-repl-results-to-emacs)
  219. (defun repl-eval (string)
  220. (clear-user-input)
  221. (with-buffer-syntax ()
  222. (with-retry-restart (:msg "Retry SLIME REPL evaluation request.")
  223. (track-package
  224. (lambda ()
  225. (multiple-value-bind (values last-form) (eval-region string)
  226. (setq *** ** ** * * (car values)
  227. /// // // / / values
  228. +++ ++ ++ + + last-form)
  229. (funcall *send-repl-results-function* values))))))
  230. nil)
  231. (defun track-package (fun)
  232. (let ((p *package*))
  233. (unwind-protect (funcall fun)
  234. (unless (eq *package* p)
  235. (send-to-emacs (list :new-package (package-name *package*)
  236. (package-string-for-prompt *package*)))))))
  237. (defun send-repl-results-to-emacs (values)
  238. (finish-output)
  239. (if (null values)
  240. (send-to-emacs `(:write-string "; No value" :repl-result))
  241. (dolist (v values)
  242. (send-to-emacs `(:write-string ,(cat (prin1-to-string v) #\newline)
  243. :repl-result)))))
  244. (defslimefun redirect-trace-output (target)
  245. (setf (connection.trace-output *emacs-connection*)
  246. (swank:make-output-stream-for-target *emacs-connection* target))
  247. nil)
  248. ;;;; IO to Emacs
  249. ;;;
  250. ;;; This code handles redirection of the standard I/O streams
  251. ;;; (`*standard-output*', etc) into Emacs. The `connection' structure
  252. ;;; contains the appropriate streams, so all we have to do is make the
  253. ;;; right bindings.
  254. ;;;;; Global I/O redirection framework
  255. ;;;
  256. ;;; Optionally, the top-level global bindings of the standard streams
  257. ;;; can be assigned to be redirected to Emacs. When Emacs connects we
  258. ;;; redirect the streams into the connection, and they keep going into
  259. ;;; that connection even if more are established. If the connection
  260. ;;; handling the streams closes then another is chosen, or if there
  261. ;;; are no connections then we revert to the original (real) streams.
  262. ;;;
  263. ;;; It is slightly tricky to assign the global values of standard
  264. ;;; streams because they are often shadowed by dynamic bindings. We
  265. ;;; solve this problem by introducing an extra indirection via synonym
  266. ;;; streams, so that *STANDARD-INPUT* is a synonym stream to
  267. ;;; *CURRENT-STANDARD-INPUT*, etc. We never shadow the "current"
  268. ;;; variables, so they can always be assigned to affect a global
  269. ;;; change.
  270. ;;;;; Global redirection setup
  271. (defvar *saved-global-streams* '()
  272. "A plist to save and restore redirected stream objects.
  273. E.g. the value for '*standard-output* holds the stream object
  274. for *standard-output* before we install our redirection.")
  275. (defun setup-stream-indirection (stream-var &optional stream)
  276. "Setup redirection scaffolding for a global stream variable.
  277. Supposing (for example) STREAM-VAR is *STANDARD-INPUT*, this macro:
  278. 1. Saves the value of *STANDARD-INPUT* in `*SAVED-GLOBAL-STREAMS*'.
  279. 2. Creates *CURRENT-STANDARD-INPUT*, initially with the same value as
  280. *STANDARD-INPUT*.
  281. 3. Assigns *STANDARD-INPUT* to a synonym stream pointing to
  282. *CURRENT-STANDARD-INPUT*.
  283. This has the effect of making *CURRENT-STANDARD-INPUT* contain the
  284. effective global value for *STANDARD-INPUT*. This way we can assign
  285. the effective global value even when *STANDARD-INPUT* is shadowed by a
  286. dynamic binding."
  287. (let ((current-stream-var (prefixed-var '#:current stream-var))
  288. (stream (or stream (symbol-value stream-var))))
  289. ;; Save the real stream value for the future.
  290. (setf (getf *saved-global-streams* stream-var) stream)
  291. ;; Define a new variable for the effective stream.
  292. ;; This can be reassigned.
  293. (proclaim `(special ,current-stream-var))
  294. (set current-stream-var stream)
  295. ;; Assign the real binding as a synonym for the current one.
  296. (let ((stream (make-synonym-stream current-stream-var)))
  297. (set stream-var stream)
  298. (set-default-initial-binding stream-var `(quote ,stream)))))
  299. (defun prefixed-var (prefix variable-symbol)
  300. "(PREFIXED-VAR \"FOO\" '*BAR*) => SWANK::*FOO-BAR*"
  301. (let ((basename (subseq (symbol-name variable-symbol) 1)))
  302. (intern (format nil "*~A-~A" (string prefix) basename) :swank)))
  303. (defvar *standard-output-streams*
  304. '(*standard-output* *error-output* *trace-output*)
  305. "The symbols naming standard output streams.")
  306. (defvar *standard-input-streams*
  307. '(*standard-input*)
  308. "The symbols naming standard input streams.")
  309. (defvar *standard-io-streams*
  310. '(*debug-io* *query-io* *terminal-io*)
  311. "The symbols naming standard io streams.")
  312. (defun init-global-stream-redirection ()
  313. (when (globally-redirect-io-p)
  314. (cond (*saved-global-streams*
  315. (warn "Streams already redirected."))
  316. (t
  317. (mapc #'setup-stream-indirection
  318. (append *standard-output-streams*
  319. *standard-input-streams*
  320. *standard-io-streams*))))))
  321. (defun globally-redirect-io-to-connection (connection)
  322. "Set the standard I/O streams to redirect to CONNECTION.
  323. Assigns *CURRENT-<STREAM>* for all standard streams."
  324. (dolist (o *standard-output-streams*)
  325. (set (prefixed-var '#:current o)
  326. (connection.user-output connection)))
  327. ;; FIXME: If we redirect standard input to Emacs then we get the
  328. ;; regular Lisp top-level trying to read from our REPL.
  329. ;;
  330. ;; Perhaps the ideal would be for the real top-level to run in a
  331. ;; thread with local bindings for all the standard streams. Failing
  332. ;; that we probably would like to inhibit it from reading while
  333. ;; Emacs is connected.
  334. ;;
  335. ;; Meanwhile we just leave *standard-input* alone.
  336. #+NIL
  337. (dolist (i *standard-input-streams*)
  338. (set (prefixed-var '#:current i)
  339. (connection.user-input connection)))
  340. (dolist (io *standard-io-streams*)
  341. (set (prefixed-var '#:current io)
  342. (connection.user-io connection))))
  343. (defun revert-global-io-redirection ()
  344. "Set *CURRENT-<STREAM>* to *REAL-<STREAM>* for all standard streams."
  345. (dolist (stream-var (append *standard-output-streams*
  346. *standard-input-streams*
  347. *standard-io-streams*))
  348. (set (prefixed-var '#:current stream-var)
  349. (getf *saved-global-streams* stream-var))))
  350. ;;;;; Global redirection hooks
  351. (defvar *global-stdio-connection* nil
  352. "The connection to which standard I/O streams are globally redirected.
  353. NIL if streams are not globally redirected.")
  354. (defun maybe-redirect-global-io (connection)
  355. "Consider globally redirecting to CONNECTION."
  356. (when (and (globally-redirect-io-p) (null *global-stdio-connection*)
  357. (connection.user-io connection))
  358. (unless *saved-global-streams*
  359. (init-global-stream-redirection))
  360. (setq *global-stdio-connection* connection)
  361. (globally-redirect-io-to-connection connection)))
  362. (defun update-redirection-after-close (closed-connection)
  363. "Update redirection after a connection closes."
  364. (check-type closed-connection connection)
  365. (when (eq *global-stdio-connection* closed-connection)
  366. (if (and (default-connection) (globally-redirect-io-p))
  367. ;; Redirect to another connection.
  368. (globally-redirect-io-to-connection (default-connection))
  369. ;; No more connections, revert to the real streams.
  370. (progn (revert-global-io-redirection)
  371. (setq *global-stdio-connection* nil)))))
  372. (provide :swank-repl)