1 module d_properties.writer;
2 
3 import std.stdio : File;
4 import std.algorithm.sorting : sort;
5 import std.regex;
6 import d_properties.properties : Properties;
7 
8 /** 
9  * The style of separator to use when writing.
10  */
11 public enum SeparatorStyle : string {
12     EQUALS = "=",
13     EQUALS_SPACED = " = ",
14     COLON = ":",
15     COLON_SPACED = " : ",
16     SPACE = " "
17 }
18 
19 /** 
20  * The style of comment to use when writing.
21  */
22 public enum CommentStyle : string {
23     HASHTAG = "#",
24     EXCLAMATION = "!"
25 }
26 
27 /** 
28  * Writes the given properties to a file.
29  * Params:
30  *   props = The properties to write.
31  *   filename = The name of the file to write to.
32  *   comment = A comment to place at the top of the file.
33  *   separatorStyle = The style to use when separating keys and values.
34  *   commentStyle = The style to use for comments.
35  */
36 public void writeToFile(
37     Properties props,
38     string filename,
39     string comment = null,
40     SeparatorStyle separatorStyle = SeparatorStyle.EQUALS_SPACED,
41     CommentStyle commentStyle = CommentStyle.HASHTAG
42 ) {
43     auto f = File(filename, "w");
44     string commentMarker = cast(string) commentStyle;
45     string separator = cast(string) separatorStyle;
46     if (comment != null) {
47         f.writefln("%s %s", commentMarker, comment);
48     }
49     auto keys = props.values.keys;
50     keys.sort(); // Sort keys to make file writing deterministic.
51     foreach (key; keys) {
52         f.writefln("%s%s%s", sanitizeKey(key), separator, sanitizeValue(props[key]));
53     }
54     f.close;
55 }
56 
57 private string sanitizeKey(string key) {
58     return key.replaceAll(regex(" "), "\\ ")
59         .replaceAll(regex(":"), "\\:")
60         .replaceAll(regex("="), "\\=");
61 }
62 
63 private string sanitizeValue(string value) {
64     return value.replaceAll(regex("\\\\(?=[^u]|$)"), "\\\\");
65 }