working CLI tool, versioning support, etc
This commit is contained in:
parent
7b76b7d80f
commit
953e0e696b
10
bin/local_release
Executable file
10
bin/local_release
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
file=./lyng/build/bin/linuxX64/releaseExecutable/lyng.kexe
|
||||||
|
|
||||||
|
./gradlew :lyng:linkReleaseExecutableLinuxX64
|
||||||
|
strip $file
|
||||||
|
upx $file
|
||||||
|
cp $file ~/bin/lyng
|
@ -16,4 +16,6 @@ fun naiveCountHappyNumbers() {
|
|||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( naiveCountHappyNumbers() == 55252 )
|
val found = naiveCountHappyNumbers()
|
||||||
|
println("Found happy numbers: "+found)
|
||||||
|
assert( found == 55252 )
|
||||||
|
2
docs/samples/helloworld.lyng
Normal file
2
docs/samples/helloworld.lyng
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
println("Hello, world!");
|
@ -4,9 +4,11 @@ org.gradle.caching=true
|
|||||||
org.gradle.configuration-cache=true
|
org.gradle.configuration-cache=true
|
||||||
#Kotlin
|
#Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.js.compiler=ir
|
|
||||||
#MPP
|
#MPP
|
||||||
kotlin.mpp.enableCInteropCommonization=true
|
kotlin.mpp.enableCInteropCommonization=true
|
||||||
#Android
|
#Android
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
|
||||||
|
# other
|
||||||
|
kotlin.native.cacheKind.linuxX64=none
|
@ -1,18 +1,24 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.5.2"
|
agp = "8.5.2"
|
||||||
|
clikt = "5.0.3"
|
||||||
kotlin = "2.1.21"
|
kotlin = "2.1.21"
|
||||||
android-minSdk = "24"
|
android-minSdk = "24"
|
||||||
android-compileSdk = "34"
|
android-compileSdk = "34"
|
||||||
kotlinx-coroutines = "1.10.1"
|
kotlinx-coroutines = "1.10.1"
|
||||||
mp_bintools = "0.1.12"
|
mp_bintools = "0.1.12"
|
||||||
firebaseCrashlyticsBuildtools = "3.0.3"
|
firebaseCrashlyticsBuildtools = "3.0.3"
|
||||||
|
okioVersion = "3.10.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }
|
||||||
|
clikt-markdown = { module = "com.github.ajalt.clikt:clikt-markdown", version.ref = "clikt" }
|
||||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
||||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
||||||
mp_bintools = { module = "net.sergeych:mp_bintools", version.ref = "mp_bintools" }
|
mp_bintools = { module = "net.sergeych:mp_bintools", version.ref = "mp_bintools" }
|
||||||
firebase-crashlytics-buildtools = { group = "com.google.firebase", name = "firebase-crashlytics-buildtools", version.ref = "firebaseCrashlyticsBuildtools" }
|
firebase-crashlytics-buildtools = { group = "com.google.firebase", name = "firebase-crashlytics-buildtools", version.ref = "firebaseCrashlyticsBuildtools" }
|
||||||
|
okio = { module = "com.squareup.okio:okio", version.ref = "okioVersion" }
|
||||||
|
okio-fakefilesystem = { module = "com.squareup.okio:okio-fakefilesystem", version.ref = "okioVersion" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
androidLibrary = { id = "com.android.library", version.ref = "agp" }
|
androidLibrary = { id = "com.android.library", version.ref = "agp" }
|
||||||
|
@ -11,7 +11,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.0.1-SNAPSHOT"
|
version = "0.0.5-SNAPSHOT"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
@ -26,7 +26,7 @@ kotlin {
|
|||||||
// iosArm64()
|
// iosArm64()
|
||||||
// iosSimulatorArm64()
|
// iosSimulatorArm64()
|
||||||
linuxX64()
|
linuxX64()
|
||||||
js(IR) {
|
js {
|
||||||
browser()
|
browser()
|
||||||
nodejs()
|
nodejs()
|
||||||
}
|
}
|
||||||
@ -44,12 +44,13 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
|
kotlin.srcDir("$buildDir/generated/buildConfig/commonMain/kotlin")
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
|
||||||
//put your multiplatform dependencies here
|
//put your multiplatform dependencies here
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
api(libs.kotlinx.coroutines.core)
|
||||||
implementation(libs.mp.bintools)
|
api(libs.mp.bintools)
|
||||||
implementation("net.sergeych:mp_stools:1.5.2")
|
api("net.sergeych:mp_stools:1.5.2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val commonTest by getting {
|
val commonTest by getting {
|
||||||
@ -109,3 +110,40 @@ mavenPublishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val projectVersion by project.extra(provider {
|
||||||
|
// Compute value lazily
|
||||||
|
(version as String)
|
||||||
|
})
|
||||||
|
|
||||||
|
val generateBuildConfig by tasks.registering {
|
||||||
|
// Declare outputs safely
|
||||||
|
val outputDir = layout.buildDirectory.dir("generated/buildConfig/commonMain/kotlin")
|
||||||
|
outputs.dir(outputDir)
|
||||||
|
|
||||||
|
val version = projectVersion.get()
|
||||||
|
|
||||||
|
// Inputs: Version is tracked as an input
|
||||||
|
inputs.property("version", version)
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
val packageName = "net.sergeych.lyng.buildconfig"
|
||||||
|
val packagePath = packageName.replace('.', '/')
|
||||||
|
val buildConfigFile = outputDir.get().file("$packagePath/BuildConfig.kt").asFile
|
||||||
|
|
||||||
|
buildConfigFile.parentFile?.mkdirs()
|
||||||
|
buildConfigFile.writeText(
|
||||||
|
"""
|
||||||
|
|package $packageName
|
||||||
|
|
|
||||||
|
|object BuildConfig {
|
||||||
|
| const val VERSION = "$version"
|
||||||
|
|}
|
||||||
|
""".trimMargin()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||||
|
dependsOn(generateBuildConfig)
|
||||||
|
}
|
||||||
|
@ -21,7 +21,6 @@ class Script(
|
|||||||
companion object {
|
companion object {
|
||||||
val defaultContext: Context = Context().apply {
|
val defaultContext: Context = Context().apply {
|
||||||
addFn("println") {
|
addFn("println") {
|
||||||
print("yn: ")
|
|
||||||
for ((i, a) in args.withIndex()) {
|
for ((i, a) in args.withIndex()) {
|
||||||
if (i > 0) print(' ' + a.asStr.value)
|
if (i > 0) print(' ' + a.asStr.value)
|
||||||
else print(a.asStr.value)
|
else print(a.asStr.value)
|
||||||
|
@ -5,6 +5,7 @@ package net.sergeych.lyng
|
|||||||
open class ScriptError(val pos: Pos, val errorMessage: String,cause: Throwable?=null) : Exception(
|
open class ScriptError(val pos: Pos, val errorMessage: String,cause: Throwable?=null) : Exception(
|
||||||
"""
|
"""
|
||||||
$pos: Error: $errorMessage
|
$pos: Error: $errorMessage
|
||||||
|
|
||||||
${pos.currentLine}
|
${pos.currentLine}
|
||||||
${"-".repeat(pos.column)}^
|
${"-".repeat(pos.column)}^
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package net.sergeych.lyng
|
||||||
|
|
||||||
|
import net.sergeych.lyng.buildconfig.BuildConfig
|
||||||
|
|
||||||
|
val LyngVersion = BuildConfig.VERSION
|
@ -6,6 +6,12 @@ import kotlin.test.*
|
|||||||
|
|
||||||
class ScriptTest {
|
class ScriptTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testVersion() {
|
||||||
|
println("--------------------------------------------")
|
||||||
|
println("version = ${LyngVersion}")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseNewlines() {
|
fun parseNewlines() {
|
||||||
fun check(expected: String, type: Token.Type, row: Int, col: Int, src: String, offset: Int = 0) {
|
fun check(expected: String, type: Token.Type, row: Int, col: Int, src: String, offset: Int = 0) {
|
||||||
|
@ -7,10 +7,20 @@ version = "unspecified"
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven("https://maven.universablockchain.com/")
|
||||||
|
maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven")
|
||||||
|
mavenLocal()
|
||||||
|
maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm {
|
||||||
|
binaries {
|
||||||
|
executable {
|
||||||
|
mainClass.set("net.sergeych.lyng_cli.MainKt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
linuxX64 {
|
linuxX64 {
|
||||||
binaries {
|
binaries {
|
||||||
executable()
|
executable()
|
||||||
@ -18,11 +28,21 @@ kotlin {
|
|||||||
}
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":library"))
|
||||||
|
implementation(libs.okio)
|
||||||
|
|
||||||
|
implementation(libs.clikt)
|
||||||
|
|
||||||
|
// optional support for rendering markdown in help messages
|
||||||
|
// implementation(libs.clikt.markdown)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val commonTest by getting {
|
val commonTest by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("test-common"))
|
implementation(kotlin("test-common"))
|
||||||
implementation(kotlin("test-annotations-common"))
|
implementation(kotlin("test-annotations-common"))
|
||||||
|
implementation(libs.okio.fakefilesystem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val linuxX64Main by getting {
|
val linuxX64Main by getting {
|
||||||
|
@ -1,7 +1,110 @@
|
|||||||
package net.sergeych
|
package net.sergeych
|
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.CliktCommand
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.multiple
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.optional
|
||||||
|
import com.github.ajalt.clikt.parameters.options.flag
|
||||||
|
import com.github.ajalt.clikt.parameters.options.option
|
||||||
|
import net.sergeych.lyng.*
|
||||||
|
import okio.FileSystem
|
||||||
|
import okio.Path.Companion.toPath
|
||||||
|
import okio.SYSTEM
|
||||||
|
import okio.buffer
|
||||||
|
import okio.use
|
||||||
|
|
||||||
// common code
|
// common code
|
||||||
|
|
||||||
fun commonCode() {
|
expect fun exit(code: Int)
|
||||||
println("Common code")
|
|
||||||
}
|
val baseContext = Context().apply {
|
||||||
|
addFn("exit") {
|
||||||
|
exit(requireOnlyArg<ObjInt>().toInt())
|
||||||
|
ObjVoid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LyngCLI(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() {
|
||||||
|
|
||||||
|
override val printHelpOnEmptyArgs = true
|
||||||
|
|
||||||
|
val version by option("-v", "--version", help = "Print version and exit").flag()
|
||||||
|
val script by argument(help = "one or more scripts to execute").optional()
|
||||||
|
val execute: String? by option(
|
||||||
|
"-x", "--execute", help = """
|
||||||
|
execute string <text>, the rest of command line is passed to Lyng as ARGV
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
val args by argument(help = "arguments for script").multiple()
|
||||||
|
|
||||||
|
override fun help(context: com.github.ajalt.clikt.core.Context): String =
|
||||||
|
"""
|
||||||
|
The Lyng script language interpreter, language version is $LyngVersion.
|
||||||
|
|
||||||
|
Please refer form more information to the project site:
|
||||||
|
https://gitea.sergeych.net/SergeychWorks/lyng
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
when {
|
||||||
|
version -> {
|
||||||
|
println("Lyng language version ${LyngVersion}")
|
||||||
|
}
|
||||||
|
|
||||||
|
execute != null -> {
|
||||||
|
val objargs = mutableListOf<String>()
|
||||||
|
script?.let { objargs += it }
|
||||||
|
objargs += args
|
||||||
|
baseContext.addConst(
|
||||||
|
"ARGV", ObjList(
|
||||||
|
objargs.map { ObjString(it) }.toMutableList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
launcher {
|
||||||
|
// there is no script name, it is a first argument instead:
|
||||||
|
processErrors {
|
||||||
|
baseContext.eval(execute!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
if (script == null) {
|
||||||
|
println(
|
||||||
|
"""
|
||||||
|
|
||||||
|
Error: no script specified.
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
echoFormattedHelp()
|
||||||
|
} else {
|
||||||
|
baseContext.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList()))
|
||||||
|
launcher { executeFile(script!!) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun executeFile(fileName: String) {
|
||||||
|
val text = FileSystem.SYSTEM.source(fileName.toPath()).use { fileSource ->
|
||||||
|
fileSource.buffer().use { bs ->
|
||||||
|
bs.readUtf8()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processErrors {
|
||||||
|
Compiler().compile(Source(fileName, text)).execute(baseContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun processErrors(block: suspend () -> Unit) {
|
||||||
|
try {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
catch (e: ScriptError) {
|
||||||
|
println("\nError executing the script:\n$e\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
7
lyng/src/jvmMain/kotlin/Common.jvm.kt
Normal file
7
lyng/src/jvmMain/kotlin/Common.jvm.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package net.sergeych
|
||||||
|
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
actual fun exit(code: Int) {
|
||||||
|
exitProcess(code)
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
import net.sergeych.commonCode
|
|
||||||
|
|
||||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
|
||||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
|
||||||
fun main() {
|
|
||||||
val name = "Kotlin"
|
|
||||||
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
|
|
||||||
// to see how GIGA IDE suggests fixing it.
|
|
||||||
println("Hello, native " + name + "!")
|
|
||||||
|
|
||||||
commonCode()
|
|
||||||
|
|
||||||
for (i in 1..5) {
|
|
||||||
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
|
|
||||||
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
|
|
||||||
println("i = $i")
|
|
||||||
}
|
|
||||||
}
|
|
9
lyng/src/jvmMain/kotlin/net/sergeych/lyng_cli/Main.kt
Normal file
9
lyng/src/jvmMain/kotlin/net/sergeych/lyng_cli/Main.kt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package net.sergeych.lyng_cli
|
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.main
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import net.sergeych.LyngCLI
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
LyngCLI({ runBlocking { it() } }).main(args)
|
||||||
|
}
|
@ -1,18 +1,7 @@
|
|||||||
import net.sergeych.commonCode
|
import com.github.ajalt.clikt.core.main
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import net.sergeych.LyngCLI
|
||||||
|
|
||||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
fun main(args: Array<String>) {
|
||||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
LyngCLI( { runBlocking { it() } }).main(args)
|
||||||
fun main() {
|
|
||||||
val name = "Kotlin"
|
|
||||||
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
|
|
||||||
// to see how GIGA IDE suggests fixing it.
|
|
||||||
println("Hello, native " + name + "!")
|
|
||||||
|
|
||||||
commonCode()
|
|
||||||
|
|
||||||
for (i in 1..5) {
|
|
||||||
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
|
|
||||||
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
|
|
||||||
println("i = $i")
|
|
||||||
}
|
|
||||||
}
|
}
|
7
lyng/src/nativeMain/kotlin/Common.native.kt
Normal file
7
lyng/src/nativeMain/kotlin/Common.native.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package net.sergeych
|
||||||
|
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
actual fun exit(code: Int) {
|
||||||
|
exitProcess(code)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user