GExperts 1.3.29 released

GExperts 1.3.29 is available. It brings 12 new features, 34 enhancements and 72 bug fixes, including two new experts, a way to move your whole GExperts configuration from one Delphi installation to another, and a set of fixes for a silent data corruption in the Code Librarian library file.

For the impatient: head over to the GExperts download page to get it.

Code Formatter

The most important achievement for me personally is that all known bugs in the Code Formatter have been fixed. There are now unit tests for every one that has ever been found so hopefully any future regressions will be caught before the code ever gets released. Those tests are files whose expected output is what the formatter should produce, so they fail until the bug they document is fixed. There are none failing left, and all 1518 formatter tests pass.

There are also some improvements:

Two new options on the Line Breaks tab. “After inline var” splits an inline variable declaration onto its own line:

// with the option turned off
var LTest := 1;

// with the option turned on
var
  LTest := 1;

A for loop header keeps its declaration where it is, so for var i: Integer := 5 to 10 do is not broken up, and a classic var section is not affected either.

“Except single lines” does the opposite for the existing “After var, type etc.” option: a var, const or type section that was written on a single line stays on that line, so var Rslt: Integer; is left as it is. Several variables sharing a type still count as one declaration.

Both options are off by default. Thanks to Luka Havrlišan and Ian Branch, who requested them.

And the “Unindent Labels” option on the Indent tab is finally remembered, it was never written to the configuration and silently reverted to off the next time the IDE started.

Introduce Actions

The new Introduce Actions expert converts the menu items of the form you are designing into actions, so a form that only has a TMainMenu can be moved to a TMainMenu plus a TActionList without doing it by hand. It lists the items of the form’s main menu and, optionally, of its popup menus, pre-filtered to those that can actually be converted. You tick the ones you want and pick the action list to add them to, either an existing one or a new TActionList that is created for you.

For each selected menu item a TAction is created that takes over the item’s caption, shortcut, hint, image index, help context, enabled, visible and checked state, and its OnClick handler. The action is then assigned to the menu item, which is what makes the IDE drop the now redundant caption, shortcut and OnClick from the DFM.

It converts buttons as well, for the many old programs that hang important code off a button’s OnClick handler. Which classes it offers is configurable and covers TButton, TBitBtn, TSpeedButton and TToolButton plus their descendants by default, so third party buttons are covered too. Buttons and menu items without an OnClick handler are listed but not preselected.

Menu items and buttons are named the same way: the action name is derived from the control name either by stripping a prefix and prepending one, or by stripping a suffix and appending one. Which of the two schemes is used depends on the tab you leave the dialog on, and that choice is remembered. A prefix or suffix is only stripped where it really is one, that is where it starts a new word in the name, so miscItem is left alone.

Control name Action name What happened
mniFileOpen actFileOpen prefix mni stripped, act prepended
mi_FileOpen actFileOpen prefix mi_ stripped, act prepended
btnSave actSave prefix btn stripped, act prepended
FileOpenItem FileOpenAction suffix Item stripped, Action appended
SaveButton SaveAction suffix Button stripped, Action appended

By default the prefixes that get stripped are mni, mnu, mit, itm, mi_, mi, mn, btn, bbtn, sbtn, tbtn, bt_ and b_, and the suffixes are Item, MenuItem, Button and Btn. The action prefix is act and the action suffix is Action. All of them are configurable.

Thanks to David Cornelius, who requested this, and to Keld Hansen for the suffix naming scheme.

Take your configuration with you

The GExperts configuration dialog has new Export and Import buttons on the Experts tab. They save the complete configuration to a ZIP archive and load it back, instead of exporting and hand editing registry entries.

Import shows a dialog where you pick which experts and which parts of the global configuration to bring in, so a configuration exported from one Delphi version can be imported into another. The four paths that depend on the IDE version (VCL source, configuration, caching and help file) are listed as individual entries but are unchecked by default, so importing across versions does not overwrite the paths of the target IDE.

