Files
rktplayer/misc/utils.rkt
T

249 lines
6.6 KiB
Racket

#lang racket/base
(require racket/gui
racket/contract
xml
xml/xexpr
simple-log
)
(provide ww-connect
make-delayed-reactor
mktable
simple-row-formatter
while
open-file-manager
dbg-rktplayer
err-rktplayer
info-rktplayer
warn-rktplayer
fatal-rktplayer
sync-log-rktplayer
(all-from-out simple-log)
list-drop!
path-equal?
make-select-list
new-id
check/c
check/c*
(all-from-out racket/contract)
)
(sl-def-log rktplayer)
(define-syntax check/c
(syntax-rules ()
((_ for-cl for-func name contract-expr)
(unless (contract-first-order-passes? contract-expr name)
(raise-argument-error
(string->symbol (format "~a:~a" 'for-cl 'for-func))
(format "~s" 'contract-expr)
name)))
((_ for-cl name contract-expr)
(unless (contract-first-order-passes? contract-expr name)
(raise-argument-error
'for-cl
(format "~s" 'contract-expr)
name)))
((_ name contract-expr)
(unless (contract-first-order-passes? contract-expr name)
(error
(format "~a: expected ~a, got ~a"
'name
'contract-expr
name))))))
(define-syntax check/c*-internal
(syntax-rules ()
((_ for-cl (for-func name type?))
(check/c for-cl for-func name type?))
((_ for-cl (name type?))
(check/c for-cl name type?))))
(define-syntax check/c*-internal-func
(syntax-rules ()
((_ for-cl for-func (name type?))
(check/c for-cl for-func name type?))))
(define-syntax check/c*
(syntax-rules ()
((_ (for-cl for-func) check ...)
(begin
(check/c*-internal-func for-cl for-func check)
...))
((_ for-cl check ...)
(begin
(check/c*-internal for-cl check)
...))))
(define-syntax while
(syntax-rules ()
((_ cond body ...)
(letrec ((while-f (lambda (last-result)
(if cond
(let ((last-result (begin
body
...)))
(while-f last-result))
last-result))))
(while-f #f))
)
))
(define-syntax ww-connect
(syntax-rules (this)
((_ id method)
(begin
(send this bind! id 'click
(λ (el evt data)
(send this method)))
(send this element id))
)
)
)
(define (list-drop! l idx)
(if (null? l)
l
(if (= idx 0)
(cdr l)
(cons (car l) (list-drop! (cdr l) (- idx 1))))))
(define (make-delayed-reactor seconds closure)
(let* ((last-val #f)
(last-time -1)
(interval-ms (* seconds 1000))
(timeout-check (λ ()
(let ((ms (current-milliseconds)))
(unless (= last-time -1)
(when (> ms (+ last-time interval-ms))
(set! last-time -1)
(closure last-val))))))
(timer (new timer% [notify-callback timeout-check] [interval 100]))
)
(λ (val)
(dbg-rktplayer "delayed reactor: ~a" val)
(set! last-val val)
(set! last-time (current-milliseconds))
)))
(define (simple-row-formatter row)
(map (λ (e) (list 'td (format "~a" e))) row))
(define (mktable l table-class row-formatter)
(xexpr->string
(append
(list 'table (list (list 'class (format "~a" table-class))))
(map (λ (row)
(let ((row-id (car row)))
(append (list 'tr (list (list 'id (format "~a" row-id))))
(row-formatter (cdr row)))))
l)
; Add one empty tr
(list (list 'tr (list (list 'class "unresponsive"))))
)
)
)
(define (open-file-manager path*)
(let* ((path (normal-case-path path*))
(folder (if (path? path) (path->string path) path))
(do-open (λ (prg arg)
(let ((exe (find-executable-path prg)))
(dbg-rktplayer "(process* ~a ~a)" exe arg)
(process* exe arg))))
)
(dbg-rktplayer "open-file-manager ~a" folder)
(case (system-type 'os)
[(windows) (do-open "explorer.exe" folder)]
[(macosx) (do-open "open" folder)]
[else (do-open "xdg-open" folder)]))
)
(define (path-equal? p1 p2)
(let ((p1* (build-path p1))
(p2* (build-path p2))
)
(let ((e1 (explode-path (normal-case-path p1)))
(e2 (explode-path (normal-case-path p2))))
(if (= (length e1) (length e2))
(letrec ((f (λ (l1 l2)
(if (null? l1)
#t
(if (string=? (format "~a" (car l1)) (format "~a" (car l2)))
(f (cdr l1) (cdr l2))
#f)))))
(f e1 e2))
#f)
)
)
)
(define (make-select-list id items selected)
(let ((slct (list 'select (list (list 'id (format "~a" id))))))
(for-each
(λ (item)
(let ((value (car item))
(label (cadr item)))
(set! slct
(append slct
(list
(if (equal? value selected)
(list 'option
(list (list 'value (format "~a" value)) (list 'selected "selected"))
label)
(list 'option
(list (list 'value (format "~a" value)))
label))))))
)
items)
slct))
(define (new-id)
(let* ((s (current-milliseconds))
(r (random 1000000))
(id (string->symbol (format "id-~a-~a" s r))))
id))
(module+ test
(require rackunit)
(define (multiply a b c)
(check/c* (my-class multiply)
(a number?)
(b number?)
(c symbol?))
(format "symbol ~a = ~a" c (* a b)))
(check-equal? (multiply 2 3 'answer)
"symbol answer = 6")
(check-not-exn
(lambda ()
(define value 1)
(check/c my-class value number?)))
(check-exn
exn:fail:contract?
(lambda ()
(multiply 2 "3" 'answer)))
(check-exn
#rx"my-class:multiply"
(lambda ()
(multiply 2 3 "answer")))
(check-not-exn
(lambda ()
(define value "root")
(check/c value (or/c path? string?))))
(check-exn
#rx"or/c"
(lambda ()
(define value 42)
(check/c my-class value (or/c path? string?)))))