Beautiful Code [338]
To enable fast access to such services, I added an emacspeak-url-template module in late 2000. This module has become a powerful companion to the emacspeak-websearch module described in the previous section. Together, these modules turn the Emacs minibuffer into a powerful web command line that provides rapid access to web content.
Many web services require the user to specify a date. One can usefully default the date by using the user's calendar to provide the context. Thus, Emacspeak tools for playing an NPR program or retrieving MLB scores default to using the date under the cursor when invoked from within the Emacs calendar buffer.
URL templates in Emacspeak are implemented using the following data structure:
Code View: Scroll / Show All
(defstruct (emacspeak-url-template (:constructor emacspeak-ut-constructor))
name ;; Human-readable name
template ;; template URL string
generators;; list of param generator
post-action ;; action to perform after opening
documentation ;; resource documentation
fetcher)
Users invoke URL templates via the Emacspeak command emacspeak-url-template-fetch command, which prompts for a URL template and:
Looks up the named template.
Prompts the user by calling the specified generator.
Applies the Lisp function format to the template string and the collected arguments to create the final URI.
Sets up any post actions performed after the content has been rendered.
Applies the specified fetcher to render the content.
The use of this structure is best explained with an example. The following is the URL template for playing NPR programs:
Code View: Scroll / Show All
(emacspeak-url-template-define
"NPR On Demand"
"http://www.npr.org/dmg/dmg.php?prgCode=%s&showDate=%s&segNum=%s&mediaPref=RM"
(list
#'(lambda ( ) (upcase (read-from-minibuffer "Program code:")))
#'(lambda ( )
(emacspeak-url-template-collect-date "Date:" "%d-%b-%Y"))
"Segment:")
nil; no post actions
"Play NPR shows on demand.
Program is specified as a program code:
ME Morning Edition
ATC All Things Considered
day Day To Day
newsnotes News And Notes
totn Talk Of The Nation
fa Fresh Air
wesat Weekend Edition Saturday
wesun Weekend Edition Sunday
fool The Motley Fool
Segment is specified as a two digit number --specifying a blank value
plays entire program."
#'(lambda (url)
(funcall emacspeak-media-player url 'play-list)
(emacspeak-w3-browse-xml-url-with-style
(expand-file-name "smil-anchors.xsl" emacspeak-xslt-directory)
url)))
In this example, the custom fetcher performs two actions:
Launches a media player to start playing the audio stream.
Filters the associated SMIL document via the XSLT file smil-anchors.xsl.
31.3.4. The Advent of Feed Readers
When I implemented the emacspeak-websearch and emacspeak-url-template modules, Emacspeak needed to screen-scrape HTML pages to speak the relevant information. But as the Web grew in complexity, the need to readily get beyond the superficial presentation of pages to the real content took on a wider value than eyes-free access. Even users capable of working with complex visual interfaces found themselves under a serious information overload. This led to the advent of RSS and Atom feeds, and the concomitant arrival of feed reading software.
These developments have had a very positive effect on the Emacspeak code base. During the past few years, the code has become more beautiful as I have progressively deleted screen-scraping logic and replaced it with direct content access. As an example, here is the Emacspeak URL template for retrieving the weather for a given city/state:
(emacspeak-url-template-define
"rss weather from wunderground"
"http://www.wunderground.com/auto/rss_full/%s.xml?units=both"