Monday, December 30, 2013

Dragon NaturallySpeaking, Vimperator, and Emacs

My wife got me Dragon NaturallySpeaking for Christmas. It's been fun learning how to use it, but it's been frustrating learning how to browse the Internet with it. I ended up saying a lot of hotkeys while working with Firefox, such as "press ctrl+k" and "press ctrl+pgdn".

Then I discovered Vocola, which allows you to define your own custom voice commands. That, together with Vimperator, which I have already been using, it is now a breeze to use Dragon to browse.

I just installed Vocola according to the directions found here.

Here is my .vimperatorrc file:

set hintchars='0123456789'
inoremap <C-a> <Ins><C-a><Ins>
map J gT
map K gt
highlight Hint font-size:200%;color:white;background-color:red;padding:2px;

Simply put this file in your home directory. If you are using a Windows operating system, this is something like c:\Users\djhaskin987.

Then, with Vocola installed, use Dragon NaturallySpeaking to open Firefox, and say "edit voice commands", and paste the following:

 # Voice commands for firefox
visit <_anything> = {Esc}":open $1";
close tab = {Esc}d;
open tab <_anything> = {Esc}":tabopen $1";
follow <_anything> = {Esc} f $1;
follow tab <_anything> = {Esc} F $1;
next doc = {Esc} J;
previous doc = {Esc} K;
back = {Esc} H ;

Viola! Easy browsing by speech. Just say "follow ", or just "follow" and then say the number that pops up next to the link. To open a webpage, just say "visit" followed by the address. Vimperator will give you a menu of options. A couple of "press tab" and "press enter" commands later and you're in business.

I also plan to use Vocola and Dragon NaturallySpeaking to improve my programming by defining some voice commands for Emacs, sort of like Tavis Rudd, only Vocola is way easier to define voice commands with than Python.

Here is my Vocola file so far for Emacs:

# Voice commands for emacs
<number> := 1..99;
open file = {Ctrl+x}{Ctrl+f};
boom = {Enter};
undo = {Ctrl+Shift+_};
die = {Alt+Backspace};
back = {Backspace};
whack = \;
um = {Alt+b};
curly = "{";
close curly = "}";
paren = "(";
all in = ")";
the <_anything> = $1;
start = {Ctrl+a};
end = {Ctrl+e};
camelize <_anything> = {Alt+x} camelize {Enter} $1 {Enter};
left = {Ctrl+b};
<number> up = {Ctrl+u} $1 {Ctrl+p};
<number> down = {Ctrl+u} $1 {Ctrl+n};
<number> left = {Ctrl+u} $1 {Ctrl+b};
right = {Ctrl+f};
up = {Ctrl+p};
down = {Ctrl+n};
go = {Alt+f};
scroll down = {Ctrl+v};
scroll up = {Ctrl+v};
cut = {Ctrl+k};
yank = {Ctrl+y};
nay = {Alt+y};  

The function "camelize" is an emacs lisp interactive function which takes a phrase like "the grand old duke of york" and turns it into "theGrandOldDukeOfYork", kind of like what is found in the emacs wiki, but changing from space separated instead of underscore separated, and making the function interactive as well.

I hope to also use Emacs templating like Tavis Rudd does in his video  to make functions and classes by speech easier in Emacs.

EDIT: I'm putting my vocola files for easy browsing and programming by voice in a git repository. Pull requests wecome!

Thursday, December 19, 2013


What do you want? I dabble.

I have this amazing pancake recipe I made up.

I take this from the original "German Pancake" recipe my wife found, but that was baked in the oven. This is in a pan.

It's called a Mancake rather than a pancake for the following reasons:

  1. It has tons of eggs (protein) in it
  2. It is dead simple -- only requires a 1/2 cup size measuring cup and a teaspoon. (For those of you who subscribe to the metric system, a 1/2 cup is 120ml and a teaspoon is 5ml).
  3. The recipe serves one (1) hungry person (likely, therefore, a man).
Here it is:

1/2 cup milk
1/2 cup (whole wheat pastry) flour
2 eggs
4 teaspoons (olive) oil (20ml, or 1/12 cup)
1 teaspoon baking powder, or 1 teaspoon baking soda and 2 teaspoons (apple cider) vinegar
1 pinch salt

Combine ingredients in a slightly-larger-than-normal bowl using an ordinary fork. Pre-heat your (electric) stove to a "6" (just past medium heat) while your skillet is on that stove. Pour 1/2 cup of batter onto the skillet. When there are a bunch of bubbles on the mancake, place your spatula under the right half of the large mancake and flip (or, for lefties, the left half of the mancake). Wait one  minute, then take out of the pan and repeat. Makes 3 mancakes. Serves one. Enjoy.

Monday, December 16, 2013

Moving On

So I could put another post on here about the genetic algorithm, but everything I wanted to say on the subject has been said about that particular algorithm.

Rest assured, I have many more ideas about optimization algorithms. But let me tell you -- it's getting frustrating. A lot of my ideas about new algorithms for optimization include this RankedSet idea... and it doesn't exist in standard libraries.

Michał Marczyk made one for Clojure called avl.clj (great job, Michał!), and AVL tree implementation of what I call the RankedSet, but the genetic algorithm as below described (and other algorithms bouncing around in my head) need faster insertions/deletions and virtually no lookup. That is precisely what red-black trees are better at over AVL trees.  I need a red-black tree based implementation.

So I decided to learn how to make one.

I am currently going through Chris Oksasaki's "Purely Functional Data Structures". (Even just reading the first chapter, you can tell Rich Hickey idolizes the guy, and for good reason.) For those who don't know, this is a seminal work on how to design your own rock-star data structures. A quote from the first chapter:

Rather than attempting to catalog efficient data structures for every purpose (a hopeless task!), we instead concentrate on a handful of general techniques for designing efficient functional data structures...Once you understand the techniques involved, you can easily adapt existing data structures to your particular needs, or even design new data structures from scratch. (p. 4)
I am even learning OCaml so that I can go through it better (most of the examples in his book are in standard ML, which is to OCaml as C is to C++, as far as I can tell).

Hopefully at some point into it I'll be able to make a RankedSet, share the implementation, and keep writing about awesome algorithms.