From 72f729adb07477a9fa8e0f15e542e8c39b19dc75 Mon Sep 17 00:00:00 2001 From: Kris Yotam <75515498+krisyotam@users.noreply.github.com> Date: Fri, 15 May 2026 13:16:01 -0500 Subject: [PATCH] rename to krisyotam.net, update site title, footer quote, tighten subtitle spacing --- bin/contrib/rc-httpd/rc-httpd | 2 +- bin/contrib/rc-httpd/select-handler | 14 +- bin/md2html.awk | 427 +++++++ bin/sed | 2 + bin/werc.rc | 5 - etc/initrc | 12 +- etc/initrc.local | 5 + images/plan9-cirno.jpeg | Bin 0 -> 166620 bytes lib/default_master.tpl | 3 + lib/footer.inc | 11 +- lib/headers.tpl | 9 +- lib/style.css | 185 +++ lib/top_bar.inc | 24 +- reference/pmikkelsen-werc | 1 + .../Advent-of-code-2020-in-APL/day01.html | 230 ++++ .../Advent-of-code-2020-in-APL/day02.html | 230 ++++ .../Advent-of-code-2020-in-APL/day03.html | 230 ++++ .../Advent-of-code-2020-in-APL/day04.html | 230 ++++ .../Advent-of-code-2020-in-APL/day05.html | 230 ++++ .../Advent-of-code-2020-in-APL/day06.html | 230 ++++ .../Advent-of-code-2020-in-APL/day07.html | 230 ++++ .../Advent-of-code-2020-in-APL/day08.html | 230 ++++ .../Advent-of-code-2020-in-APL/day09.html | 230 ++++ .../Advent-of-code-2020-in-APL/day10.html | 230 ++++ .../Advent-of-code-2020-in-APL/day11.html | 230 ++++ .../Advent-of-code-2020-in-APL/day12.html | 230 ++++ .../Advent-of-code-2020-in-APL/day13.html | 230 ++++ .../Advent-of-code-2020-in-APL/day14.html | 230 ++++ .../Advent-of-code-2020-in-APL/day15.html | 230 ++++ .../Advent-of-code-2020-in-APL/day16.html | 230 ++++ .../Advent-of-code-2020-in-APL/day17.html | 230 ++++ .../Advent-of-code-2020-in-APL/day18.html | 230 ++++ .../Advent-of-code-2020-in-APL/day19.html | 230 ++++ .../Advent-of-code-2020-in-APL/day20.html | 230 ++++ .../Advent-of-code-2020-in-APL/day21.html | 230 ++++ .../Advent-of-code-2020-in-APL/day22.html | 230 ++++ .../Advent-of-code-2020-in-APL/day23.html | 230 ++++ .../Advent-of-code-2020-in-APL/day24.html | 230 ++++ .../Advent-of-code-2020-in-APL/day25.html | 230 ++++ .../Advent-of-code-2020-in-APL/index.html | 283 +++++ .../APL-and-J/Date-puzzle-solver.html | 276 +++++ .../Designing_an_APL_for_9front.html | 256 ++++ .../APL-and-J/hello_world_apl_and_j.html | 209 ++++ .../pmikkelsen.com/APL-and-J/index.html | 202 +++ .../pmikkelsen.com/OpenBSD/index.html | 196 +++ .../pmikkelsen.com/OpenBSD/server-setup.html | 195 +++ .../pmikkelsen/pmikkelsen.com/contact.html | 193 +++ .../facts/Fastest-Computer-Languages.html | 222 ++++ .../pmikkelsen.com/facts/index.html | 196 +++ .../pmikkelsen.com/haskell/index.html | 196 +++ .../pmikkelsen.com/haskell/quine.html | 246 ++++ .../pmikkelsen/pmikkelsen.com/index.html | 223 ++++ .../pmikkelsen.com/linux/eduroam.html | 208 ++++ .../pmikkelsen.com/linux/index.html | 198 +++ .../pmikkelsen/pmikkelsen.com/linux/wifi.html | 203 +++ .../mainframe/MVS-TK5-Setup.html | 214 ++++ .../mainframe/adding-users.html | 219 ++++ .../pmikkelsen.com/mainframe/howto.html | 234 ++++ .../pmikkelsen.com/mainframe/index.html | 200 +++ .../me/how-i-started-using-acme.html | 223 ++++ .../pmikkelsen/pmikkelsen.com/me/index.html | 198 +++ .../pmikkelsen.com/me/stuff-i-use.html | 213 ++++ .../favourite-programming-languages.html | 195 +++ .../pmikkelsen.com/opinions/index.html | 196 +++ .../pmikkelsen.com/plan9/basic_9p_server.html | 242 ++++ .../pmikkelsen.com/plan9/discord.html | 242 ++++ .../pmikkelsen/pmikkelsen.com/plan9/dns.html | 230 ++++ .../pmikkelsen.com/plan9/fonts.html | 222 ++++ .../pmikkelsen.com/plan9/index.html | 214 ++++ .../pmikkelsen.com/plan9/lets_encrypt.html | 251 ++++ .../plan9/mounting-9p-over-drawterm.html | 242 ++++ .../pmikkelsen.com/plan9/network_booting.html | 223 ++++ .../pmikkelsen.com/plan9/trellofs.html | 533 ++++++++ .../pmikkelsen.com/plan9/using_irc.html | 236 ++++ .../pmikkelsen.com/plan9/webfs-websocket.html | 264 ++++ .../prolog/generality-of-append.html | 242 ++++ .../pmikkelsen.com/prolog/index.html | 196 +++ .../pmikkelsen/pmikkelsen.com/web/index.html | 196 +++ .../web/the-setup-of-this-site.html | 196 +++ reference/tui.tsx | 1090 +++++++++++++++++ serve.py | 76 ++ serve.rc | 21 + sites/localhost | 1 + sites/plan9.krisyotam.com/_werc/config | 4 + .../about/_werc/about_master.tpl | 31 + sites/plan9.krisyotam.com/about/_werc/config | 1 + sites/plan9.krisyotam.com/about/index.md | 93 ++ sites/plan9.krisyotam.com/blogroll.md | 14 + sites/plan9.krisyotam.com/cluster/index.md | 4 + sites/plan9.krisyotam.com/data/index.md | 5 + sites/plan9.krisyotam.com/essays/index.md | 5 + sites/plan9.krisyotam.com/harmful/index.md | 13 + sites/plan9.krisyotam.com/index.md | 10 +- sites/plan9.krisyotam.com/resources/index.md | 5 + sites/plan9.krisyotam.com/sitemap.txt | 1 + sites/plan9.krisyotam.com/software/index.md | 62 + sites/plan9.krisyotam.com/style/go.md | 53 + sites/plan9.krisyotam.com/style/index.md | 8 + sites/plan9.krisyotam.com/style/plan9_c.md | 415 +++++++ sites/plan9.krisyotam.com/style/suckless_c.md | 213 ++++ 100 files changed, 17639 insertions(+), 59 deletions(-) create mode 100755 bin/md2html.awk create mode 100755 bin/sed create mode 100644 etc/initrc.local create mode 100644 images/plan9-cirno.jpeg create mode 100644 lib/style.css create mode 160000 reference/pmikkelsen-werc create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day01.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day02.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day03.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day04.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day05.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day06.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day07.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day08.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day09.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day10.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day11.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day12.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day13.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day14.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day15.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day16.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day17.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day18.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day19.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day20.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day21.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day22.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day23.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day24.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day25.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Date-puzzle-solver.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/Designing_an_APL_for_9front.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/hello_world_apl_and_j.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/APL-and-J/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/OpenBSD/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/OpenBSD/server-setup.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/contact.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/facts/Fastest-Computer-Languages.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/facts/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/haskell/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/haskell/quine.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/linux/eduroam.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/linux/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/linux/wifi.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/mainframe/MVS-TK5-Setup.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/mainframe/adding-users.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/mainframe/howto.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/mainframe/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/me/how-i-started-using-acme.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/me/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/me/stuff-i-use.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/opinions/favourite-programming-languages.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/opinions/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/basic_9p_server.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/discord.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/dns.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/fonts.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/lets_encrypt.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/mounting-9p-over-drawterm.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/network_booting.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/trellofs.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/using_irc.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/plan9/webfs-websocket.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/prolog/generality-of-append.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/prolog/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/web/index.html create mode 100644 reference/pmikkelsen/pmikkelsen.com/web/the-setup-of-this-site.html create mode 100644 reference/tui.tsx create mode 100644 serve.py create mode 100755 serve.rc create mode 120000 sites/localhost create mode 100644 sites/plan9.krisyotam.com/_werc/config create mode 100644 sites/plan9.krisyotam.com/about/_werc/about_master.tpl create mode 100644 sites/plan9.krisyotam.com/about/_werc/config create mode 100644 sites/plan9.krisyotam.com/about/index.md create mode 100644 sites/plan9.krisyotam.com/blogroll.md create mode 100644 sites/plan9.krisyotam.com/cluster/index.md create mode 100644 sites/plan9.krisyotam.com/data/index.md create mode 100644 sites/plan9.krisyotam.com/essays/index.md create mode 100644 sites/plan9.krisyotam.com/harmful/index.md create mode 100644 sites/plan9.krisyotam.com/resources/index.md create mode 100644 sites/plan9.krisyotam.com/sitemap.txt create mode 100644 sites/plan9.krisyotam.com/software/index.md create mode 100644 sites/plan9.krisyotam.com/style/go.md create mode 100644 sites/plan9.krisyotam.com/style/index.md create mode 100644 sites/plan9.krisyotam.com/style/plan9_c.md create mode 100644 sites/plan9.krisyotam.com/style/suckless_c.md diff --git a/bin/contrib/rc-httpd/rc-httpd b/bin/contrib/rc-httpd/rc-httpd index 8e4fad9a135c223cf53d36322777dac763576862..b3f84313d35d50569c36d8aaa0c11eed7623fdc5 100755 --- a/bin/contrib/rc-httpd/rc-httpd +++ b/bin/contrib/rc-httpd/rc-httpd @@ -1,5 +1,5 @@ #!/bin/rc -rc_httpd_dir=/home/sl/www/werc/bin/contrib/rc-httpd +rc_httpd_dir=/home/krisyotam/dev/plan9.krisyotam.com/bin/contrib/rc-httpd libdir = $rc_httpd_dir/lib path=($PLAN9/bin $rc_httpd_dir/handlers $PATH) cgi_path=$PLAN9/bin diff --git a/bin/contrib/rc-httpd/select-handler b/bin/contrib/rc-httpd/select-handler index ec819d45d27788f0e7b66b25fa020ef2da860978..87c782fbc664b70131f8806c6a7aff44b377ce5b 100755 --- a/bin/contrib/rc-httpd/select-handler +++ b/bin/contrib/rc-httpd/select-handler @@ -1,20 +1,10 @@ #!/bin/rc rfork n -# Route requests to werc. -# Change paths to match your system. - -if(~ $SERVER_NAME 9base.werc.cat-v.org) - PLAN9=/usr/local/9base -if(~ $SERVER_NAME frontbase.werc.cat-v.org) - PLAN9=/usr/local/plan9front -if(~ $SERVER_NAME plan9port.werc.cat-v.org) - PLAN9=/usr/local/plan9 - if(~ $SERVER_NAME *){ PATH_INFO=$location - FS_ROOT=/home/sl/www/werc/sites/$SERVER_NAME - exec static-or-cgi /home/sl/www/werc/bin/werc.rc + FS_ROOT=/home/krisyotam/dev/plan9.krisyotam.com/sites/$SERVER_NAME + exec static-or-cgi /home/krisyotam/dev/plan9.krisyotam.com/bin/werc.rc } if not error 503 diff --git a/bin/md2html.awk b/bin/md2html.awk new file mode 100755 index 0000000000000000000000000000000000000000..81d1241a78fb97afe545df3ace5ec44eb4d99bc7 --- /dev/null +++ b/bin/md2html.awk @@ -0,0 +1,427 @@ +#!/bin/awk -f +# +# by: Jesus Galan (yiyus) 2009 +# +# Usage: md2html.awk file.md > file.html +# See: http://4l77.com/src/md2html.awk + +function eschtml(t) { + gsub("&", "\\&", t); + gsub("<", "\\<", t); + return t; +} + +function oprint(t){ + if(nr == 0) + print t; + else + otext = otext "\n" t; +} + +function subref(id){ + for(; nr > 0 && sub("<<" id, ref[id], otext); nr--); + if(nr == 0 && otext) { + print otext; + otext = ""; + } +} + +function nextil(t) { + if(!match(t, /[`<&\[*_\\-]|(\!\[)/)) + return t; + t1 = substr(t, 1, RSTART - 1); + tag = substr(t, RSTART, RLENGTH); + t2 = substr(t, RSTART + RLENGTH); + if(ilcode && tag != "`") + return eschtml(t1 tag) nextil(t2); + # Backslash escaping + if(tag == "\\"){ + if(match(t2, /^[\\`*_{}\[\]()#+\-\.!]/)){ + tag = substr(t2, 1, 1); + t2 = substr(t2, 2); + } + return t1 tag nextil(t2); + } + # Dashes + if(tag == "-"){ + if(sub(/^-/, "", t2)) + tag = "—"; + return t1 tag nextil(t2); + } + # Inline Code + if(tag == "`"){ + if(sub(/^`/, "", t2)){ + if(!match(t2, /``/)) + return t1 "”" nextil(t2); + ilcode2 = !ilcode2; + } + else if(ilcode2) + return t1 tag nextil(t2); + tag = ""; + if(ilcode){ + t1 = eschtml(t1); + tag = ""; + } + ilcode = !ilcode; + return t1 tag nextil(t2); + } + if(tag == "<"){ + # Autolinks + if(match(t2, /^[^ ]+[\.@][^ ]+>/)){ + url = eschtml(substr(t2, 1, RLENGTH - 1)); + t2 = substr(t2, RLENGTH + 1); + linktext = url; + if(match(url, /@/) && !match(url, /^mailto:/)) + url = "mailto:" url; + return t1 "" linktext "" nextil(t2); + } + # Html tags + if(match(t2, /^[A-Za-z\/!][^>]*>/)){ + tag = tag substr(t2, RSTART, RLENGTH); + t2 = substr(t2, RLENGTH + 1); + return t1 tag nextil(t2); + } + return t1 "<" nextil(t2); + } + # Html special entities + if(tag == "&"){ + if(match(t2, /^#?[A-Za-z0-9]+;/)){ + tag = tag substr(t2, RSTART, RLENGTH); + t2 = substr(t2, RLENGTH + 1); + return t1 tag nextil(t2); + } + return t1 "&" nextil(t2); + } + # Images + if(tag == "!["){ + if(!match(t2, /(\[.*\])|(\(.*\))/)) + return t1 tag nextil(t2); + match(t2, /^[^\]]*/); + alt = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(match(t2, /^\(/)){ + # Inline + sub(/^\(/, "", t2); + match(t2, /^[^\)]+/); + url = eschtml(substr(t2, 1, RLENGTH)); + t2 = substr(t2, RLENGTH + 2); + title = ""; + if(match(url, /[ ]+\".*\"[ ]*$/)) { + title = substr(url, RSTART, RLENGTH); + url = substr(url, 1, RSTART - 1); + match(title, /\".*\"/); + title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; + } + if(match(url, /^<.*>$/)) + url = substr(url, 2, RLENGTH - 2); + return t1 "\""" nextil(t2); + } + else{ + # Referenced + sub(/^ ?\[/, "", t2); + id = alt; + if(match(t2, /^[^\]]+/)) + id = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(ref[id]) + r = ref[id]; + else{ + r = "<<" id; + nr++; + } + return t1 "\""" nextil(t2); + } + } + # Links + if(tag == "["){ + if(!match(t2, /(\[.*\])|(\(.*\))/)) + return t1 tag nextil(t2); + match(t2, /^[^\]]*(\[[^\]]*\][^\]]*)*/); + linktext = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(match(t2, /^\(/)){ + # Inline + match(t2, /^[^\)]+(\([^\)]+\)[^\)]*)*/); + url = substr(t2, 2, RLENGTH - 1); + pt2 = substr(t2, RLENGTH + 2); + title = ""; + if(match(url, /[ ]+\".*\"[ ]*$/)) { + title = substr(url, RSTART, RLENGTH); + url = substr(url, 1, RSTART - 1); + match(title, /\".*\"/); + title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; + } + if(match(url, /^<.*>$/)) + url = substr(url, 2, RLENGTH - 2); + url = eschtml(url); + return t1 "" nextil(linktext) "" nextil(pt2); + } + else{ + # Referenced + sub(/^ ?\[/, "", t2); + id = linktext; + if(match(t2, /^[^\]]+/)) + id = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(ref[id]) + r = ref[id]; + else{ + r = "<<" id; + nr++; + } + pt2 = t2; + return t1 "" nextil(linktext) "" nextil(pt2); + } + } + # Emphasis + if(match(tag, /[*_]/)){ + ntag = tag; + if(sub("^" tag, "", t2)){ + if(stag[ns] == tag && match(t2, "^" tag)) + t2 = tag t2; + else + ntag = tag tag + } + n = length(ntag); + tag = (n == 2) ? "strong" : "em"; + if(match(t1, / $/) && match(t2, /^ /)) + return t1 tag nextil(t2); + if(stag[ns] == ntag){ + tag = "/" tag; + ns--; + } + else + stag[++ns] = ntag; + tag = "<" tag ">"; + return t1 tag nextil(t2); + } +} + +function inline(t) { + ilcode = 0; + ilcode2 = 0; + ns = 0; + + return nextil(t); +} + +function printp(tag) { + if(!match(text, /^[ ]*$/)){ + text = inline(text); + if(tag != "") + oprint("<" tag ">" text ""); + else + oprint(text); + } + text = ""; +} + +BEGIN { + blank = 0; + code = 0; + hr = 0; + html = 0; + nl = 0; + nr = 0; + otext = ""; + text = ""; + par = "p"; +} + +# References +!code && /^ *\[[^\]]*\]:[ ]+/ { + sub(/^ *\[/, ""); + match($0, /\]/); + id = substr($0, 1, RSTART - 1); + sub(id "\\]:[ ]+", ""); + title = ""; + if(match($0, /\".*\"$/)) + title = "\" title=\"" substr($0, RSTART + 1, RLENGTH - 2); + sub(/[ ]+\".*\"$/, ""); + url = eschtml($0); + ref[id] = url title; + + subref(id); + next; +} + +# html +!html && /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ +isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/ { + if(code) + oprint(""); + for(; !text && block[nl] == "blockquote"; nl--) + oprint(""); + match($0, /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ + isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/); + htag = substr($0, 2, RLENGTH - 1); + if(!match($0, "(<\\/" htag ">)|((^
$)")) + html = 1; + if(html && match($0, /^
$/ || +(hr && />$/)) { + html = 0; + hr = 0; + oprint($0); + next; +} + +html { + oprint($0); + next; +} + +# List and quote blocks + +# Remove indentation +{ + for(nnl = 0; nnl < nl; nnl++) + if((match(block[nnl + 1], /[ou]l/) && !sub(/^( | )/, "")) || \ + (block[nnl + 1] == "blockquote" && !sub(/^> ?/, ""))) + break; +} +nnl < nl && !blank && text && ! /^ ? ? ?([*+-]|([0-9]+\.)+)( +| )/ { nnl = nl; } +# Quote blocks +{ + while(sub(/^> /, "")) + nblock[++nnl] = "blockquote"; +} +# Horizontal rules +{ hr = 0; } +(blank || (!text && !code)) && /^ ? ? ?([-*_][ ]*)([-*_][ ]*)([-*_][ ]*)+$/ { + if(code){ + oprint(""); + code = 0; + } + blank = 0; + nnl = 0; + hr = 1; +} +# List items +block[nl] ~ /[ou]l/ && /^$/ { + blank = 1; + next; +} +{ newli = 0; } +!hr && (nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?[*+-]( +| )/ { + sub(/^ ? ? ?[*+-]( +| )/, ""); + nnl++; + nblock[nnl] = "ul"; + newli = 1; +} +(nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?([0-9]+\.)+( +| )/ { + sub(/^ ? ? ?([0-9]+\.)+( +| )/, ""); + nnl++; + nblock[nnl] = "ol"; + newli = 1; +} +newli { + if(blank && nnl == nl && !par) + par = "p"; + blank = 0; + printp(par); + if(nnl == nl && block[nl] == nblock[nl]) + oprint("
  • "); +} +blank && ! /^$/ { + if(match(block[nnl], /[ou]l/) && !par) + par = "p"; + printp(par); + par = "p"; + blank = 0; +} + +# Close old blocks and open new ones +nnl != nl || nblock[nl] != block[nl] { + if(code){ + oprint(""); + code = 0; + } + printp(par); + b = (nnl > nl) ? nblock[nnl] : block[nnl]; + par = (match(b, /[ou]l/)) ? "" : "p"; +} +nnl < nl || (nnl == nl && nblock[nl] != block[nl]) { + for(; nl > nnl || (nnl == nl && pblock[nl] != block[nl]); nl--){ + if(match(block[nl], /[ou]l/)) + oprint("
  • "); + oprint(""); + } +} +nnl > nl { + for(; nl < nnl; nl++){ + block[nl + 1] = nblock[nl + 1]; + oprint("<" block[nl + 1] ">"); + if(match(block[nl + 1], /[ou]l/)) + oprint("
  • "); + } +} +hr { + oprint("
    "); + next; +} + +# Code blocks +code && /^$/ { + if(blanK) + oprint(""); + blank = 1; + next; +} +!text && sub(/^( | )/, "") { + if(blanK) + oprint(""); + blank = 0; + if(!code) + oprint("
    ");
    +	code = 1;
    +	$0 = eschtml($0);
    +	oprint($0);
    +	next;
    +}
    +code {
    +	oprint("
    "); + code = 0; +} + +# Setex-style Headers +text && /^=+$/ {printp("h1"); next;} +text && /^-+$/ {printp("h2"); next;} + +# Atx-Style headers +/^#+/ && (!newli || par=="p" || /^##/) { + for(n = 0; n < 6 && sub(/^# */, ""); n++) + sub(/#$/, ""); + par = "h" n; +} + +# Paragraph +/^$/ { + printp(par); + par = "p"; + next; +} + +# Add text +{ text = (text ? text " " : "") $0; } + +END { + if(code){ + oprint(""); + code = 0; + } + printp(par); + for(; nl > 0; nl--){ + if(match(block[nl], /[ou]l/)) + oprint("
  • "); + oprint(""); + } + gsub(/<<[^\"]*/, "", otext); + print(otext); +} diff --git a/bin/sed b/bin/sed new file mode 100755 index 0000000000000000000000000000000000000000..797fdc0178ab85ed1c00a57a77c1b09603d869e5 --- /dev/null +++ b/bin/sed @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/sed -E "$@" diff --git a/bin/werc.rc b/bin/werc.rc index 0d006a30437b72f97e24e0b546bcdf7a147e3ad3..1f83e96b4712d7ed982b6b6ffe23606bda6efe3a 100755 --- a/bin/werc.rc +++ b/bin/werc.rc @@ -20,7 +20,6 @@ path=(. /bin ./bin) res_tail='' http_content_type='text/html' ll_add handlers_bar_left nav_tree -werc_apps=( apps/* ) werc_root=`{pwd} sitesdir=sites @@ -29,9 +28,6 @@ sitesdir=sites if(test -f etc/initrc.local) . ./etc/initrc.local -for(a in $werc_apps) - . ./$a/app.rc - fn werc_exec_request { site=$SERVER_NAME base_url=http://$site:$SERVER_PORT @@ -61,7 +57,6 @@ fn werc_exec_request { if(~ $local_path */) { if(test -d $local_path) local_path=$local_path^'index' - # XXX: This redir might step on apps with synthetic dirs. if not if(ls `{basename -d $local_path}^* >/dev/null >[2]/dev/null) perm_redirect `{echo $req_path|sed 's,/+$,,'} } diff --git a/etc/initrc b/etc/initrc index f0b26c219e410587163eefb03b1f54db3c8cd694..21a8aed161ea09dfce5d7a8606bd7a2df66366c5 100755 --- a/etc/initrc +++ b/etc/initrc @@ -18,22 +18,16 @@ plan9port=$PLAN9 # Path, make sure the plan9port /bin directory is included before /bin # Keep '.' in path! It is needed. -path=($plan9port/bin . ./bin ./bin/contrib /bin /usr/bin) +path=($plan9port/bin . ./bin /bin /usr/bin) # Set this to your favorite markdown formatter, eg., markdown.pl (fltr_cache # takes as an argument a filter, in the default configuration markdown.pl, that # caches output) Note that some werc components assume a markdown-like # formatter, but all major functionality should should be formatter agnostic. -#formatter=(fltr_cache markdown.pl) -formatter=(fltr_cache md2html.awk) # no perl for old men +formatter=(fltr_cache md2html.awk) # Enable debugging, to disable set to () -debug=true +debug=false # Globally enabled apps enabled_apps=() - -# Default site variables, must be set in initrc.local or _werc/config, only siteTitle is required. -#masterSite=cat-v.org # Not required! -#siteTitle='cat-v' -#siteSubTitle='Considered harmful' diff --git a/etc/initrc.local b/etc/initrc.local new file mode 100644 index 0000000000000000000000000000000000000000..94d0f6f609eb496a30aaf6938033dbe97ff2a70a --- /dev/null +++ b/etc/initrc.local @@ -0,0 +1,5 @@ +plan9port=/usr/lib/plan9 +masterSite=plan9.krisyotam.com +siteTitle='plan9.krisyotam.com' +siteSubTitle='- tools, patches, notes' +debug=false diff --git a/images/plan9-cirno.jpeg b/images/plan9-cirno.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..0a06952e1eb7bd2a9df2e82f4c7d08adef61d3e3 GIT binary patch literal 166620 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 literal 0 HcmV?d00001 diff --git a/lib/default_master.tpl b/lib/default_master.tpl index 6742c49c6c6306f4db0a7b6da80c72cd50a9383e..e2c0c91105f34fdec8fa6c2213dc07c3bc4e85af 100644 --- a/lib/default_master.tpl +++ b/lib/default_master.tpl @@ -5,6 +5,7 @@

    %($"siteTitle%) %($"siteSubTitle%)

    +
    % if(! ~ $#handlers_bar_left 0) {
    % cat `{ get_lib_file footer.inc }
    + diff --git a/lib/footer.inc b/lib/footer.inc index 1eac7d8f38a592c3c50fe7244036f7a514465610..787eb47285372a46162519afb7d46e295cc4af13 100644 --- a/lib/footer.inc +++ b/lib/footer.inc @@ -1,7 +1,6 @@ - - -
    User Login - +
    "And remember, my friends, future events such as these will affect you in the future."
    +
    +
    + +
    diff --git a/lib/headers.tpl b/lib/headers.tpl index 635f85e137c6799ee214352a6d9122ad540c30f9..0b5b8363ffb4064536d5d8240acd1a461c93b593 100644 --- a/lib/headers.tpl +++ b/lib/headers.tpl @@ -3,14 +3,11 @@ %($pageTitle%) - - + -% if(test -f $sitedir/_werc/pub/style.css) -% echo ' ' - -% # Legacy charset declaration for backards compatibility with non-html5 browsers. % if(! ~ $#meta_description 0) diff --git a/lib/style.css b/lib/style.css new file mode 100644 index 0000000000000000000000000000000000000000..d051acd1f443c0af0f3ac298acb9aa1b3b733438 --- /dev/null +++ b/lib/style.css @@ -0,0 +1,185 @@ +body { display: flex; flex-wrap: wrap; font-family: sans;} +header { flex-basis: 100%; flex-shrink: 0; } +article { flex-basis: 60%; padding-left: 1em; } +footer { flex-basis: 100%; flex-shrink: 0; } +header nav { display: flex; justify-content: space-between; } +nav a, header a { text-decoration: none ; color: inherit; } +header h1 span { margin-left: 0.5em; font-size: 50%; font-style: italic; } +.mainContent > nav { flex-basis: content; padding-right: 1vw; min-width: 16em; } +nav ul { display: flex; flex-direction: column; list-style-type: none; list-style-position: outside; padding-left: 0; } +nav li ul { padding-left: 0.6em } +footer { display: flex; justify-content: space-between; } + +/* cut here to leave vanity behind */ + +body { margin:0; padding: 0; font-size: 84%; font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; } +a { text-decoration: none; color: } +a:hover { text-decoration: underline; } +.thisPage { color: black; } + +/* header and top bar */ +header nav { background-color: rgb(100,135,220); color: white; padding: 0.3em; border-bottom: 2px solid black; font-size: 91%; } +header h1 { background-color: #ff6d06; color: black; margin: 0; border-bottom: 2px solid black; font-weight: normal; padding: 0.25ex; font-size: 233%; } +header a:hover { text-decoration: none; } + +/* sidebar */ +.mainContent > nav { border-right: 1px solid #ddd; padding: 0; } +.mainContent > nav > div { border-bottom: 1px solid #ddd; } +.mainContent > nav > div a { color: rgb(0, 102, 204); display: block; text-transform: capitalize; font-weight: bold; padding: 0.25em 1ex 0.25em 2mm; font-size: 102%} +.mainContent > nav > div a:hover { color: white; background-color: rgb(100,135,220); border-left: black solid 0.2em; text-decoration: none; } +.mainContent > nav > div p { font-weight: bold; margin: 0 0 0.5em 2mm; padding: 1em 0 0 0; } + +/* main copy */ +article { padding: 0.5ex 0 5vh 1vw; } +article h1, article h2 { color: rgb(0,102,204); font-weight: bold; margin: 2em 0 0 0; border-bottom: 2px solid rgb(0,102,204); } +article h3, article h4, article h5 { color: rgb(0,102,204); font-weight: bold; margin: 2em 0 0 0; } +article h6, article h7, article h8 { color: rgb(0,102,204); font-weight: bold; margin: 2em 0 0 0; } +article a { color: rgb(0,102,204); } +article a:hover { color: rgb(100,135,220); } +article pre { font-size: 1.2em; } + +/* footer */ +footer { color: white; background-color: rgb(100,135,220); } +footer a { color: inherit; } +footer div { padding: 0.2em 0.5em; } + +/* tables */ +table { border: 1px solid rgba(128,128,128,0.5); padding: 0; } +th { color: white; background-color: rgb(100,135,220); } +tr:nth-child(odd) { background-color: rgba(128,128,128,0.1) } + +/* Plan 9 / Acme palette */ +img { + max-width: 100%; + border: 1px solid #888888; +} + +header h1 { + background-color: #FFFFEA; + color: #000000; +} + +html { + font-size: 1.2em; +} + +header nav, footer { + background-color: #9EEEEE; + color: #000000; +} + +code > pre { + border: 2px solid #888888; + background-color: #EAFFFF; + width: max-content; + padding: 0 0.5em; +} + +.mainContent > nav > div a, article a:hover { + color: #000000; +} + +.mainContent > nav > div a:hover { + color: #000000; + background-color: #EAFFFF; + border-left: #55CCCC solid 0.2em; +} + +article h1, article h2 { + color: #000000; + border-bottom: 2px solid #9EEEEE; +} + +article h3, article h4, article h5 { + color: #000000; +} + +article a { + color: #55CCCC; +} + +article a:hover { + color: #9EDBDA; +} + +.thisPage { + color: #000000; + background-color: #9EE09E; +} + +footer { + padding: 0.2em 0.5em; + flex-shrink: 1; + flex-basis: unset; + color: #000000; + background-color: #9EDBDA; + font-size: 0.85em; +} + +footer a { + color: #000000; +} + +header { + flex-basis: unset; +} + +html { + display: flex; + min-height: 100%; + overflow-x: hidden; +} + +body { + flex-direction: column; + flex: 1; + background-color: #B5B5AD; +} + +.mainContent { + display: flex; + flex-grow: 1; +} + +.mainContent > nav { + background-color: #FFFFF5; + border-right: 2px solid #9EEEEE; +} + +.mainContent > nav > div { + border-bottom: 1px solid #9EEEEE; +} + +article { + background-color: #FFFFF5; +} + +th { + color: #000000; + background-color: #EAFFFF; +} + +header nav a { + color: #000000; +} + +header h1 a { + color: #000000; +} + +.mascot-row { + display: flex; + justify-content: flex-end; + padding-right: 0; + margin-right: -2em; + margin-top: -420px; + pointer-events: none; + position: relative; + z-index: 0; +} + +.mascot-row img { + width: 420px; + border: none; + display: block; +} \ No newline at end of file diff --git a/lib/top_bar.inc b/lib/top_bar.inc index cbb89b81fb36790f31c3ba10af503697d94af08b..830bac3f808cdb4d9a73a9d61b578ede06d316b6 100644 --- a/lib/top_bar.inc +++ b/lib/top_bar.inc @@ -1,15 +1,17 @@ -
    - gsoc | - doc archive | - software repo | - ninetimes | - harmful | - 9P | - cat-v.org +
    + main | + sr.ht | + notebooks | + tools | + wiki | + notes
    -
    - site updates | - site map +
    + 9times | + harmful | + rocks | + 9front | + cat-v
    diff --git a/reference/pmikkelsen-werc b/reference/pmikkelsen-werc new file mode 160000 index 0000000000000000000000000000000000000000..89a5571e26dfbdf65ccbdd3097474936ad4d43be --- /dev/null +++ b/reference/pmikkelsen-werc @@ -0,0 +1 @@ +Subproject commit 89a5571e26dfbdf65ccbdd3097474936ad4d43be diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day01.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day01.html new file mode 100644 index 0000000000000000000000000000000000000000..34304e802d083363c96eea70af7931443aff5fc4 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day01.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day01 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day02.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day02.html new file mode 100644 index 0000000000000000000000000000000000000000..cf1ce4ffeb46c08802bae6dabea25e69691a28cf --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day02.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day02 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day03.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day03.html new file mode 100644 index 0000000000000000000000000000000000000000..30a2f750069822ab909ee80d61c3a84f0baf649a --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day03.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day03 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day04.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day04.html new file mode 100644 index 0000000000000000000000000000000000000000..1d9ef9006c1ab07f095872b38b0cd31ef8f01d77 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day04.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day04 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day05.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day05.html new file mode 100644 index 0000000000000000000000000000000000000000..f793d71f04324006d03d2e8e51d9718e1cf0ded1 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day05.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day05 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day06.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day06.html new file mode 100644 index 0000000000000000000000000000000000000000..1a84a2ffa3c73703826bccb1f420ca1a4e83a0bb --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day06.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day06 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day07.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day07.html new file mode 100644 index 0000000000000000000000000000000000000000..45ebb7e72e4a1e11fa612a46ba0eb97eebd64013 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day07.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day07 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day08.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day08.html new file mode 100644 index 0000000000000000000000000000000000000000..d270f98c0c0078999e72ba243515a7333c98c7d9 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day08.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day08 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day09.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day09.html new file mode 100644 index 0000000000000000000000000000000000000000..4c8eece7ce0399b02096d6ade77ad9ce7ed38db0 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day09.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day09 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day10.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day10.html new file mode 100644 index 0000000000000000000000000000000000000000..3dc6cf63900b0d36f9e8ea00918c7c06ab4265b0 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day10.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day10 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day11.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day11.html new file mode 100644 index 0000000000000000000000000000000000000000..829f094d989f5b41ee185b777d4a9c117e413b80 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day11.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day11 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day12.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day12.html new file mode 100644 index 0000000000000000000000000000000000000000..f8756b4308dafd44b62892a2f12e48188985af6e --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day12.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day12 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day13.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day13.html new file mode 100644 index 0000000000000000000000000000000000000000..5f16e68d6e57cbc07ccccbcd90e9dfcdcde6548d --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day13.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day13 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day14.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day14.html new file mode 100644 index 0000000000000000000000000000000000000000..35ecbcf765d89c7226070945ce44af969716f25a --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day14.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day14 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day15.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day15.html new file mode 100644 index 0000000000000000000000000000000000000000..3ea942b129aa2652a08388ea6cf98bdf312ed52c --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day15.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day15 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day16.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day16.html new file mode 100644 index 0000000000000000000000000000000000000000..3e359f92e222369cd9f069fcbbeaaecc3664b59a --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day16.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day16 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day17.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day17.html new file mode 100644 index 0000000000000000000000000000000000000000..b8177582410d61c054b27c14123dbbaae95a06cc --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day17.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day17 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day18.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day18.html new file mode 100644 index 0000000000000000000000000000000000000000..68d8ffb4c4bce81819d8512136c75047e089ecbe --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day18.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day18 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day19.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day19.html new file mode 100644 index 0000000000000000000000000000000000000000..1fb68c4f4a55dc59a8f9f40968ba383ab5f22b52 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day19.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day19 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day20.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day20.html new file mode 100644 index 0000000000000000000000000000000000000000..884ce5de3415d8d80c9221cc2f190495b0913fc5 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day20.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day20 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day21.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day21.html new file mode 100644 index 0000000000000000000000000000000000000000..69e512b7a8d7ff5b91b9a5a440c7529e752377a0 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day21.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day21 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day22.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day22.html new file mode 100644 index 0000000000000000000000000000000000000000..ad82a885573e4d72f22165752d366445b6b94d73 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day22.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day22 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day23.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day23.html new file mode 100644 index 0000000000000000000000000000000000000000..52a9de5ebd66e6626d6e8b7d2e996556eb4d5579 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day23.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day23 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day24.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day24.html new file mode 100644 index 0000000000000000000000000000000000000000..c92009a2cb52193173c189d3539680d2cec19ce2 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day24.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day24 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day25.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day25.html new file mode 100644 index 0000000000000000000000000000000000000000..9097d72c2a9d817262b07e6422e8805c9f41cc9f --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/day25.html @@ -0,0 +1,230 @@ + + + + + APL-and-J - Advent of code-2020-in-APL - day25 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/index.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/index.html new file mode 100644 index 0000000000000000000000000000000000000000..af7716508367c40319e8ec6f3c5ed0f4482f3c2b --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Advent-of-code-2020-in-APL/index.html @@ -0,0 +1,283 @@ + + + + + APL-and-J - Advent of code-2020-in-APL + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Advent of code in APL

    +

    In this small blog series, I will work through the advent of code challenges from 2020 and solve each of them in the programming language APL (the dyalog variant).

    +

    As I go along, I will try to explain any new concepts, functions and operators, so it should hopefully be possible for someone who has never written any APL to follow along, and maybe even try it out for themselves ☺.

    +

    Note: At the time of writing this, the calender almost says August 2021, so it is fair to assume that this writeup will not spoil anything for anyone, unless they are, like me, doing the challenges a few months too late.

    +

    The code for this series is available here, and if you have any comments to the code, please send me an email.

    +

    Links to the days

    + + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Date-puzzle-solver.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Date-puzzle-solver.html new file mode 100644 index 0000000000000000000000000000000000000000..26a5d83c250387fdc59ebe9e4670fe679cbf4587 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Date-puzzle-solver.html @@ -0,0 +1,276 @@ + + + + + APL-and-J - Date puzzle solver + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Finding solutions to the date puzzle using APL

    +

    The problem

    +

    Karl has a puzzle with 8 pieces that almost covers a board with 43 slots, leaving 2 uncovered. Each slot has either the name of a month, or a day number between 1 and 31. The goal is to place all the pieces on the board every day, so that the two slots that aren't covered shows the current date.

    + +

    A picture of the puzzle

    +

    We decided to write a program to find solutions.

    +

    The program

    +

    The program is written using Dyalog APL, and it finds all possible solutions (for all days) in about 30 seconds on my laptop.

    +

    The Solve function finds all solutions and stores them in the global variable SOLUTIONS. The Date function finds all solutions for a given date (by finding all possible solutions and filtering them).

    +

    Solve

    +
    +Solve;board;combine;pieces;size;variants;⎕IO
    +⎕IO←0
    +size←7 7
    +board←size⍴' '
    +board[0 1;6]←'x'
    +board[6;3 4 5 6]←'x'
    +board←,board
    +
    +variants←{
    +    v←,⍵∘{size↑⍵↓(-size)↑⍺}¨⍳1+size-⍴⍵
    +    v,←⌽¨v
    +    v←∪(⌽⍤⍉¨v),(⍉⍤⌽¨v),(⌽⍤⊖¨v),v
    +    v←↑,¨v
    +    v⌿⍨~∨/v∧⍤1⊢board≠' '
    +}
    +pieces←⊂4 2⍴1 1 0 1 0 1 0 1
    +pieces,←⊂3 2⍴1 1 1 1 0 1
    +pieces,←⊂3 3⍴0 1 1 0 1 0 1 1 0
    +pieces,←⊂4 2⍴1 0 1 1 0 1 0 1
    +pieces,←⊂3 3⍴1 0 0 1 0 0 1 1 1
    +pieces,←⊂2 3⍴1 1 1 1 0 1 1
    +pieces,←⊂2 3⍴1 1 1 1 1 1
    +pieces,←⊂2 4⍴0 1 0 0 1 1 1 1
    +pieces←variants¨pieces
    +
    +combine←{
    +    (char places)←⍺
    +    boards←⍵
    +    ⊃⍪⌿(boards≠' ')∘{n←boards⌿⍨~∨/⍺(∧⍤1)⍵ ⋄ n[;⍸⍵]←char ⋄ n}¨↓places
    +}
    +SOLUTIONS←size∘⍴¨↓⊃combine⌿(↓⍉↑'ABCDEFGH'pieces),⊂⍉⍪board
    +
    +

    Date

    +
    +solutions←Date(month day);dindex;mindex;⎕IO
    +⎕IO←1
    +:If ~month∊⍳12
    +    'Invalid month'⎕SIGNAL 11
    +:EndIf
    +:If ~day∊⍳31
    +    'Invalid day'⎕SIGNAL 11
    +:EndIf
    +⎕IO←0
    +
    +:If 0=⎕NC'SOLUTIONS'
    +    ⎕←'Finding all solutions...'
    +    Solve
    +    ⎕←'Done :)'
    +:EndIf
    +
    +mindex←2 6⊤month-1
    +dindex←2 0+5 7⊤day-1
    +solutions←SOLUTIONS⌿⍨{'  '≡⍵[mindex dindex]}¨SOLUTIONS
    +
    +

    Example run

    +
    +      Date 10 6
    +┌───────┬───────┬───────┬───────┬───────┬───────┬───────┐
    +│HHHHBBx│GGAAAAx│GGAAAAx│GGAAAAx│GGAAAAx│GGAAAAx│GGAAAAx│
    +│DDH BBx│GGF FAx│GGF FAx│GGA DDx│GGA DDx│GGA DDx│GGA DDx│
    +│CDDDB A│GGFFF H│GGFFF H│GGDDD C│GGDDD C│GGDDD H│GGDDD H│
    +│CCCAAAA│EEECBHH│EEEDBHH│HHHHCCC│HEEECCC│CEEEFFH│CCBBFFH│
    +│EFCFGGG│ECCCBBH│ECCDBBH│EFHFCBB│HFFECBB│CCCEFHH│ECBBFHH│
    +│EFFFGGG│ECDDBBH│ECDDBBH│EFFFBBB│HHFEBBB│BBCEFFH│ECCBFFH│
    +│EEExxxx│DDDxxxx│CCDxxxx│EEExxxx│HFFxxxx│BBBxxxx│EEExxxx│
    +└───────┴───────┴───────┴───────┴───────┴───────┴───────┘
    +
    +

    Each nested array represents one solution. An x indicates the parts of the board that doesn't exist, and each piece is represented by an uppercase letter from A to H. So, October 6th has different solutions :)

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Designing_an_APL_for_9front.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Designing_an_APL_for_9front.html new file mode 100644 index 0000000000000000000000000000000000000000..3cb9eac256d3df02df726bbb837d4d93a76ea48c --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/Designing_an_APL_for_9front.html @@ -0,0 +1,256 @@ + + + + + APL-and-J - Designing an APL for 9front + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Designing an APL for 9front

    +

    The problem: there is no APL for 9front.

    +

    I know, for most people this is no problem at all. But for me it is. This document intends to describe what I want/need from such a system, but until implementation begins, this is all just ideas. The implementation will most likely begin in february 2022 after my exams.

    +

    Implementation requirements/goals

    +
      +
    1. +Must be implemented in C (don't want to deal with other language issues. One is enough) +
    2. +Must use utf-8 (easy, it is plan 9 after all) +
    3. +Must store code and data as plain text files, no workspaces. +
    4. +Must focus on simplicity in implementation, rather than speed. It is a one man project, and I would rather have slow features than missing features. +
    5. +The primitive functions and operators should be as close to dyalog APL as possible, since that is what I normally use. +
    6. +Must support arbitrary precision integers. +
    7. +No double letter stuff like ⍺⍺ ⍵⍵ and ∇∇ and ∘. +
    8. +
    +

    The above are the top priority goals, and below in the next few sections are some plans for how the goals should be met.

    +

    Goal 1 and 2

    +

    Plan 9 C makes is quite easy to work with unicode data, as it has the Rune type which represents a unicode character. The downsides of using C are well known, such as the need for manually managing memory. However, C is the only fully supported programming language on plan 9 (not considering the shell and awk and stuff like that). While go is ported and works, I don't want to rely on it.

    +

    Goal 3

    +

    Plan 9 gets most of its power from the file system abstractions, and it would simply be stupid to ignore this and save code in a binary workspace format. I also believe it makes is easier for other programmers, since this is the norm in pretty much every language in use. It also means there has to be some way to import the code from other files, perhaps with a ⎕IMPORT, or a feature to link a folder to the session like dyalog does with ]LINK.create.

    +

    Anyways, I want to be able to type )ed someFunction in the REPL an have it create/open the definition of a function/operator in the editor, via the plumber of course.

    +

    Goal 4

    +

    This is important if the implementation is to ever be useful. The simplicity comes in two ways: avoiding implementing unwanted features, and doing the simple thing instead of the fastest.

    +

    The first of those two is pretty simple to acheive: just don't implement the features that I don't want. This would mean that, at least in the beginning, stuff like tradfns and control structures will not be implemented, as I see dfns as superior. New features can always be added later.

    +

    The second is more important. I know the commercial APL implementations are known for their speed due to fancy use of vector instructions and special casing a lot of things, but this takes time and effort and is, in my opinition, not worth it at all in the early stages of the project. It would be nice if the system could allow defining some primitives directly in terms of others, with the definitions written in APL itself. For example, in the C code for (a very simple example), I would like to just write:

    +
    +Array builtin_right_tack(Array alpha, Array omega, ...)
    +{
    +	return PRIM_FUNC("{⍵}", alpha, omega);
    +}
    +
    +

    or something.

    +

    Goal 5

    +

    Familiar primitives are easier to implement. Features from J may be added, as they have some good stuff as well.

    +

    Goal 6

    +

    No more overflows. Plan 9 has <mp.h> which I might use in the beginning.

    +

    Goal 7

    +

    I will use the following symbols instead of those in Dyalog apl:

    +
      +
    • + instead of ⍺⍺ +
    • + instead of ⍵⍵ +
    • + instead of ∇∇ for monadic operator self reference +
    • + instead of ∇∇ for dyadic operator self reference +
    • + instead of ∘. +
    • +
    +

    Current progress See https://git.sr.ht/~pmikkelsen/APL9.

    +

    NOTE: See the new website for this project instead: https://apl.pmikkelsen.com

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/hello_world_apl_and_j.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/hello_world_apl_and_j.html new file mode 100644 index 0000000000000000000000000000000000000000..3a4fd42ef9114741c35b63b6554f6c3c64ef0842 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/hello_world_apl_and_j.html @@ -0,0 +1,209 @@ + + + + + APL-and-J - hello world apl and j + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Introduction

    +

    note: this page requires a font which can show apl symbols.

    +

    APL and J are very different from other (more conventional) programming languages, and therefore they require a little bit of introduction. Their syntax is very dense, and can be hard to read at times for a person not very familiar with it.

    +

    To be written at some point

    +
    ++/⍳200
    +
    +

    is the sum of the first 200 natural numbers in APL, and in J it would be

    +
    ++/i.200
    +
    +

    nice.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/APL-and-J/index.html b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/index.html new file mode 100644 index 0000000000000000000000000000000000000000..fcfb8590195b06b7246cd490de8b2df8b16e16ac --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/APL-and-J/index.html @@ -0,0 +1,202 @@ + + + + + APL-and-J + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/OpenBSD/index.html b/reference/pmikkelsen/pmikkelsen.com/OpenBSD/index.html new file mode 100644 index 0000000000000000000000000000000000000000..60d232ebffe0306444bf63a242c45b9184be7c50 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/OpenBSD/index.html @@ -0,0 +1,196 @@ + + + + + OpenBSD + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/OpenBSD/server-setup.html b/reference/pmikkelsen/pmikkelsen.com/OpenBSD/server-setup.html new file mode 100644 index 0000000000000000000000000000000000000000..79dbe01f4b5e7b25d5c50ef146f777d4f2a93a78 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/OpenBSD/server-setup.html @@ -0,0 +1,195 @@ + + + + + OpenBSD - server setup + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/contact.html b/reference/pmikkelsen/pmikkelsen.com/contact.html new file mode 100644 index 0000000000000000000000000000000000000000..aa4e65b5e1b5ce83f501adf308367694c91d2b33 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/contact.html @@ -0,0 +1,193 @@ + + + + + contact + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    You can reach me on email via petermikkelsen10@gmail.com

    +

    On github, gitlab and most other places, my name is pmikkelsen.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/facts/Fastest-Computer-Languages.html b/reference/pmikkelsen/pmikkelsen.com/facts/Fastest-Computer-Languages.html new file mode 100644 index 0000000000000000000000000000000000000000..8c5abdf0164da88522fdf16a0ef691d5db88da93 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/facts/Fastest-Computer-Languages.html @@ -0,0 +1,222 @@ + + + + + facts - Fastest-Computer-Languages + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    This is a guest post by Karl Holt

    +

    Based on a recent discussion about the fastest computer languages I was encouraged to create my own list by PMikkelsen.

    +

    How to measure a language's speed?

    +

    This is the essence of the discussion and looking at the lists on search engines they all seem to disagree on this point. However most list I've been able to find puts C as number 1 and C++ as number 2. The rest of the lists seems to vary a bit more. This seems a bit weird however, since there is a lot of Turing Complete languages that should outperform these, such as Assembly code. But okay, let's say we only want "high level" languages, then the again it all comes down to the implementation. How efficiently are the programmer thinking about the low level computer architecture. And so on, and so on…. That is why I've choosen to base my list of fastest languages on how fast I personal could make a computer output "Hello World!". This is not a complete list of languages, and only contains the once I want. So take that into consideration.

    +

    The list:

    +
      +
    1. +Prolog I have a prolog terminal open at the moment, so it be very quick to print it out. +
    2. +C I've a program which I debugged by writing "Hello World!" at appropriate places in the file to see which part of the program ran, therefore this is only on command away, here I would also get atleast 5X"Hello World!" so, yes, very fast! +
    3. +Python I can very quick close my Prolog terminal and start Python, also renmeber the sytax for this so it should be quick. +
    4. +APL I can see PMikkelsen is online so I would just ask him for the appropriate code. And I've earlier installed Dyalog on my computer, so I'd say the bottleneck here is how fast PMikkesen takes to answer. +
    5. +SQL I guess I could create a table and populate it with the element "Hello World!", and then ask for the element witd id 42. +
    6. +Javascript I've my browser open next to me, but first I would have to make my peace with that I was about to write JS, takes a bit of time. +
    7. +Haskell I've never written Haskell but I don't think it would take so long. +
    8. +Rust I don't think I would ever complete this, I really don't like the sytax of Rust, so no thanks +
    9. +Runoff The language doesn't have strings or chars, so literally impossible. +
    10. +C# I will never touch that language again. +
    11. +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/facts/index.html b/reference/pmikkelsen/pmikkelsen.com/facts/index.html new file mode 100644 index 0000000000000000000000000000000000000000..656b723afaaad25ecbbcae0751ee5f249e28b56b --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/facts/index.html @@ -0,0 +1,196 @@ + + + + + facts + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/haskell/index.html b/reference/pmikkelsen/pmikkelsen.com/haskell/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7633dd599f507879db15662ab61b3825c695105f --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/haskell/index.html @@ -0,0 +1,196 @@ + + + + + haskell + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/haskell/quine.html b/reference/pmikkelsen/pmikkelsen.com/haskell/quine.html new file mode 100644 index 0000000000000000000000000000000000000000..954d720cdf3effc68b388fdae675e453d0a62929 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/haskell/quine.html @@ -0,0 +1,246 @@ + + + + + haskell - quine + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Today I am going to go through the process of writing a small program which prints its own source when executed. These kinds of programs are also called quines, and I suggest that you try it out on your own if you haven't already done so, as it is a very fun little problem! So if you don't want any spoilers, please leave this page now and come back later.

    +

    First attempt

    +

    Okay, so first of let's just write a small hello world program to get things going. All our code will be in a file called quine.hs. The code for hello world looks like this

    +
    +main = putStrLn "Hello world!"
    +
    +

    When this is run using runhaskell quine.hs, it produces the output

    +
    +Hello world!
    +
    +

    Well, not quite a quine yet but we are getting something to the screen at least ;)

    +

    Second attempt

    +

    Now we get the idea that we copy the entire program's source into a string and print that string instead. To do this, the code could look something like this

    +
    +main = putStrLn code
    +  where code = "main = putStrLn code\n  where code = ???"
    +
    +

    Here we run into a problem, since we can't include the entire code into the string. Copying everything we can into the string just increases the size of the string itself, which means that there is now even more to copy! We start by only copying all the code upto the string and see how it looks when executed. The code is now

    +
    +main = putStrLn code
    +  where code = "main = putStrLn code\n  where code = "
    +
    +

    And it outputs

    +
    +main = putStrLn code
    +  where code =
    +
    +

    Quite good! Now if we could only include the string itself in its printed form, with the quotes and all, and not the interpreted form with \n shown as newlines.

    +

    Third attempt

    +

    After looking through the haskell standard libraries for a bit, we find a function that looks promising for what we want to do. This function is print, which prints the output using the show function instead of interpreting the string. We would want to both print it as before, and to print it using print, so we change our main to be main = putStrLn code >> print code, and update our string to include the print. The code then becomes

    +
    +main = putStrLn code >> print code
    +  where code = "main = putStrLn code >> print code\n  where code = "
    +
    +

    And it outputs

    +
    +main = putStrLn code >> print code
    +  where code =
    +"main = putStrLn code >> print code\n  where code = "
    +
    +

    So close! The only problem is that the putStrLn append a newline after the output, which we don't want in this case.

    +

    Final attempt

    +

    The simple fix is just to use putStrLn's little brother putStr which doesn't print that newline. The final program is then

    +
    +main = putStr code >> print code
    +  where code = "main = putStr code >> print code\n  where code = "
    +
    +

    And luckily it outputs exactly itself

    +
    +main = putStr code >> print code
    +  where code = "main = putStr code >> print code\n  where code = "
    +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/index.html b/reference/pmikkelsen/pmikkelsen.com/index.html new file mode 100644 index 0000000000000000000000000000000000000000..3e3bae1365637ee0c4ccf3d464e90f574e43dd0d --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/index.html @@ -0,0 +1,223 @@ + + + + + Peter's website - random notes + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    This website

    +

    My intention with this website is to share some ideas and thoughts on programming and other computer related subjects. The things I care about and find interesting at the moment are written below, and are updated sometimes. Hopefully, most of the content will be about one of those things.

    +
      +
    • +Functional programming (Haskell, Erlang, Scheme) +
    • +Array languages (APL and J) +
    • +Concurrent programming (Erlang, Go) +
    • +Plan 9 (the 9front fork) +
    • +
    +

    For information about how the website is setup, see this post. The nice color theme is made by my girlfriend.

    +

    Me

    +

    My name is Peter Mikkelsen and I am a software developer at Dyalog LTD, working on their APL interpreter. Location: Denmark.

    +

    The following list contains other facts and links

    +
      +
    • +Age: 27 +
    • +Favourite programming language: See this post (APL, Prolog and C) +
    • +Current job: Software developer at Dyalog LTD. +
    • +Stuff I use: See this post. +
    • +Tabs vs spaces: Tabs. +
    • +Text editor: I used to use acme (see this), but I like sam more these days. +
    • +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/linux/eduroam.html b/reference/pmikkelsen/pmikkelsen.com/linux/eduroam.html new file mode 100644 index 0000000000000000000000000000000000000000..ef8a204e08d2438cdfe2edf494d07ed687739bdc --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/linux/eduroam.html @@ -0,0 +1,208 @@ + + + + + linux - eduroam + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Connecting to the eduroam network on AAU

    +

    Goto net.aau.dk and create a new device.

    +

    Connect to the eduroam network and set the correct wifi-security settings:

    +
    +security: WPA & WPA2 Enterprise
    +Authentication: PEAP
    +CA Cert: no CA certificate is required
    +PEAP Version: Automatic
    +Inner authentication: MSCHAPv2
    +
    +

    And fill out the username and password from the website.

    +

    No need for the stupid script.

    +

    NOTE: Sometimes it doesn't work with Pop!_OS lol. "But how do I fix this??" you may ask. Easy. Install a better operating system.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/linux/index.html b/reference/pmikkelsen/pmikkelsen.com/linux/index.html new file mode 100644 index 0000000000000000000000000000000000000000..515a5d69803985eb679149ea62483194b8d05586 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/linux/index.html @@ -0,0 +1,198 @@ + + + + + linux + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/linux/wifi.html b/reference/pmikkelsen/pmikkelsen.com/linux/wifi.html new file mode 100644 index 0000000000000000000000000000000000000000..bca6fdfb711126064700d9e1f2f6a2b215914ddf --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/linux/wifi.html @@ -0,0 +1,203 @@ + + + + + linux - wifi + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Connecting to wifi on linux

    +

    What I have to do:

    +
    +wpa_passphrase NameOfNetwork NetworkKey >> /etc/wpa_supplicant/wpa_supplicant-wlp4s0.conf
    +
    +

    The network card name might be different.

    +

    Then reboot aaaand done :)

    +

    This is on void linux, so it might not be the same for you.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/mainframe/MVS-TK5-Setup.html b/reference/pmikkelsen/pmikkelsen.com/mainframe/MVS-TK5-Setup.html new file mode 100644 index 0000000000000000000000000000000000000000..4cf72d6b95aab56c3ee7860de0d2e9ca09209cda --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/mainframe/MVS-TK5-Setup.html @@ -0,0 +1,214 @@ + + + + + mainframe - MVS-TK5-Setup + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Introduction

    +

    This is how I setup mainframe.pmikkelsen.com, which runs MVS TK5. It might not be the best way to do things, and it for sure isn't the most secure way, but.. yeah.

    +

    Setup a server

    +

    I chose an ubuntu 24.04 server from Hetzner, and hopefully the cheapest one is powerful enough.

    +

    Download and setup TK5

    +

    At the time of writing, the version I downloaded is MVS TK5 update 4.

    +
    +cd somewhere/that/makes/sense
    +wget https://www.prince-webdesign.nl/images/downloads/mvs-tk5.zip
    +chmod -R +x *
    +cd unattended
    +./set_console_mode
    +./mvs
    +
    +

    Now the system is running, and you should be able to connect to it using x3270 on linux, specifying the server's IP and port 3270.

    +

    It is probably a good idea to run the ./mvs script inside screen or tmux so the ssh connection to the server can be closed without stopping the emulator.

    +

    Setting up accounts

    +

    It is probably a good idea to change the passwords for the default accounts, or at least the admin ones. Also, while we are at it, adding some new users can be added. Both of these steps are described in the Adding Users guide.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/mainframe/adding-users.html b/reference/pmikkelsen/pmikkelsen.com/mainframe/adding-users.html new file mode 100644 index 0000000000000000000000000000000000000000..16eb860d0268a86eb27a6d9b3e411dc9c2ac47c9 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/mainframe/adding-users.html @@ -0,0 +1,219 @@ + + + + + mainframe - adding users + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Adding a new user

    +

    Let's add a user called TAGE (named after the guy from the "Dage med Tage" sketch), with the password linie.

    +
      +
    • +Login as someone who has rights to do this sort of thing, such as HERC01 +
    • +Navigate to SYS2.JCLLIB(ADDUSER) +
    • +Tweak it as needed, so the last line is //ADDUSER EXEC ADDUSER,HLQ=TAGE,UTYPE=USER +
    • +
    +

    The username is specified after HLQ, and the user type here is USER, but it could also have been SYSP.

    +
      +
    • +Submit the job (write SUBMIT on the Command ===> line and hit enter). +
    • +Navigate to SYS1.SECURE.CNTL(USERS) and add a new line with the contents TAGE USER ABCD N (the fields must line up with the rest of the file, and ABCD is the password). +
    • +
    +

    Changing password

    +

    To change your password, connect to the mainframe and at the Logon ===> prompt, type your username. Instead of replying with your password, reply with linie/snaps, where linie is your current password, and snaps is your new password.

    +

    /s rakfuser (IMPORTANT)

    +

    To make any of the changes effective, you must run /s rakfuser on the mvs console (the linux terminal session where ./mvs is running).

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/mainframe/howto.html b/reference/pmikkelsen/pmikkelsen.com/mainframe/howto.html new file mode 100644 index 0000000000000000000000000000000000000000..99bcebb927556a4c2524c16116fa3aa77739ae0e --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/mainframe/howto.html @@ -0,0 +1,234 @@ + + + + + mainframe - howto + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Transfer file to/from MVS

    +

    Let's say I have written some wise words in a file on mvs, and I want a copy on my linux machine. The MVS file name is PETER.TEST.TEXT(WISDOM), and the linux file is /tmp/wisdom.txt. In the file transfer gui, the MVS file name must be enclosed in single quotes.

    +
      +
    • +On MVS: hit F3 until you get to the READY prompt. +
    • +Now click File > File transfer... in x3270, and type in the local (linux) and host (mvs) file names. The options selected should be Receive from host, Host is TSO, Transfer ASCII file. I leave the rest as it is. +
    • +Click Transfer File +
    • +Check that it transferred the file. +
    • +
    +

    Example file contents:

    +
    +peter@fedora:~$ cat /tmp/wisdom.txt 
    +Så blev de sgu sure.
    +Det er linie.
    +
    +

    To transfer a file from linux to mvs, follow the same steps, but click the Send to host option instead.

    +

    Get back to "the main menu" (ISPF) after hitting F3 too many times

    +

    Type ispf at the READY prompt.

    +

    Exit the editor when it says "SAVE not valid in VIEW mode"

    +

    You have opened the editor in view mode (v), but made changes. You should probably have opened it in edit mode (e). For now, type cancel to discard your changes, and try again in edit mode this time.

    +

    Help, I can't type anything, and there is a big red X at the bottom of my x3270 window

    +

    Hit RESET (Alt-r), and place the curser somewhere where you are allowed to type.There is also HOME (Alt-h) which is nice.

    +

    Scroll

    +
      +
    • +Up: F7 +
    • +Down: F8 +
    • +Left: F10 +
    • +Right: F11 +
    • +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/mainframe/index.html b/reference/pmikkelsen/pmikkelsen.com/mainframe/index.html new file mode 100644 index 0000000000000000000000000000000000000000..45749d1c95d46565f4f5c41b1e13a7a7a356b027 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/mainframe/index.html @@ -0,0 +1,200 @@ + + + + + mainframe + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/me/how-i-started-using-acme.html b/reference/pmikkelsen/pmikkelsen.com/me/how-i-started-using-acme.html new file mode 100644 index 0000000000000000000000000000000000000000..ce27e211cf77aaccf6479dab30a437b13dba999e --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/me/how-i-started-using-acme.html @@ -0,0 +1,223 @@ + + + + + me - how i-started using acme + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    The beginning

    +

    My very first code editor was visual studio 2010 for windows 7. This was when I didn't know what programming was, and a teacher I had suggested that we used that, so we could start learning some C#. It was very fun and all, but soon after, I decided that I wanted to learn another language, and the whole idea of using an IDE which is specialized for a specific programming language or environment just seemed very odd to me. Surely there had to be better options, where I as a user could decide by myself what languages I wanted support for. I tried out multiple different small editors but didn't really like any of them.

    +

    After some time, I decided that I wanted to try linux, and I installed fedora or linux mint (don't remember at this point), and I liked it very much. Comming from windows where it is normal just to go to a random website and download the tools I needed, it was a great joy to be able to just type a command in the terminal and watch my program get installed.

    +

    First try: vim

    +

    After reading online for some time, it seemed that the editor which all the cool linux users used was vim, so I decided to learn that. The experience was very different from what I was used to, but I liked the keyboard shortcuts and that it looked very cool. Of course I installed every plugin that I had read about online and it all became a mess, but I stuck with it for around 3-4 years. The things I liked the most was that I felt it was very fast to do what I wanted, but unfortunately the flow with multiple files was never something I could get used to, and all the plugins made me sick.

    +

    Second try: emacs

    +

    Just to give another very popular editor a try, I installed emacs sometime 2-3 years ago. Comming from vim, the keyboard shortcuts in emacs sucks, but the editor itself is just so much more powerful, because plugins and customisations could be written in a real programming language. I started, as many other emacs users do, to use emacs for everything i could. I read my mails, watched PDFs, managed my system, and even used it as my window manager for a period. Around the same time that I started using emacs, I also started using OpenBSD as a secondary operating system. I noticed that many very good tools are available in unix, but emacs almost has everything implemented again in elisp, which seemed stupid to me. But hey, it works so I stuck with it. Until late 2019.

    +

    Now acme

    +

    One day in school when one of my group mates asked if I could look at something for him, I saw that he was using visual studio code, which made it natural to use a mouse to click around in the file. Of course this was also possible in emacs, but since I came from vim, it was never something that I did. He argued that it was much faster to just click in the file where he wanted to edit, than to navigate using the keyboard, and I thought that maybe he was right, so I started digging. After some time looking though the internet for some editors which made much use of the mouse, I found acme and decided to install it. And wow it was different.

    + +

    A picture of acme in action

    +

    Acme uses the mouse for everything, since there are very few keyboard shortcuts (not even copy and paste). As shown on the picture, there are no menus and no icons; everything is just text, and the different buttons on the mouse can interpret that text in different ways. For example, middle clicking on the text New wil create a new text frame, and right clicking on the text example will search the file for the word. Actually, it is more advanced than that since the right click will first send the selected text to something called the plumber, which might do something fun like opening the file which has that name. I suggest interrested readers to read the page here and some of the documents linked from that site to learn more about acme. The video introduction from Russ Cox here is also great.

    +

    What I like about acme

    +
      +
    • +

      The colours: they cannot be changed without modifying the source, but luckily for me, I love those pale bright colours. In fact, there are the very reason this website has the colours that it has.

      +
    • +

      Writing commands: since acme allows users to control it via the 9P protocol (if you don't understand, read the links above), it is possible to write "plugins" or commands in whatever language I want. After just creating a program with the needed functionality, it is possible to write the name somewhere and middle click on it, just like it was always there. Not may editors makes it possible to use the environment as much as acme does, which was also one of my wonders about emacs back then. It allows me to turn it into my IDE using whatever tools I see fit, instead of depending on support directly in the editor.

      +
    • +

      Everything as text: this means that if I run a gdb session via the win command, it is totally possible for me to just scroll up in the history and delete lines which are not important, and to write notes as I debug. Also, since commands are just text which is clicked, it is possible to have a document with commands which are useful in a given project, which I can then open and click.

      +
    • +

      Lack of customisation: while this might seem strange, comming from a vim and emacs background, it surely is wonderful to have an editor which does not encourage the user to customise the hell out of it. I have spent way too much time doing this in the past and it had to stop.

      +
    • +

      Lack of syntax highlighting and auto completion: some people love it and can't live without it, but I very much prefer to learn the syntax of the language based on the contents, not based on some colours an editor throws at me. Also I feel like I learn and remember much better when there is no auto completion.

      +
    • +
    +

    Other editors I use sometimes

    +

    Sometimes I have to do very small editing tasks, and sometimes as root, in which case it is just simpler to open the file in vi. Note that this is the small vi, and not the "improved" vim. I also sometimes edit my text in sam with is another editor written by Rob Pike, and I quite like that one too for smaller projects. You can read more about sam here.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/me/index.html b/reference/pmikkelsen/pmikkelsen.com/me/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c1d9f979ec19290dfc3b8321c6fd81aea05775dc --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/me/index.html @@ -0,0 +1,198 @@ + + + + + me + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/me/stuff-i-use.html b/reference/pmikkelsen/pmikkelsen.com/me/stuff-i-use.html new file mode 100644 index 0000000000000000000000000000000000000000..b28bcd40d0573a73bab1bb41ff2ea4a9d80139f3 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/me/stuff-i-use.html @@ -0,0 +1,213 @@ + + + + + me - stuff i-use + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +
      +
    • +Note: Last updated on 2020/05/28 +
    • +
    +

    Operating system

    + +

    I mostly use guix but sometimes I need software that is not yet ported, and then I use fedora. If I could, I would use 9front alot more, since the system is much better and different in my opinion. I also like OpenBSD alot.

    +

    Text editor

    +

    Acme from plan9port. Sometimes I use emacs if I have to edit scheme code, since automatic closing of matching ( and ) makes life much easier.

    +

    Shell

    +

    I use the rc shell since it works nicely in both acme and 9term from plan9port. Also I like its syntax alot more than the syntax of bash.

    +

    Web browser

    +

    Mainy firefox (this page is only tested on firefox, so please let me know if you have problems on other browsers).

    +

    Laptop

    +

    I use a Lenovo Thinkpad E495 with an AMD ryzen 3700U and 16 gigabytes of ram. It is a fairly good computer for the price, and OpenBSD is supported out of the box with the exception of wifi. For this reason, I have small usb wifi dongle that is constantly plugged in, which performs a lot worse than what some people would like, but for me it is no big deal.

    +

    Mouse and keyboard

    +

    Since I have never been a fan of touchpads on laptops, I use an external mouse which is a Logitech MX Master 3. I also have a keyboard that I sometimes plug in if I have to do more writing than what I can comfortably do on my laptop. The keyboard is from the coolermaster masterkeys lite L bundle. Clicking in acme using the scroll wheel instead of using a true 3-button mouse is sometimes a bit annoying, but its OK.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/opinions/favourite-programming-languages.html b/reference/pmikkelsen/pmikkelsen.com/opinions/favourite-programming-languages.html new file mode 100644 index 0000000000000000000000000000000000000000..424916a28cd82ff489a303f7ed587d84351a4bbd --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/opinions/favourite-programming-languages.html @@ -0,0 +1,195 @@ + + + + + opinions - favourite programming languages + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/opinions/index.html b/reference/pmikkelsen/pmikkelsen.com/opinions/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4b0591fb86200df673d7e064e2fa5d55db88363d --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/opinions/index.html @@ -0,0 +1,196 @@ + + + + + opinions + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/basic_9p_server.html b/reference/pmikkelsen/pmikkelsen.com/plan9/basic_9p_server.html new file mode 100644 index 0000000000000000000000000000000000000000..fa7a22ba431e1c749f04cfeea1262182e62f73fe --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/basic_9p_server.html @@ -0,0 +1,242 @@ + + + + + plan9 - basic 9p server + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Writing a basic 9P server

    +

    On plan 9 the entire system is build around the idea of namespaces and that "everything is a file". For this reason it is very easy to write a new 9P fileserver in C since all the boring tasks are implemented in libraries. This note describes a minimal program which serves a folder to /mnt/hello9p containing a single synthetic file with the contents "Hello from 9P!".

    +

    The code

    +
    +#include <u.h>
    +#include <libc.h>
    +#include <fcall.h>
    +#include <thread.h>
    +#include <9p.h>
    +
    +void
    +fsread(Req *r)
    +{
    +	readstr(r, "Hello from 9P!\n");
    +	respond(r, nil);
    +}
    +
    +Srv fs = {
    +	.read = fsread,
    +};
    +
    +void
    +main(void)
    +{
    +	Tree *tree;
    +
    +	tree = alloctree(nil, nil, DMDIR|0555, nil);
    +	fs.tree = tree;
    +	createfile(tree->root, "hello", nil, 0555, nil);
    +
    +	postmountsrv(&fs, nil, "/mnt/hello9p", MREPL | MCREATE);
    +}
    +
    +

    Explanation

    +

    The global variable fs is a structure which contains function pointers to all the 9P handlers, but since I only plan on reading from the file, only the read field is set. The fsread function calls two helper functions from the 9p(2) library which will create a response with the given string as the file contents.

    +

    In main I start by allocating a new file tree, since this 9P server deals with a fileserver that has a tree structure, and therefore I don't have to worry about how directories are handled for example. A file is added with createfile to the root of the tree.

    +

    The call to postmountsrv will mount the 9P server under /mnt/hello9p.

    +

    Thats it

    +

    This is not very complicated, but see the manpages at 9p(2) and 9pfile(2) and intro(5) for more information about the libraries and 9P itself.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/discord.html b/reference/pmikkelsen/pmikkelsen.com/plan9/discord.html new file mode 100644 index 0000000000000000000000000000000000000000..348658dab0a64f833683addc05e387223458b1bb --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/discord.html @@ -0,0 +1,242 @@ + + + + + plan9 - discord + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Chatting on discord from 9front

    +

    Sometimes you work with people who doesn't want to use the same communication tools as you do. A sad example is when your team members wants to use discord, and not something simpler like IRC. Oh well, gotta deal with it.

    +

    This is the reason I wrote a "discord bot" (ugh) which can run on your 9front system and allow you to chat on discord anyways.

    +

    Example gif

    +

    The example below just opens two chat windows with different channels in each. While it works both in acme and in the terminal, I like having everything together inside acme.

    + +

    An animated gif showing discord chats from 9front

    +

    The code

    +

    The project is made of a few scripts and a go program. The only thing that actually communicates with discord is the go program, and the scripts just makes it easier to send and recieve on the correct channels. The code is available here, and there is a precompiled version of the go program included (compiled for 9front amd64).

    +

    Usage

    +

    To use the service, you must first create a bot on discord and get the access token. I personally found this step much more confusing then the actual coding itself, which either tells you something about my google skills, or about discord.. Oh, and then you must invite the bot to your discord server..

    +

    Next, the server part of the bot must be started:

    +
    +`discordsrv YOURTOKEN`
    +
    +

    This will post a pipe in /srv/discordfront, where messages can be send and recieved from, but you should not read from it directly. The discordsrv script does this for you as well, and it takes each line and dumps it in a nice readable format into $home/lib/discord/logs/$serverName/$channelName where the server name is the name of a discord server (or guild?), and the channel name is, well, the name of the channel.

    +

    Now that the server is started, you can either run discordacme which opens an acme with the file $home/lib/discord/channels open. This file is not handled by any of the scripts, so it is just a handy text file to keep shortcuts to various channels (see the gif for an example). Inside discordacme, the openChat command will open a new chat window, using the simpler discord script.

    +

    The discord script simply runs tail -f on the given channel's logfile while it reads messages from standard input and sends them to /srv/discordfront at the same time.

    +

    Using remotely

    +

    Since this program does not fetch previous messages, it might be a good idea to run the server part discordsrv on a machine that is always online, so that all messages gets logged. Since this is plan9, it is almost trivial to still use the client on your local machine, just by using rimport to import the relevant file trees from the server.

    +

    Here is what I do (in a seperate script which is run at startup):

    +
    +#!/bin/rc
    +rfork
    +rimport -ac -p $serverhost /srv
    +rimport -c -p $serverhost /usr/glenda/lib/discord
    +discordacme
    +
    +

    I don't even notice it is not running locally.

    +

    Notes

    +
      +
    • +Yes, the names of the scripts suck. +
    • +Yes, there is a lot of missing functionality. +
    • +No, this has not been tested very much, it just seems to do the job well enough for now. +
    • +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/dns.html b/reference/pmikkelsen/pmikkelsen.com/plan9/dns.html new file mode 100644 index 0000000000000000000000000000000000000000..16304b8ae2ecfc821624988b9dd36659095a4ed3 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/dns.html @@ -0,0 +1,230 @@ + + + + + plan9 - dns + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Using 9front as an authoritative DNS server

    +

    This note describes the steps I took to make the 9front server at pmikkelsen.com the authoritative dns server for itself.

    +

    First, I logged into my domain name registrar and changed the dns servers for my domain to ns1.pmikkelsen.com and ns2.pmikkelsen.com (It would not let me have just one, but I choose to live dangerously and point both of those domains at the same server).

    +

    To let the world know where ns1 and ns2 can be found, I added their ip on the registrar's website (since my own dns server cannot serve them for good reasons). Anyways, this might not be the same for you since you may not use the same provider.

    +

    Starting the dns server in "serve mode"

    +

    First I added 1 line to the /cfg/$sysname/cpurc file to enable the dns server.

    +
    +ndb/dns -s
    +
    +

    After that I added a few lines in /lib/ndb/local to setup all the dns records I needed:

    +
    +dom=pmikkelsen.com soa=
    +	ip=80.240.16.196
    +	mx=vps1.pmikkelsen.com pref=1
    +	txtrr="v=spf1 a mx ip:80.240.16.196 ~all"
    +
    +dom=p9auth.pmikkelsen.com soa=
    +	ip=80.240.16.196
    +
    +dom=vps1.pmikkelsen.com soa=
    +	ip=80.240.16.196
    +
    +dom=_dmarc.pmikkelsen.com soa=
    +	txtrr="v=DMARC1; p=none"
    +
    +

    With this done, I now have A records, mx records and txt records in place, so my website, mail and rcpu works as expected.

    +

    Bye.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/fonts.html b/reference/pmikkelsen/pmikkelsen.com/plan9/fonts.html new file mode 100644 index 0000000000000000000000000000000000000000..8f9e4fae3ef65259a5acec9e5f8a6672db0f2b9e --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/fonts.html @@ -0,0 +1,222 @@ + + + + + plan9 - fonts + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Fonts on 9front

    +

    By default 9front uses a font called VGA but its too small for my eyes.

    + +

    The fonts I use (dejavu) look like thisan image showing the fonts and are attached below:

    +

    proportional font

    +

    monospace font

    +

    They can be recreated by having them installed on linux and doing the following from linux with plan9port installed.

    +
    +fontsrv -m /tmp/fonts
    +cp -r /tmp/fonts/DejaVuSomeThing/14a/ /tmp/djv
    +
    +

    You can try a different font or font size if you want.

    +

    Then connect to 9front via drawterm and run:

    +
    +mkdir /lib/font/bit/djv
    +dircp /mnt/term/tmp/djv /lib/font/bit/djv
    +
    +

    Finally change your lib/profile to use /lib/font/bit/djv/font :)

    +

    Note that 9front includes truetypefs which allows you to use .ttf files directly, but I find the results are better looking this way.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/index.html b/reference/pmikkelsen/pmikkelsen.com/plan9/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0fa42fb3e230e83a5d3f34fe731edf421e3e9540 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/index.html @@ -0,0 +1,214 @@ + + + + + plan9 + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/lets_encrypt.html b/reference/pmikkelsen/pmikkelsen.com/plan9/lets_encrypt.html new file mode 100644 index 0000000000000000000000000000000000000000..3f33c8e9a281896435d048e446d23fce7f60a06b --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/lets_encrypt.html @@ -0,0 +1,251 @@ + + + + + plan9 - lets encrypt + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    How I get tls certificates for 9front

    +

    First of all, I use linux and drawterm for this for now, but I would like to be able to do it all from 9front at some point.

    +

    Generate the certificate

    +

    Install certbot on linux and run the following command

    +
    +certbot certonly --manual -d pmikkelsen.com -d vps1.pmikkelsen.com
    +
    +

    and do the challenges, they should be easy. I use the diff here to make 9fronts dns server understand the needed records.

    +

    EDIT: As of Sun Feb 14 2021, this patch is no longer needed since cinap pushed a proper fix.

    +

    Importing the cert and private key

    +

    Start drawterm and login as the hostowner. After this, the filesystem of the linux system is available at /mnt/term. Run the following:

    +
    +cd /sys/lib/tls/
    +cp /mnt/term/etc/letsencrypt/live/pmikkelsen.com/privkey.pem ./
    +cp /mnt/term/etc/letsencrypt/live/pmikkelsen.com/fullchain.pem ./cert
    +
    +

    Now the private key must be converted to one that can be loaded into factotum

    +
    +auth/pemdecode 'PRIVATE KEY' privkey.pem | auth/asn12rsa -t 'service=tls role=client' > key
    +rm privkey.pem
    +chmod 400 key
    +
    +

    Add the following to /cfg/$sysname/cpurc to load the private key on boot.

    +
    +cat /sys/lib/tls/key >> /mnt/factotum/ctl
    +
    +

    Done. The key can also be stored in secstore if that is setup, so it doesn't lay unencryped on the disk.

    +

    SMTP over TLS

    +

    I have the following in /bin/service.auth/tcp25

    +
    +#!/bin/rc
    +user=`{cat /dev/user}
    +exec upas/smtpd -c /sys/lib/tls/cert -n $3
    +
    +

    Notice I had to put it in the /bin/service.auth folder so that it could find the private key.

    +

    Https with rc-httpd

    +

    I have the following in /bin/service.auth/tcp443

    +
    +#!/bin/rc
    +
    +exec tlssrv -c /sys/lib/tls/cert -l /sys/log/https /bin/service/tcp80 $*
    +
    +

    Again, in the /bin/service.auth folder. It simply wraps the plain http service in a tls wrapper. The plain tcp80 service looks like this for me

    +
    +#!/bin/rc
    +PLAN9=/
    +auth/none /rc/bin/rc-httpd/rc-httpd >>[2]/sys/log/www
    +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/mounting-9p-over-drawterm.html b/reference/pmikkelsen/pmikkelsen.com/plan9/mounting-9p-over-drawterm.html new file mode 100644 index 0000000000000000000000000000000000000000..e4aa959a4a0d72def0ad6da47210804bd728c770 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/mounting-9p-over-drawterm.html @@ -0,0 +1,242 @@ + + + + + plan9 - mounting-9p over drawterm + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Mounting a 9P connection over drawterm

    +

    I sometimes use drawterm on linux to connect to my 9front server. While it is possible to access the host system's files under /mnt/term, there is no builtin way to access the remote system's file under linux. Now, why would anybody want to do this? In my case, I often want to write some code under 9front, but for languages which aren't supported such as prolog in this case, so there are three options as I see it:

    +
      +
    • +Store the files on the host machine, and access them under /mnt/term. +
    • +Store the files on the server and somehow mount the server's filesystem on the host. +
    • +Store the files on a third machine that both the host and server can access. +
    • +
    +

    Option number two seems best for me, so I asked around and it seems like the best tool to mount a 9P connection on linux is 9pfs.

    +

    How it works

    +

    Before I could mount the connection, I had to serve it somehow. Normally I already serve 9P directly from my server's filesystem, but that requires some authentication that 9pfs does not support, so I had to serve it without authentication. Serving directly to the internet without authentication is of course pretty dumb since everyone can then access my files, so thanks to a hint from hiro, I figured out that it is actually possible to use the host's network stack on the server by binding /mnt/term/net over /net.

    +

    I'll just show the final script below and explain it afterwards:

    +
    +#!/bin/rc
    +
    +rfork n
    +bind /mnt/term/net /net
    +aux/listen1 -t tcp!*!12335 /bin/exportfs -r / &
    +os mkdir -p /tmp/drawterm
    +os 9pfs localhost -p 12335 /tmp/drawterm
    +
    +

    So the first thing that happens is that I bind the host's network in, and from that point on, every network connection in this namespace actually goes out from the host instead of from the server!

    +

    Then exportfs is started and it is serving the / directory over 9P at port 12335. The os command runs a command on the host, so it just creates the folder that the system will be mounted to, and then uses 9pfs to actually mount it. The nice thing here is that 9pfs just connects to localhost.

    +

    Using it

    +

    As I said in the beginning, I did this to be able to edit files on the 9front server, and run compilers/interpreters on linux. The os command goes a long way, but the following script makes it even easier (I have this installed as linux):

    +
    +#!/bin/rc
    +
    +dir=/tmp/drawterm/`{pwd}
    +os -d $dir $*
    +
    +

    This means I can just go into any directory on the server, type linux ghci and I get a haskell repl running in the correct directory, as seen in the gif below.

    + +

    An animated gif showing ghci loading a file on the 9front server

    +

    Final notes

    +

    The bind net trick still blows my mind a bit, since it is so trivial, yet so powerful. It is also fun to think about how one would do this on other systems than plan9, which I can't even imagine.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/network_booting.html b/reference/pmikkelsen/pmikkelsen.com/plan9/network_booting.html new file mode 100644 index 0000000000000000000000000000000000000000..2c11adea3f17b173233c1796ebd7d854bbf5786f --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/network_booting.html @@ -0,0 +1,223 @@ + + + + + plan9 - network booting + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Network booting into the server at pmikkelsen.com

    +

    Sometimes it is nice to be able to connect directly to a remote server from my laptop and have the same root filesystem available. This is possible by typing tls at the boot prompt and then typing pmikkelsen.com for the fs and auth server.

    +

    Speed

    +

    On my internet connection some things can be very slow (such as compiling the entire system), because of fs access now happens over the network. The easy fix is to just start a cpu connection to the server where the fs access can happen fast since it is on the same machine. This is done by typing

    +
    +rcpu -h pmikkelsen.com
    +
    +

    Of course the server has a pretty slow cpu..

    +

    Server settings

    +

    Some steps are needed to make this work:

    +
      +
    1. +The user must be added to the fileserver and auth server. +
    2. +The fileserver must be listening for remote connections. +
    3. +The correct ndb entries must be set (in the beginning I forgot fs and I could only connect via tcp, not tls) +
    4. +
    +

    More information about all those steps can be found in section 7 of the 9front FQA.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/trellofs.html b/reference/pmikkelsen/pmikkelsen.com/plan9/trellofs.html new file mode 100644 index 0000000000000000000000000000000000000000..4686c36814b9fac02b37f08b3f6df0d412195770 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/trellofs.html @@ -0,0 +1,533 @@ + + + + + plan9 - trellofs + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    A filesystem for viewing trello

    +

    Since my last note here was very simple, here comes a small program (around 250 lines of C), which makes it possible to view trello as a read-only filesystem.

    +

    Usage example

    +

    First set the trellokey and trellotoken environment variables to the API key and token from the trello website.

    +
    +term% trellokey=1298791723987937123.....
    +term% trellotoken=923748237497ab798798999999.....
    +
    +

    Then webfs must be started so the program can make requests to the trello REST api.

    +
    +term% webfs
    +
    +

    Then trellofs itself must be started. It mounts the filesystem under /mnt/trello.

    +
    +term% trellofs
    +
    +

    If I now go and see which boards I have, I get the following

    +
    +term% cd /mnt/trello
    +term% ls
    +Beaglebone_Black
    +Fly
    +Fysik_Rapport
    +Guld_kobber
    +Ideer_til_2._produkt
    +Lektier
    +P0
    +P1
    +P2
    +Projekt_Materialer
    +Spil
    +Welcome_Board
    +
    +

    The names of the folders are almost like the original board names, except that that some characters have been replaced by _. Lets look at P1

    +
    +term% cd P1
    +term% ls
    +Backlog
    +Done
    +Estimat
    +In-progress
    +Info
    +Master.C_Top_Down_Ting
    +Sprint_1
    +Test
    +Test_sprint_1
    +Todo
    +
    +

    Todo must have something worth looking at

    +
    +term% ls
    +Færdig_rapport_aflevering
    +Korrekturlæsning
    +
    +

    Those two items are the actual trello "cards", which I think of as tasks. The first one means "Final report hand in", so let's have a look at that.

    +
    +term% cd Færdig_rapport_aflevering
    +term% ls
    +description
    +duedate
    +url
    +
    +

    There are always three files inside each card folder, but since the information in them is not mandatory on trello, some of them will be empty.

    +
    +term% cat description
    +term% cat duedate
    +2019-12-18T13:00:00.000Z
    +term% cat url
    +https://trello.com/c/u23ZcNAm/9-f%C3%A6rdig-rapport-aflevering
    +
    +

    Limitations

    +

    The key and token are right now in environment variables, which is somewhat awkward. Also I would like to be able to actually create and move cards directly from the filesystem just by creating files, but that is not something I will implement right now.

    +

    The code

    +

    The code for the trellofs program is listed below.

    +
    +#include <u.h>
    +#include <libc.h>
    +#include <fcall.h>
    +#include <thread.h>
    +#include <9p.h>
    +#include <json.h>
    +
    +#define MAX_RESPONSE_SIZE (1024 * 1024 * 8)
    +
    +char *key;
    +char *token;
    +
    +void
    +fsread(Req *r)
    +{
    +	char *str;
    +
    +	if (r->fid->file->aux == nil) {
    +		readstr(r, "");
    +	} else {
    +		str = malloc(strlen(r->fid->file->aux) + 2);
    +		sprint(str, "%s\n", r->fid->file->aux);
    +		readstr(r, str);
    +	}
    +	respond(r, nil);
    +}
    +
    +Srv fs = {
    +	.read = fsread,
    +};
    +
    +JSON *
    +trelloget(char *endpoint, char *params)
    +{
    +	int ctlfd, bodyfd;
    +	int n;
    +	int err;
    +	char *buf;
    +	JSON *res;
    +
    +	res = nil;
    +	bodyfd = -1;
    +
    +	buf = malloc(MAX_RESPONSE_SIZE + 1);
    +	if(buf == nil) {
    +		perror("malloc");
    +		return nil;
    +	}
    +
    +	ctlfd = open("/mnt/web/clone", ORDWR);
    +	if(ctlfd < 0) {
    +		perror("open");
    +		goto fail;
    +	}
    +
    +	if(read(ctlfd, buf, 32) < 0) {
    +		perror("read");
    +		goto fail;
    +	}
    +	
    +	n = atoi(buf);
    +
    +	sprint(buf, "url https://api.trello.com/%s?key=%s&token=%s", endpoint, key, token);
    +	if(params)
    +		sprint(buf + strlen(buf), "\&%s\n", params);
    +	else
    +		sprint(buf + strlen(buf), "\n");
    +
    +	err = write(ctlfd, buf, strlen(buf));
    +	if(err < 0){
    +		perror("write");
    +		goto fail;
    +	}
    +	
    +	sprint(buf, "/mnt/web/%d/body", n);
    +	bodyfd = open(buf, OREAD);
    +	if(bodyfd < 0){
    +		perror("open");
    +		goto fail;
    +	}
    +
    +	err = readn(bodyfd, buf, MAX_RESPONSE_SIZE);
    +	if (err < 0) {
    +		perror("read");
    +		goto fail;
    +	}
    +
    +	res = jsonparse(buf);
    +
    +fail:
    +	close(ctlfd);
    +	close(bodyfd);
    +	free(buf);
    +
    +	return res;
    +}
    +
    +char *
    +escapename(char *str)
    +{
    +	char *new;
    +	int i, len;
    +
    +	len = strlen(str);
    +
    +	new = malloc(len + 1);
    +	for(i = 0; i <= len; i++){
    +		switch(str[i]){
    +		case '/':
    +		case ' ':
    +		case ',':
    +		case ':':
    +		case '"':
    +		case '\'':
    +			new[i] = '_';
    +			break;
    +		default:
    +			new[i] = str[i];
    +		}
    +	}
    +	return new;
    +}
    +
    +void
    +addcard(File *dir, JSON *card)
    +{
    +	JSON *element;
    +	char *filename;
    +	File *carddir;
    +	char *description;
    +	char *url;
    +	char *duedate;
    +
    +	element = jsonbyname(card, "name");
    +	filename = escapename(element->s);
    +	carddir = createfile(dir, filename, nil, DMDIR|0555, nil);
    +	if(carddir == nil){
    +		perror("createfile");
    +		return;
    +	} else {
    +		element = jsonbyname(card, "desc");
    +		description = strdup(element->s);
    +		element = jsonbyname(card, "url");
    +		url = strdup(element->s);
    +		element = jsonbyname(card, "due");
    +		if (element->t == JSONString)
    +			duedate = strdup(element->s);
    +		else
    +			duedate = nil;
    +		createfile(carddir, "description", nil, 0444, description);
    +		createfile(carddir, "url", nil, 0444, url);
    +		createfile(carddir, "duedate", nil, 0444, duedate);
    +	}
    +	free(filename);
    +}
    +
    +void
    +addlist(File *dir, JSON *list)
    +{
    +	JSON *element;
    +	char *filename;
    +	JSON *cards;
    +	JSONEl *card;
    +	char cardsEndpoint[128];
    +	File *listdir;
    +
    +	element = jsonbyname(list, "name");
    +	
    +	filename = escapename(element->s);
    +	listdir = createfile(dir, filename, nil, DMDIR|0555, nil);
    +	if(listdir == nil){
    +		perror("createfile");
    +		return;
    +	} else {
    +		element = jsonbyname(list, "id");
    +		sprint(cardsEndpoint, "1/lists/%s/cards", element->s);
    +		cards = trelloget(cardsEndpoint, "fields=desc,name,url,due");
    +		if(cards == nil)
    +			return;
    +
    +		for(card = cards->first; card != nil; card = card->next){
    +			addcard(listdir, card->val);
    +		}
    +	}
    +	jsonfree(cards);
    +	free(filename);
    +}
    +
    +void
    +addboard(File *root, JSON *board)
    +{
    +	JSON *element;
    +	JSONEl *list;
    +	char *filename;
    +	File *boarddir;
    +
    +	element = jsonbyname(board, "name");
    +	filename = escapename(element->s);
    +	boarddir = createfile(root, filename, nil, DMDIR|0555, nil);
    +	if(boarddir == nil) {
    +		perror("createfile");
    +		return;
    +	}
    +
    +	element = jsonbyname(board, "lists");
    +	for(list = element->first; list != nil; list = list->next){
    +		addlist(boarddir, list->val);
    +	}
    +	
    +	free(filename);
    +}
    +
    +void
    +trelloinit(File *root)
    +{
    +	JSON *result;
    +	JSONEl *board;
    +
    +	result = trelloget("1/members/me/boards", "fields=name,lists&lists=open");
    +
    +	for(board = result->first; board != nil; board = board->next){
    +		addboard(root, board->val);
    +	}
    +	jsonfree(result);
    +}
    +
    +void
    +main(void)
    +{
    +	JSONfmtinstall();
    +
    +	key = getenv("trellokey");
    +	token = getenv("trellotoken");
    +
    +	Tree *tree;
    +
    +	tree = alloctree(nil, nil, DMDIR|0555, nil);
    +
    +	fs.tree = tree;
    +	trelloinit(tree->root);
    +
    +	postmountsrv(&fs, nil, "/mnt/trello", MREPL | MCREATE);
    +}
    +
    +

    The program can be compiled by hand or by using the following mkfile.

    +
    +BIN=/usr/glenda/bin/amd64
    +
    +TARG=trellofs
    +
    +OFILES=\
    +	main.$O\
    +
    +</sys/src/cmd/mkone
    +
    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/using_irc.html b/reference/pmikkelsen/pmikkelsen.com/plan9/using_irc.html new file mode 100644 index 0000000000000000000000000000000000000000..3f67c2dffa32d1fba6d40482a190c481d94a3f21 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/using_irc.html @@ -0,0 +1,236 @@ + + + + + plan9 - using irc + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Last updated: 2020-07-30

    +

    Using IRC on 9front

    +

    While 9front comes with an irc client called ircrc, it can be quite annoying that it does not keep a persistent connection.

    +

    A different program irc7 provides a server part which keeps a connection open to an irc server, and a client part which allows for connecting to the server. This works great since it makes it possible to get all the messages on a channel without being online all the time.

    +

    Setup

    +

    Download the irc7 code via hg:

    +
    +hg clone https://code.9front.org/hg/irc7/
    +
    +

    Build and install

    +
    +cd irc7
    +mk install
    +
    +

    Usage

    +

    First the server program ircsrv must be started, so I would run

    +
    +ircsrv -e -p VerySecretPassword pmikkelsen net!irc.freenode.net!7000
    +
    +

    to connect as pmikkelsen to freenode over tls and with password for my nickname. After this, it is possible to connect to different channels by opening new rio windows and running

    +
    +irc -t '#cat-v' -b
    +
    +

    to connect to the cat-v channel. The -b option without any extra arguments prints the entire conversation since the ircsrv was started, so it might not always be desirable.

    +

    To see all the messages sent directly to me, I would run

    +
    +irc -t MSGS
    +
    +

    and maybe start a conversation with user 'mousehater' by running

    +
    +irc -t mousehater
    +
    +

    I run this on a remote cpu server that is rarely powered off, and then I just connect via drawterm from linux to chat, or via rcpu from other 9front machines.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/plan9/webfs-websocket.html b/reference/pmikkelsen/pmikkelsen.com/plan9/webfs-websocket.html new file mode 100644 index 0000000000000000000000000000000000000000..1b0bb2f880f0234fb0ebf5ebdee18b1f9b802030 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/plan9/webfs-websocket.html @@ -0,0 +1,264 @@ + + + + + plan9 - webfs websocket + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    Creating websocket connections via 9front's webfs

    +

    With the following patch (note: work in progress, contains bugs), 9front's webfs can be used to create websocket connections. The patch is available here.

    +

    The idea

    +

    Creating a websocket connection is done just like creating a http request is, except the url must use scheme wss:// or ws://, and the body file must be opened read-write to allow both sending and receiving.

    +

    The very first message to be read from body is always "websocket ready", meaning the connection has been established. After that the actual communication begins.

    +

    Webfs itself takes care of the control messages, so only the data messages gets delivered to the user, in a textual format that is easy to parse. Each message read and writen to body consists of a 22 byte header in the following format

    +
    +b nnnnnnnnnnnnnnnnnnnn
    +
    +

    or

    +
    +t nnnnnnnnnnnnnnnnnnnn
    +
    +

    for binary and text messages respectively. The 20 last bytes are a 0-padded ascii number in base 10, telling the size of the message body, which follows directly after the header.

    +

    Example program

    +

    To demonstrate, the following rc script connects to wss://echo.websocket.org which is a service that echos everything back to the user.

    +
    +#!/bin/rc
    +
    +rfork en
    +
    +webfs
    +
    +fn sendtextmsg{
    +	awk 'BEGIN{printf "t %0.20d%s", length(ARGV[1]), ARGV[1]}' $1 >[1=0]
    +}
    +
    +fn readheader{
    +	header=`{read -c 22}
    +	length=`{echo $header(2) p | dc}
    +	echo $header(1) $length
    +}
    +
    +fn handlemsg{
    +	echo Handling message:
    +	echo '	TYPE  :' $1
    +	echo '	LENGTH:' $2
    +	echo '	BODY  :' $3
    +}
    +
    +<>/mnt/web/clone {
    +	d=/mnt/web/^`{sed 1q}
    +
    +	echo url wss://echo.websocket.org >[1=0]
    +
    +	<>$d/body {
    +		read -n 1 # Read the ready message
    +
    +		sendtextmsg 'First message sent'
    +		while(header=`{readheader}){
    +			echo Header: $header
    +			body=`''{read -c $header(2)}
    +			handlemsg $header(1) $header(2) $body
    +			sleep 2
    +			sendtextmsg 'Echo test'
    +		}
    +	}
    +}
    +
    +

    Bugs

    +

    Yes. The code doesn't really handle errors or connection shutdowns yet. Also, I need to add proper cleanup code around in different places.

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/prolog/generality-of-append.html b/reference/pmikkelsen/pmikkelsen.com/prolog/generality-of-append.html new file mode 100644 index 0000000000000000000000000000000000000000..ce8b0f006e2a6f5830e4a71b919f25802e3d54d3 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/prolog/generality-of-append.html @@ -0,0 +1,242 @@ + + + + + prolog - generality of append + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    The generality of the append predicate

    +

    In prolog we don't write functions which maps some input to an output. Instead, we write relations which states what must be true for the relation to hold. This gives a lot of power, in that those relations are often usable in many more ways than a function in another programming language would be.

    +

    To show an example of this, here is the append predicate which states that if append(A, B, C) then C is the list which contains the contents of list A followed by the contents of list B:

    +
    +append([], ListB, ListB).
    +append([A|ListA], ListB, [A|Rest]) :-
    +	append(ListA, ListB, Rest).
    +
    +

    It is only two clauses. The first clause states that an empty list followed by some list B is just B, and the second clause states that if the first list consists of head A and tail ListA, then the appended list consists of head A and tail Rest as long as appending ListA to ListB gives Rest.

    +

    Usage 1: appending two lists.

    +
    +?- append([a,b,c], [d,e,f], Result).
    +   Result = [a, b, c, d, e, f].
    +
    +

    Works as expected, and this is probably what most people want from an append function in another programming language.

    +

    Usage 2: What is the prefix?

    +
    +?- append(Prefix, [d,e,f], [a,b,c,d,e,f]).
    +   Prefix = [a, b, c].
    +
    +

    Here we ask the question "What list, when appended with [d,e,f], gives us [a,b,c,d,e,f]?" and prolog answers with [a,b,c] as we expected.

    +

    Usage 3: What is the suffix?

    +
    +?- append([a,b,c], Suffix, [a,b,c,d,e,f]).
    +   Suffix = [d, e, f].
    +
    +

    This is almost like before, but it asks for the suffix instead.

    +

    Usage 4: How about both the prefix and suffix

    +
    +?- append(Prefix, Suffix, [a,b,c,d,e,f]).
    +   Prefix = [],
    +   Suffix = [a, b, c, d, e, f]
    +;  Prefix = [a],
    +   Suffix = [b, c, d, e, f]
    +;  Prefix = [a, b],
    +   Suffix = [c, d, e, f]
    +;  Prefix = [a, b, c],
    +   Suffix = [d, e, f]
    +;  Prefix = [a, b, c, d],
    +   Suffix = [e, f]
    +;  Prefix = [a, b, c, d, e],
    +   Suffix = [f]
    +;  Prefix = [a, b, c, d, e, f],
    +   Suffix = [].
    +
    +

    Here we see that prolog is actually able to show us what prefix and suffix combined gives [a,b,c,d,e,f]! Since there are more than one solution here, each solution is seperated by the semicolon.

    +

    Conclusion

    +

    When you think about it, what the simple 2 clause append predicate does is pretty amazing compared to how little code is needed. It clearly describes a relationship between three lists in a way that allows us to use it to get answers to all sorts of questions, not just appending. How much code would be required to cover all the four use cases shown here if implemented in your favourite programming language?

    + +
    +
    + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/prolog/index.html b/reference/pmikkelsen/pmikkelsen.com/prolog/index.html new file mode 100644 index 0000000000000000000000000000000000000000..de4ace70017082be3afcc6c30bca1dce0ff35925 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/prolog/index.html @@ -0,0 +1,196 @@ + + + + + prolog + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/web/index.html b/reference/pmikkelsen/pmikkelsen.com/web/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c3275a7d3737cedcb55c2155f3b50fd78274b775 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/web/index.html @@ -0,0 +1,196 @@ + + + + + web + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + + + + + diff --git a/reference/pmikkelsen/pmikkelsen.com/web/the-setup-of-this-site.html b/reference/pmikkelsen/pmikkelsen.com/web/the-setup-of-this-site.html new file mode 100644 index 0000000000000000000000000000000000000000..323ebe4b3d8ffb94246c25d6dc8c5ad08d3af870 --- /dev/null +++ b/reference/pmikkelsen/pmikkelsen.com/web/the-setup-of-this-site.html @@ -0,0 +1,196 @@ + + + + + web - the setup of this site + + + + + + + + + + + + +
    + +

    Peter's website - random notes

    +
    + +
    + + +
    +

    This site is hosted on an OpenBSD VPS, using werc. I will write more about this in the future perhaps.

    +

    It was created by downloading werc and adding my page. Werc + my page can be found at https://git.sr.ht/~pmikkelsen/website.

    + +
    +
    + + + diff --git a/reference/tui.tsx b/reference/tui.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9b9673f4faba0be1bd4c4be5acd543f5f9355bd0 --- /dev/null +++ b/reference/tui.tsx @@ -0,0 +1,1090 @@ +/* ++------------------+----------------------------------------------------------+ +| FILE | tui.tsx | +| ROLE | Plan 9 / Acme-inspired TUI content browser | +| OWNER | Kris Yotam | +| CREATED | 2026-02-28 | +| UPDATED | 2026-02-28 | ++------------------+----------------------------------------------------------+ +| @type component | +| @path src/components/core/tui.tsx | ++------------------+----------------------------------------------------------+ +| SUMMARY | +| Full Plan 9 desktop layout: teal desktop background with island sections. | +| 3 top bars, central Acme content browser, footer taskbar — all floating | +| with gaps between them. Draggable Cirno mascot with minimize. | +| Left pane: collapsible directory tree. Right pane: raw MDX viewer. | +| Keyboard navigation (arrows, Enter, Escape) and search. | ++-----------------------------------------------------------------------------+ +*/ + +"use client" + +import { useState, useCallback, useEffect, useRef, useMemo } from "react" +import { ScrollArea } from "@/components/ui/scroll-area" + +// Types + +interface TreeEntry { + slug: string + title: string + date: string + preview: string +} + +interface TUIProps { + tree: Record +} + +interface SelectedFile { + type: string + slug: string +} + +interface FileContent { + frontmatter: string + body: string +} + +// Plan 9 Color Palette + +const P9 = { + desktop: "#B5B5AD", // grey desktop background + tagBar: "#EAFFFF", // pale cyan — Acme tag/command bar + titleBar: "#FFFFEA", // pale yellow — Acme window title bars + body: "#FFFFF5", // cream — Acme body/content background + text: "#000000", + textMuted: "#555555", + selected: "#9EE09E", + border: "#9EEEEE", // Plan 9 teal blue window borders + borderInner: "#888888", // inner dividers (pane separators) + borderLight: "#9EEEEE", + hoverBg: "#EEEEE5", + barAccent1: "#98D1CB", + barAccent2: "#E8A0A0", + barAccent3: "#88CC88", + footerBg: "#9EDBDA", + wsGrid: "#EAFFFF", + wsHighlight: "#55CCCC", +} as const + +const GAP = "14px" + +// SVG Icons (Plan 9 pixel-art style, no emoji) + +function FolderIcon({ size = 12 }: { size?: number }) { + return ( + + + + + ) +} + +function HomeIcon({ size = 12 }: { size?: number }) { + return ( + + + + ) +} + +// Floating Cirno + +function Cirno({ minimized, setMinimized }: { minimized: boolean; setMinimized: (v: boolean) => void }) { + const [pos, setPos] = useState(() => { + if (typeof window !== "undefined") { + return { + x: Math.round((window.innerWidth - 560) / 2), + y: Math.round((window.innerHeight - 600) / 2), + } + } + return { x: 200, y: 100 } + }) + const [dragging, setDragging] = useState(false) + const dragOffset = useRef({ x: 0, y: 0 }) + + const onMouseDown = useCallback((e: React.MouseEvent) => { + const target = e.target as HTMLElement + if (target.closest("[data-cirno-close]")) return + e.preventDefault() + setDragging(true) + dragOffset.current = { + x: e.clientX - pos.x, + y: e.clientY - pos.y, + } + }, [pos]) + + useEffect(() => { + if (!dragging) return + + function onMove(e: MouseEvent) { + setPos({ + x: e.clientX - dragOffset.current.x, + y: e.clientY - dragOffset.current.y, + }) + } + + function onUp() { + setDragging(false) + } + + window.addEventListener("mousemove", onMove) + window.addEventListener("mouseup", onUp) + return () => { + window.removeEventListener("mousemove", onMove) + window.removeEventListener("mouseup", onUp) + } + }, [dragging]) + + if (minimized) { + return null + } + + return ( +
    +
    + /dev/cirno + +
    + Cirno +
    + ) +} + +// Top Bars (3 separate island bars) + +function TopBars({ totalFiles }: { totalFiles: number }) { + const now = new Date() + const timeStr = now.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit" }) + + return ( +
    + {/* Bar 1: Status bar */} +
    +
    + krisyotam(9) + front +
    + {/* Plan 9 stats graph — 4 rows spelling KRIS */} +
    + {[ + { letter: "K", color: "#CC4444", bar1: "55%", bar2: "30%" }, + { letter: "R", color: "#4444BB", bar1: "70%", bar2: "45%" }, + { letter: "I", color: "#228822", bar1: "35%", bar2: "80%" }, + { letter: "S", color: "#77BB55", bar1: "60%", bar2: "20%" }, + ].map((row, i) => ( +
    + {/* Small square with letter */} +
    + {row.letter} +
    + {/* Bar 1 */} +
    +
    +
    + {/* Vertical divider */} +
    + {/* Bar 2 */} +
    +
    +
    +
    + ))} +
    +
    + + {/* Bar 2: File browser (Plan 9 file manager style) */} +
    + {/* Title bar: home, folder, up arrow | /usr/krisyotam | new folder, new file */} +
    +
    + + + + /usr/krisyotam +
    +
    + + + + + + + + + + + +
    +
    + {/* Directory listing */} +
    +
    + + Blog + 0 + Feb 28 10:15 +
    +
    + + Books + 0 + Mar 14 23:30 +
    +
    + + Documents + 0 + Jun 27 23:43 +
    +
    +
    + + {/* Bar 3: Navigation grid — command menu items */} +
    +
    + navigate(1) + site +
    +
    + {[ + { label: "home", path: "/" }, + { label: "essays", path: "/essays" }, + { label: "blog", path: "/blog" }, + { label: "diary", path: "/diary" }, + { label: "reviews", path: "/reviews" }, + { label: "fiction", path: "/fiction" }, + { label: "verse", path: "/verse" }, + { label: "til", path: "/til" }, + { label: "now", path: "/now" }, + { label: "film", path: "/film" }, + { label: "anime", path: "/anime" }, + { label: "manga", path: "/manga" }, + { label: "reading", path: "/reading" }, + { label: "library", path: "/library" }, + { label: "tags", path: "/tags" }, + { label: "about", path: "/me" }, + { label: "stats", path: "/stats" }, + { label: "globe", path: "/globe" }, + { label: "contact", path: "/contact" }, + ].map((item) => ( + { + e.currentTarget.style.background = P9.wsHighlight + e.currentTarget.style.color = "#fff" + }} + onMouseLeave={(e) => { + e.currentTarget.style.background = "#D8D8D0" + e.currentTarget.style.color = P9.text + }} + style={{ + padding: "1px 3px", + textAlign: "center", + background: "#D8D8D0", + color: P9.text, + border: "1px solid #FFFFFF", + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "center", + fontFamily: "inherit", + fontSize: "inherit", + }} + > + {item.label} + + ))} +
    +
    +
    + ) +} + +// Footer Taskbar + +function Footer({ cirnoMinimized, onRestoreCirno }: { cirnoMinimized: boolean; onRestoreCirno: () => void }) { + const [time, setTime] = useState("") + + useEffect(() => { + function tick() { + const d = new Date() + const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] + const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + setTime(`${days[d.getDay()]} ${months[d.getMonth()]} ${d.getDate()} ${d.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit" })}`) + } + tick() + const id = setInterval(tick, 10000) + return () => clearInterval(id) + }, []) + + return ( +
    + {/* Home button */} + + /home + + {/* Collapsed cirno.jpg — Plan 9 collapsed window style */} + {cirnoMinimized && ( +
    +
    + ■ +
    +
    + cirno.jpg +
    +
    + )} + {/* Colored center panel */} +
    + {/* Clock + info */} +
    + {time} + krisyotam.com + 9front +
    +
    + ) +} + +// Main TUI Component + +export function TUI({ tree }: TUIProps) { + const [expandedDirs, setExpandedDirs] = useState>(new Set()) + const [selectedFile, setSelectedFile] = useState(null) + const [fileContent, setFileContent] = useState(null) + const [searchQuery, setSearchQuery] = useState("") + const [loading, setLoading] = useState(false) + const [focusIndex, setFocusIndex] = useState(-1) + const [cirnoMinimized, setCirnoMinimized] = useState(false) + + const treeRef = useRef(null) + + const contentTypes = useMemo(() => Object.keys(tree).sort(), [tree]) + const totalFiles = useMemo( + () => Object.values(tree).reduce((sum, entries) => sum + entries.length, 0), + [tree] + ) + + const navItems = useMemo(() => { + const items: { kind: "dir" | "file"; type: string; slug?: string }[] = [] + const query = searchQuery.toLowerCase() + + for (const type of contentTypes) { + const entries = tree[type] + const filtered = query + ? entries.filter( + (e) => + e.slug.toLowerCase().includes(query) || + e.title.toLowerCase().includes(query) + ) + : entries + + if (query && filtered.length === 0) continue + items.push({ kind: "dir", type }) + + if (expandedDirs.has(type)) { + for (const entry of filtered) { + items.push({ kind: "file", type, slug: entry.slug }) + } + } + } + return items + }, [contentTypes, tree, expandedDirs, searchQuery]) + + const filteredTree = useMemo(() => { + if (!searchQuery) return tree + const query = searchQuery.toLowerCase() + const result: Record = {} + for (const type of contentTypes) { + const filtered = tree[type].filter( + (e) => + e.slug.toLowerCase().includes(query) || + e.title.toLowerCase().includes(query) + ) + if (filtered.length > 0) result[type] = filtered + } + return result + }, [tree, searchQuery, contentTypes]) + + const catFile = useCallback(async (type: string, slug: string) => { + setSelectedFile({ type, slug }) + setLoading(true) + setFileContent(null) + + try { + const res = await fetch(`/api/tui/${type}/${slug}`) + if (!res.ok) throw new Error(`HTTP ${res.status}`) + const data = await res.json() + setFileContent({ frontmatter: data.frontmatter, body: data.body }) + } catch { + setFileContent({ + frontmatter: "", + body: `Error: failed to read ${type}/${slug}.mdx`, + }) + } finally { + setLoading(false) + } + }, []) + + const toggleDir = useCallback((type: string) => { + setExpandedDirs((prev) => { + const next = new Set(prev) + if (next.has(type)) next.delete(type) + else next.add(type) + return next + }) + }, []) + + useEffect(() => { + function handleKeyDown(e: KeyboardEvent) { + if ((e.target as HTMLElement).tagName === "INPUT") return + + switch (e.key) { + case "ArrowDown": + e.preventDefault() + setFocusIndex((prev) => Math.min(prev + 1, navItems.length - 1)) + break + case "ArrowUp": + e.preventDefault() + setFocusIndex((prev) => Math.max(prev - 1, 0)) + break + case "ArrowRight": { + e.preventDefault() + const item = navItems[focusIndex] + if (item?.kind === "dir" && !expandedDirs.has(item.type)) { + toggleDir(item.type) + } + break + } + case "ArrowLeft": { + e.preventDefault() + const item = navItems[focusIndex] + if (item?.kind === "dir" && expandedDirs.has(item.type)) { + toggleDir(item.type) + } else if (item?.kind === "file") { + const dirIdx = navItems.findIndex( + (n) => n.kind === "dir" && n.type === item.type + ) + if (dirIdx >= 0) setFocusIndex(dirIdx) + } + break + } + case "Enter": { + e.preventDefault() + const item = navItems[focusIndex] + if (!item) break + if (item.kind === "dir") toggleDir(item.type) + else if (item.slug) catFile(item.type, item.slug) + break + } + case "Escape": + e.preventDefault() + setSelectedFile(null) + setFileContent(null) + break + } + } + + window.addEventListener("keydown", handleKeyDown) + return () => window.removeEventListener("keydown", handleKeyDown) + }, [navItems, focusIndex, expandedDirs, toggleDir, catFile]) + + useEffect(() => { + if (focusIndex < 0 || !treeRef.current) return + const el = treeRef.current.querySelector(`[data-nav-index="${focusIndex}"]`) + el?.scrollIntoView({ block: "nearest" }) + }, [focusIndex]) + + const breadcrumb = selectedFile + ? `/content/${selectedFile.type}/${selectedFile.slug}` + : "/content" + + // Render + + return ( +
    + {/* Floating Cirno */} + + + {/* ================================================================== */} + {/* Top 3 Bars (separate islands) */} + {/* ================================================================== */} + + + {/* ================================================================== */} + {/* Central Island: Acme workspace */} + {/* ================================================================== */} +
    + {/* Acme command/tag bar */} +
    + New + Cut + Paste + Snarf + Sort + Zerox + Delcol + | + { + setSearchQuery(e.target.value) + setFocusIndex(-1) + }} + style={{ + background: P9.body, + border: `1px solid ${P9.borderInner}`, + padding: "1px 6px", + fontFamily: "inherit", + fontSize: "inherit", + width: "180px", + outline: "none", + }} + /> +
    + + {/* Panes */} +
    + {/* Left Pane — Directory Tree */} +
    +
    + {breadcrumb} + {totalFiles} +
    + +
    + Del Snarf | Look Put Mail +
    + + +
    + {contentTypes.map((type) => { + const entries = filteredTree[type] + if (!entries && searchQuery) return null + + const isExpanded = expandedDirs.has(type) + const fileCount = tree[type].length + const dirNavIdx = navItems.findIndex( + (n) => n.kind === "dir" && n.type === type + ) + + return ( +
    +
    toggleDir(type)} + style={{ + padding: "1px 8px", + cursor: "pointer", + display: "flex", + alignItems: "center", + gap: "4px", + background: + focusIndex === dirNavIdx ? P9.selected : "transparent", + userSelect: "none", + }} + onMouseEnter={(e) => { + if (focusIndex !== dirNavIdx) + e.currentTarget.style.background = P9.hoverBg + }} + onMouseLeave={(e) => { + if (focusIndex !== dirNavIdx) + e.currentTarget.style.background = "transparent" + }} + > + + {isExpanded ? "\u25BE" : "\u25B8"} + + {type}/ + + {fileCount} + +
    + + {isExpanded && + (entries || tree[type]).map((entry) => { + const fileNavIdx = navItems.findIndex( + (n) => + n.kind === "file" && + n.type === type && + n.slug === entry.slug + ) + const isSelected = + selectedFile?.type === type && + selectedFile?.slug === entry.slug + + return ( +
    catFile(type, entry.slug)} + title={`${entry.title}\n${entry.date}\n${entry.preview}`} + style={{ + padding: "1px 8px 1px 28px", + cursor: "pointer", + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + background: isSelected + ? P9.selected + : focusIndex === fileNavIdx + ? P9.selected + : "transparent", + userSelect: "none", + }} + onMouseEnter={(e) => { + if (!isSelected && focusIndex !== fileNavIdx) + e.currentTarget.style.background = P9.hoverBg + }} + onMouseLeave={(e) => { + if (!isSelected && focusIndex !== fileNavIdx) + e.currentTarget.style.background = "transparent" + }} + > + {entry.slug}.mdx +
    + ) + })} +
    + ) + })} +
    +
    +
    + + {/* Right Pane — Content Viewer */} +
    +
    + + {selectedFile + ? `${selectedFile.type}/${selectedFile.slug}.mdx` + : "output"} + + + Del Snarf | Look Put + +
    + +
    + {selectedFile + ? `$ cat ${selectedFile.type}/${selectedFile.slug}.mdx` + : "cat"} +
    + + +
    + {!selectedFile && !loading && ( +
    +
    ; Plan 9 / Acme content browser
    +
    ; click a file to cat it, or use arrow keys + Enter
    +
    ; Escape to clear, Look to search
    +
    ;
    +
    + ; {contentTypes.length} directories, {totalFiles} files +
    +
    + )} + + {loading && ( +
    + reading... +
    + )} + + {selectedFile && fileContent && !loading && ( +
    + {fileContent.frontmatter && ( + <> +
    ---
    +
    + {fileContent.frontmatter} +
    +
    ---
    +
    + + )} + +
    + {fileContent.body} +
    +
    + )} +
    + +
    +
    +
    + + {/* ================================================================== */} + {/* Footer Taskbar (separate island) */} + {/* ================================================================== */} +
    setCirnoMinimized(false)} /> + + {/* Mobile responsive */} + +
    + ) +} diff --git a/serve.py b/serve.py new file mode 100644 index 0000000000000000000000000000000000000000..732e46cd007d2b368a8c402df4252ab553bdf2f4 --- /dev/null +++ b/serve.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Local dev server for werc. Calls werc.rc as CGI.""" +import http.server +import subprocess +import sys +import os +import urllib.parse + +PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8000 +WERC_ROOT = os.path.dirname(os.path.abspath(__file__)) +PLAN9 = "/usr/lib/plan9" + +class WercHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + # Serve static files from pub/ + parsed = urllib.parse.urlparse(self.path) + if parsed.path.startswith("/pub/") or parsed.path.startswith("/images/"): + fpath = os.path.join(WERC_ROOT, parsed.path.lstrip("/")) + if os.path.isfile(fpath): + ext = os.path.splitext(fpath)[1] + ct = {".css": "text/css", ".js": "application/javascript", + ".png": "image/png", ".ico": "image/x-icon", + ".jpeg": "image/jpeg", ".jpg": "image/jpeg"}.get(ext, "application/octet-stream") + self.send_response(200) + self.send_header("Content-Type", ct) + self.end_headers() + with open(fpath, "rb") as f: + self.wfile.write(f.read()) + return + + env = os.environ.copy() + env.update({ + "PLAN9": PLAN9, + "PATH": f"{PLAN9}/bin:{WERC_ROOT}/bin:{WERC_ROOT}/bin/contrib:/bin:/usr/bin", + "SERVER_NAME": "plan9.krisyotam.com", + "SERVER_PORT": str(PORT), + "REQUEST_METHOD": "GET", + "REQUEST_URI": self.path, + "PATH_INFO": parsed.path, + "QUERY_STRING": parsed.query or "", + "HTTP_COOKIE": self.headers.get("Cookie", ""), + "HTTP_HOST": self.headers.get("Host", "plan9.krisyotam.com"), + }) + + result = subprocess.run( + [f"{PLAN9}/bin/rc", "./werc.rc"], + cwd=os.path.join(WERC_ROOT, "bin"), + env=env, capture_output=True, timeout=5 + ) + output = result.stdout + if not output: + self.send_response(500) + self.end_headers() + self.wfile.write(result.stderr or b"empty response") + return + + # Split CGI headers from body + parts = output.split(b"\n\n", 1) + if len(parts) == 2: + headers, body = parts + else: + headers, body = b"", output + + self.send_response(200) + for line in headers.decode(errors="replace").splitlines(): + if ":" in line: + k, v = line.split(":", 1) + self.send_header(k.strip(), v.strip()) + self.end_headers() + self.wfile.write(body) + + def log_message(self, fmt, *args): + print(f" {args[0]}") + +print(f"werc serving plan9.krisyotam.com at http://localhost:{PORT}") +http.server.HTTPServer(("", PORT), WercHandler).serve_forever() diff --git a/serve.rc b/serve.rc new file mode 100755 index 0000000000000000000000000000000000000000..eafb307eee8cf185182b04c869f30ceaa1113585 --- /dev/null +++ b/serve.rc @@ -0,0 +1,21 @@ +#!/usr/lib/plan9/bin/rc +# Local dev server for plan9.krisyotam.com +# Usage: 9 rc serve.rc [port] + +PLAN9=/usr/lib/plan9 +port=$1 +if(~ $#port 0) + port=8000 + +werc_root=/home/krisyotam/dev/plan9.krisyotam.com +path=($PLAN9/bin $werc_root/bin $werc_root/bin/contrib .) + +fn handler { + SERVER_NAME=plan9.krisyotam.com \ + SERVER_PORT=$port \ + REQUEST_METHOD=GET \ + $PLAN9/bin/rc $werc_root/bin/contrib/rc-httpd/rc-httpd +} + +echo serving plan9.krisyotam.com on port $port +exec $PLAN9/bin/listen1 -t tcp!*!$port /usr/lib/plan9/bin/rc -c handler diff --git a/sites/localhost b/sites/localhost new file mode 120000 index 0000000000000000000000000000000000000000..4222820926bd51f5b1339f13e0c3ada3f5a5eae6 --- /dev/null +++ b/sites/localhost @@ -0,0 +1 @@ +plan9.krisyotam.com \ No newline at end of file diff --git a/sites/plan9.krisyotam.com/_werc/config b/sites/plan9.krisyotam.com/_werc/config new file mode 100644 index 0000000000000000000000000000000000000000..93803ce70ea359574842c89ed42118e84b4aacd3 --- /dev/null +++ b/sites/plan9.krisyotam.com/_werc/config @@ -0,0 +1,4 @@ +masterSite=plan9.krisyotam.com +siteTitle='krisyotam.net' +siteSubTitle='- tools, patches, notes' +conf_enable_duckduckgo diff --git a/sites/plan9.krisyotam.com/about/_werc/about_master.tpl b/sites/plan9.krisyotam.com/about/_werc/about_master.tpl new file mode 100644 index 0000000000000000000000000000000000000000..24cadff67e9ceccc8663fdd5a88f6ab7d9581cd8 --- /dev/null +++ b/sites/plan9.krisyotam.com/about/_werc/about_master.tpl @@ -0,0 +1,31 @@ +
    + +

    %($"siteTitle%) %($"siteSubTitle%)

    +
    + +
    +% if(! ~ $#handlers_bar_left 0) { + +% } + +
    +% run_handlers $handlers_body_head +% run_handler $handler_body_main +% run_handlers $handlers_body_foot +
    +
    + +
    + +
    +% cat `{ get_lib_file footer.inc } +
    + diff --git a/sites/plan9.krisyotam.com/about/_werc/config b/sites/plan9.krisyotam.com/about/_werc/config new file mode 100644 index 0000000000000000000000000000000000000000..b9726b7acb77f823fce99c82174468b743ce6a45 --- /dev/null +++ b/sites/plan9.krisyotam.com/about/_werc/config @@ -0,0 +1 @@ +master_template=sites/plan9.krisyotam.com/about/_werc/about_master.tpl diff --git a/sites/plan9.krisyotam.com/about/index.md b/sites/plan9.krisyotam.com/about/index.md new file mode 100644 index 0000000000000000000000000000000000000000..80c60718457c5c0377f35ea517ec2a8c31e88739 --- /dev/null +++ b/sites/plan9.krisyotam.com/about/index.md @@ -0,0 +1,93 @@ +About +===== + +Kris Yotam. Mathematics student, systems programmer. I write +software and documentation for Plan 9, 9front, and suckless +systems, and collect the results here. + +Built with [werc](http://werc.cat-v.org). Hosted on +[SourceHut](https://sr.ht/~krisyotam). + + +Elsewhere +--------- + +- [krisyotam.com](https://krisyotam.com) - writing and research +- [krisyotam.com/notebooks](https://krisyotam.com/notebooks) - topic reference notebooks +- [krisyotam.com/tools](https://krisyotam.com/tools) - tools and utilities +- [krisyotam.com/share](https://krisyotam.com/share) - shared files +- [krisyotam.com/wiki](https://krisyotam.com/wiki) - wiki (coming soon) +- [krisyotam.com/deep-research](https://krisyotam.com/deep-research) - research reports +- [notes.krisyotam.com](https://notes.krisyotam.com) - notes +- [edu.krisyotam.com](https://edu.krisyotam.com) - academic work +- [sr.ht/~krisyotam](https://sr.ht/~krisyotam) - source code (primary) +- [github.com/krisyotam](https://github.com/krisyotam) - source code (mirror) + + +Pet Projects +------------ + +- [whichisbetter.dev](https://whichisbetter.dev) - paired comparison ranking tool + + +Rules +----- + +**On responsiveness.** +I reply to most things. If I haven't responded in a week, +send it again. It probably got buried, not ignored. + +**On pen pals.** +I'm open to ongoing correspondence. If something I wrote +resonated or you want to think through a problem together, +reach out. + +**On pitches.** +Don't pitch me products or services. If you built something +interesting and want to show it to me, that's different. +Just don't lead with a sales deck. + +**On effort.** +Low-effort messages get low-effort responses. If your email +could be a Google search, it will be treated like one. + +**On encryption.** +If it's sensitive, encrypt it. My PGP key is below. If you +don't know how, that's fine. Just don't send passwords or +secrets in plaintext. + +**On gossip.** +I don't engage with gossip or drama about other people +online. I'm not interested in who said what about whom. + +**On topics.** +I'm most likely to respond to messages about mathematics, +philosophy, software, film, or anything I've written about. +I'm least likely to respond to anything that reads like it +was generated by an LLM. + + +Contact +------- + + email: kris@krisyotam.com + + +PGP +--- + + fingerprint: 4821 9A26 3BDC 66CB 2AF4 2C98 94B8 D889 8D14 5952 + + -----BEGIN PGP PUBLIC KEY BLOCK----- + + xjMEZhEGohYJKwYBBAHaRw8BAQdABZtJxhY8Ny8LxTqy7X7k+e5Q0aX+EBcr + bPGXqmTvQHbNM2tyaXN5b3RhbUBwcm90b25tYWlsLmNvbSA8a3Jpc3lvdGFt + QHByb3Rvbm1haWwuY29tPsKMBBAWCgA+BYJmEQaiBAsJBwgJkJS42ImNFFlS + AxUICgQWAAIBAhkBApsDAh4BFiEESCGaJjvcZssq9CyYlLjYiY0UWVIAALPV + AP91aquLM/vohDWJ2OkRbuRTxZ2beYBrSUTH9vVyJ++YwgEAr/eyXMuOmesc + 8Yrh69/Cqrj1etHd8NveDz2gwAOgkwDOOARmEQaiEgorBgEEAZdVAQUBAQdA + tGAx6gPp6cE6xSnnW1HtwN4IdoE1afHCV/Eh+XsAxEsDAQgHwngEGBYKACoF + gmYRBqIJkJS42ImNFFlSApsMFiEESCGaJjvcZssq9CyYlLjYiY0UWVIAAPJ7 + AP9CtvHMQMch3KDASBfnujRrFBUlRA6/6k0y0mNNF5CHAAEA+2SjjGheM8FB + HLUR5mAoWJ5eNdWCElXRJgH6H9Ikaws= + -----END PGP PUBLIC KEY BLOCK----- diff --git a/sites/plan9.krisyotam.com/blogroll.md b/sites/plan9.krisyotam.com/blogroll.md new file mode 100644 index 0000000000000000000000000000000000000000..d54bb233b6da470750f1a4ed7b68fe6d295eb944 --- /dev/null +++ b/sites/plan9.krisyotam.com/blogroll.md @@ -0,0 +1,14 @@ +Blogroll +======== + +People doing work worth reading. + +- [cat-v.org](http://cat-v.org) - founded by Uriel (1979-2012), the archive that started it all ★ +- [Drew DeVault](https://drewdevault.com) - SourceHut, Hare language, Alpine Linux +- [Hiltjo Posthuma](https://codemadness.org) - sfeed, stagit, saait ★ +- [Ori Bernstein](https://ori-b.net) - Myrddin language, 9front contributor ★ +- [Peter Mikkelsen](https://pmikkelsen.com) - APL9, PProlog, 9front +- [Rob Pike](http://herpolhode.com/rob/) - Plan 9, Go, UTF-8 +- [Russ Cox](https://swtch.com/~rsc/) - Plan 9 from User Space, Go, RE2 +- [Sigrid](https://ftrv.se) - 9front developer, media and graphics +- [Stanley Lieber](http://stanleylieber.com) - 9front, comics, music diff --git a/sites/plan9.krisyotam.com/cluster/index.md b/sites/plan9.krisyotam.com/cluster/index.md new file mode 100644 index 0000000000000000000000000000000000000000..204a1bb359b09085cbaf99f507ec1e5ecb994ba7 --- /dev/null +++ b/sites/plan9.krisyotam.com/cluster/index.md @@ -0,0 +1,4 @@ +Cluster +======= + +A Plan 9 cluster built from vintage Apple hardware. diff --git a/sites/plan9.krisyotam.com/data/index.md b/sites/plan9.krisyotam.com/data/index.md new file mode 100644 index 0000000000000000000000000000000000000000..cb3b3df35de2d35b88e9994a51601f1fcab93eab --- /dev/null +++ b/sites/plan9.krisyotam.com/data/index.md @@ -0,0 +1,5 @@ +Data +==== + +Structured datasets about the Plan 9 ecosystem. Machine-readable +where possible, browsable always. diff --git a/sites/plan9.krisyotam.com/essays/index.md b/sites/plan9.krisyotam.com/essays/index.md new file mode 100644 index 0000000000000000000000000000000000000000..62040f397e2135d277250277f681bd620a424cac --- /dev/null +++ b/sites/plan9.krisyotam.com/essays/index.md @@ -0,0 +1,5 @@ +Essays +====== + +Long-form writing on Plan 9, systems programming, +and the philosophy of simple software. diff --git a/sites/plan9.krisyotam.com/harmful/index.md b/sites/plan9.krisyotam.com/harmful/index.md new file mode 100644 index 0000000000000000000000000000000000000000..da6cd55c07f44cec0b0ae7e25f40de53d835afaf --- /dev/null +++ b/sites/plan9.krisyotam.com/harmful/index.md @@ -0,0 +1,13 @@ +Harmful +======= + +Over the years there have been a lot of opinionated +[harmful](https://harmful.cat-v.org/) pages, and to be +honest I've become a fan. Naturally it is much easier to +approach things in an inverted way. Rather than approaching +things from the stance "what is the correct way", approach +them from "what should I not do?" This yields higher quality +results as it is inane to expect someone without proper +understanding of impractical/harmful implementations to +understand the meaning of why an implementation can be good, +and furthermore why/if/when a trade off should be made. diff --git a/sites/plan9.krisyotam.com/index.md b/sites/plan9.krisyotam.com/index.md index 10cf179cc309bd7aa21c9de9b91b31c6eaad208f..014a086b059c01a3c1535239fc2e8a98abcf5dba 100644 --- a/sites/plan9.krisyotam.com/index.md +++ b/sites/plan9.krisyotam.com/index.md @@ -1,12 +1,4 @@ kris yotam ========== -Plan 9, 9front, rc, and related work. - -Tools, patches, notes, and configuration for Plan 9 and -Plan 9-adjacent systems. - -- [tools](/tools/) — scripts and programs -- [patches](/patches/) — contributed patches -- [notes](/notes/) — setup guides and reference -- [setup](/setup/) — machine configs and install notes +This is the website of Kris Yotam. I am a plan9/9front developer, and writer. I am better known for my broader work on [krisyotam.com](https://krisyotam.com). This site is more specifically narrowed to the focus of plan9. diff --git a/sites/plan9.krisyotam.com/resources/index.md b/sites/plan9.krisyotam.com/resources/index.md new file mode 100644 index 0000000000000000000000000000000000000000..2b68698d559a8c8e307aed326c9586e9d48bf51b --- /dev/null +++ b/sites/plan9.krisyotam.com/resources/index.md @@ -0,0 +1,5 @@ +Resources +========= + +Guides, references, and directories for Plan 9, 9front, +and related systems. diff --git a/sites/plan9.krisyotam.com/sitemap.txt b/sites/plan9.krisyotam.com/sitemap.txt new file mode 100644 index 0000000000000000000000000000000000000000..f3ec894b345fb7229ebcf04eae42cf33081ed97a --- /dev/null +++ b/sites/plan9.krisyotam.com/sitemap.txt @@ -0,0 +1 @@ +http://plan9.krisyotam.com:8800/index.md diff --git a/sites/plan9.krisyotam.com/software/index.md b/sites/plan9.krisyotam.com/software/index.md new file mode 100644 index 0000000000000000000000000000000000000000..8a561a70d0594617ca2c42b74962823ab7239f14 --- /dev/null +++ b/sites/plan9.krisyotam.com/software/index.md @@ -0,0 +1,62 @@ +Software Repo +============= + +Small software packages and tools. The focus is minimalism and +utility. Most are directly or indirectly related to Plan 9, +9front, or the suckless philosophy. + +All source is hosted on [SourceHut](https://sr.ht/~krisyotam/9p/sources). + + +9P / Plan 9 +----------- + +- [9hist](https://git.sr.ht/~krisyotam/9hist) - history of the Plan 9 kernel (1990 - 2003) +- [disco](https://git.sr.ht/~krisyotam/disco) - Discord client for 9front +- [glenda](https://git.sr.ht/~krisyotam/glenda) - utility Discord bot for the 9fans discord server +- [llm9p](https://git.sr.ht/~krisyotam/llm9p) - LLM exposed as a 9P filesystem + + +Suckless Tools +-------------- + +- [sbot](https://git.sr.ht/~krisyotam/sbot) - simple archiver bot, inlines all resources into self-contained HTML +- [sdiagram](https://git.sr.ht/~krisyotam/sdiagram) - simple diagram tool with canvas, pan, zoom +- [sframe](https://git.sr.ht/~krisyotam/sframe) - extract unique frames from videos +- [slock](https://git.sr.ht/~krisyotam/slock) - simple X screen locker (flexipatch variant) +- [sparser](https://git.sr.ht/~krisyotam/sparser) - simple URL extractor from text files +- [spod](https://git.sr.ht/~krisyotam/spod) - simple podcast, static page generator in the style of stagit +- [ssync](https://git.sr.ht/~krisyotam/ssync) - GitHub-to-stagit mirror daemon with SQLite +- [stask](https://git.sr.ht/~krisyotam/stask) - simple task manager, C with SQLite and GTK4 +- [suploader](https://git.sr.ht/~krisyotam/suploader) - submit URLs to web archive services +- [surf](https://git.sr.ht/~krisyotam/surf) - simple web browser based on WebKit/GTK+ +- [tabbed](https://git.sr.ht/~krisyotam/tabbed) - generic tabbed interface for X11 + + +Cloning +------- + +All repos can be cloned via SSH or HTTPS: + + git clone https://git.sr.ht/~krisyotam/[project-name] + + +License +------- + +Unless stated otherwise, all original software is released under +the GNU General Public License v3. + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + . diff --git a/sites/plan9.krisyotam.com/style/go.md b/sites/plan9.krisyotam.com/style/go.md new file mode 100644 index 0000000000000000000000000000000000000000..ba75e3d356d91330d69f695f223479b8035f6748 --- /dev/null +++ b/sites/plan9.krisyotam.com/style/go.md @@ -0,0 +1,53 @@ +Go Style +======== + +Go has one style. It is enforced by the toolchain. + + +gofmt +----- + +Run `gofmt` on everything. There is no debate about brace +placement, tab vs spaces, or alignment. The tool decides. + + gofmt -w file.go + +Or format an entire tree: + + go fmt ./... + + +Effective Go +------------ + +The canonical reference is [Effective Go](https://go.dev/doc/effective_go). +Key points: + +* **Naming**: MixedCaps, not underscores. Package names are + lowercase single words. Interface names end in `-er` when + they have a single method. +* **Semicolons**: The lexer inserts them. Opening brace must + be on the same line as the control statement. +* **Control flow**: `if` can have an init statement. There is + no `while` -- use `for`. `switch` cases do not fall through + by default. +* **Error handling**: Return errors, do not panic. Check them + immediately. +* **Goroutines**: Communicate by sharing channels, do not share + memory. +* **Commentary**: `//` comments. Doc comments precede declarations + with no blank line between. + + +Plan 9 Connection +----------------- + +Go was created by Rob Pike, Ken Thompson, and Robert Griesemer. +Its toolchain descends from the Plan 9 C compilers. The `go` +command is analogous to Plan 9's `mk`. The standard library +reflects Plan 9 sensibilities: small interfaces, composition +over inheritance, explicit error handling. + +The style follows directly from Pike's notes on C: short names, +no decoration, data structures over algorithms, measure before +optimizing. diff --git a/sites/plan9.krisyotam.com/style/index.md b/sites/plan9.krisyotam.com/style/index.md new file mode 100644 index 0000000000000000000000000000000000000000..babeafe515067fa6ff9bddd0e97eb1ff7072ebce --- /dev/null +++ b/sites/plan9.krisyotam.com/style/index.md @@ -0,0 +1,8 @@ +Style +===== + +Coding style references for the three languages that matter here. + +- [suckless C](/style/suckless_c) - the suckless coding style for C +- [Plan 9 C](/style/plan9_c) - Rob Pike's notes on programming in C +- [Go](/style/go) - Go's standard style via gofmt and Effective Go diff --git a/sites/plan9.krisyotam.com/style/plan9_c.md b/sites/plan9.krisyotam.com/style/plan9_c.md new file mode 100644 index 0000000000000000000000000000000000000000..61b16241ad95de515a38deb91eb7d3d36c8b3a2f --- /dev/null +++ b/sites/plan9.krisyotam.com/style/plan9_c.md @@ -0,0 +1,415 @@ +Notes on Programming in C +========================= + +Rob Pike, February 21, 1989. + +From [doc.cat-v.org/bell\_labs/pikestyle](http://doc.cat-v.org/bell_labs/pikestyle). + + +Introduction +------------ + +Kernighan and Plauger's *The Elements of Programming Style* +was an important and rightly influential book. But sometimes +I feel its concise rules were taken as a cookbook approach to +good style instead of the succinct expression of a philosophy +they were meant to be. If the book claims that variable names +should be chosen meaningfully, doesn't it then follow that +variables whose names are small essays on their use are even +better? Isn't `MaximumValueUntilOverflow` a better name than +`maxval`? I don't think so. + +What follows is a set of short essays that collectively +encourage a philosophy of clarity in programming rather than +giving hard rules. I don't expect you to agree with all of +them, because they are opinion and opinions change with the +times. But they've been accumulating in my head, if not on +paper until now, for a long time, and are based on a lot of +experience, so I hope they help you understand how to plan +the details of a program. (I've yet to see a good essay on +how to plan the whole thing, but then that's partly what +this course is about.) If you find them idiosyncratic, fine; +if you disagree with them, fine; but if they make you think +about why you disagree, that's better. Under no circumstances +should you program the way I say to because I say to; program +the way you think expresses best what you're trying to +accomplish in the program. And do so consistently and +ruthlessly. + + +Issues of Typography +-------------------- + +A program is a sort of publication. It's meant to be read by +the programmer, another programmer (perhaps yourself a few +days, weeks or years later), and lastly a machine. The +machine doesn't care how pretty the program is -- if the +program compiles, the machine's happy -- but people do, and +they should. Sometimes they care too much: pretty printers +mechanically produce pretty output that accentuates +irrelevant detail in the program, which is as sensible as +putting all the prepositions in English text in bold font. +Although many people think programs should look like the +Algol-68 report (and some systems even require you to edit +programs in that style), a clear program is not made any +clearer by such presentation, and a bad program is only made +laughable. + +Typographic conventions consistently held are important to +clear presentation, of course -- indentation is probably the +best known and most useful example -- but when the ink +obscures the intent, typography has taken over. So even if +you stick with plain old typewriter-like output, be conscious +of typographic silliness. Avoid decoration; for instance, +keep comments brief and banner-free. Say what you want to +say in the program, neatly and consistently. Then move on. + + +Variable Names +-------------- + +Ah, variable names. Length is not a virtue in a name; clarity +of expression is. A global variable rarely used may deserve a +long name, `maxphysaddr` say. An array index used on every +line of a loop needn't be named any more elaborately than +`i`. Saying `index` or `elementnumber` is more to type (or +calls upon your text editor) and obscures the details of the +computation. When the variable names are huge, it's harder to +see what's going on. This is partly a typographic issue; +consider + + for(i=0 to 100) + array[i]=0 + +vs. + + for(elementnumber=0 to 100) + array[elementnumber]=0; + +The problem gets worse fast with real examples. Indices are +just notation, so treat them as such. + +Pointers also require sensible notation. `np` is just as +mnemonic as `nodepointer` if you consistently use a naming +convention from which `np` means "node pointer" is easily +derived. More on this in the next essay. + +As in all other aspects of readable programming, consistency +is important in naming. If you call one variable +`maxphysaddr`, don't call its cousin `lowestaddress`. + +Finally, I prefer minimum-length but maximum-information +names, and then let the context fill in the rest. Globals, +for instance, typically have little context when they are +used, so their names need to be relatively evocative. Thus I +say `maxphysaddr` (not `MaximumPhysicalAddress`) for a global +variable, but `np` not `NodePointer` for a pointer locally +defined and used. This is largely a matter of taste, but +taste is relevant to clarity. + +I eschew embedded capital letters in names; to my +prose-oriented eyes, they are too awkward to read comfortably. +They jangle like bad typography. + + +The Use of Pointers +------------------- + +C is unusual in that it allows pointers to point to anything. +Pointers are sharp tools, and like any such tool, used well +they can be delightfully productive, but used badly they can +do great damage (I sunk a wood chisel into my thumb a few +days before writing this). Pointers have a bad reputation in +academia, because they are considered too dangerous, dirty +somehow. But I think they are powerful notation, which means +they can help us express ourselves clearly. + +Consider: When you have a pointer to an object, it is a name +for exactly that object and no other. That sounds trivial, +but look at the following two expressions: + + np + node[i] + +The first points to a node, the second evaluates to (say) +the same node. But the second form is an expression; it is +not so simple. To interpret it, we must know what `node` is, +what `i` is, and that `i` and `node` are related by the +(probably unspecified) rules of the surrounding program. +Nothing about the expression in isolation can show that `i` +is a valid index of `node`, let alone the index of the +element we want. If `i` and `j` and `k` are all indices into +the node array, it's very easy to slip up, and the compiler +cannot help. It's particularly easy to make mistakes when +passing things to subroutines: a pointer is a single thing; +an array and an index must be believed to belong together in +the receiving subroutine. + +An expression that evaluates to an object is inherently more +subtle and error-prone than the address of that object. +Correct use of pointers can simplify code: + + parent->link[i].type + +vs. + + lp->type + +If we want the next element's type, it's + + parent->link[++i].type + +or + + (++lp)->type + +`i` advances but the rest of the expression must stay +constant; with pointers, there's only one thing to advance. + +Typographic considerations enter here, too. Stepping through +structures using pointers can be much easier to read than with +expressions: less ink is needed and less effort is expended by +the compiler and computer. A related issue is that the type of +the pointer affects how it can be used correctly, which allows +some helpful compile-time error checking that array indices +cannot share. Also, if the objects are structures, their tag +fields are reminders of their type, so + + np->left + +is sufficiently evocative; if an array is being indexed the +array will have some well-chosen name and the expression will +end up longer: + + node[i].left + +Again, the extra characters become more irritating as the +examples become larger. + +As a rule, if you find code containing many similar, complex +expressions that evaluate to elements of a data structure, +judicious use of pointers can clear things up. Consider what + + if(goleft) + p->left=p->right->left; + else + p->right=p->left->right; + +would look like using a compound expression for `p`. +Sometimes it's worth a temporary variable (here `p`) or a +macro to distill the calculation. + + +Procedure Names +--------------- + +Procedure names should reflect what they do; function names +should reflect what they return. Functions are used in +expressions, often in things like `if`'s, so they need to +read appropriately. + + if(checksize(x)) + +is unhelpful because we can't deduce whether `checksize` +returns true on error or non-error; instead + + if(validsize(x)) + +makes the point clear and makes a future mistake in using the +routine less likely. + + +Comments +-------- + +A delicate matter, requiring taste and judgement. I tend to +err on the side of eliminating comments, for several reasons. +First, if the code is clear, and uses good type names and +variable names, it should explain itself. Second, comments +aren't checked by the compiler, so there is no guarantee +they're right, especially after the code is modified. A +misleading comment can be very confusing. Third, the issue +of typography: comments clutter code. + +But I do comment sometimes. Almost exclusively, I use them as +an introduction to what follows. Examples: explaining the use +of global variables and types (the one thing I always comment +in large programs); as an introduction to an unusual or +critical procedure; or to mark off sections of a large +computation. + +There is a famously bad comment style: + + i=i+1; /* Add one to i */ + +and there are worse ways to do it: + + /********************************** + * * + * Add one to i * + * * + **********************************/ + + i=i+1; + +Don't laugh now, wait until you see it in real life. + +Avoid cute typography in comments, avoid big blocks of +comments except perhaps before vital sections like the +declaration of the central data structure (comments on data +are usually much more helpful than on algorithms); +basically, avoid comments. If your code needs a comment to be +understood, it would be better to rewrite it so it's easier +to understand. Which brings us to + + +Complexity +---------- + +Most programs are too complicated -- that is, more complex +than they need to be to solve their problems efficiently. +Why? Mostly it's because of bad design, but I will skip that +issue here because it's a big one. But programs are often +complicated at the microscopic level, and that is something I +can address here. + +**Rule 1.** You can't tell where a program is going to spend +its time. Bottlenecks occur in surprising places, so don't +try to second guess and put in a speed hack until you've +proven that's where the bottleneck is. + +**Rule 2.** Measure. Don't tune for speed until you've +measured, and even then don't unless one part of the code +overwhelms the rest. + +**Rule 3.** Fancy algorithms are slow when *n* is small, and +*n* is usually small. Fancy algorithms have big constants. +Until you know that *n* is frequently going to be big, don't +get fancy. (Even if *n* does get big, use Rule 2 first.) For +example, binary trees are always faster than splay trees for +workaday problems. + +**Rule 4.** Fancy algorithms are buggier than simple ones, +and they're much harder to implement. Use simple algorithms +as well as simple data structures. + +The following data structures are a complete list for almost +all practical programs: + +* array +* linked list +* hash table +* binary tree + +Of course, you must also be prepared to collect these into +compound data structures. For instance, a symbol table might +be implemented as a hash table containing linked lists of +arrays of characters. + +**Rule 5.** Data dominates. If you've chosen the right data +structures and organized things well, the algorithms will +almost always be self-evident. Data structures, not +algorithms, are central to programming. + +**Rule 6.** There is no Rule 6. + + +Programming with Data +--------------------- + +Algorithms, or details of algorithms, can often be encoded +compactly, efficiently and expressively as data rather than, +say, as lots of `if` statements. The reason is that the +complexity of the job at hand, if it is due to a combination +of independent details, can be encoded. A classic example of +this is parsing tables, which encode the grammar of a +programming language in a form interpretable by a fixed, +fairly simple piece of code. Finite state machines are +particularly amenable to this form of attack, but almost any +program that involves the "parsing" of some abstract sort of +input into a sequence of some independent "actions" can be +constructed profitably as a data-driven algorithm. + +Perhaps the most intriguing aspect of this kind of design is +that the tables can sometimes be generated by another program +-- a parser generator, in the classical case. As a more +earthy example, if an operating system is driven by a set of +tables that connect I/O requests to the appropriate device +drivers, the system may be "configured" by a program that +reads a description of the particular devices connected to +the machine in question and prints the corresponding tables. + +One of the reasons data-driven programs are not common, at +least among beginners, is the tyranny of Pascal. Pascal, like +its creator, believes firmly in the separation of code and +data. It therefore (at least in its original form) has no +ability to create initialized data. This flies in the face of +the theories of Turing and von Neumann, which define the +basic principles of the stored-program computer. Code and +data are the same, or at least they can be. How else can you +explain how a compiler works? (Functional languages have a +similar problem with I/O.) + + +Function Pointers +----------------- + +Another result of the tyranny of Pascal is that beginners +don't use function pointers. (You can't have function-valued +variables in Pascal.) Using function pointers to encode +complexity has some interesting properties. + +Some of the complexity is passed to the routine pointed to. +The routine must obey some standard protocol -- it's one of a +set of routines invoked identically -- but beyond that, what +it does is its business alone. The complexity is distributed. + +There is this idea of a protocol, in that all functions used +similarly must behave similarly. This makes for easy +documentation, testing, growth and even making the program +run distributed over a network -- the protocol can be encoded +as remote procedure calls. + +I argue that clear use of function pointers is the heart of +object-oriented programming. Given a set of operations you +want to perform on data, and a set of data types you want to +respond to those operations, the easiest way to put the +program together is with a group of function pointers for +each type. This, in a nutshell, defines class and method. The +O-O languages give you more of course -- prettier syntax, +derived types and so on -- but conceptually they provide +little extra. + +Combining data-driven programs with function pointers leads +to an astonishingly expressive way of working, a way that, in +my experience, has often led to pleasant surprises. Even +without a special O-O language, you can get 90% of the +benefit for no extra work and be more in control of the +result. I cannot recommend an implementation style more +highly. All the programs I have organized this way have +survived comfortably after much development -- far better +than with less disciplined approaches. Maybe that's it: the +discipline it forces pays off handsomely in the long run. + + +Include Files +------------- + +Simple rule: include files should never include include files. +If instead they state (in comments or implicitly) what files +they need to have included first, the problem of deciding +which files to include is pushed to the user (programmer) but +in a way that's easy to handle and that, by construction, +avoids multiple inclusions. Multiple inclusions are a bane of +systems programming. It's not rare to have files included +five or more times to compile a single C source file. The +Unix `/usr/include/sys` stuff is terrible this way. + +There's a little dance involving `#ifdef`'s that can prevent +a file being read twice, but it's usually done wrong in +practice -- the `#ifdef`'s are in the file itself, not the +file that includes it. The result is often thousands of +needless lines of code passing through the lexical analyzer, +which is (in good compilers) the most expensive phase. + +Just follow the simple rule. diff --git a/sites/plan9.krisyotam.com/style/suckless_c.md b/sites/plan9.krisyotam.com/style/suckless_c.md new file mode 100644 index 0000000000000000000000000000000000000000..99df6276f83c5cc5d58afb353c159e6df6b6ad63 --- /dev/null +++ b/sites/plan9.krisyotam.com/style/suckless_c.md @@ -0,0 +1,213 @@ +Suckless C Style +================ + +From [suckless.org/coding_style](https://suckless.org/coding_style/). +The most important aspect of style is consistency. + + +Recommended Reading +------------------- + +* [OpenBSD style(9)](https://man.openbsd.org/style) +* [Pike style](http://doc.cat-v.org/bell_labs/pikestyle) +* [Linux kernel coding standards](https://www.kernel.org/doc/Documentation/process/coding-style.rst) + + +File Layout +----------- + +* Comment with LICENSE and possibly short explanation of file/tool. +* Headers +* Macros +* Types +* Function declarations: + * Include variable names. + * For short files these can be left out. + * Group/order in logical manner. +* Global variables. +* Function definitions in same order as declarations. +* `main` + + +C Features +---------- + +* Use C99 without extensions (ISO/IEC 9899:1999). +* Use POSIX.1-2008: + * When using gcc define `_POSIX_C_SOURCE 200809L`. + * Alternatively define `_XOPEN_SOURCE 700`. +* Do not mix declarations and code. +* Do not use for loop initial declarations. +* Use `/* */` for comments, not `//`. +* Variadic macros are acceptable, but remember: + * `__VA_ARGS__` not a named parameter. + * Arg list cannot be empty. + + +Blocks +------ + +* All variable declarations at top of block. +* `{` on same line preceded by single space (except functions). +* `}` on own line unless continuing statement (`if else`, `do while`, ...). + +Use block for single statement if inner statement needs a block. + + for (;;) { + if (foo) { + bar; + baz; + } + } + +Use block if another branch of the same statement needs a block: + + if (foo) { + bar; + } else { + baz; + qux; + } + + +Leading Whitespace +------------------ + +Use tabs for indentation and spaces for alignment. This ensures +everything will line up independent of tab size. This means: + +* No tabs except beginning of line. +* Use spaces - not tabs - for multiline macros as the indentation + level is 0, where the `#define` began. + + +Functions +--------- + +* Return type and modifiers on own line. +* Function name and argument list on next line. + This allows to grep for function names simply using `grep ^functionname(`. +* Opening `{` on own line (function definitions are a special case + of blocks as they cannot be nested). +* Functions not used outside translation unit should be declared + and defined `static`. + +Example: + + static void + usage(void) + { + eprintf("usage: %s [file ...]\n", argv0); + } + + +Variables +--------- + +* Global variables not used outside translation unit should be + declared `static`. +* In declaration of pointers the `*` is adjacent to variable name, + not type. + + +Keywords +-------- + +* Use a space after `if`, `for`, `while`, `switch` (they are not + function calls). +* Do not use a space after the opening `(` and before the closing `)`. +* Preferably use `()` with `sizeof`. +* Do not use a space with `sizeof()`. + + +Switch +------ + +* Do not indent cases another level. +* Comment cases that FALLTHROUGH. + +Example: + + switch (value) { + case 0: /* FALLTHROUGH */ + case 1: + case 2: + break; + default: + break; + } + + +Headers +------- + +* Place system/libc headers first in alphabetical order. + * If headers must be included in a specific order add a comment + to explain. +* Place local headers after an empty line. +* When writing and using local headers: + * Try to avoid cyclic header inclusion dependencies. + * Instead ensure they are included where and when they are needed. + * Read [Go import design](https://talks.golang.org/2012/splash.article#TOC_5.) + * Read [Plan 9 compiler notes](http://plan9.io/sys/doc/comp.html) + + +User Defined Types +------------------ + +* Do not use `type_t` naming (it is reserved for POSIX and less + readable). +* Typedef opaque structs. +* Do not typedef builtin types. +* Use `CamelCase` for typedef'd types. + + +Line Length +----------- + +* Keep lines to reasonable length (max 79 characters). + + +Tests and Boolean Values +------------------------ + +* Do not use C99 `bool` types (stick to integer types). +* Otherwise use compound assignment and tests unless the line grows + too long: + + if (!(p = malloc(sizeof(*p)))) + hcf(); + + +Handling Errors +--------------- + +* When functions `return -1` for error test against `0` not `-1`: + + if (func() < 0) + hcf(); + +* Use `goto` to unwind and cleanup when necessary instead of + multiple nested levels. +* `return` or `exit` early on failures instead of multiple nested + levels. +* Unreachable code should have a NOTREACHED comment. +* Think long and hard on whether or not you should cleanup on fatal + errors. For simple "one-shot" programs (not daemons) it can be OK + to not free memory. It is advised to cleanup temporary files however. + + +Enums and #define +----------------- + +Use enums for values that are grouped semantically and `#define` +otherwise: + + #define MAXSZ 4096 + #define MAGIC1 0xdeadbeef + + enum { + DIRECTION_X, + DIRECTION_Y, + DIRECTION_Z + };