Can anyone out there with superpowers in writing shell script help with the following? Id like to write a command that can locate the currently selected word as a file within the project (assuming the word is the name of a class or some such thing) and open that file. Now I know what you¹re all saying, just copy the selection and paste it into the ³Go To file...² window, I just thought this might be, you know, fractionally quicker, add up all those extra clicks and key presses and over the course of a day I might save, oh, 10 seconds or so. ;-)
I just know someone out there can do this, but the more I stare at combinations of locate, grep, perl and whatnot the more I can feel my sanity ebb away.
Go on, you know you want to.
Chris
______________________________________________________________________ This email has been scanned by the MessageLabs Email Security System. For more information please visit http://www.messagelabs.com/email ______________________________________________________________________
On 24/11/2005, at 18:52, Chris Jenkins wrote:
Id like to write a command that can locate the currently selected word as a file within the project (assuming the word is the name of a class or some such thing) and open that file. [...] the more I stare at combinations of locate, grep, perl and whatnot the more I can feel my sanity ebb away.
find is for finding files, and it's pretty great :)
It takes as first argument(s), the location(s) to search. We probably want to use $TM_PROJECT_DIRECTORY (and fallback to $TM_DIRECTORY).
Then it takes conditions the file (path) should match, here one can use grouping, and, or, and not (i.e. boolean logic). In our case, we want to find a file by name, and thus use -name with $TM_SELECTED_TEXT or $TM_CURRENT_WORD (if there's no selection), - name is actually a shell pattern, so we can add * to find files starting with the current word.
By default, find will find all matches. To limit it, we need to pipe it through head (with argument -n1).
This gives us the match, to actually open it, we use “mate” with the result.
So we end up with a command that has Input: None, Output: Show as Tool Tip (so we can show a “Not found” error), and Command:
dir=${TM_PROJECT_DIRECTORY:-$TM_DIRECTORY} file=${TM_SELECTED_TEXT:-$TM_CURRENT_WORD} res=$(find "$dir" -name ".svn" -prune -or -name "$file*" -print| head -n1) if [[ -n "$res" ]] then mate "$res" &>/dev/null & else echo "Couldn't find file: “${file}”" fi
I made find skip .svn directories. There's an implicit “-and” between the arguments, and -and binds stronger than -or, so the find expression really says:
( if the name is .svn and “prune” ) or ( name is $file* and “print” )
Here “prune” and “print” both evaluate to true, but have side- effects, “prune” has the side-effect that it skips the current directory, and “print” has the side-effect that it prints the current file. And of course, find does short-circuit the logic/lazy evaluation, so if the left side of an or evaluates to true, it won't evaluate right side.
As said, find is really great -- it might take a little to get comfortable with the way it mixes actions and boolean logic, but it's really powerful. There's also an -exec which runs a shell command which can also both have side-effects and decide whether evaluation of the miscellaneous conditions should continue.
Of course if the file to be found is located in the same folder as the current file, the command could simply be:
mate "$TM_SELECTED_TEXT" &>/dev/null &