From 495f9db0606b0ed09e6fac59dc32de4cdc8c0087 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Sun, 28 Mar 2021 00:03:41 +0100 Subject: 2021 Spring redesign --- site/cleopatra.org | 62 +- site/cleopatra/commands.org | 36 ++ site/cleopatra/coq.org | 60 +- site/cleopatra/dependencies.org | 89 +++ site/cleopatra/literate-programming.org | 27 +- site/cleopatra/org.org | 183 +++--- site/cleopatra/soupault.org | 811 ++++++++++++------------- site/cleopatra/theme.org | 722 ++++++++++++++-------- site/coq.org | 44 ++ site/haskell.org | 13 + site/img/icons.svg | 39 ++ site/img/merida.webp | Bin 36922 -> 0 bytes site/index.org | 77 +-- site/meta.org | 23 + site/miscellaneous.org | 14 + site/news/index.html | 15 + site/opinions/MonadTransformers.org | 13 +- site/opinions/index.org | 6 +- site/posts/AlgebraicDatatypes.v | 6 +- site/posts/ClightIntroduction.v | 6 +- site/posts/Coqffi.org | 7 +- site/posts/CoqffiEcho.org | 10 +- site/posts/CoqffiIntro.org | 10 +- site/posts/ExtensibleTypeSafeErrorHandling.org | 9 +- site/posts/Ltac.org | 18 +- site/posts/LtacMetaprogramming.v | 3 + site/posts/LtacPatternMatching.v | 10 +- site/posts/MixingLtacAndGallina.v | 5 +- site/posts/RewritingInCoq.v | 6 +- site/posts/StronglySpecifiedFunctions.org | 7 +- site/posts/StronglySpecifiedFunctionsProgram.v | 11 +- site/posts/StronglySpecifiedFunctionsRefine.v | 20 +- site/posts/Thanks.org | 40 +- 33 files changed, 1392 insertions(+), 1010 deletions(-) create mode 100644 site/cleopatra/commands.org create mode 100644 site/cleopatra/dependencies.org create mode 100644 site/coq.org create mode 100644 site/haskell.org create mode 100644 site/img/icons.svg delete mode 100644 site/img/merida.webp create mode 100644 site/meta.org create mode 100644 site/miscellaneous.org (limited to 'site') diff --git a/site/cleopatra.org b/site/cleopatra.org index 77e8ff1..0831621 100644 --- a/site/cleopatra.org +++ b/site/cleopatra.org @@ -1,46 +1,44 @@ -#+BEGIN_EXPORT html -

A Series on Generating this Static Website

-#+END_EXPORT +#+TITLE: A Series on Generating this Static Website -The generation of this website is far from being trivial, and requires the -combination of —probably too— many tools. For instance, my write-ups about Coq -are actually Coq files, and I use ~coqdoc~ to generate the HTML pages you read. -The theme is not written in CSS, but in SASS that needs to be compiled. Even -more, the whole website is postprocessed using ~soupault~. +#+SERIES: ./meta.html +#+SERIES_PREV: ./posts/Thanks.html + +At some point, I felt like the whole process of generating this +website was interesting enough so that it would deserve a write-up of +its own, but the risk was that such a piece of text would quickly +become out-dated. This is reminescent of documenting any software +project, and I was aware at that time of a dedicated paradigm to +prevent these kind of issues: [[http://www.literateprogramming.com/][literate programming]]. -At some point, I felt like the whole process was interesting enough so that it -would deserve a write-up of its own, but the risk was that such a piece of text -would quickly become out-dated. This is reminescent of documenting any software -project, and I was aware at that time of a dedicated paradigm to prevent these -kind of issues: [[http://www.literateprogramming.com/][literate programming]]. I spent quite some time turning my custom toolchain into a literate program, so that its actual code source would actually be the write-ups I wanted to add to my website. This was an interesting challenge, since it meant *~cleopatra~* would have to generate itself before it could build my website. In other words, *~cleopatra~* achieves the bootstsrapping challenge! -I really enjoyed this first experiment with literate programming, and I started -using *~cleopatra~* for other projects of mine where literate programming felt -like an interesting choice. In doing so, it quickly became clear *~cleopatra~* -was cumbersome to set-up for a new project. At the end, -[[https://cleopatra.soap.coffee][I ended up rewriting it]] to overcome the -specific issues posed by its initial design[fn:bootstrap]. But the so-called -generation processes I had written for *~cleopatra~* the first basically “just -worked” with *~cleopatra~* the second. +I really enjoyed this first experiment with literate programming, and +I started using *~cleopatra~* for other projects of mine where +literate programming felt like an interesting choice. In doing so, it +quickly became clear *~cleopatra~* was cumbersome to set-up for a new +project. At the end, [[https://cleopatra.soap.coffee][I ended up rewriting it]] to overcome the specific +issues posed by its initial design[fn::For the record, this second +version is also implemented using literate programming, and if I was +first using the first version to build it, I quickly “made the +bootstrap jump.”]. But the so-called generation processes I had +written for *~cleopatra~* the first basically “just worked” with +*~cleopatra~* the second. So, coming back to this series, it is just the very reason why I started using *~cleopatra~* in the first place: the generation processes used by this website, written as literate programs. -#+BEGIN_EXPORT html -
-#+END_EXPORT +- [[./cleopatra/dependencies.org][Installing Dependencies]] :: -- [[./cleopatra/theme.org][Theming and Templating]] :: +- [[file:cleopatra/coq.org][Authoring Contents with Coq ~(TODO)~]] :: -- [[file:cleopatra/coq.org][Authoring Contents As Coq Documents ~(TODO)~]] :: +- [[./cleopatra/org.org][Authoring Contents with ~org-mode~ ~(TODO)~]] :: -- [[./cleopatra/literate-programming.org][Authoring Literate Programs]] :: +- [[./cleopatra/literate-programming.org][Literate Programming Projects]] :: Literate programming is an interesting exercice, and it is particularly well-suited for blog posts, since at the very least it provides the tool to enforce the code presented to readers is @@ -48,7 +46,7 @@ written as literate programs. programming projects present in the ~posts/~ directory of this website. -- [[./cleopatra/org.org][Authoring Contents As Org Documents ~(TODO)~]] :: +- [[./cleopatra/theme.org][Layout and Style]] :: - [[./cleopatra/soupault.org][Processing HTML with ~soupault~]] :: ~soupault~ is a HTML processor, and it can be used as a static website @@ -57,11 +55,3 @@ written as literate programs. *Appendix:* In case you are curious, you can have a look at [[./posts/CleopatraV1.html][the first implementaiton of *~cleopatra~*]]. - -#+BEGIN_EXPORT html -
-#+END_EXPORT - -[fn:bootstrap] For the record, this second version is also implemented using -literate programming, and if I was first using the first version to build it, I -quickly “made the bootstrap jump.” diff --git a/site/cleopatra/commands.org b/site/cleopatra/commands.org new file mode 100644 index 0000000..fbf0430 --- /dev/null +++ b/site/cleopatra/commands.org @@ -0,0 +1,36 @@ +#+TITLE: Adhoc *~cleopatra~* commands + +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./soupault.html + +In this generation process, we provide adhoc commands to ease the +authoring experience. A given command ~~ is implemented as a +~makefile~ rule, and can be called with ~cleopatra ~. + +#+BEGIN_EXPORT html + +
site/cleopatra/commands.org
+#+END_EXPORT + +* ~serve~ + + This command spawns a simple HTTP server which allows us to navigate + the website more easily. + + #+begin_src makefile :tangle commands.mk +serve : + @cleopatra echo Spwaning "HTTP server" + @cd out && python -m http.server + #+end_src + +* ~update~ + + This commands updates the various dependencies locally installed to + build this website, such as ~soupault~ for instance. + + #+begin_src makefile :tangle commands.mk +update : + @cleopatra echo "Updating" "OCaml dependencies" + @opam update + @opam upgrade -y + #+end_src diff --git a/site/cleopatra/coq.org b/site/cleopatra/coq.org index 64d1e9d..81f3d27 100644 --- a/site/cleopatra/coq.org +++ b/site/cleopatra/coq.org @@ -1,3 +1,15 @@ +#+TITLE: Authoring Content with Coq + +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./dependencies.html +#+SERIES_NEXT: ./org.html + +#+BEGIN_EXPORT html + +
site/cleopatra/coq.org
+#+END_EXPORT + + * Author Guidelines * Under the Hood @@ -13,7 +25,6 @@ COQ_ARTIFACTS := $(COQ_POSTS:.v=.vo) \ coq-build : ${COQ_HTML} -theme-build : site/style/coq.sass soupault-build : coq-build ARTIFACTS += ${COQ_ARTIFACTS} .lia.cache @@ -28,52 +39,9 @@ COQDOCARG := --no-index --charset utf8 --short \ --external "https://compcert.org/doc/html" compcert \ --external "https://lysxia.github.io/coq-simple-io" SimpleIO -%.html : %.v coq.mk - @cleopatra echo Exporting "$*.v" +%.html : %.v coq.mk _opam/init + @cleopatra echo Exporting "$*.v" @coqc ${COQCARG} $< @coqdoc ${COQDOCARG} -d $(shell dirname $<) $< @rm -f $(shell dirname $<)/coqdoc.css #+END_SRC - -#+BEGIN_SRC sass :tangle site/style/coq.sass -div.code - padding-left : 1.5rem - padding-left : 1.5rem - white-space: nowrap - line-height : 140% - -div.code, -span.inlinecode - font-family : 'Fira Code', monospace - color : $monospace-color - font-size : 80% - overflow-x : auto - -div.doc - max-width : $content-width - line-height : 140% - - /* dirty patch to get the code in full page width */ - pre - width : calc(100vw - 2*var(--side-margin)) - -.paragraph - margin-bottom : .8em -#+END_SRC - -#+BEGIN_SRC sass :tangle site/style/coq.sass -.code - a[href] - color : inherit - text-decoration : none - background : #f7f7f7 - padding : .1rem .15rem .1rem .15rem - border-radius : 15% - - .url-mark - display: none -#+END_SRC - -# Local Variables: -# org-src-preserve-indentation: t -# End: diff --git a/site/cleopatra/dependencies.org b/site/cleopatra/dependencies.org new file mode 100644 index 0000000..5a79741 --- /dev/null +++ b/site/cleopatra/dependencies.org @@ -0,0 +1,89 @@ +#+TITLE: Installing Dependencies + +#+SERIES: ../cleopatra.html +#+SERIES_NEXT: ./coq.html + +* OCaml and Coq + + #+caption: Dependencies for Coq articles + #+name: coq-deps + | Package | Version | + |--------------+---------| + | coq | 8.13.1 | + | coq-compcert | 3.8 | + + #+caption: Dependencies for the ~coqffi~ series + #+name: lp-deps + | Package | Version | + |---------------+-------------| + | dune | 2.8.4 | + | coq-coqffi | 1.0.0~beta5 | + | coq-simple-io | 1.5.0 | + + #+caption: Soupault + #+name: soupault-deps + | Package | Version | + |----------+---------| + | soupault | 2.5.0 | + + #+name: deps-listing + #+begin_src emacs-lisp :noweb yes :var coq-deps=coq-deps :var lp-deps=lp-deps :var soupault-deps=soupault-deps :results value raw :exports none +;; We use this Emacs Lisp snippet to generate the list of dependencies +;; we have to install with Opam +(defun fmt-deps (d) + (mapconcat (lambda (d) (format "%s" d)) d ".")) + +(string-join + (append (mapcar 'fmt-deps lp-deps) + (mapcar 'fmt-deps soupault-deps) + (mapcar 'fmt-deps coq-deps)) + " ") + #+end_src + + #+begin_src makefile :tangle dependencies.mk :noweb yes +OCAML_VERSION := 4.11.2 +OCAML := ocaml-base-compiler.${OCAML_VERSION} + +_opam/init : + @cleopatra echo "Creating" "a local Opam switch" + @opam switch create . ${OCAML} --repos default,coq-released || true + @cleopatra echo "Installing" "OCaml dependencies" + @opam install <> -y + @touch $@ + +CONFIGURE += _opam + #+end_src + +* Frontend + + #+caption: Frontend dependencies + #+name: frontend-deps + | Package | Version | + |---------------+---------| + | katex | 0.13.0 | + | minify | 7.0.1 | + | normalize.css | 8.0.1 | + + #+name: frontend-listing + #+begin_src emacs-lisp :var frontend-deps=frontend-deps :exports none +;; We use this Emacs Lisp snippet to generate the list of dependencies +;; we have to install with npm +(defun fmt-deps (d) + (format " \"%s\": \"^%s\"" (nth 0 d) (nth 1 d))) + +(string-join (mapcar 'fmt-deps frontend-deps) ",\n") + #+end_src + + #+begin_src json :tangle package.json :noweb yes +{ + "dependencies": { + <> + } +} + #+end_src + + #+begin_src makefile :tangle dependencies.mk :noweb yes +package-lock.json : package.json + @cleopatra echo "Installing" "frontend dependencies" + @npm install + #+end_src diff --git a/site/cleopatra/literate-programming.org b/site/cleopatra/literate-programming.org index be25097..63e0b02 100644 --- a/site/cleopatra/literate-programming.org +++ b/site/cleopatra/literate-programming.org @@ -1,6 +1,8 @@ -#+BEGIN_EXPORT html -

