33 template <
typename A, 
typename B>
 
   34 std::string generateDiff(
const A& prev, 
const B& curr) {
 
   35     TempFileStream in_prev;
 
   36     TempFileStream in_curr;
 
   41     std::string diff_cmd =
 
   42             "diff --new-line-format='+%L' " 
   43             "     --old-line-format='-%L' " 
   44             "     --unchanged-line-format=' %L' ";
 
   45     return execStdOut(diff_cmd + in_prev.getFileName() + 
" " + in_curr.getFileName()).str();
 
   48 std::string replaceAll(std::string_view text, std::string_view key, std::string_view replacement) {
 
   49     std::ostringstream 
ss;
 
   50     for (
auto tail = text; !
tail.empty();) {
 
   51         auto i = 
tail.find(key);
 
   53         if (
i == std::string::npos) 
break;
 
   63     out << 
"<a href=\"#" << 
id << 
"\">" << 
title << 
"</a>\n";
 
   67         if (subsection.hasSubsections()) {
 
   74             out << 
"<li class='leaf'>";
 
   78         subsection.printIndex(out);
 
   85     out << 
"<a id=\"" << 
id << 
"\"></a>\n";
 
   86     out << 
"<div class='headerdiv'>\n";
 
   87     out << 
"<h1>" << 
title << 
"</h1>\n";
 
   88     out << 
"<a href='#'>(return to top)</a>\n";
 
   89     out << 
"</div><div style='clear:both'></div>\n";
 
   94     out << 
"<div style='padding-left: 1em'>\n";
 
   97         subsection.printContent(out);
 
  104         endSection(
"forced-closed", 
"Forcing end of unknown section");
 
  112     if (dst.empty() || 
empty()) 
return;
 
  114     std::ofstream(dst) << *
this;
 
  119             std::move(
id), std::move(title), 
tfm::format(
"<pre>%s</pre>", replaceAll(code, 
"<", 
"<"))));
 
  123         std::string_view prev, std::string_view curr) {
 
  125             replaceAll(replaceAll(prev.empty() ? curr : generateDiff(prev, curr), 
"\\", 
"\\\\"), 
"`", 
"\\`");
 
  128         <div id="code-id-%d"></div> 
  129         <script type="text/javascript"> renderDiff('%s', 'code-id-%d', `%s`) </script> 
  132             std::move(id), std::move(title), 
tfm::format(html, divId, language, divId, diff)));
 
  139             std::move(currentSectionName), std::move(currentSectionTitle), std::move(subsections), 
""));
 
  148 <meta charset=\"UTF-8\"> 
  149 <title>Souffle Debug Report ()"; 
  152     ul { list-style-type: none; } 
  153     ul > li.leaf { display: inline-block; padding: 0em 1em; } 
  154     ul > li.nonleaf { padding: 0em 1em; } 
  155     * { font-family: sans-serif; } 
  156     pre { white-space: pre-wrap; font-family: monospace; } 
  157     a:link { text-decoration: none; color: blue; } 
  158     a:visited { text-decoration: none; color: blue; } 
  159     div.headerdiv { background-color:lightgrey; margin:10px; padding-left:10px; padding-right:10px; 
  160         padding-top:3px; padding-bottom:3px; border-radius:5px } 
  161     .headerdiv h1 { display:inline; } 
  162     .headerdiv a { float:right; } 
  165 <link rel="stylesheet" type="text/css" href= 
  166     "https://cdn.jsdelivr.net/npm/highlight.js@10.0.0/styles/default.min.css" /> 
  167 <script type="text/javascript" src= 
  168     "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.0.0/build/highlight.min.js"></script> 
  170 <link rel="stylesheet" type="text/css" href= 
  171     "https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" /> 
  172 <script type="text/javascript" src= 
  173     "https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui-base.min.js"></script> 
  176   function toggleVisibility(id) { 
  177     var element = document.getElementById(id); 
  178     if (element.style.display == 'none') { 
  179       element.style.display = 'block'; 
  181       element.style.display = 'none'; 
  185   if (typeof hljs !== 'undefined') { 
  186     hljs.registerLanguage('souffle', function (hljs) { 
  187       let COMMENT_MODES = [ 
  188         hljs.C_LINE_COMMENT_MODE, 
  189         hljs.C_BLOCK_COMMENT_MODE, 
  193         $pattern: '\\.?\\w+', 
  194         literal: 'true false', 
  195         keyword: '.pragma .functor .component .decl .input .output ' + 
  196           'ord strlen strsub range matches land lor lxor lnot bwand bwor bwxor bwnot bshl bshr bshru', 
  199       let STRING = hljs.QUOTE_STRING_MODE 
  201         className: 'number', relevance: 0, variants: [ 
  202           { begin: /0b[01]+/ }, 
  203           { begin: /\d+\.\d+/ }, // float 
  204           { begin: /\d+\.\d+.\d+.\d+/ }, // IPv4 literal 
  206           { begin: /0x[a-fA-F0-9]+u?/ } 
  212         begin: /#\s*[a-z]+\b/, 
  215           'meta-keyword': 'if else elif endif define undef warning error line pragma ifdef ifndef include' 
  218           { begin: /\\\n/, relevance: 0 }, 
  219           hljs.inherit(STRING, { className: 'meta-string' }), 
  220         ].concat(COMMENT_MODES) 
  223       let ATOM = { begin: /[a-z][A-Za-z0-9_]*/, relevance: 0 } 
  225         className: 'symbol', relevance: 0, variants: [ 
  226           { begin: /[A-Z][a-zA-Z0-9_]*/ }, 
  227           { begin: /_[A-Za-z0-9_]*/ }, 
  230       let PARENTED = { begin: /\(/, end: /\)/, relevance: 0 } 
  231       let LIST = { begin: /\[/, end: /\]/ } 
  232       let PRED_OP = { begin: /:-/ } // relevance booster 
  242       ].concat(COMMENT_MODES) 
  244       PARENTED.contains = INNER; 
  245       LIST.contains = INNER; 
  250         contains: INNER.concat([{ begin: /\.$/ }]) // relevance booster 
  253     // TODO: Add a highlighter for `ram` 
  254     hljs.configure({ languages: ['souffle'] }) 
  257   if (typeof Diff2HtmlUI !== 'undefined' && typeof hljs !== 'undefined') { 
  258     function renderDiff(lang, id, diff) { 
  259       // file extension determines the language used for highlighting 
  260       let file   = `Datalog.${lang}` 
  261       let prefix = `diff ${file} ${file} 
  266       new Diff2HtmlUI(document.getElementById(id), prefix + diff, { 
  270         outputFormat: 'side-by-side', 
  271         synchronisedScroll: true, 
  274   } else { // fallback to plain text 
  275     function renderDiff(lang, id, diff) { 
  276       document.getElementById(id).innerText = diff 
  282 <div class='headerdiv'><h1>Souffle Debug Report ()"; 
  284     for (
const DebugReportSection& section : 
sections) {
 
  285         section.printIndex(out);
 
  287     for (
const DebugReportSection& section : 
sections) {
 
  288         section.printContent(out);
 
  290     out << R
"(<a href='#'>(return to top)</a>