The goal of this program is to take an input from the command line, either by piping the output of a program through the parser or by listening to the output of a program, and format the output according to specific rules that are defined through a JSON input file.
To compile dotify, simply run
make
and you should be good to go. Note that this requires a C++ compiler that is compatible with the 2014 C++ standard. Or, if you feel a bit adventurous try the following magic lines:
meson build && ninja -C build
(your future self will thank you for learning meson, honestly! ...). More info: https://mesonbuild.com/Quick-guide.html
To use dotify on a static text file, you can use the following syntax
cat textFileToParse | /path/to/dotify -f /path/to/inputFile.json
Alternatively you can run dotify on the output of a different program to parse its output
/path/to/programm | tee log | /path/to/dotify -f /path/to/inputFile.json
To test the usage, try the following command (assuming dotify has been compiled into the bin directory)
cat examples/templates.txt | tee log | bin/dotify -f input/ninja.json
you may wish to compare the output against the examples/templates.txt file.
The following command line arguments are supported
- -h,--help Prints the help with short description of argumentes and usage
- -f,--file Path to the
JSON
input file. Without this, dotify will effectively just print the text that it receives. - -k,--keywordsOnly Only print string to screen if it contains one of the keywords specified in the
JSON
file. This is useful if a lot of additional lines are printed that are difficult or cumbersome to suppress through theignoreCompleteLineIfItContainsSubstring
property (see JSON file explanation)
The following shows the basic structure of the input file with simple examples, provided in JSON
format
{
"ignoreCompleteLineIfItContainsSubstring" : [
"should be suppressed"
],
"ignoreContentBetweenDelimiter" : [
{
"startingDelimiter" : "<",
"endingDelimiter" : ">",
"replaceContentBy" : "..."
}
],
"styleLineContainingKeywords" : [
{
"keyword" : "error",
"removeDuplicates" : true,
"applyStyle" : "onKeyword",
"color" : "red",
"style" : "bold"
}
]
}
Suppose the above is stored as "example.json", consider the following example
name@pc:~$ printf "This string should be suppressed\nerror when compiling file containing container::data<std::vector<int>, std::vector<double>>\nerror when compiling file conng container::data<std::vector<int>, std::vector<double>>\n" > log
name@pc:~$ cat log
This string should be suppressed
error when compiling file containing container::data<std::vector<int>, std::vector<double>>
error when compiling file containing container::data<std::vector<int>, std::vector<double>>
name@pc:~$ cat log | /path/to/dotify -f /path/to/example.json
There are 3 sections that can be specified in the input file, which are
-
ignoreCompleteLineIfItContainsSubstring
: In here comes a list of all strings that should be removed from the output. A string will be removed from the output as long as parts of the string match one of the statements in this list. -
ignoreContentBetweenDelimiter
: This property defines delimiters which are used to suppress content between those delimiters. Unlike theignoreCompleteLineIfItContainsSubstring
property, this only acts locally on strings between the delimiter. Furthermore, we can provide two additional argumentsreplaceContentBy
andmustContain
, which provide fine grained control over the content between the delimiters.replaceContentBy
defines the string which will be printed instead of the actual content between the delimiters, if this entry is not provided, it will default to "...".mustContain
specifies a string that must be included between the delimiters if the content is to be replaced. This is useful if there are several delimiters of the same type but with different content between those. Regular expressions are currently not allowed for performance reasons.
-
styleLineContainingKeywords
This list defines keywords and how they should be formatted when printed to screen. In the above example the keyword iserror
, which should be printed inred
using abold
formatting for the text. A complete list of allowed entries is as follows:keyword
This is the keyword to be matched. If thekeyword
is encountered in a string, the line will be formated according to the parameters set for thiskeyword
.removeDuplicates
A boolean flag indicating if duplicate entries should be shown or removed from the output. This is useful for cyclic dependencies where the same message may be printed more than once. As shown in the example above, strings that are identical will not be printed twice if this flag is set to true.applyStyle
This entry determines how the formatting should be applied to the line, specifically, it determines which portion of the string are colored and formatted. The following entries are supported:preKeyword
Everything before thekeyword
will be formatted.onKeyword
Only thekeyword
will be formatted.postKeyword
Everything after thekeyword
will be formatted.everywhere
Everything (on current line) will be formatted, as long as the string contains thekeyword
.
color
This is the color which the text should take, the following colors are supported:neutral
(default background color)red
green
yellow
blue
magenta
cyan
format
This is the formatting that should be applied to the text, the following entries are supported:normal
(default text formatting)bold
dim
(darker than base color)underline
blink
(flashing text)
now let's consider a small but real life example. Suppose we have the following file that we want to put through dotify:
[1/4] Compiling src/foo.cpp
[2/4] Compiling src/bar.cpp
/home/user/project/include/bar.hpp:107: warning: argument 'value' of command @param is not found in the argument list
../include/bar.hpp:120:22: warning: unused variable ‘value’ [-Wunused-variable]
[3/4] Linking lib/libBaz.so
../include/temp.hpp: In instantiation of ‘void myNamespace::myTempClass<myContainerType>::myTempFunction(std::vector<dataContainer> &) const [with dataContainer = myNamespace::dataContainer<std::map<int, std::string>, std::vector<std::array<myArray<double, specialisedDataContainer<std::vector<double>>>>, 3>>]’:
src/temp2.cpp:21:1: required from here
../include/temp2.hpp:345:23: error: ‘using MyContainer = std::conditional<true, std::vector<double>, std::vector<int> >::type {aka class std::vector<double>}’ has no member named ‘bbegin’
std::fill(genericContainer.bbegin(), genericContainer.end(), 0.0);
Build failed
-> task in 'tempProject' failed with exit status 1 (run with -v to display more information)
and we have a corresponding input file like so:
{
"ignoreCompleteLineIfItContainsSubstring" : [
"is not found in the argument list"
],
"ignoreContentBetweenDelimiter" : [
{
"startingDelimiter" : "<",
"endingDelimiter" : ">",
"replaceContentBy" : "..."
}
],
"styleLineContainingKeywords" : [
{
"keyword" : "warning",
"removeDuplicates" : true,
"applyStyle" : "onKeyword",
"color" : "magenta",
"style" : "bold"
},
{
"keyword" : "error",
"removeDuplicates" : true,
"applyStyle" : "onKeyword",
"color" : "red",
"style" : "bold"
},
{
"keyword" : "Compiling",
"applyStyle" : "postKeyword",
"color" : "green"
},
{
"keyword" : "Linking",
"applyStyle" : "postKeyword",
"color" : "yellow"
},
{
"keyword" : "Build failed",
"applyStyle" : "everywhere",
"color" : "red",
"style" : "bold"
},
{
"keyword" : "failed with exit status",
"applyStyle" : "everywhere",
"removeDuplicates" : true,
"color" : "red",
"style" : "bold"
}
]
}
Running the above text through dotify using
user@pc:~$ cat /path/to/logFile | /path/to/dotify -f /path/to/inputFile.json
will result in the following output:
We may further wish to suppress clutter by only printing strings that contain keywords. We use the -k
command line
argument for this. Thus, our command becomes
user@pc:~$ cat /path/to/logFile | /path/to/dotify -k -f /path/to/inputFile.json
and our output