Literate Programming Projects

-#+END_EXPORT +#+TITLE: Literate Programming Projects + +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./org.html +#+SERIES_NEXT: ./theme.html Literate programming is an interesting exercice. It forces programmers to think about how to present their code for other people to @@ -12,18 +14,27 @@ That being said, literate programming is particularly well-suited for blog posts, since at the very least it provides the tool to enforce the code presented to readers is correct. +#+BEGIN_EXPORT html + +
site/cleopatra/literate-programming.org
+#+END_EXPORT + +* Tangling + We use Emacs and ~org-mode~ to tangle the literate programming projects present in the ~posts/~ directory of this website. This is done with the following emacs lisp script. #+BEGIN_SRC emacs-lisp :tangle export-lp.el -(cleopatra:configure) ; opinionated configuration provided by cleopatra +;; opinionated configuration provided by cleopatra +(cleopatra:configure) +;; allow the execution of shell block code (org-babel-do-load-languages 'org-babel-load-languages - '((shell . t))) ; allow the execution of shell block code + '((shell . t))) - ;; scan the posts/ directory and tangled it into lp/ +;; scan the posts/ directory and tangled it into lp/ (setq org-publish-project-alist '(("lp" :base-directory "site/posts" @@ -46,6 +57,8 @@ literate-programming-prebuild : ARTIFACTS += lp/ site/posts/deps.svg #+END_SRC +* Building + In the =build= phase, we actually try to compile the tangled projects. As of now, there is only one literate program: [[../posts/CoqffiEcho.org][the Echo server implemented in Coq]] which demonstrates how ~coqffi~ can be used to @@ -54,7 +67,7 @@ implement realistic software projects. #+BEGIN_SRC makefile :tangle literate-programming.mk COQFFI_ARCHIVE := site/files/coqffi-tutorial.tar.gz -coqffi-tutorial-build : literate-programming-prebuild +coqffi-tutorial-build : literate-programming-prebuild _opam/init @cleopatra echo "Building" "coqffi tutorial" @cd lp/coqffi-tutorial; dune build --display quiet @cleopatra echo "Archiving" "coqffi tutorial" diff --git a/site/cleopatra/org.org b/site/cleopatra/org.org index acfd432..829272b 100644 --- a/site/cleopatra/org.org +++ b/site/cleopatra/org.org @@ -1,54 +1,30 @@ -* Author Guidelines - -* Under the Hood +#+TITLE: Authoring Content with ~org-mode~ -#+BEGIN_SRC emacs-lisp :tangle scripts/packages.el -(use-package lua-mode :ensure t :defer t) -(use-package rust-mode :ensure t :defer t) -(use-package sass-mode :ensure t :defer t) -(use-package haskell-mode :ensure t :defer t) -(use-package toml-mode :ensure t :defer t) -(use-package json-mode :ensure t :defer t) -(use-package proof-general :ensure t :defer t) -(use-package tuareg :ensure t :defer t) -#+END_SRC - -#+BEGIN_SRC emacs-lisp :tangle scripts/export-org.el -(cleopatra:configure) +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./coq.html +#+SERIES_NEXT: ./literate-programming.html -(setq org-html-doctype "html5") -(setq org-html-html5-fancy t) - -(org-babel-do-load-languages - 'org-babel-load-languages - '((shell . t) - (dot . t))) +#+BEGIN_EXPORT html + +
site/cleopatra/org.org
+#+END_EXPORT -(setq org-html-htmlize-output-type nil) -(setq org-export-with-toc nil) - -(add-to-list 'org-entities-user - '("im" "\\(" nil "" "" "" "")) -(add-to-list 'org-entities-user - '("mi" "\\)" nil "" "" "" "")) +* Author Guidelines -(org-html-export-to-html nil nil nil t) -#+END_SRC +* Implementation -#+BEGIN_SRC makefile :tangle org.mk +#+begin_src makefile :tangle org.mk EMACS := cleopatra-emacs -ORG_POSTS := $(shell find site/ -name "*.org") -ORG_HTML := $(ORG_POSTS:.org=.html) +ORG_IN := $(shell find site/ -name "*.org") +ORG_OUT := $(ORG_IN:.org=.html) org-prebuild : .emacs -org-build : ${ORG_HTML} +org-build : ${ORG_OUT} -theme-build : site/style/org.sass soupault-build : org-build -org-build : literate-programming-build -ARTIFACTS += ${ORG_HTML} +ARTIFACTS += ${ORG_OUT} CONFIGURE += .emacs EXPORT := --batch \ @@ -68,44 +44,91 @@ INIT := --batch --load="${ROOT}/scripts/packages.el" \ .emacs org.mk @cleopatra echo Exporting "$*.org" @${EMACS} $< ${EXPORT} -#+END_SRC - -#+BEGIN_SRC sass :tangle site/style/org.sass -#text-footnotes - max-width : 35rem - -.footpara - display: inline - margin-left: .2em - -.section-number-2:after, -.section-number-3:after - content: ". " - -.section-number-4, -.section-number-5, -.section-number-6 - display: none - -dl - dd p - margin-top: 0 - -.footnotes - font-size : 1rem - -.org-literate-programming - .org-src-tangled-to:before - content: "\f054" - font : normal normal normal 11px/1 ForkAwesome - - .org-src-tangled-to, - padding-left : 2rem - - .org-src-tangled-to, - .org-src-name - font-family : 'Fira Code', monospace - font-size : 70% - font-weight: bold - color : #444 -#+END_SRC +#+end_src + +#+begin_src emacs-lisp :tangle scripts/packages.el +(use-package ox-tufte :ensure t) +#+end_src + +#+begin_src emacs-lisp :tangle scripts/export-org.el +(cleopatra:configure) + +(org-babel-do-load-languages + 'org-babel-load-languages + '((dot . t) + (shell . t))) + +(setq org-export-with-toc nil + org-html-htmlize-output-type nil + org-export-with-section-numbers nil) + +(add-to-list 'org-entities-user + '("im" "\\(" nil "" "" "" "")) +(add-to-list 'org-entities-user + '("mi" "\\)" nil "" "" "" "")) + +(defun with-keyword (keyword k) + "Look-up for keyword KEYWORD, and call continuation K with its value." + (pcase (org-collect-keywords `(,keyword)) + (`((,keyword . ,kw)) + (when kw (funcall k (string-join kw " ")))))) + +(defun get-keyword (keyword) + "Look-up for keyword KEYWORD, and returns its value" + (with-keyword keyword (lambda (x) x))) + +(defun get-org-title (path) + "Fetch the title of an Org file whose path is PATH." + (with-temp-buffer + (find-file-read-only path) + (get-keyword "TITLE"))) + +(defun insert-title () + "Insert the title of the article." + (with-keyword + "TITLE" + (lambda (title) + (insert + (format "\n\n@@html:

@@ %s @@html:

@@\n\n" title))))) + +(defun insert-series () + "Insert the series root link." + (with-keyword + "SERIES" + (lambda (series) + (insert "\n\n#+attr_html: :class series\n") + (insert series)))) + +(defun insert-series-prev () + "Insert the series previous article link." + (with-keyword + "SERIES_PREV" + (lambda (series-prev) + (insert "\n\n#+attr_html: :class series-prev\n") + (insert series-prev)))) + +(defun insert-series-next () + "Insert the series next article link." + (with-keyword + "SERIES_NEXT" + (lambda (series-next) + (insert "\n\n#+attr_html: :class series-next\n") + (insert series-next)))) + +(defun insert-nav () + "Insert the navigation links." + (when (get-keyword "SERIES") + (insert "\n\n#+begin_nav\n") + (insert-series) + (insert-series-prev) + (insert-series-next) + (insert "\n\n#+end_nav\n"))) + +(beginning-of-buffer) +(insert-nav) +(insert-title) + +(let ((outfile (org-export-output-file-name ".html")) + (org-html-footnotes-section "")) + (org-export-to-file 'tufte-html outfile nil nil nil t)) +#+end_src diff --git a/site/cleopatra/soupault.org b/site/cleopatra/soupault.org index 452f442..92042c2 100644 --- a/site/cleopatra/soupault.org +++ b/site/cleopatra/soupault.org @@ -1,209 +1,136 @@ -#+BEGIN_EXPORT html -

soupault Configuration

