Skip to content

Instantly share code, notes, and snippets.

@Riduidel
Created February 25, 2011 10:23
Show Gist options
  • Select an option

  • Save Riduidel/843613 to your computer and use it in GitHub Desktop.

Select an option

Save Riduidel/843613 to your computer and use it in GitHub Desktop.
import java.io.File
import groovy.xml.MarkupBuilder
abstract class Entry {
/** parent documentor, used to access doc various formats */
def doc;
/** node name */
def name;
/** Comments to be kept at last */
def finalComments;
/** current comments */
def comments = [:]
def currentFormatting = null
def add(String line) {
if(line.startsWith(doc.docStart)) {
def content = line.substring(line.indexOf(doc.docStart)+doc.docStart.length()).trim()
def newFormatting = doc.formattings.find { f ->
content.contains(f)
}
if(newFormatting!=null) {
currentFormatting = newFormatting
}
if(content.indexOf(currentFormatting)>=0) {
content = content.substring(content.indexOf(currentFormatting)+currentFormatting.length())
}
if(comments.containsKey(currentFormatting)) {
comments[currentFormatting]= (comments[currentFormatting]==null ? content : (comments[currentFormatting]==false ? content : comments[currentFormatting]+"\n"+content))
} else {
comments[currentFormatting]= content.size()==0 ? false : content
}
} else {
handle(line)
}
}
abstract handle(String line)
}
class Section extends Entry {
private Collection<Parameter> parameters = []
def getLastEntry() {
return this
}
def handle(String line) {
if(line==~IniDocumentor.PARAMETER_REGEX) {
def matching = (line=~IniDocumentor.PARAMETER_REGEX)
def param = new Parameter(doc:doc, name:matching[0][1], value:matching[0][2], finalComments:comments)
comments = [:]
parameters << param
} else if(line==~IniDocumentor.SECTION_REGEX) {
def matching = (line=~IniDocumentor.SECTION_REGEX)
if(name==null) {
// Found section name
name = matching[0][1]
finalComments = comments
comments = [:]
} else {
def newSection = new Section(doc:doc, name:matching[0][1], finalComments:comments)
comments = [:]
doc.sections << newSection
}
} else {
}
}
public String toString() {
return name+"\n"+finalComments[IniDocumentor.BRIEF_COMMENT]+parameters.inject("") { text, param -> text+"\n\t"+param.toString() }
}
}
class Parameter extends Entry {
def value;
def handle(String line) {
throw new UnsupportedOperationException("not in parameter\n"+line)
}
String toString() {
return name+"="+value+"\n"+finalComments
}
}
public class IniDocumentor {
public static final String DEFAULT_PATH = "../PSS.ini"
public static final String DEFAULT_DOC = "##"
public static final String DEFAULT_OUTPUT = "../../../../target/doc/PSS.ini.mediawiki"
public static final String BRIEF_COMMENT = "@brief"
public static final String MANDATORY_COMMENT = "@mandatory"
public static final String OPT_COMMENT = "@optionnal"
public static final String DEPRECATED_COMMENT = "@deprecated"
public static final String DEFAULT_COMMENT = "@default"
public static final String TYPE_COMMENT = "@type"
public static final def PARAMETER_REGEX = /^(\w+)\s*=\s*((?:\p{Alnum}|\p{Punct})*)\s*(;#)*(;#)*.*/
public static final def SECTION_REGEX = /\[(\w*)\].*/
String path;
String docStart;
Collection<String> formattings = [BRIEF_COMMENT, MANDATORY_COMMENT, OPT_COMMENT, DEFAULT_COMMENT, TYPE_COMMENT,DEPRECATED_COMMENT]
Collection<Section> sections = []
/**
* Parse given file
*/
private void parse() throws Exception {
def file = new File(path)
println "parsing ..."
file.eachLine() { line ->
if(line.trim().size()>0) {
getLastEntry().add(line)
}
print "."
}
println "\nfinished parsing \"${path}\""
}
def getLastEntry() {
if(sections.isEmpty()) {
sections << new Section(doc:this)
}
def section = sections.get(sections.size()-1)
return section.getLastEntry()
}
def toHTML(String outputPath) {
File output = new File(outputPath)
output.parentFile.mkdirs()
FileWriter writer = new FileWriter(output)
def builder = new MarkupBuilder(writer)
builder.html {
head {
title "Documentation for ${path} built on ${new Date()}"
}
body {
sections.each { section ->
a(name:section.name)
h3 section.name
p section.finalComments[BRIEF_COMMENT]
section.parameters.each { parameter ->
a(name:parameter.name)
if(parameter.finalComments.containsKey(DEPRECATED_COMMENT)) {
h4 {
strike parameter.name
}
p parameter.finalComments[DEPRECATED_COMMENT] ?: "Abandonné"
} else if(parameter.finalComments.containsKey(MANDATORY_COMMENT)) {
h4 {
u parameter.name
}
p parameter.finalComments[MANDATORY_COMMENT] ?: "Obligatoire"
} else {
h4 parameter.name
if(parameter.finalComments[OPT_COMMENT]!=false)
p parameter.finalComments[OPT_COMMENT]
}
if(parameter.finalComments.containsKey(BRIEF_COMMENT)) {
p parameter.finalComments[BRIEF_COMMENT]
}
if(parameter.finalComments.containsKey(TYPE_COMMENT)) {
p "Type : "+parameter.finalComments[TYPE_COMMENT]
}
if(parameter.finalComments.containsKey(DEFAULT_COMMENT)) {
p "Valeur par défaut : "+parameter.finalComments[DEFAULT_COMMENT]
}
p {
b "Valeur du fichier : "
span parameter.value
}
}
}
}
}
}
def toMediaWiki(String outputPath) {
File output = new File(outputPath)
output.parentFile.mkdirs()
FileWriter writer = new FileWriter(output)
writer.write("= Documentation for ${path} built on ${new Date()} =\n");
sections.each { section ->
writer.write("=="+section.name+"==\n");
writer.write(section.finalComments[BRIEF_COMMENT]?:""+"\n")
section.parameters.each { parameter ->
writer.write("==="+parameter.name+"===\n")
if(parameter.finalComments.containsKey(DEPRECATED_COMMENT)) {
writer.write("'''"+(parameter.finalComments[DEPRECATED_COMMENT] ?: "Abandonné")+"'''\n\n")
} else if(parameter.finalComments.containsKey(MANDATORY_COMMENT)) {
writer.write("'''"+(parameter.finalComments[MANDATORY_COMMENT] ?: "Obligatoire" )+"'''\n\n")
} else {
if(parameter.finalComments[OPT_COMMENT]!=false)
writer.write(parameter.finalComments[OPT_COMMENT]?.trim()+"\n\n")
}
if(parameter.finalComments.containsKey(BRIEF_COMMENT)) {
writer.write(parameter.finalComments[BRIEF_COMMENT]?.trim()+"\n\n")
}
if(parameter.finalComments.containsKey(TYPE_COMMENT)) {
writer.write("Type : "+parameter.finalComments[TYPE_COMMENT]+"\n\n")
}
if(parameter.finalComments.containsKey(DEFAULT_COMMENT)) {
writer.write("Valeur par défaut : "+parameter.finalComments[DEFAULT_COMMENT]+"\n\n")
}
writer.write("'''Valeur du fichier : "+ parameter.value+"'''\n\n")
}
}
writer.close()
}
def toOutput(String outputPath) {
println "generating output"
def lowCasePath = outputPath.toLowerCase()
if(lowCasePath==~/.*\.htm.*/)
toHTML(outputPath)
else if(lowCasePath==~/.*\.mediawiki*/)
toMediaWiki(outputPath)
else
throw new UnsupportedOperationException("output format of "+outputPath+" is not yet supported")
println "finished generating \"${outputPath}\""
}
static void main(args) throws Exception {
def cli = new CliBuilder(usage:'groovy ini_doc.groovy options')
cli.o(longOpt: 'output', 'Output file. Notice it will be html content, so use appropriated format. Notice output format will be either html (if path ends with .html*) or mediawiki synatx (if path ends with .mediawiki). Defaults to '+DEFAULT_OUTPUT)
cli.h(longOpt: 'help', 'Shows this help')
cli.p(longOpt: 'path', 'Path of PSS.ini file. Defaults to '+DEFAULT_PATH)
cli.d(longOpt: 'docPrefix', 'Prefix for documentation comments. Defaults to '+DEFAULT_DOC)
def opt = cli.parse(args);
if(opt.h) {
cli.usage();
} else {
def documentor = new IniDocumentor(
path: opt.p==false ? DEFAULT_PATH : opt.p,
docStart: opt.d==false ? DEFAULT_DOC : opt.d
)
documentor.parse()
/* now output it */
documentor.toOutput(opt.o==false ? DEFAULT_OUTPUT : opt.o)
}
}
}
IniDocumentor.main(this.args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment