diff --git a/app/build.gradle b/app/build.gradle index 2fd451c..e2d4714 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,25 @@ dependencies { compile "com.xenomachina:kotlin-argparser:2.0.7" } +ext.generatedResourcesDir = file("$buildDir/generated-resources") +task generateResources { + doLast { + generatedResourcesDir.mkdir() + generatePresetsIndex() + } +} +sourceSets.main.output.dir generatedResourcesDir, builtBy: generateResources + +private void generatePresetsIndex() { + def presets = new File(sourceSets.main.resources.srcDirs[0], "presets") + def index = new PrintWriter(new FileWriter(new File(generatedResourcesDir, "presets.index"))) + presets.listFiles().each { index.println(it.name) } + index.close() +} + jar { + dependsOn generateResources + zip64 true manifest { attributes 'Main-Class': 'io.smnp.SMNPKt' diff --git a/app/src/main/kotlin/io/smnp/SMNP.kt b/app/src/main/kotlin/io/smnp/SMNP.kt index ba9a365..33626de 100644 --- a/app/src/main/kotlin/io/smnp/SMNP.kt +++ b/app/src/main/kotlin/io/smnp/SMNP.kt @@ -7,6 +7,7 @@ import io.smnp.cli.model.enumeration.ModulesPrintMode import io.smnp.environment.DefaultEnvironment import io.smnp.ext.DefaultModuleRegistry import io.smnp.interpreter.DefaultInterpreter +import io.smnp.preset.PresetProvider.providePresetCode import io.smnp.type.model.Value fun main(args: Array): Unit = mainBody { @@ -19,6 +20,7 @@ fun main(args: Array): Unit = mainBody { when { file != null -> interpreter.run(file!!, environment, printTokens, printAst, dryRun) code != null -> interpreter.run(code!!, environment, printTokens, printAst, dryRun) + preset != null -> interpreter.run(providePresetCode(preset!!), environment, printTokens, printAst, dryRun) else -> null }?.let { it as DefaultEnvironment }?.let { disposedEnvironment -> if(loadedModules != null) { diff --git a/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt b/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt index 1b0a30c..3abdc45 100644 --- a/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt +++ b/app/src/main/kotlin/io/smnp/cli/model/entity/Arguments.kt @@ -3,6 +3,7 @@ package io.smnp.cli.model.entity import com.xenomachina.argparser.ArgParser import com.xenomachina.argparser.default import io.smnp.cli.model.enumeration.ModulesPrintMode +import io.smnp.preset.PresetProvider import java.io.File class Arguments(parser: ArgParser) { @@ -30,6 +31,14 @@ class Arguments(parser: ArgParser) { } } } + val preset by parser.storing( + "-p", + "--preset", + argName = "NAME", + help = "load preset by name and execute it. Preset is a predefined snippet of SMNP code that allows user to " + + "perform some useful action without having to script it himself. Presets are located in SMNP executable JAR " + + "file. Available presets: ${PresetProvider.presets.joinToString()}" + ).default(null) val code by parser.storing("-c", "--code", help = "inline code to be executed").default(null) val file by parser.positional( diff --git a/app/src/main/kotlin/io/smnp/error/PresetException.kt b/app/src/main/kotlin/io/smnp/error/PresetException.kt new file mode 100644 index 0000000..2c79294 --- /dev/null +++ b/app/src/main/kotlin/io/smnp/error/PresetException.kt @@ -0,0 +1,3 @@ +package io.smnp.error + +class PresetException(message: String?) : SmnpException("Preset error", message) \ No newline at end of file diff --git a/app/src/main/kotlin/io/smnp/preset/PresetProvider.kt b/app/src/main/kotlin/io/smnp/preset/PresetProvider.kt new file mode 100644 index 0000000..a162a5b --- /dev/null +++ b/app/src/main/kotlin/io/smnp/preset/PresetProvider.kt @@ -0,0 +1,24 @@ +package io.smnp.preset + +import io.smnp.error.PresetException +import java.io.File +import java.nio.file.Paths + +object PresetProvider { + private const val PRESETS_DIR = "presets" + private val classLoader = javaClass.classLoader + + val presets: List + get() = classLoader + .getResource("presets.index") + ?.readText() + ?.trim() + ?.split("\n") + ?.map { File(it).nameWithoutExtension } + ?: throw RuntimeException("Presets index not found") + + fun providePresetCode(name: String) = classLoader + .getResource(Paths.get(PRESETS_DIR, "$name.mus").toString()) + ?.readText() + ?: throw PresetException("Preset with name '$name' does not exist") +} \ No newline at end of file diff --git a/app/src/main/resources/presets/alert.mus b/app/src/main/resources/presets/alert.mus new file mode 100644 index 0000000..873ba1f --- /dev/null +++ b/app/src/main/resources/presets/alert.mus @@ -0,0 +1,16 @@ +import smnp.music.tools; +import smnp.text; + +infinite = __param__.containsKey("cycles"); +melody = __param__.getOrDefault("melody", "beep"); + +if(infinite) { + cycles = __param__.get("cycles").toInt(); + if(typeOf(cycles) != "int") { + throw "Expected 'cycles' to be of int type"; + } + + alert(cycles, melody); +} else { + alert(melody); +} \ No newline at end of file diff --git a/app/src/main/resources/presets/metronome.mus b/app/src/main/resources/presets/metronome.mus new file mode 100644 index 0000000..3c8b1ba --- /dev/null +++ b/app/src/main/resources/presets/metronome.mus @@ -0,0 +1,15 @@ +import smnp.music.tools; +import smnp.text; + +bpm = __param__.getOrDefault("bpm", "120").toInt(); +if(typeOf(bpm) != "int") { + throw "Expected 'bpm' to be of int type"; +} + +beats = __param__.getOrDefault("beats", "4").toInt(); +if(typeOf(beats) != "int") { + throw "Expected 'beats' to be of int type"; +} + +metronome(bpm, beats); + diff --git a/modules/collection/src/main/resources/map.mus b/modules/collection/src/main/resources/map.mus index 67b5831..8fcc73c 100644 --- a/modules/collection/src/main/resources/map.mus +++ b/modules/collection/src/main/resources/map.mus @@ -18,4 +18,12 @@ extend map as this { function isNotEmpty() { return not this.isEmpty(); } + + function getOrDefault(key, default) { + if(this.containsKey(key)) { + return this.get(key); + } + + return default; + } } \ No newline at end of file diff --git a/modules/text/src/main/resources/main.mus b/modules/text/src/main/resources/main.mus index b18c609..c680d59 100644 --- a/modules/text/src/main/resources/main.mus +++ b/modules/text/src/main/resources/main.mus @@ -59,7 +59,7 @@ extend string as this { output = -output; } - return output; + return Int(output); } function substring(startIndex: int, endIndex: int) {