-#+END_EXPORT +#+TITLE: ~soupault~ -#+NAME: build-dir -#+BEGIN_SRC text :exports none -build -#+END_SRC +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./theme.html +#+SERIES_NEXT: ./commands.html -#+NAME: prefix -#+BEGIN_SRC text :exports none -~lthms -#+END_SRC +We use ~soupault~ to build this website[fn::~soupault~ is an awesome +free software project, with a unique approach to static website +generation. You should definitely [[https://soupault.app][check out their website]]!]. + +#+begin_export html + +#+end_export -In a nutshell, the purpose of ~soupault~ is to post-process HTML files -generated by the generation processes of *~cleopatra~* +* Installation -The rest of this document proceeds as follows. We first describe the general -settings of ~soupault~. Then, we enumerate the widgets enabled for this website. -Finally, we provide a proper definition for ~soupault~ the *~cleopatra~* -generation process. + We install ~soupault~ in a local switch. We use a witness file + ~_opam/.init~ to determine whether or not our switch has always been + created during a previous invocation of *~cleopatra~*. -#+TOC: headlines 2 + #+begin_src makefile :tangle soupault.mk +OCAML_VERSION := 4.11.2 +OCAML := ocaml-base-compiler.${OCAML_VERSION} -* ~soupault~ General Settings +CONFIGURE += _opam rss.json +ARTIFACTS += out -The general ~settings~ section of ~soupault.conf~ is fairly basic, and there is -little to say that the -[[https://soupault.neocities.org/reference-manual/#getting-started][“Getting -Started”]] already discuss in length. +soupault-prebuild : _opam/init + #+end_src -We emphasize three things: + Using ~soupault~ is as simple as calling it, without any particular + command-line arguments. + + #+begin_src makefile :tangle soupault.mk +soupault-build : package-lock.json style.min.css + @cleopatra echo "Executing" "soupault" + @soupault + #+end_src -- The ~build_dir~ is set to src_text[:exports code :noweb yes]{<>/<>} - in place of simply src_text[:exports code :noweb yes]{<>}. -- The ~ignore_extensions~ shall be updated to take into account artifacts - produces by other *~cleopatra~* generation processes. -- We disable the “clean URLs” feature of ~soupault. This option renames - a HTML files ~foo/bar.html~ into ~foo/bar/index.html~, which means when served - by a HTTP server, the ~foo/bar~ URL will work. The issue we have with this - feature is that the internal links within your websiste needs to take their - /final/ URL into account, rather than their actual name. If one day ~soupault~ - starts rewriting internal URLs when ~clean_url~ is enabled, we might - reconsider using it. + We now describe our configuration file for ~soupault~. + +* Configuration + + #+name: base-dir + #+begin_src verbatim :noweb yes :exports none +~lthms + #+end_src -#+BEGIN_SRC toml :tangle soupault.conf :noweb yes +** Global Settings + + The options of the ~[settings]~ section of a ~soupault~ + configuration are often self-explanatory, and we do not spend too + much time to detaul them. + + #+begin_src toml :tangle soupault.conf :noweb yes [settings] strict = true -verbose = false -debug = false site_dir = "site" -build_dir = "<>/<>" - +build_dir = "out/<>" +doctype = "" +clean_urls = false +generator_mode = true +complete_page_selector = "html" +default_content_selector = "main" page_file_extensions = ["html"] ignore_extensions = [ - "draft", "vo", "vok", "vos", "glob", - "html~", "org", "aux", "sass", + "v", "vo", "vok", "vos", "glob", + "html~", "org" ] - -generator_mode = true -complete_page_selector = "html" default_template_file = "templates/main.html" -default_content_selector = "main" -doctype = "" -clean_urls = false -#+END_SRC - -#+BEGIN_TODO -The list of ignored extensions should be programmatically generated with the -help of *~cleopatra~*. -#+END_TODO - -* Widgets +pretty_print_html = false + #+end_src ** Setting Page Title -We use the “page title” widget to set the title of the webpage based on the -first (and hopefully the only) ~

~ tag of the page. + We use the “page title” widget to set the title of the webpage + based on the first (and hopefully the only) ~

~ tag of the + page. -#+BEGIN_SRC toml :tangle soupault.conf + #+begin_src toml :tangle soupault.conf [widgets.page-title] widget = "title" selector = "h1" default = "~lthms" prepend = "~lthms: " -#+END_SRC + #+end_src ** Acknowledging ~soupault~ -When creating a new ~soupault~ project (using ~soupault --init~), the default -configuration file suggests advertising the use of ~soupault~. Rather than -hard-coding the used version of ~soupault~ (which is error-prone), we rather -determine the version of ~soupault~ with the following script. + When creating a new ~soupault~ project (using ~soupault --init~), + the default configuration file suggests advertising the use of + ~soupault~. Rather than hard-coding the used version of ~soupault~ + (which is error-prone), we rather determine the version of + ~soupault~ with the following script. -#+NAME: soupault-version -#+BEGIN_SRC bash :results verbatim output + #+NAME: soupault-version + #+begin_src bash :results verbatim output soupault --version | head -n 1 | tr -d '\n' -#+END_SRC + #+end_src -The configuration of the widget ---initially provided by ~soupault~--- becomes -less subject to the obsolescence. + The configuration of the widget ---initially provided by + ~soupault~--- becomes less subject to the obsolescence[fn::That + is, as long as ~soupault~ does not change the output of its + ~--version~ option.]. -#+BEGIN_SRC toml :tangle soupault.conf :noweb yes + #+begin_src toml :tangle soupault.conf :noweb yes [widgets.generator-meta] widget = "insert_html" html = """""" selector = "head" -#+END_SRC - -** Generating Table of Contents - -The ~toc~ widget allows for generating a table of contents for HTML files which -contains a node matching a given ~selector~ (in the case of this document, -~#generate-toc~). - -#+BEGIN_SRC toml :tangle soupault.conf -[widgets.table-of-contents] -widget = "toc" -selector = "#generate-toc" -action = "replace_element" -valid_html = true -min_level = 2 -numbered_list = true -#+END_SRC - -#+BEGIN_TODO -We could propose a patch to ~soupault~'s upstream to add numbering in titles. -#+END_TODO - -** Fixing Org Internal Links - -For some reason, Org prefix internal links to other Org documents with -~file://~. To avoid that, we provide a simple plugin which removes ~file://~ -from the begining of a URL. - -#+BEGIN_TODO -This plugin definition should be part of [[./Contents/Org.org][the ~org~ -generation process]], but that would require to aggregate “subconfig” into a -larger one. -#+END_TODO - -This plugin key component is the =fix_org_urls= function. - -- =fix_org_urls(LIST, ATTR)= :: - Enumerate the DOM elements of =LIST=, and check their =ATTR= attribute. - -#+BEGIN_SRC lua :tangle plugins/fix-org-urls.lua -function fix_org_urls(list, attr) - index, link = next(list) - - while index do - href = HTML.get_attribute(link, attr) - - if href then - href = Regex.replace(href, "^file://", "") - HTML.set_attribute(link, attr, href) - end - - index, link = next(list, index) - end -end -#+END_SRC - -We use this function to fix the URLs of tags known to be subject to Org strange -behavior. For now, only ~~ has been affected. - -#+BEGIN_SRC lua :tangle plugins/fix-org-urls.lua -fix_org_urls(HTML.select(page, "a"), "href") -fix_org_urls(HTML.select(page, "img"), "src") -#+END_SRC - -The configuration of this plugin, and the associated widget, is straightforward. - -#+BEGIN_SRC toml :tangle soupault.conf :noweb tangle -[widgets.fix-org-urls] -widget = "fix-org-urls" -#+END_SRC + #+end_src ** Prefixing Internal URLs -On the one hand, internal links can be absolute, meaning they start with a -leading ~/~, and therefore are relative to the website root. On the other hand, -website (especially static website) can be placed in larger context. For -instance, my personal website lives inside the ~~lthms~ directory of the -~soap.coffee~ domain. + On the one hand, internal links can be absolute, meaning they + start with a leading ~/~, and therefore are relative to the + website root. On the other hand, website (especially static + website) can be placed in larger context. For instance, my + personal website lives inside the ~~lthms~ directory of the + ~soap.coffee~ domain[fn::To my experience in hosting webapps and + websites, this set-up is way harder to get right than I initially + expect.]. -The purpose of this plugin is to rewrite internal URLs which are relative to the -root, in order to properly prefix them. + The purpose of this plugin is to rewrite internal URLs which are relative to the + root, in order to properly prefix them. -From a high-level perspective, the plugin structure is the following. + From a high-level perspective, the plugin structure is the following. -#+BEGIN_SRC lua :tangle plugins/urls-rewriting.lua :noweb no-export -prefix_url = config["prefix_url"] -<> + First, we validate the widget configuration. -<> -<> -#+END_SRC - -1. We validate the widget configuration. -2. We propose a generic function to enumerate and rewrite tags which can have - internal URLs as attribute argument. -3. We use this generic function for relevant tags. + #+BEGIN_SRC lua :tangle plugins/urls-rewriting.lua +prefix_url = config["prefix_url"] -#+NAME: validate_prefix -#+BEGIN_SRC lua if not prefix_url then Plugin.fail("Missing mandatory field: `prefix_url'") end @@ -215,10 +142,12 @@ end if not Regex.match(prefix_url, "(.*)/$") then prefix_url = prefix_url .. "/" end -#+END_SRC + #+END_SRC + + Then, we propose a generic function to enumerate and rewrite tags + which can have. -#+NAME: prefix_func -#+BEGIN_SRC lua + #+BEGIN_SRC lua :tangle plugins/urls-rewriting.lua function prefix_urls (links, attr, prefix_url) index, link = next(links) @@ -236,33 +165,35 @@ function prefix_urls (links, attr, prefix_url) index, link = next(links, index) end end -#+END_SRC + #+END_SRC -#+NAME: prefix_calls -#+BEGIN_SRC lua + Finally, we use this generic function for relevant tags. + + #+BEGIN_SRC lua :tangle plugins/urls-rewriting.lua prefix_urls(HTML.select(page, "a"), "href", prefix_url) prefix_urls(HTML.select(page, "link"), "href", prefix_url) prefix_urls(HTML.select(page, "img"), "src", prefix_url) prefix_urls(HTML.select(page, "script"), "src", prefix_url) -#+END_SRC +prefix_urls(HTML.select(page, "use"), "href", prefix_url) + #+END_SRC -Again, configuring soupault to use this plugin is relatively straightforward. -The only important thing to notice is the use of the ~after~ field, to ensure -this plugin is run /after/ the plugin responsible for fixing Org documents URLs. + Again, configuring soupault to use this plugin is relatively + straightforward. -#+BEGIN_SRC toml :tangle soupault.conf :noweb tangle + #+BEGIN_SRC toml :tangle soupault.conf :noweb yes [widgets.urls-rewriting] widget = "urls-rewriting" -prefix_url = "<>" -after = "fix-org-urls" -#+END_SRC +prefix_url = "<>" +after = "mark-external-urls" + #+END_SRC ** Marking External Links -#+BEGIN_SRC lua :tangle plugins/external-urls.lua + #+BEGIN_SRC lua :tangle plugins/external-urls.lua function mark(name) - return '' + return '' end links = HTML.select(page, "a") @@ -274,85 +205,101 @@ while index do if href then if Regex.match(href, "^https?://github.com") then - icon = HTML.parse(mark('github')) + icon = HTML.parse(mark("github")) HTML.append_child(link, icon) elseif Regex.match(href, "^https?://") then - icon = HTML.parse(mark('external-link')) + icon = HTML.parse(mark("external-link")) HTML.append_child(link, icon) end end index, link = next(links, index) end -#+END_SRC - -#+BEGIN_SRC sass :tangle site/style/plugins.sass -.url-mark.fa - display: inline - font-size: 90% - width: 1em - -.url-mark.fa-github::before - content: "\00a0\f09b" + #+END_SRC -.url-mark.fa-external-link::before - content: "\00a0\f08e" -#+END_SRC - -#+BEGIN_SRC toml :tangle soupault.conf + #+BEGIN_SRC toml :tangle soupault.conf [widgets.mark-external-urls] after = "generate-history" widget = "external-urls" -#+END_SRC + #+END_SRC + +** Generating a Table of Contents + + The ~toc~ widget allows for generating a table of contents for + HTML files which contains a node matching a given ~selector~ (in + the case of this document, ~#generate-toc~). + + #+begin_src toml :tangle soupault.conf +[widgets.table-of-contents] +widget = "toc" +selector = "#generate-toc" +action = "replace_content" +valid_html = true +min_level = 2 +max_level = 3 +numbered_list = false +heading_links = true +heading_link_text = " §" +heading_links_append = true +heading_link_class = "anchor-link" + +[widgets.append-toc-title] +widget = "preprocess_element" +selector = "#generate-toc" +command = 'echo "

