dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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)