Add cancel / triggerChange extension methods to watcher functions

This commit is contained in:
Edwin Jakobs
2019-09-08 19:48:21 +02:00
parent ab1a1b601d
commit f40655e113

View File

@@ -11,8 +11,6 @@ import java.nio.file.WatchKey
import kotlin.concurrent.thread import kotlin.concurrent.thread
class FileWatcher(private val program: Program, val file: File, private val onChange: (File) -> Unit) { class FileWatcher(private val program: Program, val file: File, private val onChange: (File) -> Unit) {
init {
watchThread
val path = file.absoluteFile.toPath() val path = file.absoluteFile.toPath()
val parent = path.parent val parent = path.parent
val key = pathKeys.getOrPut(parent) { val key = pathKeys.getOrPut(parent) {
@@ -21,12 +19,18 @@ class FileWatcher(private val program: Program, val file: File, private val onCh
SensitivityWatchEventModifier.HIGH SensitivityWatchEventModifier.HIGH
) )
} }
init {
watchThread
watching.getOrPut(path) { watching.getOrPut(path) {
mutableListOf() mutableListOf()
}.add(this) }.add(this)
keyPaths.getOrPut(key) { parent } keyPaths.getOrPut(key) { parent }
} }
fun stop() {
watching[path]?.remove(this)
}
internal fun triggerChange() { internal fun triggerChange() {
program.launch { program.launch {
onChange(file) onChange(file)
@@ -34,20 +38,45 @@ class FileWatcher(private val program: Program, val file: File, private val onCh
} }
} }
private val watchers = mutableMapOf< ()->Any, FileWatcher>()
fun <T> watchFile(program: Program, file: File, transducer: (File) -> T): () -> T { fun <T> watchFile(program: Program, file: File, transducer: (File) -> T): () -> T {
var result = transducer(file) var result = transducer(file)
FileWatcher(program, file) { val watcher = FileWatcher(program, file) {
try { try {
result = transducer(file) result = transducer(file)
} catch (e: Throwable) { } catch (e: Throwable) {
e.printStackTrace() e.printStackTrace()
} }
} }
return {
val function = {
result result
} }
@Suppress("UNCHECKED_CAST")
watchers[function as ()->Any] = watcher
return function
} }
/**
* Stops the watcher
*/
fun <T> (()->T).stop() {
@Suppress("UNCHECKED_CAST")
watchers[this as ()->Any]?.stop()
}
/**
* Triggers reload
*/
fun <T> (()->T).triggerChange() {
@Suppress("UNCHECKED_CAST")
watchers[this as ()->Any]?.triggerChange()
}
@JvmName("programWatchFile") @JvmName("programWatchFile")
fun <T> Program.watchFile(file: File, transducer: (File) -> T): () -> T = watchFile(this, file, transducer) fun <T> Program.watchFile(file: File, transducer: (File) -> T): () -> T = watchFile(this, file, transducer)
@@ -67,9 +96,8 @@ private val watchThread by lazy {
key.pollEvents().forEach { key.pollEvents().forEach {
val contextPath = it.context() as Path val contextPath = it.context() as Path
val fullPath = path?.resolve(contextPath) val fullPath = path?.resolve(contextPath)
watching[fullPath]?.forEach { watching[fullPath]?.forEach { w ->
w.triggerChange()
it.triggerChange()
} }
} }
key.reset() key.reset()
@@ -82,12 +110,12 @@ fun main() {
it.readText() it.readText()
} }
a.stop()
a.triggerChange()
while (true) { while (true) {
println(a()) println(a())
Thread.sleep(2000) Thread.sleep(2000)
} }
} }