2020-05-04 05:54:07 +00:00
|
|
|
#lang racket
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; prefs:
|
|
|
|
;; utilities for reading and writing preferences
|
|
|
|
|
2020-05-04 05:54:07 +00:00
|
|
|
(require net/url-string)
|
|
|
|
|
|
|
|
(provide prefs-save prefs-load prefs-get prefs-update DEFAULT-PREFS)
|
|
|
|
|
|
|
|
(define (instance-url? x)
|
|
|
|
(and (string? x)
|
2020-05-05 04:16:46 +00:00
|
|
|
(char=? (last (string->list x)) #\/)
|
2020-05-04 05:54:07 +00:00
|
|
|
(with-handlers ([exn? (lambda (e) #f)])
|
|
|
|
(let ([u (string->url x)])
|
|
|
|
(string=? "https" (url-scheme u))))))
|
|
|
|
|
|
|
|
(define (id-string? x)
|
|
|
|
(and (string? x) (regexp-match-exact? #px"^[a-zA-Z0-9_]+$" x)))
|
|
|
|
|
|
|
|
(define (pronoun-list? x)
|
|
|
|
(and (list? x) (= 5 (length x))))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; a preferences schema with validation functions
|
2020-05-04 05:54:07 +00:00
|
|
|
(define SCHEMA
|
|
|
|
(hash 'instance-url instance-url?
|
|
|
|
'display-name string?
|
|
|
|
'name id-string?
|
2020-07-23 05:02:00 +00:00
|
|
|
'title string?
|
2020-05-04 05:54:07 +00:00
|
|
|
'make-discoverable boolean?
|
|
|
|
'is-cat boolean?
|
2020-07-23 05:02:00 +00:00
|
|
|
'lang string?
|
2020-05-04 05:54:07 +00:00
|
|
|
'pronouns pronoun-list?))
|
|
|
|
|
|
|
|
(define DEFAULT-PREFS
|
|
|
|
'((instance-url "https://myinstance.tld/")
|
|
|
|
(display-name "Display Name(tm)")
|
|
|
|
(name "username")
|
2020-07-23 05:02:00 +00:00
|
|
|
(title "My Shiny New Blog")
|
|
|
|
(lang "en")
|
2020-05-04 05:54:07 +00:00
|
|
|
(make-discoverable #t)
|
|
|
|
(is-cat #t)
|
|
|
|
(pronouns ("they" "them" "their" "theirs" "themselves"))))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; saves preferences to the given port (or current out)
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (prefs-save prefs [port (current-output-port)])
|
|
|
|
(pretty-write prefs port))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; validates a preference entry against the schema
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (validate-one k v)
|
|
|
|
(unless (hash-has-key? SCHEMA k)
|
|
|
|
(error "unknown preference name" k))
|
|
|
|
(unless (apply (hash-ref SCHEMA k) (list v))
|
|
|
|
(error "invalid preference value" v (hash-ref SCHEMA k))))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; validates a whole prefs object
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (validate x)
|
|
|
|
(unless (list? x)
|
|
|
|
(error "preferences must be list"))
|
|
|
|
(for ([kv (in-list x)])
|
|
|
|
(match kv
|
|
|
|
[(list k v) (validate-one k v)]
|
|
|
|
[_ (error "invalid preference")]))
|
|
|
|
x)
|
2020-07-23 05:02:00 +00:00
|
|
|
;; check the defaults
|
2020-05-04 05:54:07 +00:00
|
|
|
(void (validate DEFAULT-PREFS))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; reads and validates preferences from the given port (or current in)
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (prefs-load [port (current-input-port)])
|
|
|
|
(validate (read port)))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; finds a preference by name
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (prefs-get prefs what)
|
|
|
|
(match prefs
|
|
|
|
[(list _ ... (list (? (curry symbol=? what)) value) _ ...) value]
|
|
|
|
[_ (error "no such pref" prefs what)]))
|
|
|
|
|
2020-07-23 05:02:00 +00:00
|
|
|
;; updates one key/value pair in the preferences list
|
2020-05-04 05:54:07 +00:00
|
|
|
(define (prefs-update prefs key value)
|
|
|
|
(validate-one key value)
|
|
|
|
(define (upd p)
|
|
|
|
(match p
|
|
|
|
['() (list (list key value))]
|
|
|
|
[(list (list (? (curry symbol=? key)) _) rst ...) (cons (list key value) rst)]
|
|
|
|
[x (cons (first x) (upd (rest x)))]))
|
|
|
|
(upd prefs))
|