(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)")))