Saturday, November 21, 2020

Emacspeak 53.0 EfficientDog Unleashed!

Announcing Emacspeak 52.0—WorkAtHomeDog!

The enjoyment of one's tools is an essential ingredient of successful work. – Donald E. Knuth

1 For Immediate Release:

San Jose, CA, (Nov 22, 2020)

1.1 Emacspeak 53.0 (EfficientDog) 🦮 Unleashed!

— Making Telecommuting Fun Again!

Advancing Accessibility In The Age Of User-Aware Interfaces — Zero cost of Ownership makes priceless software Universally affordable!

Emacspeak Inc (NASDOG: ESPK) — http://github.com/tvraman/emacspeak — announces the immediate world-wide availability of Emacspeak 53.0 (EfficientDog) 🦮 — a powerful audio desktop that leverages today's evolving Data, Social and Assistant-Oriented Internet cloud to enable working efficiently and effectively from anywhere!

2 Investors Note:

With several prominent tweeters expanding coverage of #emacspeak, NASDOG: ESPK has now been consistently trading over the social net at levels close to that once attained by DogCom high-fliers—and as of Nov 2020 is trading at levels close to that achieved by once better known stocks in the tech sector.

3 What Is It?

Emacspeak is a fully functional audio desktop that provides complete eyes-free access to all major 32 and 64 bit operating environments. By seamlessly blending live access to all aspects of the Internet such as ubiquitous assistance, Web-surfing, blogging, remote software development, social computing and electronic messaging into the audio desktop, Emacspeak enables speech access to local and remote information with a consistent and well-integrated user interface. A rich suite of task-oriented tools provides efficient speech-enabled access to the evolving assistant-oriented social Internet cloud.

4 Major Enhancements:

This version requires emacs-26.1 or later.

  1. Speech-Enabled Haskell Mode ⁡
  2. Speech-Enable VTerm 🖳
  3. Speech-Enable Package Syslog 
  4. Speech-enable Package hide-lines 𐇪
  5. Speech-Enable Racer 🖹
  6. Speech-Enable Eglot 󠀁
  7. speech-Enable project.el 📽
  8. Speech-Enable rust-mode 🦊
  9. Emacspeak-sdcv — speech-Enable Stardict Interaction 🤩
  10. Add CTL-Z As A New Prefix Keymap ⌨

— And a lot more than will fit this margin. … 🗞

5 Establishing Liberty, Equality And Freedom:

Never a toy system, Emacspeak is voluntarily bundled with all major Linux distributions. Though designed to be modular, distributors have freely chosen to bundle the fully integrated system without any undue pressure—a documented success for the integrated innovation embodied by Emacspeak. As the system evolves, both upgrades and downgrades continue to be available at the same zero-cost to all users. The integrity of the Emacspeak codebase is ensured by the reliable and secure Linux platform and the underlying GIT versioning software used to develop and distribute the system.

Extensive studies have shown that thanks to these features, users consider Emacspeak to be absolutely priceless. Thanks to this wide-spread user demand, the present version remains priceless as ever—it is being made available at the same zero-cost as previous releases.

At the same time, Emacspeak continues to innovate in the area of eyes-free Assistance and social interaction and carries forward the well-established Open Source tradition of introducing user interface features that eventually show up in luser environments.

On this theme, when once challenged by a proponent of a crash-prone but well-marketed mousetrap with the assertion "Emacs is a system from the 70's", the creator of Emacspeak evinced surprise at the unusual candor manifest in the assertion that it would take popular idiot-proven interfaces until the year 2070 to catch up to where the Emacspeak audio desktop is today. Industry experts welcomed this refreshing breath of Courage Certainty and Clarity (CCC) at a time when users are reeling from the Fear Uncertainty and Doubt (FUD) unleashed by complex software systems backed by even more convoluted press releases.

6 Independent Test Results:

Independent test results have proven that unlike some modern (and not so modern) software, Emacspeak can be safely uninstalled without adversely affecting the continued performance of the computer. These same tests also revealed that once uninstalled, the user stopped functioning altogether. Speaking with Aster Labrador, the creator of Emacspeak once pointed out that these results re-emphasize the user-centric design of Emacspeak; “It is the user — and not the computer– that stops functioning when Emacspeak is uninstalled!”.

6.1 Note from Aster,Bubbles and Tilden:

UnDoctored Videos Inc. is looking for volunteers to star in a video demonstrating such complete user failure.

7 Obtaining Emacspeak:

Emacspeak can be downloaded from GitHub — see https://github.com/tvraman/emacspeak you can visit Emacspeak on the WWW at http://emacspeak.sf.net. You can subscribe to the emacspeak mailing list — emacspeak@cs.vassar.edu — by sending mail to the list request address emacspeak-request@cs.vassar.edu. The Emacspeak Blog is a good source for news about recent enhancements and how to use them.

The latest development snapshot of Emacspeak is always available at GitHub.

8 History:

  • Emacspeak 53.0 (EfficientDog) focuses on efficiency.
  • Emacspeak 52.0 (WorkAtHomeDog) makes working remotely a pleasurable experience.
  • Bigger and more powerful than any smart assistAnt, AssistDog provides

instant access to the most relevant information at all times.

  • Emacspeak 50.0 (SageDog) embraces the wisdom of stability as opposed to rapid change and the concomitant creation of bugs.🚭: Naturally Intelligent (NI)™ at how information is spoken, Emacspeak

