V.9 -- Update to only save old versions of files that have been modified. Previous versions saved everything, which was creating hundreds of never-used files.
V.7 -- Minor edit to ensure tabs and spaces are considered the same for ' } else ' formatting.
This is a PERL formatter for .MAC and .INC files to "beautify" messy code. I wrote it to be able to better read my own code, and read other people's code (which can be a mix of spaces and tab indents, which can play havoc in different editors). This is especially useful for visual clarity with complex logic chains of /if && /for statements. Plus, I am OCD about code styling.
Basically, the program indents code according to standard rules for { } brackets and /for /next statements. The code also creates a header for subroutines if one doesn't exist. The program creates a subfolder called Processed into which it places your old .MAC /.INC scripts (so original code is not lost). MQ2f.pl never overwrites anything in the Processed folder, it just increments the file number if a duplication-- so nothing is ever lost.
The MQ2f.pl program will:
Requires PERL. PERL Install instructions are at the bottom of this post after the MQ2f.pl script.
MQ2f.pl V9-- Defaults to leading tabs. Use s switch for leading tabs. Last Updated: 6/23/2019
Installing Perl:
I find PERL to be amazingly flexible at complex string editing. It has great abilities to "reach" into the Windows system as well. It's not as easy as AHK, but is great for a lot of quick and dirty programming.
General instructions for installing PERL are here: https://www.perl.org/get.html
I use ActiveState PERL (Strawberry Perl and others also work). There is a community version (free of charge).
http://www.activestate.com/activeperl/downloads
Running MQ2f.pl :
There are lots of online tutorials for Perl script newbies. Most often you will find yourself at PerlMaven as he has excellent examples and tutorials (he also wrote the free IDE so he knows what he's doing).
V.7 -- Minor edit to ensure tabs and spaces are considered the same for ' } else ' formatting.
This is a PERL formatter for .MAC and .INC files to "beautify" messy code. I wrote it to be able to better read my own code, and read other people's code (which can be a mix of spaces and tab indents, which can play havoc in different editors). This is especially useful for visual clarity with complex logic chains of /if && /for statements. Plus, I am OCD about code styling.
Basically, the program indents code according to standard rules for { } brackets and /for /next statements. The code also creates a header for subroutines if one doesn't exist. The program creates a subfolder called Processed into which it places your old .MAC /.INC scripts (so original code is not lost). MQ2f.pl never overwrites anything in the Processed folder, it just increments the file number if a duplication-- so nothing is ever lost.
The MQ2f.pl program will:
- Read all .MAC and .INC folders in the folder in which the MQ2f.pl file is placed.
- Increments indents on { and /for statements.
- Decrements indents in } and } /else and /next statements.
- Temporarily decrements (for one line) all comments "|" and gotos ":" -- this is for visual clarity.
- Will use either tabs (default) or spaces for indents (use s switch on CMD line for spaces).
- Will create a subroutine "header" for subroutines if no header exists. Inserts 1 blank line if it's a newly created header, respects spacing if already a header.
- Will remove empty lines if 2 or more in a row.
- Moves the "old" files to a subfolder called Processed (respecting overwrites with a numbered file approach file.mac.0, file.mac.1 etc.).
- Writes the newly formatted file (same name) back into the folder in which the MQ2f.pl was run.
- Place the MQ2f.pl file in any folder in which you will place .MAC and .INC files.
- Open a CMD line.
- Type "perl mq2f.pl" or "perl mq2f.pl s" (don't use the quotes, silly). Hit return.
- the t switch will use tabs rather than tabs for the indents.
Requires PERL. PERL Install instructions are at the bottom of this post after the MQ2f.pl script.
MQ2f.pl V9-- Defaults to leading tabs. Use s switch for leading tabs. Last Updated: 6/23/2019
Rich (BB code):
# Version 9 6/22/2019 by Joojoobee
#!/usr/bin/perl -w
#use strict;
use File::Spec::Functions qw'catfile';
use File::Copy qw'move';
use autodie qw'move';
use File::Stat qw/:stat/;
use File::Compare;
my $proc_file = "";
my $countindents = 1; # default to at least one indent for whole file
my $countEmptyRows = 0; # counter to ensure only one empty row allowed. If 2 or more, remove those lines
my $subCommentCount = 0; # check for a subroutine header
my $oldSubCommentCount = 0;
my $subroutineTag = 0; # Was there a subroutine tag?
my $subroutineName = ""; # name of the subroutine to place in a header
my $useTabsOrSpaces = "\t";
my $TabOrSpaceUse = " using tabs for indents";
my $modtime8 = time();
my $modtime9 = time();
my $newmac= "";
my $oldfile = "";
my $msg = '';
if (exists $ARGV[0] && $ARGV[0] eq "s") { $useTabsOrSpaces = " "; $TabOrSpaceUse = " using spaces for indents"; }
foreach $proc_file (<*.*>)
{
if (!($proc_file=~ m/.mac$|.inc$/)) { goto nextFile; } # only read .mac or .int files
#print "$proc_file\t\t ... Opened \n";
$oldfile = $proc_file;
open(FILE, "$proc_file");
$modtime8 = (stat($proc_file))[8];
$modtime9 = (stat($proc_file))[9];
$countindents = 0; # reset the indent count for each new file
if ($proc_file=~ m/.mac/) { # if it's a .mac file, rename output file to .fmac and open it for writing
$proc_file =~ s/.mac//; # get the base name of the file
open (OUT22,">$proc_file".".fmac"); # create a temporary version for writing
$newmac = "$proc_file".".fmac";
}
if ($proc_file=~ m/.inc/) { # if it's a .inc file, rename output file to .finc and open it for writing
$proc_file =~ s/.inc//; # get the base name of the file
open (OUT22,">$proc_file".".finc"); # create a temporary version for writing
$newmac = "$proc_file".".finc";
}
while(my $row = <FILE> ) # get each line in file
{
my $addback = 0; # set | and : check to 0
chomp $row; # clean up the last row, remove line feed/CR tags
$row =~ s/^\s+|\s+$//g; # remove leading and trailing tabs and spaces
my $string=""; # reset the indent string to blank for each line
if ($countindents <0) { $countindents = 0; } # in case of weird over use of }
if (($row=~ m/}$/) && index($row,"{") < 0) { $countindents--; } # decrement the indent for end of bracket }
if ($row=~ m/}\s*else/i) { $countindents--; } # decrement the indent for end of bracket } else (case insensitive)
if ($row=~ m/^\/next\s*\S/i) { $countindents--; } # decrement the indent for a next statment
if ($row=~ m/^\|/ || $row=~ m/^:/) { # decrement the indent for comments or : goto lines
#$countindents--;
#$addback = 1; # set the addback flag to put indent back after | or :
}
if (($row=~ m/^\|\s*---/ || $row=~ m/^\|\s*=-=/ || $row=~ m/^\||\s*---/ || $row=~ m/^\||\s*=-=/) && ($subCommentCount == 0 || $subCommentCount == 2)) { $subCommentCount++; } # start a simple count for subroutine header
if (($row=~ m/^\|\s*sub/i || $row=~ m/^\|\s*===/ || $row=~ m/^\|:\s*sub/i || $row=~ m/^\|:\s*===/)&& $subCommentCount == 1) { $subCommentCount++; } # found a reasonable tag for "| SUB". Case insensitive and tolerant of variation
if ($row=~ m/^sub\s\S/i && ($subCommentCount == 3 || $subCommentCount == 0)) { # found a subroutine tag (looks for word "sub" a space/tab and at least a single non space/tab letter)
$subroutineTag++;
$subroutineName = $row;
$subroutineName =~ s/^sub\s//i; # remove the sub keyword
$subroutineName =~ s/\(.*\)//i; # remove any variable names and ()
}
if ($oldSubCommentCount !=0 && $oldSubCommentCount == $subCommentCount) { # Check for Header should not allow for any interceding lines.
$countLines++;
if ($countLines == 2) { # two lines went by without a Header key, this is not a header
$subCommentCount = 0; # reset header check to 0
$oldSubCommentCount = 0;
$countLines = 0;
}
}
$oldSubCommentCount = $subCommentCount; # save subCommentCount for comparison to determine if proper structure.
if ($row ne "") { # build the indents
for my $i (0 .. $countindents) {
$string = "$string"."$useTabsOrSpaces"; # by concatenating tabs or spaces
}
}
if ($row eq "") { # check for empty lines
$countEmptyRows++;
}
if ($countEmptyRows == 2) { # two empty lines in a row, skip printing it
$countEmptyRows = 1;
next;
}
if ($subroutineTag == 1) { # a sub keyword was found
if ($subCommentCount != 3) { # if the lines immediately above did not already have a header, print a header
$subCommentCount = 0; # reset the header check counters, print a header
$oldSubCommentCount = 0;
$countLines = 0;
if ($countEmptyRows > 0) { print OUT22 "\n"; }
print OUT22 "|: --------------------------------------------------------------------------------------------\n";
print OUT22 "|: SUB: $subroutineName\n";
print OUT22 "|: --------------------------------------------------------------------------------------------\n";
}
if ($subroutineTag == 1 && $subCommentCount > 0) { #incomplete header check, so zero the header check
$subCommentCount = 0;
$oldSubCommentCount = 0;
$countLines = 0;
}
$subroutineTag = 0; # finished with header, reset subroutine line check
}
if ($subCommentCount > 3) { # invalid header structure, so zero the header check
$subCommentCount = 0;
$oldSubCommentCount = 0;
$countLines = 0;
}
if ($row =~ m/\+\+\+ Formatted by MQ2f/i) { next; } # dom't rewrite the end line.
if ($countEmptyRows <= 1) { # allow printing if as many as 1 empty line above
print OUT22 "$string"."$row\n"; # print the line
if ($row ne "") {$countEmptyRows = 0;} # was a single empty line prior, reset counter of empty lines to 0
}
if ($addback == 1) { $countindents++; } # add back the line if de-indented for | or :
if($row=~ m/{$/) { $countindents++; } # increment the indent if an open bracket { at the end of the line
if($row=~ m/^\/for\s+\S/i ) { $countindents++; } # increment the indent if a /for statement
if($row=~ m/^\/squelch\s*\/for\s*\S/i ) { $countindents++; } # increment the indent if a /squelch /for statement
}
close FILE; # close input file
if ($countEmptyRows > 0) { print OUT22 "\n"; }
print OUT22 "\n[+++ Formatted by MQ2f"."$TabOrSpaceUse +++]\n" ;
close OUT22; # close output file
utime $modtime8, $modtime9, $newmac;
my $directory = "Processed"; # If Processed subdirectory does not exist, create one
unless(-e $directory or mkdir $directory) {
die "Unable to create $directory, potential permission or space limitations\n";
}
if (compare($oldfile,$newmac) != 0) {
print "reformatted ==> $oldfile\n";
my $origin = '.';
my $destination = 'Processed';
my $path = catfile $destination, $oldfile;
my $counter = 0;
while( -e $path ){
$counter++;
$path = catfile $destination, "$oldfile.$counter";
}
move( catfile( $origin, $oldfile ), $path );
my $modtime8 = (stat($newmac))[8];
my $modtime9 = (stat($newmac))[9];
my $newname = $newmac;
if ($oldfile=~ m/.mac/) {
$newname =~ s{.fmac}{.mac}gxms;
}
if ($oldfile=~ m/.inc/) {
$newname =~ s{.finc}{.inc}gxms;
}
rename $newmac, $newname;
utime $modtime8, $modtime9, $newmac;
} else {
unlink $newmac;
}
nextFile:
}
print "Exiting \n";
my $exit = 0;
Installing Perl:
I find PERL to be amazingly flexible at complex string editing. It has great abilities to "reach" into the Windows system as well. It's not as easy as AHK, but is great for a lot of quick and dirty programming.
General instructions for installing PERL are here: https://www.perl.org/get.html
I use ActiveState PERL (Strawberry Perl and others also work). There is a community version (free of charge).
http://www.activestate.com/activeperl/downloads
Install:
- Download PERLinstall package (32 and 64 bit available)
- Run exe file
- Activestate loads all necessary files, including the Perl Package Manager (PPM).
- PPM keeps track of module updates, allows you to search for and load unique modules for math and string functions.
- All modules used in MQ2f.pl are contained in the default PERL download.
Running MQ2f.pl :
- Open a cmd window in the folder in which MQ2f.pl resides along with the .MAC or .INC files you want to convert.
- At command line, type "perl MQ2f.pl" (no quotes) or with options for tabs:
- perl MQ2f.pl t
- KOMODO editor by Activestate (I use this). http://www.activestate.com/komodo-ide
- Has a nice built in syntax and debug system. Costs $$, limited function free version available.
- Padre. Written by PerlMaven . Free to use. http://padre.perlide.org/
There are lots of online tutorials for Perl script newbies. Most often you will find yourself at PerlMaven as he has excellent examples and tutorials (he also wrote the free IDE so he knows what he's doing).
Last edited:


