I’ve kind of given up on the graph.
Instead, I modified the script to generate HTML, which could be a log
option like --output-format html
.
This shows both directions of the dependencies.
(this script inherited the function parentheses, which could probably be removed)
Direct the output to a .htm file.
Edit: I added code to output list of files for each change.
Edit: I convert <
to <
in the message and description.
#!/bin/bash
# arguments are reserved for passing directly to the pijul log command
LEN=10
PROJECT=$(pwd)
PROJECT=$(basename "$PROJECT")
CHANNEL=$(pijul channel | grep \*)
(
echo "<!DOCTYPE html> <html><head><title>$PROJECT $CHANNEL</title>"
echo "<style>.descript,.depend,.neededby,.file{font-size:0.9em;margin-inline-start:2em}[id]{margin-bottom:0.6em;scroll-margin-top: 2ex}"
echo ":target{background-color:honeydew;border: 1px solid}::marker{font-size:smaller;color:gray}"
echo "body{background:white linear-gradient(to bottom,transparent 15%,aliceblue 40%,lightyellow 65%,pink 90%);color:black}"
echo ".descript[open] summary {opacity: 0.5}.descript[open]{background:rgba(88,88,100,0.05)}</style>"
echo "<script>function expandAll(sel){document.querySelectorAll(sel).forEach(function(el){el.setAttribute('open','');})};"
echo "function collapseAll(sel){document.querySelectorAll(sel).forEach(function(el){el.removeAttribute('open');})};</script></head>"
echo "<body><h2>$PROJECT $CHANNEL</h2>"
echo "<div><button onclick=\"expandAll('details.descript')\">Expand descriptions</button>"
echo "<button onclick=\"collapseAll('details.descript')\">Collapse descriptions</button>"
echo " <button onclick=\"expandAll('details.depend')\">Expand dependencies</button>"
echo "<button onclick=\"collapseAll('details.depend')\">Collapse dependencies</button>"
echo " <button onclick=\"expandAll('details.neededby')\">Expand needed by</button>"
echo "<button onclick=\"collapseAll('details.neededby')\">Collapse needed by</button>"
echo " <button onclick=\"expandAll('details.file')\">Expand files</button>"
echo "<button onclick=\"collapseAll('details.file')\">Collapse files</button><br>"
echo "<small><em>in-page search will not find hidden text</em></small></div>"
echo "<ol class=\"log\" reversed>"
pijul log --hash-only "$@" | while read ID; do
pijul change "$ID" | awk -v oid="$ID" -v idlen="$LEN" '
/^message =/ { msg = substr($0, index($0, $3));
gsub( /"/, "", msg );
gsub(/</, "<", msg);
print "\n<li id=\"" substr(oid,1,idlen) "\">" substr(oid,1,idlen) " : " msg "<br>";
}
/^timestamp =/ {
before = indesc ? "" : "<div class=\"descript\">";
print before "<time datetime=" $3 ">" $3 "</time>" (before?"</div>":"</small></details>");
indesc = 0;
}
indesc { gsub(/</,"<"); print $0 "<br>"; }
/^description =/ { indesc = 1; print "<details class=\"descript\"><summary>Description</summary><small>";}
/^# Dependencies/ {
FS="]";
print "<details class=\"depend\"><summary>Dependencies</summary>";
getline;
while (substr($2,1,1) == " " ) {
print "<a href=\"#" substr($2,2,idlen) "\">" substr($0,1,idlen+6) "</a><br>";
getline;
}
print "</details>";
}
/^# Hunks/ {
FS="\"";
print "<details class=\"file\"><summary>Files</summary>";
err=getline;
while (err > 0) {
if (match($0, /^[0-9]+/)) {
if ($2 == "\\") gsub(/\\"/,"")
names[(NF>1?$2:$0)]=1
}
err=getline;
}
for (n in names) print n "<br>";
print "</details></li>";
}
'
done
echo "</ol><script>(function() {
var allIDs=document.querySelectorAll('[id]');
allIDs.forEach(function(item, i){
const id=item.getAttribute('id');
let needed=document.querySelectorAll('.depend [href=\"#'+id+'\"]');
if (needed.length) {
let neededBy='';
needed.forEach(function(el, i){
let byid=el.parentNode.parentNode.getAttribute('id');
neededBy +='<a href=\"#'+byid+'\">'+byid+'</a><br>'
});
item.innerHTML+='<details class=\"neededby\"><summary>Needed By</summary>'+neededBy+'</details>';
}
});
})();
</script>"
echo '</body></html>'
)