is entirely free of Artificial Ingredients (AI)™.

  • Emacspeak 49.0 (WiseDog) leverages the wisdom gleaned from earlier releases to provide an enhanced auditory experience.
  • Emacspeak 48.0 (ServiceDog) builds on earlier releases to provide continued end-user value.
  • Emacspeak 47.0 (GentleDog) goes the next step in being helpful while letting users learn and grow.
  • Emacspeak 46.0 (HelpfulDog) heralds the coming of Smart Assistants.
  • Emacspeak 45.0 (IdealDog) is named in recognition of Emacs' excellent integration with various programming language environments — thanks to this, Emacspeak is the IDE of choice for eyes-free software engineering.
  • Emacspeak 44.0 continues the steady pace of innovation on the audio desktop.
  • Emacspeak 43.0 brings even more end-user efficiency by leveraging the ability to spatially place multiple audio streams to provide timely auditory feedback.
  • Emacspeak 42.0 while moving to GitHub from Google Code continues to innovate in the areas of auditory user interfaces and efficient, light-weight Internet access.
  • Emacspeak 41.0 continues to improve on the desire to provide not just equal, but superior access — technology when correctly implemented can significantly enhance the human ability.
  • Emacspeak 40.0 goes back to Web basics by enabling efficient access to large amounts of readable Web content.
  • Emacspeak 39.0 continues the Emacspeak tradition of increasing the breadth of user tasks that are covered without introducing unnecessary bloatware.
  • Emacspeak 38.0 is the latest in a series of award-winning releases from Emacspeak Inc.
  • Emacspeak 37.0 continues the tradition of delivering robust software as reflected by its code-name.
  • Emacspeak 36.0 enhances the audio desktop with many new tools including full EPub support — hence the name EPubDog.
  • Emacspeak 35.0 is all about teaching a new dog old tricks — and is aptly code-named HeadDog in on of our new Press/Analyst contact. emacspeak-34.0 (AKA Bubbles) established a new beach-head with respect to rapid task completion in an eyes-free environment.
  • Emacspeak-33.0 AKA StarDog brings unparalleled cloud access to the audio desktop.
  • Emacspeak 32.0 AKA LuckyDog continues to innovate via open technologies for better access.
  • Emacspeak 31.0 AKA TweetDog — adds tweeting to the Emacspeak desktop.
  • Emacspeak 30.0 AKA SocialDog brings the Social Web to the audio desktop—you cant but be social if you speak!
  • Emacspeak 29.0—AKAAbleDog—is a testament to the resilliance and innovation embodied by Open Source software—it would not exist without the thriving Emacs community that continues to ensure that Emacs remains one of the premier user environments despite perhaps also being one of the oldest.
  • Emacspeak 28.0—AKA PuppyDog—exemplifies the rapid pace of development evinced by Open Source software.
  • Emacspeak 27.0—AKA FastDog—is the latest in a sequence of upgrades that make previous releases obsolete and downgrades unnecessary.
  • Emacspeak 26—AKA LeadDog—continues the tradition of introducing innovative access solutions that are unfettered by the constraints inherent in traditional adaptive technologies.
  • Emacspeak 25 —AKA ActiveDog —re-activates open, unfettered access to online information.
  • Emacspeak-Alive —AKA LiveDog —enlivens open, unfettered information access with a series of live updates that once again demonstrate the power and agility of open source software development.
  • Emacspeak 23.0 — AKA Retriever—went the extra mile in fetching full access.
  • Emacspeak 22.0 —AKA GuideDog —helps users navigate the Web more effectively than ever before.
  • Emacspeak 21.0 —AKA PlayDog —continued the Emacspeak tradition of relying on enhanced productivity to liberate users.
  • Emacspeak-20.0 —AKA LeapDog —continues the long established GNU/Emacs tradition of integrated innovation to create a pleasurable computing environment for eyes-free interaction.
  • emacspeak-19.0 –AKA WorkDog– is designed to enhance user productivity at work and leisure.
  • Emacspeak-18.0 –code named GoodDog– continued the Emacspeak tradition of enhancing user productivity and thereby reducing total cost of ownership.
  • Emacspeak-17.0 –code named HappyDog– enhances user productivity by exploiting today's evolving WWW standards.
  • Emacspeak-16.0 –code named CleverDog– the follow-up to SmartDog– continued the tradition of working better, faster, smarter.
  • Emacspeak-15.0 –code named SmartDog–followed up on TopDog as the next in a continuing series of award-winning audio desktop releases from Emacspeak Inc.
  • Emacspeak-14.0 –code named TopDog–was

the first release of this millennium.

  • Emacspeak-13.0 –codenamed YellowLab– was the closing release of the 20th. century.
  • Emacspeak-12.0 –code named GoldenDog– began leveraging the evolving semantic WWW to provide task-oriented speech access to Webformation.
  • Emacspeak-11.0 –code named Aster– went the final step in making Linux a zero-cost Internet access solution for blind and visually impaired users.
  • Emacspeak-10.0 –(AKA Emacspeak-2000) code named WonderDog– continued the tradition of award-winning software releases designed to make eyes-free computing a productive and pleasurable experience.
  • Emacspeak-9.0 –(AKA Emacspeak 99) code named BlackLab– continued to innovate in the areas of speech interaction and interactive accessibility.
  • Emacspeak-8.0 –(AKA Emacspeak-98++) code named BlackDog– was a major upgrade to the speech output extension to Emacs.
  • Emacspeak-95 (code named Illinois) was released as OpenSource on the Internet in May 1995 as the first complete speech interface to UNIX workstations. The subsequent release, Emacspeak-96 (code named Egypt) made available in May 1996 provided significant enhancements to the interface. Emacspeak-97 (Tennessee) went further in providing a true audio desktop. Emacspeak-98 integrated Internetworking into all aspects of the audio desktop to provide the first fully interactive speech-enabled WebTop.

9 About Emacspeak:

Originally based at Cornell (NY) — http://www.cs.cornell.edu/home/raman —home to Auditory User Interfaces (AUI) on the WWW, Emacspeak is now maintained on GitHub —https://github.com/tvraman/emacspeak. The system is mirrored world-wide by an international network of software archives and bundled voluntarily with all major Linux distributions. On Monday, April 12, 1999, Emacspeak became part of the Smithsonian's Permanent Research Collection on Information Technology at the Smithsonian's National Museum of American History.

The Emacspeak mailing list is archived at Vassar –the home of the Emacspeak mailing list– thanks to Greg Priest-Dorman, and provides a valuable knowledge base for new users. Note that we are currently looking for a new home for the mailing list — stay tuned; in the meantime, the list is available via nntp+news.gmane.io:gmane.emacs.emacspeak.general from within Gnus.

10 Press/Analyst Contact: Tilden Labrador

Going forward, Tilden acknowledges his exclusive monopoly on setting the direction of the Emacspeak Audio Desktop (🦮) and promises to exercise this freedom to innovate and her resulting power responsibly (as before) in the interest of all dogs.

*About This Release:


Windows-Free (WF) is a favorite battle-cry of The League Against Forced Fenestration (LAFF). –see http://www.usdoj.gov/atr/cases/f3800/msjudgex.htm for details on the ill-effects of Forced Fenestration.

