tweak feed icons and tag list styles
[~bandali/bndl.org] / haunt.scm
CommitLineData
85314da0
AB
1(use-modules (haunt asset)
2 (haunt builder blog)
3 (haunt builder atom)
4 (haunt builder assets)
99ac860d 5 (haunt builder rss)
85314da0
AB
6 (haunt html)
7 (haunt page)
8 (haunt post)
9 (haunt reader commonmark)
10 (haunt site)
11 (haunt utils)
12 (ice-9 match)
13 (srfi srfi-19))
14
8c2dfb46
AB
15(define my-scheme 'https)
16(define my-domain "bandali.eu.org")
17(define my-url
18 (string-append (symbol->string my-scheme) "://" my-domain))
cfff0eef 19(define my-tag-prefix "tags")
38037201 20(define my-date-format "~B ~e, ~Y")
2527e234 21
85314da0
AB
22(define (stylesheet name)
23 `(link (@ (rel "stylesheet")
24 (href ,(string-append "/" name ".css")))))
25
455bb137
AB
26(define* (aa content #:optional (uri content) . title)
27 `(a (@ (href ,uri) (title ,(apply string-append title))) ,content))
28
6f911f10 29(define* (base-layout site body #:key title copy license-page?)
85314da0
AB
30 `((doctype "html")
31 (html
32 (head
33 (meta (@ (charset "utf-8")))
34 (title ,(if title (string-append title " — " (site-title site))
35 "Amin Bandali’s Personal Site"))
36 ,(stylesheet "reset")
37 ,(stylesheet "style"))
38 (body
39 (main ,body)
40 (footer
6f911f10
AB
41 (p "Copyright © "
42 ,(if copy copy "2016–2019")
43 " Amin Bandali. See "
44 ,(if license-page? "the above"
45 (aa "license.html" "/license.html"))
61246b59 46 " for license conditions. Please copy and share."))))))
85314da0 47
cfff0eef
AB
48(define* (tag-uri prefix tag #:optional (ext ".html"))
49 "Return a URI relative to the site's root for a page listing entries
50in PREFIX that are tagged with TAG."
51 (string-append "/" my-tag-prefix "/" tag ext))
52
53(define* (tag-pages #:key
54 (theme bandali-theme)
55 (prefix "")
56 (filter posts/reverse-chronological))
57 "Return a builder procedure that renders a list page for every tag
58used in a post. All arguments are optional:
59
60PREFIX: The directory in which to write the posts
61FILTER: The procedure called to manipulate the posts list before rendering"
62 (lambda (site posts)
63 (define (tag-list tag posts all-posts)
64 (define (render-list title posts prefix)
65 (let ((body ((theme-collection-template theme)
66 site title posts prefix all-posts tag)))
67 ((theme-layout theme) site title body)))
68 (make-page (tag-uri my-tag-prefix tag)
69 (render-list (string-append "Notes tagged ‘" tag "’")
70 (filter posts)
71 prefix)
72 sxml->html))
73 (let ((tag-groups (posts/group-by-tag posts)))
74 (map (match-lambda
75 ((tag . tagged-posts) (tag-list tag tagged-posts posts)))
76 tag-groups))))
77
78(define (tag-links posts)
79 "Generate an alphabetically sorted list of links to tagged posts.
80The link text consists of the tag name and the number of tagged posts
81in parentheses."
82 `(ul (@ (class "tag-list"))
83 ,(map (match-lambda
84 ((tag . posts)
85 `(li
86 ,(aa (string-append tag
87 " ("
88 (number->string (length posts))
89 ")")
90 (tag-uri my-tag-prefix tag)))))
91 ;; sort by tag
92 (sort (posts/group-by-tag posts)
93 (lambda (a b) (string<? (car a) (car b)))))))
2527e234
AB
94
95(register-metadata-parser! 'updated string->date*)
cd5ad35b 96
cfff0eef
AB
97(define (intersperse lst delim)
98 "Return the elements of LST delimited by DELIM, such that the
99resulting list is of an odd length and every second element is DELIM."
100 (if (<= (length lst) 1)
101 lst
102 (cons* (car lst)
103 delim
104 (intersperse (cdr lst) delim))))
105
cd5ad35b 106(define (my-post-template post)
85314da0
AB
107 `((header
108 (h1 ,(post-ref post 'title))
455bb137 109 (address "By " ,(aa (post-ref post 'author) "/")
85314da0
AB
110 " <" ,(post-ref post 'email) ">")
111 (p (@ (class "date"))
2527e234
AB
112 "Published "
113 ,(date->string (post-date post) my-date-format))
114 ,(if (post-ref post 'updated)
115 `(p (@ (class "updated"))
116 "Updated "
117 ,(date->string (post-ref post 'updated)
cfff0eef
AB
118 my-date-format)) '())
119 ,(if (post-ref post 'tags)
120 `(p (@ (class "tags"))
121 "Tagged "
122 ,@(intersperse
123 (map (lambda (tag)
124 (aa tag (tag-uri my-tag-prefix tag)))
125 (post-ref post 'tags))
126 ", "))
127 '()))
90169139
AB
128 ,(post-sxml post)
129 (p (@ (class "muted inbox"))
130 "Have a question or comment? Start a discussion in my "
455bb137 131 ,(aa "public inbox" "https://lists.sr.ht/~bandali/public-inbox")
90169139 132 " by sending an email to "
455bb137
AB
133 ,(aa "~bandali/public-inbox@lists.sr.ht"
134 "mailto:~bandali/public-inbox@lists.sr.ht")
90169139 135 (small
455bb137
AB
136 " [" ,(aa "mailing list etiquette"
137 "https://man.sr.ht/lists.sr.ht/etiquette.md") "]")
90169139 138 ".")))
85314da0 139
cfff0eef
AB
140(define* (my-collection-template site title posts prefix
141 #:optional all-posts tag)
85314da0
AB
142 (define (post-uri post)
143 (string-append (or prefix "") "/"
144 (site-post-slug site post) ".html"))
145
cfff0eef
AB
146 `((h2 ,title
147 ,(if tag
08d93db6
AB
148 (aa `(img (@ (class "feed-icon-h2")
149 (src "/icon-16px.png")
cfff0eef
AB
150 (alt "subscribe to atom feed")))
151 (tag-uri my-tag-prefix tag ".xml"))
152 '()))
1202585a
AB
153 (table
154 (@ (class "post-list"))
155 (tbody
156 ,@(map (lambda (post)
157 `(tr
158 (td ,(aa (post-ref post 'title) (post-uri post)))
08d93db6
AB
159 (td (small
160 ,(date->string (post-date post)
161 my-date-format)))))
cfff0eef
AB
162 posts)))
163 (h2 "Tags")
164 ,(tag-links (or all-posts posts))
165 ,(if tag
166 '(a (@ (href "/notes.html"))
08d93db6 167 "← all notes")
cfff0eef 168 '())))
85314da0
AB
169
170(define bandali-theme
171 (theme #:name "bandali"
172 #:layout
173 (lambda (site title body)
174 (base-layout site body
175 #:title title))
cd5ad35b
AB
176 #:post-template my-post-template
177 #:collection-template my-collection-template))
178
6f911f10 179(define* (static-page title file-name body copy #:key license?)
cd5ad35b
AB
180 (lambda (site posts)
181 (make-page file-name
6f911f10
AB
182 (base-layout site body #:title title #:copy copy
183 #:license-page? license?)
cd5ad35b 184 sxml->html)))
85314da0
AB
185
186(define (index-material site posts)
61246b59 187 `((h1 (@ (style "font-size: 0;"))
85314da0
AB
188 "Amin Bandali")
189 (p (@ (style "margin-top: 0;"))
190 "Hi, I’m "
455bb137
AB
191 ,(aa "Amin Bandali" "images/bandali-with-rms.jpg"
192 "photo of bandali with rms wearing a "
193 "“pay cash don’t be tracked” pin")
85314da0 194 ". I’m a graduate student at "
455bb137 195 ,(aa "WatForm" "https://watform.uwaterloo.ca")
85314da0 196 " at University of Waterloo, supervised by "
455bb137 197 ,(aa "Dr. Nancy Day" "https://cs.uwaterloo.ca/~nday/")
85314da0
AB
198 ". The main goal of my research is improving "
199 (strong "software and systems reliability")
200 " through application of " (em "formal methods") ".")
201 (p "My research at WatForm focuses on formal logic, model "
202 "checking, and verification. I’m also interested in "
203 "programming languages, theorem provers, and their "
204 "type systems. You may wish to view my academic "
455bb137 205 ,(aa "curriculum vitae" "bandali-cv.html") ".")
85314da0
AB
206 (p (@ (class "notice"))
207 (strong "SE 212 students: ")
455bb137
AB
208 "see " ,(aa "here" "se212-f19/") " for slides and other "
209 "material from the tutorials.")
85314da0 210 (p "On the side, I dabble in "
455bb137
AB
211 ,(aa "Lean" "https://leanprover.github.io") " and enjoy "
212 ,(aa "hacking" "https://stallman.org/articles/on-hacking.html")
85314da0 213 " on "
455bb137
AB
214 ,(aa "Elisp"
215 "https://www.gnu.org/software/emacs/manual/elisp.html")
216 ". I’m a " ,(aa "Free Software"
217 "https://www.gnu.org/philosophy/free-sw.html")
99ac860d 218 " activist, a GNU "
455bb137 219 ,(aa "maintainer" "https://www.gnu.org/people/#bandali")
85314da0 220 " and "
455bb137
AB
221 ,(aa "webmaster"
222 "https://www.gnu.org/people/webmeisters.html#bandali")
223 ", and an " ,(aa "associate member"
224 "https://www.fsf.org/associate/")
225 " of the " ,(aa "FSF" "https:///www.fsf.org"
226 "Free Software Foundation")
227 ". I co-host the " ,(aa "Emacs.el" "https://emacsel.com")
228 " podcast with " ,(aa "Daniel Gopar" "https://www.pygopar.com")
229 ", and organize " ,(aa "EmacsConf" "https://emacsconf.org")
230 " with help from many wonderful people. I am also a member of"
231 " the Systems Committee for the "
232 ,(aa "CSC" "https://csclub.uwaterloo.ca"
233 "Computer Science Club of the University of Waterloo")
85314da0 234 ".")
455bb137
AB
235 (p "See my " ,(aa "contact" "contact.html") " page for how to "
236 "best reach me.")
85314da0
AB
237 (h2 (@ (id "papers")) "Papers")
238 (dl
239 (dt "A Comparison of the Declarative Modelling Languages B, DASH,
240 and TLA" (sup "+")
90169139 241 (small
455bb137
AB
242 " [ " ,(aa "pdf" "papers/modre2018-declarative.pdf") " | "
243 ,(aa "bib" "papers/modre2018-declarative.bib") " ]"))
85314da0 244 (dd "Ali Abbassi, "
8c2dfb46 245 ,(aa "Amin Bandali" my-url) ", "
455bb137
AB
246 ,(aa "Nancy A. Day" "https://cs.uwaterloo.ca/~nday/") ", "
247 "Jose Serna"
85314da0
AB
248 (br)
249 (em "2018 IEEE 8th International Model-Driven Requirements"
250 " Engineering Workshop (MoDRE)")
251 (br)
252 "Copyright © 2018 IEEE. All Rights Reserved. Sadly."))
253 (h2 (@ (id "talks")) "Talks")
254 (dl
255 (dt
256 "The Magic of Specifications and Type Systems"
455bb137
AB
257 (small
258 " [ "
259 ,(aa "slides" "talks/cucsc-2017-slides.pdf"
260 "presented at the Canadian Undergraduate Computer Science"
261 " Conference 2017,\n"
262 "University of Toronto, Canada, June 15–17, 2017")
263 " | "
264 ,(aa "poster" "talks/eecs4080-poster.pdf"
265 "presented at the Lassonde Undergraduate Summer Student"
266 " Research Conference,\n"
267 "York University, Toronto, Canada, August 15, 2017")
268 " ]"))
8c2dfb46 269 (dd ,(aa "Amin Bandali" my-url) ", "
455bb137
AB
270 ,(aa "Simon Hudon" "https://github.com/cipher1024") ", "
271 ,(aa "Jonathan S. Ostroff"
272 "http://www.cse.yorku.ca/~jonathan/")))
85314da0
AB
273 (h2 (@ (id "projects")) "Projects")
274 (p "Below are a number of free software projects I have worked "
275 "on:")
276 (dl
455bb137 277 (dt ,(aa "george-mode" "https://git.sr.ht/~bandali/george-mode"))
85314da0 278 (dd "Emacs major mode for editing George files")
455bb137
AB
279 (dt ,(aa "alloy-catalyst"
280 "https://git.uwaterloo.ca/bandali/alloy-catalyst"))
85314da0 281 (dd "Framework for performance analysis of Alloy models")
455bb137 282 (dt ,(aa "unitb-web" "https://github.com/unitb/unitb-web"))
85314da0 283 (dd "Web interface for Unit-B")
455bb137 284 (dt ,(aa "tex2png-hs" "https://github.com/unitb/tex2png-hs"))
85314da0
AB
285 (dd "Library and CLI for converting TeX and LaTeX to PNG "
286 "images"))
287 (h2 (@ (id "notes")) "Notes")
22cb271b 288 (p "Here are notes about a variety of topics and issues I care "
08d93db6
AB
289 "about. They’re also available via "
290 ,(aa `((img (@ (class "feed-icon")
291 (src "/icon-12px.png")
292 (alt "subscribe to atom feed")))
293 "Atom")
294 "notes.atom")
295 " and "
296 ,(aa `((img (@ (class "feed-icon")
297 (src "/icon-12px.png")
298 (alt "subscribe to rss feed")))
299 "RSS") "notes.rss") " feeds.")
60d388df
AB
300 (table
301 (@ (class "post-list"))
302 (tbody
f9e7c277
AB
303 ,@(map
304 (lambda (post)
305 (define (post-uri post)
306 (string-append "/"
307 (site-post-slug site post) ".html"))
308 `(tr
309 (td ,(aa (post-ref post 'title) (post-uri post)))
310 (td (small
311 ,(date->string (post-date post) my-date-format)))))
312 (take-up-to 10 (posts/reverse-chronological posts)))))))
85314da0
AB
313
314(define (index-page site posts)
315 (make-page
316 "index.html"
317 (base-layout site (index-material site posts))
318 sxml->html))
319
cd5ad35b
AB
320(define license-page
321 (static-page
6f911f10 322 "Licensing Information"
cd5ad35b 323 "license.html"
61246b59
AB
324 `((h1 "License information for "
325 ,(aa my-domain my-url))
cd5ad35b 326 (p "I strongly believe in "
455bb137
AB
327 ,(aa "free culture"
328 "https://questioncopyright.org/what_is_free_culture")
cd5ad35b 329 " and that all creative works everywhere should be "
455bb137 330 ,(aa "free" "https://freedomdefined.org/Definition") ".")
cd5ad35b
AB
331 (p "Unless otherwise noted material on this site is licensed "
332 "under the GNU General Public License as published by the "
333 "Free Software Foundation, either version 3 of the License, "
334 "or (at your option) any later version. A copy of the "
455bb137 335 "license is included at " ,(aa "gpl-3.0.html") ".")
cd5ad35b
AB
336 (p "Some resources on free software and licenses:")
337 (ul
455bb137
AB
338 (li ,(aa "What is free software?"
339 "https://www.gnu.org/philosophy/free-sw.html"))
340 (li ,(aa "Various Licenses and Comments about Them"
341 "https://www.gnu.org/licenses/license-list.html"))
342 (li ,(aa "Proprietary Software Is Often Malware"
6f911f10
AB
343 "https://www.gnu.org/proprietary/proprietary.html"))))
344 "2019"
345 #:license? #t))
cd5ad35b 346
7c12f0da
AB
347(define contact-page
348 (static-page
349 "Contact Information"
350 "contact.html"
351 `((h1 "Contact information")
352 (p "Email is by far my preferred method of communication. I may"
353 " be contacted at any of the following addresses (choose the"
354 " most closely related):")
355 (ul
356 (li "bandali@gnu.org")
357 (li "bandali@uwaterloo.ca")
358 (li "bandali@csclub.uwaterloo.ca"))
359 (p "If you want to send me GPG-encrypted mail, you can use my "
360 ,(aa "public key" "bandali-pubkey.txt") " with the"
361 " fingerprint "
362 (code "BE62 7373 8E61 6D6D 1B3A 08E8 A21A 0202 4881 6103")
363 ".")
364 (table
365 (tbody
366 (tr
367 (td "IRC")
368 (td "bandali on " ,(aa "freenode" "https://freenode.net") ", "
369 ,(aa "moznet" "https://wiki.mozilla.org/IRC") ", and "
370 ,(aa "oftc" "https://www.oftc.net")))
371 (tr
372 (td "XMPP")
373 (td ,(aa "bandali@member.fsf.org"
374 "xmpp:bandali@member.fsf.org")))
375 (tr
376 (td "Matrix")
377 (td ,(aa "@bandali:matrix.org"
378 "https://matrix.to/#/@bandali:matrix.org")))
379 (tr
380 (td "Fediverse")
381 (td ,(aa "@bandali@pleroma.site"
382 "https://pleroma.site/bandali")))))
383 (h2 "Elsewhere")
384 (p "You may also find me at a few other places online. Stricken"
385 " through accounts are those I don’t use anymore, unless"
386 " absolutely necessary.")
387 (ul
388 (li ,(aa "bandali" "https://libreplanet.org/wiki/User:Bandali")
389 " on LibrePlanet")
390 (li ,(aa "bandali" "https://emacsconf.org/bandali")
391 " on EmacsConf")
392 (li ,(aa "bandali" "https://savannah.gnu.org/users/bandali")
393 " on Savannah")
394 (li ,(aa "bandali" "https://git.sr.ht/~bandali")
395 " on Sourcehut")
396 (li ,(aa "bandali" "https://lobste.rs/u/bandali")
397 " on Lobsters")
398 (li ,(aa "bandali" "https://hackage.haskell.org/user/bandali")
399 " on Hackage")
400 (li ,(aa "bandali" "https://gitlab.com/bandali")
e810d7d1 401 " on GitLab")
7c12f0da
AB
402 (li ,(aa "bandali"
403 "https://news.ycombinator.com/user?id=bandali")
404 " on HN")
405 (li ,(aa "bandali" "https://www.reddit.com/u/bandali")
406 " on reddit")
407 (li (del ,(aa "bandali0" "https://github.com/bandali0")
408 " on GitHub"))
409 (li (del ,(aa "bandali0" "https://twitter.com/bandali0")
6f911f10
AB
410 " on Twitter"))))
411 "2019"))
7c12f0da 412
cd68557a
AB
413(define cv-page
414 (static-page
415 "Curriculum vitae"
416 "bandali-cv.html"
417 `((h1 "Curriculum vitae (" ,(aa "PDF" "bandali-cv.pdf") ")")
418 (table
419 (tbody
420 (tr
421 (td "Site")
422 (td ,(aa my-domain my-url)))
423 (tr
424 (td "Email")
425 (td "bandali@uwaterloo.ca"))
426 (tr
427 (td "Phone")
428 (td "available upon request via email"))))
429 (h2 "Education")
430 (h3 "Master of Mathematics (Computer Science) | 2018–present")
431 (p "University of Waterloo, Canada")
432 (p "Supervised by Dr. Nancy Day | GPA: 3.7/4.0 | "
433 "Expected completion: April 2020")
434 (p "Research focusing on formal logic, model checking, and "
435 "verification.")
436 (h3 "B.Sc. Honours Computer Science | 2013–2017")
437 (p "York University, Toronto, Canada")
438 (p "GPA: 7.84/9.0")
439 (p "Relevant courses: System Specification & Refinement, "
440 "Software Requirements Eng., Software Design, "
441 "Operating Systems, Computational Complexity, "
442 "Design & Analysis of Algorithms.")
443 (p "Finished first year (2013-14) at " (em "Carleton University")
444 " with a GPA of 11.0/12.0, then transferred to "
445 (em "York University") " in Fall 2014.")
446 (h2 "Publications")
447 (p "Listed on my " ,(aa "homepage" "/#papers"))
448 (h2 "Work & Research Experience")
449 (h3 "Cheriton School of Computer Science, University of Waterloo"
450 " | 2018–present")
451 (p "Instructional Apprentice, Teaching Assistant, "
452 "Research Assistant")
453 (ul
454 (li (abbr (@ (title "Logic and Computation")) "SE 212") ": "
455 (abbr (@ (title "Instructional Apprentice")) "IA") " in "
456 "Fall 2019, "
457 (abbr (@ (title "Teaching Assistant")) "TA") " in "
458 "Fall 2018")
459 (li (abbr (@ (title ,(string-append
460 "Software Requirements Specification and "
461 "Analysis"))) "SE 463")
462 ": TA in Summer 2019 and 2018")
463 (li (abbr (@ (title ,(string-append
464 "Elementary Algorithm Design and "
465 "Data Abstraction"))) "CS 136")
466 ": TA in Winter 2018"))
467 (h3 (abbr (@ (title
468 ,(string-append
469 "Electrical Engineering & Computer Science")))
470 "EECS")
471 " Department, York University | Fall 2017")
472 (p "Teaching Assistant")
473 (p (abbr (@ (title "Net-Centric Introduction to Computing"))
474 "EECS 1012")
6f911f10
AB
475 ": TA in Fall 2017"))
476 "2019"))
cd68557a 477
577bfe36
AB
478(define se212-f19-page
479 (static-page
480 "SE 212 Material"
481 "se212-f19/index.html"
482 `((h1 "Material from SE 212 tutorials")
483 (p "This page contains slides and other material from "
484 ,(aa "SE 212 tutorials"
485 "https://www.student.cs.uwaterloo.ca/~se212/times.html")
486 " held by me in Fall 2019. "
487 (del "If you have any questions, concerns, or suggestions "
488 "about the presented material, please email me at "
489 "bandali@uwaterloo.ca or come see me during my "
490 ,(aa "Friday office hours"
491 "https://www.student.cs.uwaterloo.ca/~se212/personnel.html")
492 "."))
493 (ul
494 (li "Tutorial 1:"
495 (ul
496 (li ,(aa "TUT 101 slides" "se212-t01-101.pdf"))
497 (li ,(aa "TUT 102 slides" "se212-t01-102.pdf"))
498 (li ,(aa "Org beamer sources" "se212-t01.org"))))
499 (li "Tutorial 2:"
500 (ul
501 (li ,(aa "Homework 2 q04d solution"
502 "se212-h02q04d-soln.grg"))))
503 (li "Tutorial 3: —")
504 (li "Tutorial 4: —")
505 (li "Tutorial 5:"
506 (ul
507 (li ,(aa "Slides" "se212-t05.pdf"))
508 (li ,(aa "Org beamer sources" "se212-t05.org"))))
509 (li "Tutorial 6: —")
510 (li "Tutorial 7: worked through questions 1–5 of Homework 7")
511 (li "Tutorial 8: —")
512 (li "Tutorial 9: —")
513 (li "Tutorial 10: worked through questions 1–10 of "
6f911f10
AB
514 "Homework 10")))
515 "2019"))
577bfe36 516
7e8d7215
AB
517(module-define!
518 (resolve-module '(haunt builder blog))
519 'render-post
520 (lambda (theme site post)
521 (let ((title (post-ref post 'title))
522 (body ((theme-post-template theme) post))
523 (copy (post-ref post 'copyright)))
524 (base-layout site body #:title title #:copy copy))))
525
85314da0 526(site #:title "Amin Bandali"
8c2dfb46
AB
527 ;; TODO: uncomment after new haunt release
528 ;; #:scheme my-scheme
85314da0
AB
529 #:domain my-domain
530 #:default-metadata
531 '((author . "Amin Bandali")
532 (email . "bandali@gnu.org")
533 (domain . my-domain))
534 #:readers (list commonmark-reader)
535 #:builders (list (blog #:theme bandali-theme
536 #:collections
537 `(("Notes" "notes.html"
538 ,posts/reverse-chronological)))
cfff0eef 539 (tag-pages)
85314da0 540 index-page
99ac860d 541 (atom-feed
cfff0eef 542 #:file-name "notes.atom")
99ac860d 543 (atom-feeds-by-tag
cfff0eef 544 #:prefix my-tag-prefix)
99ac860d 545 (rss-feed
cfff0eef 546 #:file-name "notes.rss")
7c12f0da 547 contact-page
cd68557a 548 cv-page
cd5ad35b 549 license-page
577bfe36 550 se212-f19-page
85314da0 551 (static-directory "static" "")))