Delphi macro recipes: Fields to properties

Today I’m going to share a Delphi IDE macro that I record and use several times a week: transforming fields to properties.

The basic idea is: You’ve just added seven fields to your class, and you want to make properties for all of them.

Why not use Class Completion?

If you declare the property first, Class Completion will add the field (and, optionally, the setter as well) for you, right? So why use a macro instead?

First and foremost, Class Completion for properties is horribly, horribly broken in Delphi 2006 and in BDS 2007. We use strict private in our code, which means we run up into the Delphi bug that makes Class Completion unusable. It also tends to complete to the wrong class. And I’m sure there are other bugs that I just don’t remember, because I never use it. I’ve learned better than to complete properties.

A macro also gives you more control. It’s easy to tune it to make read-only properties, or read and write the field with no SetXXX method. You can do that with Class Completion too (if you can get it to work), but you have to do extra typing for every property. With a macro, you just cut a swath through the code.

What it looks like

You start by copying your field declarations to the end of the public section (or wherever you want your properties to go). Then the macro transforms those field declarations into property declarations.

For today’s example, we’ll do read-only properties. So this:

FFoo: Integer;
FBar: string;
FBaz: TPoint;

will become:

property Foo: Integer read FFoo;
property Bar: string read FBar;
property Baz: TPoint read FBaz;

Note some limitations. With imagination, you can get around some of these, but the simple recipe I’ll give here won’t deal with anything complex.

  • You need one complete field declaration per line. This won’t deal with FFoo, FBar: Integer;.
  • It won’t turn array declarations into indexed properties, or anything uber-fancy like that. You need to write a method to make that work, and this is simple text transformation, not code generation.
  • This assumes no comments on the same line with the variable declarations.
  • The steps, as written, assume that you follow the Delphi convention of prefixing field names with F. If you have some other convention, alter the steps accordingly.

So, nothing too fancy. But macros make short work of simple, repetitive stuff. Let’s get started.

The setup

Highlight the lines with your field declarations. Copy them. Paste where you want your properties to end up (usually the end of one of the visibility sections, e.g. at the end of the public section).

Now put the cursor back on the first line you pasted. The macro will transform each line into a property declaration, then move to the next line.

The macro

  1. Press Ctrl+Shift+R to start recording.
  2. Press Home to go to the beginning of the line.
  3. Press Ctrl+Right arrow to go to the beginning of the field name.
  4. Press Ctrl+K, T to select the field name.
  5. Press Ctrl+C to copy the field name to the clipboard.
  6. Press Ctrl+Left arrow to go back to the beginning of the field name.
  7. Press Del to delete the F off the beginning of the field name.
  8. Type property and hit the Space bar.
  9. Press End to move to the end of the line, just after the semicolon.
  10. Press Left arrow to move just before the semicolon.
  11. Type Space bar, read, Space bar.
  12. Press Ctrl+V to paste the field name.
  13. Press Down arrow to move to the next line.
  14. Press Ctrl+Shift+R to stop recording.

Of course, with macros, you always do the first one by hand. The first line should now be a property declaration just like you wanted.

Now press Ctrl+Shift+P to play back the macro. The next line will be transformed from a field declaration into a read-only property declaration. Keep hitting Ctrl+Shift+P, and you’re in business.

One last cute trick: If there’s a line you want to skip — maybe you copied some comment lines along with the variable declarations — just hit Down arrow before your next Ctrl+Shift+P.

Leave a Reply

Your email address will not be published. Required fields are marked *