(chapter-start ‘settings “Utilities for managing settings”)
(assign settings {}) (assign initial-settings {})
;; convert expr to a function that returns the expr, unless expr is a symbol in which case we assume it already refers to a fn (def settings/fn (expr)
(if (sym? expr) expr (or (atom? expr) (no expr)) `(k ,expr) (hash? expr) `(k ',expr) (caris 'quote expr) `(k ,expr) (caris 'brace-list expr) `(k ,expr) `(fn (_) ,expr)))
;; update value of setting ‘name (mac set-setting (name value)
`(do (hash-cons (dox-item-by-type 'setting ',(sym name)) 'values { plugin this-plugin script this-script value ',value }) (hash-set settings ',(sym name) ,(settings/fn value))))
;; update value of setting ‘name (mac reset-setting (name)
`(set-setting ,name ,(hash-get initial-settings (sym name))))
;; define a setting in the given ‘context with a ’name and an ‘initial value, with a ’doc to explain it ;; if value is a function, it is invoked with ‘context and ’name to retrieve its value ;; if value is a constant, it is wrapped in a function to return the constant (mac def-setting (name initial)
(let context (car:string-split name ".") `(do (dox-add-doc ',(sym name) 'setting ',(fetch-and-clear-comments) nil '(def-setting ,name ,initial) (hash-merge { setting { default ',initial context ',context name ',name } } (dox/attrs (,(sym "settings/~context"))))) (hash-set initial-settings ',(sym name) ',initial) (set-setting ,(sym name) ,initial))))
;; get the value of the given setting. Raises an error if the setting is unknown. ;; (note for testing: when using set-settings in ruby, make sure to quote string values, eg ;; set-settings “key.for.setting” => “this is the value”.inspect ;; or alternatively, ;; set-settings “key.for.setting” => ‘“this is the value”’ (def setting (name)
(aif (hash-get settings (sym name)) (on-err (error "can't get value of setting ~name : stored object is ~(inspect it)") (it name)) (error "unknown setting ~(inspect name)")))