music utility now on github
I’ve completed a music-transcription utility; it’s up on github.
It’s a command-line utility. It works thusly:
$> ./music -r c c eb f#
Finding matches scales for notes c eb f#:
Eb min: 1.00
Db min: 1.00
Db maj: 1.00
Degrees of notes in c:
c : r
eb : b3
f# : #11
In this example I ask the program to analyse C, Eb, and F# in the context of the key of C. It returns that those notes, together, are in exactly 3 scales. It also tells me what degrees of the key of C those notes represent.
The code itself, in my opinion, is very clean. TDD followed; 100% code coverage; lots of small, well-defined classes; short methods; some amount of documentation; open-source.
Check it out, it’s all online.
Official move from Vim to Netbeans
The better you know me the more shocked you will be to learn this: I am officially switching my primary programming environment from Vim to Netbeans.
And it’s all Martin Fowler’s fault.
Background
First, a bit of background. I currently use Vim for everything. Everything. I’m writing this post in it right now. It is, and will probably always continue to be, the best text editing environment ever devised. I will certainly continue to use it over ugly hacks like, for example, Word.
Vim is such a good text editor, such a good programmer’s text editor, that it has been able to meet all my programming and customization needs for the last year or so. I use it at home, and at work as my IDE.
Then, as I said, Martin Fowler stepped in.
The Problem
Problems began when I picked up his book, Refactoring. Being the excellent book it is, it naturally led me to want to refactor everything, constantly, and automatically. This led me on a hunt for good refactoring tools, and this led me to modern IDEs — with Netbeans being a fine example.
See, Vim is somewhat aware of syntax, but only on a regex level. For true refactoring assistance, the editor really needs to understand languages on an AST level. To my dismay, Vim does not have comprehensive plugins to solve this problem for every language I regularity use. Further, writing all those plugins would be, I think, more effort than it was worth.
And I so I follow the productivity fairy to Netbeans.
Making the Switch
At first I was tempted to use jVi, the excellent vim plugin for Netbeans. I ran into two — but really only two — problems. First, jVi selection is different from Netbeans selection. It’s irritation, distracting, and time-consuming to be constantly switching between the two types. Second, on a admittedly more emotional level, I wanted to sound Netbeans’ depths. Find out what it could do under its own steam. Be "pure" in my experiment.
So I thought about what it is in Vim that I really like, and boiled it down to two things.
- Hands remain on homerow. Now mouse or arrow keys needed.
- Quickly accomplish common programming tasks.
As it happed, Netbeans can handle both aspects.
Homerow
The solution was remapping everything, which was surprisingly easy. My currently (and will certainly change) layout on my mac:
CTRL +
| shortcut | action |
|---|---|
| h, j, k, l | move cursor left, down, up, right (like in vim) |
| u, o | move cursor to the previous, next word |
| y, p | move cursor to beginning, end of line |
| ,, . | contract, expand selection |
| t, b | top, bottom of document |
| e, d | scroll screen up, down one line |
Adding SHIFT to any combination (except the last) adds messing with the current selection.
Together, this relatively small set of shortcuts nicely solves my homerow problem (and, if I do say so myself, better than emacs solves it). This probably alone gives me 50% of why I like vim so much.
Common Programming Tasks
Vim is largely a generic tool that lets me solve any text editing problem quickly. Netbeans is specialized to solve most common programming tasks quickly. Apparently, when it comes to programming, I perform the same tasks as everybody else.
A quick example:
Programmers often need to rename a variable. Vim makes this easy for me: I select the scope I care about, and fire off a quick regex search-replace to change that word — thereby using generalized tools to solve the problem.
In Netbeans, I CTRL-R on the variable I want to rename, and type in the new name — using a highly specific tool to give me slightly faster and slightly more accurate results.
What I’m giving up
Leaving Vim for Netbeans, there are some things I’ll be giving up. In no particular order:
Speed. Vim is fast. It starts up fast, it runs fast. It waits for you, I’ve never waited for it. Netbeans takes long enough to start up that I get impatient. Also, sometimes it will randomly stop accepting input and start crunching on something behind the scenes that I may or may not have asked for.
Stability. Vim has only ever crashed on me, by which I mean I had to restart it, once — and that was when I was playing around with a broken plugin on several 200MB+ files. Netbeans has out-and-out crashed on me before, and required two restarts just in setting it up this week.
Consistency. Vim’s keybindings haven’t changed in 30 years (or whatever). What I learn on it will apply to every version of vim used by basically anyone anywhere, and for years to come. Netbeans’ interface is not anywhere near so stable. There will be new things to learn — and things to unlearn come every release.
Universality. Vim is installed by default on all OSs that really matter. Netbeans is an enormous, additional install.
One ring to rule them all. With Vim there was only one tool in my toolset: Vim. I learned one tool, and could apply that knowledge to anything I did on a computer. Now, with Netbeans, there are two camps to learn. Now I am master of none.
Customizability. Have a problem with vim? Change it. Between myriad options, remappings, new commands, and an easy-to-use plugin system, there’s really nothing about the editor you can’t change in an hour or two. Heck, I even wrote a typing tutor program in the editor. Netbeans proponents would no doubt argue that the same is true of Netbeans, but I would say that there is an important difference in ease.
No Dialog Boxes. I hate dialog boxes. Vim doesn’t have them. Netbeans has lots.
Aesthetic. When you’ve got a GNU Screen + Vim setup running fullscreen, it looks awesome: ASCII and ASCII alone, as far as the eye can see. With Netbeans, you’re just using an IDE.
Conclusion
Vim is a text-editing machine. Once you’ve mastered it, you can quickly solve text-related tasks no one’s ever thought of.
Netbeans is "just" a programming environment, and not really suited to say, writing blog posts. However, it’s very good at being a programming environment. It’s Extract Method functionality alone is worth making the switch for. When combined with its good custom keybinding functionality, its larger development community (meaning, as just one example, built-in live templates for everything under the sun), and the project’s overall attention-to-detail, I feel confident that I’ve made the right choice.
There will still be plenty of days, though, when I fire up vim to do something Netbeans will never be able to touch.
vim and ruby koans
In this screencast I demonstrate the (okay, "a") vim way to work through the ruby_koans.
The crux of the method is vim’s awesome make command, which runs your makeprg (rake, in this case), hops you to the first error, and displays more information in the QuickFix window.
I can’t imagine a more streamlined system for working through the koans. I make a change, and "seeing if I’m right and moving on to the next assert" is only a single shortcut away (@: repeats the last command; I have it mapped to tab).
ruby_koans is an innovative and fun way to learn the ruby language. I highly recommend trying it out — with vim, of course.
vim: paste yanked text
Vim automatically yanks all text into the "0 register, and deletes all text into the "1 – "9" registers.
This is handy if you want to yank out some useful text before deleting a section. Later, just "0p to drop the good bit where you want it.
But "0p is pretty awkward to type.
I created these alternate mappings today, which are both easier to type and have better mnemonics.
" put last yanked text nmap yp "0p nmap yP "0P
TortoiseTyping vim plugin
I’ve successfully uploaded my first vim plugin! It’s a minimal typing tutor aimed at touch-typists who would like to spend a few minutes a week sharpening their skills. I’ve noticed, for myself, that for less than 10 minutes a week I can increase my average speed from around 50 to 85 WPM, which seems worthwhile.
This script is called TortoiseTyping because with typing its slow, steady, and accurate wins the race.
I enjoy vim so much, it feels good to be able to give something back, however small.
Trailing whitespace is never necessary. To remove it automatically every time you save a file, add this to your .vimrc:
" on save any: trim trailing whitespace autocmd! BufWrite * mark ' | silent! %s/\s\+$// | norm ''
The regular expression should be clear to anyone familiar with regular expressions. The junk immediately before and after ensures that the cursor ends up where it started. The autocmd sets the command to fire on the BufWrite event for all files.
S-expressions are lisp’s great syntactical strength, and death-by-parentheses its greatest weakness. Why not take a page from python’s book and make whitespace significant?
The rules are simple. ( or ) add a newline. ( adds an indentation level, while ) removes one.
example 1
" old way (a b c d) " new way a b c d
example 2
" old way
(a b (c d e (f g)))
" new way
a b
c d e
f g
example 3
" old way
(a b (c d (e f) g))
" new way
a b
c d
e f
g
example 4
" some conventional pseudo language if a == 0 then 1 + 2 else 3 + 4 " S-expression (if (== a 0) (+ 1 2) (+ 3 4)) " new way if == a 0 + 1 2 + 3 4
Even modern languages have extra syntactic junk floating around. Why not get rid of it?
Update: It was brought to my attention that this scheme breaks under some circumstances. Specifically, whenever two or more open parentheses appear in a row — (( — double indenting and ambiguity can occur.
There are two fixes, neither great.
- Make the using parentheses optional, so that they can be pulled out in the more complex situations. Haskell’s "on-sides" strategy works like this (though for different reasons), where curly braces and semicolons can be used — though in practice no ones does.
- In situations where (( would appear, introduce a place-holding element. Maybe a ., for example, between the two. My understanding of lisp is weak, but I think this might bear some resemblance to its let.
Both cases require disallowing the "((" situation.
PostgreSQL port woes on upgrade
This consumed enough of my time that I thought I’d post something about it.
When I installed Ubuntu 10.04 my postgres bumped from 8.3 to 8.4. In order to avoid stomping on 8.3′s old ports, 8.4 silently moved from port 5432 to 5433 — which is great except for the "silent" part. The only indication I had of the change was everything exploding in my face.
To set 8.4′s port number back to 5432:
-
create this line in your .bashrc
export PGPORT=5432
-
and change this line in /etc/postgresql/8.4/main/postgresql.conf
port = 5432 # (change requires restart)
-
I no longer trust the postgres restart, so restart with
$ sudo service postgres-8.4 stop $ sudo service postgres-8.4 start
And, hopefully, your frustrations will end sooner than mine did.
One-line recursive python function
The original challenge posed to me was to create a one-line recursive function in python. To reach this solution I started with this function
def shortAny(n): """Return if any of a list of bools are True.""" if(n): if(n[0]): return True else: return shortAny(n[1:]) else: return False
then "simplified" it to this
def shortAny(n): return bool(n) and (n[0] or shortAny(n[1:])) # basic testing T = True f = False assert shortAny([]) == f assert shortAny([f]) == f assert shortAny([T]) == T assert shortAny([T, T]) == T assert shortAny([T, f]) == T assert shortAny([f, T]) == T assert shortAny([f, f]) == f assert shortAny([f, f, f]) == f assert shortAny([T, f, f]) == T assert shortAny([f, T, f]) == T assert shortAny([f, f, T]) == T assert shortAny([f, T, T]) == T assert shortAny([T, T, f]) == T assert shortAny([T, f, T]) == T assert shortAny([T, T, T]) == T
This function would not have been possible without python’s short cutting feature for "and" and "or".
Note that this was an intellectual exercise, and that code like this should never really be written by anyone.
Simple python Rubik’s Cube timer
In my quest for the sub-30 Rubik’s Cube solve, I realized that I needed data. To that end, I wrote the following python script. It times how long I take on each step of the solve, and provides depressing statistics afterwards.
Efforts were made to make the code as clear as possible. I received assistance from this guy.
#!/usr/bin/env python import timeit """ Stephen Mann April 2010 Terminal program for timing Rubik's Cube solves using a modified Roux method. Intended to be used as a bash utility. Run chmod +x on the file and drop it in your PATH somewhere. Now the script can be run from anywhere on the system with just $ cuberun Credits ------- Editing and suggestions from Adam Colton, http://adamcolton.net """ stages = [ "inspect", "left 2x2 block", "left 2x1 block", "right 2x2 block", "right 2x1 block", "permutate corners", "orient corners", "orient edges", "permutate R/L edges", "permutate M edges" ] def wait(message): """ Return how many seconds it takes the user to hit <enter>. Display message in meantime. """ cmd = "raw_input(' %s')" % message return timeit.Timer(cmd).timeit(1) print print "=========================================" print "press <enter> after completing each stage" print "=========================================" durs = map(wait, stages) # durations nDurs = zip(durs, stages) # named durations total = sum(durs) slowest = max(nDurs) fastest = min(nDurs) print print "results" print "=======" for nDur in nDurs: print "%4.1f: %s" % nDur print "total: %.1f seconds" % total print print 'slowest stage at %4.1f seconds was "%s"' % slowest print 'fastest stage at %4.1f seconds was "%s"' % fastest