Friday 9 March 2018

Converting line endings

eolconv

An up-to-date version of this and other files can be found in my CommandLineTools project on GitHub.

On Stack Overflow and in the Embarcadero forums I regularly see people ask how to convert a file with Unix line endings to Windows line endings, or vice versa. The usual advice is to load the file into Notepad++ and to save it with the desired line ending format.

But Delphi can do this too, either using AdjustLineBreaks or using a TStringList. That is why I wrote this simple command line tool. The actual conversion is extremely simple:

  • Load the file into a TStringList.
  • Set the LineBreak property of the string list, depending on the desired output format (Windows or Unix).
  • Convert the file depending on the encoding: 8 bit, 16 bit little endian or 16 bit big endian.
  • Rename the old file to a name with a unique extension.
  • Rename the new file to the name of the old file.
  • Save the contents of the TStringList back to the file.

Most of the code is there to handle command line parameters.

Update

The TStringList way is simple to write, but is not only pretty slow and — if the file is large — can also require a lot of memory. The new way uses a buffer of up to 2MB to load blocks of the file and convert on the fly. This turned out to be a lot faster for large files.

Synopsis

EOLCONV [options ...] Name[s]

Multiple file names can be specified. EOLConv does not understand wildcards (yet), but for instance on the Windows command line, you can do something like:

for %f in (*.txt) do eolconv %f -U

That will convert all files with the extension .txt in the current directory to the Unix format.

Each original file will be preserved by renaming it, adding a unique .~1, .~2, etc. extension to the original file name. EOLConv will try to add extensions up to .~200, and if the file name with that extension exists too, EOLConv will give up and the original file will remain as it was.

Options

On Windows, all options start with either a / or a . On other platforms, they start with a .

Options are case insensitive.

If no options are specified, the files will be converted to the default line ending format for the platform. To set the line ending format to a specific style, use:

  • -W     to set the line endings to Windows format (CR+LF)*
  • -U     to set the line endings to Unix format (LF)*

* CR stands for Carriage Return (#13 in Delphi), LF stands for Line Feed (#10 in Delphi).

To get help, either start eolconv without any parameters, or specify -H or -?.

Finally

EOLConv is freeware. All rights are reserved. Its code is provided as is, expressly without a warranty of any kind. You use it at your own risk.

I hope this code is useful to you. If you use some of it, please credit me. If you modify or improve EOLConv, please send me the modifications.

I may improve or enhance EOLConv myself, and I will try to post changes here. But this is not a promise. Please don’t request features.

Rudy Velthuis

Sunday 4 March 2018

AutoSuffix

I guess everyone who had to maintain one package for several different versions of Delphi had wished this was possible to do with a single package source. The alternative is to have different set of .dpk and .dproj files, each with a different name or suffix, for each version you want to cover.

Some, including me, devised a "clever" include file that set a different {$LIBSUFFIX } for each version. So did I, but every simple change to the package would remove the {$INCLUDE 'LibSuffixes.inc'} I put in the .dpk file and replace it with something like {$LIBSUFFIX '230'} if 230 was the suffix found in the .dproj file.

If you are very careful not to modifiy the package, and the include file is not removed, this compiles as intended, i.e. a file MyPackage.dpk compiles as MyPackage250.bpl, but if you try to install that way the IDE is not aware of the changed suffix, so it complains that it could not install MyPackage.bpl.

Note: The {$LIBSUFFIX} directive works for DLLs too, but there is no entry in the Project → Options... → Description page (there is not even a Description page). The previously mentioned "clever" includes work very well for DLLs (and so for DLL-based experts too). The IDE does not meddle with the contents of a .dpr file for a library.

This problem has been discussed many times on forums and in communities. On Stack Overflow, someone called LaKraven set out to create an IDE expert (AutoSuffix) to solve this problem. But I can't find this expert anymore. All the links I found to it are dead.

The New AutoSuffix Expert

So I wrote a simple expert myself and called it AutoSuffix too.

If the current project is a package, it adds a menu item to the context menu of the Project Manager with the title Add Version Suffix, under the Rename menu item. If you click it, it sets the suffix for the package to a number that matches the suffixes used for the version of the compiler, i.e. for Delphi 10.2 Tokyo, it sets it to 250, for 10.1 Berlin to 240, for XE3 to 170, etc.

I could have made this an expert that sets the suffix automatically, but I wanted to leave the user (myself too) a choice, so it must be done manually, using the context menu.

Tested

I only tested this in Delphi XE3, Delphi 10 Seattle, 10.1 Berlin and 10.2 Tokyo, but it probably works in versions inbetween as well. I will update this as soon as I have tested it more.

Installation

Get all the files from GitHub (either clone the repository or download the files as zip) and put them in a single directory. Open the package AutoSuffix.dproj in your IDE, select the project in the Project Manager and click the Install menu item from the context menu. If all is well, this installs the expert and adds one menu item to the context menu of the Project Manager: Add Version Suffix, under the Rename item. This menu item only appears if the project is a package.

Rudy Velthuis