Klimi's new dotfiles with stow.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

1805 рядки
68 KiB

4 роки тому
  1. ;;; slime-repl.el ---
  2. ;;
  3. ;; Original Author: Helmut Eller
  4. ;; Contributors: too many to mention
  5. ;; License: GNU GPL (same license as Emacs)
  6. ;;
  7. ;;; Description:
  8. ;;
  9. ;;
  10. ;;; Installation:
  11. ;;
  12. ;; Call slime-setup and include 'slime-repl as argument:
  13. ;;
  14. ;; (slime-setup '(slime-repl [others conribs ...]))
  15. ;;
  16. (require 'slime)
  17. (require 'slime-parse)
  18. (require 'cl-lib)
  19. (eval-when-compile (require 'cl)) ; slime-def-connection-var, which
  20. ; expands to defsetf not in cl-lib
  21. (define-slime-contrib slime-repl
  22. "Read-Eval-Print Loop written in Emacs Lisp.
  23. This contrib implements a Lisp Listener along with some niceties like
  24. a persistent history and various \"shortcut\" commands. Nothing here
  25. depends on comint.el; I/O is multiplexed over SLIME's socket.
  26. This used to be the default REPL for SLIME, but it was hard to
  27. maintain."
  28. (:authors "too many to mention")
  29. (:license "GPL")
  30. (:on-load
  31. (slime-repl-add-hooks)
  32. (setq slime-find-buffer-package-function 'slime-repl-find-buffer-package))
  33. (:on-unload (slime-repl-remove-hooks))
  34. (:swank-dependencies swank-repl))
  35. ;;;;; slime-repl
  36. (defgroup slime-repl nil
  37. "The Read-Eval-Print Loop (*slime-repl* buffer)."
  38. :prefix "slime-repl-"
  39. :group 'slime)
  40. (defcustom slime-repl-shortcut-dispatch-char ?\,
  41. "Character used to distinguish repl commands from lisp forms."
  42. :type '(character)
  43. :group 'slime-repl)
  44. (defcustom slime-repl-only-save-lisp-buffers t
  45. "When T we only attempt to save lisp-mode file buffers. When
  46. NIL slime will attempt to save all buffers (as per
  47. save-some-buffers). This applies to all ASDF related repl
  48. shortcuts."
  49. :type '(boolean)
  50. :group 'slime-repl)
  51. (defcustom slime-repl-auto-right-margin nil
  52. "When T we bind CL:*PRINT-RIGHT-MARGIN* to the width of the
  53. current repl's (as per slime-output-buffer) window."
  54. :type '(boolean)
  55. :group 'slime-repl)
  56. (defface slime-repl-prompt-face
  57. '((t (:inherit font-lock-keyword-face)))
  58. "Face for the prompt in the SLIME REPL."
  59. :group 'slime-repl)
  60. (defface slime-repl-output-face
  61. '((t (:inherit font-lock-string-face)))
  62. "Face for Lisp output in the SLIME REPL."
  63. :group 'slime-repl)
  64. (defface slime-repl-input-face
  65. '((t (:bold t)))
  66. "Face for previous input in the SLIME REPL."
  67. :group 'slime-repl)
  68. (defface slime-repl-result-face
  69. '((t ()))
  70. "Face for the result of an evaluation in the SLIME REPL."
  71. :group 'slime-repl)
  72. (defcustom slime-repl-history-file "~/.slime-history.eld"
  73. "File to save the persistent REPL history to."
  74. :type 'string
  75. :group 'slime-repl)
  76. (defcustom slime-repl-history-size 200
  77. "*Maximum number of lines for persistent REPL history."
  78. :type 'integer
  79. :group 'slime-repl)
  80. (defcustom slime-repl-history-file-coding-system
  81. (cond ((slime-find-coding-system 'utf-8-unix) 'utf-8-unix)
  82. (t slime-net-coding-system))
  83. "*The coding system for the history file."
  84. :type 'symbol
  85. :group 'slime-repl)
  86. ;; dummy defvar for compiler
  87. (defvar slime-repl-read-mode)
  88. (defun slime-reading-p ()
  89. "True if Lisp is currently reading input from the REPL."
  90. (with-current-buffer (slime-output-buffer)
  91. slime-repl-read-mode))
  92. ;;;; Stream output
  93. (slime-def-connection-var slime-connection-output-buffer nil
  94. "The buffer for the REPL. May be nil or a dead buffer.")
  95. (make-variable-buffer-local
  96. (defvar slime-output-start nil
  97. "Marker for the start of the output for the evaluation."))
  98. (make-variable-buffer-local
  99. (defvar slime-output-end nil
  100. "Marker for end of output. New output is inserted at this mark."))
  101. ;; dummy definitions for the compiler
  102. (defvar slime-repl-package-stack)
  103. (defvar slime-repl-directory-stack)
  104. (defvar slime-repl-input-start-mark)
  105. (defvar slime-repl-prompt-start-mark)
  106. (defvar slime-repl-history-use-mark nil
  107. "A non-nil value means that history will be replaced from the mark.
  108. Instead of replacing form input-start, look up history and replace input
  109. from the mark. Calling 'slime-repl-previous-input',
  110. 'slime-repl-previous-matching-input' or their -next counterparts with a prefix
  111. argument sets this variable for the duration of one history lookup.")
  112. (defun slime-repl-history-yank-start ()
  113. "The position which 'slime-repl-previous-input' will replace from.
  114. When 'slime-repl-history-use-mark' is non-nil, and (mark) is after the current
  115. input start, return it. Otherwise, return 'slime-repl-input-start-mark'."
  116. (if (and slime-repl-history-use-mark (mark))
  117. (max (mark) slime-repl-input-start-mark)
  118. slime-repl-input-start-mark))
  119. (defun slime-output-buffer (&optional noprompt)
  120. "Return the output buffer, create it if necessary."
  121. (let ((buffer (slime-connection-output-buffer)))
  122. (or (if (buffer-live-p buffer) buffer)
  123. (setf (slime-connection-output-buffer)
  124. (let ((connection (slime-connection)))
  125. (with-current-buffer (slime-repl-buffer t connection)
  126. (unless (eq major-mode 'slime-repl-mode)
  127. (slime-repl-mode))
  128. (setq slime-buffer-connection connection)
  129. (setq slime-buffer-package (slime-lisp-package connection))
  130. (slime-reset-repl-markers)
  131. (unless noprompt
  132. (slime-repl-insert-prompt))
  133. (current-buffer)))))))
  134. (defvar slime-repl-banner-function 'slime-repl-insert-banner)
  135. (defun slime-repl-update-banner ()
  136. (funcall slime-repl-banner-function)
  137. (slime-move-point (point-max))
  138. (slime-mark-output-start)
  139. (slime-mark-input-start)
  140. (slime-repl-insert-prompt))
  141. (defun slime-repl-insert-banner ()
  142. (when (zerop (buffer-size))
  143. (let ((welcome (concat "; SLIME " slime-version)))
  144. (insert welcome))))
  145. (defun slime-init-output-buffer (connection)
  146. (with-current-buffer (slime-output-buffer t)
  147. (setq slime-buffer-connection connection
  148. slime-repl-directory-stack '()
  149. slime-repl-package-stack '())
  150. (slime-repl-update-banner)))
  151. (defun slime-display-output-buffer ()
  152. "Display the output buffer and scroll to bottom."
  153. (with-current-buffer (slime-output-buffer)
  154. (goto-char (point-max))
  155. (unless (get-buffer-window (current-buffer) t)
  156. (display-buffer (current-buffer) t))
  157. (slime-repl-show-maximum-output)))
  158. (defun slime-output-filter (process string)
  159. (with-current-buffer (process-buffer process)
  160. (when (and (plusp (length string))
  161. (eq (process-status slime-buffer-connection) 'open))
  162. (slime-write-string string))))
  163. (defvar slime-open-stream-hooks)
  164. (defun slime-open-stream-to-lisp (port coding-system)
  165. (let ((stream (open-network-stream "*lisp-output-stream*"
  166. (slime-with-connection-buffer ()
  167. (current-buffer))
  168. (car (process-contact (slime-connection)))
  169. port))
  170. (emacs-coding-system (car (cl-find coding-system
  171. slime-net-valid-coding-systems
  172. :key #'cl-third))))
  173. (slime-set-query-on-exit-flag stream)
  174. (set-process-filter stream 'slime-output-filter)
  175. (set-process-coding-system stream emacs-coding-system emacs-coding-system)
  176. (let ((secret (slime-secret)))
  177. (when secret
  178. (slime-net-send secret stream)))
  179. (run-hook-with-args 'slime-open-stream-hooks stream)
  180. stream))
  181. (defun slime-io-speed-test (&optional profile)
  182. "A simple minded benchmark for stream performance.
  183. If a prefix argument is given, instrument the slime package for
  184. profiling before running the benchmark."
  185. (interactive "P")
  186. (eval-and-compile
  187. (require 'elp))
  188. (elp-reset-all)
  189. (elp-restore-all)
  190. (load "slime.el")
  191. ;;(byte-compile-file "slime-net.el" t)
  192. ;;(setq slime-log-events nil)
  193. (setq slime-enable-evaluate-in-emacs t)
  194. ;;(setq slime-repl-enable-presentations nil)
  195. (when profile
  196. (elp-instrument-package "slime-"))
  197. (kill-buffer (slime-output-buffer))
  198. (switch-to-buffer (slime-output-buffer))
  199. (delete-other-windows)
  200. (sit-for 0)
  201. (slime-repl-send-string "(swank:io-speed-test 4000 1)")
  202. (let ((proc (slime-inferior-process)))
  203. (when proc
  204. (display-buffer (process-buffer proc) t)
  205. (goto-char (point-max)))))
  206. (defvar slime-write-string-function 'slime-repl-write-string)
  207. (defun slime-write-string (string &optional target)
  208. "Insert STRING in the REPL buffer or some other TARGET.
  209. If TARGET is nil, insert STRING as regular process
  210. output. If TARGET is :repl-result, insert STRING as the result of the
  211. evaluation. Other values of TARGET map to an Emacs marker via the
  212. hashtable `slime-output-target-to-marker'; output is inserted at this marker."
  213. (funcall slime-write-string-function string target))
  214. (defun slime-repl-write-string (string &optional target)
  215. (case target
  216. ((nil) (slime-repl-emit string))
  217. (:repl-result (slime-repl-emit-result string t))
  218. (t (slime-repl-emit-to-target string target))))
  219. (defvar slime-repl-popup-on-output nil
  220. "Display the output buffer when some output is written.
  221. This is set to nil after displaying the buffer.")
  222. (defmacro slime-save-marker (marker &rest body)
  223. (declare (debug (sexp &rest form)))
  224. (let ((pos (cl-gensym "pos")))
  225. `(let ((,pos (marker-position ,marker)))
  226. (prog1 (progn . ,body)
  227. (set-marker ,marker ,pos)))))
  228. (put 'slime-save-marker 'lisp-indent-function 1)
  229. (defun slime-repl-emit (string)
  230. ;; insert the string STRING in the output buffer
  231. (with-current-buffer (slime-output-buffer)
  232. (save-excursion
  233. (goto-char slime-output-end)
  234. (slime-save-marker slime-output-start
  235. (slime-propertize-region '(face slime-repl-output-face
  236. slime-repl-output t
  237. rear-nonsticky (face))
  238. (let ((inhibit-read-only t))
  239. (insert-before-markers string)
  240. (when (and (= (point) slime-repl-prompt-start-mark)
  241. (not (bolp)))
  242. (insert-before-markers "\n")
  243. (set-marker slime-output-end (1- (point))))))))
  244. (when slime-repl-popup-on-output
  245. (setq slime-repl-popup-on-output nil)
  246. (display-buffer (current-buffer)))
  247. (slime-repl-show-maximum-output)))
  248. (defun slime-repl-emit-result (string &optional bol)
  249. ;; insert STRING and mark it as evaluation result
  250. (with-current-buffer (slime-output-buffer)
  251. (save-excursion
  252. (goto-char slime-repl-input-start-mark)
  253. (slime-save-marker slime-output-start
  254. (goto-char slime-repl-input-start-mark)
  255. (when (and bol (not (bolp))) (insert-before-markers-and-inherit "\n"))
  256. (slime-save-marker slime-output-end
  257. (slime-propertize-region `(face slime-repl-result-face
  258. rear-nonsticky (face))
  259. (insert-before-markers string)))
  260. (set-marker slime-output-end (point))))
  261. (slime-repl-show-maximum-output)))
  262. (defvar slime-last-output-target-id 0
  263. "The last integer we used as a TARGET id.")
  264. (defun slime-repl-emit-to-target (string target)
  265. "Insert STRING at target TARGET.
  266. See `slime-output-target-to-marker'."
  267. (let* ((marker (slime-repl-output-target-marker target))
  268. (buffer (and marker (marker-buffer marker))))
  269. (when buffer
  270. (with-current-buffer buffer
  271. (save-excursion
  272. ;; Insert STRING at MARKER, then move MARKER behind
  273. ;; the insertion.
  274. (goto-char marker)
  275. (insert-before-markers string)
  276. (set-marker marker (point)))))))
  277. (defun slime-repl-output-target-marker (target)
  278. (case target
  279. ((nil)
  280. (with-current-buffer (slime-output-buffer)
  281. slime-output-end))
  282. (:repl-result
  283. (with-current-buffer (slime-output-buffer)
  284. slime-repl-input-start-mark))
  285. (t
  286. (slime-output-target-marker target))))
  287. (defun slime-switch-to-output-buffer ()
  288. "Select the output buffer, when possible in an existing window.
  289. Hint: You can use `display-buffer-reuse-frames' and
  290. `special-display-buffer-names' to customize the frame in which
  291. the buffer should appear."
  292. (interactive)
  293. (pop-to-buffer (slime-output-buffer))
  294. (goto-char (point-max)))
  295. ;;;; REPL
  296. ;;
  297. ;; The REPL uses some markers to separate input from output. The
  298. ;; usual configuration is as follows:
  299. ;;
  300. ;; ... output ... ... result ... prompt> ... input ...
  301. ;; ^ ^ ^ ^ ^
  302. ;; output-start output-end prompt-start input-start point-max
  303. ;;
  304. ;; input-start is a right inserting marker, because
  305. ;; we want it to stay behind when the user inserts text.
  306. ;;
  307. ;; We maintain the following invariant:
  308. ;;
  309. ;; output-start <= output-end <= input-start.
  310. ;;
  311. ;; This invariant is important, because we must be prepared for
  312. ;; asynchronous output and asynchronous reads. ("Asynchronous" means,
  313. ;; triggered by Lisp and not by Emacs.)
  314. ;;
  315. ;; All output is inserted at the output-end marker. Some care must be
  316. ;; taken when output-end and input-start are at the same position: if
  317. ;; we insert at that point, we must move the right markers. We should
  318. ;; also not leave (window-)point in the middle of the new output. The
  319. ;; idiom we use is a combination to slime-save-marker,
  320. ;; insert-before-markers, and manually updating window-point
  321. ;; afterwards.
  322. ;;
  323. ;; A "synchronous" evaluation request proceeds as follows: the user
  324. ;; inserts some text between input-start and point-max and then hits
  325. ;; return. We send that region to Lisp, move the output and input
  326. ;; makers to the line after the input and wait. When we receive the
  327. ;; result, we insert it together with a prompt between the output-end
  328. ;; and input-start mark. See `slime-repl-insert-prompt'.
  329. ;;
  330. ;; It is possible that some output for such an evaluation request
  331. ;; arrives after the result. This output is inserted before the
  332. ;; result (and before the prompt).
  333. ;;
  334. ;; If we are in "reading" state, e.g., during a call to Y-OR-N-P,
  335. ;; there is no prompt between output-end and input-start.
  336. ;;
  337. ;; FIXME: slime-lisp-package should be local in a REPL buffer
  338. (slime-def-connection-var slime-lisp-package
  339. "COMMON-LISP-USER"
  340. "The current package name of the Superior lisp.
  341. This is automatically synchronized from Lisp.")
  342. (slime-def-connection-var slime-lisp-package-prompt-string
  343. "CL-USER"
  344. "The current package name of the Superior lisp.
  345. This is automatically synchronized from Lisp.")
  346. (slime-make-variables-buffer-local
  347. (defvar slime-repl-package-stack nil
  348. "The stack of packages visited in this repl.")
  349. (defvar slime-repl-directory-stack nil
  350. "The stack of default directories associated with this repl.")
  351. (defvar slime-repl-prompt-start-mark)
  352. (defvar slime-repl-input-start-mark)
  353. (defvar slime-repl-old-input-counter 0
  354. "Counter used to generate unique `slime-repl-old-input' properties.
  355. This property value must be unique to avoid having adjacent inputs be
  356. joined together."))
  357. (defun slime-reset-repl-markers ()
  358. (dolist (markname '(slime-output-start
  359. slime-output-end
  360. slime-repl-prompt-start-mark
  361. slime-repl-input-start-mark))
  362. (set markname (make-marker))
  363. (set-marker (symbol-value markname) (point))))
  364. ;;;;; REPL mode setup
  365. (defvar slime-repl-mode-map
  366. (let ((map (make-sparse-keymap)))
  367. (set-keymap-parent map lisp-mode-map)
  368. map))
  369. (slime-define-keys slime-prefix-map
  370. ("\C-z" 'slime-switch-to-output-buffer)
  371. ("\M-p" 'slime-repl-set-package))
  372. (slime-define-keys slime-mode-map
  373. ("\C-c~" 'slime-sync-package-and-default-directory)
  374. ("\C-c\C-y" 'slime-call-defun)
  375. ("\C-c\C-j" 'slime-eval-last-expression-in-repl))
  376. (slime-define-keys slime-connection-list-mode-map
  377. ((kbd "RET") 'slime-goto-connection)
  378. ([return] 'slime-goto-connection))
  379. (slime-define-keys slime-repl-mode-map
  380. ("\C-m" 'slime-repl-return)
  381. ([return] 'slime-repl-return)
  382. ("\C-j" 'slime-repl-newline-and-indent)
  383. ("\C-\M-m" 'slime-repl-closing-return)
  384. ([(control return)] 'slime-repl-closing-return)
  385. ("\M-p" 'slime-repl-previous-input)
  386. ((kbd "C-<up>") 'slime-repl-backward-input)
  387. ("\M-n" 'slime-repl-next-input)
  388. ((kbd "C-<down>") 'slime-repl-forward-input)
  389. ("\M-r" 'slime-repl-previous-matching-input)
  390. ("\M-s" 'slime-repl-next-matching-input)
  391. ("\C-c\C-c" 'slime-interrupt)
  392. (" " 'slime-space)
  393. ((string slime-repl-shortcut-dispatch-char) 'slime-handle-repl-shortcut)
  394. ("\C-c\C-o" 'slime-repl-clear-output)
  395. ("\C-c\M-o" 'slime-repl-clear-buffer)
  396. ("\C-c\C-u" 'slime-repl-kill-input)
  397. ("\C-c\C-n" 'slime-repl-next-prompt)
  398. ("\C-c\C-p" 'slime-repl-previous-prompt)
  399. ("\C-c\C-z" 'slime-nop)
  400. ("\C-cI" 'slime-repl-inspect)
  401. ("\C-x\C-e" 'slime-eval-last-expression))
  402. (slime-define-keys slime-inspector-mode-map
  403. ((kbd "M-RET") 'slime-inspector-copy-down-to-repl))
  404. (slime-define-keys sldb-mode-map
  405. ("\C-y" 'sldb-insert-frame-call-to-repl)
  406. ((kbd "M-RET") 'sldb-copy-down-to-repl))
  407. (def-slime-selector-method ?r
  408. "SLIME Read-Eval-Print-Loop."
  409. (slime-output-buffer))
  410. (define-minor-mode slime-repl-map-mode
  411. "Minor mode which makes slime-repl-mode-map available.
  412. \\{slime-repl-mode-map}"
  413. nil
  414. nil
  415. slime-repl-mode-map)
  416. (defun slime-repl-mode ()
  417. "Major mode for interacting with a superior Lisp.
  418. \\{slime-repl-mode-map}"
  419. (interactive)
  420. (kill-all-local-variables)
  421. (setq major-mode 'slime-repl-mode)
  422. (slime-editing-mode 1)
  423. (slime-repl-map-mode 1)
  424. (lisp-mode-variables t)
  425. (set (make-local-variable 'lisp-indent-function)
  426. 'common-lisp-indent-function)
  427. (slime-setup-completion)
  428. (set (make-local-variable 'tab-always-indent) 'complete)
  429. (setq font-lock-defaults nil)
  430. (setq mode-name "REPL")
  431. (setq slime-current-thread :repl-thread)
  432. (set (make-local-variable 'scroll-conservatively) 20)
  433. (set (make-local-variable 'scroll-margin) 0)
  434. (when slime-repl-history-file
  435. (slime-repl-safe-load-history)
  436. (add-hook 'kill-buffer-hook
  437. 'slime-repl-safe-save-merged-history
  438. 'append t))
  439. (add-hook 'kill-emacs-hook 'slime-repl-save-all-histories)
  440. ;; At the REPL, we define beginning-of-defun and end-of-defun to be
  441. ;; the start of the previous prompt or next prompt respectively.
  442. ;; Notice the interplay with SLIME-REPL-BEGINNING-OF-DEFUN.
  443. (set (make-local-variable 'beginning-of-defun-function)
  444. 'slime-repl-mode-beginning-of-defun)
  445. (set (make-local-variable 'end-of-defun-function)
  446. 'slime-repl-mode-end-of-defun)
  447. (run-mode-hooks 'slime-repl-mode-hook))
  448. (defun slime-repl-buffer (&optional create connection)
  449. "Get the REPL buffer for the current connection; optionally create."
  450. (funcall (if create #'get-buffer-create #'get-buffer)
  451. (format "*slime-repl %s*" (slime-connection-name connection))))
  452. (defun slime-repl ()
  453. (interactive)
  454. (slime-switch-to-output-buffer)
  455. (current-buffer))
  456. (defun slime-repl-mode-beginning-of-defun (&optional arg)
  457. (if (and arg (< arg 0))
  458. (slime-repl-mode-end-of-defun (- arg))
  459. (dotimes (i (or arg 1))
  460. (slime-repl-previous-prompt))))
  461. (defun slime-repl-mode-end-of-defun (&optional arg)
  462. (if (and arg (< arg 0))
  463. (slime-repl-mode-beginning-of-defun (- arg))
  464. (dotimes (i (or arg 1))
  465. (slime-repl-next-prompt))))
  466. (defun slime-repl-send-string (string &optional command-string)
  467. (cond (slime-repl-read-mode
  468. (slime-repl-return-string string))
  469. (t (slime-repl-eval-string string))))
  470. (defun slime-repl-eval-string (string)
  471. (slime-rex ()
  472. ((if slime-repl-auto-right-margin
  473. `(swank-repl:listener-eval
  474. ,string
  475. :window-width
  476. ,(with-current-buffer (slime-output-buffer)
  477. (window-width)))
  478. `(swank-repl:listener-eval ,string))
  479. (slime-lisp-package))
  480. ((:ok result)
  481. (slime-repl-insert-result result))
  482. ((:abort condition)
  483. (slime-repl-show-abort condition))))
  484. (defun slime-repl-insert-result (result)
  485. (with-current-buffer (slime-output-buffer)
  486. (save-excursion
  487. (when result
  488. (slime-dcase result
  489. ((:values &rest strings)
  490. (cond ((null strings)
  491. (slime-repl-emit-result "; No value\n" t))
  492. (t
  493. (dolist (s strings)
  494. (slime-repl-emit-result s t)))))))
  495. (slime-repl-insert-prompt))
  496. (slime-repl-show-maximum-output)))
  497. (defun slime-repl-show-abort (condition)
  498. (with-current-buffer (slime-output-buffer)
  499. (save-excursion
  500. (slime-save-marker slime-output-start
  501. (slime-save-marker slime-output-end
  502. (goto-char slime-output-end)
  503. (insert-before-markers (format "; Evaluation aborted on %s.\n"
  504. condition))
  505. (slime-repl-insert-prompt))))
  506. (slime-repl-show-maximum-output)))
  507. (defvar slime-repl-suppress-prompt nil
  508. "Supresses Slime REPL prompt when bound to T.")
  509. (defun slime-repl-insert-prompt ()
  510. "Insert the prompt (before markers!).
  511. Set point after the prompt.
  512. Return the position of the prompt beginning.
  513. If `slime-repl-suppress-prompt' is true, does nothing and returns nil."
  514. (goto-char slime-repl-input-start-mark)
  515. (unless slime-repl-suppress-prompt
  516. (slime-save-marker slime-output-start
  517. (slime-save-marker slime-output-end
  518. (unless (bolp) (insert-before-markers "\n"))
  519. (let ((prompt-start (point))
  520. (prompt (format "%s> " (slime-lisp-package-prompt-string))))
  521. (slime-propertize-region
  522. '(face slime-repl-prompt-face
  523. read-only t slime-repl-prompt t
  524. rear-nonsticky t front-sticky (read-only)
  525. inhibit-line-move-field-capture t
  526. field output)
  527. (insert-before-markers prompt))
  528. (set-marker slime-repl-prompt-start-mark prompt-start)
  529. (setq buffer-undo-list nil)
  530. prompt-start)))))
  531. (defun slime-repl-show-maximum-output ()
  532. "Put the end of the buffer at the bottom of the window."
  533. (when (eobp)
  534. (let ((win (if (eq (window-buffer) (current-buffer))
  535. (selected-window)
  536. (get-buffer-window (current-buffer) t))))
  537. (when win
  538. (with-selected-window win
  539. (set-window-point win (point-max))
  540. (recenter -1))))))
  541. (defvar slime-repl-current-input-hooks)
  542. (defun slime-repl-current-input (&optional until-point-p)
  543. "Return the current input as string.
  544. The input is the region from after the last prompt to the end of
  545. buffer."
  546. (or (run-hook-with-args-until-success 'slime-repl-current-input-hooks
  547. until-point-p)
  548. (buffer-substring-no-properties (slime-repl-history-yank-start)
  549. (if until-point-p
  550. (point)
  551. (point-max)))))
  552. (defun slime-property-position (text-property &optional object)
  553. "Return the first position of TEXT-PROPERTY, or nil."
  554. (if (get-text-property 0 text-property object)
  555. 0
  556. (next-single-property-change 0 text-property object)))
  557. (defun slime-mark-input-start ()
  558. (set-marker slime-repl-input-start-mark (point) (current-buffer)))
  559. (defun slime-mark-output-start ()
  560. (set-marker slime-output-start (point))
  561. (set-marker slime-output-end (point)))
  562. (defun slime-mark-output-end ()
  563. ;; Don't put slime-repl-output-face again; it would remove the
  564. ;; special presentation face, for instance in the SBCL inspector.
  565. (add-text-properties slime-output-start slime-output-end
  566. '(;;face slime-repl-output-face
  567. rear-nonsticky (face))))
  568. (defun slime-preserve-zmacs-region ()
  569. "In XEmacs, ensure that the zmacs-region stays active after this command."
  570. (when (boundp 'zmacs-region-stays)
  571. (set 'zmacs-region-stays t)))
  572. (defun slime-repl-in-input-area-p ()
  573. (<= slime-repl-input-start-mark (point)))
  574. (defun slime-repl-at-prompt-start-p ()
  575. ;; This will not work on non-current prompts.
  576. (= (point) slime-repl-input-start-mark))
  577. (defun slime-repl-beginning-of-defun ()
  578. "Move to beginning of defun."
  579. (interactive)
  580. ;; We call BEGINNING-OF-DEFUN if we're at the start of a prompt
  581. ;; already, to trigger SLIME-REPL-MODE-BEGINNING-OF-DEFUN by means
  582. ;; of the locally bound BEGINNING-OF-DEFUN-FUNCTION, in order to
  583. ;; jump to the start of the previous prompt.
  584. (if (and (not (slime-repl-at-prompt-start-p))
  585. (slime-repl-in-input-area-p))
  586. (goto-char slime-repl-input-start-mark)
  587. (beginning-of-defun))
  588. t)
  589. ;; FIXME: this looks very strange
  590. (defun slime-repl-end-of-defun ()
  591. "Move to next of defun."
  592. (interactive)
  593. ;; C.f. SLIME-REPL-BEGINNING-OF-DEFUN.
  594. (if (and (not (= (point) (point-max)))
  595. (slime-repl-in-input-area-p))
  596. (goto-char (point-max))
  597. (end-of-defun))
  598. t)
  599. (defun slime-repl-previous-prompt ()
  600. "Move backward to the previous prompt."
  601. (interactive)
  602. (slime-repl-find-prompt t))
  603. (defun slime-repl-next-prompt ()
  604. "Move forward to the next prompt."
  605. (interactive)
  606. (slime-repl-find-prompt))
  607. (defun slime-repl-find-prompt (&optional backward)
  608. (let ((origin (point))
  609. (prop 'slime-repl-prompt))
  610. (while (progn
  611. (slime-search-property-change prop backward)
  612. (not (or (slime-end-of-proprange-p prop) (bobp) (eobp)))))
  613. (unless (slime-end-of-proprange-p prop)
  614. (goto-char origin))))
  615. (defun slime-search-property-change (prop &optional backward)
  616. (cond (backward
  617. (goto-char (or (previous-single-char-property-change (point) prop)
  618. (point-min))))
  619. (t
  620. (goto-char (or (next-single-char-property-change (point) prop)
  621. (point-max))))))
  622. (defun slime-end-of-proprange-p (property)
  623. (and (get-char-property (max 1 (1- (point))) property)
  624. (not (get-char-property (point) property))))
  625. (defvar slime-repl-return-hooks)
  626. (defun slime-repl-return (&optional end-of-input)
  627. "Evaluate the current input string, or insert a newline.
  628. Send the current input only if a whole expression has been entered,
  629. i.e. the parenthesis are matched.
  630. With prefix argument send the input even if the parenthesis are not
  631. balanced."
  632. (interactive "P")
  633. (slime-check-connected)
  634. (cond (end-of-input
  635. (slime-repl-send-input))
  636. (slime-repl-read-mode ; bad style?
  637. (slime-repl-send-input t))
  638. ((and (get-text-property (point) 'slime-repl-old-input)
  639. (< (point) slime-repl-input-start-mark))
  640. (slime-repl-grab-old-input end-of-input)
  641. (slime-repl-recenter-if-needed))
  642. ((run-hook-with-args-until-success 'slime-repl-return-hooks end-of-input))
  643. ((slime-input-complete-p slime-repl-input-start-mark (point-max))
  644. (slime-repl-send-input t))
  645. (t
  646. (slime-repl-newline-and-indent)
  647. (message "[input not complete]"))))
  648. (defun slime-repl-recenter-if-needed ()
  649. "Make sure that (point) is visible."
  650. (unless (pos-visible-in-window-p (point-max))
  651. (save-excursion
  652. (goto-char (point-max))
  653. (recenter -1))))
  654. (defun slime-repl-send-input (&optional newline)
  655. "Goto to the end of the input and send the current input.
  656. If NEWLINE is true then add a newline at the end of the input."
  657. (unless (slime-repl-in-input-area-p)
  658. (error "No input at point."))
  659. (goto-char (point-max))
  660. (let ((end (point))) ; end of input, without the newline
  661. (slime-repl-add-to-input-history
  662. (buffer-substring slime-repl-input-start-mark end))
  663. (when newline
  664. (insert "\n")
  665. (slime-repl-show-maximum-output))
  666. (let ((inhibit-modification-hooks t))
  667. (add-text-properties slime-repl-input-start-mark
  668. (point)
  669. `(slime-repl-old-input
  670. ,(incf slime-repl-old-input-counter))))
  671. (let ((overlay (make-overlay slime-repl-input-start-mark end)))
  672. ;; These properties are on an overlay so that they won't be taken
  673. ;; by kill/yank.
  674. (overlay-put overlay 'face 'slime-repl-input-face)))
  675. (let ((input (slime-repl-current-input)))
  676. (goto-char (point-max))
  677. (slime-mark-input-start)
  678. (slime-mark-output-start)
  679. (slime-repl-send-string input)))
  680. (defun slime-repl-grab-old-input (replace)
  681. "Resend the old REPL input at point.
  682. If replace is non-nil the current input is replaced with the old
  683. input; otherwise the new input is appended. The old input has the
  684. text property `slime-repl-old-input'."
  685. (multiple-value-bind (beg end) (slime-property-bounds 'slime-repl-old-input)
  686. (let ((old-input (buffer-substring beg end)) ;;preserve
  687. ;;properties, they will be removed later
  688. (offset (- (point) beg)))
  689. ;; Append the old input or replace the current input
  690. (cond (replace (goto-char slime-repl-input-start-mark))
  691. (t (goto-char (point-max))
  692. (unless (eq (char-before) ?\ )
  693. (insert " "))))
  694. (delete-region (point) (point-max))
  695. (save-excursion
  696. (insert old-input)
  697. (when (equal (char-before) ?\n)
  698. (delete-char -1)))
  699. (forward-char offset))))
  700. (defun slime-repl-closing-return ()
  701. "Evaluate the current input string after closing all open lists."
  702. (interactive)
  703. (goto-char (point-max))
  704. (save-restriction
  705. (narrow-to-region slime-repl-input-start-mark (point))
  706. (while (ignore-errors (save-excursion (backward-up-list 1)) t)
  707. (insert ")")))
  708. (slime-repl-return))
  709. (defun slime-repl-newline-and-indent ()
  710. "Insert a newline, then indent the next line.
  711. Restrict the buffer from the prompt for indentation, to avoid being
  712. confused by strange characters (like unmatched quotes) appearing
  713. earlier in the buffer."
  714. (interactive)
  715. (save-restriction
  716. (narrow-to-region slime-repl-prompt-start-mark (point-max))
  717. (insert "\n")
  718. (lisp-indent-line)))
  719. (defun slime-repl-delete-current-input ()
  720. "Delete all text from the prompt."
  721. (interactive)
  722. (delete-region (slime-repl-history-yank-start) (point-max)))
  723. (defun slime-eval-last-expression-in-repl (prefix)
  724. "Evaluates last expression in the Slime REPL.
  725. Switches REPL to current package of the source buffer for the duration. If
  726. used with a prefix argument (C-u), doesn't switch back afterwards."
  727. (interactive "P")
  728. (let ((expr (slime-last-expression))
  729. (buffer-name (buffer-name (current-buffer)))
  730. (new-package (slime-current-package))
  731. (old-package (slime-lisp-package))
  732. (slime-repl-suppress-prompt t)
  733. (yank-back nil))
  734. (with-current-buffer (slime-output-buffer)
  735. (unless (eq (current-buffer) (window-buffer))
  736. (pop-to-buffer (current-buffer) t))
  737. (goto-char (point-max))
  738. ;; Kill pending input in the REPL
  739. (when (< (marker-position slime-repl-input-start-mark) (point))
  740. (kill-region slime-repl-input-start-mark (point))
  741. (setq yank-back t))
  742. (unwind-protect
  743. (progn
  744. (insert-before-markers (format "\n;;; from %s\n" buffer-name))
  745. (when new-package
  746. (slime-repl-set-package new-package))
  747. (let ((slime-repl-suppress-prompt nil))
  748. (slime-repl-insert-prompt))
  749. (insert expr)
  750. (slime-repl-return))
  751. (unless (or prefix (equal (slime-lisp-package) old-package))
  752. ;; Switch back.
  753. (slime-repl-set-package old-package)
  754. (let ((slime-repl-suppress-prompt nil))
  755. (slime-repl-insert-prompt))))
  756. ;; Put pending input back.
  757. (when yank-back
  758. (yank)))))
  759. (defun slime-repl-kill-input ()
  760. "Kill all text from the prompt to point."
  761. (interactive)
  762. (cond ((< (marker-position slime-repl-input-start-mark) (point))
  763. (kill-region slime-repl-input-start-mark (point)))
  764. ((= (point) (marker-position slime-repl-input-start-mark))
  765. (slime-repl-delete-current-input))))
  766. (defun slime-repl-replace-input (string)
  767. (slime-repl-delete-current-input)
  768. (insert-and-inherit string))
  769. (defun slime-repl-input-line-beginning-position ()
  770. (save-excursion
  771. (goto-char slime-repl-input-start-mark)
  772. (let ((inhibit-field-text-motion t))
  773. (line-beginning-position))))
  774. (defun slime-clear-repl-variables ()
  775. (interactive)
  776. (slime-eval-async `(swank-repl:clear-repl-variables)))
  777. (defvar slime-repl-clear-buffer-hook)
  778. (add-hook 'slime-repl-clear-buffer-hook 'slime-clear-repl-variables)
  779. (defun slime-repl-clear-buffer ()
  780. "Delete the output generated by the Lisp process."
  781. (interactive)
  782. (let ((inhibit-read-only t))
  783. (delete-region (point-min) slime-repl-prompt-start-mark)
  784. (delete-region slime-output-start slime-output-end)
  785. (when (< (point) slime-repl-input-start-mark)
  786. (goto-char slime-repl-input-start-mark))
  787. (recenter t))
  788. (run-hooks 'slime-repl-clear-buffer-hook))
  789. (defun slime-repl-clear-output ()
  790. "Delete the output inserted since the last input."
  791. (interactive)
  792. (let ((start (save-excursion
  793. (when (>= (point) slime-repl-input-start-mark)
  794. (goto-char slime-repl-input-start-mark))
  795. (slime-repl-previous-prompt)
  796. (ignore-errors (forward-sexp))
  797. (forward-line)
  798. (point)))
  799. (end (1- (slime-repl-input-line-beginning-position))))
  800. (when (< start end)
  801. (let ((inhibit-read-only t))
  802. (delete-region start end)
  803. (save-excursion
  804. (goto-char start)
  805. (insert ";;; output flushed"))))))
  806. (defun slime-repl-set-package (package)
  807. "Set the package of the REPL buffer to PACKAGE."
  808. (interactive (list (let* ((p (slime-current-package))
  809. (p (and p (slime-pretty-package-name p)))
  810. (p (and (not (equal p (slime-lisp-package))) p)))
  811. (slime-read-package-name "Package: " p))))
  812. (with-current-buffer (slime-output-buffer)
  813. (let ((previouse-point (- (point) slime-repl-input-start-mark))
  814. (previous-prompt (slime-lisp-package-prompt-string)))
  815. (destructuring-bind (name prompt-string)
  816. (slime-repl-shortcut-eval `(swank:set-package ,package))
  817. (setf (slime-lisp-package) name)
  818. (setf slime-buffer-package name)
  819. (unless (equal previous-prompt prompt-string)
  820. (setf (slime-lisp-package-prompt-string) prompt-string)
  821. (slime-repl-insert-prompt))
  822. (when (plusp previouse-point)
  823. (goto-char (+ previouse-point slime-repl-input-start-mark)))))))
  824. ;;;;; History
  825. (defcustom slime-repl-wrap-history nil
  826. "*T to wrap history around when the end is reached."
  827. :type 'boolean
  828. :group 'slime-repl)
  829. (make-variable-buffer-local
  830. (defvar slime-repl-input-history '()
  831. "History list of strings read from the REPL buffer."))
  832. (defun slime-repl-add-to-input-history (string)
  833. "Add STRING to the input history.
  834. Empty strings and duplicates are ignored."
  835. (setq string (slime-trim-whitespace string))
  836. (unless (equal string "")
  837. (setq slime-repl-input-history
  838. (remove string slime-repl-input-history))
  839. (unless (equal string (car slime-repl-input-history))
  840. (push string slime-repl-input-history))))
  841. ;; These two vars contain the state of the last history search. We
  842. ;; only use them if `last-command' was 'slime-repl-history-replace,
  843. ;; otherwise we reinitialize them.
  844. (defvar slime-repl-input-history-position -1
  845. "Newer items have smaller indices.")
  846. (defvar slime-repl-history-pattern nil
  847. "The regexp most recently used for finding input history.")
  848. (defun slime-repl-history-replace (direction &optional regexp)
  849. "Replace the current input with the next line in DIRECTION.
  850. DIRECTION is 'forward' or 'backward' (in the history list).
  851. If REGEXP is non-nil, only lines matching REGEXP are considered."
  852. (setq slime-repl-history-pattern regexp)
  853. (let* ((min-pos -1)
  854. (max-pos (length slime-repl-input-history))
  855. (pos0 (cond ((slime-repl-history-search-in-progress-p)
  856. slime-repl-input-history-position)
  857. (t min-pos)))
  858. (pos (slime-repl-position-in-history pos0 direction (or regexp "")
  859. (slime-repl-current-input)))
  860. (msg nil))
  861. (cond ((and (< min-pos pos) (< pos max-pos))
  862. (slime-repl-replace-input (nth pos slime-repl-input-history))
  863. (setq msg (format "History item: %d" pos)))
  864. ((not slime-repl-wrap-history)
  865. (setq msg (cond ((= pos min-pos) "End of history")
  866. ((= pos max-pos) "Beginning of history"))))
  867. (slime-repl-wrap-history
  868. (setq pos (if (= pos min-pos) max-pos min-pos))
  869. (setq msg "Wrapped history")))
  870. (when (or (<= pos min-pos) (<= max-pos pos))
  871. (when regexp
  872. (setq msg (concat msg "; no matching item"))))
  873. ;;(message "%s [%d %d %s]" msg start-pos pos regexp)
  874. (message "%s%s" msg (cond ((not regexp) "")
  875. (t (format "; current regexp: %s" regexp))))
  876. (setq slime-repl-input-history-position pos)
  877. (setq this-command 'slime-repl-history-replace)))
  878. (defun slime-repl-history-search-in-progress-p ()
  879. (eq last-command 'slime-repl-history-replace))
  880. (defun slime-repl-terminate-history-search ()
  881. (setq last-command this-command))
  882. (defun slime-repl-position-in-history (start-pos direction regexp
  883. &optional exclude-string)
  884. "Return the position of the history item matching REGEXP.
  885. Return -1 resp. the length of the history if no item matches.
  886. If EXCLUDE-STRING is specified then it's excluded from the search."
  887. ;; Loop through the history list looking for a matching line
  888. (let* ((step (ecase direction
  889. (forward -1)
  890. (backward 1)))
  891. (history slime-repl-input-history)
  892. (len (length history)))
  893. (loop for pos = (+ start-pos step) then (+ pos step)
  894. if (< pos 0) return -1
  895. if (<= len pos) return len
  896. for history-item = (nth pos history)
  897. if (and (string-match regexp history-item)
  898. (not (equal history-item exclude-string)))
  899. return pos)))
  900. (defun slime-repl-previous-input ()
  901. "Cycle backwards through input history.
  902. If the `last-command' was a history navigation command use the
  903. same search pattern for this command.
  904. Otherwise use the current input as search pattern.
  905. With a prefix-arg, do replacement from the mark."
  906. (interactive)
  907. (let ((slime-repl-history-use-mark (or slime-repl-history-use-mark
  908. current-prefix-arg)))
  909. (slime-repl-history-replace 'backward (slime-repl-history-pattern t))))
  910. (defun slime-repl-next-input ()
  911. "Cycle forwards through input history.
  912. See `slime-repl-previous-input'.
  913. With a prefix-arg, do replacement from the mark."
  914. (interactive)
  915. (let ((slime-repl-history-use-mark (or slime-repl-history-use-mark
  916. current-prefix-arg)))
  917. (slime-repl-history-replace 'forward (slime-repl-history-pattern t))))
  918. (defun slime-repl-forward-input ()
  919. "Cycle forwards through input history."
  920. (interactive)
  921. (slime-repl-history-replace 'forward (slime-repl-history-pattern)))
  922. (defun slime-repl-backward-input ()
  923. "Cycle backwards through input history."
  924. (interactive)
  925. (slime-repl-history-replace 'backward (slime-repl-history-pattern)))
  926. (defun slime-repl-previous-matching-input (regexp)
  927. "Insert the previous matching input.
  928. With a prefix-arg, do the insertion at the mark."
  929. (interactive (list (slime-read-from-minibuffer
  930. "Previous element matching (regexp): ")))
  931. (slime-repl-terminate-history-search)
  932. (let ((slime-repl-history-use-mark (or slime-repl-history-use-mark
  933. current-prefix-arg)))
  934. (slime-repl-history-replace 'backward regexp)))
  935. (defun slime-repl-next-matching-input (regexp)
  936. "Insert the next matching input.
  937. With a prefix-arg, do the insertion at the mark."
  938. (interactive (list (slime-read-from-minibuffer
  939. "Next element matching (regexp): ")))
  940. (slime-repl-terminate-history-search)
  941. (let ((slime-repl-history-use-mark (or slime-repl-history-use-mark
  942. current-prefix-arg)))
  943. (slime-repl-history-replace 'forward regexp)))
  944. (defun slime-repl-history-pattern (&optional use-current-input)
  945. "Return the regexp for the navigation commands."
  946. (cond ((slime-repl-history-search-in-progress-p)
  947. slime-repl-history-pattern)
  948. (use-current-input
  949. (goto-char (max (slime-repl-history-yank-start) (point)))
  950. (let ((str (slime-repl-current-input t)))
  951. (cond ((string-match "^[ \t\n]*$" str) nil)
  952. (t (concat "^" (regexp-quote str))))))
  953. (t nil)))
  954. (defun slime-repl-delete-from-input-history (string)
  955. "Delete STRING from the repl input history.
  956. When string is not provided then clear the current repl input and
  957. use it as an input. This is useful to get rid of unwanted repl
  958. history entries while navigating the repl history."
  959. (interactive (list (slime-repl-current-input)))
  960. (let ((merged-history
  961. (slime-repl-merge-histories (slime-repl-read-history nil t)
  962. slime-repl-input-history)))
  963. (setq slime-repl-input-history
  964. (cl-delete string merged-history :test #'string=))
  965. (slime-repl-save-history))
  966. (slime-repl-delete-current-input))
  967. ;;;;; Persistent History
  968. (defun slime-repl-merge-histories (old-hist new-hist)
  969. "Merge entries from OLD-HIST and NEW-HIST."
  970. ;; Newer items in each list are at the beginning.
  971. (let* ((ht (make-hash-table :test #'equal))
  972. (test (lambda (entry)
  973. (or (gethash entry ht)
  974. (progn (setf (gethash entry ht) t)
  975. nil)))))
  976. (append (cl-remove-if test new-hist)
  977. (cl-remove-if test old-hist))))
  978. (defun slime-repl-load-history (&optional filename)
  979. "Set the current SLIME REPL history.
  980. It can be read either from FILENAME or `slime-repl-history-file' or
  981. from a user defined filename."
  982. (interactive (list (slime-repl-read-history-filename)))
  983. (let ((file (or filename slime-repl-history-file)))
  984. (setq slime-repl-input-history (slime-repl-read-history file t))))
  985. (defun slime-repl-read-history (&optional filename noerrer)
  986. "Read and return the history from FILENAME.
  987. The default value for FILENAME is `slime-repl-history-file'.
  988. If NOERROR is true return and the file doesn't exits return nil."
  989. (let ((file (or filename slime-repl-history-file)))
  990. (cond ((not (file-readable-p file)) '())
  991. (t (with-temp-buffer
  992. (insert-file-contents file)
  993. (read (current-buffer)))))))
  994. (defun slime-repl-read-history-filename ()
  995. (read-file-name "Use SLIME REPL history from file: "
  996. slime-repl-history-file))
  997. (defun slime-repl-save-merged-history (&optional filename)
  998. "Read the history file, merge the current REPL history and save it.
  999. This tries to be smart in merging the history from the file and the
  1000. current history in that it tries to detect the unique entries using
  1001. `slime-repl-merge-histories'."
  1002. (interactive (list (slime-repl-read-history-filename)))
  1003. (let ((file (or filename slime-repl-history-file)))
  1004. (with-temp-message "saving history..."
  1005. (let ((hist (slime-repl-merge-histories (slime-repl-read-history file t)
  1006. slime-repl-input-history)))
  1007. (slime-repl-save-history file hist)))))
  1008. (defun slime-repl-save-history (&optional filename history)
  1009. "Simply save the current SLIME REPL history to a file.
  1010. When SLIME is setup to always load the old history and one uses only
  1011. one instance of slime all the time, there is no need to merge the
  1012. files and this function is sufficient.
  1013. When the list is longer than `slime-repl-history-size' it will be
  1014. truncated. That part is untested, though!"
  1015. (interactive (list (slime-repl-read-history-filename)))
  1016. (let ((file (or filename slime-repl-history-file))
  1017. (hist (or history slime-repl-input-history)))
  1018. (unless (file-writable-p file)
  1019. (error (format "History file not writable: %s" file)))
  1020. (let ((hist (cl-subseq hist 0 (min (length hist) slime-repl-history-size))))
  1021. ;;(message "saving %s to %s\n" hist file)
  1022. (with-temp-file file
  1023. (let ((cs slime-repl-history-file-coding-system)
  1024. (print-length nil) (print-level nil))
  1025. (setq buffer-file-coding-system cs)
  1026. (insert (format ";; -*- coding: %s -*-\n" cs))
  1027. (insert ";; History for SLIME REPL. Automatically written.\n"
  1028. ";; Edit only if you know what you're doing\n")
  1029. (prin1 (mapcar #'substring-no-properties hist) (current-buffer)))))))
  1030. (defun slime-repl-save-all-histories ()
  1031. "Save the history in each repl buffer."
  1032. (dolist (b (buffer-list))
  1033. (with-current-buffer b
  1034. (when (eq major-mode 'slime-repl-mode)
  1035. (slime-repl-safe-save-merged-history)))))
  1036. (defun slime-repl-safe-save-merged-history ()
  1037. (slime-repl-call-with-handler
  1038. #'slime-repl-save-merged-history
  1039. "%S while saving the history. Continue? "))
  1040. (defun slime-repl-safe-load-history ()
  1041. (slime-repl-call-with-handler
  1042. #'slime-repl-load-history
  1043. "%S while loading the history. Continue? "))
  1044. (defun slime-repl-call-with-handler (fun query)
  1045. "Call FUN in the context of an error handler.
  1046. The handler will use qeuery to ask the use if the error should be ingored."
  1047. (condition-case err
  1048. (funcall fun)
  1049. (error
  1050. (if (y-or-n-p (format query (error-message-string err)))
  1051. nil
  1052. (signal (car err) (cdr err))))))
  1053. ;;;;; REPL Read Mode
  1054. (defvar slime-repl-read-mode-map
  1055. (let ((map (make-sparse-keymap)))
  1056. (define-key map "\C-m" 'slime-repl-return)
  1057. (define-key map [return] 'slime-repl-return)
  1058. (define-key map (kbd "TAB") 'self-insert-command)
  1059. (define-key map "\C-c\C-b" 'slime-repl-read-break)
  1060. (define-key map "\C-c\C-c" 'slime-repl-read-break)
  1061. (define-key map [remap slime-indent-and-complete-symbol] 'ignore)
  1062. (define-key map [remap slime-handle-repl-shortcut] 'self-insert-command)
  1063. map))
  1064. (define-minor-mode slime-repl-read-mode
  1065. "Mode to read input from Emacs
  1066. \\{slime-repl-read-mode-map}"
  1067. nil
  1068. "[read]")
  1069. (make-variable-buffer-local
  1070. (defvar slime-read-string-threads nil))
  1071. (make-variable-buffer-local
  1072. (defvar slime-read-string-tags nil))
  1073. (defun slime-repl-read-string (thread tag)
  1074. (slime-switch-to-output-buffer)
  1075. (push thread slime-read-string-threads)
  1076. (push tag slime-read-string-tags)
  1077. (goto-char (point-max))
  1078. (slime-mark-output-end)
  1079. (slime-mark-input-start)
  1080. (slime-repl-read-mode 1))
  1081. (defun slime-repl-return-string (string)
  1082. (slime-dispatch-event `(:emacs-return-string
  1083. ,(pop slime-read-string-threads)
  1084. ,(pop slime-read-string-tags)
  1085. ,string))
  1086. (slime-repl-read-mode -1))
  1087. (defun slime-repl-read-break ()
  1088. (interactive)
  1089. (slime-dispatch-event `(:emacs-interrupt ,(car slime-read-string-threads))))
  1090. (defun slime-repl-abort-read (thread tag)
  1091. (with-current-buffer (slime-output-buffer)
  1092. (pop slime-read-string-threads)
  1093. (pop slime-read-string-tags)
  1094. (slime-repl-read-mode -1)
  1095. (message "Read aborted")))
  1096. ;;;;; REPL handlers
  1097. (cl-defstruct (slime-repl-shortcut (:conc-name slime-repl-shortcut.))
  1098. symbol names handler one-liner)
  1099. (defvar slime-repl-shortcut-table nil
  1100. "A list of slime-repl-shortcuts")
  1101. (defvar slime-repl-shortcut-history '()
  1102. "History list of shortcut command names.")
  1103. (defvar slime-within-repl-shortcut-handler-p nil
  1104. "Bound to T if we're in a REPL shortcut handler invoked from the REPL.")
  1105. (defun slime-handle-repl-shortcut ()
  1106. (interactive)
  1107. (if (> (point) slime-repl-input-start-mark)
  1108. (insert (string slime-repl-shortcut-dispatch-char))
  1109. (let ((shortcut (slime-lookup-shortcut
  1110. (completing-read "Command: "
  1111. (slime-bogus-completion-alist
  1112. (slime-list-all-repl-shortcuts))
  1113. nil t nil
  1114. 'slime-repl-shortcut-history))))
  1115. (with-struct (slime-repl-shortcut. handler) shortcut
  1116. (let ((slime-within-repl-shortcut-handler-p t))
  1117. (call-interactively handler))))))
  1118. (defun slime-list-all-repl-shortcuts ()
  1119. (loop for shortcut in slime-repl-shortcut-table
  1120. append (slime-repl-shortcut.names shortcut)))
  1121. (defun slime-lookup-shortcut (name)
  1122. (cl-find-if (lambda (s) (member name (slime-repl-shortcut.names s)))
  1123. slime-repl-shortcut-table))
  1124. (defmacro defslime-repl-shortcut (elisp-name names &rest options)
  1125. "Define a new repl shortcut. ELISP-NAME is a symbol specifying
  1126. the name of the interactive function to create, or NIL if no
  1127. function should be created.
  1128. NAMES is a list of \(full-name . aliases\).
  1129. OPTIONS is an plist specifying the handler doing the actual work
  1130. of the shortcut \(`:handler'\), and a help text \(`:one-liner'\)."
  1131. `(progn
  1132. ,(when elisp-name
  1133. `(defun ,elisp-name ()
  1134. (interactive)
  1135. (call-interactively ,(second (assoc :handler options)))))
  1136. (let ((new-shortcut (make-slime-repl-shortcut
  1137. :symbol ',elisp-name
  1138. :names (list ,@names)
  1139. ,@(apply #'append options))))
  1140. (setq slime-repl-shortcut-table
  1141. (cl-remove-if (lambda (s)
  1142. (member ',(car names) (slime-repl-shortcut.names s)))
  1143. slime-repl-shortcut-table))
  1144. (push new-shortcut slime-repl-shortcut-table)
  1145. ',elisp-name)))
  1146. (defun slime-repl-shortcut-eval (sexp &optional package)
  1147. "This function should be used by REPL shortcut handlers instead
  1148. of `slime-eval' to evaluate their final expansion. (This
  1149. expansion will be added to the REPL's history.)"
  1150. (when slime-within-repl-shortcut-handler-p ; were we invoked via ,foo?
  1151. (slime-repl-add-to-input-history (prin1-to-string sexp)))
  1152. (slime-eval sexp package))
  1153. (defun slime-repl-shortcut-eval-async (sexp &optional cont package)
  1154. "This function should be used by REPL shortcut handlers instead
  1155. of `slime-eval-async' to evaluate their final expansion. (This
  1156. expansion will be added to the REPL's history.)"
  1157. (when slime-within-repl-shortcut-handler-p ; were we invoked via ,foo?
  1158. (slime-repl-add-to-input-history (prin1-to-string sexp)))
  1159. (slime-eval-async sexp cont package))
  1160. (defun slime-list-repl-short-cuts ()
  1161. (interactive)
  1162. (slime-with-popup-buffer ((slime-buffer-name :repl-help))
  1163. (let ((table (cl-sort (cl-copy-list slime-repl-shortcut-table) #'string<
  1164. :key (lambda (x)
  1165. (car (slime-repl-shortcut.names x))))))
  1166. (save-excursion
  1167. (dolist (shortcut table)
  1168. (let ((names (slime-repl-shortcut.names shortcut)))
  1169. (insert (pop names)) ;; first print the "full" name
  1170. (when names
  1171. ;; we also have aliases
  1172. (insert " (aka ")
  1173. (while (cdr names)
  1174. (insert (pop names) ", "))
  1175. (insert (car names) ")"))
  1176. (when (slime-repl-shortcut.one-liner shortcut)
  1177. (insert "\n " (slime-repl-shortcut.one-liner shortcut)))
  1178. (insert "\n")))))))
  1179. (defun slime-save-some-lisp-buffers ()
  1180. (if slime-repl-only-save-lisp-buffers
  1181. (save-some-buffers nil (lambda ()
  1182. (and (memq major-mode slime-lisp-modes)
  1183. (not (null buffer-file-name)))))
  1184. (save-some-buffers)))
  1185. (defun slime-kill-all-buffers ()
  1186. "Kill all the SLIME-related buffers."
  1187. (dolist (buf (buffer-list))
  1188. (when (or (string= (buffer-name buf) slime-event-buffer-name)
  1189. (string-match "^\\*inferior-lisp*" (buffer-name buf))
  1190. (string-match "^\\*slime-repl .*\\*$" (buffer-name buf))
  1191. (string-match "^\\*sldb .*\\*$" (buffer-name buf))
  1192. (string-match "^\\*SLIME.*\\*$" (buffer-name buf)))
  1193. (kill-buffer buf))))
  1194. (defslime-repl-shortcut slime-repl-shortcut-help ("help")
  1195. (:handler 'slime-list-repl-short-cuts)
  1196. (:one-liner "Display the help."))
  1197. (defslime-repl-shortcut nil ("change-directory" "!d" "cd")
  1198. (:handler 'slime-set-default-directory)
  1199. (:one-liner "Change the current directory."))
  1200. (defslime-repl-shortcut nil ("pwd")
  1201. (:handler (lambda ()
  1202. (interactive)
  1203. (let ((dir (slime-eval `(swank:default-directory))))
  1204. (message "Directory %s" dir))))
  1205. (:one-liner "Show the current directory."))
  1206. (defslime-repl-shortcut slime-repl-push-directory
  1207. ("push-directory" "+d" "pushd")
  1208. (:handler (lambda (directory)
  1209. (interactive
  1210. (list (read-directory-name
  1211. "Push directory: "
  1212. (slime-eval '(swank:default-directory))
  1213. nil nil "")))
  1214. (push (slime-eval '(swank:default-directory))
  1215. slime-repl-directory-stack)
  1216. (slime-set-default-directory directory)))
  1217. (:one-liner "Save the current directory and set it to a new one."))
  1218. (defslime-repl-shortcut slime-repl-pop-directory
  1219. ("pop-directory" "-d" "popd")
  1220. (:handler (lambda ()
  1221. (interactive)
  1222. (if (null slime-repl-directory-stack)
  1223. (message "Directory stack is empty.")
  1224. (slime-set-default-directory
  1225. (pop slime-repl-directory-stack)))))
  1226. (:one-liner "Restore the last saved directory."))
  1227. (defslime-repl-shortcut nil ("change-package" "!p" "in-package" "in")
  1228. (:handler 'slime-repl-set-package)
  1229. (:one-liner "Change the current package."))
  1230. (defslime-repl-shortcut slime-repl-push-package ("push-package" "+p")
  1231. (:handler (lambda (package)
  1232. (interactive (list (slime-read-package-name "Package: ")))
  1233. (push (slime-lisp-package) slime-repl-package-stack)
  1234. (slime-repl-set-package package)))
  1235. (:one-liner "Save the current package and set it to a new one."))
  1236. (defslime-repl-shortcut slime-repl-pop-package ("pop-package" "-p")
  1237. (:handler (lambda ()
  1238. (interactive)
  1239. (if (null slime-repl-package-stack)
  1240. (message "Package stack is empty.")
  1241. (slime-repl-set-package
  1242. (pop slime-repl-package-stack)))))
  1243. (:one-liner "Restore the last saved package."))
  1244. (defslime-repl-shortcut slime-repl-resend ("resend-form")
  1245. (:handler (lambda ()
  1246. (interactive)
  1247. (insert (car slime-repl-input-history))
  1248. (insert "\n")
  1249. (slime-repl-send-input)))
  1250. (:one-liner "Resend the last form."))
  1251. (defslime-repl-shortcut slime-repl-disconnect ("disconnect")
  1252. (:handler 'slime-disconnect)
  1253. (:one-liner "Disconnect the current connection."))
  1254. (defslime-repl-shortcut slime-repl-disconnect-all ("disconnect-all")
  1255. (:handler 'slime-disconnect-all)
  1256. (:one-liner "Disconnect all connections."))
  1257. (defslime-repl-shortcut slime-repl-sayoonara ("sayoonara")
  1258. (:handler (lambda ()
  1259. (interactive)
  1260. (when (slime-connected-p)
  1261. (slime-quit-lisp))
  1262. (slime-kill-all-buffers)))
  1263. (:one-liner "Quit all Lisps and close all SLIME buffers."))
  1264. (defslime-repl-shortcut slime-repl-quit ("quit")
  1265. (:handler (lambda ()
  1266. (interactive)
  1267. ;; `slime-quit-lisp' determines the connection to quit
  1268. ;; on behalf of the REPL's `slime-buffer-connection'.
  1269. (let ((repl-buffer (slime-output-buffer)))
  1270. (slime-quit-lisp)
  1271. (kill-buffer repl-buffer))))
  1272. (:one-liner "Quit the current Lisp."))
  1273. (defslime-repl-shortcut slime-repl-defparameter ("defparameter" "!")
  1274. (:handler (lambda (name value)
  1275. (interactive (list (slime-read-symbol-name "Name (symbol): " t)
  1276. (slime-read-from-minibuffer "Value: " "*")))
  1277. (insert "(cl:defparameter " name " " value
  1278. " \"REPL generated global variable.\")")
  1279. (slime-repl-send-input t)))
  1280. (:one-liner "Define a new global, special, variable."))
  1281. (defslime-repl-shortcut slime-repl-compile-and-load ("compile-and-load" "cl")
  1282. (:handler (lambda (filename)
  1283. (interactive (list (expand-file-name
  1284. (read-file-name "File: " nil nil nil nil))))
  1285. (slime-save-some-lisp-buffers)
  1286. (slime-repl-shortcut-eval-async
  1287. `(swank:compile-file-if-needed
  1288. ,(slime-to-lisp-filename filename) t)
  1289. #'slime-compilation-finished)))
  1290. (:one-liner "Compile (if neccessary) and load a lisp file."))
  1291. (defslime-repl-shortcut nil ("restart-inferior-lisp")
  1292. (:handler 'slime-restart-inferior-lisp)
  1293. (:one-liner "Restart *inferior-lisp* and reconnect SLIME."))
  1294. (defun slime-redirect-inferior-output (&optional noerror)
  1295. "Redirect output of the inferior-process to the REPL buffer."
  1296. (interactive)
  1297. (let ((proc (slime-inferior-process)))
  1298. (cond (proc
  1299. (let ((filter (slime-rcurry #'slime-inferior-output-filter
  1300. (slime-current-connection))))
  1301. (set-process-filter proc filter)))
  1302. (noerror)
  1303. (t (error "No inferior lisp process")))))
  1304. (defun slime-inferior-output-filter (proc string conn)
  1305. (cond ((eq (process-status conn) 'closed)
  1306. (message "Connection closed. Removing inferior output filter.")
  1307. (message "Lost output: %S" string)
  1308. (set-process-filter proc nil))
  1309. (t
  1310. (slime-output-filter conn string))))
  1311. (defun slime-redirect-trace-output ()
  1312. "Redirect the trace output to a separate Emacs buffer."
  1313. (interactive)
  1314. (let ((buffer (get-buffer-create (slime-buffer-name :trace))))
  1315. (with-current-buffer buffer
  1316. (let ((marker (copy-marker (buffer-size)))
  1317. (target (incf slime-last-output-target-id)))
  1318. (puthash target marker slime-output-target-to-marker)
  1319. (slime-eval `(swank-repl:redirect-trace-output ,target))))
  1320. ;; Note: We would like the entries in
  1321. ;; slime-output-target-to-marker to disappear when the buffers are
  1322. ;; killed. We cannot just make the hash-table ":weakness 'value"
  1323. ;; -- there is no reference from the buffers to the markers in the
  1324. ;; buffer, so entries would disappear even though the buffers are
  1325. ;; alive. Best solution might be to make buffer-local variables
  1326. ;; that keep the markers. --mkoeppe
  1327. (pop-to-buffer buffer)))
  1328. (defun slime-call-defun ()
  1329. "Insert a call to the toplevel form defined around point into the REPL."
  1330. (interactive)
  1331. (cl-labels ((insert-call
  1332. (name &key (function t)
  1333. defclass)
  1334. (let* ((setf (and function
  1335. (consp name)
  1336. (= (length name) 2)
  1337. (eql (car name) 'setf)))
  1338. (symbol (if setf
  1339. (cadr name)
  1340. name))
  1341. (qualified-symbol-name
  1342. (slime-qualify-cl-symbol-name symbol))
  1343. (symbol-name (slime-cl-symbol-name qualified-symbol-name))
  1344. (symbol-package (slime-cl-symbol-package
  1345. qualified-symbol-name))
  1346. (call (if (cl-equalp (slime-lisp-package) symbol-package)
  1347. symbol-name
  1348. qualified-symbol-name)))
  1349. (slime-switch-to-output-buffer)
  1350. (goto-char slime-repl-input-start-mark)
  1351. (insert (if function
  1352. "("
  1353. " "))
  1354. (when setf
  1355. (insert "setf ("))
  1356. (if defclass
  1357. (insert "make-instance '"))
  1358. (insert call)
  1359. (cond (setf
  1360. (insert " ")
  1361. (save-excursion (insert ") )")))
  1362. (function
  1363. (insert " ")
  1364. (save-excursion (insert ")"))))
  1365. (unless function
  1366. (goto-char slime-repl-input-start-mark)))))
  1367. (let ((toplevel (slime-parse-toplevel-form)))
  1368. (if (symbolp toplevel)
  1369. (error "Not in a function definition")
  1370. (slime-dcase toplevel
  1371. (((:defun :defgeneric :defmacro :define-compiler-macro) symbol)
  1372. (insert-call symbol))
  1373. ((:defmethod symbol &rest args)
  1374. (declare (ignore args))
  1375. (insert-call symbol))
  1376. (((:defparameter :defvar :defconstant) symbol)
  1377. (insert-call symbol :function nil))
  1378. (((:defclass) symbol)
  1379. (insert-call symbol :defclass t))
  1380. (t
  1381. (error "Not in a function definition")))))))
  1382. (defun slime-repl-copy-down-to-repl (slimefun &rest args)
  1383. (slime-eval-async `(swank-repl:listener-save-value ',slimefun ,@args)
  1384. #'(lambda (_ignored)
  1385. (with-current-buffer (slime-repl)
  1386. (slime-eval-async '(swank-repl:listener-get-value)
  1387. #'(lambda (_ignored)
  1388. (slime-repl-insert-prompt)))))))
  1389. (defun slime-inspector-copy-down-to-repl (number)
  1390. "Evaluate the inspector slot at point via the REPL (to set `*')."
  1391. (interactive (list (or (get-text-property (point) 'slime-part-number)
  1392. (error "No part at point"))))
  1393. (slime-repl-copy-down-to-repl 'swank:inspector-nth-part number))
  1394. (defun sldb-copy-down-to-repl (frame-id var-id)
  1395. "Evaluate the frame var at point via the REPL (to set `*')."
  1396. (interactive (list (sldb-frame-number-at-point) (sldb-var-number-at-point)))
  1397. (slime-repl-copy-down-to-repl 'swank/backend:frame-var-value frame-id var-id))
  1398. (defun sldb-insert-frame-call-to-repl ()
  1399. "Insert a call to a frame at point."
  1400. (interactive)
  1401. (let ((call (slime-eval `(swank/backend::frame-call
  1402. ,(sldb-frame-number-at-point)))))
  1403. (slime-switch-to-output-buffer)
  1404. (if (>= (point) slime-repl-prompt-start-mark)
  1405. (insert call)
  1406. (save-excursion
  1407. (goto-char (point-max))
  1408. (insert call))))
  1409. (slime-repl))
  1410. (defun slime-set-default-directory (directory)
  1411. "Make DIRECTORY become Lisp's current directory."
  1412. (interactive (list (read-directory-name "Directory: " nil nil t)))
  1413. (let ((dir (expand-file-name directory)))
  1414. (message "default-directory: %s"
  1415. (slime-from-lisp-filename
  1416. (slime-repl-shortcut-eval `(swank:set-default-directory
  1417. ,(slime-to-lisp-filename dir)))))
  1418. (with-current-buffer (slime-output-buffer)
  1419. (setq default-directory dir))))
  1420. (defun slime-sync-package-and-default-directory ()
  1421. "Set Lisp's package and directory to the values in current buffer."
  1422. (interactive)
  1423. (let* ((package (slime-current-package))
  1424. (exists-p (or (null package)
  1425. (slime-eval `(cl:packagep
  1426. (swank::guess-package ,package)))))
  1427. (directory default-directory))
  1428. (when (and package exists-p)
  1429. (slime-repl-set-package package))
  1430. (slime-set-default-directory directory)
  1431. ;; Sync *inferior-lisp* dir
  1432. (let* ((proc (slime-process))
  1433. (buffer (and proc (process-buffer proc))))
  1434. (when (buffer-live-p buffer)
  1435. (with-current-buffer buffer
  1436. (setq default-directory directory))))
  1437. (message "package: %s%s directory: %s"
  1438. (with-current-buffer (slime-output-buffer)
  1439. (slime-lisp-package))
  1440. (if exists-p "" (format " (package %s doesn't exist)" package))
  1441. directory)))
  1442. (defun slime-goto-connection ()
  1443. "Switch to the REPL buffer for the connection at point."
  1444. (interactive)
  1445. (let ((slime-dispatching-connection (slime-connection-at-point)))
  1446. (switch-to-buffer (slime-output-buffer))))
  1447. (defun slime-repl-inside-string-or-comment-p ()
  1448. (save-restriction
  1449. (when (and (boundp 'slime-repl-input-start-mark)
  1450. slime-repl-input-start-mark
  1451. (>= (point) slime-repl-input-start-mark))
  1452. (narrow-to-region slime-repl-input-start-mark (point)))
  1453. (slime-inside-string-or-comment-p)))
  1454. (defvar slime-repl-easy-menu
  1455. (let ((C '(slime-connected-p)))
  1456. `("REPL"
  1457. [ "Send Input" slime-repl-return ,C ]
  1458. [ "Close and Send Input " slime-repl-closing-return ,C ]
  1459. [ "Interrupt Lisp process" slime-interrupt ,C ]
  1460. "--"
  1461. [ "Previous Input" slime-repl-previous-input t ]
  1462. [ "Next Input" slime-repl-next-input t ]
  1463. [ "Goto Previous Prompt " slime-repl-previous-prompt t ]
  1464. [ "Goto Next Prompt " slime-repl-next-prompt t ]
  1465. [ "Clear Last Output" slime-repl-clear-output t ]
  1466. [ "Clear Buffer " slime-repl-clear-buffer t ]
  1467. [ "Kill Current Input" slime-repl-kill-input t ])))
  1468. (defun slime-repl-add-easy-menu ()
  1469. (easy-menu-define menubar-slime-repl slime-repl-mode-map
  1470. "REPL" slime-repl-easy-menu)
  1471. (easy-menu-define menubar-slime slime-repl-mode-map
  1472. "SLIME" slime-easy-menu)
  1473. (easy-menu-add slime-repl-easy-menu 'slime-repl-mode-map))
  1474. (add-hook 'slime-repl-mode-hook 'slime-repl-add-easy-menu)
  1475. (defun slime-hide-inferior-lisp-buffer ()
  1476. "Display the REPL buffer instead of the *inferior-lisp* buffer."
  1477. (let* ((buffer (if (slime-process)
  1478. (process-buffer (slime-process))))
  1479. (window (if buffer (get-buffer-window buffer t)))
  1480. (repl-buffer (slime-output-buffer t))
  1481. (repl-window (get-buffer-window repl-buffer)))
  1482. (when buffer
  1483. (bury-buffer buffer))
  1484. (cond (repl-window
  1485. (when window
  1486. (delete-window window)))
  1487. (window
  1488. (set-window-buffer window repl-buffer))
  1489. (t
  1490. (pop-to-buffer repl-buffer)
  1491. (goto-char (point-max))))))
  1492. (defun slime-repl-choose-coding-system ()
  1493. (let ((candidates (slime-connection-coding-systems)))
  1494. (or (cl-find (symbol-name (car default-process-coding-system))
  1495. candidates
  1496. :test (lambda (s1 s2)
  1497. (if (fboundp 'coding-system-equal)
  1498. (coding-system-equal (intern s1) (intern s2)))))
  1499. (car candidates)
  1500. (error "Can't find suitable coding-system"))))
  1501. (defun slime-repl-connected-hook-function ()
  1502. (destructuring-bind (package prompt)
  1503. (let ((slime-current-thread t)
  1504. (cs (slime-repl-choose-coding-system)))
  1505. (slime-eval `(swank-repl:create-repl nil :coding-system ,cs)))
  1506. (setf (slime-lisp-package) package)
  1507. (setf (slime-lisp-package-prompt-string) prompt))
  1508. (slime-hide-inferior-lisp-buffer)
  1509. (slime-init-output-buffer (slime-connection)))
  1510. (defun slime-repl-event-hook-function (event)
  1511. (slime-dcase event
  1512. ((:write-string output &optional target)
  1513. (slime-write-string output target)
  1514. t)
  1515. ((:read-string thread tag)
  1516. (assert thread)
  1517. (slime-repl-read-string thread tag)
  1518. t)
  1519. ((:read-aborted thread tag)
  1520. (slime-repl-abort-read thread tag)
  1521. t)
  1522. ((:open-dedicated-output-stream port coding-system)
  1523. (slime-open-stream-to-lisp port coding-system)
  1524. t)
  1525. ((:new-package package prompt-string)
  1526. (setf (slime-lisp-package) package)
  1527. (setf (slime-lisp-package-prompt-string) prompt-string)
  1528. (let ((buffer (slime-connection-output-buffer)))
  1529. (when (buffer-live-p buffer)
  1530. (with-current-buffer buffer
  1531. (setq slime-buffer-package package))))
  1532. t)
  1533. (t nil)))
  1534. (defun slime-change-repl-to-default-connection ()
  1535. "Change current REPL to the REPL of the default connection.
  1536. If the current buffer is not a REPL, don't do anything."
  1537. (when (equal major-mode 'slime-repl-mode)
  1538. (let ((slime-buffer-connection slime-default-connection))
  1539. (pop-to-buffer-same-window (slime-connection-output-buffer)))))
  1540. (defun slime-repl-find-buffer-package ()
  1541. (or (slime-search-buffer-package)
  1542. (slime-lisp-package)))
  1543. (defun slime-repl-add-hooks ()
  1544. (add-hook 'slime-event-hooks 'slime-repl-event-hook-function)
  1545. (add-hook 'slime-connected-hook 'slime-repl-connected-hook-function)
  1546. (add-hook 'slime-cycle-connections-hook
  1547. 'slime-change-repl-to-default-connection))
  1548. (defun slime-repl-remove-hooks ()
  1549. (remove-hook 'slime-event-hooks 'slime-repl-event-hook-function)
  1550. (remove-hook 'slime-connected-hook 'slime-repl-connected-hook-function)
  1551. (remove-hook 'slime-cycle-connections-hook
  1552. 'slime-change-repl-to-default-connection))
  1553. (defun slime-repl-sexp-at-point ()
  1554. "Returns the current sexp at point (or NIL if none is found)
  1555. while ignoring the repl prompt text."
  1556. (if (<= slime-repl-input-start-mark (point))
  1557. (save-restriction
  1558. (narrow-to-region slime-repl-input-start-mark (point-max))
  1559. (slime-sexp-at-point))
  1560. (slime-sexp-at-point)))
  1561. (defun slime-repl-inspect (string)
  1562. (interactive
  1563. (list (slime-read-from-minibuffer "Inspect value (evaluated): "
  1564. (slime-repl-sexp-at-point))))
  1565. (slime-inspect string))
  1566. (require 'bytecomp)
  1567. ;; (mapc (lambda (sym)
  1568. ;; (cond ((fboundp sym)
  1569. ;; (unless (byte-code-function-p (symbol-function sym))
  1570. ;; (byte-compile sym)))
  1571. ;; (t (error "%S is not fbound" sym))))
  1572. ;; '(slime-repl-event-hook-function
  1573. ;; slime-write-string
  1574. ;; slime-repl-write-string
  1575. ;; slime-repl-emit
  1576. ;; slime-repl-show-maximum-output))
  1577. (provide 'slime-repl)