expandTags

String-replaces <tags> in a string with the results from calls to Tint. Also works with dstrings and wstrings.

<tags> are the lowercase first letter of all LogLevels; <l>, <t>, <i>, <w> <e>, <c> and <f>. <a> is not included.

</> equals the passed baseLevel and is used to terminate colour sequences, returning to a default.

Lastly, text between a <h> and a </> are replaced with the results from a call to colourByHash.

This should hopefully make highlighted strings more readable.

  1. auto expandTags(T line, LogLevel baseLevel, bool strip)
    @safe
    expandTags
    (
    T
    )
    (
    const T line
    ,,
    const bool strip
    )
  2. auto expandTags(T line, LogLevel baseLevel)

Parameters

line T

A line of text, presumably with <tags>.

baseLevel LogLevel

The base LogLevel to fall back to on </> tags.

strip bool

Whether to expand tags or strip them.

Return Value

Type: auto

The passed line but with any <tags> replaced with ANSI colour sequences. The original string is passed back if there was nothing to replace.

Examples

enum oldPattern = "
    %1$sYour private authorisation key is: %2$s%3$s%4$s
    It should be entered as %2$spass%4$s under %2$s[IRCBot]%4$s.
    ";
immutable oldMessage = oldPattern.format(Tint.log, Tint.info, pass, Tint.off);

enum newPattern = "
    <l>Your private authorisation key is: <i>%s</>
    It should be entered as <i>pass</> under <i>[IRCBot]</>
    ";
immutable newMessage = newPattern
    .format(pass)
    .expandTags(LogLevel.off);

enum patternWithColouredNickname = "No quotes for nickname <h>%s<h>.";

immutable colouredMessage = patternWithColouredNickname
    .format(event.sender.nickname)
    .expandTags(LogLevel.off);
