1pub struct Formatter<'a> {
2 pub comma: &'a str,
3 pub hr: &'a str, pub indent: &'a str,
5 pub lb: &'a str, pub space: &'a str,
7}
8
9pub fn one_line<'a>() -> Formatter<'a> {
10 Formatter {
11 comma: ", ",
12 hr: "",
13 indent: "",
14 lb: "",
15 space: " ",
16 }
17}
18
19pub fn multiline<'a>() -> Formatter<'a> {
20 Formatter {
21 comma: ", ",
22 hr: "-- ------------------------------------------------------------------------------\x1b[0m",
23 indent: " ",
24 lb: "\n",
25 space: " ",
26 }
27}
28
29pub fn colorize(query: String) -> String {
30 let sql_syntax: Vec<(fn(&str) -> String, &str, &str)> = vec![
31 (blue, "ADD", "add"),
32 (blue, "ALTER", "alter"),
33 (blue, "COLUMN", "column"),
34 (blue, "COMMIT", "commit"),
35 (blue, "COMMITTED", "committed"),
36 (blue, "CONCURRENTLY", "concurrently"),
37 (blue, "CONFLICT", "conflict"),
38 (blue, "CONSTRAINT", "constraint"),
39 (blue, "CREATE ", "create "),
40 (blue, "DEFAULT", "default"),
41 (blue, "DEFERRABLE", "deferrable"),
42 (blue, "DELETE ", "delete "),
43 (blue, "DISTINCT", "distinct"),
44 (blue, "DROP", "drop"),
45 (blue, "EXCEPT", "except"),
46 (blue, "EXISTS", "exists"),
47 (blue, "FROM ", "from "),
48 (blue, "GROUP BY", "group by"),
49 (blue, "HAVING", "having"),
50 (blue, "INCLUDE", "include"),
51 (blue, "INDEX", "index"),
52 (blue, "INNER", "inner"),
53 (blue, "INSERT", "insert"),
54 (blue, "INTERSECT", "intersect"),
55 (blue, "ISOLATION", "isolation"),
56 (blue, "JOIN ", "join "),
57 (blue, "LEFT ", "left "),
58 (blue, "LIMIT ", "limit "),
59 (blue, "NOTHING", "nothing"),
60 (blue, "OFFSET", "offset"),
61 (blue, "ON ", "on "),
62 (blue, "ONLY ", "only "),
63 (blue, "ORDER BY", "order by"),
64 (blue, "OVERRIDING", "overriding"),
65 (blue, "PRIMARY", "primary"),
66 (blue, "READ ONLY", "read only"),
67 (blue, "READ WRITE", "read write"),
68 (blue, "RELEASE", "release"),
69 (blue, "REPEATABLE", "repeatable"),
70 (blue, "REPLACE", "REPLACE"),
71 (blue, "RETURNING", "returning"),
72 (blue, "RIGHT", "right"),
73 (blue, "ROLLBACK", "rollback"),
74 (blue, "SAVEPOINT", "savepoint"),
75 (blue, "SELECT ", "select "),
76 (blue, "SERIALIZABLE", "serializable"),
77 (blue, "SET ", "set "),
78 (blue, "START ", "start "),
79 (blue, "TABLE", "table"),
80 (blue, "TRANSACTION", "transaction"),
81 (blue, "UNCOMMITTED", "uncommitted"),
82 (blue, "UNION ", "union "),
83 (blue, "UNIQUE ", "unique "),
84 (blue, "UPDATE ", "update "),
85 (blue, "USING ", "using "),
86 (blue, "VALUES ", "values "),
87 (blue, "WHERE ", "where "),
88 (blue, "WITH ", "with "),
89 (blue, " ALL", " all"),
90 (blue, " AND", " and"),
91 (blue, " AS ", " as "),
92 (blue, " ASC", " asc"),
93 (blue, " CROSS", " cross"),
94 (blue, " DESC", " desc"),
95 (blue, " DO", " do"),
96 (blue, " END", " end"),
97 (blue, " FIRST", " first"),
98 (blue, " FULL", " full"),
99 (blue, " IF", " if"),
100 (blue, " IN ", " in "),
101 (blue, " INTO", " into"),
102 (blue, " KEY", " key"),
103 (blue, " LAST", " last"),
104 (blue, " LEVEL", " level"),
105 (blue, " NOT", " not"),
106 (blue, " OR ", " or "),
107 (blue, " OUTER", " OUTER"),
108 (blue, " UNIQUE", " unique"),
109 (blue, " USING", " using"),
110 (blue, " VARCHAR", " varchar"),
111 (red, " NULL", " null"),
112 (comment_start, "--", "--"),
113 (comment_start, "/*", "/*"),
114 (comment_end, "*/", "*/"),
115 ];
116
117 let mut query = sql_syntax.iter().fold(query, |acc, item| {
118 let (color_fn, text_upper, text_lower) = item;
119 acc
120 .replace(text_upper, &color_fn(text_upper))
121 .replace(text_lower, &color_fn(text_lower))
122 });
123
124 for index in 1..=10 {
125 let arg_number = format!("${index}");
126 query = query.replace(&arg_number, &bold(&arg_number))
127 }
128
129 query
130}
131
132pub fn format(query: String, fmts: &Formatter) -> String {
133 let template = format!("{0}{1}{0}{query}{0}{1}{0}", fmts.lb, fmts.hr);
134 let template = colorize(template);
135 template
136}
137
138fn blue(text: &str) -> String {
139 format!("\x1b[34;1m{text}\x1b[0m")
140}
141
142fn red(text: &str) -> String {
143 format!("\x1b[91;2m{text}\x1b[0m")
144}
145
146fn bold(text: &str) -> String {
147 format!("\x1b[0;1m{text}\x1b[0m")
148}
149
150fn comment_start(text: &str) -> String {
151 format!("\x1b[32;2m{text}")
152}
153
154fn comment_end(text: &str) -> String {
155 format!("\x1b[32;2m{text}\x1b[0m")
156}