The archive also bundles the configuration files that individual experts keep outside the registry: Favorite Files, Code Librarian, Code Proofreader, Macro Templates, Clipboard History, Grep history, Project Option Sets, Replace Components, Uses Clause Manager favorites, Convert Strings and the Code Formatter capitalization file. On import these appear on their own tab where you choose which to restore, and you are asked before an existing file is overwritten.

Related to this: when a new GExperts version whose settings live under a new registry key starts for the first time and finds settings from an earlier version for the same IDE, it now copies them over automatically. Upgrading no longer means reconfiguring.

Code Librarian: import ready made snippet collections, and no more corrupted libraries

The Code Librarian File menu has a new “Import Collection …” entry that imports the two snippet collections published by DelphiDabbler: the Code Snippets Collection (about 700 documented Pascal routines) and the SWAG archive (about 4200 packets from the Pascal newsgroups of the 1990s). You point the dialog at the release ZIP as downloaded from GitHub, no unpacking needed, and it tells you which of the two it is and lists its categories with a checkbox each, so you can import three categories rather than all sixty.

More important for anyone already using the Code Librarian: three separate defects in the storage layer that keeps the library in a single file could corrupt it silently. Deleting a folder with more than about ten sub-folders, deleting an entry that happened to be the second to last in its folder, or deleting entries from a library larger than about a quarter of a megabyte could each leave the file inconsistent. The deletion appeared to succeed, and the damage only surfaced the next time the Code Librarian was opened, with a “Stream read error” that made the whole library inaccessible.

All three are fixed, and all three were version independent, so they could bite on any Delphi version. On top of that, opening the Code Librarian in a 64 bit IDE always failed with an access violation, because the storage code predates 64 bit Delphi and squeezed pointers through a 32 bit integer in two places. That is fixed too.

Smaller things you may notice

  • The two separate lists of favorite files have been unified. The Open File dialog’s Favorites tab is now a full favorites manager, with a folder tree you can add to, rename, delete and drag entries between, and files can be dragged in from Windows Explorer or from the dialog’s other tabs.
  • The editor popup menu can group its entries into submenus, to any depth, each with its own set of A to Z hotkeys.
  • Rename Identifier can optionally rename whole word matches in comments too, including the parameter name in the @param tag of an XML doc comment above the routine.
  • Components to Code now also generates the assignments that other components on the form make to the selected ones, so a data source pointing at the selected table ends up in the generated code.
  • IDE Menu Shortcuts has a “Copy List to Clipboard” button that copies all your custom shortcuts as plain text.
  • Select Components can select the form itself, matching what the IDE’s structure pane does.
  • For Delphi versions before 10.3, which have no native Tabs menu, there is a new (disabled by default) Window/Tabs Menu expert that adds one.

Bug fixes

72 of them. Besides the Code Librarian and formatter fixes above, a few worth calling out:

  • Find Next and Find Previous Identifier, Rename Identifier and Declare Variable used a byte offset as a character column in Delphi 2005 to 2007, so they misbehaved on lines containing non US-ASCII characters.
  • Closing the IDE could raise “List index out of bounds” from the Uses Clause Manager. The notifiers GExperts registers with the IDE are reference counted but were held as plain object references.
  • The Class Browser no longer descends into version control folders (.svn, .git, .hg) or the Delphi backup folders when parsing a directory tree.
  • Grep’s history lists no longer accumulate duplicates without bound. Lists that had already grown large are cleaned up on the next start.
  • In Delphi 6 and 7 the GExperts message boxes were unreadable, with the text clipped to a thin strip at the top and the dialog stretched to most of the screen width.
  • In the Keyboard Shortcuts window the selected row and the column captions looked bold because they were drawn twice at slightly different offsets.
  • The Filter Exceptions expert now stays out of the way when the program being debugged is not a Win32 or Win64 program, instead of risking an access violation in the IDE.

The bug tracker is down to three open reports, which is the lowest it has been in a long time. (I must admit that I closed some of the ancient ones which I could never reproduce. They may or may not have already been fixed as a side effect of other change.)

Discussion about this in the corresponding post in the international Delphi Praxis forum.