mirror of
https://codeberg.org/hako/Rosenthal.git
synced 2025-09-18 20:54:37 +00:00
153 lines
4.0 KiB
Scheme
153 lines
4.0 KiB
Scheme
;;; SPDX-FileCopyrightText: Copyright © 2022 Andrew Tropin <andrew@trop.in>
|
|
;;;
|
|
;;; SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
(define-module (rosenthal utils serializers ini)
|
|
#:use-module (ice-9 match)
|
|
#:use-module (ice-9 format)
|
|
#:use-module (srfi srfi-1)
|
|
#:use-module (rosenthal utils serializers)
|
|
#:use-module (guix packages)
|
|
#:use-module (guix gexp)
|
|
#:use-module (guix diagnostics)
|
|
#:use-module (guix ui)
|
|
#:use-module (gnu services configuration)
|
|
#:export (ini-serialize
|
|
ini-print
|
|
ini-merge
|
|
ini-append
|
|
|
|
serialize-ini-config
|
|
ini-config?))
|
|
|
|
(define ini-config? list?)
|
|
|
|
(define sample-ini
|
|
`((global ((daemon)
|
|
(log . file)))
|
|
(http ((host . 127.0.0.1)
|
|
(port . 1234)))))
|
|
|
|
(define (format-ini-section section)
|
|
(match section
|
|
('global "")
|
|
(name (format #f "[~a]\n" (symbol->string name)))))
|
|
|
|
(define* (ini-serialize
|
|
config
|
|
#:key
|
|
(equal-string " = ")
|
|
(format-ini-section format-ini-section))
|
|
"For global properties use global section, the properties will be added to the
|
|
beginning of the list before any section, this behavior can be adjusted with
|
|
FORMAT-INI-SECTION argument.
|
|
|
|
@lisp
|
|
`((global ((daemon)
|
|
(log . file)))
|
|
(http ((host . 127.0.0.1)
|
|
(port . 1234))))
|
|
@end lisp
|
|
|
|
would yeld
|
|
|
|
@example
|
|
@end example
|
|
"
|
|
(define (serialize-ini-term term)
|
|
(match term
|
|
(#t "true")
|
|
(#f "false")
|
|
((? symbol? e) (symbol->string e))
|
|
((? number? e) (number->string e))
|
|
((? string? e) (object->string e))
|
|
((lst ...)
|
|
(raise (formatted-message
|
|
(G_ "INI term should be a non-list value (string, \
|
|
boolean, number, symbol, or gexp). Provided term is:\n ~a") lst)))
|
|
(e e)))
|
|
|
|
(define (serialize-ini-properties properties)
|
|
(unless (alist? properties)
|
|
(raise (formatted-message
|
|
(G_ "INI properties should be an alist, \
|
|
but provided value is:\n ~a") properties)))
|
|
(append-map
|
|
(match-lambda
|
|
((? gexp? e)
|
|
(list e "\n"))
|
|
((k)
|
|
(list (serialize-ini-term k) equal-string "\n"))
|
|
((k . v)
|
|
(list (serialize-ini-term k) equal-string
|
|
(serialize-ini-term v) "\n")))
|
|
properties))
|
|
|
|
(define (serialize-ini-section section)
|
|
(match section
|
|
((name properties)
|
|
(append
|
|
(list (format-ini-section name))
|
|
(serialize-ini-properties properties)))
|
|
(e
|
|
(raise (formatted-message
|
|
(G_ "INI section should be a list containing a section name as \
|
|
the first element and alist of properties as the second, but provided value \
|
|
is:\n~a") e)))))
|
|
|
|
;; TODO: serialize global section before all other sections.
|
|
(append-map
|
|
(lambda (expr)
|
|
(append
|
|
(match expr
|
|
((? gexp? e) (list e))
|
|
(e (serialize-ini-section e)))
|
|
(list "\n")))
|
|
config))
|
|
|
|
(define (ini-merge ini1 ini2)
|
|
"Combine to INIs. Naive quadratic implementation, which can be rediculously
|
|
slow."
|
|
(define keys-to-merge
|
|
(fold
|
|
(match-lambda*
|
|
(((k v) acc) (if (assoc-ref ini2 k) (cons k acc) acc))
|
|
(((? gexp? e) acc) acc))
|
|
'() ini1))
|
|
|
|
(define enriched-ini1
|
|
(fold-right
|
|
(match-lambda*
|
|
(((k v) acc)
|
|
(cons
|
|
(cons k (list (append v (car (or (assoc-ref ini2 k) '(()))))))
|
|
acc))
|
|
(((? gexp? e) acc) (cons e acc)))
|
|
'()
|
|
ini1))
|
|
|
|
(define stripped-ini2
|
|
(remove (match-lambda
|
|
((k . v) (memq k keys-to-merge))
|
|
(e #f))
|
|
ini2))
|
|
(append enriched-ini1 stripped-ini2))
|
|
|
|
(define (ini-append x acc)
|
|
(ini-merge acc x))
|
|
|
|
(define serialize-ini-config ini-serialize)
|
|
;; (display
|
|
;; (merge-ini
|
|
;; '((section1 ((k1 . v1)))
|
|
;; (section2 ((k4 . v4))))
|
|
;; '((section1 ((k2 . v2)
|
|
;; (k3 . v3)))
|
|
;; (section3 ((k5 . v5))))))
|
|
|
|
;; (cdr '(a ((k . v) (k2 . v2))))
|
|
|
|
(define (ini-print ini)
|
|
"Prints generated INI, useful for debugging."
|
|
(display (apply string-append (ini-serialize ini))))
|