#lang racket (require racket/rerequire) ;; (require "signatures/plugin-sig.rkt") (provide (all-defined-out)) (define-signature plugin^ (description ; string? load ; (-> void?) unload ; (-> void?) dependencies)) (struct Plugin [name description dependencies load unload] #:transparent) (define (mod->unit-name name) (string->symbol (format "~a@" (match name [(regexp #rx"([^/]+)\\.rkt" (list _ base)) base])))) (define loaded-plugins (make-hash)) (define (load-plugin name) (dynamic-rerequire name #:verbosity 'none) (define-values/invoke-unit (dynamic-require name (mod->unit-name name)) (import) (export plugin^)) (load) (define p (Plugin name description dependencies load unload)) (hash-set! loaded-plugins name p) p) (define (stale-plugin? p) (not (empty? (dynamic-rerequire (Plugin-name p) #:verbosity 'none)))) (define (unload-plugin p) (begin0 ((Plugin-unload p)) (hash-remove! loaded-plugins (Plugin-name p)))) (define (reload-plugin p) (unload-plugin p) (load-plugin (Plugin-name p))) (define (load-directory dir) (for ([p (in-directory dir)]) (load-plugin p))) (module+ main (define targets '("plugins/hello.rkt")) (displayln "Starting up...") (for ([p targets]) (load-plugin p)) (printf "loaded plugins: ~v\n" (hash-keys loaded-plugins)) (displayln "Shutting down...") (for ([p (in-hash-values (hash-copy loaded-plugins))]) (unload-plugin p))) ;; example plugin below!!! #lang racket/unit (require "../main.rkt") (import) (export plugin^) (define dependencies '(sayer)) (define version "0.1") (define description "Greet users") (define (load) (printf "Hello ~a loaded.\n" version)) (define (unload) (printf "Hello ~a unloaded.\n" version))