1:- encoding(utf8).
2:- module(
3 conf,
4 [
5 cli_argument/2, 6 cli_argument/3, 7 cli_arguments/1, 8 cli_arguments/2, 9 cli_arguments/3, 10 conf_json/1, 11 conf_json/2, 12 data_directory/1, 13 data_file/1, 14 data_file/2 15 ]
16).
47:- use_module(library(apply)). 48:- use_module(library(error)). 49:- use_module(library(lists)). 50:- use_module(library(uuid)). 51
52:- use_module(library(dcg)). 53:- use_module(library(dict)). 54:- use_module(library(file_ext)). 55:- use_module(library(json_ext)).
63cli_argument(Key, Value) :-
64 cli_arguments(Conf),
65 dict_get(Key, Conf, Value).
71cli_argument(Key, Default, Value) :-
72 cli_arguments(Conf),
73 dict_get(Key, Conf, Default, Value).
81cli_arguments(Conf) :-
82 current_prolog_flag(argv, Argv),
83 cli_arguments(Argv, [], Conf).
84
85cli_arguments(FlagMap, Conf) :-
86 current_prolog_flag(argv, Argv),
87 cli_arguments(Argv, FlagMap, Conf).
88
89cli_arguments(Argv, FlagMap, Conf) :-
90 maplist(cli_argument_(FlagMap), Argv, Pairs1),
91 keysort(Pairs1, Pairs2),
92 group_pairs_by_key(Pairs2, GroupedPairs1),
93 maplist(remove_singleton_value_, GroupedPairs1, GroupedPairs2),
94 dict_pairs(Conf, GroupedPairs2).
95
96remove_singleton_value_(Key-[Value], Key-Value) :- !.
97remove_singleton_value_(Pair, Pair).
98
99cli_argument_(Map, Flag, Arg) :-
100 atom_phrase(cli_flag_(Map, Arg), Flag), !.
101cli_argument_(_, Arg, positional-Arg).
102
103cli_flag_(Map, Key-Value) -->
104 ( "--"
105 -> '...'(Codes),
106 "=",
107 {atom_codes(Key, Codes)}
108 ; "-"
109 -> '...'(Codes),
110 "=",
111 {
112 atom_codes(Short, Codes),
113 memberchk(Short-Key, Map)
114 }
115 ), !,
116 remainder_as_atom(Value).
117cli_flag_(Map, Key-true) -->
118 ( "--"
119 -> remainder_as_atom(Key)
120 ; "-"
121 -> remainder_as_atom(Short),
122 {memberchk(Short-Key, Map)}
123 ).
135conf_json(Conf) :-
136 conf_file(File), !,
137 json_load(File, Conf).
138conf_json(_) :-
139 throw(error(existence_error(conf_file),conf_json/1)).
140
141conf_file(File) :-
142 conf_file_spec(Spec),
143 expand_file_name(Spec, Files),
144 member(File, Files),
145 access_file(File, read), !.
146
148conf_file_spec(Spec) :-
149 cli_argument(conf, Spec), !.
151conf_file_spec('conf.json').
153conf_file_spec('~/conf.json').
166conf_json(Key, Value) :-
167 conf_json(Conf),
168 dict_get(Key, Conf, Value), !.
169conf_json(Key, _) :-
170 existence_error(conf_key, Key).
176data_directory(Dir) :-
177 conf_json('data-directory', Dir), !.
178data_directory(_) :-
179 existence_error(config, data_directory).
185data_file(File) :-
186 uuid(Local),
187 data_file(Local, File).
193data_file(RelativePath, AbsolutePath) :-
194 data_directory(Dir),
195 absolute_file_name(RelativePath, AbsolutePath, [relative_to(Dir)]),
196 create_file_directory(AbsolutePath).
197
198
199
200
201
203
204:- multifile
205 prolog:error_message//1. 206
207prolog:error_message(cannot_find_cli_argument(Key)) -->
208 ['Cannot find CLI argument â--~a="VALUE"â.'-[Key]].
209prolog:error_message(cannot_find_configuration(Key)) -->
210 ["Cannot find the configuration section for â~aâ."-[Key]]
Configuration support
This module is typically used in the following way:
or
The configuration file location can be supplied from the command line by using the following flag. If no location is supplied, the default configuration file location is used, i.e., `~/conf.json'.
*/