anchor.diff:        (if-process-then-terminate mode)))))
   
   (defmethod process-document ((mode tts-mode))
  -  "Fetch the text in buffer that matches `selector` and send it off
  -to get *spoken*."
  +  "Fetch the text in buffer that matches `selector` and send it off to the TTS."
     (if (executable mode)
         (let* ((tags
  -              (handler-case
  -                  (coerce 
  -                   (clss:select (selector mode) (document-model (buffer mode)))
  -                   'list)
  -                (error ()
  -                       (log:warn "tts-mode: no document-model available.")
  -                       nil)))
  +               (handler-case
  +                   (coerce 
  +                    (clss:select (selector mode) (document-model (buffer mode)))
  +                    'list)
  +                 (error ()
  +                   (log:warn "tts-mode: no document-model available.")
  +                   nil)))
  +             ;; TODO properly handle punctuation like Emacspeak does
                (text (str:remove-punctuation
  -                    (with-output-to-string
  -                      (s)
  +                    (with-output-to-string (s)
                         (dolist (tag tags)
                           (format s "~a" (plump:text tag)))))))
           (when tags
             (speak mode text)))
  -    (echo-warning "tts-mode: no executable configured.")))
  +      (echo-warning "tts-mode: no executable configured.")))
   
   (defmethod speak ((mode tts-mode) text)
  -  "Start an asynchronous process of the `executable` with `text`
  -passed as the argument."
  +  "Start an asynchronous process of the `executable` with TEXT passed as the
  +argument."
     (let ((program-string
  -         (format nil "~s ~s" (executable mode) text)))
  +          (format nil "~s ~s" (executable mode) text)))
       (progn
  -      (log:info "tts-mode: starting speak.")
  -      ;; make sure that a running process is stopped before starting a new
  +      (log:info "tts-mode: starting TTS.")
  +      ;; make sure that a running process is stopped before starting a new one
         (if-process-then-terminate mode)
         (setf (executable-process-info mode)
               (uiop:launch-program program-string
                                    :output *standard-output*
                                    :error-output *standard-output*))
         (if (not (zerop (uiop:wait-process (executable-process-info mode))))
  -          (log:warn "tts-mode executable terminated.")
  -        (log:info "tts-mode: speak done."))
  +          (log:info "tts-mode: TTS done."))
         (if-process-then-terminate mode))))
   
   (defmethod if-process-then-terminate ((mode tts-mode))
     "If there is a running process, terminate it."
     (when (and (executable-process-info mode)
                (uiop:process-alive-p (executable-process-info mode)))
  -    (log:info "tts-mode: stopping speak.")
  +    (log:info "tts-mode: terminating TTS.")
       (uiop:terminate-process (executable-process-info mode) :urgent t)
       (setf (executable-process-info mode) nil)))
   
  -(define-command start-speak ()
  -  "Start text-to-speak the content of the current buffer
  -matching the selector."
  +(define-command start-tts ()
  +  "Start TTS on the content of the current buffer matching the selector."
     (process-document (current-mode 'tts-mode)))
   
  -(define-command stop-speak ()
  -  "Stop running text-to-speak process if there is one."
  -    (if-process-then-terminate (current-mode 'tts-mode)))
  +(define-command stop-tts ()
  +  "Stop running TTS process if there is one."
  +  (if-process-then-terminate (current-mode 'tts-mode)))
  
positive.code:   ((executable nil
                 :type (or string null)
                 :documentation "The executable command to run.")
     ;; TODO: If you specify multiple tags, like h1, h2, h3, p, they are selected in that
     ;; order, not in the order they appear on the page. This is different than how it's
     ;; done with e.g. JS document.querySelectorAll which returns them in the order they
     ;; appear, which is IMO the correct way ... can you configure clss to do this?
     (selector "p"
               :type string
               :documentation "css selector that describes what elements text to speak.")
     (executable-process-info nil
                              :type (or uiop/launch-program::process-info null)
                              :documentation "Holds the process-info object of the running process")
  
negative.code: ;;;; SPDX-License-Identifier: BSD-3-Clause
  
  (uiop:define-package :nyxt/tts-mode
    (:use :common-lisp :nyxt)
    (:documentation "Mode for interacting with Text-to-Speech (TTS) software."))
  
  (in-package :nyxt/tts-mode)
  
  (define-mode tts-mode ()
    "A mode for interacting with Text-to-Speech (TTS) software.
  
  By default, no executable is configured, so for the mode to work, you need to
  configure an executable that can take a string of text. Something like `espeak`
  or `espeak-ng` should work out of the box. The content that will be sent to the
  executable is the text content of paragraph tags on the page. This can be
  configured by changing the `selector` slot.
  
  Example:
  
  