+(define (serve-dynamic-gemini path)
+ (with-input-from-file path
+ (lambda ()
+ (let loop ((c (peek-char)))
+ (if (eof-object? c)
+ 'done
+ (begin
+ (if (eq? c #\,)
+ (begin
+ (read-char)
+ (serve-dynamic-element (read) (pathname-directory path))
+ (read-line))
+ (print (read-line)))
+ (loop (peek-char))))))))
+
+(define (serve-dynamic-element element working-directory)
+ (match element
+ (('eval expression)
+ (with-current-working-directory
+ working-directory
+ (lambda ()
+ (eval expression))))
+ (('shell command)
+ (with-current-working-directory
+ working-directory
+ (lambda ()
+ (let-values (((in-port out-port id) (process command)))
+ (let ((string (read-string #f in-port)))
+ (unless (eof-object? string)
+ (print string))
+ (close-input-port in-port)
+ (close-output-port out-port))))))
+ (else (error "Unknown element type."))))
+
+(define (with-current-working-directory directory thunk)
+ (let ((old-wd (current-directory))
+ (result 'none))
+ (condition-case
+ (begin
+ (change-directory directory)
+ (set! result (thunk))
+ (change-directory old-wd)
+ result)
+ (o (exn)
+ (change-directory old-wd)
+ (signal o)))))