-
Notifications
You must be signed in to change notification settings - Fork 8
/
configuration.clj
151 lines (138 loc) · 5.68 KB
/
configuration.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
(ns ^{:doc "Read and make available configuration."
:author "Simon Brooke"}
smeagol.configuration
(:require [clojure.pprint :refer [pprint]]
[clojure.string :as s]
[environ.core :refer [env]]
[noir.io :as io]
[taoensso.timbre :as log]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; Smeagol: a very simple Wiki engine.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2017 Simon Brooke
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; Right, doing the data visualisation thing is tricky. Doing it in the
;;;; pipeline doesn't work, because the md-to-html-string filter messes up
;;;; both YAML and JSON notation. So we need to extract the visualisation
;;;; fragments from the Markdown text and replace them with tokens we will
;;;; recognise afterwards, perform md-to-html-string, and then replace our
;;;; tokens with the transformed visualisation specification.
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def config-file-path
"The relative path to the config file."
(or
(env :smeagol-config)
(str (io/resource-path) "../config.edn")))
(defn- from-env-vars
"Read a map from those of these environment variables which have values"
[& vars]
(reduce
#(let [v (env %2)]
(if v (assoc %1 %2 v) %1))
{}
vars))
(defn to-keyword
"Convert this argument into an idiomatic clojure keyword."
[arg]
(if (and arg (not (keyword? arg)))
(keyword
(s/lower-case
(s/replace (str arg) #"[^A-Za-z0-9]+" "-")))
arg))
(defn transform-map
"transform this map `m` by applying these `transforms`. Each transforms
is expected to comprise a map with the keys :from and :to, whose values
are respectively a key to match and a key to replace that match with,
and optionally a key :transform, whose value is a function of one
argument to be used to transform the value of that key."
[m tuples]
(log/debug
"transform-map:\n"
(with-out-str (clojure.pprint/pprint m)))
(reduce
(fn [m tuple]
(if
(and (map? tuple) (map? m) (m (:from tuple)))
(let [old-val (m (:from tuple))
t (:transform tuple)]
(assoc
(dissoc m (:from tuple))
(:to tuple)
(if-not
(nil? t)
(eval (list t old-val)) old-val)))
m))
m
tuples))
(def config-env-transforms
"Transforms to use with `transform-map` to convert environment
variable names (which need to be specific) into the shorter names
used internally"
'( {:from :smeagol-content-dir :to :content-dir}
{:from :smeagol-default-locale :to :default-locale}
{:from :smeagol-formatters :to :formatters :transform read-string}
{:from :smeagol-js-from :to :extensions-from :transform to-keyword}
{:from :smeagol-log-level :to :log-level :transform to-keyword}
{:from :smeagol-passwd :to :passwd}
{:from :smeagol-site-title :to :site-title}))
(def build-config
"The actual configuration, as a map. The idea here is that the config
file is read (if it is specified and present), but that individual
values can be overridden by environment variables."
(memoize (fn []
(try
(log/info (str "Reading configuration from " config-file-path))
(let [file-contents (try
(read-string (slurp config-file-path))
(catch Exception x
(log/error
(str
"Failed to read configuration from "
config-file-path
" because: "
(type x)
"; "
(.getMessage x)))
{}))
config (merge
file-contents
(transform-map
(from-env-vars
:smeagol-content-dir
:smeagol-default-locale
:smeagol-formatters
:smeagol-js-from
:smeagol-log-level
:smeagol-passwd
:smeagol-site-title)
config-env-transforms))]
(if (env :dev)
(log/debug
"Loaded configuration\n"
(with-out-str (clojure.pprint/pprint config))))
config)
(catch Exception any
(log/error any "Could not load configuration")
{})))))
(def config
"The actual configuration, as a map."
(build-config))