Compare commits

...

10 Commits

47 changed files with 121 additions and 339 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.gradle/
docs/jlp-docs/
build/
.*.sw?

View File

@ -1,5 +1,8 @@
# J Literate Programming
* [Source](https://git.jdb-labs.com/jdb-labs/jlp)
* [Annotated Source and Documentation](https://doc.jdb-labs.com/jlp/current/)
## Overview
*Jonathan's Literate Programming* is my take on literate programming.
This project grew out of a desire for a documentation system that:
@ -57,14 +60,19 @@ This project is in its infancy and some of the larger goals are still unmet:
## Project Architecture
JLP processes it's own documentation. The latest documentation is available at
https://doc.jdb-labs.com/jlp/current/
Below are some starting points.
### Control and Flow
* [JLPMain](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/JLPMain.groovy.html)
* [JLPMain](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/JLPMain.groovy.html)
The entry point to the JLP executable. Parses the command line input and
sets up the processor.
* [Processor](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/Processor)
* [Processor](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/Processor.groovy.html)
The Processor processes one batch of input files to create a set of output files.
It holds the intermediate state needed by the generators and coordinates the
@ -72,14 +80,14 @@ This project is in its infancy and some of the larger goals are still unmet:
processor only generates HTML documentation and will likely be renamed in
the future to reflect this.
* [JLPBaseGenerator](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/JLPBaseGenerator)
* [JLPBaseGenerator](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/JLPBaseGenerator.groovy.html)
The Generator processes one input file. It parses the AST for the input file
and emits the final documentation for the file. JLPBaseGenerator
implementations are expected to be tightly coupled to Processor
implementations.
* [LiterateMarkdownGenerator](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/LiterateMarkdownGenerator)
* [LiterateMarkdownGenerator](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/LiterateMarkdownGenerator.groovy.html)
This implemetation of JLPBaseGenerator generates literate-style
documentation (as opposed to API-style), using
@ -88,11 +96,11 @@ This project is in its infancy and some of the larger goals are still unmet:
### Parsing
* [JLPParser](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/JLPParser)
* [JLPParser](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/JLPParser.groovy.html)
A very simple interface for parsing JLP input.
* [JLPPegParser](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/JLPPegParser)
* [JLPPegParser](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/JLPPegParser.groovy.html)
A [PEG parser](http://en.wikipedia.org/wiki/Parsing_expression_grammar)
implemented using the [parboiled](http://www.parboiled.org) library. This
@ -102,6 +110,6 @@ This project is in its infancy and some of the larger goals are still unmet:
### Abstract Syntax Tree
* [SourceFile](https://jdbernard.github.io/jlp/doc/src/com/jdblabs/jlp/JLPPegParserSourceFile)
* [SourceFile](https://doc.jdb-labs.com/jlp/current/src/main/groovy/com/jdblabs/jlp/JLPPegParserSourceFile.groovy.html)
The top-level AST element. This represents a source file.

26
build.gradle Normal file
View File

@ -0,0 +1,26 @@
apply plugin: "groovy"
apply plugin: "maven"
group = "com.jdblabs"
version = "1.10"
repositories {
mavenLocal()
mavenCentral() }
dependencies {
compile 'org.codehaus.groovy:groovy-all:[2.4.0,)'
compile 'org.pegdown:pegdown:[1.6.0,)'
compile 'org.slf4j:slf4j-api:[1.7.10,)'
compile 'ch.qos.logback:logback-core:[1.1.2,)'
compile 'ch.qos.logback:logback-classic:[1.1.2,)'
compile 'commons-cli:commons-cli:[1.2,)'
compile 'org.apache.commons:commons-lang3:[3.3.2,)'
compile 'com.jdbernard:jdb-util:[4.0,)'
}
jar {
manifest {
attributes("Main-Class": "com.jdblabs.jlp.JLPMain")
}
}

View File

@ -1,20 +0,0 @@
<project name="Jonathan's Literate Programming" basedir="." default="release">
<import file="jdb-build-1.10.xml"/>
<property environment="env"/>
<property file="project.properties"/>
<target name="release" depends="build">
<mkdir dir="${release.dir}/lib"/>
<copy file="${build.dir}/${name}-${version}.${build.number}.jar"
tofile="${release.dir}/${name}-${version}.jar"/>
<copy todir="${release.dir}">
<fileset dir="${resources.dir}/release"/>
</copy>
<copy todir="${release.dir}/lib">
<fileset dir="${build.dir}/lib/runtime/jar"/>
</copy>
</target>
</project>

View File

@ -1,248 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project name="Jonathan Bernard Build Common"
xmlns:ivy="antlib:org.apache.ivy.ant">
<property environment="env"/>
<!--======== INIT TARGETS ========-->
<target name="-init" depends="-common-init,init"/>
<target name="-common-init">
<!-- Set default values for some key properties. Since properties are
write once, any value set before this point takes precedence. -->
<property name="versioning.file" value="project.properties"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="lib.dir" value="${basedir}/lib"/>
<property name="resources.dir" value="${basedir}/resources"/>
<property name="splash.image" value="splash.png"/>
<!--======== PATHS ========-->
<path id="groovy.classpath">
<fileset dir="${env.GROOVY_HOME}/lib">
<include name="*.jar"/>
</fileset>
</path>
<path id="groovy.embeddable">
<fileset dir="${env.GROOVY_HOME}/embeddable">
<include name="*.jar"/>
</fileset>
</path>
<path id="compile-libs">
<fileset dir="${build.dir}/lib/compile/jar">
<include name="*.jar"/>
</fileset>
</path>
<path id="runtime-libs">
<fileset dir="${build.dir}/lib/runtime/jar">
<include name="*.jar"/>
</fileset>
</path>
</target>
<target name="-init-groovy">
<taskdef name="groovyc" classpathref="groovy.classpath"
classname="org.codehaus.groovy.ant.Groovyc"/>
<taskdef name="groovy" classpathref="groovy.classpath"
classname="org.codehaus.groovy.ant.Groovy"/>
</target>
<target name="init"/>
<target name="clean" depends="-init">
<delete dir="${build.dir}"/>
</target>
<!--======== LIBRARY TARGETS ========-->
<target name="-lib" depends="-lib-local,-lib-ivy,lib"/>
<target name="lib"/>
<target name="-init-ivy">
<ivy:settings id="ivy.settings" file="ivysettings.xml"/>
</target>
<target name="-lib-ivy" depends="-init-ivy" unless="${lib.local}">
<ivy:retrieve settingsRef="ivy.settings"
pattern="${lib.dir}/[conf]/[type]/[artifact]-[revision].[ext]"
conf="compile,runtime"/>
</target>
<target name="-lib-groovy" if="${lib.local}">
<copy todir="${build.dir}/lib/runtime/jar">
<fileset dir="${env.GROOVY_HOME}/embeddable"/>
</copy>
</target>
<target name="-lib-local" if="${lib.local}">
<echo message="Resolving libraries locally."/>
<mkdir dir="${build.dir}/lib/compile/jar"/>
<mkdir dir="${build.dir}/lib/runtime/jar"/>
<copy todir="${build.dir}/lib/compile/jar" failonerror="false">
<fileset dir="${lib.dir}/compile/jar"/>
</copy>
<copy todir="${build.dir}/lib/runtime/jar" failonerror="false">
<fileset dir="${lib.dir}/runtime/jar"/>
</copy>
</target>
<!--======== VERSIONING TARGETS ========-->
<target name="increment-build-number" depends="-init">
<propertyfile file="${versioning.file}">
<entry key="build.number" default="0" type="int" value="1"
operation="+"/>
</propertyfile>
</target>
<target name="set-version" depends="-init">
<input
message="The current version is ${version}. Enter a new version: "
addproperty="new-version"/>
<propertyfile file="${versioning.file}">
<entry key="version" value="${new-version}" operation="="
type="string"/>
<entry key="build.number" value="0" type="int" operation="="/>
</propertyfile>
</target>
<!--======== COMPILATION TARGETS ========-->
<target name="-compile-groovy" depends="-init,-init-groovy,-lib,-lib-groovy">
<mkdir dir="${build.dir}/main/classes"/>
<groovyc srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
includeAntRuntime="false" fork="true">
<classpath>
<path refid="groovy.classpath"/>
<path refid="compile-libs"/>
</classpath>
<javac/>
</groovyc>
</target>
<target name="-compile-java" depends="-init,-lib">
<mkdir dir="${build.dir}/main/classes"/>
<javac srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
includeAntRuntime="false" classpathref="compile-libs"/>
</target>
<target name="compile" depends="-compile-groovy"/>
<!--======== JUNIT TARGETS ========-->
<target name="-compile-tests-groovy" depends="-init,compile">
<mkdir dir="${build.dir}/test/classes"/>
<groovyc srcdir="${src.dir}/test" destdir="${build.dir}/test/classes"
includeAntRuntime="false" fork="true">
<classpath>
<path refid="groovy.classpath"/>
<path refid="compile-libs"/>
<path location="${build.dir}/main/classes"/>
</classpath>
</groovyc>
</target>
<target name="-compile-tests-java" depends="-init,compile">
<mkdir dir="${build.dir}/test/classes"/>
<javac srcdir="${src.dir}/test" destdir="${build.dir}/test/classes"
includeAntRuntime="false">
<classpath>
<path refid="compile-libs"/>
<path location="${build.dir}/main/classes"/>
</classpath>
</javac>
</target>
<target name="compile-tests" depends="-compile-tests-groovy"/>
<target name="run-tests" depends="compile-tests,resources-test">
<junit printsummary="true">
<classpath>
<path refid="groovy.classpath"/>
<path refid="compile-libs"/>
<path location="${build.dir}/main/classes"/>
<path location="${build.dir}/test/classes"/>
</classpath>
<formatter type="plain" usefile="false"/>
<batchtest>
<fileset dir="${build.dir}/test/classes">
<include name="**/*"/>
</fileset>
</batchtest>
</junit>
</target>
<!--======== RESOURCES TARGETS ========-->
<target name="resources" depends="-init">
<mkdir dir="${build.dir}/main/classes"/>
<copy todir="${build.dir}/main/classes" failonerror="false">
<fileset dir="${resources.dir}/main/"/>
</copy>
</target>
<target name="resources-test" depends="-init">
<mkdir dir="${build.dir}/test/classes"/>
<copy todir="${build.dir}/test/classes" failonerror="false">
<fileset dir="${resources.dir}/test/"/>
</copy>
</target>
<!--======== BUILD TARGETS ========-->
<target name="-build-modular-lib" unless="executable.jar"
depends="compile,increment-build-number,resources">
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
basedir="${build.dir}/main/classes"/>
</target>
<target name="-build-modular-executable" if="executable.jar"
depends="compile,increment-build-number,resources">
<pathconvert property="jar.classpath" pathsep=" " refid="runtime-libs">
<mapper>
<chainedmapper>
<!-- remove absolute path -->
<flattenmapper />
<!-- add lib/ prefix -->
<globmapper from="*" to="lib/*" />
</chainedmapper>
</mapper>
</pathconvert>
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
basedir="${build.dir}/main/classes">
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
<attribute name="SplashScreen-Image" value="${splash.image}"/>
</manifest>
</jar>
</target>
<target name="-build-modular"
depends="-build-modular-lib,-build-modular-executable"/>
<target name="-build-packed-libs"
depends="compile,increment-build-number,resources">
<unjar destdir="${build.dir}/main/classes">
<fileset dir="${build.dir}/lib/runtime/jar"/>
</unjar>
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
basedir="${build.dir}/main/classes"/>
</target>
<target name="build" depends="-build-modular"/>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,8 +0,0 @@
#Tue, 13 Aug 2013 08:48:43 -0500
name=jlp
version=1.7
build.number=25
lib.local=true
release.dir=release
main.class=com.jdblabs.jlp.JLPMain
executable.jar=true

View File

@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory
*/
public class JLPMain {
public static final String VERSION = "1.7"
public static final String VERSION = "1.10"
private static Logger log = LoggerFactory.getLogger(JLPMain.class)
@ -113,7 +113,7 @@ public class JLPMain {
/// Resolve the file against our relative root.
if (!cssFile.isAbsolute()) {
cssFile = new File(pathRoot, cssFile.path) }
/// Finally, make sure the CSS file actually exists.
if (cssFile.exists()) {
css = cssFile
@ -142,14 +142,14 @@ public class JLPMain {
/// For each filename we try to resolve it to an actual file
/// relative to our root.
File file = new File(filename)
if (!file.isAbsolute()) { file = new File(pathRoot, filename) }
if (!file.isAbsolute()) { file = new File(pathRoot, filename) }
/// If this file does not exist, warn the user and skip it.
if (!file.exists()) {
System.err.println(
"'${file.canonicalPath}' does not exist: ignored.")
return }
/// If this file is a directory, we want to add all the files in it
/// to our input list, recursing into all the subdirectories and
/// adding their files as well. We will ignore hidden files.

View File

@ -13,7 +13,7 @@ import com.jdblabs.jlp.ast.SourceFile;
* be an abstract class implementing methods that take additional input for
* convenience.
*
* [`SourceFile`]: jlp://jlp.jdb-labs.com/SourceFile
* [`SourceFile`]: jlp://jlp.jdb-labs.com/ast/SourceFile
*
* @org jlp.jdb-labs.com/JLPParser
*/

View File

@ -40,8 +40,8 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
*/
/**
* #### Full constructor
* This allows the caller to specific all four of the comment delimiters
* #### Full constructor.
* This allows the caller to specify all four of the comment delimiters
* recognized by the parser.
*/
public JLPPegParser(String mdocStart, String mdocEnd,
@ -52,6 +52,20 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
SDOC_START = String(sdocStart).label("SDOC_START");
MDOC_LINE_START = AnyOf(mdocLineStart).label("MDOC_LINE_START"); }
/**
* #### Full constructor supporting multiple comment types.
* This allows the caller to specify all four of the comment delimiters
* recognized by the parser, supplying multiple types of comment
* delimiters.
*/
public JLPPegParser(List mdocStarts, List mdocEnds,
String mdocLineStarts, List sdocStart) {
MDOC_START = FirstOf(mdocStarts.toArray()).label("MDOC_START");
MDOC_END = FirstOf(mdocEnds.toArray()).label("MDOC_END");
SDOC_START = FirstOf(mdocStarts.toArray()).label("SDOC_START");
MDOC_LINE_START = AnyOf(mdocLineStarts).label("MDOC_LINE_START"); }
/**
* #### Single-line comments only constructor.
* This allows the caller to easily set up the parser to only recognize
@ -110,7 +124,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
public Rule SourceFile() {
return Sequence(
/// At the start of processing a new SourceFile, we need to set up
/// our internal state.
/// our internal state.
/// Clear the line count.
clearLineCount(),
@ -125,7 +139,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
FirstOf(
/// Match a whole Block. This pushes a Block on the stack.
Block(),
Block(),
/// A standalone DocBlock. We will create an empty CodeBlock
/// to pair with it, then push a new Block onto the stack
@ -204,7 +218,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
Rule DocBlock() { return FirstOf(SDocBlock(), MDocBlock()); }
/**
* #### SDocBlock
* #### SDocBlock
* Parses the rule:
*
* SDocBlock = (SDirective / SDocText)+
@ -221,7 +235,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
addToDocBlock((ASTNode) pop())))); }
/**
* #### MDocBlock
* #### MDocBlock
* Parses the rule:
*
* MDocBlock = MDOC_START (MDirective / MDocText)+ MDOC_END
@ -243,7 +257,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
addToDocBlock((ASTNode) pop()))),
MDOC_END); }
/**
* #### CodeBlock
* #### CodeBlock
* Parses the rule:
*
* CodeBlock = (RemainingCodeLine)+
@ -259,7 +273,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
addToCodeBlock(match())))); }
/**
* #### SDirective
* #### SDirective
* Parses the rule:
*
* SDirective = SDocLineStart AT (SLongDirective / SShortDirective)
@ -273,7 +287,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
SDocLineStart(), AT, FirstOf(SLongDirective(), SShortDirective())); }
/**
* #### MDirective
* #### MDirective
* Parses the rule:
*
* MDirective = MDocLineStart? AT (MLongDirective / MShortDirective)
@ -288,11 +302,11 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
AT, FirstOf(MLongDirective(), MShortDirective())); }
/**
* #### SLongDirective
* #### SLongDirective
* Parses the rule:
*
* SLongDirective =
* (API_DIR / EXAMPLE_DIR) RemainingSDocLine SDocText?
* (API_DIR / EXAMPLE_DIR / PARAM_DIR) RemainingSDocLine SDocText?
*
* Pushes a [`Directive`] node onto the stack.
*
@ -302,23 +316,23 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
return Sequence(
push(curLineNum),
FirstOf(API_DIR, EXAMPLE_DIR), push(match()),
RemainingSDocLine(), push(match()),
FirstOf(API_DIR, EXAMPLE_DIR, PARAM_DIR), push(match()),
RemainingSDocLine(), push(match()),
Optional(Sequence(
SDocText(),
swap(),
push(popAsString() + ((DocText) pop()).value))),
push(new Directive(popAsString(), popAsString(), popAsInt(),
(DocBlock)peek()))); }
/**
* #### MLongDirective
* #### MLongDirective
* Parses the rule:
*
* MLongDirective =
* (API_DIR / EXAMPLE_DIR) RemainingMDocLine MDocText?
* MLongDirective =
* (API_DIR / EXAMPLE_DIR / PARAM_DIR) RemainingMDocLine MDocText?
*
* Pushes a [`Directive`] node onto the stack.
*
@ -328,8 +342,8 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
return Sequence(
push(curLineNum),
FirstOf(API_DIR, EXAMPLE_DIR), push(match()),
RemainingMDocLine(), push(match()),
FirstOf(API_DIR, EXAMPLE_DIR, PARAM_DIR), push(match()),
RemainingMDocLine(), push(match()),
Optional(Sequence(
MDocText(),
@ -340,7 +354,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
(DocBlock) peek()))); }
/**
* #### SShortDirective
* #### SShortDirective
* Parses the rule:
*
* SShortDirective =
@ -356,12 +370,12 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
push(curLineNum),
FirstOf(AUTHOR_DIR, ORG_DIR, INCLUDE_DIR, COPYRIGHT_DIR), push(match()),
RemainingSDocLine(),
push(new Directive(match().trim(), popAsString(), popAsInt(),
(DocBlock) peek()))); }
/**
* #### MShortDirective
* #### MShortDirective
* Parses the rule:
*
* MShortDirective =
@ -382,7 +396,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
(DocBlock) peek()))); }
/**
* #### SDocText
* #### SDocText
* Parses the rule:
*
* SDocText = (SDocLineStart !AT RemainingSDocLine)+
@ -399,7 +413,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
addToDocText(match())))); }
/**
* #### MDocText
* #### MDocText
* Parses the rule:
*
* MDocText = (MDocLineStart? !AT RemainingMDocLine)+
@ -417,7 +431,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
addToDocText(match())))); }
/**
* #### SDocLineStart
* #### SDocLineStart
* Parses the rule:
*
* SDocLineStart = SPACE* SDOC_START SPACE?
@ -427,7 +441,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
ZeroOrMore(SPACE), SDOC_START, Optional(SPACE)); }
/**
* #### MDocLineStart
* #### MDocLineStart
* Parses the rule:
*
* MDocLineStart = SPACE* !MDOC_END MDOC_LINE_START SPACE?
@ -437,7 +451,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
ZeroOrMore(SPACE), TestNot(MDOC_END), MDOC_LINE_START, Optional(SPACE)); }
/**
* #### RemainingSDocLine
* #### RemainingSDocLine
* Parses the rule:
*
* RemainingSDocLine = ((!EOL)* EOL) / ((!EOL)+ EOI)
@ -448,10 +462,10 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
Sequence(OneOrMore(NOT_EOL), EOI, incLineCount())); }
/**
* #### RemainingMDocLine
* #### RemainingMDocLine
* Parses the rule:
*
* RemainingMDocLine =
* RemainingMDocLine =
* ((!(EOL / MDOC_END))* EOL) /
* ((!MDOC_END)+)
*/
@ -467,10 +481,10 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
OneOrMore(Sequence(TestNot(MDOC_END), ANY))); }
/**
* #### RemainingCodeLine
* #### RemainingCodeLine
* Parses the rule:
*
* RemainingCodeLine =
* RemainingCodeLine =
* ((!(EOL / MDOC_START / SDocLineStart))* EOL) /
* (!(MDOC_START / SDocLineStart))+
*/
@ -497,6 +511,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
Rule EXAMPLE_DIR = IgnoreCase("example");
Rule INCLUDE_DIR = IgnoreCase("include");
Rule ORG_DIR = IgnoreCase("org");
Rule PARAM_DIR = IgnoreCase("param");
/// #### Hard-coded terminals.
Rule AT = Ch('@').label("AT");
@ -550,7 +565,7 @@ public class JLPPegParser extends BaseParser<Object> implements JLPParser {
docBlock.docTexts.add((DocText) an); }
else { throw new IllegalStateException(); }
return push(docBlock); }
boolean addToCodeBlock(String line) {
CodeBlock codeBlock = (CodeBlock) pop();
codeBlock.lines.put(curLineNum - 1, line);

View File

@ -217,7 +217,7 @@ public class LiterateMarkdownGenerator extends JLPBaseGenerator {
/// Close the table row.
sb.append('</tr>') }
/** @api Emit a [`DocBlock`](jlp://jlp/jdb-labs.com/ast/DocBlock). */
/** @api Emit a [`DocBlock`](jlp://jlp.jdb-labs.com/ast/DocBlock). */
protected String emit(DocBlock docBlock) {
/// Create a queue for the doc block elements, we are going to
/// sort them by type and line number
@ -248,7 +248,7 @@ public class LiterateMarkdownGenerator extends JLPBaseGenerator {
[lineNumber, line] }
/// Sort by line number.
codeLines.sort({ i1, i2 -> i1[0] - i2[0] } as Comparator)
codeLines.sort { i1, i2 -> i1[0] <=> i2[0] }
codeLines = codeLines.collect { arr -> arr[1] }
@ -281,6 +281,9 @@ public class LiterateMarkdownGenerator extends JLPBaseGenerator {
case DirectiveType.Example:
return directive.value
case DirectiveType.Param:
return "" // TODO: can we do better here, even though we're
// not understanding the source yet?
// TODO:
// case DirectiveType.Include:

View File

@ -125,10 +125,10 @@ public class Processor {
/// is more than one file with the same name we will include the
/// file's parent directory as well.
inputFiles.each { file ->
// Get the relative path as path elements.
def relPath = getRelativeFilepath(inputRoot, file)
def pathParts = relPath.split('/') as List
def pathParts = relPath.split('/|\\\\') as List
// We will skip binary files and files we know nothing about.
def fileType = sourceTypeForFile(file)
@ -160,7 +160,7 @@ public class Processor {
// TODO: better error detection and handling
currentDoc.sourceAST = parser.parse(currentDoc.sourceFile.text)
if (currentDoc.sourceAST == null) {
log.warn("Unable to parse '{}'. Ignoring this document.", currentDocId)
badDocs << currentDocId }}
@ -186,7 +186,7 @@ public class Processor {
/// * Write the output to the output directory.
processDocs {
/// Create the path and file object for the output file
String relativePath =
getRelativeFilepath(inputRoot, currentDoc.sourceFile)
@ -238,7 +238,7 @@ public class Processor {
* : Return the link as-is.
*
* *absolute path (starts with `/`)*
* : Returns the link resolved against the output root.
* : Returns the link resolved against the output root.
*
* *relative path (no leading `/`)*
* : Returns the link resolved against the `TargetDoc` passed in.
@ -281,12 +281,12 @@ public class Processor {
case ~/^\w+:.*/: return link
/// Absolute link, resolve relative to the output root.
case ~/^\/.*/:
case ~/^\/.*/:
/// Our link should be the relative path (if needed) plus the
/// link without the leading `/`.
def relPath = getRelativeFilepath(targetDoc.sourceFile, inputRoot)
return (relPath ? "${relPath}/" : "") + link[1..-1]
/// Relative link, resolve using the output root and the source
/// document relative to the input root.
default:
@ -295,7 +295,7 @@ public class Processor {
/**
* #### getRelativeFilepath
* Assuming our current directory is `root`, get the relative path to
* Assuming our current directory is `root`, get the relative path to
* `file`.
* @org jlp.jdb-labs.com/Processor/getRelativeFilepath
*/
@ -304,8 +304,8 @@ public class Processor {
if (!root.isDirectory()) root= root.parentFile
/// Split both paths into their individual parts.
def rootPath = root.canonicalPath.split('/')
def filePath = file.canonicalPath.split('/')
def rootPath = root.canonicalPath.split('/|\\\\')
def filePath = file.canonicalPath.split('/|\\\\')
def relativePath = []
@ -329,17 +329,17 @@ public class Processor {
* #### getCommonParent
* Find the common parent directory to the given files.
* @org jlp.jdb-labs.com/Processor/getCommonParent
*/
*/
public static File getCommonParent(File file1, File file2) {
def path1 = file1.canonicalPath.split('/')
def path2 = file2.canonicalPath.split('/')
def path1 = file1.canonicalPath.split('/|\\\\')
def path2 = file2.canonicalPath.split('/|\\\\')
def newPath = []
// build new commonPath based on matching paths so far
int i = 0
while (i < Math.min(path1.length, path2.length) &&
path1[i] == path2[i]) {
newPath << path2[i]
i++ }
@ -438,8 +438,8 @@ public class Processor {
break
case 'html': case 'xml':
parsers[sourceType] = Parboiled.createParser(
JLPPegParser, '<!--', '-->',
'#$%^&*()_-+=|;:\'",<>?~`', '<<?')
JLPPegParser, '<!--!', '-->',
'!#$%^&*()_-+=|;:\'",<>?~`', '<<?')
break
case 'sql':
parsers[sourceType] = Parboiled.createParser(JLPPegParser,

View File

@ -50,10 +50,15 @@ public class Directive extends ASTNode {
* the [`LinkAnchor`] documentation for more information about link
* anchors.
*
* Param
* : Used to document a parameter to a function, method, or subroutine.
* This is typically used in API documentation, but no generator
* currently knows how to do anything intelligent with this directive.
*
* [`LinkAnchor`]: jlp://jlp.jdb-labs.com/LinkAnchor
*/
public static enum DirectiveType {
Api, Author, Copyright, Example, Include, Org;
Api, Author, Copyright, Example, Include, Org, Param;
public static DirectiveType parse(String typeString) {
valueOf(typeString.toLowerCase().capitalize()) } }