Wednesday, July 8, 2009

Commenter

I really don't have the time to write scripts recently, but this one will definitely save me some time tomorrow.

So, hey! I started this a while back when I was doing another one of those damn big Java projects, and I had to stick a bunch of generic comments to the beginning of each file, so it's (slightly more) compliant with the code convention. Alas, I didn't have the attention span to finish it then, and I just wrote the comments by hand.

But the problem reared its ugly head yet again, so I took the time to finish the script, and now I have one menial task less to do!

Here's how it works.

Supposing you've got a big Java project that needs to get those pesky comments included, you whip out the Commenter and go:

./commenter \
--author "Doctor Steve" \
--version 1.5 \
--output-dir BigJavaProject/commented \
BigJavaProject/src


And you're good to go! Every file from BigJavaProject/src will be copied (with the full package path) into BigJavaProject/commented while prepending a comment.

And, as an example, for a file called JavaParser.java, the comment will look something like:
/*
* JavaParser
*
* Version 1.5
*
* Date 8 July 2009
*
* Copyright 2009 Doctor Steve
*/


And if you want to know more, read the comments, or the entire code. I mean, if you're interested in this one, you must be a developer anyway.

Oh! and it's GPL.

And here's the code:
 
1 #!/bin/bash
2 #
3 # Commenter
4 #
5 # A simple program to include a generic c-style header comment to a
6 # Java project. The comment includes the classname, the version
7 # number and date, and the copyright notice -- as specified in the
8 # code convention for the Java language, available at:
9 # <http://java.sun.com/docs/codeconv/>
10 #
11 # Parameters:
12 # -o|--output-dir output directory for the generated files,
13 # default: current working directory, i.e., HERE;
14 # -a|--author set author for the copyright notice,
15 # default: the current system user;
16 # -y|--year set the year for the copyright notice,
17 # default: the current year;
18 # -d|--date set date for of creation for the comment,
19 # default: the current date;
20 # -v|--version set the default version for all files,
21 # default: 1.0;
22 # --verbose display additional info.
23 # Author:
24 # Konrad Siek <konrad.siek@gmail.com>
25 #
26 # License information:
27 #
28 # This program is free software: you can redistribute it and/or modify
29 # it under the terms of the GNU General Public License as published by
30 # the Free Software Foundation, either version 3 of the License, or
31 # (at your option) any later version.
32 #
33 # This program is distributed in the hope that it will be useful,
34 # but WITHOUT ANY WARRANTY; without even the implied warranty of
35 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 # GNU General Public License for more details.
37 #
38 # You should have received a copy of the GNU General Public License
39 # along with this program. If not, see <http://www.gnu.org/licenses/>.
40 #
41 # Copyright 2009 Konrad Siek
42
43 # Sets unset variables to some presets.
44 function initiate_presets() {
45 [ "$output_dir" == "" ] && output_dir=$(pwd)
46 [ "$date" == "" ] && date=$(date +'%-d %B %Y')
47 [ "$year" == "" ] && year=$(date +%Y)
48 [ "$version" == "" ] && version=1.0
49 [ "$author" == "" ] && author=$(whoami)
50 [ "$extension" == "" ] && extension=.java
51 }
52
53 # Print an error to stderr
54 # @param error message
55 function syserr() {
56 echo "$0: $@" >& 2
57 }
58
59 # Generate a single comment from a list of strings.
60 # @param zero or more strings
61 # @return c-style comment string
62 function generate_comment() {
63 echo "/*"
64 if (( $# == 0 ))
65 then
66 echo " * "
67 else
68 while (( $# > 0 ))
69 do
70 echo " * $1"
71 if (( $# > 1 ))
72 then
73 echo " * "
74 fi
75 shift
76 done
77 fi
78 echo " */"
79 }
80
81 # Copy a file with and append a generated file comment.
82 # @param absolute file path
83 function comment () {
84 comment=$( \
85 generate_comment \
86 "$(basename "$1" $extension)" \
87 "Version $version" \
88 "Date $date" \
89 "Copyright $year $author" \
90 )
91
92 package=$(dirname ${1:${#base_dir}})
93 output=$output_dir$package/$(basename "$1")
94
95 if [ $verbose ]
96 then
97 echo "Commenting file '$1' as '$output'."
98 fi
99
100 mkdir -p $(dirname "$output")
101 echo -e "$comment" | cat - "$1" > "$output"
102 }
103
104 # Apply transformation to an entire project or directory.
105 # @param absolute directory path
106 function comment_dir () {
107 base_dir="$1"
108 find "$1" -type f -name "*$extension" | \
109 while read f
110 do
111 comment "$f"
112 done
113 }
114
115 # Apply transformation to a file or directory.
116 # @param resource path
117 function comment_resource () {
118 if [ ! \( -e "$1" \) ]
119 then
120 syserr "Resource '$1' does not exist."
121 return 1
122 fi
123
124 input=$(readlink -f "$1")
125 if [ -d "$input" ]
126 then
127 comment_dir "$input"
128 else
129 base_dir=$(dirname "$input")
130 comment "$input"
131 fi
132 }
133
134 # Parse options
135 options=$( \
136 getopt \
137 -o o:v:a:d:y:e: \
138 --long output-dir:,version:,author:,date:,year:,extension:,verbose \
139 -n $0 -- "$@" \
140 )
141
142 # Stop if there's some sort of problem
143 if [ $? != 0 ]
144 then
145 syserr "Argh! Parsing went pear-shaped!"
146 exit 1
147 fi
148
149 # Set the parsed command options
150 eval set -- "$options"
151
152 # Setup selected options
153 while true
154 do
155 case "$1" in
156 -o|--output-dir)
157 output_dir="$2"
158 shift 2
159 ;;
160 -v|--version)
161 version="$2"
162 shift 2
163 ;;
164 -a|--author)
165 author="$2"
166 shift 2
167 ;;
168 -y|--year)
169 year="$2"
170 shift 2
171 ;;
172 -d|--date)
173 date="$2"
174 shift 2
175 ;;
176 -e|--extension)
177 [ ${2:0:1} == . ] && extension="$2" || extension=".$2"
178 shift 2
179 ;;
180 --verbose)
181 verbose=true
182 shift 1
183 ;;
184 --)
185 # Stop parsing options
186 shift
187 break
188 ;;
189 *)
190 # Weird error
191 syserr "The end of the world is nigh!"
192 exit 2
193 ;;
194 esac
195 done
196
197 # Process configuration
198 initiate_presets
199
200 if [ $verbose ]
201 then
202 echo "Output: $output_dir"
203 echo "Date: $date"
204 echo "Version: $version"
205 echo "Author: $author"
206 echo "Year: $year"
207 echo "Extension: $extension"
208 fi
209
210 # Process inputs
211 if [ "$#" == 0 ]
212 then
213 # If no paths were given, use the current directory.
214 comment_resource .
215 else
216 # If some paths were given, comment them each individually.
217 for arg
218 do
219 comment_resource "$arg"
220 done
221 fi


The code is also available at GitHub as bash/commenter.

No comments: