summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <romangraef@gmail.com>2021-08-13 00:54:39 +0200
committernea <romangraef@gmail.com>2021-08-13 00:54:39 +0200
commit06d9212e5901b8b73e17bb8938b0c4542a42770b (patch)
tree15ca09200aea736f4342d34d29a08f343e4d2c68
parent2ee4b7c2bef9f80ed12e58bc3cdbb965299920e1 (diff)
downloadwebos-06d9212e5901b8b73e17bb8938b0c4542a42770b.tar.gz
webos-06d9212e5901b8b73e17bb8938b0c4542a42770b.tar.bz2
webos-06d9212e5901b8b73e17bb8938b0c4542a42770b.zip
test basics
-rw-r--r--build.gradle.kts29
-rw-r--r--src/main/kotlin/Path.kt75
-rw-r--r--src/main/kotlin/WebOS.kt80
-rw-r--r--src/main/kotlin/files.kt86
-rw-r--r--src/main/kotlin/util/sequence.kt5
-rw-r--r--src/main/resources/index.html17
6 files changed, 23 insertions, 269 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index 0986f02..06e8b90 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,15 +1,32 @@
plugins {
- kotlin("js") version "1.5.21"
+ kotlin("multiplatform") version "1.5.21"
+ //id("io.kotest.multiplatform") version "5.0.0.3"
}
repositories {
- mavenCentral()
+ mavenCentral()
+ maven("https://oss.sonatype.org/content/repositories/snapshots")
}
+val kotestVersion: String by project
+
kotlin {
- js {
- browser {
+ targets {
+ js(IR) {
+ nodejs { }
+ browser { }
+ }
+ }
+ sourceSets {
+ val jsMain by getting {
- }
- }
+ }
+ val jsTest by getting {
+ dependencies {
+ implementation("io.kotest:kotest-assertions-core:4.6.1")
+ implementation("io.kotest:kotest-framework-api:4.6.1")
+ implementation("io.kotest:kotest-framework-engine:4.6.1")
+ }
+ }
+ }
}
diff --git a/src/main/kotlin/Path.kt b/src/main/kotlin/Path.kt
deleted file mode 100644
index 0e209cf..0000000
--- a/src/main/kotlin/Path.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-import util.expandWith
-
-sealed interface Path {
- val parts: List<String>
- fun toAbsolutePath(relativeTo: Absolute): Absolute {
- return relativeTo.resolve(this)
- }
-
- fun resolve(path: Path): Path
-
- companion object {
- val root = Absolute(listOf())
-
- fun ofShell(string: String, userHome: Absolute): Path =
- ofShell(string.split("/"), userHome)
-
- fun ofShell(vararg parts: String, userHome: Absolute): Path =
- ofShell(parts.toList(), userHome)
-
- fun of(vararg parts: String): Path =
- of(parts.toList())
-
- fun of(string: String): Path =
- of(string.split("/"))
-
- fun ofShell(parts: List<String>, userHome: Absolute): Path {
- if (parts.firstOrNull() == "~")
- return userHome.resolve(Relative(parts.subList(1, parts.size).filter { it.isNotEmpty() }))
- return of(parts)
- }
-
- fun of(parts: List<String>): Path {
- if (parts.isEmpty())
- return root
- if (parts[0] == "") // Starts with a /
- return Absolute(parts.subList(1, parts.size).filter { it.isNotEmpty() })
- return Relative(parts.filter { it.isNotEmpty() })
- }
- }
-
- data class Relative internal constructor(override val parts: List<String>) : Path {
- override fun resolve(path: Path): Path {
- if (path is Absolute) return path
- return Relative(this.parts + path.parts)
- }
- }
-
- data class Absolute internal constructor(override val parts: List<String>) : Path {
- override fun resolve(path: Path): Absolute {
- if (path is Absolute) return path
- return Absolute(this.parts + path.parts)
- }
-
- fun relativize(path: Path): Relative = when (path) {
- is Relative -> path
- is Absolute -> {
- var commonPrefix = true
- val partList = mutableListOf<String>()
- var returns = 0
- for ((idx, part) in path.parts.withIndex()) {
- if (idx < this.parts.size) {
- if (this.parts[idx] == part && commonPrefix) {
- continue
- } else {
- commonPrefix = false
- returns++
- }
- }
- partList.add(part)
- }
- Relative(List(returns) { ".." } + partList)
- }
- }
- }
-}
diff --git a/src/main/kotlin/WebOS.kt b/src/main/kotlin/WebOS.kt
deleted file mode 100644
index 9160a75..0000000
--- a/src/main/kotlin/WebOS.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-import kotlinx.browser.document
-import kotlinx.browser.window
-import org.w3c.dom.Element
-import org.w3c.dom.asList
-
-fun main() {
- console.log("Hello from Kotlin")
- val webos = WebOS()
- document.body?.addEventListener("load", {
- document.body?.querySelectorAll(".webosconsole")?.asList()?.forEach {
- if (it !is Element) return@forEach
- webos.registerConsole(it)
- }
- })
-}
-
-data class CharacterRun(val text: String, val color: String)
-
-abstract class Activity(val console: Console) {
- abstract fun render(columns: Int, rows: Int): List<List<CharacterRun>>
-}
-
-class Console(val os: WebOS, val renderElement: Element?) {
- val isVirtual get() = renderElement == null
- val activityStack = ArrayDeque<Activity>()
-
- var columns: Int = 80
- var rows: Int = 46
-
- var shouldRerender = true
-
- var currentUser: User? = null
-
- private var _workingDirectory: Path.Absolute? = null
-
- var workingDirectory: Path.Absolute
- get() = _workingDirectory ?: currentUser?.homeDirectory ?: Path.root
- set(value) {
- _workingDirectory = value
- }
-
- fun openActivity(activity: Activity) {
- activityStack.addLast(activity)
- invalidateRender()
- }
-
- fun render() {
- if (renderElement == null) return
- if (!shouldRerender) return
- shouldRerender = false
- activityStack.last()
- }
-
- fun invalidateRender() {
- shouldRerender = true
- window.requestAnimationFrame { render() }
- }
-
- fun resize(newColumns: Int, newRows: Int) {
- invalidateRender()
- }
-
- // TODO: Handle resizes of the renderElement
-
-}
-
-class WebOS {
- private val _consoles = mutableListOf<Console>()
- val consoles get() = _consoles.toList()
- val files = IOHandler()
- fun registerConsole(element: Element) {
- _consoles.add(Console(this, element))
- }
-}
-
-data class User(
- val name: String,
- val homeDirectory: Path.Absolute
-)
-
diff --git a/src/main/kotlin/files.kt b/src/main/kotlin/files.kt
deleted file mode 100644
index 990ae7e..0000000
--- a/src/main/kotlin/files.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-class IOHandler {
- val mounts = mutableListOf<Mount>()
- fun mount(absolutePath: Path.Absolute, fileSystem: FileSystem) {
- if (mounts.any { it.mountPoint == absolutePath })
- return // TODO sensible error message handling
- mounts += Mount(absolutePath, fileSystem)
- }
-
- fun unmount(mountPoint: Path.Absolute) {
- mounts.removeAll { it.mountPoint == mountPoint }
- }
-
- fun <T> findMountFor(
- workingDirectory: Path.Absolute,
- path: Path,
- operation: FileSystem.(relativePath: Path) -> T
- ): T {
- val absolutPath = path.toAbsolutePath(workingDirectory)
- val mount = mounts.filter {
- it.mountPoint.parts.zip(absolutPath.parts).all { (a, b) -> a == b }
- }.maxByOrNull { it.mountPoint.parts.size } ?: throw IllegalStateException("No mount present")
- return mount.fileSystem.operation(
- Path.Absolute(
- absolutPath.parts.subList(
- mount.mountPoint.parts.size,
- absolutPath.parts.size
- )
- ) // TODO: unangenehm
- )
- }
-
- fun findINode(absolutePath: Path.Absolute): INode {
- val mount = mounts.filter {
- it.mountPoint.parts.zip(absolutePath.parts).all { (a, b) -> a == b }
- }.maxByOrNull { it.mountPoint.parts.size } ?: throw IllegalStateException("No mount present")
- val iNode = mount.fileSystem.getINode(absolutePath.relativize(mount.mountPoint))
- return when (iNode) {
- is INodeResult.File -> iNode.op
- is INodeResult.ResolveAgain -> findINode(absolutePath.resolve(iNode.relativeToOriginal))
- }
- }
-
- fun read(workingDirectory: Path.Absolute, path: Path): ReadResult =
- findMountFor(workingDirectory, path) { read(it) }
-
- fun write(workingDirectory: Path.Absolute, path: Path, data: ByteArray): Unit =
- findMountFor(workingDirectory, path) { write(it, data) }
-
- fun stat(workingDirectory: Path.Absolute, path: Path): Unit =
- findMountFor(workingDirectory, path) { stat(it) }
-}
-
-interface INode {
- val fs: FileSystem
-}
-
-sealed interface INodeResult {
- class File(val op: INode) : INodeResult
- class ResolveAgain(val relativeToOriginal: Path): INodeResult
-}
-
-interface FileSystem {
- fun getINode(relativePath: Path.Relative): INodeResult
- fun read(relativePath: Path): ReadResult
- fun write(path: Path, data: ByteArray): Unit // Write result
- fun stat(path: Path): Unit // TODO Stat result
-}
-
-sealed class ReadResult {
- class Success(val text: String) : ReadResult()
- object NotFound : ReadResult()
- object NoAccess : ReadResult()
-}
-
-data class Mount(
- val mountPoint: Path.Absolute,
- val fileSystem: FileSystem
-)
-
-data class Stat(
- val exists: Boolean,
- var owner: User,
- val created: Long,
- val edited: Long,
- val size: Long
-)
diff --git a/src/main/kotlin/util/sequence.kt b/src/main/kotlin/util/sequence.kt
deleted file mode 100644
index 72b07dc..0000000
--- a/src/main/kotlin/util/sequence.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package util
-
-fun <T> Iterable<T>.expandWith(t: T): Sequence<T> =
- this.asSequence() + generateSequence { t }.asSequence()
-
diff --git a/src/main/resources/index.html b/src/main/resources/index.html
deleted file mode 100644
index 719506b..0000000
--- a/src/main/resources/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport"
- content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>WebOs</title>
-</head>
-<body>
-<noscript>tf you don't have js enabled? do you still live in the stone ages or what?</noscript>
-<div id="content">
-
-</div>
-<script src="/webos.js"></script>
-</body>
-</html>