builtin-programs/web/index.folk
Wish the web server handles route "/" with handler {
fn readOutputFile {path} {
if {[catch {set fp [open $path r]}]} { return "" }
set content [read $fp]
close $fp
return $content
}
fn emitHtmlForProgramList {programList label} {
set programList [lsort -command {apply {{a b} {string compare $a(programName) $b(programName)}}} $programList]
set prettyLabel [string map {- " "} $label]
set prettyLabel [string totitle $prettyLabel]:
set returnList [list "<details open data-label='$label' data-count='[llength $programList]'><summary>$prettyLabel ([llength $programList])</summary>"]
lappend returnList "<ul>"
foreach item $programList {
set escapedThis [regsub -all -- / $item(programName) __]
set out [readOutputFile "/var/tmp/folk-[pid]/$escapedThis.stdout"]
set err [readOutputFile "/var/tmp/folk-[pid]/$escapedThis.stderr"]
set outputHtml ""
if {$out ne ""} {
append outputHtml "<pre style='margin: 0.25em 0 0 1em; padding: 0.25em 0.5em; font-size: 0.85em; white-space: pre-wrap; border-left: 3px solid #888'>[htmlEscape $out]</pre>"
}
if {$err ne ""} {
append outputHtml "<pre style='margin: 0.25em 0 0 1em; padding: 0.25em 0.5em; font-size: 0.85em; white-space: pre-wrap; border-left: 3px solid #c00; color: #c00'>[htmlEscape $err]</pre>"
}
set outLen [string length $out]
set errLen [string length $err]
set outputSuffix ""
if {$item(programName) ne "sysmon.c"} {
set outputSuffix "(<a href='/program/$item(programName)'>source</a>)"
}
if {$outLen > 0} { append outputSuffix " <span style='font-size: 0.75em; color: #888'>${outLen}b stdout</span>" }
if {$errLen > 0} { append outputSuffix " <span style='font-size: 0.75em; color: #888'>${errLen}b stderr</span>" }
set errors [Query! $item(programName) has error /err/ with info /info/]
foreach e $errors {
append outputHtml "<pre style='margin: 0.25em 0 0 1em; padding: 0.25em 0.5em; font-size: 0.85em; white-space: pre-wrap; border-left: 3px solid #c00; color: #c00'>[htmlEscape $e(err)]</pre>"
}
set errCount [llength $errors]
set displayName [regsub {^builtin-programs/} $item(programName) ""]
set nameStyle [expr {$errCount > 0 ? "style='color: #c00'" : ""}]
if {$errCount > 0} { append outputSuffix " (<span style='font-size: 0.75em; color: #c00'>${errCount} errors</span>)" }
set summaryStyle [expr {$outputHtml eq "" ? "style='list-style: none'" : ""}]
lappend returnList [subst {
<li id="program-[string map {{ } -} $item(programName)]"><details>
<summary $summaryStyle><span $nameStyle>$displayName</span> $outputSuffix</summary>
$outputHtml
</details></li>
}]
}
lappend returnList "</ul>"
lappend returnList "</details>"
join $returnList
}
fn emitHtmlForPrograms {programs} {
set vp [list]; # builtin programs
set cp [list]; # local programs
set wp [list]; # web programs
set rp [list]; # real programs
foreach match $programs {
set programName [dict get $match programName]
switch -glob $programName {
"builtin-programs/*" { lappend vp $match }
"/home/*" { lappend cp $match }
"/Users/*" { lappend cp $match }
"web-program-*" { lappend wp $match }
default { lappend rp $match }
}
}
lappend vp {programName "sysmon.c"}
return [join [list \
[emitHtmlForProgramList $vp "builtin-programs"] \
[emitHtmlForProgramList $cp "local-programs"] \
[emitHtmlForProgramList $rp "real-programs"] \
[emitHtmlForProgramList $wp "web-programs"] ]]
}
html [subst {
<html>
<head>
<title>Folk: Running programs</title>
<link rel="stylesheet" href="/style.css">
<style>
body {
font-family: math;
}
summary {
font-family: monospace;
}
details ul {
margin-block: 0;
list-style-type: none;
}
</style>
<script src="/lib/folk.js"></script>
<script src="/vendor/idiomorph.js"></script>
<script>
const folk = new FolkWS();
</script>
</head>
<body>
[QueryOne! the web navigation HTML is /./]
[HtmlWhen the collected results for [list /programName/ has program code /programCode/] are /programs/ {
emitHtmlForPrograms $programs
} -beforeAttributeUpdated {(attributeName, node, mutationType) => {
if (attributeName === "open") { return false; }
}}]
</body>
</html>
}]
}