For a site titled Hands-Free Coding, I haven’t written much about How To Actually Write The Code. It turns out this is easier than you might expect. Before reading this post, please familiarize yourself with my getting started guide and how to move around a file quickly.
There are two basic approaches to dictating code: using custom grammars such as Dragonfly, or using VoiceCode, (not to be confused with VoiceCode.io for Mac, which I just discovered and haven’t used yet). VoiceCode is much more powerful out-of-the-box, but is also harder to extend and more restrictive in terms of programming language and environment. You might say that VoiceCode is Eclipse, and Dragonfly is Emacs. You could also consider Vocola for your custom grammars; it is more concise but not quite as flexible because you can’t execute arbitrary Python. Since I prefer Dragonfly, I’ll cover that approach.
The multi-edit module is a good place to start. I follow a few fundamental techniques for dictating code:
1) I use prefix commands to dictate keywords in any style. For example, I can say “score test word” to print “test_word”, or “camel test word” to print “testWord”.
2) I use short made-up words to dictate common symbols. For example, I can print “()” with “leap reap”. I made these words up over time, but if I were starting new I would probably use a standard language such as ShortTalk.
3) I use templates in my text editor to quickly generate boilerplate syntax, such as the skeleton of a for loop. In particular, since I use Emacs, I use the yasnippet package.
4) I rely on automatic formatting in my text editor to keep the code neat.
5) Most importantly, I structure my grammar so that I can dictate continuously, instead of having to stop and start after every keyword or symbol. This is the hardest part of my setup, because there are many trade-offs between supporting continuous commands and keeping performance high, which I will cover in another post.
If you follow these basic techniques, the biggest problem that remains is misrecognized words. You can avoid this in your own code by preferring easily recognized identifiers, but it’s much harder when working with someone else’s code or library. I find that the best way to combat this issue is to use Dragon’s built-in Vocabulary Editor. The moment you find yourself spelling out a word, stop right away and add this word to the Vocabulary Editor. If the problem is a variable or function with multiple misrecognized words, add the whole phrase to your vocabulary. For example, if you regularly use a class named SimDataManager, add “sim data manager” to your vocabulary and then you can type it in any style using the prefix commands.
I have also experimented with a fancier solution to this problem, where I dynamically add words from nearby code into my Dragonfly grammar. Unfortunately, I haven’t found a way to seamlessly integrate this into my vocabulary without incurring a significant performance penalty, so I only call upon this dynamic grammar explicitly. So it’s not quite as powerful as you might expect, and most of the time I rely on the built-in vocabulary. It’s better than nothing, though, so I will cover this in a later post.
That covers the basics, but much of the challenge of writing code is editing code you (or someone else) have already written. I’ll save that for later posts!