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, Flag!"strip" strip)
    @safe
    expandTags
    (
    T
    )
    (
    const T line
    ,,
    const Flag!"strip" strip
    )
    if (
    isSomeString!T
    )
  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 Flag!"strip"

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

Meta