CopyWrite )C( Aster, Hubbell and Tilden Labrador. All Writes Reserved. HeadDog (DM), LiveDog (DM), GoldenDog (DM), BlackDog (DM) etc., are Registered Dogmarks of Aster, Hubbell and Tilden Labrador. All other dogs belong to their respective owners.

Monday, November 02, 2020

Web: Data Tables Can Be More Than Screen-Deep

Web: Data Tables Can Be More Than Screen-Deep

1 Executive Summary

A few years ago, layout tables made speaking Web content difficult; that phase has now morphed into an even more horrifying soup of div and span tags styled by CSS. This also means that now, if you encounter a table element, it likely contains some useful data; also, deeply nested tables are beginning to feel like a thing of the past.

Sadly, this has not made getting data out of HTML tables any easier. A combination of badly created markup, many redundant DOM nodes that exist purely for enabling DOM scripting, and heavy-weight DOM structures that result from code-generation have mostly created a different, but equally appalling situation .

One of the primary reasons to do everything in a rich end-user environment like Emacs is the ability to share data across tasks and being able to manipulate data as data, rather than working with that data's underlying visual representation. Emacs can now render Web documents that are content focused, so the next immediate desire is to be able to extract data in a useful form from EWW rendered pages. This article describes one simple approach that lets me turn HTML tables found in the wild into a coherent tabular data structure that I can access meaningfully via emacspeak to obtain multiple spoken views of the data.

2 Initial Approach That Failed

I first tried to see if I could make EWW annotate the rendered table data with text properties — sadly that proved impossible to do in the current implementation. Note however that Emacspeak does use text properties to provide access to other aspects of HTML document structure such as section headers, and moving through the rendered tables in an EWW buffer.

3 Ensuring That EWW Rendered Tables Are More than Screen-Deep

I implemented the approach described below a couple of weeks ago and it appears to work well barring a few known limitations.

  1. I advice EWW to store a pointer to the Table DOM in the EWW buffer.
  2. I defined a function that converts the DOM nodes from the table-dom into a two-dimensional vector.
  3. I then pass this structure to Emacspeak's Table-UI module to obtain a browsable two-dimensional structure.
  4. Module emacspeak-table-ui enables the user to obtain multiple spoken views of the tabular data.

See the following sections for details on each of these steps.

3.1 Storing A Pointer To The Table-DOM

(defadvice shr-tag-table-1 (around emacspeak pre act comp) 
  "Cache pointer to table dom as a text property"
  (let ((table-dom (ad-get-arg 0))
        (start (point)))
    ad-do-it
    (unless (get-text-property start 'table-dom)
      (put-text-property start (point)
                         'table-dom table-dom))
    ad-return-value))

This advice stores a pointer to the DOM of the table being rendered over the region containing the rendering.

3.2 Generate A Tabular Structure From The Dom

Function emacspeak-eww-table-table generates a two-dimensional vector that encaspulates the tabular data.

(defun emacspeak-eww-table-table ()
  "Return table cells as a table, a 2d structure."
  (let* ((data nil)
         (table (get-text-property (point) 'table-dom))
         (head (dom-by-tag table 'th)))
    (cl-assert table t "No table here.")
    (setq data
          (cl-loop
           for r in (dom-by-tag table 'tr) collect
           (cl-loop
            for c in
            (append
             (dom-by-tag r 'th)
             (dom-by-tag r 'td))
            collect
            (string-trim (dom-node-as-text c)))))
    ;;; handle head case differently:
    (if head
        (apply #'vector (mapcar #'vconcat  (cdr data)))
      (apply #'vector (mapcar #'vconcat  data)))))

The above code handles the case where there are header (i.e., th) cells specially to avoid a bug where we get two copies of the data. The nested loops generates a list of lists, and the final call turns this into a two-dimensional vector.

3.3 Browsing Tables As Data

Interactive command emacspeak-eww-table-data (bound to C-t) takes the table at point, i.e. when point is anywhere within a table rendering, and creates a browsable table buffer as implemented by module emacspeak-table-ui.

(defun emacspeak-eww-table-data ()
  "View  table at point as a data table using Emacspeak Table UI."
  (interactive)
  (let ((data (emacspeak-eww-table-table))
        (data-table nil)
        (inhibit-read-only  t)
        (buffer
         (get-buffer-create
          (format  "Table: %s" (emacspeak-eww-current-title)))))
    (setq data-table (emacspeak-table-make-table data))
      (emacspeak-table-prepare-table-buffer data-table buffer)))

The two-dimensional vector described earlier is now converted to a tabular structure as expected by module emacspeak-table-ui, the primary difference being that this structure explicitly captures row and column headers.

3.4 Browsing The Tabular Data

Emacspeak's Table UI allows one to:

  1. Move through table cells, either by row or column.
  2. Determine what is spoken during such navigation,
  3. Spoken views can include cell value, row header and column header.
  4. For more advanced use-cases, one can define a row filter or column filter, think of these as specialized formatters that can format selected cells and their headers into a natural-sounding sentence.

Saturday, October 10, 2020

Extracted A Light-Weight Key-Reader By Progressive Simplification

Extracting A Light-Weight Key-Sequence Reader By Progressive Simplification

1 Background

In the previous article entitled On Defining Keys In Emacs I covered the issue of declaring key-sequences when defining keyboard short-cuts. During the last week, I took the underlying Emacs Lisp function edmacro-parse-key and via a process of progressive simplification derived a new new-kbd function that is much simpler and consequently easier to understand. You can see the step-by-step simplification via the Git history for file new-kbd.el (note: used to be called ems-kbd.el). That file contains the final version of the simplified function, along with a test-suite that verifies that it's behavior is convenient with the solution built into Emacs. The updated function is now part of Emacspeak and is named ems-kbd in that package.

The next section gives a high-level overview of the steps that led to the final version.

2 Steps Toward Simplification

2.1 Separate Tokenization From Processing

Function edmacro-parse-keys interweaves the process of tokenizing its input string and how various parts of that string are processed in a single while loop.

The first step in simplification was to separate these steps, by using function split-string to split the input string on whitespace to generate a list of words.

A simple cl-loop is then used to turn each word into a key that is accumulated into a result vector.

2.2 Refactoring Case Analysis

Once tokenization is factored out, the remainder of function edmacro-parse-keys converts each key-specification into either the corresponding string or vector representation.

The original requirement of parsing the serialization of keyboard-macros brought along additional logic that I first eliminated, since my goal was to create a function to be used in defining keyboard-shortcuts.

  • I eliminated code that handled invocation of M-x execute-extended-command during a keyboard-macro.
  • I eliminated processing of comments within the keyboard-macro serialization.

2.3 Rearranging Conditionals

Next, I rearranged conditionals and in that process eliminated cond clauses that were now effectively dead-code.

In the process, I also eliminated test-predicates that had side-effects to hopefully result in less fragile code.

2.4 Lexically Bind Regex Patterns

To improve readability, I created let-bindings to some of the regex patterns used to identify key-sequence patterns. In the process, I also made these more readable by using [:space:] for white-space tests.

2.5 Always Return A Vector

Finally, I setup the new function to always return a vector; function edmacro-parse-keys returns either a string or a vector based on how it is called. Since Emacs now takes a vector in every context where a key-sequence is expected, this simplification does not break when using our simplified function for defining keys.

   (defun new-kbd (string )
  "Simplified and hopefully more robust kbd function.
Always returns a vector i.e. like passing need-vector to edmacro-parse-keys. "
  (let ((res [])
        (special-char-reg "^\\(NUL\\|RET\\|LFD\\|ESC\\|SPC\\|DEL\\)$")
        (modifier+angle-reg "^\\(\\([ACHMsS]-\\)*\\)<\\(.+\\)>$"))
    (cl-loop
     for word in (split-string string)
     do
     (let* ((key nil))
       (cond 
        ((and ;;; modifier+-<key> without DEL etc
          (not (string-match special-char-reg word))
          (string-match modifier+angle-reg word))
         (setq key
               (list
                (intern 
                 (concat ;;; strip < and >
                  (substring word (match-beginning 1) (match-end 1))
                  (substring word (match-beginning 3) (match-end 3)))))))
        (t
         (let ((prefix 0)
               (bits 0))
           (while ;;; calculate modifier bits
               (string-match "^[ACHMsS]-." word)
             (cl-incf bits
                      (cdr
                       (assq (aref word 0)
                             '((?A . ?\A-\^@)
                               (?C . ?\C-\^@)
                               (?H . ?\H-\^@)
                               (?M . ?\M-\^@)
                               (?s . ?\s-\^@)
                               (?S . ?\S-\^@)))))
             (cl-incf prefix 2)
             (cl-callf substring word 2))
           (when (string-match "^\\^.$" word)
             (cl-incf bits ?\C-\^@)
             (cl-incf prefix)
             (cl-callf substring word 1))
           (when-let
               (found
                (assoc word
                       '(("NUL" . "\0")
                         ("RET" . "\r")
                         ("LFD" . "\n")
                         ("TAB" . "\t")
                         ("ESC" . "\e")
                         ("SPC" . " ")
                         ("DEL" . "\177"))))
             (setq word (cdr found)))
           (cond ;;; apply modifiers 
            ((= bits 0) (setq key word))
            ((/= (length word) 1)
             (error "%s: Prefix  must precede a single character, not %s"
                    string word))
            ((and
              (/= (logand bits ?\C-\^@) 0)
              (string-match "[@-_a-z]" word))
             (setq key
                   (list (+ bits (- ?\C-\^@)
                            (logand (aref word 0) 31)))))
            (t (setq key (list (+ bits (aref word 0)))))))))
;;; push key on to the result vector 
       (when key (cl-callf vconcat res key))))
    res))

You can verify the code above by running the tests found at the end of file new-kbd.el — the tests were extracted from the various patterns described in the Elisp Reference, as well as by reading the code in edmacro-parse-keys.

2.6 Closing Thoughts

The above simplification exercise was done by:

  1. Starting with the original edmacro-parse-keys copied over to a new file and renamed to function new-kbd.
  2. Adding a set of tests at the end of file, essentially this is a let that binds a set of tests, then compares the result of calling our new function on each value with that returned by the original.
  3. Modifying and simplifying our new function and running eval-buffer after each step.
  4. It was a fun exercise to see order emerge from chaos at each step!

Monday, October 05, 2020

On Defining Keys In Emacs

On Defining Keys In Emacs

1 Overview

Emacs is extremely flexible with respect to letting you bind keys to commands. Interestingly, and perhaps because of its history tracing back to keyboard macros, naming the key you wish to bind is not so straight-forward as it appears on the surface. Here are things I've used and learnt over the last 30 years of Emacs hackery:

  1. The most basic way of naming a key is via a string of the form \C-a or \M-\C-a where \C denotes the Control Modifier.
  2. This notation gets unwieldy fast when using multiple modifiers as in the \M-\C-a example.
  3. It gets worse, under X, you can bind \C- / for /Control Space — notice that the space character here which is easy to miss as white-space is significant.
  4. The \<modifier>-char notation mostly appears to date back to the age of the terminal emulator (tty), so for example, it cannot denote Control+Right for example.
  5. The Emacs and Elisp info manuals recommend using function kbd for this reason, this function on the surface provides a unified interface for naming keys.

If you look no further, you remain happy, but …

2 Function kbd

But if you do peel the onion, here is what you find:

  1. Function kbd does nothing more than calling function read-kbd-macro.
  2. Function read-kbd-macro documents itself as reading the region as a keyboard macro.
  3. The above overloading is achieved by the call to function edmacro-parse-keys.
  4. And finally we reach the scary core of the onion that is sufficient to make your eyes water!
  5. Function edmacro-parse-keys is an inscrutable piece of code that both looks extremely clever and magical and like all clever code, feels fragile.

3 Understanding And (Hopefully) Simplifying Function kbd

A simplified ems-kbd function that is free from the complexity resulting from reading in a saved keyboard macro feels like a worthwhile goal. I started down this road both to understand function edmacro-parse-keys — sadly, I haven't yet found a specification for naming all available keys outside of the implementation of that function. So I started ems-kbd.el along with a simple test-suite to see how far I could get toward the goal of creating an equivalent kbd function.

3.1 Steps So Far

  1. Documented the implementation.
  2. Added a simple set of tests in the file.
  3. Changed if to cond or when as appropriate.
  4. Eliminated the logic that handled the keyboard macro serialization for repeated keys.
  5. Removed the logic for handling invocations of execute-extended-command — otherwise known as M-x.
  6. A lot more remains, e.g.,
    • simplifying how modifier bits are handled,
    • Simplifying how special patterns like SPC or TAB are handled.
    • And likely a lot more.

An alternative approach might be to rewrite it from scratch, but that feels intractable unless I can track down a specification for naming keys that is exhaustive with respect to the various conventions that have been used over the years.

Wednesday, September 16, 2020

Emacs: Paired Commands --- Efficient Keyboard Interaction Using Hydra

Emacs: paired Commands — Efficient Keyboard Interaction Using Hydra

1 Executive Summary

Emacs commands such as yank and yank-pop or undo-only and undo-redo come in logical pairs. Such logical pairs (or command tuples in general) are characterized by the fact that one often invokes a sequence of these commands repeatedly until the desired result is attained. Package Hydra defines an elegant means of combining such command pairs into a single higher-level command that can be invoked more efficiently from the keyboard. To my knowledge, the only built-in Emacs command that exhibits a similar behavior is Emacs' text-scale-adjust.

1.1 Example: undo-oanly And undo-redo

Command undo-only allows one to move back through a sequence of changes.Command undo-redo in contrast undoes previous undo commands. In practice, one often moves back through a sequence of operations, with a few undo-redo invocations mixed in if one moves back too far.

Emacs convention would suggest that one bind these commands to separate keys, but this has a few disadvantages:

  • Binding separate keys to the two commands feels wasteful, especially as unbound keys in Emacs become increasingly precious.
  • It's not ergonomic to jump between the two commands in this pair unless one chooses the key-bindings carefully — as an example, I used C-x u for undo-only and _C-x C-u for undo-redo for many years. But now, a continuous sequence of undo operations requires too much chording.

1.2 A Hydra Inspired Solution

  1. Combine the two commands into a higher-level command.
  2. Bind that command to a single key, in my case C-/ (C-_ on a tty).
  3. When invoked, the Hydra-defined command does one of the following:
    1. Invokes undo-only on being called, then continues to read keys.
    2. Subsequent presses of / invoke command undo-only.
    3. Pressing \ invokes undo-redo.
    4. Any other key quits the Hydra-generated higher-level command.

This is defined as part of Emacspeak's collection of Muggles, as is evident, this is much nicer to your wrists.

(global-set-key
 (kbd "C-/") 
 (defhydra emacspeak-muggles-undo-only/undo-redo
   (:body-pre (emacspeak-hydra-body-pre "Undo Smartly")
              :pre
              (progn
                (when hydra-is-helpful (emacspeak-hydra-toggle-talkative))
                (emacspeak-hydra-pre))
              :post emacspeak-hydra-post)
   "Undo"
   ("?" (emacspeak-hydra-self-help "emacspeak-muggles-undo-only/undo-redo"))
   ("/" undo-only nil)
   ("\\" undo-redo nil)))

Note that the above can be simplified by dropping the emacspeak-specific clauses when not using Emacspeak.

1.3 Repeatable Yank/Pop From The Hydra Wiki

I originally discovered the metaphor of repeatable paired commands a few years ago from the Hydra Wiki which demonstrates a repeatable yank/pop. To summarize its effects:

  1. C-y invokes the hydra-generated higher-level command.
  2. Subsequent presses of y is the same of yank-pop.
  3. Pressing Y invokes yank-pop with a negative argument.
  4. Consequence of above, you can grab the last entry on the kill-ring by pressing Y after invoking the command — would take a lot more keystrokes in vanilla Emacs.
  5. You can also add smart affordances such as searching the kill-ring via interfaces such as ido.

1.4 Conclusion

As Emacs gains in functionality, grouping commands into higher-level abstractions, generating a single higher-level command that is bound to a key, and using that invocation context to implement the result of subsequent keypresses is an abstraction that generalizes well.

Tuesday, September 08, 2020

Searching GMail From GNUS

Using GMail Search Operators In GNUS

1 Executive Summary

I have been using the following to search GMail from GNUS for over 8 years now. The recent announcement of the nnselect back-end reminded me that I had never gotten to writing this up formally, So here goes. With the described solution in place, you can search your GMail from within GNUS using the same GMail Search operators that you're familiar with from within your Web Browser, e.g. searches of the form from: foo, subject:bar, after:date and combinations of the above.

2 Background

You can read email with GNUS, and many people read GMail with GNUS, however, the details of GMail setup with GNUS wont fit this margin. For my own GMail setup using Ceasar's excellent auth-xoauth2 package, see file gnus-gmail-prepare.el.

3 Leveraging GNUS Back-end NNIR To Search GMail

GMail is accessed from GNUS using the imap protocol. The imap specification defines a set of standard search operators; GMail itself defines a slightly different and arguably easier to use set of search operators. Module gm-nnir himplements both the standard IMap search operator as well as GMail's search operators; in practice, I have mostly only used the GMail Search operators in the last 8 years since implementing this module.

Without further ado, here is the code to enable GMail Search:

(defun gm-nnir-group-make-gmail-group (query)
  "Use GMail search syntax.
See https://support.google.com/mail/answer/7190?hl=en for syntax. "
  (interactive "sGMail Query: ")  
  (let ((nnir-imap-default-search-key "imap")
        (q (format "X-GM-RAW \"%s\"" query)))
    (cond
     ((gnus-group-group-name)           ; Search current group
      (gnus-group-make-nnir-group
       nil                              ; no extra params needed
       `(nnir-specs (nnir-query-spec (query ,q)))))
     (t (error "Not on a group.")))))

I bind the above to / by using

(define-key gnus-group-mode-map "/" 'gm-nnir-group-make-gmail-group)

4 Example Of Use

I am subscribed to list emacs-devel@gnu.org and email sent to that list gets GMail Label emacs-devel. In Gnus, I open that label as group emacs-devel@gnu.org. Typing / on the group line and entering

from:rms after:2020/09/01

in the minibuffer results in the following:

1.1 Re: Good first issues to contribute Richard Stallman 05-Sep [5.3k]
2.1 Lars Ingebrigtsen is now one of the Emacs maintainers Richard Stallman 06-Sep [4.9k]
3.1 Re: A new user perspective about "Changes for emacs 28" Richard Stallman 07-Sep [5.5k]
4.5 Re: Changes for emacs 28 Richard Stallman 07-Sep [5.3k]
5.1  Richard Stallman 07-Sep <6.2k>
6.1  Richard Stallman 07-Sep <6.0k>
7.1  Richard Stallman 07-Sep <5.5k>
8.1  Richard Stallman 07-Sep <5.7k>

The search above creates an ephemeral group with matching messages appearing as shown above, you can read messages, reply to them and do anything else that you might ordinarily do within the GNUS interface.

Sunday, August 16, 2020

Start Emacs In A Defun

Start Emacs In A Defun

1 Summary

This is a follow-up to my earlier article titled Speeding Up Emacs Startup from August 2017. Three years later, I once again spent time cleaning up and refactoring the results as described below. The end-result is to once again speed up Emacs startup, (about 25% faster on my laptop)while making the setup cleaner and easier to maintain than before.

2 Start Emacs In A Defun

This startup file is set up with the following goals:

  1. Speed up emacs startup — setting environment variable TVR_TIME_EMS before starting emacs produces detailed timing information in the Messages buffer.
  2. Customize packages via Custom as far as possible.
  3. Keep the custom settings in a separate file, with a later goal of turning that into a theme.
  4. After converting to a theme, Move machine-specific custom settings into a separate host-specific custom file, thus making the earlier theme host-independent. Place host-specific non-customizable bits in default.el (not done yet).
  5. Define package-specific settings not available via Custom in a package-specific <package>-prepare.el file.
  6. Install everything from elpa/melpa as far as possible. (vm is an exception at present) — I have nearly 200 packages activated.
  7. The startup file is a collection of functions with entry-point tvr-emacs.
  8. The only top-level call is (tvr-emacs).
  9. Function tvr-emacs starts up Emacspeak, and sets up two hooks:
    • after-init-hook to do the bulk of the work.
    • emacs-startup-hook to set up initial window configuration.
  10. Function tvr-after-init-hook on after-init-hook does the following:
    • Load package-specific prepare.el files.
    • Load the custom settings file.
    • Starts up things like the emacs server.
    • Some of these tasks are done on a separate thread using make-thread.
  11. The work of loading files etc., is done within macro tvr-fastload

which sets up an efficient environment for loading files.

3 Conclusion

With this setup, M-x emacs-init-time shows init-time as

1.288381225 seconds

on my laptop with an SSD. Setting package-quickstart to T is a major win when running with a spinning-disk instead of an SSD. But the biggest win is that I no longer have to go hunting to find out where something in emacs got configured a given way — AKA, there are a limited number of places I need to look.

4 Wish-List

  1. Remembering the name of a custom-setting you set up a while ago is still a challenge, You cant find it unless you remember its approximate name.
  2. Command emacspeak-wizards-customize-saved bound to C-h C-s helps some in this regard but is a stop-gap solution.
  3. Custom themes are not easy to use.
  4. I keep my custom-file checked into a local Git repository and is the only part of my setup that I cannot publish — since that file tends to hoover up information that you shouldn't publish, e.g., aPI keys and other private/personal bits.
  5. Perhaps Emacs needs at least two custom-files, a public and a private custom-file.

Tuesday, June 16, 2020

Learning Rust: Programming The Pick-Up Sticks Game

Learning Rust: The Pick-Up Sticks Game

1 Overview

This directory contains an implementation of the Pick Up Sticks game
described in my paper Thinking Of Mathematics (Section 5).


It's an interesting experience writing it in Rust as I learn the
language. The original implementation described in my paper was
written in 1987 in Fortran-77, and consisted of one single
function. Though that style of programming would be frowned upon today
and is clearly not advisable for programming in the large, it's
interesting to observe that a more structured implementation as seen
in this Rust implementation qrequires a lot more fore-thought with
respect to code organization.


2 Programming Environment

here is a short overview of the programming environment used:


  1. Emacs 28.0.50 with emacspeak 52.0.
  2. Package eglot for managing the project with an LSP server.
  3. Rust Language Server (RLS) as the LSP server.
  4. Package company for completion.
  5. Package yasnippet for code templates.
  6. Package rust-mode for Rust editing smarts.
  7. Package racer for additional cross-referencing and
    documentation support.
  8. Package cargo for cargo integration from inside Emacs.

In the process of setting up my Rust environment, I also
speech-enabled Emacs packages rust-mode, racer and cargo for Emacspeak.



3 Books

I downloaded The Rust Programming Language (2018) from Bookshare
and it's what I am still using as I write this. Note that this book is
also available in the Rust distribution. The version in the Rust
distribution is a little less usable since it's split into multiple
smaller HTML files with each file repeating a lot of navigational
boiler-plate at the top.


4 Experience Learning Rust

I usually find that I learn a language better if I write some code as
I learn the language.
In this instance, I decided to program the pick-up-sticks game — a
simple game that I programmed in 1987 for the final class project for
CS-101 at IIT-Bombay. Here are the rules of the game:


  1. This is a two-player game and the game starts with \(n\) sticks.
  2. The first player can pick at most \(n-1\) sticks.
  3. Assume a player picks \(k\) sticks. At the subsequent turn, opponent
    can pick at most \(2 * k\) sticks.
  4. The player who is able to clean-up the remaining sticks while
    adhering to the rules is the winner.

Read Thinking Of Mathematics (Section 5) for a description of an
algorithm that is guaranteed to win.


5 The Implementation

Learning Rust's ownership rules for memory management, and learning to
use references the Rust way were some of the things that were unique
to this learning experience.
Rust has some unique features including declaring lifetimes that are
typically needed in more advanced cases; however in my initial
attempts, not doing things the Rust way caused compile-time errors
that initially guided me toward using and declaring
lifetimes. Eventually, all of those declarations became unnecessary.
More generally, the Rust compiler turns out to be a very good Rust
teacher.


6 Crux Of The Implementation

See module game.rs for the implementation. The core of the
implementation is still a handful of lines to implement the winning
strategy of:


  1. If the number of sticks at the start is a Fibonacci number, ask
    the opponent to play first.
  2. At each turn, force the opponent toward the closest Fibonacci number.
  3. Do above while respecting the limit rule, i.e. if you pick \(k\)
    sticks, the opponent can pick up to \(2k\) sticks, so never pick \(k\)
    where \(3k >= n\).
  4. The result of (3) is to subdivide the game into smaller games
    when playing with larger values of \(n\) — see the while loop in
    method my_move.

7 Closing Thoughts

  1. The computing environment I now have is far more sophisticated
    than what I had in 1987.
  2. Today, I have interactive completion, source-code
    cross-references, on-the-fly access to documentation, and a fully
    accessible book where I can look up things whenever I want.
  3. In 1987, I did most of my thinking and problem-solving in my
    dorm-room with no computer to hand. When ready with the solution,
    I made a few notes in Braille using a pocket-slate and stylus,
    then went to the computer room with a volunteer reader and typed
    up the program, with the student volunteer providing high-quality
    interactive spoken feedback.
  4. Interestingly, I think it took me less time from memory to
    implement the solution in 1987 — perhaps this is time shrinking
    with number of years passed.
  5. Either way, the primary take-away is that it pays to analyse a
    problem before one actually starts writing code. Writing code is
    always fun, and today, even more so given the excellent array of
    tools — but unless one focuses on the problem at hand, one can
    spend a lot of time sharpening one's pencils as opposed to
    writing something useful.

Wednesday, June 03, 2020

Viewing Data Records As Forms --- Old Is Gold

Viewing Data Records As Forms: Old Is Gold!

1 Executive Summary

Given a file containing data records made up of multiple fields, you
can easily view them using Emacs' forms library.


2 Background: BBC Program Listings

I use Perl utility get_player to fetch details of BBC Radio
programs. When I was using this frequently, I had installed package
iplayer.el from Melpa — that package presented the data as a
nicely organized Org document. Time passed, and I somehow stopped
using it, until … last week. Then I discovered that package
iplayer on Melpa hadn't been updated in a few years, and worse had
broken because package org no longer includes now obsoleted
sub-module orgstruct.



3 Task: Viewing BBC Program Listings

When I realized package iplayer was broken, I tried to make up for
its loss for a few days by using shell-level utilities like cut. But
then I missed the convenience of being able to work with the data with
all of Emacs' power and was initially tempted to write a new package
— after all, how hard is it to take a record, split it into fields
and display it in a desired form? Fortunately, I remembered another of
my favorite edicts from the creator of Perl (Larry Wall)

Lazy Programmer Is A Good Programmer


At the same time I had a strong sense of dejavu — in the early daysa
of Emacspeak (approx 1995), I remembered demonstrating the power of
Emacs to manipulate and display data records by using file
/etc/passwd as an example.


4 The Free Solution

So the completely free (AKA zero-work) solution I used was to leverage
Emacs' built-in forms library — the solution
as created
in
get-iplayer.el is below:




(setq forms-read-only t)
(setq forms-file (expand-file-name "~/.get_iplayer/radio.cache"))
(setq forms-number-of-fields 16)
(setq forms-field-sep "|")
(setq forms-format-list
      (list
       "Id: "  1 "\t" "Name: " 3 "\n"
       "Episode: " 4 "\t" "Description: "  12 "\n"))


With the above in place, you can:


  1. M-x forms-find-file RET get-iplayer.el
  2. This displays one record at a time as specified by forms-format-list.
  3. You can search through records etc.

Saturday, May 30, 2020

Magit/Forge Cheatsheet For GitHub Workflow

Magit/Forge Fork And Create Pull-Request Cheat-Sheet For GitHub

The previous article covered the fork/create-pullreq workflow for
GitHub without using a browser.
It turns out that in learning by doing, I had made a few mis-steps
that made things a lot more convoluted. Here is a quick cheat-sheet on
how to do this exclusively with Magit/Forge.


  1. Run M-x magit-status on your Git clone of the project to
    which you wish to contribute.
  2. Add your GitHub user-id "tvraman" in my case to forge custom
    option forge-owned-accounts.
  3. In the magit-status buffer above, type 'cf to create the fork
    and answer the prompts with the defaults as they appear in the minibuffer.
  4. Create your feature branch, add your contribution and check-in.
  5. In the magit-status buffer, type 'cp to create the
    pull-request.

Share And Enjoy!


Thursday, May 28, 2020

GitHub Standard Fork And Pull-Request Workflow From Emacs


GitHub Standard Fork And Pull Request From Inside Emacs

1 Executive Summary

Collaborating via GitHub (and similar platforms) requires
understanding and following a somewhat standardized fork, create, push
workflow. Most of the gory details of this workflow typically get
hidden by instructions of the form

Sign in to GitHub in your browser and /push/ the button on the  top-left

or something similar.
I live exclusively in Emacs and use Chrome as the weapon of
last-resort, this article details how to perform the afore-mentioned
GitHub collaboration workflow from within Emacs. Caveat — you may
still need to resort to Chrome or Firefox to set up GitHub tokens etc.


2 The Standard GitHub Workflow

The GitHub collaboration workflow is documented (if somewhat sparsely)
on GitHub, and it's augmented by many excellent tutorials on the
Web. I will avoid repeating that information, other than to link to
them below and point out that reading those is essential to build a
clear mental picture of how things work. The remainder of this article
will focus on how to achieve the equivalent without having to push
buttons on the GitHub web site.




3 Collecting The Needed Tools

Here are the tools I needed to achieve the goal of achieving the above
workflow from within Emacs and without resorting to a Web browser.


  1. Package Magit from Melpa.
  2. Package Magit/Forge from Melpa.
  3. Command-Line tool hub from GitHub
  4. Newer Command-Line tool gh from GitHub.


Command-line tools gh and hub are written in go and implement
the GitHub API.
At the time of writing, hub appears more complete, but gh is
catching up fast.


4 Implementing The GitHub Workflow

I'll use a concrete example to avoid introducing additional confusing
terminology. In my own learning journey, I often got confused by
terminology such as name, remote, etc. each of which were being
used in a specialized sense.


4.1 Task:

Create a Pull-Request to project speech-rule-engine from user
zorkow/ — the project repository is
Speech Rule Engine from user zorkow.



Fork
Fork the project you wish to contribute to. I found multiple ways of doing this (eventually).
  1. magit/forge inside emacs:
'cf RET RET

This invokes command M-x forge-fork which prompts for two name
arguments. The meaning of those arguments are somewhat
non-obvious which is why I failed initially. To use it
successfully, set Forge Custom option forge-owned-accounts to
your GitHub user-id — in my case tvraman. Note that this
variable can hold a list of GitHub user-ids that you use.

(setq forge-owned-accounts '(("tvraman")))

With the above in place, go to where you have the source
repository checked out, in my case:

cd ~/sources/zorkow/speech-rule-engine

and open the magit status buffer by executing

M-x magit-status

and execute Emacs command forge-fork — by default
magit/forge binds this to 'cf. The minibuffer shows the
user-id you set up in forge-owned-accounts/ earlier as the
default, press RET to accept the user-id value for both the
fork and remote arguments.

  • The above flow works once it's all set-up — note however that
    if you are happier to just do this at the shell, you can use
    either hub or gh — read the documentation for those
    commands. Either way, you now have a copy of the
    speech-rule-engine project under your list of GitHub
    repositories — in my case at https://github.com/tvraman/speech-rule-engine.
Clone
Next, git clone the fork you just created. This is just a regular clone operation, in my case I did:
mkdir -p ~/sources/tvraman; cd ~/sources/tvraman; git clone https://github.com/tvraman/speech-rule-engine

Create Your Changes
Follow the steps from the earlier tutorials to do your work, i.e., creating a feature-branch to hold your changes,etc. Note that all this work is being done in your fork, i.e., in this example, within ~/sources/tvraman/speech-rule-engine.
Create Pull Request
When ready, open the magit-status buffer for your fork, and create the pull-request using magit/forge — in the magit status buffer, type 'cp.
Uploading The Pull Request
Now, you need to send the pull-request to the author of the project you are contributing to — this is again one of those steps that all the docs talk about pushing a button on GitHub.com. The easiest means I found to do this was via command-line tool hub:
cd ~/sources/tvraman/speech-rule-engine; hub pull-request 

Assuming you have emacsclient configured as your EDITOR, this opens
a standard commit-like message buffer that lets you complete the
action. Result: a new, shiny pull-request shows up in the target
project — in this case in zorkow/speech-rule-engine.


Sunday, May 03, 2020

Emacspeak 52.0 (WorkAtHomeDog) Unleashed!

Announcing Emacspeak 52.0—WorkAtHomeDog!

The enjoyment of one's tools is an essential ingredient of successful work. – Donald E. Knuth


1 For Immediate Release:

San Jose, CA, (May 4, 2020)


1.1 Emacspeak 52.0 (WorkAtHomeDog) 🦮 Unleashed!

— Making Telecommuting Great Again!


Advancing Accessibility In The Age Of User-Aware Interfaces — Zero
cost of Ownership makes priceless software Universally affordable!




Emacspeak Inc (NASDOG: ESPK) — http://github.com/tvraman/emacspeak
— announces the immediate world-wide availability of Emacspeak 52.0
(WorkAtHomeDog) 🦮 — a powerful audio desktop that leverages today's evolving
Data, Social and Assistant-Oriented Internet cloud to enable working
effectively from anywhere!


2 Investors Note:

With several prominent tweeters expanding coverage of #emacspeak,
NASDOG: ESPK has now been consistently trading over the social net at
levels close to that once attained by DogCom high-fliers—and as of
May 2020 is trading at levels close to that achieved by once
better known stocks in the tech sector.


3 What Is It?

Emacspeak is a fully functional audio desktop that provides complete
eyes-free access to all major 32 and 64 bit operating environments. By
seamlessly blending live access to all aspects of the Internet such as
ubiquitous assistance, Web-surfing, blogging, social computing and
electronic messaging into the audio desktop, Emacspeak enables speech
access to local and remote information with a consistent and
well-integrated user interface. A rich suite of task-oriented tools
provides efficient speech-enabled access to the evolving
assistant-oriented social Internet cloud.


4 Major Enhancements:

This version requires emacs-26.1 or later.


  1. Emacs 27 Support 🤻
  2. Updated URL templates 🕷
  3. Updated websearch wizards 🧙
  4. Updated EWW support 🕸
  5. Speech-enables Emacs Chess ♕ ♔
  6. Speech-enables package Vuiet for music discovery and playback
    using LastFM 🎼
  7. Smart templates for accessing Hacker News ⎔
  8. Updated support for Emacs Ipython Notebooks 📓
  9. Works fluently with Sage Notebooks  


— And a lot more than will fit this margin. … 🗞


5 Establishing Liberty, Equality And Freedom:

Never a toy system, Emacspeak is voluntarily bundled with all
major Linux distributions. Though designed to be modular,
distributors have freely chosen to bundle the fully integrated
system without any undue pressure—a documented success for
the integrated innovation embodied by Emacspeak. As the system
evolves, both upgrades and downgrades continue to be available at
the same zero-cost to all users. The integrity of the Emacspeak
codebase is ensured by the reliable and secure Linux platform
used to develop and distribute the software.


Extensive studies have shown that thanks to these features, users
consider Emacspeak to be absolutely priceless. Thanks to this
wide-spread user demand, the present version remains priceless
as ever—it is being made available at the same zero-cost as
previous releases.


At the same time, Emacspeak continues to innovate in the area of
eyes-free Assistance and social interaction and carries forward the
well-established Open Source tradition of introducing user interface
features that eventually show up in luser environments.


On this theme, when once challenged by a proponent of a crash-prone
but well-marketed mousetrap with the assertion "Emacs is a system from
the 70's", the creator of Emacspeak evinced surprise at the unusual
candor manifest in the assertion that it would take popular
idiot-proven interfaces until the year 2070 to catch up to where the
Emacspeak audio desktop is today. Industry experts welcomed this
refreshing breath of Courage Certainty and Clarity (CCC) at a time
when users are reeling from the Fear Uncertainty and Doubt (FUD)
unleashed by complex software systems backed by even more convoluted
press releases.


6 Independent Test Results:

Independent test results have proven that unlike some modern (and
not so modern) software, Emacspeak can be safely uninstalled without
adversely affecting the continued performance of the computer. These
same tests also revealed that once uninstalled, the user stopped
functioning altogether. Speaking with Aster Labrador, the creator of
Emacspeak once pointed out that these results re-emphasize the
user-centric design of Emacspeak; “It is the user — and not the
computer– that stops functioning when Emacspeak is uninstalled!”.


6.1 Note from Aster,Bubbles and Tilden:

UnDoctored Videos Inc. is looking for volunteers to star in a
video demonstrating such complete user failure.


7 Obtaining Emacspeak:

Emacspeak can be downloaded from GitHub — see
https://github.com/tvraman/emacspeak you can visit Emacspeak on the
WWW at http://emacspeak.sf.net. You can subscribe to the emacspeak
mailing list — emacspeak@cs.vassar.edu — by sending mail to the
list request address emacspeak-request@cs.vassar.edu. The Emacspeak Blog is a good source for news about recent enhancements and how to
use them.


The latest development snapshot of Emacspeak is always available at
GitHub.


8 History:

  • Emacspeak 52.0 (WorkAtHomeDog) makes working remotely a pleasurable experience.
  • Gigger and more powerful than any smart assistAnt, AssistDog provides

instant access to the most relevant information at all times.

  • Emacspeak 50.0 (SageDog) embraces the wisdom of stability as
    opposed to rapid change and the concomitant creation of bugs.🚭: Naturally Intelligent (NI)™ at how information is spoken, Emacspeak

is entirely free of Artificial Ingredients (AI)™.

  • Emacspeak 49.0 (WiseDog) leverages the wisdom gleaned from
    earlier releases to provide an enhanced auditory experience.
  • Emacspeak 48.0 (ServiceDog) builds on earlier releases to provide
    continued end-user value.
  • Emacspeak 47.0 (GentleDog) goes the next step in being helpful
    while letting users learn and grow.
  • Emacspeak 46.0 (HelpfulDog) heralds the coming of Smart Assistants.
  • Emacspeak 45.0 (IdealDog) is named in recognition of Emacs'
    excellent integration with various programming language
    environments — thanks to this, Emacspeak is the IDE of choice
    for eyes-free software engineering.
  • Emacspeak 44.0 continues the steady pace of innovation on the
    audio desktop.
  • Emacspeak 43.0 brings even more end-user efficiency by leveraging the
    ability to spatially place multiple audio streams to provide timely
    auditory feedback.
  • Emacspeak 42.0 while moving to GitHub from Google Code continues to
    innovate in the areas of auditory user interfaces and efficient,
    light-weight Internet access.
  • Emacspeak 41.0 continues to improve
    on the desire to provide not just equal, but superior access —
    technology when correctly implemented can significantly enhance the
    human ability.
  • Emacspeak 40.0 goes back to Web basics by enabling
    efficient access to large amounts of readable Web content.
  • Emacspeak 39.0 continues the Emacspeak tradition of increasing the breadth of
    user tasks that are covered without introducing unnecessary
    bloatware.
  • Emacspeak 38.0 is the latest in a series of award-winning
    releases from Emacspeak Inc.
  • Emacspeak 37.0 continues the tradition of
    delivering robust software as reflected by its code-name.
  • Emacspeak 36.0 enhances the audio desktop with many new tools including full
    EPub support — hence the name EPubDog.
  • Emacspeak 35.0 is all about
    teaching a new dog old tricks — and is aptly code-named HeadDog in
    on of our new Press/Analyst contact. emacspeak-34.0 (AKA Bubbles)
    established a new beach-head with respect to rapid task completion in
    an eyes-free environment.
  • Emacspeak-33.0 AKA StarDog brings
    unparalleled cloud access to the audio desktop.
  • Emacspeak 32.0 AKA
    LuckyDog continues to innovate via open technologies for better
    access.
  • Emacspeak 31.0 AKA TweetDog — adds tweeting to the Emacspeak
    desktop.
  • Emacspeak 30.0 AKA SocialDog brings the Social Web to the
    audio desktop—you cant but be social if you speak!
  • Emacspeak 29.0—AKAAbleDog—is a testament to the resilliance and innovation
    embodied by Open Source software—it would not exist without the
    thriving Emacs community that continues to ensure that Emacs remains
    one of the premier user environments despite perhaps also being one of
    the oldest.
  • Emacspeak 28.0—AKA PuppyDog—exemplifies the rapid pace of
    development evinced by Open Source software.
  • Emacspeak 27.0—AKA
    FastDog—is the latest in a sequence of upgrades that make previous
    releases obsolete and downgrades unnecessary.
  • Emacspeak 26—AKA
    LeadDog—continues the tradition of introducing innovative access
    solutions that are unfettered by the constraints inherent in
    traditional adaptive technologies.
  • Emacspeak 25 —AKA ActiveDog
    —re-activates open, unfettered access to online
    information.
  • Emacspeak-Alive —AKA LiveDog —enlivens open, unfettered
    information access with a series of live updates that once again
    demonstrate the power and agility of open source software
    development.
  • Emacspeak 23.0 — AKA Retriever—went the extra mile in
    fetching full access.
  • Emacspeak 22.0 —AKA GuideDog —helps users
    navigate the Web more effectively than ever before.
  • Emacspeak 21.0
    —AKA PlayDog —continued the
    Emacspeak tradition of relying on enhanced
    productivity to liberate users.
  • Emacspeak-20.0 —AKA LeapDog —continues
    the long established GNU/Emacs tradition of integrated innovation to
    create a pleasurable computing environment for eyes-free
    interaction.
  • emacspeak-19.0 –AKA WorkDog– is designed to enhance
    user productivity at work and leisure.
  • Emacspeak-18.0 –code named
    GoodDog– continued the Emacspeak tradition of enhancing user
    productivity and thereby reducing total cost of
    ownership.
  • Emacspeak-17.0 –code named HappyDog– enhances user
    productivity by exploiting today's evolving WWW
    standards.
  • Emacspeak-16.0 –code named CleverDog– the follow-up to
    SmartDog– continued the tradition of working better, faster,
    smarter.
  • Emacspeak-15.0 –code named SmartDog–followed up on TopDog
    as the next in a continuing series of award-winning audio desktop
    releases from Emacspeak Inc.
  • Emacspeak-14.0 –code named TopDog–was

the first release of this millennium.

  • Emacspeak-13.0 –codenamed
    YellowLab– was the closing release of the
    20th. century.
  • Emacspeak-12.0 –code named GoldenDog– began
    leveraging the evolving semantic WWW to provide task-oriented speech
    access to Webformation.
  • Emacspeak-11.0 –code named Aster– went the
    final step in making Linux a zero-cost Internet access solution for
    blind and visually impaired users.
  • Emacspeak-10.0 –(AKA
    Emacspeak-2000) code named WonderDog– continued the tradition of
    award-winning software releases designed to make eyes-free computing a
    productive and pleasurable experience.
  • Emacspeak-9.0 –(AKA
    Emacspeak 99) code named BlackLab– continued to innovate in the areas
    of speech interaction and interactive accessibility.
  • Emacspeak-8.0 –(AKA Emacspeak-98++) code named BlackDog– was a major upgrade to
    the speech output extension to Emacs.
  • Emacspeak-95 (code named Illinois) was released as OpenSource on
    the Internet in May 1995 as the first complete speech interface
    to UNIX workstations. The subsequent release, Emacspeak-96 (code
    named Egypt) made available in May 1996 provided significant
    enhancements to the interface. Emacspeak-97 (Tennessee) went
    further in providing a true audio desktop. Emacspeak-98
    integrated Internetworking into all aspects of the audio desktop
    to provide the first fully interactive speech-enabled WebTop.

9 About Emacspeak:

Originally based at Cornell (NY) —
http://www.cs.cornell.edu/home/raman —home to Auditory User
Interfaces (AUI) on the WWW, Emacspeak is now maintained on GitHub
https://github.com/tvraman/emacspeak. The system is mirrored
world-wide by an international network of software archives and
bundled voluntarily with all major Linux distributions. On Monday,
April 12, 1999, Emacspeak became part of the Smithsonian's Permanent
Research Collection
on Information Technology at the Smithsonian's
National Museum of American History.


The Emacspeak mailing list is archived at Vassar –the home of the
Emacspeak mailing list– thanks to Greg Priest-Dorman, and provides a
valuable knowledge base for new users.


10 Press/Analyst Contact: Tilden Labrador

Going forward, Tilden acknowledges his exclusive monopoly on
setting the direction of the Emacspeak Audio Desktop (🦮) and
promises to exercise this freedom to innovate and her resulting
power responsibly (as before) in the interest of all dogs.


*About This Release:



Windows-Free (WF) is a favorite battle-cry of The League Against
Forced Fenestration (LAFF). –see
http://www.usdoj.gov/atr/cases/f3800/msjudgex.htm for details on
the ill-effects of Forced Fenestration.


CopyWrite )C( Aster, Hubbell and Tilden Labrador. All Writes Reserved.
HeadDog (DM), LiveDog (DM), GoldenDog (DM), BlackDog (DM) etc., are Registered
Dogmarks of Aster, Hubbell and Tilden Labrador. All other dogs belong to
their respective owners.

Author: T.V Raman

Created: 2020-04-27 Mon 08:27

Validate