geiser-repl.el (44881B)
1 ;;; geiser-repl.el --- Geiser's REPL -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2009-2013, 2015-2016, 2018-2022 Jose Antonio Ortega Ruiz 4 5 ;; This program is free software; you can redistribute it and/or 6 ;; modify it under the terms of the Modified BSD License. You should 7 ;; have received a copy of the license along with this program. If 8 ;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>. 9 10 11 ;;; Code: 12 13 (require 'geiser-capf) 14 (require 'geiser-doc) 15 (require 'geiser-autodoc) 16 (require 'geiser-edit) 17 (require 'geiser-completion) 18 (require 'geiser-syntax) 19 (require 'geiser-impl) 20 (require 'geiser-eval) 21 (require 'geiser-connection) 22 (require 'geiser-menu) 23 (require 'geiser-image) 24 (require 'geiser-custom) 25 (require 'geiser-base) 26 27 (require 'comint) 28 (require 'compile) 29 (require 'scheme) 30 (require 'font-lock) 31 (require 'project) 32 33 (eval-when-compile (require 'subr-x)) 34 35 36 ;;; Customization: 37 38 (defgroup geiser-repl nil 39 "Interacting with the Geiser REPL." 40 :group 'geiser) 41 42 (geiser-custom--defcustom geiser-repl-buffer-name-function 43 'geiser-repl-buffer-name 44 "Function used to define the name of a REPL buffer. 45 The function is called with a single argument - an implementation 46 symbol (e.g., `guile', `chicken', etc.)." 47 :type '(choice (function-item geiser-repl-buffer-name) 48 (function :tag "Other function"))) 49 50 (geiser-custom--defcustom geiser-repl-per-project-p nil 51 "Whether to spawn a separate REPL per project. 52 See also `geiser-repl-current-project-function' for the function 53 used to discover a buffer's project." 54 :type 'boolean) 55 56 (defun geiser-repl-project-root () 57 "Use project.el, to determine a buffer's project root." 58 (when-let (p (project-current)) (project-root p))) 59 60 (geiser-custom--defcustom geiser-repl-current-project-function 61 #'geiser-repl-project-root 62 "Function used to determine the current project. 63 The function is called from both source and REPL buffers, and 64 should return a value which uniquely identifies the project." 65 :type '(choice (function-item :tag "Ignore projects" ignore) 66 (function-item :tag "Use project.el" geiser-repl-project-root) 67 (function-item :tag "Use projectile" projectile-project-root) 68 (function :tag "Other function"))) 69 70 (geiser-custom--defcustom geiser-repl-use-other-window t 71 "Whether to Use a window other than the current buffer's when 72 switching to the Geiser REPL buffer." 73 :type 'boolean) 74 75 (geiser-custom--defcustom geiser-repl-window-allow-split t 76 "Whether to allow window splitting when switching to the Geiser REPL buffer." 77 :type 'boolean) 78 79 (geiser-custom--defcustom geiser-repl-history-filename 80 (expand-file-name "~/.geiser_history") 81 "File where REPL input history is saved, so that it persists between sessions. 82 83 This is actually the base name: the concrete Scheme 84 implementation name gets appended to it." 85 :type 'file) 86 87 (geiser-custom--defcustom geiser-repl-history-size comint-input-ring-size 88 "Maximum size of the saved REPL input history." 89 :type 'integer) 90 91 (geiser-custom--defcustom geiser-repl-history-no-dups-p t 92 "Whether to skip duplicates when recording history." 93 :type 'boolean) 94 95 (geiser-custom--defcustom geiser-repl-save-debugging-history-p t 96 "Whether to save debugging input in REPL history. 97 98 By default, REPL interactions while scheme is in the debugger are 99 not added to the REPL command history. Set this variable to t to 100 change that." 101 :type 'boolean) 102 103 (geiser-custom--defcustom geiser-repl-autodoc-p t 104 "Whether to enable `geiser-autodoc-mode' in the REPL by default." 105 :type 'boolean) 106 107 (geiser-custom--defcustom geiser-repl-read-only-prompt-p t 108 "Whether the REPL's prompt should be read-only." 109 :type 'boolean) 110 111 (geiser-custom--defcustom geiser-repl-read-only-output-p t 112 "Whether the REPL's output should be read-only." 113 :type 'boolean) 114 115 (geiser-custom--defcustom geiser-repl-highlight-output-p nil 116 "Whether to syntax highlight REPL output." 117 :type 'boolean) 118 119 (geiser-custom--defcustom geiser-repl-auto-indent-p t 120 "Whether newlines for incomplete sexps are autoindented." 121 :type 'boolean) 122 123 (geiser-custom--defcustom geiser-repl-send-on-return-p t 124 "Wheter to Send input to REPL when ENTER is pressed in a balanced S-expression, 125 regardless of cursor positioning. 126 127 When off, pressing ENTER inside a balance S-expression will 128 introduce a new line without sending input to the inferior 129 Scheme process. This option is useful when using minor modes 130 which might do parentheses balancing, or when entering additional 131 arguments inside an existing expression. 132 133 When on (the default), pressing ENTER inside a balanced S-expression 134 will send the input to the inferior Scheme process regardless of the 135 cursor placement." 136 :type 'boolean) 137 138 (geiser-custom--defcustom geiser-repl-forget-old-errors-p t 139 "Whether to forget old errors upon entering a new expression. 140 141 When on (the default), every time a new expression is entered in 142 the REPL old error messages are flushed, and using \\[next-error] 143 afterwards will jump only to error locations produced by the new 144 expression, if any." 145 :type 'boolean) 146 147 (geiser-custom--defcustom geiser-repl-skip-version-check-p nil 148 "Whether to skip version checks for the Scheme executable. 149 150 When set, Geiser won't check the version of the Scheme 151 interpreter when starting a REPL, saving a few tenths of a 152 second." 153 :type 'boolean) 154 155 (geiser-custom--defcustom geiser-repl-query-on-exit-p nil 156 "Whether to prompt for confirmation on \\[geiser-repl-exit]." 157 :type 'boolean) 158 159 (geiser-custom--defcustom geiser-repl-delete-last-output-on-exit-p nil 160 "Whether to delete partial outputs when the REPL's process exits." 161 :type 'boolean) 162 163 (geiser-custom--defcustom geiser-repl-query-on-kill-p t 164 "Whether to prompt for confirmation when killing a REPL buffer with 165 a life process." 166 :type 'boolean) 167 168 (geiser-custom--defcustom geiser-repl-default-host "localhost" 169 "Default host when connecting to remote REPLs." 170 :type 'string) 171 172 (geiser-custom--defcustom geiser-repl-default-port 37146 173 "Default port for connecting to remote REPLs." 174 :type 'integer) 175 176 (geiser-custom--defcustom geiser-repl-startup-time 10000 177 "Time, in milliseconds, to wait for Racket to startup. 178 If you have a slow system, try to increase this time." 179 :type 'integer) 180 181 (geiser-custom--defcustom geiser-repl-inline-images-p t 182 "Whether to display inline images in the REPL." 183 :type 'boolean) 184 185 (geiser-custom--defcustom geiser-repl-auto-display-images-p t 186 "Whether to automatically invoke the external viewer to display 187 images popping up in the REPL. 188 189 See also `geiser-debug-auto-display-images'." 190 :type 'boolean) 191 192 (geiser-custom--defcustom geiser-repl-add-project-paths t 193 "Whether to automatically add current project's root to load path on startup. 194 195 If set to `t' (the default), the directory returned by 196 `geiser-repl-current-project-function' is added to the load path. 197 198 If set to a list of sudirectories (e.g. (\".\" \"src\" \"tests\")), 199 their full path (starting with the project's root, is added 200 instead. 201 202 This variable is a good candidate for .dir-locals.el. 203 204 This option has no effect if no project root is found." 205 :type '(choice boolean (list string))) 206 207 (geiser-custom--defcustom geiser-repl-startup-hook nil 208 "Functions run right after a REPL has started and is fully set up. 209 210 See also `geiser-repl-startup-forms'." 211 :type 'hook) 212 213 (geiser-custom--defcustom geiser-repl-startup-forms nil 214 "List scheme forms, as strings, sent to a REPL on start-up. 215 216 This variable is a good candidate for .dir-locals.el. 217 218 See also `geiser-repl-startup-hook'." 219 :type '(repeat string)) 220 221 (geiser-custom--defface repl-input 222 'comint-highlight-input geiser-repl "evaluated input highlighting") 223 224 (geiser-custom--defface repl-output 225 'font-lock-string-face geiser-repl "REPL output") 226 227 (geiser-custom--defface repl-prompt 228 'comint-highlight-prompt geiser-repl "REPL prompt") 229 230 231 232 ;;; Implementation-dependent parameters 233 234 (geiser-impl--define-caller geiser-repl--binary binary () 235 "A variable or function returning the path to the scheme binary 236 for this implementation.") 237 238 (geiser-impl--define-caller geiser-repl--arglist arglist () 239 "A function taking no arguments and returning a list of 240 arguments to be used when invoking the scheme binary.") 241 242 (geiser-impl--define-caller geiser-repl--prompt-regexp prompt-regexp () 243 "A variable (or thunk returning a value) giving the regular 244 expression for this implementation's geiser scheme prompt.") 245 246 (geiser-impl--define-caller 247 geiser-repl--debugger-prompt-regexp debugger-prompt-regexp () 248 "A variable (or thunk returning a value) giving the regular 249 expression for this implementation's debugging prompt.") 250 251 (geiser-impl--define-caller geiser-repl--startup repl-startup (remote) 252 "Function taking no parameters that is called after the REPL 253 has been initialised. All Geiser functionality is available to 254 you at that point.") 255 256 (geiser-impl--define-caller geiser-repl--enter-cmd enter-command (module) 257 "Function taking a module designator and returning a REPL enter 258 module command as a string") 259 260 (geiser-impl--define-caller geiser-repl--import-cmd import-command (module) 261 "Function taking a module designator and returning a REPL import 262 module command as a string") 263 264 (geiser-impl--define-caller geiser-repl--exit-cmd exit-command () 265 "Function returning the REPL exit command as a string") 266 267 (geiser-impl--define-caller geiser-repl--version version-command (binary) 268 "Function returning the version of the corresponding scheme process, 269 given its full path.") 270 271 (geiser-impl--define-caller geiser-repl--min-version minimum-version () 272 "A variable providing the minimum required scheme version, as a string.") 273 274 (geiser-impl--define-caller geiser-repl--connection-address connection-address () 275 "If this implementation supports a parallel connection, return its address. 276 The implementation is responsible of setting up the listening REPL on 277 startup. When this function returns a non-nil address, a connection 278 will be set up using `geiser-connect-local' when a REPL is started.") 279 280 281 ;;; Geiser REPL buffers and processes: 282 283 (defvar geiser-repl--repls nil) 284 (defvar geiser-repl--closed-repls nil) 285 286 (defvar geiser-repl--last-output-start nil) 287 (defvar geiser-repl--last-output-end nil) 288 289 (defvar-local geiser-repl--repl nil) 290 291 (defvar-local geiser-repl--project nil) 292 293 (defsubst geiser-repl--set-this-buffer-repl (r) 294 (setq geiser-repl--repl r)) 295 296 (defsubst geiser-repl--set-this-buffer-project (p) 297 (setq geiser-repl--project p)) 298 299 (defsubst geiser-repl--current-project () 300 (or (when geiser-repl-per-project-p 301 (funcall geiser-repl-current-project-function)) 302 'no-project)) 303 304 (defun geiser-repl--live-p () 305 (and geiser-repl--repl 306 (get-buffer-process geiser-repl--repl))) 307 308 (defun geiser-repl--repl/impl (impl &optional proj repls) 309 (let ((proj (or proj 310 geiser-repl--project 311 (geiser-repl--current-project))) 312 (repls (or repls 313 geiser-repl--repls))) 314 (catch 'repl 315 (dolist (repl repls) 316 (when (buffer-live-p repl) 317 (with-current-buffer repl 318 (when (and (eq geiser-impl--implementation impl) 319 (equal geiser-repl--project proj)) 320 (throw 'repl repl)))))))) 321 322 (defun geiser-repl--set-up-repl (impl) 323 (or (and (not impl) geiser-repl--repl) 324 (setq geiser-repl--repl 325 (let ((impl (or impl 326 geiser-impl--implementation 327 (geiser-impl--guess)))) 328 (when impl (geiser-repl--repl/impl impl)))))) 329 330 (defun geiser-repl--active-impls () 331 (let ((act)) 332 (dolist (repl geiser-repl--repls act) 333 (with-current-buffer repl 334 (unless (memq geiser-impl--implementation act) 335 (push geiser-impl--implementation act)))))) 336 337 (defsubst geiser-repl--repl-name (impl) 338 (format "%s REPL" (geiser-impl--impl-str impl))) 339 340 (defsubst geiser-repl--buffer-name (impl) 341 (funcall geiser-repl-buffer-name-function impl)) 342 343 (defun geiser-repl-buffer-name (impl) 344 "Return default name of the REPL buffer for implementation IMPL." 345 (let ((repl-name (geiser-repl--repl-name impl)) 346 (current-project (funcall geiser-repl-current-project-function))) 347 (if (and geiser-repl-per-project-p current-project) 348 (let ((project-name (file-name-nondirectory 349 (directory-file-name current-project)))) 350 (format "*Geiser %s: %s*" repl-name project-name)) 351 (format "*Geiser %s*" repl-name)))) 352 353 (defun geiser-repl--switch-to-buffer (buffer) 354 (unless (eq buffer (current-buffer)) 355 (let ((pop-up-windows geiser-repl-window-allow-split)) 356 (if geiser-repl-use-other-window 357 (switch-to-buffer-other-window buffer) 358 (switch-to-buffer buffer))))) 359 360 (defun geiser-repl--to-repl-buffer (impl) 361 (unless (and (eq major-mode 'geiser-repl-mode) 362 (eq geiser-impl--implementation impl) 363 (not (get-buffer-process (current-buffer)))) 364 (let* ((proj (geiser-repl--current-project)) 365 (old (geiser-repl--repl/impl impl proj geiser-repl--closed-repls)) 366 (old (and (buffer-live-p old) 367 (not (get-buffer-process old)) 368 old))) 369 (geiser-repl--switch-to-buffer 370 (or old (generate-new-buffer (geiser-repl--buffer-name impl)))) 371 (unless old 372 (geiser-repl-mode) 373 (geiser-impl--set-buffer-implementation impl) 374 (geiser-repl--set-this-buffer-project proj) 375 (geiser-syntax--add-kws t))))) 376 377 (defun geiser-repl--read-impl (prompt &optional active) 378 (geiser-impl--read-impl prompt (and active (geiser-repl--active-impls)))) 379 380 (defsubst geiser-repl--only-impl-p () 381 (and (null (cdr geiser-active-implementations)) 382 (car geiser-active-implementations))) 383 384 (defun geiser-repl--get-impl (prompt) 385 (or (geiser-repl--only-impl-p) 386 (and (eq major-mode 'geiser-repl-mode) geiser-impl--implementation) 387 (geiser-repl--read-impl prompt))) 388 389 390 ;;; Prompt &co. 391 392 (defun geiser-repl--last-prompt-end () 393 (cond ((and (boundp 'comint-last-prompt) (markerp (cdr comint-last-prompt))) 394 (marker-position (cdr comint-last-prompt))) 395 ((and (boundp 'comint-last-prompt-overlay) comint-last-prompt-overlay) 396 (overlay-end comint-last-prompt-overlay)) 397 (t (save-excursion 398 (geiser-repl--bol) 399 (min (+ 1 (point)) (point-max)))))) 400 401 (defun geiser-repl--last-prompt-start () 402 (cond ((and (boundp 'comint-last-prompt) (markerp (car comint-last-prompt))) 403 (marker-position (car comint-last-prompt))) 404 ((and (boundp 'comint-last-prompt-overlay) comint-last-prompt-overlay) 405 (overlay-start comint-last-prompt-overlay)) 406 (t (save-excursion (geiser-repl--bol) (point))))) 407 408 409 ;;; REPL connections 410 411 (defvar-local geiser-repl--address nil) 412 413 (defvar-local geiser-repl--connection nil) 414 415 (defun geiser-repl--local-p () 416 "Return non-nil, if current REPL is local (connected to socket)." 417 (stringp geiser-repl--address)) 418 419 (defun geiser-repl--remote-p () 420 "Return non-nil, if current REPL is remote (connected to host:port)." 421 (consp geiser-repl--address)) 422 423 (defsubst geiser-repl--host () (car geiser-repl--address)) 424 (defsubst geiser-repl--port () (cdr geiser-repl--address)) 425 426 (defun geiser-repl--read-address (&optional host port) 427 (let ((defhost (or (geiser-repl--host) geiser-repl-default-host)) 428 (defport (or (geiser-repl--port) geiser-repl-default-port))) 429 (cons (or host 430 (read-string (format "Host (default %s): " defhost) 431 nil nil defhost)) 432 (or port (read-number "Port: " defport))))) 433 434 (defun geiser-repl--autodoc-mode (n) 435 (when (or geiser-repl-autodoc-p (< n 0)) 436 (geiser--save-msg (geiser-autodoc-mode n)))) 437 438 (defun geiser-repl--save-remote-data (address) 439 (setq geiser-repl--address address) 440 (cond ((consp address) 441 (setq header-line-format 442 (format "Host: %s Port: %s" 443 (geiser-repl--host) 444 (geiser-repl--port)))) 445 ((stringp address) 446 (setq header-line-format 447 (format "Socket: %s" address))))) 448 449 (defun geiser-repl--fontify-output-region (beg end) 450 "Apply highlighting to a REPL output region." 451 (remove-text-properties beg end '(font-lock-face nil face nil)) 452 (if geiser-repl-highlight-output-p 453 (geiser-syntax--fontify-syntax-region beg end) 454 (geiser-repl--fontify-plaintext beg end))) 455 456 (defun geiser-repl--fontify-plaintext (start end) 457 "Fontify REPL output plainly." 458 (add-text-properties 459 start end 460 '(font-lock-fontified t 461 fontified t 462 font-lock-multiline t 463 font-lock-face geiser-font-lock-repl-output))) 464 465 (defun geiser-repl--narrow-to-prompt () 466 "Narrow to active prompt region and return t, otherwise returns nil." 467 (let* ((proc (get-buffer-process (current-buffer))) 468 (pmark (and proc (process-mark proc))) 469 (intxt (when (>= (point) (marker-position pmark)) 470 (save-excursion 471 (if comint-eol-on-send 472 (if comint-use-prompt-regexp 473 (end-of-line) 474 (goto-char (field-end)))) 475 (buffer-substring pmark (point))))) 476 (prompt-beg (marker-position pmark)) 477 (prompt-end (+ prompt-beg (length intxt)))) 478 (when (> (length intxt) 0) 479 (narrow-to-region prompt-beg prompt-end) 480 t))) 481 482 (defun geiser-repl--wrap-fontify-region-function (_beg _end &optional _loudly) 483 (save-restriction 484 (when (geiser-repl--narrow-to-prompt) 485 (let ((font-lock-dont-widen t)) 486 (font-lock-default-fontify-region (point-min) (point-max) nil))))) 487 488 (defun geiser-repl--wrap-unfontify-region-function (_beg _end &optional _loudly) 489 (save-restriction 490 (when (geiser-repl--narrow-to-prompt) 491 (let ((font-lock-dont-widen t)) 492 (font-lock-default-unfontify-region (point-min) (point-max)))))) 493 494 (defun geiser-repl--find-output-region () 495 (save-excursion 496 (goto-char (point-max)) 497 (re-search-backward comint-prompt-regexp) 498 (move-to-column 0) 499 (set-marker geiser-repl--last-output-end (point)) 500 (save-excursion 501 (when (re-search-backward comint-prompt-regexp nil t) 502 (forward-line) 503 (when (> (point) geiser-repl--last-output-start) 504 (set-marker geiser-repl--last-output-start (point))))) 505 (> (- geiser-repl--last-output-end geiser-repl--last-output-start) 2))) 506 507 (defun geiser-repl--treat-output-region () 508 (with-silent-modifications 509 (add-text-properties (max (point-min) (1- geiser-repl--last-output-start)) 510 (min geiser-repl--last-output-end (point-max)) 511 `(read-only ,geiser-repl-read-only-output-p)) 512 (geiser-repl--fontify-output-region geiser-repl--last-output-start 513 geiser-repl--last-output-end) 514 (geiser--font-lock-ensure geiser-repl--last-output-start 515 geiser-repl--last-output-end))) 516 517 (defun geiser-repl--output-filter (txt) 518 (when (geiser-repl--find-output-region) (geiser-repl--treat-output-region)) 519 (geiser-con--connection-update-debugging geiser-repl--connection txt) 520 (geiser-image--replace-images geiser-repl-inline-images-p 521 geiser-repl-auto-display-images-p) 522 (when (string-match-p (geiser-con--connection-prompt geiser-repl--connection) 523 txt) 524 (geiser-autodoc--disinhibit-autodoc))) 525 526 (defun geiser-repl--check-version (impl) 527 (when (not geiser-repl-skip-version-check-p) 528 (let ((v (geiser-repl--version impl (geiser-repl--binary impl))) 529 (r (geiser-repl--min-version impl))) 530 (when (and v r (geiser--version< v r)) 531 (error "Geiser requires %s version %s but detected %s" impl r v))))) 532 533 (defvar geiser-repl--last-scm-buffer) 534 535 (defun geiser-repl--set-default-directory () 536 (when-let (root (funcall geiser-repl-current-project-function)) 537 (setq-local default-directory root))) 538 539 (defun geiser-repl--set-up-load-path () 540 (when geiser-repl-add-project-paths 541 (when-let (root (funcall geiser-repl-current-project-function)) 542 (dolist (p (cond ((eq t geiser-repl-add-project-paths) '(".")) 543 ((listp geiser-repl-add-project-paths) 544 geiser-repl-add-project-paths))) 545 (geiser-add-to-load-path (expand-file-name p root)))))) 546 547 (defvar-local geiser-repl--repl-buffer nil) 548 549 (defvar-local geiser-repl--binary nil) 550 551 (defvar-local geiser-repl--arglist nil) 552 553 (defun geiser-repl--start-repl (impl address) 554 (message "Starting Geiser REPL ...") 555 (when (not address) (geiser-repl--check-version impl)) 556 (let ((buffer (current-buffer)) 557 (binary (geiser-repl--binary impl)) 558 (arglist (geiser-repl--arglist impl))) 559 (geiser-repl--to-repl-buffer impl) 560 (setq geiser-repl--last-scm-buffer buffer 561 geiser-repl--binary binary 562 geiser-repl--arglist arglist)) 563 (sit-for 0) 564 (goto-char (point-max)) 565 (geiser-repl--autodoc-mode -1) 566 (let* ((prompt-rx (geiser-repl--prompt-regexp impl)) 567 (deb-prompt-rx (geiser-repl--debugger-prompt-regexp impl)) 568 (prompt (geiser-con--combined-prompt prompt-rx deb-prompt-rx))) 569 (unless prompt-rx 570 (error "Sorry, I don't know how to start a REPL for %s" impl)) 571 (geiser-repl--set-default-directory) 572 (geiser-repl--save-remote-data address) 573 (geiser-repl--start-scheme impl address prompt) 574 (geiser-repl--quit-setup) 575 (geiser-repl--history-setup) 576 (add-to-list 'geiser-repl--repls (current-buffer)) 577 (geiser-repl--set-this-buffer-repl (current-buffer)) 578 (setq geiser-repl--connection 579 (geiser-repl--connection-setup impl address prompt-rx deb-prompt-rx)) 580 (geiser-repl--startup impl address) 581 (geiser-repl--autodoc-mode 1) 582 (geiser-repl--set-up-load-path) 583 (add-hook 'comint-output-filter-functions 584 'geiser-repl--output-filter 585 nil 586 t) 587 (set-process-query-on-exit-flag (get-buffer-process (current-buffer)) 588 geiser-repl-query-on-kill-p) 589 (dolist (f geiser-repl-startup-forms) 590 (geiser-log--info "Evaluating startup form %s..." f) 591 (geiser-eval--send/wait `(:eval (:scm ,f)))) 592 (run-hooks 'geiser-repl-startup-hook) 593 (message "%s up and running!" (geiser-repl--repl-name impl)))) 594 595 (defvar-local geiser-repl--connection-buffer nil) 596 597 (defun geiser-repl--connection-buffer (addr) 598 (when addr (get-buffer-create (format " %s <%s>" (buffer-name) addr)))) 599 600 (defun geiser-repl--connection-setup (impl address prompt deb-prompt) 601 (let* ((addr (unless address (geiser-repl--connection-address impl))) 602 (buff (or (geiser-repl--connection-buffer addr) (current-buffer)))) 603 (when addr 604 (setq geiser-repl--connection-buffer buff) 605 (geiser-repl--comint-local-connect buff addr)) 606 (geiser-con--make-connection (get-buffer-process buff) prompt deb-prompt))) 607 608 (defun geiser-repl--comint-local-connect (buff address) 609 "Connect over a Unix-domain socket." 610 (with-current-buffer buff 611 (let ((proc (make-network-process :name (buffer-name buff) 612 :buffer buff 613 :family 'local 614 :remote address))) 615 ;; brittleness warning: this is stuff 616 ;; make-comint-in-buffer sets up, via comint-exec, when 617 ;; it creates its own process, something we're doing 618 ;; here by ourselves. 619 (set-process-filter proc 'comint-output-filter) 620 (goto-char (point-max)) 621 (set-marker (process-mark proc) (point))))) 622 623 (defun geiser-repl--start-scheme (impl address prompt) 624 (setq comint-prompt-regexp prompt) 625 (let* ((name (geiser-repl--repl-name impl)) 626 (buff (current-buffer)) 627 (args (cond ((consp address) (list address)) 628 ((stringp address) '(())) 629 (t `(,(geiser-repl--get-binary impl) 630 nil 631 ,@(geiser-repl--get-arglist impl)))))) 632 (condition-case err 633 (if (and address (stringp address)) 634 (geiser-repl--comint-local-connect buff address) 635 (apply 'make-comint-in-buffer `(,name ,buff ,@args))) 636 (error (insert "Unable to start REPL:\n" (error-message-string err) "\n") 637 (error "Couldn't start Geiser: %s" err))) 638 (geiser-repl--wait-for-prompt geiser-repl-startup-time))) 639 640 (defun geiser-repl--wait-for-prompt (timeout) 641 (let ((p (point)) (seen) (buffer (current-buffer))) 642 (while (and (not seen) 643 (> timeout 0) 644 (get-buffer-process buffer)) 645 (sleep-for 0.1) 646 (setq timeout (- timeout 100)) 647 (goto-char p) 648 (setq seen (re-search-forward comint-prompt-regexp nil t))) 649 (goto-char (point-max)) 650 (unless seen (error "%s" "No prompt found!")))) 651 652 (defun geiser-repl--is-debugging () 653 (let ((dp (geiser-con--connection-debug-prompt geiser-repl--connection))) 654 (and dp 655 (save-excursion 656 (goto-char (geiser-repl--last-prompt-start)) 657 (re-search-forward dp (geiser-repl--last-prompt-end) t))))) 658 659 (defun geiser-repl--connection* () 660 (let ((buffer (geiser-repl--set-up-repl geiser-impl--implementation))) 661 (and (buffer-live-p buffer) 662 (get-buffer-process buffer) 663 (with-current-buffer buffer geiser-repl--connection)))) 664 665 (defun geiser-repl--connection () 666 (or (geiser-repl--connection*) 667 (error "No Geiser REPL for this buffer (try M-x geiser)"))) 668 669 (setq geiser-eval--default-connection-function 'geiser-repl--connection) 670 671 (defun geiser-repl--prepare-send () 672 (geiser-image--clean-cache) 673 (geiser-autodoc--inhibit-autodoc) 674 (geiser-con--connection-deactivate geiser-repl--connection)) 675 676 (defun geiser-repl--send (cmd &optional save-history) 677 "Send CMD input string to the current REPL buffer. 678 If SAVE-HISTORY is non-nil, save CMD in the REPL history." 679 (when (and cmd (eq major-mode 'geiser-repl-mode)) 680 (geiser-repl--prepare-send) 681 (goto-char (point-max)) 682 (comint-kill-input) 683 (insert cmd) 684 (let ((comint-input-filter (if save-history 685 comint-input-filter 686 'ignore))) 687 (comint-send-input nil t)))) 688 689 (defun geiser-repl-interrupt () 690 (interactive) 691 (when (get-buffer-process (current-buffer)) 692 (interrupt-process nil comint-ptyp))) 693 694 695 ;;; REPL history 696 697 (defconst geiser-repl--history-separator "\n}{\n") 698 699 (defsubst geiser-repl--history-file () 700 (format "%s.%s" geiser-repl-history-filename geiser-impl--implementation)) 701 702 (defun geiser-repl--read-input-ring () 703 (let ((comint-input-ring-file-name (geiser-repl--history-file)) 704 (comint-input-ring-separator geiser-repl--history-separator) 705 (buffer-file-coding-system 'utf-8)) 706 (comint-read-input-ring t))) 707 708 (defun geiser-repl--write-input-ring () 709 (let ((comint-input-ring-file-name (geiser-repl--history-file)) 710 (comint-input-ring-separator geiser-repl--history-separator) 711 (buffer-file-coding-system 'utf-8)) 712 (comint-write-input-ring))) 713 714 (defun geiser-repl--history-setup () 715 (set (make-local-variable 'comint-input-ring-size) geiser-repl-history-size) 716 (set (make-local-variable 'comint-input-filter) 'geiser-repl--input-filter) 717 (geiser-repl--read-input-ring)) 718 719 720 ;;; Cleaning up 721 722 (defun geiser-repl--on-quit () 723 (geiser-repl--write-input-ring) 724 (let ((cb (current-buffer)) 725 (impl geiser-impl--implementation) 726 (comint-prompt-read-only nil)) 727 (geiser-con--connection-deactivate geiser-repl--connection t) 728 (geiser-con--connection-close geiser-repl--connection) 729 (setq geiser-repl--repls (remove cb geiser-repl--repls)) 730 (unless (eq cb geiser-repl--connection-buffer) 731 (when (buffer-live-p geiser-repl--connection-buffer) 732 (kill-buffer geiser-repl--connection-buffer) 733 (setq geiser-repl--connection-buffer nil) 734 (when-let (a (geiser-repl--connection-address 735 geiser-impl--implementation)) 736 (delete-file a)))) 737 (dolist (buffer (buffer-list)) 738 (when (buffer-live-p buffer) 739 (with-current-buffer buffer 740 (when (and (eq geiser-impl--implementation impl) 741 (equal cb geiser-repl--repl)) 742 (geiser-repl--set-up-repl geiser-impl--implementation))))))) 743 744 (defun geiser-repl--sentinel (proc _event) 745 (let ((pb (process-buffer proc))) 746 (when (buffer-live-p pb) 747 (with-current-buffer pb 748 (let ((comint-prompt-read-only nil) 749 (comint-input-ring-file-name (geiser-repl--history-file)) 750 (comint-input-ring-separator geiser-repl--history-separator)) 751 (geiser-repl--on-quit) 752 (push pb geiser-repl--closed-repls) 753 (goto-char (point-max)) 754 (when geiser-repl-delete-last-output-on-exit-p 755 (comint-kill-region comint-last-input-start (point))) 756 (insert "\nIt's been nice interacting with you!\n") 757 (insert 758 (substitute-command-keys 759 "Press \\[geiser-repl-switch] to bring me back.\n"))))))) 760 761 (defun geiser-repl--on-kill () 762 (geiser-repl--on-quit) 763 (setq geiser-repl--closed-repls 764 (remove (current-buffer) geiser-repl--closed-repls))) 765 766 (defun geiser-repl--input-filter (str) 767 (not (or (and (not geiser-repl-save-debugging-history-p) 768 (geiser-repl--is-debugging)) 769 (string-match "^\\s *$" str) 770 (string-match "^,quit *$" str)))) 771 772 (defun geiser-repl--old-input () 773 (save-excursion 774 (let ((end (point))) 775 (backward-sexp) 776 (buffer-substring (point) end)))) 777 778 (defun geiser-repl--quit-setup () 779 (add-hook 'kill-buffer-hook 'geiser-repl--on-kill nil t) 780 (set-process-sentinel (get-buffer-process (current-buffer)) 781 'geiser-repl--sentinel)) 782 783 784 ;;; geiser-repl mode: 785 786 (defun geiser-repl--bol () 787 (interactive) 788 (when (= (point) (comint-bol)) (beginning-of-line))) 789 790 (defun geiser-repl--beginning-of-defun () 791 (save-restriction 792 (narrow-to-region (geiser-repl--last-prompt-end) (point)) 793 (let ((beginning-of-defun-function nil)) 794 (beginning-of-defun)))) 795 796 (defun geiser-repl--module-function (&optional module) 797 (if (and module geiser-eval--get-impl-module) 798 (funcall geiser-eval--get-impl-module module) 799 :f)) 800 801 (defun geiser-repl--doc-module () 802 (interactive) 803 (let ((geiser-eval--get-module-function 804 (geiser-impl--method 'find-module geiser-impl--implementation))) 805 (geiser-doc-module))) 806 807 (defun geiser-repl--newline-and-indent () 808 (interactive) 809 (save-restriction 810 (narrow-to-region comint-last-input-start (point-max)) 811 (insert "\n") 812 (lisp-indent-line))) 813 814 (defun geiser-repl--nesting-level () 815 (save-restriction 816 (narrow-to-region (geiser-repl--last-prompt-end) (point-max)) 817 (geiser-syntax--nesting-level))) 818 819 (defun geiser-repl--is-input () 820 (not (eq (field-at-pos (point)) 'output))) 821 822 (defun geiser-repl--grab-input () 823 (let ((pos (comint-bol))) 824 (goto-char (point-max)) 825 (insert (field-string-no-properties pos)))) 826 827 (defun geiser-repl--send-input () 828 (set-marker geiser-repl--last-output-start (point-max)) 829 830 (let* ((proc (get-buffer-process (current-buffer))) 831 (pmark (and proc (process-mark proc))) 832 (intxt (and pmark (buffer-substring pmark (point))))) 833 (when intxt 834 (when geiser-repl-forget-old-errors-p 835 (compilation-forget-errors)) 836 (geiser-repl--prepare-send) 837 (comint-send-input) 838 (when (string-match "^\\s-*$" intxt) 839 (comint-send-string proc (geiser-eval--scheme-str '(:ge no-values))) 840 (comint-send-string proc "\n"))))) 841 842 (define-obsolete-function-alias 'geiser-repl--maybe-send 843 #'geiser-repl-maybe-send "0.26") 844 845 (defun geiser-repl-maybe-send () 846 "Handle the current input at the REPL's prompt. 847 848 If `geiser-repl-send-on-return-p' is t and the input is a 849 complete sexp, send the input to the REPL process; otherwise, 850 insert a new line and, if `geiser-repl-auto-indent-p' is t, 851 indentation." 852 (interactive) 853 (let ((p (point))) 854 (cond ((< p (geiser-repl--last-prompt-start)) 855 (if (geiser-repl--is-input) 856 (geiser-repl--grab-input) 857 (ignore-errors (compile-goto-error)))) 858 ((let ((inhibit-field-text-motion t)) 859 (when geiser-repl-send-on-return-p 860 (end-of-line)) 861 (<= (geiser-repl--nesting-level) 0)) 862 (geiser-repl--send-input)) 863 (t (goto-char p) 864 (if geiser-repl-auto-indent-p 865 (geiser-repl--newline-and-indent) 866 (insert "\n")))))) 867 868 (defun geiser-repl-tab-dwim (n) 869 "If we're after the last prompt, complete symbol or indent (if 870 there's no symbol at point). Otherwise, go to next error in the REPL 871 buffer." 872 (interactive "p") 873 (if (>= (point) (geiser-repl--last-prompt-end)) 874 (or (completion-at-point) 875 (lisp-indent-line)) 876 (compilation-next-error n))) 877 878 (defun geiser-repl--previous-error (n) 879 "Go to previous error in the REPL buffer." 880 (interactive "p") 881 (compilation-next-error (- n))) 882 883 (defun geiser-repl-clear-buffer () 884 "Delete the output generated by the scheme process." 885 (interactive) 886 (let ((inhibit-read-only t)) 887 (delete-region (point-min) (geiser-repl--last-prompt-start)) 888 (when (< (point) (geiser-repl--last-prompt-end)) 889 (goto-char (geiser-repl--last-prompt-end))) 890 (recenter t))) 891 892 (defvar geiser-repl-mode-map 893 (let ((map (make-sparse-keymap))) 894 (set-keymap-parent map comint-mode-map) 895 896 (define-key map "\C-d" 'delete-char) 897 (define-key map "\C-m" 'geiser-repl-maybe-send) 898 (define-key map "\r" 'geiser-repl-maybe-send) 899 (define-key map "\C-j" 'geiser-repl--newline-and-indent) 900 (define-key map (kbd "TAB") 'geiser-repl-tab-dwim) 901 (define-key map [backtab] 'geiser-repl--previous-error) 902 903 (define-key map "\C-a" 'geiser-repl--bol) 904 (define-key map (kbd "<home>") 'geiser-repl--bol) 905 906 (geiser-menu--defmenu repl map 907 ("Complete symbol" ((kbd "M-TAB")) 908 completion-at-point :enable (geiser--symbol-at-point)) 909 ("Complete module name" ((kbd "C-.") (kbd "M-`")) 910 geiser-capf-complete-module :enable (geiser--symbol-at-point)) 911 ("Edit symbol" "\M-." geiser-edit-symbol-at-point 912 :enable (geiser--symbol-at-point)) 913 -- 914 ("Load scheme file..." "\C-c\C-l" geiser-load-file) 915 ("Switch to module..." "\C-c\C-m" geiser-repl-switch-to-module) 916 ("Import module..." "\C-c\C-i" geiser-repl-import-module) 917 ("Add to load path..." "\C-c\C-r" geiser-add-to-load-path) 918 -- 919 ("Previous matching input" "\M-p" comint-previous-matching-input-from-input 920 "Previous input matching current") 921 ("Next matching input" "\M-n" comint-next-matching-input-from-input 922 "Next input matching current") 923 ("Previous prompt" "\C-c\C-p" geiser-repl-previous-prompt) 924 ("Next prompt" "\C-c\C-n" geiser-repl-next-prompt) 925 ("Previous input" "\C-c\M-p" comint-previous-input) 926 ("Next input" "\C-c\M-n" comint-next-input) 927 -- 928 ("Interrupt evaluation" ("\C-c\C-k" "\C-c\C-c") 929 geiser-repl-interrupt) 930 -- 931 (mode "Autodoc mode" ("\C-c\C-da" "\C-c\C-d\C-a") geiser-autodoc-mode) 932 ("Symbol documentation" ("\C-c\C-dd" "\C-c\C-d\C-d") 933 geiser-doc-symbol-at-point 934 "Documentation for symbol at point" :enable (geiser--symbol-at-point)) 935 ("Lookup symbol in manual" ("\C-c\C-di" "\C-c\C-d\C-i") 936 geiser-doc-look-up-manual 937 "Documentation for symbol at point" :enable (geiser--symbol-at-point)) 938 ("Module documentation" ("\C-c\C-dm" "\C-c\C-d\C-m") geiser-repl--doc-module 939 "Documentation for module at point" :enable (geiser--symbol-at-point)) 940 -- 941 ("Clear buffer" "\C-c\M-o" geiser-repl-clear-buffer 942 "Clean up REPL buffer, leaving just a lonely prompt") 943 ("Toggle ()/[]" ("\C-c\C-e\C-[" "\C-c\C-e[") geiser-squarify) 944 ("Insert λ" ("\C-c\\" "\C-c\C-\\") geiser-insert-lambda) 945 -- 946 ("Kill Scheme interpreter" "\C-c\C-q" geiser-repl-exit 947 :enable (geiser-repl--live-p)) 948 ("Restart" "\C-c\C-z" geiser-repl-switch 949 :enable (not (geiser-repl--live-p))) 950 951 -- 952 (custom "REPL options" geiser-repl)) 953 954 (define-key map [menu-bar completion] 'undefined) 955 map)) 956 957 (define-derived-mode geiser-repl-mode comint-mode "REPL" 958 "Major mode for interacting with an inferior scheme repl process. 959 \\{geiser-repl-mode-map}" 960 (scheme-mode-variables) 961 (hack-dir-local-variables-non-file-buffer) 962 (set (make-local-variable 'geiser-repl--last-output-start) (point-marker)) 963 (set (make-local-variable 'geiser-repl--last-output-end) (point-marker)) 964 (set (make-local-variable 'face-remapping-alist) 965 '((comint-highlight-prompt geiser-font-lock-repl-prompt) 966 (comint-highlight-input geiser-font-lock-repl-input))) 967 (set (make-local-variable 'mode-line-process) nil) 968 (set (make-local-variable 'comint-use-prompt-regexp) nil) 969 (set (make-local-variable 'comint-prompt-read-only) 970 geiser-repl-read-only-prompt-p) 971 (setq comint-process-echoes nil) 972 (set (make-local-variable 'beginning-of-defun-function) 973 'geiser-repl--beginning-of-defun) 974 (set (make-local-variable 'comint-input-ignoredups) 975 geiser-repl-history-no-dups-p) 976 (setq geiser-eval--get-module-function 'geiser-repl--module-function) 977 (geiser-capf-setup t) 978 (setq geiser-smart-tab-mode-string "") 979 (geiser-smart-tab-mode t) 980 981 (setq-local font-lock-fontify-region-function 982 #'geiser-repl--wrap-fontify-region-function) 983 (setq-local font-lock-unfontify-region-function 984 #'geiser-repl--wrap-unfontify-region-function) 985 986 ;; enabling compilation-shell-minor-mode without the annoying highlighter 987 (compilation-setup t)) 988 989 990 ;;; User commands 991 992 (define-obsolete-function-alias 'run-geiser 'geiser "Geiser 0.26") 993 994 (defun geiser (impl) 995 "Start a new Geiser REPL." 996 (interactive 997 (list (geiser-repl--get-impl "Start Geiser for scheme implementation: "))) 998 (geiser-repl--start-repl impl nil)) 999 1000 (defun geiser-connect (impl &optional host port) 1001 "Start a new Geiser REPL connected to a remote Scheme process." 1002 (interactive 1003 (list (geiser-repl--get-impl "Connect to Scheme implementation: "))) 1004 (geiser-repl--start-repl impl (geiser-repl--read-address host port))) 1005 1006 (defun geiser-connect-local (impl socket) 1007 "Start a new Geiser REPL connected to a remote Scheme process 1008 over a Unix-domain socket." 1009 (interactive 1010 (list (geiser-repl--get-impl "Connect to Scheme implementation: ") 1011 (expand-file-name (read-file-name "Socket file name: ")))) 1012 (geiser-repl--start-repl impl socket)) 1013 1014 (defvar-local geiser-repl--last-scm-buffer nil) 1015 1016 (defun geiser-repl--maybe-remember-scm-buffer (buffer) 1017 (when (and buffer 1018 (eq 'scheme-mode (with-current-buffer buffer major-mode)) 1019 (eq major-mode 'geiser-repl-mode)) 1020 (setq geiser-repl--last-scm-buffer buffer))) 1021 1022 (defun geiser-repl--get-binary (impl) 1023 (or geiser-repl--binary (geiser-repl--binary impl))) 1024 1025 (defun geiser-repl--get-arglist (impl) 1026 (or geiser-repl--arglist (geiser-repl--arglist impl))) 1027 1028 (defun geiser-repl--call-in-repl (cmd) 1029 (when-let (b (geiser-repl--repl/impl geiser-impl--implementation)) 1030 (save-window-excursion 1031 (with-current-buffer b (funcall cmd))))) 1032 1033 (define-obsolete-function-alias 'switch-to-geiser 'geiser-repl-switch "0.26") 1034 1035 (defun geiser-repl-switch (&optional ask impl buffer) 1036 "Switch to running Geiser REPL. 1037 1038 If REPL is the current buffer, switch to the previously used 1039 scheme buffer. 1040 1041 With prefix argument, ask for which one if more than one is running. 1042 If no REPL is running, execute `geiser' to start a fresh one." 1043 (interactive "P") 1044 (let* ((impl (or impl geiser-impl--implementation)) 1045 (in-repl (eq major-mode 'geiser-repl-mode)) 1046 (in-live-repl (and in-repl (get-buffer-process (current-buffer)))) 1047 (repl (unless ask 1048 (if impl 1049 (geiser-repl--repl/impl impl) 1050 (or geiser-repl--repl (car geiser-repl--repls)))))) 1051 (cond (in-live-repl 1052 (when (and (not (eq repl buffer)) 1053 (buffer-live-p geiser-repl--last-scm-buffer)) 1054 (geiser-repl--switch-to-buffer geiser-repl--last-scm-buffer))) 1055 (repl (geiser-repl--switch-to-buffer repl)) 1056 ((geiser-repl--remote-p) 1057 (geiser-connect impl (geiser-repl--host) (geiser-repl--port))) 1058 ((geiser-repl--local-p) 1059 (geiser-connect-local impl geiser-repl--address)) 1060 (impl (geiser impl)) 1061 (t (call-interactively 'geiser))) 1062 (geiser-repl--maybe-remember-scm-buffer buffer))) 1063 1064 (define-obsolete-function-alias 'switch-to-geiser-module 1065 'geiser-repl-switch-to-module "0.26") 1066 1067 (defun geiser-repl-switch-to-module (&optional module buffer) 1068 "Switch to running Geiser REPL and try to enter a given module." 1069 (interactive) 1070 (let* ((module (or module 1071 (geiser-completion--read-module 1072 "Switch to module (default top-level): "))) 1073 (cmd (and module 1074 (geiser-repl--enter-cmd geiser-impl--implementation 1075 module)))) 1076 (unless (eq major-mode 'geiser-repl-mode) 1077 (geiser-repl-switch nil nil (or buffer (current-buffer)))) 1078 (geiser-repl--send cmd))) 1079 1080 (defun geiser-repl--switch-to-repl (&optional and-module) 1081 (if and-module 1082 (geiser-repl-switch-to-module (geiser-eval--get-module) (current-buffer)) 1083 (geiser-repl-switch nil nil (current-buffer)))) 1084 1085 (defun geiser-repl--repl-buffer-p () 1086 (and (buffer-live-p geiser-repl--repl) geiser-repl--repl)) 1087 1088 (defun geiser-repl-restart-repl () 1089 "Restarts the REPL associated with the current buffer." 1090 (interactive) 1091 (let ((b (current-buffer)) 1092 (impl geiser-impl--implementation)) 1093 (when (geiser-repl--repl-buffer-p) 1094 (geiser-repl--switch-to-repl nil) 1095 (comint-kill-subjob) 1096 (sit-for 0.1)) ;; ugly hack; but i don't care enough to fix it 1097 (geiser impl) 1098 (sit-for 0.2) 1099 (goto-char (point-max)) 1100 (pop-to-buffer b))) 1101 1102 (defun geiser-repl-import-module (&optional module) 1103 "Import a given module in the current namespace of the REPL." 1104 (interactive) 1105 (let* ((module (or module 1106 (geiser-completion--read-module "Import module: "))) 1107 (cmd (and module 1108 (geiser-repl--import-cmd geiser-impl--implementation 1109 module)))) 1110 (geiser-repl--switch-to-repl) 1111 (geiser-repl--send cmd))) 1112 1113 (defun geiser-repl-exit (&optional arg) 1114 "Exit the current REPL. 1115 With a prefix argument, force exit by killing the scheme process." 1116 (interactive "P") 1117 (when (or (not geiser-repl-query-on-exit-p) 1118 (y-or-n-p "Really quit this REPL? ")) 1119 (geiser-con--connection-deactivate geiser-repl--connection t) 1120 (let ((cmd (and (not arg) 1121 (geiser-repl--exit-cmd geiser-impl--implementation)))) 1122 (if cmd 1123 (when (stringp cmd) (geiser-repl--send cmd)) 1124 (comint-kill-subjob))))) 1125 1126 (defun geiser-repl-next-prompt (n) 1127 (interactive "p") 1128 (when (> n 0) 1129 (end-of-line) 1130 (re-search-forward comint-prompt-regexp nil 'go n))) 1131 1132 (defun geiser-repl-previous-prompt (n) 1133 (interactive "p") 1134 (when (> n 0) 1135 (end-of-line 0) 1136 (when (re-search-backward comint-prompt-regexp nil 'go n) 1137 (goto-char (match-end 0))))) 1138 1139 (defun geiser-add-to-load-path (path) 1140 "Add a new directory to running Scheme's load path. 1141 When called interactively, this function will ask for the path to 1142 add, defaulting to the current buffer's directory." 1143 (interactive "DDirectory to add: ") 1144 (let* ((c `(:eval (:ge add-to-load-path ,(expand-file-name path)))) 1145 (r (geiser-eval--send/result c))) 1146 (message "%s%s added to load path" path (if r "" " couldn't be")))) 1147 1148 1149 ;;; Unload: 1150 1151 (defun geiser-repl--repl-list () 1152 (let (lst) 1153 (dolist (repl geiser-repl--repls lst) 1154 (when (buffer-live-p repl) 1155 (with-current-buffer repl 1156 (push (cons geiser-impl--implementation 1157 geiser-repl--address) 1158 lst)))))) 1159 1160 (defun geiser-repl--restore (impls) 1161 (dolist (impl impls) 1162 (when impl 1163 (condition-case err 1164 (geiser-repl--start-repl (car impl) (cdr impl)) 1165 (error (message (error-message-string err))))))) 1166 1167 (defun geiser-repl-unload-function () 1168 (dolist (repl geiser-repl--repls) 1169 (when (buffer-live-p repl) 1170 (with-current-buffer repl 1171 (let ((geiser-repl-query-on-exit-p nil)) (geiser-repl-exit)) 1172 (sit-for 0.05) 1173 (kill-buffer))))) 1174 1175 1176 (provide 'geiser-repl) 1177 1178 1179 ;;; Initialization: 1180 ;; After providing 'geiser-repl, so that impls can use us. 1181 (mapc 'geiser-impl--load-impl geiser-active-implementations)