Table of Contents

$(cat)"' +after = "table-of-contents" + #+end_src ** Generating Per-File Revisions Tables *** Users Instructions -This widgets allows to generate a so-called “revisions table” of the filename -contained in a DOM element of id ~history~, based on its history. Paths should -be relative to the directory from which you start the build process (typically, -the root of your repository). The revisions table notably provides hyperlinks to -a ~git~ webview for each commit. + This widgets allows to generate a so-called “revisions table” of + the filename contained in a DOM element of id ~history~, based on + its history. Paths should be relative to the directory from which + you start the build process (typically, the root of your + repository). The revisions table notably provides hyperlinks to a + ~git~ webview for each commit. -For instance, considering the following HTML snippet + For instance, considering the following HTML snippet -#+BEGIN_SRC html + #+begin_src html
site/posts/FooBar.org
-#+END_SRC + #+end_src -This plugin will replace the content of this ~
~ with the revisions table of -~site/posts/FooBar.org~. + This plugin will replace the content of this ~
~ with the + revisions table of ~site/posts/FooBar.org~. *** Customization -The base of the URL webview for the document you are currently reading -—afterwards abstracted with the ~<>~ noweb reference— is + The base of the URL webview for the document you are currently + reading is src_verbatim[:noweb yes :exports code]{<>}. -#+NAME: repo -#+BEGIN_SRC text + #+name: repo + #+begin_src verbatim :exports none https://code.soap.coffee/writing/lthms.git -#+END_SRC + #+end_src -#+BEGIN_SRC html :tangle templates/history.html :noweb tangle -
+ The template used to generate the revision table is the following. + + #+begin_src html :tangle templates/history.html :noweb yes +
Revisions

This revisions table has been automatically generated - from the git history - of this website repository, and the change - descriptions may not always be as useful as they - should. + from the + git history of this website repository, and the + change descriptions may not always be as useful as they should.

- You can consult the source of this file in its current - version here. + You can consult the source of this file in its current version + here.