1 import kameloso.common : logger;
2 import std.conv : text, to;
3 import std.format : format;
4 
5 {
6     immutable line = "This is a <l>log</> line.";
7     immutable replaced = line.expandTags(LogLevel.off, strip: false);
8     immutable expected = text("This is a ", logger.logtint, "log", logger.offtint, " line.");
9     assert((replaced == expected), replaced);
10 }
11 {
12     import std.conv : wtext;
13 
14     immutable line = "This is a <l>log</> line."w;
15     immutable replaced = line.expandTags(LogLevel.off, strip: false);
16     immutable expected = wtext("This is a "w, logger.logtint, "log"w, logger.offtint, " line."w);
17     assert((replaced == expected), replaced.to!string);
18 }
19 {
20     import std.conv : dtext;
21 
22     immutable line = "This is a <l>log</> line."d;
23     immutable replaced = line.expandTags(LogLevel.off, strip: false);
24     immutable expected = dtext("This is a "d, logger.logtint, "log"d, logger.offtint, " line."d);
25     assert((replaced == expected), replaced.to!string);
26 }
27 {
28     immutable line = `<i>info</>nothing<c>critical</>nothing\<w>not warning`;
29     immutable replaced = line.expandTags(LogLevel.off, strip: false);
30     immutable expected = text(logger.infotint, "info", logger.offtint, "nothing",
31         logger.criticaltint, "critical", logger.offtint, "nothing<w>not warning");
32     assert((replaced == expected), replaced);
33 }
34 {
35     immutable line = "This is a line with no tags";
36     immutable replaced = line.expandTags(LogLevel.off, strip: false);
37     assert(line is replaced);
38 }
39 {
40     immutable emptyLine = string.init;
41     immutable replaced = emptyLine.expandTags(LogLevel.off, strip: false);
42     assert(replaced is emptyLine);
43 }
44 {
45     immutable line = "hello<h>kameloso</>hello";
46     immutable replaced = line.expandTags(LogLevel.off, strip: true);
47     immutable expected = "hellokamelosohello";
48     assert((replaced == expected), replaced);
49 }
50 {
51     immutable line = "hello<h></>hello";
52     immutable replaced = line.expandTags(LogLevel.off, strip: true);
53     immutable expected = "hellohello";
54     assert((replaced == expected), replaced);
55 }
56 {
57     immutable line = `hello\<harbl>kameloso<h>hello</>hi`;
58     immutable replaced = line.expandTags(LogLevel.off, strip: true);
59     immutable expected = "hello<harbl>kamelosohellohi";
60     assert((replaced == expected), replaced);
61 }
62 {
63     enum pattern = "Failed to fetch, replay and clear notes for " ~
64         "<l>%s<e> on <l>%s<e>: <l>%s";
65     immutable line = pattern.format("nickname", "<no channel>", "error");
66     immutable replaced = line.expandTags(LogLevel.off, strip: false);
67     immutable expected = "Failed to fetch, replay and clear notes for " ~
68         logger.logtint ~ "nickname" ~ logger.errortint ~ " on " ~ logger.logtint ~
69         "<no channel>" ~ logger.errortint ~ ": " ~ logger.logtint ~ "error";
70     assert((replaced == expected), replaced);
71 }
72 {
73     enum pattern = "Failed to fetch, replay and clear notes for " ~
74         "<l>%s<e> on <l>%s<e>: <l>%s";
75     immutable line = pattern.format("nickname", "<no channel>", "error");
76     immutable replaced = line.expandTags(LogLevel.off, strip: true);
77     immutable expected = "Failed to fetch, replay and clear notes for " ~
78         "nickname on <no channel>: error";
79     assert((replaced == expected), replaced);
80 }
81 {
82     enum pattern = "Failed to fetch, replay and clear notes for " ~
83         "<l>%s</> on <l>%s</>: <l>%s";
84     immutable line = pattern.format("nickname", "<no channel>", "error");
85     immutable replaced = line.expandTags(LogLevel.error, strip: false);
86     immutable expected = "Failed to fetch, replay and clear notes for " ~
87         logger.logtint ~ "nickname" ~ logger.errortint ~ " on " ~ logger.logtint ~
88         "<no channel>" ~ logger.errortint ~ ": " ~ logger.logtint ~ "error";
89     assert((replaced == expected), replaced);
90 }
91 {
92     enum pattern = "Failed to fetch, replay and clear notes for " ~
93         "<l>%s</> on <l>%s</>: <l>%s";
94     immutable line = pattern.format("nickname", "<no channel>", "error");
95     immutable replaced = line.expandTags(LogLevel.error, strip: true);
96     immutable expected = "Failed to fetch, replay and clear notes for " ~
97         "nickname on <no channel>: error";
98     assert((replaced == expected), replaced);
99 }
100 {
101     enum origPattern = "Could not apply <i>+%s<l> <i>%s<l> in <i>%s<l> " ~
102         "because we are not an operator in the channel.";
103     enum newPattern = "Could not apply <i>+%s</> <i>%s</> in <i>%s</> " ~
104         "because we are not an operator in the channel.";
105     immutable origLine = origPattern.format("o", "nickname", "#channel").expandTags(LogLevel.off, strip: false);
106     immutable newLine = newPattern.format("o", "nickname", "#channel").expandTags(LogLevel.all, strip: false);
107     assert((origLine == newLine), newLine);
108 }
109 
110 version(Colours)
111 {
112     import kameloso.terminal.colours : colourByHash;
113     import kameloso.pods : CoreSettings;
114 
115     CoreSettings brightSettings;
116     CoreSettings darkSettings;
117     brightSettings.brightTerminal = true;
118 
119     {
120         immutable line = "hello<h>kameloso</>hello";
121         immutable replaced = line.expandTags(LogLevel.off, strip: false);
122         immutable expected = text("hello", colourByHash("kameloso",
123             darkSettings), logger.offtint, "hello");
124         assert((replaced == expected), replaced);
125     }
126     {
127         immutable line = `hello\<harbl>kameloso<h>hello</>hi`;
128         immutable replaced = line.expandTags(LogLevel.off, strip: false);
129         immutable expected = text("hello<harbl>kameloso", colourByHash("hello",
130             darkSettings), logger.offtint, "hi");
131         assert((replaced == expected), replaced);
132     }
133     {
134         immutable line = "<l>%%APPDATA%%\\\\kameloso</>.";
135         immutable replaced = line.expandTags(LogLevel.off, strip: false);
136         immutable expected = logger.logtint ~ "%%APPDATA%%\\kameloso" ~ logger.offtint ~ ".";
137         assert((replaced == expected), replaced);
138     }
139     {
140         immutable line = "<l>herp\\</>herp\\\\herp\\\\<l>herp</>";
141         immutable replaced = line.expandTags(LogLevel.off, strip: false);
142         immutable expected = logger.logtint ~ "herp</>herp\\herp\\" ~ logger.logtint ~ "herp" ~ logger.offtint;
143         assert((replaced == expected), replaced);
144     }
145     {
146         immutable line = "Added <h>hirrsteff</> as a blacklisted user in #garderoben";
147         immutable replaced = line.expandTags(LogLevel.off, strip: false);
148         immutable expected = "Added " ~
149             colourByHash("hirrsteff", brightSettings) ~
150             logger.offtint ~ " as a blacklisted user in #garderoben";
151         assert((replaced == expected), replaced);
152     }
153 }