How do I minify Delphi code using Delphi?

191 Views Asked by At

The title might be a bit confusing, but basically, I want a function that can minify Delphi code.

Something like this:

function MinifyDelphiCode(delphi: String): String;
begin
// Returns the minified Delphi (.pas) code String
end;

Is there by any chance a built-in function or a library for this? or does anyone have a function that already does this?


Here's an example of what I would expect in terms of input and output:

Input:

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Skia,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.Skia;

type
  TForm2 = class(TForm)
    SkSvg1: TSkSvg;
    Button1: TButton;
    RadioButton1: TRadioButton;
    CheckBox1: TCheckBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

{
   gas

        dgsgdsdgs
     gdsdgs
  dgssdgdg

}

procedure TForm2.Button1Click(Sender: TObject);
  // Some comment
begin
  ShowMessage('Hello World');  // Random comment that I put here
end;

end.

Output:

unit Unit2;  interface  uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Skia, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Skia;  type TForm2 = class(TForm) SkSvg1: TSkSvg; Button1: TButton; RadioButton1: TRadioButton; CheckBox1: TCheckBox; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;  var Form2: TForm2;  implementation  {$R *.fmx}  { gas  dgsgdsdgs gdsdgs dgssdgdg  }  procedure TForm2.Button1Click(Sender: TObject); begin ShowMessage('Hello World');   end;  end. 

It doesn't need to be exactly like my output. My output is just an example.

1

There are 1 best solutions below

8
Shaun Roselt On

I decided to write my own function for this. Here's the code:

function MinifyDelphi(delphi: String): String;
  function RemoveCommentsFromLine(MyLine: String): String;
  begin
    var MultiLineComment := '';
    if (MyLine.Contains('//')) then
    begin
      if (MyLine[1] = '/') AND (MyLine[2] = '/') then
      begin
        MyLine := ''; // This whole line is a comment that can't be minified, so remove it.
      end else
      begin
        var StringCharCount := MyLine.CountChar('''');
        var StringCharFirst := MyLine.IndexOf('''');
        var StringCharSecond := MyLine.Substring(StringCharFirst+1).IndexOf('''') + StringCharFirst + 1;
        var CommentChar := MyLine.IndexOf('//');
        if (MyLine.CountChar('{') > 0) AND (MyLine.CountChar('}') > 0) then
            if (MyLine.IndexOf('}') > MyLine.IndexOf('{')) then
            begin
                MultiLineComment := MyLine.Remove(MyLine.IndexOf('}')+1);
                MyLine := MyLine.Substring(MultiLineComment.Length);
                StringCharCount := MyLine.CountChar('''');
                StringCharFirst := MyLine.IndexOf('''');
                StringCharSecond := MyLine.Substring(StringCharFirst+1).IndexOf('''') + StringCharFirst + 1;
                CommentChar := MyLine.IndexOf('//');
            end;

        if (StringCharCount > 1) AND (MyLine.Contains('//')) then
        begin
          if (StringCharFirst > -1) AND (StringCharSecond > -1) AND (StringCharFirst <> StringCharSecond) then
            if (StringCharFirst < CommentChar) AND (StringCharSecond > CommentChar) AND (StringCharCount mod 2 = 0) then
            begin
               // We found //, but it is within a string (quotes ' '), let's leave it.
              var CommentCharAnother := MyLine.LastIndexOf('//');
              if (CommentChar <> CommentCharAnother) then
                MyLine := MyLine.Remove(CommentCharAnother); // Somewhere else is a comment, remove it.
            end else
            begin
              if (StringCharFirst < CommentChar) AND (StringCharSecond > CommentChar) then
                CommentChar := MyLine.Substring(CommentChar+2).IndexOf('//') + CommentChar + 1;
              MyLine := MyLine.Remove(CommentChar); // Somewhere else is a comment, remove it.
            end;
        end else
          MyLine := MyLine.Remove(CommentChar); // There's no strings, remove this comment.
      end;
    end;
    Result := MultiLineComment + MyLine;
  end;
begin
  var sLine := '';
  for var I in delphi.Split([sLineBreak]) do
  begin
    var TrimmedLine := I.Trim([' ', #09, #10, #13]);
    TrimmedLine := RemoveCommentsFromLine(TrimmedLine);

    if ((sLine.Length + TrimmedLine.Length + 1) >= 1023) then
    begin
      Result := Result + sLine + sLineBreak;
      sLine := TrimmedLine + ' ';
    end else
      sLine := sLine + TrimmedLine + ' ';
  end;

  if (sLine.Length > 0) then Result := Result + sLine;
end;

This function minifies the Delphi code, but note that it removes single-line comments (//) and keeps multiline comments ({}). I remove single-line comments (//) because they can't be minified.


I tested it on various Delphi codes and it seems to work fine for the minify needs that I have. If there are any issues, then feel free to comment and I'll try to fix them or improve this function to minify better