summaryrefslogtreecommitdiff
path: root/sly/live-reload.scm
diff options
context:
space:
mode:
Diffstat (limited to 'sly/live-reload.scm')
-rw-r--r--sly/live-reload.scm55
1 files changed, 35 insertions, 20 deletions
diff --git a/sly/live-reload.scm b/sly/live-reload.scm
index f354fda..cb40e7c 100644
--- a/sly/live-reload.scm
+++ b/sly/live-reload.scm
@@ -26,9 +26,40 @@
#:use-module (sly agenda)
#:use-module (sly coroutine)
#:use-module (sly signal)
- #:export (live-reload))
+ #:export (watch-files
+ with-live-reload))
-(define* (live-reload proc #:optional (polling-interval 120))
+(define* (watch-files files thunk #:optional (polling-interval 120))
+ "Watch FILES, a list of file names, and apply THUNK each time one of
+them changes. A signal is returned that contains the current result
+of THUNK. The POLLING-INTERVAL flag determines how often FILES are
+polled for changes, defaulting to two seconds."
+ (define (current-mtime file-name)
+ (let ((info (stat file-name)))
+ (max (stat:mtime info) (stat:ctime info))))
+
+ (define (max-current-mtime)
+ (and (every file-exists? files)
+ (reduce max 0 (map current-mtime files))))
+
+ (let ((asset (make-signal (thunk))))
+ (coroutine
+ (let loop ((last-mtime (max-current-mtime)))
+ (wait polling-interval)
+ (let ((mtime (max-current-mtime)))
+ (when (cond
+ ;; Some files do not exist anymore, can't reload.
+ ((not mtime) #f)
+ ;; Some files were missing, but are back now.
+ ((and mtime (not last-mtime)) #t)
+ ;; All the files exist and existed last time, too, so
+ ;; check if they have been modified since last time.
+ (else (> mtime last-mtime)))
+ (signal-set! asset (thunk)))
+ (loop mtime))))
+ asset))
+
+(define* (with-live-reload proc #:optional (polling-interval 120))
"Return a new procedure that re-applies PROC whenever the associated
file is modified. The new procedure returns a signal that contains
the return value of PROC. The first argument to PROC must be a
@@ -37,21 +68,5 @@ file name string.
A simple polling method is used to test for updates. Files are polled
every POLLING-INTERVAL ticks (120 by default)."
(lambda (file-name . args)
- (define (load-asset)
- (apply proc file-name args))
-
- (define (current-mtime)
- (let ((info (stat file-name)))
- (max (stat:mtime info) (stat:ctime info))))
-
- (let ((asset (make-signal (load-asset))))
- (coroutine
- (let loop ((last-mtime (current-mtime)))
- (wait polling-interval)
- (let ((mtime (if (file-exists? file-name)
- (current-mtime)
- last-mtime)))
- (when (> mtime last-mtime)
- (signal-set! asset (load-asset)))
- (loop mtime))))
- asset)))
+ (watch-files (list file-name)
+ (lambda () (apply proc file-name args)))))