Search My Blog

ruby (4) web (4) ruby on rails (3) security (3) GPG (2) OpenPGP (2) RFC (2) linux (2) rails (2) shell (2) sysadmin (2) Exchange (1) GIT. (1) IMAP (1) RCS (1) SSH (1) SVN (1) bundle (1) cURL (1) command line (1) crack (1) css (1) developer (1) email (1) fail (1) hack (1) http (1) mac (1) network (1) password (1) regular expression (1) script (1) subversion (1) terminal (1) textmate (1) tip (1) vim (1)

Thursday, October 6, 2011

Add a shortcut to TextMate to lookup a class or method definition in a tooltip

UPDATED Mar 11 Ott 2011 12:52:36 CEST

I'm Vim user. I love the command mode, and I had fun to dance with those keystroke commands.
However changing OS means viewing things in another perspective, and switching from Linux to Mac OS for me meant choosing an editor that has its roots in the operating system where it runs.
In the case of Mac OS it not only means it should have a suitable GUI, but it should fire up instantly and above all it should behave like a Mac App.
TextMate was the obvious choice. Because behaving like a Mac App means that if you pick a folder in the Finder and drop it in the editor icon, it should straight open it like a Project. And it means that under the guise of a bare and simple application hides a world of possibilities and customization. That world in TextMate is called Bundles.

Let's talk about Bundles with a real case. (TextMate|I) was missing a shortcut to quickly lookup the definition of a class or method name, so I decided to write a TextMate command that shows me the definition in a tooltip for the current word under the caret.
The difficulties I had were merely related to the complexity of this shell scripting. Since I was trying to keep it as simple and efficient I could, I chose to use the standard unix tools: grep find and sed (it ended up that maybe a ruby script would have done it easier :))

All you have to do to use it in your TextMate is to open the Bundle editor (⌃ ⌥ ⌘ B), make a new command under "Ruby", assign a "Key Equivalent" like ⌃ ] and paste the following script in the "Command(s):" windows
SEARCHPATH=$(test -x "$TM_PROJECT_DIRECTORY" && echo "$TM_PROJECT_DIRECTORY" || echo $(dirname "$TM_FILEPATH") )
FILESMATCH=$( (egrep -ns "$STARTPATTERN" "$TM_FILEPATH" || egrep -nsR "$STARTPATTERN" --exclude="*.svn*" "$SEARCHPATH") |cut -d: -f-2 )
echo $FILESMATCH # Show on tooltip
echo $FILESMATCH |cut -d: -f1 |xargs -0 basename |pbcopy # Copy on clipboard for later use with cmd+T
find "$TM_FILEPATH" "$SEARCHPATH" -type f -name '*.rb' -exec sed -En "/$STARTPATTERN/,/$ENDPATTERN/p" {} \; |sed -E "/$ENDPATTERN/q"
CODE UPDATED Mar 11 Ott 2011 12:52:36 CEST
Now it also copies the first matching filename to the clipboard, so you can open this file by pressing cmd+T (and then go to the exact line with cmd+L)

Make sure the output is "Show as Tool Tip" like this:

If you've done it correctly, placing the caret on or after any method or class name and pressing ⌃ ] (or whatever key assignment you've made) will search in the current file ($TM_FILEPATH) and then recursively in the project directory ($TM_PROJECT_DIRECTORY) or in the file directory (if file is not in a project), and show a tooltip with:
  1. the name of the file (if different from the one you are editing) and the line where the first definition of the method or class is found
  2. the portion of definition from the declaration to the first "end" found

Although not perfect, it will do its best to avoid commented lines and false matches.
Even if this script was done for ruby, you can use it as a base for other programming languages, just change the -name '*.rb' part of the find command in the extension of your sources, and the keywords def - class - end that matches your method, function or class definitions.

In the very unsual case you are running TextMate not on a Mac OS, or if you want to adapt the script to run in a linux shell, just skip the line to "Copy on clipboard for later use with cmd+T" and remember that to use the Extended Regular Expression in SED you have to use the -r switch instead of -E.

For any explanation, contribution or discussion on the script please leave a comment below, and if you find it useful please leave me a positive feedback! :)

No comments:

Post a Comment

If you find this useful please leave a feedback :)