| Category: |
|
| Author/Contact Info |
jpfarmer |
| Description: |
In my code, I like to use very visible comments to indicated major program components (subroutines, a block of global variables, etc). The format I prefer looks like this:
#######################
# This subroutine... #
#######################
However, these are a pain to create because you have to manage the space padding. It's more work than I care to put into it. So, I wrote a Perl program that will parse my program for specially formatted comments, then format them they way I like them.
Any feedback is greatly appreciated. |
#!/usr/bin/perl
use warnings;
use strict;
use Fcntl ':flock';
use File::Copy;
use Tie::File;
############################################################
# Author: jpfarmer @ Perlmonks #
# http://www.perlmonks.org/index.pl?node_id=126392 #
# #
# This program takes one argument, the name of the source #
# to clean up. It copies that file to <filename>.bak #
# and then operates on the original. It creates formatted #
# comments when they are properly marked. Example: #
# #
# #/* #
# # This subroutine ... #
# #*/ #
# #
# becomes #
# #
# ####################### #
# # This subroutine ... # #
# ####################### #
# #
############################################################
####################
# Global Variables #
####################
our $fn = shift @ARGV;
our $fn_bak = "$fn.bak";
our $border_char = '#';
our @program;
####################
# Begin Program #
####################
# Backup program
copy($fn, $fn_bak);
# Tie the file to an array so we can manipulate it easily.
tie @program, 'Tie::File', $fn;
# Begin iterating over the file and converting comments.
# If the comments are improperly formed, then we do not
# do anything. Better to do nothing then to blow something
# up.
my $slurp_start;
my $slurp_end;
my @slurp_lines;
for (my $i = 0; $i < $#program; $i++){
my $line = $program[$i];
if (! defined $slurp_start){
# Skip to the next line if this isn't a comment
next unless ($line =~ m{^#});
# If we end up with a comment, we need to figure out if
# it is telling us to start slurping
next unless ($line =~ m{^#/\*});
# If we get to this point, we need to start slurping.
# So, we mark the beginning index and next.
$slurp_start = $i;
print STDERR "Found a block starting at line $i.\n";
next;
} else{
# We need to see if we've come across either an uncommented
# or a block end. A block end means we need to set $slurp_end
# and make our changes. If it's uncommened, we'll undef slurp_sta
+rt
# and slurp_end and empty slurp_lines. If it's just a commented
# line, chomp it and store it.
if ($line =~ m/^[^#]/){
$slurp_start = undef;
$slurp_end = undef;
@slurp_lines = ();
next;
} elsif ($line =~ m{^#\*/}){
$slurp_end = $i;
print STDERR "Block ended at line $i.\n";
&create_block;
next;
} else {
chomp $line;
push(@slurp_lines, $line);
print STDERR "$line\n";
}
}
}
######################################################################
+##
# This takes no arguments, and operates on global variables. It takes
+ #
# a discovered block comment, and processes it commiting the changes
+ #
# to the file.
+ #
######################################################################
+##
sub create_block {
# First, we need to calculate the length of the longest line, then
+
# add 2 to it (for a trailing space and the boundry marker) to fin
+d
# our box width.
my $box_width = &max(map {length($_) + 2} @slurp_lines);
# Now, replace the first and last lines with solid bars
# $border_char
$program[$slurp_start] = $program[$slurp_end] = $border_char x $bo
+x_width;
# Finally, stick the remaining lines in between border_chars
for (my $i = ($slurp_start + 1); $i < $slurp_end; $i++){
$program[$i] = sprintf("%-" . ($box_width - 2) . "s #", $program[$
+i]);
}
# Clear out the globals, and we're done.
$slurp_start = undef;
$slurp_end = undef;
@slurp_lines = ();
}
####################################################################
# This takes one argument, an array, and returns the maximum value #
# The code is swiped from the perlsub page. #
####################################################################
sub max(@list) {
my $max = shift(@_);
foreach my $foo (@_) {
$max = $foo if $max < $foo;
}
return $max;
}
|
Re: Comment Block Creator
by diotalevi (Canon) on Dec 03, 2003 at 20:01 UTC
|
Goodness, I like perl. Here's the same thing in a fraction of the lines. It probably works.
use List::Util 'max';
use File::Copy 'copy';
use File::Slurp qw'read_file write_file';
@ARGV == 1 or die "$^X $0 filename.pl\n";
my $file = shift;
copy $file, "$file.bak"
or die "Couldn't copy $file to $file.bak: $!";
my $source = read_file( $file );
$source =~
s(^#/*.*\n((?s:.+?))^#*/.*\n){
my @lines = map /^\s*#\s*(.+?)[\s#]*$/, split /\n/, $1;
my $len = 1 + max( map length(), @lines );
join "\n",
"#" x $len,
map( sprintf("%-" . ($len - 1) . "s #"), @lines ),
"#" x $len
}meg
and write_file( $file, $source )
or die "Couldn't write changed source to $file: $!";
| [reply] [d/l] |
Re: Comment Block Creator
by duff (Parson) on Dec 03, 2003 at 22:04 UTC
|
Interesting if a bit long. I normally use Damian Conway's Text::Autoformat for reformatting emails and such in vi. It seems like it would be a useful addition to create a mode for it to handle your commenting style as well so that comment edits are painless. Heck, it may already handle this format and I just don't know. Update: I just tried it and it works fine as long as you're willing to live without the trailing # on each line. I.e.,
######################################################################
# Hello there, this is a test.
# And this too is a test. More testing,
# more testing, more testing ... What a bore! :-)
#
######################################################################
is reformatted as
######################################################################
# Hello there, this is a test. And this too is a test. More testing,
# more testing, more testing ... What a bore! :-)
#
######################################################################
| [reply] [d/l] [select] |
Re: Comment Block Creator
by Anonymous Monk on Dec 03, 2003 at 20:02 UTC
|
| [reply] |
|
|
Sort of. I have some routines to handle that (that remove the old comments and reformat), but I did them quickly and they don't always work, so I took them out before posting so I wouldn't be ripped apart in a public forum.
| [reply] |
•Re: Comment Block Creator
by merlyn (Sage) on Dec 04, 2003 at 13:27 UTC
|
My comment? I think it's ugly. Please don't use this on anything you upload to the CPAN, or contribute here. It's OK to use in the privacy of your own cube... just don't let it get out into the wild.
| [reply] |
|
|
I think your comment is a little snide and extremely discouraging. I'm making a concerted attempt to create thoroughly commented code, and am trying to keep it formatted so it's clear to read. If the format is offensive to you, I'd appreciate suggestions on how to make it less so, but a blanket "it's too ugly to be used in public" reply makes me want to do exactly what you suggest and avoid contributing any code. In any event, I'll think two or three times before sharing anything in the future.
| [reply] |
|
|
I didn't intend for you to stop sharing!
But you did post here, and posting here implies inviting critique and comment. Hence my comment.
The problem with "fancy comments" is that they are either making into comments what should be POD or a separate document, or they are making it hard to rewrite the code, because you don't want to touch the "sacred" fancy comments. Also, being set off that way, you might
trust the comments more than the code, and many years of programming has lead me to believe that in "live" code, the comments eventually lie, because someone has edited the code and not the comments.
Keep your comment style simple. Keep it describing the "what" and not the "how", unless the "how" is particularly tricky. (And most "how" comments should be inline anyway.) Keep it describing any tricky presumptions, assertions, or dependencies. Keep it being for other programmers, not for users of the code (which should be in POD anyway).
I think once you figure out what really does need commenting, you'll comment less and code more.
| [reply] |
|
|
|
|
| |
|
Please don't let the lack of social skills of a few discourage you too
greatly.
On the other hand, many experienced programmers find the kind of comment
block formatting you are doing to be both excessive and hard to maintain.
At the very least, consider leaving the right side of the comment box open
rather than closed. Many editors can reflow text with comment characters
on the left, making updates relatively painless. But closed-box comments
require additional effort and/or tools to maintain, which hinders their
usefulness.
| [reply] |
|
|