I'm currently working on a OS X application that uses a few different NSTableViews to display user data. I was testing them out a bit to make sure multiple deletions worked correctly from my database and I found myself pressing 'j' and 'k' to try and move down and up. I decided it would be pretty cool to implement those two vim shortcuts into my table view just in case anyone else thinks like me.
This functionality already exists in The Hit List an awesome GTD app that has a lot of baggage with me, and I'm sure it exists in other applications as well.
keyDown: method I tried a few things.
Attempt 1: First I tried to re implement the functionality myself. In retrospect this doesn't make any sense but at first it was pretty simple. It looked something like this.
The issue with this is the way
NSTableView typically expands it's selection. I think of it as a pivot point where you start. Then you go up and down relative to that point. So if you start at index 2 and go down till index 4, you should have 2 rows selected. Then when you go back up you should deselect the rows and indexes 3 and 4 and select the rows and index 1 and 0. At this point I realized it was more difficult than I realized at first and went in search on another solution.
Attempt 2: The next solution I discovered used the Quartz Event Services APIs.
This solution worked perfectly, at first. This mainly emulates a key press with a different key code. So as you can see I was catching j and k and spitting them out as down and up. I spent a few minutes testing this before I remembered that I had sandboxing disabled so I could more easily delete my application support folder while messing with my Core Data stack. There went that solution.
Attempt 3: Before I used the weird
CGEventRef solution I tried to create my own
NSEvent passing it all the same attributes from the original event (all this code is being used in the
keyDown: function of my subclass) but I couldn't figure out how to get the correct character string for the up and down arrows. I typically use Key Codes to get all the possible information you could want about each key you press. But for some keys, including the arrow keys, it returns garbage for the character code. Then I discovered this answer on StackOverflow where there is a brief mention of
NSUpArrowFunctionKey. With that I came up with this.
Not the prettiest solution I but one that seems to work perfectly, even sandboxed, to provide the expected behavior in an