Searching through Delphi code
I’m writing a tool that does a sort of “find in files” on Delphi source files. Yes, I know, there are zillions of such tools out there, but this one has a few extra features:
- Ability to restrict your search only to comments, to compiler directives, to string literals, or to code. As far as I know, there are no other tools out there that have this feature.
- Drag and drop from the search results into the Delphi editor, to open the files for editing
- Full support for PCRE (Perl-compatible regular expressions), including positive and negative lookahead and lookbehind
- Compound searches, e.g., “Find all files that do contain this string, but do not contain this string”
- Lets you search within multiline comments and multiline strings (see examples below)
- Option to search recursively but exclude certain directories
- If you have the same filename multiple places in your source tree, will allow you to tell it that they’re really the same file (think VSS’s shared files), and only read the one with the most recent timestamp and/or shortest pathname
- Will eventually have some degree of integration with VSS (check in, check out, undo checkout; icons change to show which files are/aren’t checked out), maybe plugin-style to allow for other SCMs
- Will eventually let you add external tools (e.g., apps to reformat your source code), and run “check out, run the tool, check back in with an appropriate comment” as a single operation
- Caches file contents in memory to speed future searches (but checks timestamps and reloads as needed)
An example: Suppose I have source code that looks like this.
raise EMyException.Create('This action is only available to system ' +
'administrators and power users.');
I’ll be able to search on the text “system administrators” and get a match. Can’t do that with Find in Files, or GExperts grep, or ordinary grep. (Very useful for searching through DFMs, where you have no control over line breaks.)
Another example:
// This function will only work on Windows 9x. Windows NT // 4.0 is not supported.
Searching on “NT 4″ will get a match (if you enable the “loose whitespace” option, since it actually sees a newline between “NT” and ” 4.0″).
Another example: Suppose you have hundreds or thousands of units in your codebase, and there’s a class (TMyClass) in a commonly-used unit (call it unit MyGlobals). You want to move it into a different commonly-used unit (MyOtherGlobals). This will break any units that use TMyClass but don’t already have MyOtherGlobals in their uses clause. No problem: search for all files that do contain TMyClass, but do not contain MyOtherGlobals. Click “Check Out” to check the files out of VSS; drag them into the IDE; add MyOtherGlobals to their uses clauses; save; and click “Check In”. (Much simpler than the alternative, of just moving the class, compiling to see what breaks, and checking out and fixing one unit at a time.)
I’m writing the code in .NET, mainly because of its fabulous regex library. (Ironically enough, I’m writing this tool, whose biggest selling point is a Delphi parser, in C#. Eh, big deal; the Delphi compiler is written in C.)
I already have proof-of-concepts working for all of these features. All that’s left is to tie them all together, which is what I’m working on now. I’m writing this utility because I need it at work (where I’ve already written, and am using, some of the proof-of-concepts). I’m writing the full tool on my own time so that I own the code.
Does anyone else need a tool like this? If so, I may polish it up and release it at some point. (Also let me know if there are any features you’d like added, or if you have a killer name for the app.)
October 9th, 2004 at 3:19 pm
This is a great idea. I would certainly like to be able to use some of those features.
October 10th, 2004 at 1:49 am
Great set of features!! Would be interested in using it!
J.
October 10th, 2004 at 6:32 am
I wrote one such tool sometime ago which did something similar to what you did.
Difference was, it used syntax info and let the user search and replace things that were, say,
–in remarks
–variables
–commands
etc.
I used it a lot at the time but I did not have time enough to polish it.
I hope yours is more polished and usable.
cheers,
adem
October 10th, 2004 at 7:27 am
Hey, that’s cool. How did you parse the code to figure out what was a variable and what wasn’t? Did you write a parser, or is there something available in the IDE’s Open Tools API to do that for you? (I haven’t looked. Then again, I want to be able to scan all files, not just ones that are open in the IDE.)
I’ve just written a fairly trivial parser that only knows about comments (the three different styles), compiler directives, and string literals. It doesn’t know anything about code syntax, other than strings. (And it actually doesn’t do a 100% complete implementation of strings — it doesn’t recognize the (very obscure) ^M syntax; just #13, #$0D, and ‘…’.)
Search-and-replace… yes, I’ll have to consider adding that at some point. That would be really handy combined with the check-out / check-in features.
October 24th, 2004 at 5:44 pm
Grokking Delphi Source
May 9th, 2006 at 11:48 am
Why is this a Delphi specific search, as opposed to a proximity search? If you used something that could find system within two words of administrators, like Lexis searches…
May 9th, 2006 at 8:05 pm
Well, to take one example off the top of my head, that wouldn’t work if the word "administrators" was split across two lines, which will happen e.g. in a .DFM. And it wouldn’t be able to search only within string literals, which is pretty useful (had occasion to want it just yesterday).