diff options
Diffstat (limited to '')
31 files changed, 925 insertions, 200 deletions
@@ -540,12 +540,10 @@ sitemap po4a for markdown... -article in root???? - render slides error on missing variable owith envsubst? how to use tmp fd over tmpfile? -i18n of the collection name +build makemake output in parallel @@ -10,8 +10,9 @@ export DOMAIN='euandre.org' export EMAIL='eu@euandre.org' export CONTENT_PREFIX='src/content' export COLLECTIONS=' -tils -pastebins +article +til +pastebin ' export LAYOUTS=' slides slide diff --git a/v2/.gitignore b/v2/.gitignore index 971b0fe..9ad29bd 100644 --- a/v2/.gitignore +++ b/v2/.gitignore @@ -22,3 +22,4 @@ /src/content/**/*.indexentry /src/content/**/*.xmlentry /src/content/**/*.xml +/src/content/.gitignore diff --git a/v2/dynamic.mk b/v2/dynamic.mk index 9ebd5ef..ba07dfe 100644 --- a/v2/dynamic.mk +++ b/v2/dynamic.mk @@ -7,9 +7,12 @@ include generated.mk .SUFFIXES: -.SUFFIXES: .md .content .conf .html .categoryentry .indexentry .xmlentry +.SUFFIXES: .page .md .content .conf .html .categoryentry .indexentry .xmlentry +.page.md: + ln -f $< $@ + .md.content: awk 'sep >= 2; /^---$$/ {sep++}' < $< > $@ @@ -50,7 +53,8 @@ $(all-generated.xml): clean: rm -rf \ - public/ $(all-generated) *.sentinel generated.mk po/po4a.cfg \ + $(all-generated) $(pages-mds) public/ *.sentinel generated.mk \ + po/po4a.cfg src/content/.gitignore \ src/content/*/*.category src/content/*/*/*.category \ src/content/*/*.categorysort src/content/*/*/*.categorysort \ src/content/*/*.html src/content/*/*/*.html \ @@ -122,6 +126,8 @@ test-files = \ aux/checks/shellcheck.sh \ aux/checks/todos.sh \ +aux/checks/shellcheck.sh: src/lib/generated.conf + $(test-files): ALWAYS sh $@ diff --git a/v2/po/euandre.org.pot b/v2/po/euandre.org.pot index 90c1acb..c90685c 100644 --- a/v2/po/euandre.org.pot +++ b/v2/po/euandre.org.pot @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2023-04-08 12:41-0300\n" +"POT-Creation-Date: 2023-04-08 15:21-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -65,72 +65,112 @@ msgstr "" #. type: Plain text #: src/lib/base.en.conf:8 -msgid "export index_pastebins_title='Pastebins'" +msgid "export about='About'" msgstr "" #. type: Plain text #: src/lib/base.en.conf:10 -msgid "export index_recent_pastebins_title='Pastebins listing'" +msgid "export about_url_name='about.html'" msgstr "" #. type: Plain text #: src/lib/base.en.conf:12 -msgid "export index_category_pastebins_title='Pastebins by category'" +msgid "export by_category_url_name='by-category.html'" msgstr "" #. type: Plain text #: src/lib/base.en.conf:14 -msgid "export index by_category_url_part='by-category.html'" +msgid "export homepage_url=\"$(url-for \"$lang/\")\"" msgstr "" #. type: Plain text #: src/lib/base.en.conf:16 -msgid "export feed_pastebins_title=\"EuAndreh's pastebins\"" +msgid "export homepage_url_absolute=\"$(absolute \"$homepage_url\")\"" msgstr "" #. type: Plain text #: src/lib/base.en.conf:18 -msgid "export index_tils_title='TIL'" +msgid "export about_url=\"$(url-for \"$lang/$about_url_name\")\"" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:20 -msgid "export index_recent_tils_title='TIL listing'" +#: src/lib/base.en.conf:21 +msgid "export index__title='Blog'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:22 -msgid "export index_category_tils_title='TIL by category'" +#: src/lib/base.en.conf:23 +msgid "export index_recent__title='Recent articles'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:24 -msgid "export feed_tils_title=\"EuAndreh's TIL\"" +#: src/lib/base.en.conf:25 +msgid "export index_category__title='Articles by category'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:26 -msgid "export about='About'" +#: src/lib/base.en.conf:27 +msgid "export feed__title=\"EuAndreh's articles\"" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:28 -msgid "export about_url_name='about.html'" +#: src/lib/base.en.conf:30 +msgid "export index_pastebin_title='Pastebins'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:30 -msgid "export homepage_url=\"$(url-for \"$lang/\")\"" +#: src/lib/base.en.conf:32 +msgid "export index_recent_pastebin_title='Pastebins listing'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:32 -msgid "export homepage_url_absolute=\"$(absolute \"$homepage_url\")\"" +#: src/lib/base.en.conf:34 +msgid "export index_category_pastebin_title='Pastebins by category'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:33 -msgid "export about_url=\"$(url-for \"$lang/$about_url_name\")\"" +#: src/lib/base.en.conf:36 +msgid "export feed_pastebin_title=\"EuAndreh's pastebins\"" +msgstr "" + +#. type: Plain text +#: src/lib/base.en.conf:39 +msgid "export index_til_title='TIL'" +msgstr "" + +#. type: Plain text +#: src/lib/base.en.conf:41 +msgid "export index_recent_til_title='TIL listing'" +msgstr "" + +#. type: Plain text +#: src/lib/base.en.conf:43 +msgid "export index_category_til_title='TIL by category'" +msgstr "" + +#. type: Plain text +#: src/lib/base.en.conf:44 +msgid "export feed_til_title=\"EuAndreh's TIL\"" +msgstr "" + +#. type: Plain text +#: src/lib/commencement.en.conf:2 +msgid "#!/bin/sh" +msgstr "" + +#. type: Plain text +#: src/lib/commencement.en.conf:4 +msgid "export article_collection_name=''" +msgstr "" + +#. type: Plain text +#: src/lib/commencement.en.conf:6 +msgid "export pastebin_collection_name='pastebin'" +msgstr "" + +#. type: Plain text +#: src/lib/commencement.en.conf:7 +msgid "export til_collection_name='til'" msgstr "" #. type: Content of: <p> @@ -163,8 +203,10 @@ msgstr "" #. type: Plain text #: src/content/en/about.md:1 src/content/en/about.md:5 -#: src/content/en/pastebins/sicp-exercise-3-19.md:1 -#: src/content/en/pastebins/sicp-exercise-3-19.md:9 +#: src/content/en/pastebin/sicp-exercise-3-19.md:1 +#: src/content/en/pastebin/sicp-exercise-3-19.md:9 +#: src/content/en/til/lisp-three-way-conditional.md:1 +#: src/content/en/til/lisp-three-way-conditional.md:11 #, no-wrap msgid "---\n" msgstr "" @@ -180,27 +222,27 @@ msgid "It's all about me, baby!" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:4 +#: src/content/en/pastebin/sicp-exercise-3-19.md:4 msgid "title: SICP exercise 3.19" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:6 +#: src/content/en/pastebin/sicp-exercise-3-19.md:6 msgid "date: 2021-09-02" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:8 +#: src/content/en/pastebin/sicp-exercise-3-19.md:8 msgid "categories: lisp programming-languages" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:12 +#: src/content/en/pastebin/sicp-exercise-3-19.md:12 msgid "Some content here, before:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:22 +#: src/content/en/pastebin/sicp-exercise-3-19.md:22 #, no-wrap msgid "" "```scheme\n" @@ -215,12 +257,12 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:24 +#: src/content/en/pastebin/sicp-exercise-3-19.md:24 msgid "Sample interactive session:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:41 +#: src/content/en/pastebin/sicp-exercise-3-19.md:41 #, no-wrap msgid "" "```scheme\n" @@ -242,93 +284,93 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:43 +#: src/content/en/pastebin/sicp-exercise-3-19.md:43 msgid "# An h1" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:45 +#: src/content/en/pastebin/sicp-exercise-3-19.md:45 msgid "a list:" msgstr "" #. type: Bullet: '1. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 #, markdown-text msgid "one" msgstr "" #. type: Bullet: '2. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 #, markdown-text msgid "two" msgstr "" #. type: Bullet: '3. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 #, markdown-text msgid "three" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:51 +#: src/content/en/pastebin/sicp-exercise-3-19.md:51 msgid "some content." msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 #, markdown-text msgid "item" msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 #, markdown-text msgid "another" msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 #, markdown-text msgid "yet another" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:57 +#: src/content/en/pastebin/sicp-exercise-3-19.md:57 msgid "## An h2" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:59 +#: src/content/en/pastebin/sicp-exercise-3-19.md:59 msgid "Xablau:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:62 +#: src/content/en/pastebin/sicp-exercise-3-19.md:62 msgid "``` xupliu 1" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:65 +#: src/content/en/pastebin/sicp-exercise-3-19.md:65 msgid "3 4" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:72 +#: src/content/en/pastebin/sicp-exercise-3-19.md:72 msgid "dez ```" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:74 +#: src/content/en/pastebin/sicp-exercise-3-19.md:74 msgid "Foi `wikiwiu`." msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:76 +#: src/content/en/pastebin/sicp-exercise-3-19.md:76 msgid "a very long code block:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:82 +#: src/content/en/pastebin/sicp-exercise-3-19.md:82 #, no-wrap msgid "" "```\n" @@ -340,27 +382,144 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:84 +#: src/content/en/pastebin/sicp-exercise-3-19.md:84 msgid "Someone said:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:86 +#: src/content/en/pastebin/sicp-exercise-3-19.md:86 msgid "> Xablau, xupliu." msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:89 +#: src/content/en/pastebin/sicp-exercise-3-19.md:89 msgid "### A repeated header ### A repeated header" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:91 +#: src/content/en/pastebin/sicp-exercise-3-19.md:91 msgid "a big list:" msgstr "" #. type: Bullet: '1. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:109 +#: src/content/en/pastebin/sicp-exercise-3-19.md:109 #, markdown-text msgid "a" msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:4 +msgid "title: Three-way conditional for number signs on Lisp" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:6 +msgid "date: 2021-04-24 3" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:8 +msgid "update: 2021-08-14" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:10 +#, no-wrap +msgid "categories: lisp scheme common-lisp\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:14 +msgid "A useful macro from Paul Graham's [On Lisp][on-lisp] book:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:23 +#, no-wrap +msgid "" +"```lisp\n" +"(defmacro nif (expr pos zero neg)\n" +" (let ((g (gensym)))\n" +" `(let ((,g ,expr))\n" +" (cond ((plusp ,g) ,pos)\n" +" ((zerop ,g) ,zero)\n" +" (t ,neg)))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:25 +msgid "" +"After I looked at this macro, I started seeing opportunities to using it in " +"many places, and yet I didn't see anyone else using it." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:27 +msgid "" +"The latest example I can think of is section 1.3.3 of [Structure and " +"Interpretation of Computer Programs][sicp], which I was reading recently:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:40 +#, no-wrap +msgid "" +"```scheme\n" +"(define (search f neg-point pos-point)\n" +" (let ((midpoint (average neg-point pos-point)))\n" +" (if (close-enough? neg-point post-point)\n" +" midpoint\n" +" (let ((test-value (f midpoint)))\n" +" (cond ((positive? test-value)\n" +" (search f neg-point midpoint))\n" +" ((negative? test-value)\n" +" (search f midpoint pos-point))\n" +" (else midpoint))))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:42 +msgid "" +"Not that the book should introduce such macro this early, but I couldn't " +"avoid feeling bothered by not using the `nif` macro, which could even remove " +"the need for the intermediate `test-value` variable:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:53 +#, no-wrap +msgid "" +"```scheme\n" +"(define (search f neg-point pos-point)\n" +" (let ((midpoint (average neg-point pos-point)))\n" +" (if (close-enough? neg-point post-point)\n" +" midpoint\n" +" (nif (f midpoint)\n" +" (search f neg-point midpoint)\n" +" (midpoint)\n" +" (search f midpoint pos-point)))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:55 +msgid "" +"It also avoids `cond`'s extra clunky parentheses for grouping, which is " +"unnecessary but built-in." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:57 +msgid "" +"As a macro, I personally feel it tilts the balance towards expressivenes " +"despite its extra cognitive load toll." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:59 +msgid "" +"[on-lisp]: http://www.paulgraham.com/onlisptext.html [sicp]: " +"https://mitpress.mit.edu/sites/default/files/sicp/index.html" +msgstr "" diff --git a/v2/po/i18n.mappings b/v2/po/i18n.mappings index af1584a..39a7319 100644 --- a/v2/po/i18n.mappings +++ b/v2/po/i18n.mappings @@ -1,2 +1,3 @@ -[type: text] src/content/en/about.md pt:src/content/pt/sobre.md -[type: text] src/content/en/pastebins/sicp-exercise-3-19.md pt:src/content/pt/pastebins/exercicios-sicp-e-19.md +[type: text] src/content/en/about.page pt:src/content/pt/sobre.page +[type: text] src/content/en/pastebin/sicp-exercise-3-19.md pt:src/content/pt/pastebin/exercicios-sicp-e-19.md +[type: text] src/content/en/til/lisp-three-way-conditional.md pt:src/content/pt/hea/condicional-ternario-lisp.md diff --git a/v2/po/pt.po b/v2/po/pt.po index 2df706c..bee1fc3 100644 --- a/v2/po/pt.po +++ b/v2/po/pt.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"POT-Creation-Date: 2023-04-08 12:41-0300\n" +"POT-Creation-Date: 2023-04-08 15:21-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -60,74 +60,114 @@ msgstr "export lang='pt'" #. type: Plain text #: src/lib/base.en.conf:8 -msgid "export index_pastebins_title='Pastebins'" +msgid "export about='About'" msgstr "" #. type: Plain text #: src/lib/base.en.conf:10 -msgid "export index_recent_pastebins_title='Pastebins listing'" -msgstr "" +msgid "export about_url_name='about.html'" +msgstr "export about_url_name='sobre.html'" #. type: Plain text #: src/lib/base.en.conf:12 -msgid "export index_category_pastebins_title='Pastebins by category'" -msgstr "" +msgid "export by_category_url_name='by-category.html'" +msgstr "export by_category_url_name='por-categoria.html'" #. type: Plain text #: src/lib/base.en.conf:14 -msgid "export index by_category_url_part='by-category.html'" +msgid "export homepage_url=\"$(url-for \"$lang/\")\"" msgstr "" #. type: Plain text #: src/lib/base.en.conf:16 -msgid "export feed_pastebins_title=\"EuAndreh's pastebins\"" +msgid "export homepage_url_absolute=\"$(absolute \"$homepage_url\")\"" msgstr "" #. type: Plain text #: src/lib/base.en.conf:18 -msgid "export index_tils_title='TIL'" +msgid "export about_url=\"$(url-for \"$lang/$about_url_name\")\"" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:20 -msgid "export index_recent_tils_title='TIL listing'" -msgstr "" +#: src/lib/base.en.conf:21 +msgid "export index__title='Blog'" +msgstr "export index__title='Blog'" #. type: Plain text -#: src/lib/base.en.conf:22 -msgid "export index_category_tils_title='TIL by category'" -msgstr "" +#: src/lib/base.en.conf:23 +msgid "export index_recent__title='Recent articles'" +msgstr "export index_recent__title='Artigos recentes'" #. type: Plain text -#: src/lib/base.en.conf:24 -msgid "export feed_tils_title=\"EuAndreh's TIL\"" -msgstr "" +#: src/lib/base.en.conf:25 +msgid "export index_category__title='Articles by category'" +msgstr "export index_category__title='Artigos por categoria'" #. type: Plain text -#: src/lib/base.en.conf:26 -msgid "export about='About'" +#: src/lib/base.en.conf:27 +msgid "export feed__title=\"EuAndreh's articles\"" +msgstr "export feed__title=\"Artigos do EuAndreh\"" + +#. type: Plain text +#: src/lib/base.en.conf:30 +msgid "export index_pastebin_title='Pastebins'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:28 -msgid "export about_url_name='about.html'" +#: src/lib/base.en.conf:32 +msgid "export index_recent_pastebin_title='Pastebins listing'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:30 -msgid "export homepage_url=\"$(url-for \"$lang/\")\"" +#: src/lib/base.en.conf:34 +msgid "export index_category_pastebin_title='Pastebins by category'" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:32 -msgid "export homepage_url_absolute=\"$(absolute \"$homepage_url\")\"" +#: src/lib/base.en.conf:36 +msgid "export feed_pastebin_title=\"EuAndreh's pastebins\"" msgstr "" #. type: Plain text -#: src/lib/base.en.conf:33 -msgid "export about_url=\"$(url-for \"$lang/$about_url_name\")\"" +#: src/lib/base.en.conf:39 +msgid "export index_til_title='TIL'" +msgstr "export index_til_title='HEA'" + +#. type: Plain text +#: src/lib/base.en.conf:41 +msgid "export index_recent_til_title='TIL listing'" +msgstr "export index_recent_til_title='HEA recentes'" + +#. type: Plain text +#: src/lib/base.en.conf:43 +msgid "export index_category_til_title='TIL by category'" +msgstr "export index_category_til_title='HEA por categoria'" + +#. type: Plain text +#: src/lib/base.en.conf:44 +msgid "export feed_til_title=\"EuAndreh's TIL\"" +msgstr "export feed_til_title=\"HEA do EuAndreh\"" + +#. type: Plain text +#: src/lib/commencement.en.conf:2 +msgid "#!/bin/sh" msgstr "" +#. type: Plain text +#: src/lib/commencement.en.conf:4 +msgid "export article_collection_name=''" +msgstr "export article_collection_name=''" + +#. type: Plain text +#: src/lib/commencement.en.conf:6 +msgid "export pastebin_collection_name='pastebin'" +msgstr "export pastebin_collection_name='pastebin'" + +#. type: Plain text +#: src/lib/commencement.en.conf:7 +msgid "export til_collection_name='til'" +msgstr "export til_collection_name='hea'" + #. type: Content of: <p> #: src/lib/comment.en.html:3 msgid "" @@ -157,8 +197,10 @@ msgstr "" #. type: Plain text #: src/content/en/about.md:1 src/content/en/about.md:5 -#: src/content/en/pastebins/sicp-exercise-3-19.md:1 -#: src/content/en/pastebins/sicp-exercise-3-19.md:9 +#: src/content/en/pastebin/sicp-exercise-3-19.md:1 +#: src/content/en/pastebin/sicp-exercise-3-19.md:9 +#: src/content/en/til/lisp-three-way-conditional.md:1 +#: src/content/en/til/lisp-three-way-conditional.md:11 #, no-wrap msgid "---\n" msgstr "" @@ -174,27 +216,27 @@ msgid "It's all about me, baby!" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:4 +#: src/content/en/pastebin/sicp-exercise-3-19.md:4 msgid "title: SICP exercise 3.19" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:6 +#: src/content/en/pastebin/sicp-exercise-3-19.md:6 msgid "date: 2021-09-02" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:8 +#: src/content/en/pastebin/sicp-exercise-3-19.md:8 msgid "categories: lisp programming-languages" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:12 +#: src/content/en/pastebin/sicp-exercise-3-19.md:12 msgid "Some content here, before:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:22 +#: src/content/en/pastebin/sicp-exercise-3-19.md:22 #, no-wrap msgid "" "```scheme\n" @@ -209,12 +251,12 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:24 +#: src/content/en/pastebin/sicp-exercise-3-19.md:24 msgid "Sample interactive session:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:41 +#: src/content/en/pastebin/sicp-exercise-3-19.md:41 #, no-wrap msgid "" "```scheme\n" @@ -236,87 +278,87 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:43 +#: src/content/en/pastebin/sicp-exercise-3-19.md:43 msgid "# An h1" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:45 +#: src/content/en/pastebin/sicp-exercise-3-19.md:45 msgid "a list:" msgstr "" #. type: Bullet: '1. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 msgid "one" msgstr "" #. type: Bullet: '2. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 msgid "two" msgstr "" #. type: Bullet: '3. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +#: src/content/en/pastebin/sicp-exercise-3-19.md:49 msgid "three" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:51 +#: src/content/en/pastebin/sicp-exercise-3-19.md:51 msgid "some content." msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 msgid "item" msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 msgid "another" msgstr "" #. type: Bullet: '- ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +#: src/content/en/pastebin/sicp-exercise-3-19.md:55 msgid "yet another" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:57 +#: src/content/en/pastebin/sicp-exercise-3-19.md:57 msgid "## An h2" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:59 +#: src/content/en/pastebin/sicp-exercise-3-19.md:59 msgid "Xablau:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:62 +#: src/content/en/pastebin/sicp-exercise-3-19.md:62 msgid "``` xupliu 1" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:65 +#: src/content/en/pastebin/sicp-exercise-3-19.md:65 msgid "3 4" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:72 +#: src/content/en/pastebin/sicp-exercise-3-19.md:72 msgid "dez ```" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:74 +#: src/content/en/pastebin/sicp-exercise-3-19.md:74 msgid "Foi `wikiwiu`." msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:76 +#: src/content/en/pastebin/sicp-exercise-3-19.md:76 msgid "a very long code block:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:82 +#: src/content/en/pastebin/sicp-exercise-3-19.md:82 #, no-wrap msgid "" "```\n" @@ -327,26 +369,143 @@ msgid "" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:84 +#: src/content/en/pastebin/sicp-exercise-3-19.md:84 msgid "Someone said:" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:86 +#: src/content/en/pastebin/sicp-exercise-3-19.md:86 msgid "> Xablau, xupliu." msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:89 +#: src/content/en/pastebin/sicp-exercise-3-19.md:89 msgid "### A repeated header ### A repeated header" msgstr "" #. type: Plain text -#: src/content/en/pastebins/sicp-exercise-3-19.md:91 +#: src/content/en/pastebin/sicp-exercise-3-19.md:91 msgid "a big list:" msgstr "" #. type: Bullet: '1. ' -#: src/content/en/pastebins/sicp-exercise-3-19.md:109 +#: src/content/en/pastebin/sicp-exercise-3-19.md:109 msgid "a" msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:4 +msgid "title: Three-way conditional for number signs on Lisp" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:6 +msgid "date: 2021-04-24 3" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:8 +msgid "update: 2021-08-14" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:10 +#, no-wrap +msgid "categories: lisp scheme common-lisp\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:14 +msgid "A useful macro from Paul Graham's [On Lisp][on-lisp] book:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:23 +#, no-wrap +msgid "" +"```lisp\n" +"(defmacro nif (expr pos zero neg)\n" +" (let ((g (gensym)))\n" +" `(let ((,g ,expr))\n" +" (cond ((plusp ,g) ,pos)\n" +" ((zerop ,g) ,zero)\n" +" (t ,neg)))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:25 +msgid "" +"After I looked at this macro, I started seeing opportunities to using it in " +"many places, and yet I didn't see anyone else using it." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:27 +msgid "" +"The latest example I can think of is section 1.3.3 of [Structure and " +"Interpretation of Computer Programs][sicp], which I was reading recently:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:40 +#, no-wrap +msgid "" +"```scheme\n" +"(define (search f neg-point pos-point)\n" +" (let ((midpoint (average neg-point pos-point)))\n" +" (if (close-enough? neg-point post-point)\n" +" midpoint\n" +" (let ((test-value (f midpoint)))\n" +" (cond ((positive? test-value)\n" +" (search f neg-point midpoint))\n" +" ((negative? test-value)\n" +" (search f midpoint pos-point))\n" +" (else midpoint))))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:42 +msgid "" +"Not that the book should introduce such macro this early, but I couldn't " +"avoid feeling bothered by not using the `nif` macro, which could even remove " +"the need for the intermediate `test-value` variable:" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:53 +#, no-wrap +msgid "" +"```scheme\n" +"(define (search f neg-point pos-point)\n" +" (let ((midpoint (average neg-point pos-point)))\n" +" (if (close-enough? neg-point post-point)\n" +" midpoint\n" +" (nif (f midpoint)\n" +" (search f neg-point midpoint)\n" +" (midpoint)\n" +" (search f midpoint pos-point)))))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:55 +msgid "" +"It also avoids `cond`'s extra clunky parentheses for grouping, which is " +"unnecessary but built-in." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:57 +msgid "" +"As a macro, I personally feel it tilts the balance towards expressivenes " +"despite its extra cognitive load toll." +msgstr "" + +#. type: Plain text +#: src/content/en/til/lisp-three-way-conditional.md:59 +msgid "" +"[on-lisp]: http://www.paulgraham.com/onlisptext.html [sicp]: https://" +"mitpress.mit.edu/sites/default/files/sicp/index.html" +msgstr "" diff --git a/v2/src/bin/categories b/v2/src/bin/categories index bc08704..de65acb 100755 --- a/v2/src/bin/categories +++ b/v2/src/bin/categories @@ -24,7 +24,7 @@ help() { Generate the index.categories entry for english pastebins: - $ categories src/en/pastebins/index.categories + $ categories src/en/pastebin/index.categories EOF } diff --git a/v2/src/bin/category b/v2/src/bin/category index 2a2fdea..16eea0e 100755 --- a/v2/src/bin/category +++ b/v2/src/bin/category @@ -68,7 +68,7 @@ eval "$(assert_arg "$FILENAME" 'FILENAME')" # shellcheck source=/dev/null -. "${FILENAME%.md}.conf" +. "${FILENAME%.*}.conf" DIR="$(dirname "$FILENAME")" diff --git a/v2/src/bin/coll2path b/v2/src/bin/coll2path new file mode 100755 index 0000000..79b2f53 --- /dev/null +++ b/v2/src/bin/coll2path @@ -0,0 +1,88 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + coll2path LANGUAGE COLLECTION + coll2path -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + LANGUAGE in which language to list the collections + names for + COLLECTION what collection to get the path for + + + Get the path for the COLLECTION, doing the proper translation + on the way, and checking if is "article". + + + Examples: + + Get the path for "TIL" in portuguese: + + $ coll2path pt til + hea/ + + + Get the path for "articles" in english + + $ collections en articles + + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + esac +done +shift $((OPTIND - 1)) + +. src/lib.sh + + +LANGUAGE="${1:-}" +COLLECTION="${2:-}" +eval "$(assert_arg "$LANGUAGE" 'LANGUAGE')" + +# shellcheck source=/dev/null +. src/lib/commencement."$LANGUAGE".conf + +if [ -z "$COLLECTION" ]; then + echo "${article_collection_name:-}" +else + NAME="$(eval "echo \"\$${COLLECTION}_collection_name\"")" + echo "$NAME${NAME:+/}" +fi diff --git a/v2/src/bin/collection-for b/v2/src/bin/collection-for index b3fc211..87f1204 100755 --- a/v2/src/bin/collection-for +++ b/v2/src/bin/collection-for @@ -24,10 +24,10 @@ help() { Examples: - Get "tils" for "src/en/tils/some-pt.md": + Get "til" for "src/en/til/some-pt.md": - $ collection-for src/en/tils/some-pt.md - tils + $ collection-for src/en/til/some-pt.md + til EOF } @@ -69,15 +69,18 @@ FILE="${1:-}" eval "$(assert_arg "$FILE" 'FILE')" -# echo "${FILE#"$CONTENT_PREFIX"/}" | cut -d/ -f1 -# echo "${FILE#"$CONTENT_PREFIX"/}" | awk '{ - # awk -F/ '$3 && $0=$2 { print; next } $0' - -ATTEMPT="$(echo "${FILE#"$CONTENT_PREFIX"/}" | cut -d/ -f2-)" - -if [ "$ATTEMPT" = 'index.html' ]; then - echo articles +lang="$(lang-for "$FILE")" +DIR="$(dirname "$FILE")" +if [ "$DIR" = "$CONTENT_PREFIX/$lang" ]; then + echo else - NAME="$(echo "$ATTEMPT" | cut -d/ -f1)" - collections | grep "$NAME" + NAME="$(basename "$DIR")" + NTH="$( + collections | + xargs -I% coll2path "$lang" % | + awk '{ print NR, substr($0, 1, length($0) - 1) }' | + grep " $NAME$" | + cut -d' ' -f1 + )" + collections | awk -vNTH="$NTH" 'NR == NTH' fi diff --git a/v2/src/bin/collections b/v2/src/bin/collections index 1df0c39..0a8e156 100755 --- a/v2/src/bin/collections +++ b/v2/src/bin/collections @@ -28,8 +28,8 @@ help() { Just run it: $ collections - tils - pastebins + til + pastebin EOF } diff --git a/v2/src/bin/conf b/v2/src/bin/conf index 62ef97a..92ecc68 100755 --- a/v2/src/bin/conf +++ b/v2/src/bin/conf @@ -178,7 +178,7 @@ if [ -n "${update:-}" ]; then fi -url_part="$(printf '%s' "${FILENAME%.md}.html" | sed "s|^$CONTENT_PREFIX/||")" +url_part="$(printf '%s' "${FILENAME%.*}.html" | sed "s|^$CONTENT_PREFIX/||")" url="$(url-for "$url_part")" title_uri="$(uri "$title")" diff --git a/v2/src/bin/feed b/v2/src/bin/feed index 52c6199..f55ba89 100755 --- a/v2/src/bin/feed +++ b/v2/src/bin/feed @@ -27,7 +27,7 @@ help() { Generate a feed for TILs: - $ feed src/en/tils/feed.xml + $ feed src/en/til/feed.xml EOF } @@ -76,8 +76,9 @@ eval "$(assert_arg "$FILENAME" 'FILENAME')" now="$(date -uIs)" url_absolute="$(url-for "${FILENAME#"$CONTENT_PREFIX"/}" | absolute)" site_name_html="$(htmlesc "${site_name:?}")" -collection="$(collection-for "$FILENAME")" -collection_url_absolute="$(url-for "${lang:?}/$collection/" | absolute)" +collection="$(sh src/bin/collection-for "$FILENAME")" +coll_path="$(coll2path "${lang:?}" "$collection")" +collection_url_absolute="$(url-for "${lang:?}/$coll_path" | absolute)" feed_title_html="$(eval "echo \"\$feed_${collection}_title\"" | htmlesc)" export now url_absolute site_name_html collection_url_absolute feed_title_html @@ -96,7 +97,7 @@ mkdir -p "$DIR" printf '' > "$DIR"/index.extrafeeds while read -r category; do url_absolute="$(url-for "${DIR#"$CONTENT_PREFIX"/}/feed.$category.xml" | absolute)" - collection_url_absolute="$(url-for "${DIR#"$CONTENT_PREFIX"/}/${by_category_url_part:?}#$category" | absolute)" + collection_url_absolute="$(url-for "${DIR#"$CONTENT_PREFIX"/}/${by_category_url_name:?}#$category" | absolute)" feed_title_html="$(eval "echo \"\$index_category_${collection}_title\"" | htmlesc)" export url_absolute collection_url_absolute feed_title_html diff --git a/v2/src/bin/html b/v2/src/bin/html index f995753..578c539 100755 --- a/v2/src/bin/html +++ b/v2/src/bin/html @@ -68,7 +68,7 @@ eval "$(assert_arg "$FILENAME" 'FILENAME')" # shellcheck source=/dev/null -. "${FILENAME%.md}.conf" +. "${FILENAME%.*}.conf" # # Utility functions @@ -99,7 +99,7 @@ markdown_to_html() { } extract_plaintext_snippets() ( - SNIPPETS="${FILENAME%.md}.snippets" + SNIPPETS="${FILENAME%.*}.snippets" printf '' > "$SNIPPETS" F="$(mkstemp)" cat > "$F" @@ -117,7 +117,7 @@ extract_plaintext_snippets() ( if printf '%s' "$line" | grep -q "^$INDENT<pre><code"; then IN_BLOCK=1 - OUT="${FILENAME%.md}.html.$BLOCK_NUMBER.txt" + OUT="${FILENAME%.*}.html.$BLOCK_NUMBER.txt" BLOCK_NUMBER=$((BLOCK_NUMBER + 1)) printf '%s\n' "$line" | sed "s|^\($INDENT<pre><code.*>\)\(.*\)$|\2|" | @@ -205,7 +205,7 @@ warn_duplicate_ids() { } emit_body() { - < "${FILENAME%.md}.content" \ + < "${FILENAME%.*}.content" \ markdown_to_html | extract_plaintext_snippets | add_line_numbers | @@ -214,5 +214,5 @@ emit_body() { } envsubst < src/lib/preamble.html -emit_body | tee "${FILENAME%.md}.htmlbody" +emit_body | tee "${FILENAME%.*}.htmlbody" envsubst < src/lib/postamble.html diff --git a/v2/src/bin/index b/v2/src/bin/index index 36750b3..46e0c88 100755 --- a/v2/src/bin/index +++ b/v2/src/bin/index @@ -4,8 +4,8 @@ set -eu usage() { cat <<-'EOF' Usage: - collection FILENAME - collection -h + index FILENAME + index -h EOF } @@ -25,7 +25,7 @@ help() { Generate an index.html entry for english pastebins: - $ collection src/en/pastebins/index.html + $ index src/en/pastebin/index.html EOF } @@ -79,7 +79,7 @@ url_part="$(printf '%s' "${FILENAME#"$CONTENT_PREFIX"/}" | sed "s|\.md$|.html|") url_absolute="$(url-for "$url_part" | absolute)" collection="$(collection-for "$FILENAME")" feed_url="$(url-for "${DIR#"$CONTENT_PREFIX"/}"/feed.xml)" -by_category_url="$(url-for "${DIR#"$CONTENT_PREFIX"/}/${by_category_url_part:?}")" +by_category_url="$(url-for "${DIR#"$CONTENT_PREFIX"/}/${by_category_url_name:?}")" title_html="$(eval "echo \"\$index_${collection}_title\"" | htmlesc)" index_recent_title_html="$(eval "echo \"\$index_recent_${collection}_title\"" | htmlesc)" index_category_title_html="$(eval "echo \"\$index_category_${collection}_title\"" | htmlesc)" diff --git a/v2/src/bin/indexentry b/v2/src/bin/indexentry index 03bf771..f971a30 100755 --- a/v2/src/bin/indexentry +++ b/v2/src/bin/indexentry @@ -26,7 +26,7 @@ help() { Generate the index entry for a TIL: - $ indexentry src/tils/a-til.md > src/tils/a-til.indexentry + $ indexentry src/til/a-til.md > src/til/a-til.indexentry EOF } @@ -68,6 +68,6 @@ eval "$(assert_arg "$FILENAME" 'FILENAME')" # shellcheck source=/dev/null -. "${FILENAME%.md}.conf" +. "${FILENAME%.*}.conf" envsubst < src/lib/entry.html diff --git a/v2/src/bin/makemake b/v2/src/bin/makemake index 20fd6dd..06041b0 100755 --- a/v2/src/bin/makemake +++ b/v2/src/bin/makemake @@ -98,14 +98,17 @@ for lang in $(langs); do for c in pages $(collections); do if [ "$c" = 'pages' ]; then filter="$page_ext_filter" - dir="$CONTENT_PREFIX/$lang" + src='page' + coll_path='' else filter='^$' - dir="$CONTENT_PREFIX/$lang/$c" + src='md' + coll_path="$(coll2path "$lang" "$c")" fi mds() { - find "$dir"/*.md 2>/dev/null + git ls-files "$CONTENT_PREFIX/$lang/$coll_path"*."$src" | + sed 's|\.page$|.md|' } exts() { @@ -120,17 +123,19 @@ for lang in $(langs); do mds | sed 's/^\(.*\)\.md$/\1.categoryentry \1.indexentry \1.html: \1.conf \1.content/' mds | sed 's/^\(.*\)\.md$/\1.snippets \1.htmlbody: \1.html/' if [ "$c" = 'pages' ]; then + mds | sed 's|\.md$|\.page|' | varlist "pages.$lang.page" + mds | sed "s|^\(.*\).md$|\1.md: \1.page|" continue fi mds | sed 's/^\(.*\)\.md$/\1.xmlentry: \1.htmlbody/' - echo "$CONTENT_PREFIX/$lang/$c/index.categories: \$($c.$lang.categoryentry)" - echo "$CONTENT_PREFIX/$lang/$c/index.html: \$($c.$lang.indexentry) $CONTENT_PREFIX/$lang/$c/index.categories" - echo "$CONTENT_PREFIX/$lang/$c/feed.xml: \$($c.$lang.xmlentry) $CONTENT_PREFIX/$lang/$c/index.categories" + echo "$CONTENT_PREFIX/$lang/${coll_path}index.categories: \$($c.$lang.categoryentry)" + echo "$CONTENT_PREFIX/$lang/${coll_path}index.html: \$($c.$lang.indexentry) $CONTENT_PREFIX/$lang/${coll_path}index.categories" + echo "$CONTENT_PREFIX/$lang/${coll_path}feed.xml: \$($c.$lang.xmlentry) $CONTENT_PREFIX/$lang/${coll_path}index.categories" - echo "$CONTENT_PREFIX/$lang/$c/index.extrahtml: $CONTENT_PREFIX/$lang/$c/index.html" - echo "$CONTENT_PREFIX/$lang/$c/index.extrafeeds: $CONTENT_PREFIX/$lang/$c/feed.xml" + echo "$CONTENT_PREFIX/$lang/${coll_path}index.extrahtml: $CONTENT_PREFIX/$lang/${coll_path}index.html" + echo "$CONTENT_PREFIX/$lang/${coll_path}index.extrafeeds: $CONTENT_PREFIX/$lang/${coll_path}feed.xml" printf '\n\n' done @@ -146,23 +151,28 @@ for lang in $(langs); do done collections | - sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1/index.categories|" | + xargs -I% coll2path "$lang" % | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1index.categories|" | varlist "all-generated.$lang.categories" collections | - sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1/index.extrahtml|" | + xargs -I% coll2path "$lang" % | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1index.extrahtml|" | varlist "all-generated.$lang.extrahtml" collections | - sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1/index.extrafeeds|" | + xargs -I% coll2path "$lang" % | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1index.extrafeeds|" | varlist "all-generated.$lang.extrafeeds" collections | - sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1/index.html|" | + xargs -I% coll2path "$lang" % | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1index.html|" | varlist "all-generated.$lang.index" collections | - sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1/feed.xml|" | + xargs -I% coll2path "$lang" % | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/\1feed.xml|" | varlist "all-generated.$lang.xml" extensions '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml' | @@ -172,6 +182,11 @@ for lang in $(langs); do printf '\n' done +git ls-files | + grep '\.page' | + sed "s|^$CONTENT_PREFIX\(.*\)\.page|\1.md|" > "$CONTENT_PREFIX"/.gitignore + + for e in $(extensions '.categories' '.extrahtml' '.extrafeeds' '.index' '.xml'); do langs | sed "s|^\(.*\)\$|\$(all-generated.\1$e)|" | @@ -180,6 +195,11 @@ done # shellcheck disable=2016 langs | + sed 's|^\(.*\)$|$(pages.\1.md)|' | + varlist 'pages-mds' + +# shellcheck disable=2016 +langs | sed 's|^\(.*\)$|$(all-generated.\1)|' | varlist 'all-generated' @@ -190,4 +210,5 @@ git ls-files src/ | git ls-files "$CONTENT_PREFIX"/ | grep -v '\.md$' | + grep -v '\.page$' | varlist 'static-content' diff --git a/v2/src/bin/xmlentry b/v2/src/bin/xmlentry index b0760ae..f6fb6ea 100755 --- a/v2/src/bin/xmlentry +++ b/v2/src/bin/xmlentry @@ -26,7 +26,7 @@ help() { Generate the XML entry for a TIL: - $ xmlentry src/tils/a-til.md > src/tils/a-til.xml + $ xmlentry src/til/a-til.md > src/til/a-til.xml EOF } @@ -68,14 +68,14 @@ eval "$(assert_arg "$FILENAME" 'FILENAME')" # shellcheck source=/dev/null -. "${FILENAME%.md}.conf" +. "${FILENAME%.*}.conf" envsubst < src/lib/entry.xml -head -n1 < "${FILENAME%.md}.htmlbody" | htmlesc +head -n1 < "${FILENAME%.*}.htmlbody" | htmlesc printf ' </summary>\n' printf ' <content type="html" xml:base="%s">\n' "${url:?}" -htmlesc < "${FILENAME%.md}.htmlbody" +htmlesc < "${FILENAME%.*}.htmlbody" printf ' </content>\n' printf ' </entry>\n' diff --git a/v2/src/content/en/about.md b/v2/src/content/en/about.page index aac3e67..aac3e67 100644 --- a/v2/src/content/en/about.md +++ b/v2/src/content/en/about.page diff --git a/v2/src/content/en/pastebins/raku-tuple-type-annotation.md b/v2/src/content/en/pastebin/raku-tuple-type-annotation.md index 6c13b39..6c13b39 100644 --- a/v2/src/content/en/pastebins/raku-tuple-type-annotation.md +++ b/v2/src/content/en/pastebin/raku-tuple-type-annotation.md diff --git a/v2/src/content/en/pastebins/sicp-exercise-3-19.md b/v2/src/content/en/pastebin/sicp-exercise-3-19.md index 32f7aa9..32f7aa9 100644 --- a/v2/src/content/en/pastebins/sicp-exercise-3-19.md +++ b/v2/src/content/en/pastebin/sicp-exercise-3-19.md diff --git a/v2/src/content/en/remembering-ann.md b/v2/src/content/en/remembering-ann.md new file mode 100644 index 0000000..9013ad4 --- /dev/null +++ b/v2/src/content/en/remembering-ann.md @@ -0,0 +1,186 @@ +--- + +title: ANN: remembering - Add memory to dmenu, fzf and similar tools + +date: 2021-01-26 + +categories: ann + +--- + +Today I pushed v0.1.0 of [remembering][remembering], a tool to enhance the interactive usability of menu-like tools, such as [dmenu][dmenu] and [fzf][fzf]. + +## Previous solution + +I previously used [yeganesh][yeganesh] fill this gap, but as I started to rely less on Emacs, I added fzf as my go-to tool for doing fuzzy searching on the terminal. +But I didn't like that fzf always showed the same order of things, when I would only need 3 or 4 commonly used files. + +For those who don't know: yeganesh is a wrapper around dmenu that will remember your most used programs and put them on the beginning of the list of executables. +This is very convenient for interactive prolonged use, as with time the things you usually want are right at the very beginning. + +But now I had this thing, yeganesh, that solved this problem for dmenu, but didn't for fzf. + +I initially considered patching yeganesh to support it, but I found it more coupled to dmenu than I would desire. +I'd rather have something that knows nothing about dmenu, fzf or anything, but enhances tools like those in a useful way. + +[remembering]: https://euandreh.xyz/remembering/ +[dmenu]: https://tools.suckless.org/dmenu/ +[fzf]: https://github.com/junegunn/fzf +[yeganesh]: http://dmwit.com/yeganesh/ + +## Implementation + +Other than being decoupled from dmenu, another improvement I though that could be made on top of yeganesh is the programming language choice. +Instead of Haskell, I went with POSIX sh. +Sticking to POSIX sh makes it require less build-time dependencies. There aren't any, actually. Packaging is made much easier due to that. + +The good thing is that the program itself is small enough ([119 lines][119-lines] on v0.1.0) that POSIX sh does the job just fine, combined with other POSIX utilities such as [getopts][getopts], [sort][sort] and [awk][awk]. + +[119-lines]: https://euandre.org/git/remembering/tree/remembering?id=v0.1.0 +[getopts]: http://www.opengroup.org/onlinepubs/9699919799/utilities/getopts.html +[sort]: http://www.opengroup.org/onlinepubs/9699919799/utilities/sort.html +[awk]: http://www.opengroup.org/onlinepubs/9699919799/utilities/awk.html + +The behaviour is: given a program that will read from STDIN and write a single entry to STDOUT, `remembering` wraps that program, and rearranges STDIN so that previous choices appear at the beginning. + +Where you would do: + +```shell +$ seq 5 | fzf + + 5 + 4 + 3 + 2 +> 1 + 5/5 +> +``` + +And every time get the same order of numbers, now you can write: + +```shell +$ seq 5 | remembering -p seq-fzf -c fzf + + 5 + 4 + 3 + 2 +> 1 + 5/5 +> +``` + +On the first run, everything is the same. If you picked 4 on the previous example, the following run would be different: + +```shell +$ seq 5 | remembering -p seq-fzf -c fzf + + 5 + 3 + 2 + 1 +> 4 + 5/5 +> +``` + +As time passes, the list would adjust based on the frequency of your choices. + +I aimed for reusability, so that I could wrap diverse commands with `remembering` and it would be able to work. To accomplish that, a "profile" (the `-p something` part) stores data about different runs separately. + +I took the idea of building something small with few dependencies to other places too: +- the manpages are written in troff directly; +- the tests are just more POSIX sh files; +- and a POSIX Makefile to `check` and `install`. + +I was aware of the value of sticking to coding to standards, but I had past experience mostly with programming language standards, such as ECMAScript, Common Lisp, Scheme, or with IndexedDB or DOM APIs. +It felt good to rediscover these nice POSIX tools, which makes me remember of a quote by [Henry Spencer][poor-unix]: + +> Those who do not understand Unix are condemned to reinvent it, poorly. + +[poor-unix]: https://en.wikipedia.org/wiki/Henry_Spencer#cite_note-3 + +## Usage examples + +Here are some functions I wrote myself that you may find useful: + +### Run a command with fzf on `$PWD` + +```shellcheck +f() { + profile="$f-shell-function(pwd | sed -e 's_/_-_g')" + file="$(git ls-files | \ + remembering -p "$profile" \ + -c "fzf --select-1 --exit -0 --query \"$2\" --preview 'cat {}'")" + if [ -n "$file" ]; then + # shellcheck disable=2068 + history -s f $@ + history -s "$1" "$file" + "$1" "$file" +fi +} +``` + +This way I can run `f vi` or `f vi config` at the root of a repository, and the list of files will always appear on the most used order. +Adding `pwd` to the profile allows it to not mix data for different repositories. + +### Copy password to clipboard + +```shell +choice="$(find "$HOME/.password-store" -type f | \ + grep -Ev '(.git|.gpg-id)' | \ + sed -e "s|$HOME/.password-store/||" -e 's/\.gpg$//' | \ + remembering -p password-store \ + -c 'dmenu -l 20 -i')" + + +if [ -n "$choice" ]; then + pass show "$choice" -c +fi +``` + +Adding the above to a file and binding it to a keyboard shortcut, I can access the contents of my [password store][password-store], with the entries ordered by usage. + +[password-store]: https://www.passwordstore.org/ + +### Replacing yeganesh + +Where I previously had: + +```shell +exe=$(yeganesh -x) && exec $exe +``` + +Now I have: + +```shell +exe=$(dmenu_path | remembering -p dmenu-exec -c dmenu) && exec $exe +``` + +This way, the executables appear on order of usage. + +If you don't have `dmenu_path`, you can get just the underlying `stest` tool that looks at the executables available in your `$PATH`. Here's a juicy one-liner to do it: + +```shell +$ wget -O- https://dl.suckless.org/tools/dmenu-5.0.tar.gz | \ + tar Ozxf - dmenu-5.0/arg.h dmenu-5.0/stest.c | \ + sed 's|^#include "arg.h"$|// #include "arg.h"|' | \ + cc -xc - -o stest +``` + +With the `stest` utility you'll be able to list executables in your `$PATH` and pipe them to dmenu or something else yourself: +```shell +$ (IFS=:; ./stest -flx $PATH;) | sort -u | remembering -p another-dmenu-exec -c dmenu | sh +``` + +In fact, the code for `dmenu_path` is almost just like that. + +## Conclusion + +For my personal use, I've [packaged] `remembering` for GNU Guix and Nix. Packaging it to any other distribution should be trivial, or just downloading the tarball and running `[sudo] make install`. + +Patches welcome! + +[packaged]: https://euandre.org/git/package-repository/ +[nix-file]: https://euandre.org/git/dotfiles/tree/nixos/not-on-nixpkgs/remembering.nix?id=0831444f745cf908e940407c3e00a61f6152961f diff --git a/v2/src/content/en/tils/lisp-three-way-conditional.md b/v2/src/content/en/til/lisp-three-way-conditional.md index 20fbd09..20fbd09 100644 --- a/v2/src/content/en/tils/lisp-three-way-conditional.md +++ b/v2/src/content/en/til/lisp-three-way-conditional.md diff --git a/v2/src/content/pt/hea/condicional-ternario-lisp.md b/v2/src/content/pt/hea/condicional-ternario-lisp.md new file mode 100644 index 0000000..6971827 --- /dev/null +++ b/v2/src/content/pt/hea/condicional-ternario-lisp.md @@ -0,0 +1,65 @@ +--- + +title: Three-way conditional for number signs on Lisp + +date: 2021-04-24 3 + +update: 2021-08-14 + +categories: lisp scheme common-lisp + +--- + +A useful macro from Paul Graham's [On Lisp][on-lisp] book: + +```lisp +(defmacro nif (expr pos zero neg) + (let ((g (gensym))) + `(let ((,g ,expr)) + (cond ((plusp ,g) ,pos) + ((zerop ,g) ,zero) + (t ,neg))))) +``` + +After I looked at this macro, I started seeing opportunities to using it in +many places, and yet I didn't see anyone else using it. + +The latest example I can think of is section 1.3.3 of [Structure and +Interpretation of Computer Programs][sicp], which I was reading recently: + +```scheme +(define (search f neg-point pos-point) + (let ((midpoint (average neg-point pos-point))) + (if (close-enough? neg-point post-point) + midpoint + (let ((test-value (f midpoint))) + (cond ((positive? test-value) + (search f neg-point midpoint)) + ((negative? test-value) + (search f midpoint pos-point)) + (else midpoint)))))) +``` + +Not that the book should introduce such macro this early, but I couldn't +avoid feeling bothered by not using the `nif` macro, which could even remove +the need for the intermediate `test-value` variable: + +```scheme +(define (search f neg-point pos-point) + (let ((midpoint (average neg-point pos-point))) + (if (close-enough? neg-point post-point) + midpoint + (nif (f midpoint) + (search f neg-point midpoint) + (midpoint) + (search f midpoint pos-point))))) +``` + +It also avoids `cond`'s extra clunky parentheses for grouping, which is +unnecessary but built-in. + +As a macro, I personally feel it tilts the balance towards expressivenes +despite its extra cognitive load toll. + +[on-lisp]: http://www.paulgraham.com/onlisptext.html [sicp]: +https://mitpress.mit.edu/sites/default/files/sicp/index.html diff --git a/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md b/v2/src/content/pt/pastebin/exercicios-sicp-e-19.md index 89dacfd..89dacfd 100644 --- a/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md +++ b/v2/src/content/pt/pastebin/exercicios-sicp-e-19.md diff --git a/v2/src/content/pt/sobre.md b/v2/src/content/pt/sobre.page index aac3e67..aac3e67 100644 --- a/v2/src/content/pt/sobre.md +++ b/v2/src/content/pt/sobre.page diff --git a/v2/src/lib/base.en.conf b/v2/src/lib/base.en.conf index 5ced00a..bc90b10 100644 --- a/v2/src/lib/base.en.conf +++ b/v2/src/lib/base.en.conf @@ -4,30 +4,41 @@ export site_name="EuAndreh's website" export lang='en' -export index_pastebins_title='Pastebins' +export about='About' -export index_recent_pastebins_title='Pastebins listing' +export about_url_name='about.html' -export index_category_pastebins_title='Pastebins by category' +export by_category_url_name='by-category.html' -export index by_category_url_part='by-category.html' +export homepage_url="$(url-for "$lang/")" -export feed_pastebins_title="EuAndreh's pastebins" +export homepage_url_absolute="$(absolute "$homepage_url")" -export index_tils_title='TIL' +export about_url="$(url-for "$lang/$about_url_name")" -export index_recent_tils_title='TIL listing' -export index_category_tils_title='TIL by category' +export index__title='Blog' -export feed_tils_title="EuAndreh's TIL" +export index_recent__title='Recent articles' -export about='About' +export index_category__title='Articles by category' -export about_url_name='about.html' +export feed__title="EuAndreh's articles" -export homepage_url="$(url-for "$lang/")" -export homepage_url_absolute="$(absolute "$homepage_url")" +export index_pastebin_title='Pastebins' -export about_url="$(url-for "$lang/$about_url_name")" +export index_recent_pastebin_title='Pastebins listing' + +export index_category_pastebin_title='Pastebins by category' + +export feed_pastebin_title="EuAndreh's pastebins" + + +export index_til_title='TIL' + +export index_recent_til_title='TIL listing' + +export index_category_til_title='TIL by category' + +export feed_til_title="EuAndreh's TIL" diff --git a/v2/src/lib/base.pt.conf b/v2/src/lib/base.pt.conf index fe03f42..5703bed 100644 --- a/v2/src/lib/base.pt.conf +++ b/v2/src/lib/base.pt.conf @@ -4,30 +4,41 @@ export site_name="EuAndreh's website" export lang='pt' -export index_pastebins_title='Pastebins' +export about='About' -export index_recent_pastebins_title='Pastebins listing' +export about_url_name='sobre.html' -export index_category_pastebins_title='Pastebins by category' +export by_category_url_name='por-categoria.html' -export index by_category_url_part='by-category.html' +export homepage_url="$(url-for "$lang/")" -export feed_pastebins_title="EuAndreh's pastebins" +export homepage_url_absolute="$(absolute "$homepage_url")" -export index_tils_title='TIL' +export about_url="$(url-for "$lang/$about_url_name")" -export index_recent_tils_title='TIL listing' -export index_category_tils_title='TIL by category' +export index__title='Blog' -export feed_tils_title="EuAndreh's TIL" +export index_recent__title='Artigos recentes' -export about='About' +export index_category__title='Artigos por categoria' -export about_url_name='about.html' +export feed__title="Artigos do EuAndreh" -export homepage_url="$(url-for "$lang/")" -export homepage_url_absolute="$(absolute "$homepage_url")" +export index_pastebin_title='Pastebins' -export about_url="$(url-for "$lang/$about_url_name")" +export index_recent_pastebin_title='Pastebins listing' + +export index_category_pastebin_title='Pastebins by category' + +export feed_pastebin_title="EuAndreh's pastebins" + + +export index_til_title='HEA' + +export index_recent_til_title='HEA recentes' + +export index_category_til_title='HEA por categoria' + +export feed_til_title="HEA do EuAndreh" diff --git a/v2/src/lib/commencement.en.conf b/v2/src/lib/commencement.en.conf new file mode 100644 index 0000000..9b19b18 --- /dev/null +++ b/v2/src/lib/commencement.en.conf @@ -0,0 +1,7 @@ +#!/bin/sh + +export article_collection_name='' + +export pastebin_collection_name='pastebin' + +export til_collection_name='til' diff --git a/v2/src/lib/commencement.pt.conf b/v2/src/lib/commencement.pt.conf new file mode 100644 index 0000000..e3b9544 --- /dev/null +++ b/v2/src/lib/commencement.pt.conf @@ -0,0 +1,7 @@ +#!/bin/sh + +export article_collection_name='' + +export pastebin_collection_name='pastebin' + +export til_collection_name='hea' |