test_reload.icl 1.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
module test_reload

import StdBool
import StdClass
import StdFile
import StdFunc
import StdInt
import StdString
import Data.Either
import Data.Maybe
import Inotify

/** test_reload
 *
 * This module will watch the directory it is in. Whenever the attributes of
 * its own binaries change, it will exit. Hence, putting it in a loop:
 *
 *     while :; do ./test_reload; done
 *
 * will give a program that automatically reloads itself when its binary has
 * changed.
 *
 * Test it by running `make run_test_reload`, then editing `changeme` below and
 * running `make test_reload` to recompile.
25
 * You can also use `touch test_reload`.
26 27 28 29 30 31 32 33 34 35 36
 */

my_name  :== "test_reload"
my_dir   :== "."
changeme :== 42
verbose  :== False

:: Void = Void

Start w
# (io,w)             = stdio w
37
# io = io          <<< changeme <<< " (edit changeme and recompile)\n"
38 39
# (ok,w)             = fclose io w
# (Just inot)        = inotify_init Void
40
# (Right watch,inot) = inotify_add_watch reload IN_ATTRIB my_dir inot
41 42 43 44 45 46 47 48
# (inot,w)           = inotify_loop_forever inot w
= inotify_close inot
where
	reload :: !INEvent (Maybe String) Void !*World -> *(Void, *World)
	reload ev mbName _ w
		# w = echo (\f -> f <<< "event: " <<< ev <<< "; " <<< mbName) w
		| isNothing mbName = (Void, w)
		# (Just name) = mbName
49
		| inotify_is_event IN_ATTRIB ev && name == my_name
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
			# w = echo (\f -> f <<< "reloading...") w
			# w = exit 127 w
			= (Void, w)
		= (Void, w)

	echo :: (*File -> *File) *World -> *World
	echo f w
		# (io,w) = stdio w
		# io     = if verbose (flip (<<<) "\n" o f) id io
		# (ok,w) = fclose io w
		= w
	
	exit :: !Int !*World -> *World
	exit c w = code {
		ccall exit "I:V:A"
	}

instance <<< (Maybe x) | <<< x
where
	(<<<) f Nothing  = f
	(<<<) f (Just x) = f <<< x