Content Inclusion
ReadingBat supports several mechanisms for composing content from multiple sources. This is useful when you want to combine your own challenges with community-contributed content or split large challenge sets across repositories.
Merging Language Groups with Unary Plus
Use the + operator to merge all challenge groups from an external language group
into the current content:
val unaryPlusLanguageExample =
readingBatContent {
// Define Python content in a separate variable
val externalPython =
readingBatContent {
repo = FileSystemSource("./")
python {
srcPath = "python"
group("External-Warmup") {
packageName = "warmup1"
includeFilesWithType = "*.py" returns BooleanType
}
}
}
repo = FileSystemSource("./")
java {
group("Warmup-1") {
packageName = "warmup1"
includeFiles = "*.java"
}
}
// Merge external Python content using unary plus
+externalPython.python
}
The +externalPython.python line merges all Python challenge groups from
externalPython into the current ReadingBatContent.
Including with Name Prefixes
When merging content that might have conflicting group names, use the include()
function with a namePrefix parameter:
val includeWithPrefixExample =
readingBatContent {
val community =
readingBatContent {
repo = GitHubRepo(Organization, "readingbat", "readingbat-java-content")
java {
group("Warmup-1") {
packageName = "warmup1"
includeFiles = "*.java"
}
}
}
repo = FileSystemSource("./")
java {
group("My-Warmup") {
packageName = "warmup1"
includeFiles = "*.java"
}
}
// Include with a name prefix to avoid group name collisions
include(community.java, namePrefix = "Community-")
}
The community "Warmup-1" group becomes "Community-Warmup-1", avoiding collision with your own "My-Warmup" group.
Conditional Content
Since the DSL is plain Kotlin code, you can use conditionals to vary content based on environment:
val conditionalContent =
readingBatContent {
repo = FileSystemSource("./")
java {
group("Warmup-1") {
packageName = "warmup1"
includeFiles = "*.java"
}
// Only include advanced challenges in production
if (System.getenv("IS_PRODUCTION")?.toBoolean() == true) {
group("Advanced-1") {
packageName = "advanced1"
includeFiles = "*.java"
}
}
}
}
The isProduction() and isTesting() functions are also available within DSL
files for this purpose:
if (isProduction()) {
// Include production-only groups
}
if (isTesting()) {
// Include test-only groups
}
Remote Content Loading
For content defined in remote Content.kt files, you can load and evaluate remote
DSL scripts using the ContentSource extension method. This fetches the remote file,
evaluates it as a Kotlin script, and returns the resulting ReadingBatContent:
val remote = GitHubContent(
ownerType = Organization,
ownerName = "readingbat",
repoName = "readingbat-java-content",
fileName = "Content.kt",
)
// Load the remote DSL and merge its Java content
val externalContent = remote.evaluate(this, "content")
include(externalContent.java)
Note
The second parameter ("content") is the variable name in the remote script that
holds the ReadingBatContent result. The method fetches the file, runs it as a
Kotlin script, and extracts the content variable.
Inclusion Methods Summary
| Method | Use Case |
|---|---|
+languageGroup |
Merge an entire language group's challenges |
include(languageGroup, prefix) |
Merge with a name prefix to avoid collisions |
remote.evaluate(this) |
Load and evaluate a remote Content.kt file |
| Conditional logic | Vary content based on environment or configuration |