Beautiful Code [333]
Auditory icons are produced by the following user interactions:
To cue explicit user actions
To add additional cues to spoken output
Auditory icons that confirm user actions—e.g., a file being saved successfully—are produced by adding an after advice to the various Emacs built-ins. To provide a consistent sound and feel across the Emacspeak desktop, such extensions are attached to code that is called from many places in Emacs.
Here is an example of such an extension, implemented via an advice fragment:
(defadvice save-buffer (after emacspeak pre act)
"Produce an auditory icon if possible."
(when (interactive-p) (emacspeak-auditory-icon 'save-object)
(or emacspeak-last-message (message "Wrote %s" (buffer-file-name)))))
Extensions can also be implemented via an Emacs-provided hook. As explained in the brief advice tutorial given earlier, advice allows the behavior of existing software to be extended or modified without having to modify the underlying source code. Emacs is itself an extensible system, and well-written Lisp code has a tradition of providing appropriate extension hooks for common use cases. As an example, Emacspeak attaches auditory feedback to Emacs' default prompting mechanism (the Emacs minibuffer) by adding the function emacspeak-minibuffer-setup-hook to Emacs' minibuffer-setup-hook:
(defun emacspeak-minibuffer-setup-hook ()
"Actions to take when entering the minibuffer."
(let ((inhibit-field-text-motion t))
(when emacspeak-minibuffer-enter-auditory-icon
(emacspeak-auditory-icon 'open-object))
(tts-with-punctuations 'all (emacspeak-speak-buffer))))
(add-hook 'minibuffer-setup-hook 'emacspeak-minibuffer-setup-hook)
This is a good example of using built-in extensibility where available. However, Emac-speak uses advice in a lot of cases because the Emacspeak requirement of adding auditory feedback to all of Emacs was not originally envisioned when Emacs was implemented. Thus, the Emacspeak implementation demonstrates a powerful technique for discovering extension points.
Lack of an advice-like feature in a programming language often makes experimentation difficult, especially when it comes to discovering useful extension points. This is because software engineers are faced with the following trade-off:
Make the system arbitrarily extensible (and arbitrarily complex)
Guess at some reasonable extension points and hardcode these
Once extension points are implemented, experimenting with new ones requires rewriting existing code, and the resulting inertia often means that over time, such extension points remain mostly undiscovered. Lisp advice, and its Java counterpart Aspects, offer software engineers the opportunity to experiment without worrying about adversely affecting an existing body of source code.
31.2.7. Producing Auditory Icons While Speaking Content
In addition to using auditory icons to cue the results of user interaction, Emacspeak uses auditory icons to augment what is being spoken. Examples of such auditory icons include:
A short icon at the beginning of paragraphs
The auditory icon mark-object when moving across source lines that have a breakpoint set on them
Auditory icons are implemented by attaching the text property emacspeak-auditory-icon with a value equal to the name of the auditory icon to be played on the relevant text.
As an example, commands to set breakpoints in the Grand Unified Debugger Emacs package (GUD) are adviced to add the property emacspeak-auditory-icon to the line containing the breakpoint. When the user moves across such a line, the function tts-format-text-and-speak