- +
{{#history}} + >{{date}} {{/history}}
- {{date}} - {{subject}} - - {{abbr_hash}} - + {{abbr_hash}}
-#+END_SRC - -#+BEGIN_SRC sass :tangle site/style/plugins.sass -table - border-top : 2px solid black - border-bottom : 2px solid black - border-collapse : collapse - width : 35rem - -td - border-bottom : 1px solid black - padding : .5em - -#history .commit - font-size : smaller - font-family : 'Fira Code', monospace - width : 7em - text-align : center -#+END_SRC + #+end_src *** Implementation -We use the built-in [[https://soupault.neocities.org/reference-manual/#widgets-preprocess-element][=preprocess_element=]] to implement, which means we need a -script which gets its input from the standard input, and echoes its output to -the standard input. + We use the built-in [[https://soupault.neocities.org/reference-manual/#widgets-preprocess-element][=preprocess_element=]] to implement, which + means we need a script which gets its input from the standard + input, and echoes its output to the standard input. -#+BEGIN_SRC toml :tangle soupault.conf + #+begin_src toml :tangle soupault.conf [widgets.generate-history] widget = "preprocess_element" selector = "#history" command = 'scripts/history.sh templates/history.html' -action = "replace_content" -#+END_SRC +action = "replace_element" + #+end_src -This plugin proceeds as follows: + This plugin proceeds as follows: -1. Using an ad-hoc script, it generates a JSON containing for each revision - - The subject, date, hash, and abbreviated hash of the related commit - - The name of the file at the time of this commit -2. This JSON is passed to a mustache engine (~haskell-mustache~) with a - proper template -3. The content of the selected DOM element is replaced with the output of - ~haskell-mustache~ + 1. Using an ad-hoc script, it generates a JSON containing for each revision + - The subject, date, hash, and abbreviated hash of the related commit + - The name of the file at the time of this commit + 2. This JSON is passed to a mustache engine (~haskell-mustache~) with a + proper template + 3. The content of the selected DOM element is replaced with the output of + ~haskell-mustache~ -This translates in Bash like this. + This translates in Bash like this. -#+BEGIN_SRC bash :tangle scripts/history.sh :shebang "#!/usr/bin/bash" + #+begin_src bash :tangle scripts/history.sh :shebang "#!/usr/bin/bash" function main () { local file="${1}" local template="${2}" @@ -431,26 +356,27 @@ function main () { haskell-mustache ${template} ${tmp_file} rm ${tmp_file} } -#+END_SRC - -Generating the expected JSON is therefore as simple as: - -- Fetching the logs -- Reading 8 line from the logs, parse the filename from the 6th - line -- Outputing the JSON - -We will use ~git~ to get the information we need. By default, ~git~ -subcommands use a pager when its output is likely to be long. This -typically includes ~git-log~. To disable this behavior, ~git~ exposes -the ~--no-pager~ command. Besides, we also need ~--follow~ and -~--stat~ to deal with file renaming. Without this option, ~git-log~ -stops when the file first appears in the repository, even if this -“creation” is actually a renaming. Therefore, the ~git~ command line -we use to collect our history is - -#+NAME: gitlog -#+BEGIN_SRC bash :tangle scripts/history.sh :noweb yes + #+end_src + + Generating the expected JSON is therefore as simple as: + + - Fetching the logs + - Reading 8 line from the logs, parse the filename from the 6th + line + - Outputing the JSON + + We will use ~git~ to get the information we need. By default, + ~git~ subcommands use a pager when its output is likely to be + long. This typically includes ~git-log~. To disable this + behavior, ~git~ exposes the ~--no-pager~ command. Besides, we + also need ~--follow~ and ~--stat~ to deal with file + renaming. Without this option, ~git-log~ stops when the file + first appears in the repository, even if this “creation” is + actually a renaming. Therefore, the ~git~ command line we use to + collect our history is + + #+name: gitlog + #+begin_src bash :tangle scripts/history.sh :noweb yes function gitlog () { local file="${1}" git --no-pager log \ @@ -459,33 +385,35 @@ function gitlog () { --pretty=format:'%s%n%h%n%H%n%cs%n' \ "${file}" } -#+END_SRC + #+end_src -This function will generate a sequence of 8 lines containing all the -relevant information we are looking for, for each commit, namely: + This function will generate a sequence of 8 lines containing all + the relevant information we are looking for, for each commit, + namely: -- Subject -- Abbreviated hash -- Full hash -- Date -- Empty line -- Change summary -- Shortlog -- Empty line + - Subject + - Abbreviated hash + - Full hash + - Date + - Empty line + - Change summary + - Shortlog + - Empty line -For instance, the =gitlog= function will output the following lines -for the last commit of this very file: + For instance, the =gitlog= function will output the following + lines for the last commit of this very file: -#+BEGIN_SRC bash :results verbatim :exports results :noweb yes + #+begin_src bash :results verbatim :exports results :noweb yes <> gitlog "soupault.org" | head -n8 -#+END_SRC + #+end_src -Among other things, the 6th line contains the filename. We need to -extract it, and we do that with ~sed~. In case of file renaming, we -need to parse something of the form ~both/to/{old => new}~. + Among other things, the 6th line contains the filename. We need + to extract it, and we do that with ~sed~. In case of file + renaming, we need to parse something of the form ~both/to/{old => + new}~. -#+BEGIN_SRC bash :tangle scripts/history.sh :noweb yes + #+begin_src bash :tangle scripts/history.sh :noweb yes function parse_filename () { local line="${1}" local shrink='s/ *\(.*\) \+|.*/\1/' @@ -493,18 +421,18 @@ function parse_filename () { echo ${line} | sed -e "${shrink}" | sed -e "${unfold}" } -#+END_SRC - -The next step is to process the logs to generate the expected JSON. We -have to deal with the fact that JSON does not allow the last item of -an array to be concluded by ",". Besides, we also want to indicate -which commit is responsible for the creation of the file. To do that, -we use two variables: =idx= and =last_entry=. When =idx= is equal to -0, we know it is the latest commit. When =idx= is equal to -=last_entry=, we know we are looking at the oldest commit for that -file. - -#+BEGIN_SRC bash :tangle scripts/history.sh :noweb yes + #+end_src + + The next step is to process the logs to generate the expected + JSON. We have to deal with the fact that JSON does not allow the + last item of an array to be concluded by ",". Besides, we also + want to indicate which commit is responsible for the creation of + the file. To do that, we use two variables: =idx= and + =last_entry=. When =idx= is equal to 0, we know it is the latest + commit. When =idx= is equal to =last_entry=, we know we are + looking at the oldest commit for that file. + + #+begin_src bash :tangle scripts/history.sh :noweb yes function generate_json () { local input="${1}" local logs="$(gitlog ${input})" @@ -562,11 +490,11 @@ function generate_json () { echo -n "]}" } -#+END_SRC + #+end_src -Generating the JSON object for a given commit is as simple as + Generating the JSON object for a given commit is as simple as -#+BEGIN_SRC bash :tangle scripts/history.sh :noweb yes + #+begin_src bash :tangle scripts/history.sh :noweb yes function output_json_entry () { local subject="${1}" local abbr_hash="${2}" @@ -585,66 +513,31 @@ function output_json_entry () { echo -n ",\"filename\":\"${file}\"" echo -n "}" } -#+END_SRC + #+end_src -And we are done! We can safely call the =main= function to generate -our revisions table. + And we are done! We can safely call the =main= function to generate + our revisions table. -#+BEGIN_SRC bash :tangle scripts/history.sh + #+begin_src bash :tangle scripts/history.sh main "$(cat)" "${1}" -#+END_SRC + #+end_src ** Rendering Equations Offline *** Users instructions -Inline equations written in the DOM under the class src_css{.imath} and using -the \im \LaTeX \mi syntax can be rendered once and -for all by ~soupault~. User For instance, ~\LaTeX~ is -rendered \im \LaTeX \mi as expected. + Inline equations written in the DOM under the class + src_css{.imath} and using the \im \LaTeX \mi syntax can be + rendered once and for all by ~soupault~. User For instance, + ~\LaTeX~ is rendered \im \LaTeX \mi as + expected. -Using this widgets requires being able to inject raw HTML in input files. + Using this widgets requires being able to inject raw HTML in + input files. *** Implementation -We will use [[https://katex.org][\im \KaTeX \mi]] to render equations offline. \im \KaTeX \mi -availability on most systems is unlikely, but it is part of [[https://www.npmjs.com/package/katex][npm]], so we can -define a minimal ~package.json~ file to fetch it automatically. - -#+BEGIN_SRC json :tangle package.json -{ - "private": true, - "devDependencies": { - "katex": "^0.11.1" - } -} -#+END_SRC - -We introduce a Makefile recipe to call ~npm install~. This command produces a -file called ~package-lock.json~ that we add to ~GENFILES~ to ensure \im \KaTeX -\mi will be available when ~soupault~ is called. - -If ~Soupault.org~ has been modified since the last generation, Babel will -generate ~package.json~ again. However, if the modifications of ~Soupault.org~ -do not concern ~package.json~, then ~npm install~ will not modify -~package-lock.json~ and its “last modified” time will not be updated. This means -that the next time ~make~ will be used, it will replay this recipe again. As a -consequence, we systematically ~touch~ ~packase-lock.json~ to satisfy ~make~. - -#+BEGIN_SRC makefile :tangle katex.mk -package-lock.json : package.json - @cleopatra echo "Fetching" "npm packages" - @npm install &>> build.log - @touch $@ - -CONFIGURE += package-lock.json node_modules/ -#+END_SRC - -Once installed and available, \im \KaTeX \mi is really simple to use. The -following script reads (synchronously!) the standard input, renders it using \im -\KaTeX \mi and outputs the resut to the standard output. - -#+BEGIN_SRC js :tangle scripts/katex.js + #+begin_src js :tangle scripts/render-equations.js var katex = require("katex"); var fs = require("fs"); var input = fs.readFileSync(0); @@ -656,102 +549,160 @@ var html = katex.renderToString(String.raw`${input}`, { }); console.log(html) -#+END_SRC + #+end_src -We reuse once again the =preprocess_element= widget. The selector is ~.imath~ -(~i~ stands for inline in this context), and we replace the previous content -with the result of our script. + We reuse once again the =preprocess_element= widget. The selector + is ~.imath~ (~i~ stands for inline in this context), and we + replace the previous content with the result of our script. -#+BEGIN_SRC toml :tangle soupault.conf + #+begin_src toml :tangle soupault.conf [widgets.inline-math] widget = "preprocess_element" selector = ".imath" -command = "node scripts/katex.js" +command = "node scripts/render-equations.js" action = "replace_content" [widgets.display-math] widget = "preprocess_element" selector = ".dmath" -command = "DISPLAY=1 node scripts/katex.js" +command = "DISPLAY=1 node scripts/render-equations.js" action = "replace_content" -#+END_SRC + #+end_src + +** RSS Feed + + #+begin_src toml :tangle soupault.conf +[index] +index = true +dump_json = "rss.json" +extract_after_widgets = ["urls-rewriting"] + +[index.fields] +title = { + selector = ["h1"] +} -The \im\KaTeX\mi font is bigger than the serif font used for this -website, so we reduce it a bit with a dedicated SASS rule. +modified-at = { + selector = ["#modified-at"] +} -#+BEGIN_SRC sass :tangle site/style/plugins.sass -.imath, .dmath - font-size : smaller +created-at = { + selector = ["#created-at"] +} + #+end_src -.dmath - text-align : center -#+END_SRC +** Series Navigation -* *~cleopatra~* Generation Process Definition + #+begin_src lua :tangle plugins/series.lua +function get_title_from_path (path) + if Sys.is_file(path) then + local content_raw = Sys.read_file(path) + local content_dom = HTML.parse(content_raw) + local title = HTML.select_one(content_dom, "h1") -We introduce the ~soupault~ generation process, obviously based on the -[[https://soupault.neocities.org/][~soupault~ HTML processor]]. The structure of -a *~cleopatra~* generation process is always the same. + if title then + return String.trim(HTML.inner_html(title)) + else + Plugin.fail(path .. ' has no

tag') + end + else + Plugin.fail(path .. ' is not a file') + end +end + #+end_src + + #+begin_src lua :tangle plugins/series.lua +function generate_nav_item_from_title (title, url, template) + local env = {} + env["url"] = url + env["title"] = title + local new_content = String.render_template(template, env) + return HTML.parse(new_content) +end + #+end_src -#+BEGIN_SRC makefile :tangle soupault.mk :noweb no-export -<> -<> -<> -#+END_SRC + #+begin_src lua :tangle plugins/series.lua +function generate_nav_items (cwd, cls, template) + local elements = HTML.select(page, cls) -In the rest of this section, we define these three components. + local i = 1 + while elements[i] do + local element = elements[i] + local url = HTML.strip_tags(element) + local path = Sys.join_path(cwd, url) + local title_str = get_title_from_path(path) -** Build Stages + HTML.replace_content( + element, + generate_nav_item_from_title(title_str, url, template) + ) -From the perspective of *~cleopatra~*, it is a rather simple component, since -the ~build~ stage is simply a call to ~soupault~, whose outputs are located in a -single (configurable) directory. + i = i + 1 + end +end + #+end_src -#+NAME: stages -#+BEGIN_SRC makefile :noweb yes -soupault-build : - @cleopatra echo Running soupault - @soupault + #+begin_src lua :tangle plugins/series.lua +cwd = Sys.dirname(page_file) -ARTIFACTS += <>/ -#+END_SRC +home_template = 'This article is part of the series “{{ title }}.”' +nav_template = '{{ title }}' -** Dependencies +generate_nav_items(cwd, ".series", home_template) +generate_nav_items(cwd, ".series-prev", nav_template) +generate_nav_items(cwd, ".series-next", nav_template) + #+end_src -Most of the generation processes (if not all of them) need to declare themselves -as a prerequisite for ~soupault-build~. If they do not, they will likely be -executed after ~soupault~ is called. +#+begin_src toml :tangle soupault.conf +[widgets.series] +widget = "series" +#+end_src -This file defines an auxiliary SASS sheet that needs to be declared as a -dependency of the build stage of the [[./Theme.org][~theme~ generation -process]]. +** Injecting Minified CSS -Finally, the offline rendering of equations requires \im \KaTeX \mi to be -available, so we include the ~katex.mk~ file, and make ~package-lock.json~ (the -proof that ~npm install~ has been executed) a prerequisite of ~soupault-build~. + #+begin_src lua :tangle plugins/css.lua +style = HTML.select_one(page, "style") -#+NAME: dependencies -#+BEGIN_SRC makefile -theme-build : site/style/plugins.sass -include katex.mk -soupault-build : package-lock.json -#+END_SRC +if style then + css = HTML.create_text(Sys.read_file("style.min.css")) + HTML.replace_content(style, css) +end + #+end_src -** Ad-hoc Commands + #+begin_src toml :tangle soupault.conf +[widgets.css] +widget = "css" + #+end_src -Finally, this generation process introduces a dedicated (~PHONY~) command to -start a HTTP server in order to navigate the generated website from a browser. +** Cleaning-up -#+NAME: ad-hoc-cmds -#+BEGIN_SRC makefile :noweb yes -serve : - @echo " start a python server" - @cd <>; python -m http.server 2>/dev/null + #+begin_src lua :tangle plugins/clean-up.lua +function remove_if_empty(html) + if String.trim(HTML.inner_html(html)) == "" then + HTML.delete(html) + end +end + #+end_src + + #+begin_src lua :tangle plugins/clean-up.lua +function remove_all_if_empty(cls) + local elements = HTML.select(page, cls) + + local i = 1 + while elements[i] do + local element = elements[i] + remove_if_empty(element) + i = i + 1 + end +end + #+end_src -.PHONY : serve -#+END_SRC + #+begin_src lua :tangle plugins/clean-up.lua +remove_all_if_empty("p") -- introduced by org-mode +remove_all_if_empty("div.code") -- introduced by coqdoc + #+end_src -This command does not assume anything about the current state of generation of -the project. In particular, it does not check whether or not the ~<>~ -directory exists. The responsibility to use ~make serve~ in a good setting lies -with final users. +#+begin_src toml :tangle soupault.conf +[widgets.clean-up] +widget = "clean-up" +#+end_src diff --git a/site/cleopatra/theme.org b/site/cleopatra/theme.org index dce9520..9041be8 100644 --- a/site/cleopatra/theme.org +++ b/site/cleopatra/theme.org @@ -1,267 +1,471 @@ -#+BEGIN_EXPORT html -

Theming and Templating

-#+END_EXPORT +#+TITLE: Layout and Style -The purpose of this build process is to implement the default layout of this -website. To that end, it provides a template file (~main.html~), and a -collection of SASS files that *~cleopatra~* then compiles into a single CSS file -using ~sassc~. +#+SERIES: ../cleopatra.html +#+SERIES_PREV: ./literate-programming.html +#+SERIES_NEXT: ./soupault.html -We first discuss the structure of the website, by defining the default HTML -template =soupault= will use to generate the website. Then, we specify its -minimal design, implemented in SASS. Finally, we discuss the necessary build -instructions for *~cleopatra~*. +#+BEGIN_EXPORT html + +
site/cleopatra/theme.org
+#+END_EXPORT -* Main HTML Template +* Setup + + As often when it comes to frontend development, we will use several + tools hosted in the ~npm~ packages repository. ~npm~ is infamous + for downloading lots of files and to store it in the ~node_modules/~ + directory. We configure *~cleopatra~* accordingly. + + #+begin_src makefile :tangle theme.mk +CONFIGURE += package.json package-lock.json node_modules + #+end_src + +* Base CSS + + We know construct piece by piece the “base” CSS layout which we will + inject inside a ~ + + - <> + + +
+
+ -#+END_SRC - -** ~~ - -#+NAME: meta-tags -#+BEGIN_SRC html :noweb no-export - - -#+END_SRC - -*** Assets Loading - -#+NAME: syncloading_html -#+BEGIN_SRC html - - - -#+END_SRC - -#+NAME: asyncloading_js -#+BEGIN_SRC js -let noscript = document.getElementById('asyncloading'); -noscript.insertAdjacentHTML('beforebegin', noscript.innerText); -noscript.parentNode.removeChild(noscript); -#+END_SRC - -#+NAME: asyncloading_html -#+BEGIN_SRC html - -#+END_SRC - -** ~body~ - -#+NAME: body -#+BEGIN_SRC html :noweb no-export - -
- Technical Articles / - Opinions / - News / - Projects -
-
- -
- - - -#+END_SRC - -* Main SASS File - -First, we introduce a set of variables. - -#+BEGIN_SRC sass :tangle site/style/main.sass -$content-width : 30rem -$large-side-margin : 7rem -$small-side-margin : 2rem -$monospace-color : #FF006D -#+END_SRC - -Then, we introduce a key CSS variable whose definition will change according to -the current width of the page (something we cannot achieve with SASS variables, -whose behavior is purely static). - -#+BEGIN_SRC sass :tangle site/style/main.sass -\:root - @media screen and (min-width: calc(#{$content-width} + 2 * #{$large-side-margin})) - --side-margin : #{$large-side-margin} - @media screen and (max-width: calc(#{$content-width} + 2 * #{$large-side-margin})) - --side-margin : #{$small-side-margin} -#+END_SRC - -Then, we style! - -#+BEGIN_SRC sass :tangle site/style/main.sass -* - box-sizing : border-box - -html - width : 100% - height : 100% - font-size : 100% - font-weight : normal - color : #222 - -a - color : black - -a:visited - color : #222 - -body - font-family : serif - margin : 0 var(--side-margin) 0 calc(var(--side-margin) - 2rem) !important - padding : 2rem - @media screen and (min-width: calc(#{$content-width} + 2 * #{$large-side-margin})) - border-left : 1px solid #ccc - -main p, -main h1, -main h2, -main h3, -main h4, -main h5, -main h6, -main ul, -main dl, -main ol, -header, -footer - max-width : $content-width - line-height : 140% - -main h1, -main h2, -main h3, -main h4, -main h5, -main h6 - font-weight : bold - color : #0c0016 - -header a, -footer p - font-size : 90% - -main - padding-top : 4rem - padding-bottom : 4rem - - dl dd - margin-left : 0 - - dl dt - font-weight : bold - - dl dt:not(:first-child) - padding-top : .5rem - - details - font-size : 90% - filter : opacity(0.8) - -footer img - border-radius : 100% - max-width : 7rem - float : right - margin-left : 1rem - margin-bottom : 1rem - -pre - padding-left : 1.5rem - padding-right : 1.5rem - overflow-x : auto - -code, -tt, -pre - font-family : 'Fira Code', monospace - font-size : 80% - line-height : 140% - color : $monospace-color - -#gallery - display : flex - flex-wrap : wrap - align-content : flex-start - - img - max-width : 20rem - -@import plugins -@import org -@import coq -#+END_SRC - -* Build Instructions - -The build instruction are pretty straightforward. We start by how to compile the -main CSS file. - -#+BEGIN_SRC makefile :tangle theme.mk -SASS := $(wildcard site/style/*.sass) -MAIN_SASS := site/style/main.sass -CSS := $(MAIN_SASS:.sass=.css) - -${CSS} : ${SASS} - @cleopatra echo Compiling "${CSS}" - @sassc --style=compressed --sass ${MAIN_SASS} ${CSS} -#+END_SRC - -Since the HTML template does not need any particular processing, the -=theme-build= phase is only responsible for generating the main CSS file. The -[[./soupault.org][=soupault= build phase]] needs to start after the CSS file is -compiled (since it copies all relevant files to the ~build/~ directory), so we -explicit this dependency. - -#+BEGIN_SRC makefile :tangle theme.mk -theme-build : ${CSS} -soupault-build : theme-build -#+END_SRC - -Therefore, at the end of this generation process only one file has been -generated. - -#+BEGIN_SRC makefile :tangle theme.mk -ARTIFACTS += ${CSS} -#+END_SRC + #+end_src diff --git a/site/coq.org b/site/coq.org new file mode 100644 index 0000000..d13d387 --- /dev/null +++ b/site/coq.org @@ -0,0 +1,44 @@ +#+SERIES: ./index.html +#+SERIES_NEXT: haskell.html + +#+TITLE: About Coq + +Coq is a formal proof management system which provides a pure +functional language with nice dependent types together with an +environment for writing machine-checked proofs. + +- [[./posts/StronglySpecifiedFunctions.org][A Series on Strongly-Specified Funcions in Coq]] :: + Using dependent types and the ~Prop~ sort, it becomes possible to specify + functions whose arguments and results are constrained by properties. + Using such a “strongly-specified” function requires to provide a proof that + the supplied arguments satisfy the expected properties, and allows for soundly + assuming the results are correct too. However, implementing dependently-typed + functions can be challenging. + +- [[./posts/Ltac.org][A Series on Ltac]] :: + Ltac is the “tactic language” of Coq. It is commonly advertised as the common + approach to write proofs, which tends to bias how it is introduced to new Coq + users (/e.g./, in Master courses). In this series, we present Ltac as the + metaprogramming tool it is, since fundamentally it is an imperative language + which allows for constructing Coq terms interactively and incrementally. + +- [[./posts/RewritingInCoq.html][Rewriting in Coq]] :: + The ~rewrite~ tactics are really useful, since they are not limited to the Coq + built-in equality relation. + +- [[./posts/ClightIntroduction.html][A Study of Clight and its Semantics]] :: + Clight is a “simplified” C AST used by CompCert, the certified C compiler. In + this write-up, we prove a straighforward functional property of a small C + function, as an exercise to discover the Clight semantics. + +- [[./posts/AlgebraicDatatypes.html][Proving Algebraic Datatypes are “Algebraic”]] :: + The set of types which can be defined in a language together with ~+~ and ~*~ + form an “algebraic structure” in the mathematical sense, hence the name. It + means the definitions of ~+~ and ~*~ have to satisfy properties such as + commutativity or the existence of neutral elements. + +- [[./posts/Coqffi.org][A Series on ~coqffi~]] :: + ~coqffi~ generates Coq FFI modules from compiled OCaml interface + modules (~.cmi~). In practice, it greatly reduces the hassle to + together OCaml and Coq modules within the same codebase, especially + when used together with the ~dune~ build system. diff --git a/site/haskell.org b/site/haskell.org new file mode 100644 index 0000000..c18fbb7 --- /dev/null +++ b/site/haskell.org @@ -0,0 +1,13 @@ +#+SERIES: index.html +#+SERIES_PREV: coq.html +#+SERIES_NEXT: miscellaneous.html + +#+TITLE: About Haskell + +Haskell is a pure, lazy, functional programming language with a very +expressive type system. + +- [[./posts/ExtensibleTypeSafeErrorHandling.html][Extensible, Type-Safe Error Handling In Haskell]] :: + Ever heard of “extensible effects?” By applying the same principle, but for + error handling, the result is nice, type-safe API for Haskell, with a lot of + GHC magic under the hood. diff --git a/site/img/icons.svg b/site/img/icons.svg new file mode 100644 index 0000000..917a417 --- /dev/null +++ b/site/img/icons.svg @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/site/img/merida.webp b/site/img/merida.webp deleted file mode 100644 index c0e6354..0000000 Binary files a/site/img/merida.webp and /dev/null differ diff --git a/site/index.org b/site/index.org index e1b61bc..e4a7e18 100644 --- a/site/index.org +++ b/site/index.org @@ -1,76 +1,27 @@ -#+OPTIONS: toc:nil num:nil - -#+BEGIN_EXPORT html -

Technical Articles

-#+END_EXPORT +#+TITLE: Technical Articles Over the past years, I have tried to capitalize on my findings. What I have lacked in regularity I made up for in subject exoticism. -If you like what you read, have a question or for any other reasons really, you -can shoot an [[mailto:lthms@soap.coffee][email]], or start a discussion on -whichever site you like (I personnaly enjoy -[[https://lobste.rs/search?q=domain%3Asoap.coffee&what=stories&order=relevance][Lobste.rs]] -very much). +If you like what you read, have a question or for any other reasons +really, you can shoot an [[mailto:lthms@soap.coffee][email]], or start a discussion on whichever +site you like[fn::I personnaly enjoy [[https://lobste.rs/search?q=domain%3Asoap.coffee&what=stories&order=relevance][Lobste.rs]] very much]. * About Coq -:PROPERTIES: -:CUSTOM_ID: coq -:END: - -Coq is a formal proof management system which provides a pure functional -language with nice dependent types together with an environment for writing -machine-checked proofs. - -- [[./posts/StronglySpecifiedFunctions.org][A Series on Strongly-Specified Funcions in Coq]] :: - Using dependent types and the ~Prop~ sort, it becomes possible to specify - functions whose arguments and results are constrained by properties. - Using such a “strongly-specified” function requires to provide a proof that - the supplied arguments satisfy the expected properties, and allows for soundly - assuming the results are correct too. However, implementing dependently-typed - functions can be challenging. - -- [[./posts/Ltac.org][A Series on Ltac]] :: - Ltac is the “tactic language” of Coq. It is commonly advertised as the common - approach to write proofs, which tends to bias how it is introduced to new Coq - users (/e.g./, in Master courses). In this series, we present Ltac as the - metaprogramming tool it is, since fundamentally it is an imperative language - which allows for constructing Coq terms interactively and incrementally. - -- [[./posts/RewritingInCoq.html][Rewriting in Coq]] :: - The ~rewrite~ tactics are really useful, since they are not limited to the Coq - built-in equality relation. + :PROPERTIES: + :CUSTOM_ID: coq + :END: -- [[./posts/ClightIntroduction.html][A Study of Clight and its Semantics]] :: - Clight is a “simplified” C AST used by CompCert, the certified C compiler. In - this write-up, we prove a straighforward functional property of a small C - function, as an exercise to discover the Clight semantics. - -- [[./posts/AlgebraicDatatypes.html][Proving Algebraic Datatypes are “Algebraic”]] :: - The set of types which can be defined in a language together with ~+~ and ~*~ - form an “algebraic structure” in the mathematical sense, hence the name. It - means the definitions of ~+~ and ~*~ have to satisfy properties such as - commutativity or the existence of neutral elements. - -- [[./posts/Coqffi.org][A Series on ~coqffi~]] :: - ~coqffi~ generates Coq FFI modules from compiled OCaml interface - modules (~.cmi~). In practice, it greatly reduces the hassle to - together OCaml and Coq modules within the same codebase, especially - when used together with the ~dune~ build system. + #+include: ./coq.org * About Haskell -Haskell is a pure, lazy, functional programming language with a very expressive -type system. - -- [[./posts/ExtensibleTypeSafeErrorHandling.html][Extensible, Type-Safe Error Handling In Haskell]] :: - Ever heard of “extensible effects?” By applying the same principle, but for - error handling, the result is nice, type-safe API for Haskell, with a lot of - GHC magic under the hood. + #+include: ./haskell.org * Miscellaneous -- [[./posts/DiscoveringCommonLisp.html][Discovering Common Lisp with ~trivial-gamekit~]] :: - Common Lisp is a venerable programming languages like no other I know. From - the creation of a Lisp package up to the creation of a standalone executable, - we explore the shore of this strange beast. + #+include: ./miscellaneous.org + +* About this Website + + #+include: ./meta.org diff --git a/site/meta.org b/site/meta.org new file mode 100644 index 0000000..d5ce4b4 --- /dev/null +++ b/site/meta.org @@ -0,0 +1,23 @@ +#+TITLE: About this Website + +#+SERIES: ./index.html +#+SERIES_PREV: miscellaneous.html + +The generation of this website is far from being trivial, and requires +the combination of —probably too— many tools. For instance, even if I +mostly use Org mode for authoring content, most of my write-ups about +Coq are actually Coq files, and I use ~coqdoc~ to generate the HTML +pages you read. + +- [[./posts/Thanks.org][Thanks!]] :: + This website could not exist without many awesome free software + projects. Although I could not list them all even if I wanted, my + desire is at least to try keeping up-to-date a curated description + of the most significant ones. + +- [[./cleopatra.org][A Series on Generating this Website]] :: + At some point, I felt like the whole process of generating this + website was interesting enough so that it would deserve a write-up + of its own. As a result, I spent quite some time turning my custom + toolchain into a literate program, so that its actual code source + would actually be the write-ups I wanted to add to my website. diff --git a/site/miscellaneous.org b/site/miscellaneous.org new file mode 100644 index 0000000..c348c28 --- /dev/null +++ b/site/miscellaneous.org @@ -0,0 +1,14 @@ +#+SERIES: index.html +#+SERIES_PREV: haskell.html +#+SERIES_NEXT: meta.html + +#+TITLE: Miscellaneous + +Over the years, I have made a habit of learning new programming +languages, out of curiosity, and I intend to continue this way for the +time being. + +- [[./posts/DiscoveringCommonLisp.html][Discovering Common Lisp with ~trivial-gamekit~]] :: + Common Lisp is a venerable programming languages like no other I + know. From the creation of a Lisp package up to the creation of a + standalone executable, we explore the shore of this strange beast. diff --git a/site/news/index.html b/site/news/index.html index 5a0331e..43315c0 100644 --- a/site/news/index.html +++ b/site/news/index.html @@ -3,6 +3,21 @@

2021

    +
  • + On March 4, 2021, + FreeSpec packages + (coq-freespec-core.0.3, coq-freespec-ffi.0.3 + and + coq-freespec-exec.0.3) have finally been released. +
  • +
  • + On March 1st, 2021, coq-coqffi.1.0.0~beta5 + has been released. +
  • +
  • + On February 24, 2021, coq-coqffi.1.0.0~beta4 + has been released. +
  • On January 27, 2021, FreeSpec has been diff --git a/site/opinions/MonadTransformers.org b/site/opinions/MonadTransformers.org index 7296f08..0424c7b 100644 --- a/site/opinions/MonadTransformers.org +++ b/site/opinions/MonadTransformers.org @@ -1,12 +1,12 @@ -#+BEGIN_EXPORT html -

    Monad Transformers are a Great Abstraction

    +#+TITLE: Monad Transformers are a Great Abstraction + +#+SERIES: ../opinions/index.html +#+BEGIN_EXPORT html

    This article has originally been published on July 15, 2017.

    #+END_EXPORT -#+OPTIONS: toc:nil - #+BEGIN_EXPORT html
    site/opinions/MonadTransformers.org
    #+END_EXPORT @@ -14,8 +14,8 @@ id="original-created-at">July 15, 2017.

    Monads are hard to get right. I think it took me around a year of Haskelling to feel like I understood them. The reason is, to my opinion, there is not such thing as /the/ Monad. It is even the contrary. When someone asks me how I would -define Monads in only a few words, [[https://techn.ical.ist/@lthms/590439][I say Monad is a convenient formalism to -chain specific computations]]. Once I’ve got that, I started noticing “monadic +define Monads in only a few words, I say monads are a convenient formalism to +chain specific computations. Once I’ve got that, I started noticing “monadic construction” everywhere, from the Rust ~?~ operator to the [[https://blog.drewolson.org/elixirs-secret-weapon/][Elixir ~with~ keyword]]. @@ -46,7 +46,6 @@ issue with the Monad Transformers. #+BEGIN_SRC diff -type Builder = StateT Text IO +type Builder = StateT Text (ReaderT Language IO) - #+END_SRC As you may have already understood, I wasn't using the “raw” ~State~ Monad, but diff --git a/site/opinions/index.org b/site/opinions/index.org index 0be267e..58b0407 100644 --- a/site/opinions/index.org +++ b/site/opinions/index.org @@ -1,8 +1,4 @@ -#+options: num:nil - -#+BEGIN_EXPORT html -

    Opinions

    -#+END_EXPORT +#+TITLE: Opinions I may have some opinions on some topics, and sometimes I may want to share them. However, I strongly believe facts and opinions are two differents things, diff --git a/site/posts/AlgebraicDatatypes.v b/site/posts/AlgebraicDatatypes.v index 1b24520..f32551c 100644 --- a/site/posts/AlgebraicDatatypes.v +++ b/site/posts/AlgebraicDatatypes.v @@ -1,3 +1,7 @@ +(** ## *) + (** * Proving Algebraic Datatypes are “Algebraic” *) (** Several programming languages allow programmers to define (potentially @@ -93,7 +97,7 @@ Inductive prod (A B : Type) : Type := | pair : A -> B -> prod A B >> - #
    # + ## #
    site/posts/AlgebraicDatatypes.v
    # *) diff --git a/site/posts/ClightIntroduction.v b/site/posts/ClightIntroduction.v index 4bd9a52..85d084b 100644 --- a/site/posts/ClightIntroduction.v +++ b/site/posts/ClightIntroduction.v @@ -1,3 +1,7 @@ +(** ## *) + (** * A Study of Clight and its Semantics *) (* begin hide *) From Coq Require Import List. @@ -12,7 +16,7 @@ Import ListNotations. challenged myself to study Clight and its semantics. This write-up is the result of this challenge, written as I was progressing. - #
    # + ## #
    site/posts/ClightIntroduction.v
    # *) diff --git a/site/posts/Coqffi.org b/site/posts/Coqffi.org index 3d8b867..f8d9695 100644 --- a/site/posts/Coqffi.org +++ b/site/posts/Coqffi.org @@ -1,6 +1,7 @@ -#+BEGIN_EXPORT html -

    A Series on coqffi

    -#+END_EXPORT +#+TITLE: A series on ~coqffi~ + +#+SERIES: ../coq.html +#+SERIES_PREV: AlgebraicDatatypes.html ~coqffi~ generates Coq FFI modules from compiled OCaml interface modules (~.cmi~). In practice, it greatly reduces the hassle to mix diff --git a/site/posts/CoqffiEcho.org b/site/posts/CoqffiEcho.org index 04fa253..81ae0e9 100644 --- a/site/posts/CoqffiEcho.org +++ b/site/posts/CoqffiEcho.org @@ -1,6 +1,7 @@ -#+BEGIN_EXPORT html -

    Implementing an Echo Server in Coq with coqffi

    -#+END_EXPORT +#+TITLE: Implementing an Echo Server in Coq with ~coqffi~ + +#+SERIES: ./Coqffi.html +#+SERIES_PREV: ./CoqffiIntro.html #+NAME: coqffi_output #+BEGIN_SRC sh :results output :exports none :var mod="" @@ -21,9 +22,8 @@ Besides, this article is a literate program, and you can download [[/files/coqffi-tutorial.tar.gz][the resulting source tree]] if you want to try to read the source directly, or modify it to your taste. -#+TOC: headlines 2 - #+BEGIN_EXPORT html +
    site/posts/CoqffiEcho.org
    #+END_EXPORT diff --git a/site/posts/CoqffiIntro.org b/site/posts/CoqffiIntro.org index 053826b..411f3cf 100644 --- a/site/posts/CoqffiIntro.org +++ b/site/posts/CoqffiIntro.org @@ -1,6 +1,7 @@ -#+BEGIN_EXPORT html -

    coqffi in a Nutshell

    -#+END_EXPORT +#+TITLE: ~coqffi~ in a Nutshell + +#+SERIES: ./Coqffi.html +#+SERIES_NEXT: ./CoqffiEcho.html For each entry of a ~cmi~ file (a /compiled/ ~mli~ file), ~coqffi~ tries to generate an equivalent (from the extraction mechanism @@ -10,9 +11,8 @@ perspective) Coq definition. In this article, we walk through how Note that we do not dive into the vernacular commands ~coqffi~ generates. They are of no concern for users of ~coqffi~. -#+TOC: headlines 2 - #+BEGIN_EXPORT html +
    site/posts/CoqffiIntro.org
    #+END_EXPORT diff --git a/site/posts/ExtensibleTypeSafeErrorHandling.org b/site/posts/ExtensibleTypeSafeErrorHandling.org index cc276f0..e817e31 100644 --- a/site/posts/ExtensibleTypeSafeErrorHandling.org +++ b/site/posts/ExtensibleTypeSafeErrorHandling.org @@ -1,13 +1,14 @@ -#+BEGIN_EXPORT html -

    Extensible Type-Safe Error Handling in Haskell

    +#+TITLE: Extensible Type-Safe Error Handling in Haskell + +#+SERIES: ../haskell.html +#+BEGIN_EXPORT html

    This article has originally been published on February 04, 2018.

    #+END_EXPORT -#+TOC: headlines 2 - #+BEGIN_EXPORT html +
    site/posts/ExtensibleTypeSafeErrorHandling.org
    #+END_EXPORT diff --git a/site/posts/Ltac.org b/site/posts/Ltac.org index caba76c..37580cd 100644 --- a/site/posts/Ltac.org +++ b/site/posts/Ltac.org @@ -1,12 +1,16 @@ -#+BEGIN_EXPORT html -

    A Series on Ltac

    -#+END_EXPORT +#+TITLE: A Series on Ltac + +#+SERIES: ../coq.html +#+SERIES_PREV: ./StronglySpecifiedFunctions.html +#+SERIES_NEXT: ./RewritingInCoq.html Ltac is the “tactic language” of Coq. It is commonly advertised as the common -approach to write proofs, which tends to bias how it is introduced to new Coq -users (/e.g./, in Master courses). In this series, we present Ltac as the -metaprogramming tool it is, since fundamentally it is an imperative language -which allows for constructing Coq terms interactively and incrementally. +approach to write proofs, which tends to bias how it is introduced to +new Coq users[fn::I know /I/ was introduced to Coq in a similar way in +my Master courses.]. In this series, we present Ltac as the +metaprogramming tool it is, since fundamentally it is an imperative +language which allows for constructing Coq terms interactively and +incrementally. - [[./LtacMetaprogramming.html][Ltac is an Imperative Metaprogramming Language]] :: Ltac generates terms, therefore it is a metaprogramming language. It does it diff --git a/site/posts/LtacMetaprogramming.v b/site/posts/LtacMetaprogramming.v index 2a4fe50..6b086e3 100644 --- a/site/posts/LtacMetaprogramming.v +++ b/site/posts/LtacMetaprogramming.v @@ -1,3 +1,6 @@ +(** ## *) + (** * Ltac is an Imperative Metaprogramming Language *) (** #
    site/posts/LtacMetaprogramming.v
    # *) diff --git a/site/posts/LtacPatternMatching.v b/site/posts/LtacPatternMatching.v index d52d0bf..a0b8a4d 100644 --- a/site/posts/LtacPatternMatching.v +++ b/site/posts/LtacPatternMatching.v @@ -1,3 +1,7 @@ +(** ## *) + (** * Pattern Matching on Types and Contexts *) (** In the ##previous article## of our @@ -11,7 +15,7 @@ contexts. In this article, we give a short introduction on this feature of key importance. *) -(** #
    # +(** ## #
    site/posts/LtacPatternMatching.v
    # *) @@ -137,8 +141,8 @@ Ltac not_param_type x := | _ => idtac end. -(** Both <> of type [list nat] and <<(@eq_refl nat - 0)>> of type [0 = 0] fail, but <> of type [nat] +(** Both <> of type [list nat] and + <<(@eq_refl nat 0)>> of type [0 = 0] fail, but <> of type [nat] succeeds. *) (** ** Pattern Matching on the Context with [goal] *) diff --git a/site/posts/MixingLtacAndGallina.v b/site/posts/MixingLtacAndGallina.v index 4e6b28d..d77cd8a 100644 --- a/site/posts/MixingLtacAndGallina.v +++ b/site/posts/MixingLtacAndGallina.v @@ -1,3 +1,6 @@ +(** ## *) + (** * Mixing Ltac and Gallina for Fun and Profit *) (** One of the most misleading introduction to Coq is to say that “Gallina is @@ -20,7 +23,7 @@ It turns out these features are more than handy when it comes to metaprogramming (that is, the generation of programs by programs). *) -(** #
    # +(** ## #
    site/posts/MixingLtacAndGallina.v
    # *) diff --git a/site/posts/RewritingInCoq.v b/site/posts/RewritingInCoq.v index 0020a3e..a285e09 100644 --- a/site/posts/RewritingInCoq.v +++ b/site/posts/RewritingInCoq.v @@ -1,3 +1,7 @@ +(** ## *) + (** * Rewriting in Coq *) (** I have to confess something. In the codebase of SpecCert lies a shameful @@ -9,7 +13,7 @@ 13, 2017 how it is possible to rewrite a term in a proof using a ad-hoc equivalence relation and, when necessary, a proper morphism. *) -(** #
    # +(** ## #
    site/posts/RewritingInCoq.v
    # *) diff --git a/site/posts/StronglySpecifiedFunctions.org b/site/posts/StronglySpecifiedFunctions.org index 805b944..83148c6 100644 --- a/site/posts/StronglySpecifiedFunctions.org +++ b/site/posts/StronglySpecifiedFunctions.org @@ -1,8 +1,7 @@ -#+OPTIONS: toc:nil num:nil +#+TITLE: A Series on Strongly-Specified Functions in Coq -#+BEGIN_EXPORT html -

    A Series on Strongly-Specified Functions in Coq

    -#+END_EXPORT +#+SERIES: ../coq.html +#+SERIES_NEXT: ./Ltac.html Using dependent types and the ~Prop~ sort, it becomes possible to specify functions whose arguments and results are constrained by properties. Using such diff --git a/site/posts/StronglySpecifiedFunctionsProgram.v b/site/posts/StronglySpecifiedFunctionsProgram.v index 1b4ab5f..c5763ea 100644 --- a/site/posts/StronglySpecifiedFunctionsProgram.v +++ b/site/posts/StronglySpecifiedFunctionsProgram.v @@ -5,7 +5,7 @@ to write strongly-specified functions in Coq. You can read the previous part #here#. # *) -(** #
    # +(** ## #
    site/posts/StronglySpecifiedFunctionsProgram.v
    # *) @@ -341,7 +341,8 @@ Defined. (** val extract : 'a1 vector -> nat -> nat -> 'a1 vector **) let extract v e b = take (drop v b) (sub e b) ->> *) +>> + *) (** I was pretty happy, so I tried some more. Each time, using [nth], I managed to write a precise post condition and to prove it holds true. For instance, @@ -467,7 +468,8 @@ cannot be applied to the terms "b" : "Type" The 3rd term has type "Type" which should be coercible to "nat". ->> *) +>> + *) #[program] Fixpoint map2 {a b c n} @@ -520,4 +522,5 @@ cannot be applied to the terms "wildcard'" : "vector A n'" The 3rd term has type "vector A n'" which should be coercible to "nat". ->> *) +>> + *) diff --git a/site/posts/StronglySpecifiedFunctionsRefine.v b/site/posts/StronglySpecifiedFunctionsRefine.v index 1d4ec2e..4ffb385 100644 --- a/site/posts/StronglySpecifiedFunctionsRefine.v +++ b/site/posts/StronglySpecifiedFunctionsRefine.v @@ -19,7 +19,7 @@ return value is the list passed in argument in which the first element has been removed for example. - #
    # + ## #
    site/posts/StronglySpecifiedFunctionsRefine.v
    # *) @@ -54,7 +54,8 @@ Import ListNotations. << Definition predicate_b (args) := if predicate_dec args then true else false. ->> *) +>> + *) (** *** Defining the <> predicate *) @@ -174,7 +175,8 @@ Definition pop {a} (l : list a) (h : ~ empty l) h : ~ empty l ============================ list a ->> *) +>> + *) (** Using the [refine] tactic naively, for instance this way: *) @@ -280,7 +282,8 @@ Definition pop {a} (l : list a | ~ empty l) equ : proj1_sig l = [] ============================ {l' : list a | exists a0 : a, proj1_sig l = a0 :: l'} ->> *) +>> + *) + destruct l as [l nempty]; cbn in *. rewrite equ in nempty. @@ -299,7 +302,8 @@ Definition pop {a} (l : list a | ~ empty l) equ : proj1_sig l = a0 :: rst ============================ exists a1 : a, proj1_sig l = a1 :: rst ->> *) +>> + *) + destruct l as [l nempty]; cbn in *. rewrite equ. @@ -339,7 +343,8 @@ Definition push {a} (l : list a) (x : a) << let push l a = Cons (a, l) ->> *) +>> + *) (** ** Defining [head] *) @@ -376,7 +381,8 @@ Defined. let head = function | Nil -> assert false (* absurd case *) | Cons (a, l0) -> a ->> *) +>> + *) (** ** Conclusion & Moving Forward *) diff --git a/site/posts/Thanks.org b/site/posts/Thanks.org index ba76a88..c20f1e5 100644 --- a/site/posts/Thanks.org +++ b/site/posts/Thanks.org @@ -1,18 +1,15 @@ -#+BEGIN_EXPORT html -

    Thanks!

    - -
    -#+END_EXPORT +#+TITLE: Thanks! -This website could not exist without (many) awesome free software -projects. Although I could not list them all even if I wanted, my desire is at -least to try keeping up-to-date a curated description of the “main” ones. +#+SERIES: ../meta.html +#+SERIES_NEXT: ../cleopatra.html -#+OPTIONS: toc:nil num:nil +This website could not exist without many awesome free software +projects. Although I could not list them all even if I wanted, my +desire is at least to try keeping up-to-date a curated description of +the most significant ones. #+BEGIN_EXPORT html -
    - +
    site/posts/Thanks.org
    #+END_EXPORT @@ -35,9 +32,6 @@ least to try keeping up-to-date a curated description of the “main” ones. - [[https://soupault.neocities.org][soupault]] :: Soupault is a static website generator and HTML processor written by [[https://www.baturin.org/][Daniil Baturin]]. -- [[https://github.com/sass/sassc][~sassc~]] :: - ~sassc~ is a compiler for SASS files (actually, a wrapper around [[https://github.com/sass/libsass][~libsass~]]), - authored by [[https://github.com/akhleung][Aaron Leung]], [[https://github.com/hcatlin][Hampton Catlin]], [[https://github.com/mgreter][Marcel Greter]], and [[https://github.com/xzyfer][Michael Mifsud]]. - [[https://cleopatra.soap.coffee][~cleopatra~]] :: ~cleopatra~ is a generic, extensible toolchain with facilities for literate programming projects using Org mode and more. I have @@ -45,25 +39,9 @@ least to try keeping up-to-date a curated description of the “main” ones. * Frontend -- [[https://forkaweso.me/Fork-Awesome/][Fork Awesome]] :: - Fork Awesome is a collection of icons for the web. It is a community fork of - [[https://fontawesome.com/][Font Awesome]]. - [[https://katex.org][\im \KaTeX \mi]] :: \im \KaTeX \mi is the “fastest” math typesetting library for the web, and is - uses to render inline mathematics in my posts at build time. It has been + used to render inline mathematics in my posts at build time. It has been created by [[https://github.com/xymostech][Emily Eisenberg]] and [[https://sophiebits.com/][Sophie Alpert]], with the help of [[https://github.com/KaTeX/KaTeX/graphs/contributors][many contributors]]. -- [[https://github.com/tonsky/FiraCode][Fira Code]] :: - Fira Code is a monospaced font by [[https://github.com/tonsky][Nikita Prokopov]] inspired with Fira Mono by - the [[https://www.mozilla.org/en-US/][Mozilla Foundation]], with “programming ligatures” (/e.g./, =>>==, ====, - =!==, etc.), and it is used here for verbatim content (principally source - code). -- [[https://github.com/productiontype/spectral][Spectral]] :: - Spectral is an original typeface designed by Production Type, - primarily intended for use inside Google’s Docs and Slides. It is - used as the main font of this website. - -#+BEGIN_EXPORT html -
    -#+END_EXPORT -- cgit v1.2.3