From 1fc994f588dd9ef2ef8395e57e2492a6b4d730eb Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Sun, 16 Jan 2022 16:52:43 -0300 Subject: git mv locale/ po/ --- .../_tils/2020-08-12-simple-filename-timestamp.po | 68 ++++++ ...8-13-anchor-headers-and-code-lines-in-jekyll.po | 187 ++++++++++++++++ ...browse-a-git-repository-at-a-specific-commit.po | 119 ++++++++++ .../LC_MESSAGES/_tils/2020-08-16-search-in-git.po | 89 ++++++++ .../_tils/2020-08-28-grep-online-repositories.po | 184 +++++++++++++++ ...ls-using-the-command-line-for-fun-and-profit.po | 98 ++++++++ ...05-pull-requests-with-git-the-old-school-way.po | 164 ++++++++++++++ ...changes-to-a-filename-pattern-in-git-history.po | 63 ++++++ .../2020-11-08-find-broken-symlinks-with-find.po | 51 +++++ ...2-diy-bare-bones-ci-server-with-bash-and-nix.po | 129 +++++++++++ .../_tils/2020-11-12-git-bisect-automation.po | 53 +++++ .../_tils/2020-11-12-useful-bash-variables.po | 94 ++++++++ ...1-14-gpodder-as-a-media-subscription-manager.po | 49 ++++ .../2020-11-30-storing-ci-data-on-git-notes.po | 149 ++++++++++++ ...ippet-shellcheck-all-scripts-in-a-repository.po | 240 ++++++++++++++++++++ po/fr/LC_MESSAGES/_tils/2020-12-29-svg-favicon.po | 168 ++++++++++++++ ...-send-email-to-multiple-recipients-with-curl.po | 249 +++++++++++++++++++++ .../_tils/2021-01-17-posix-sh-and-shebangs.po | 97 ++++++++ .../_tils/2021-04-24-clojure-auto-curry.po | 220 ++++++++++++++++++ ...order-parameterization-of-a-generic-function.po | 210 +++++++++++++++++ ...04-24-three-way-conditional-for-number-signs.po | 95 ++++++++ 21 files changed, 2776 insertions(+) create mode 100644 po/fr/LC_MESSAGES/_tils/2020-08-12-simple-filename-timestamp.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-08-13-anchor-headers-and-code-lines-in-jekyll.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-08-16-search-in-git.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-08-28-grep-online-repositories.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-09-04-send-emails-using-the-command-line-for-fun-and-profit.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-10-11-search-changes-to-a-filename-pattern-in-git-history.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-08-find-broken-symlinks-with-find.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-12-diy-bare-bones-ci-server-with-bash-and-nix.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-12-git-bisect-automation.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-12-useful-bash-variables.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-14-gpodder-as-a-media-subscription-manager.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-11-30-storing-ci-data-on-git-notes.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.po create mode 100644 po/fr/LC_MESSAGES/_tils/2020-12-29-svg-favicon.po create mode 100644 po/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po create mode 100644 po/fr/LC_MESSAGES/_tils/2021-01-17-posix-sh-and-shebangs.po create mode 100644 po/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po create mode 100644 po/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po create mode 100644 po/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po (limited to 'po/fr/LC_MESSAGES/_tils') diff --git a/po/fr/LC_MESSAGES/_tils/2020-08-12-simple-filename-timestamp.po b/po/fr/LC_MESSAGES/_tils/2020-08-12-simple-filename-timestamp.po new file mode 100644 index 0000000..ef8e489 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-08-12-simple-filename-timestamp.po @@ -0,0 +1,68 @@ +# +msgid "" +msgstr "" + +msgid "" +"When writing Jekyll posts or creating log files with dates on them, I " +"usually struggle with finding a direct way of accomplishing that. There's a " +"simple solution: `date -I`." +msgstr "" + +msgid "" +"Using this built-in GNU/Linux tool allows you to `touch $(date -I).md` to " +"readily create a `2020-08-12.md` file." +msgstr "" + +msgid "" +"I always had to read `man date` or search the web over and over, and after " +"doing this repeatedly it became clear that both `date -I` and `date -Is` " +"(`s` here stands for seconds) are the thing that I'm looking for 95% of the " +"time:" +msgstr "" + +msgid "" +"Both date formats are hierarchical, having the bigger time intervals to the " +"left. This means that you can easily sort them (and even tab-complete them) " +"with no extra effort or tool required." +msgstr "" + +msgid "title: Simple filename timestamp" +msgstr "" + +msgid "date: 2020-08-12" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: simple-filename-timestamp" +msgstr "" + +msgid "updated_at:" +msgstr "" + +msgid "" +"./my-program.sh > my-program.$(date -I).log\n" +"cp post-template.md _posts/$(date -I)-post-slug.md\n" +msgstr "" + +msgid "" +"# inside my-program.sh\n" +"echo \"Program started at $(date -Is)\"\n" +"# output is:\n" +"# Program started at 2020-08-12T09:04:58-03:00\n" +msgstr "" + +msgid "eu_categories: shell" +msgstr "" + +#~ msgid "" +#~ "title: Simple filename timestamp\n" +#~ "date: 2020-08-12\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: simple-filename-timestamp" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-08-13-anchor-headers-and-code-lines-in-jekyll.po b/po/fr/LC_MESSAGES/_tils/2020-08-13-anchor-headers-and-code-lines-in-jekyll.po new file mode 100644 index 0000000..a11e17c --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-08-13-anchor-headers-and-code-lines-in-jekyll.po @@ -0,0 +1,187 @@ +# +msgid "" +msgstr "" + +msgid "" +"title: Anchor headers and code lines in Jekyll\n" +"date: 2020-08-13\n" +"layout: post\n" +"lang: en\n" +"ref: anchor-headers-and-code-lines-in-jekyll" +msgstr "" + +msgid "" +"The default Jekyll toolbox ([Jekyll](https://jekyllrb.com/), " +"[kramdown](https://kramdown.gettalong.org/) and " +"[rouge](http://rouge.jneen.net/)) doesn't provide with a configuration " +"option to add anchors to headers and code blocks." +msgstr "" + +msgid "" +"The best way I found of doing this is by creating a simple Jekyll plugin, " +"more specifically, a [Jekyll " +"hook](https://jekyllrb.com/docs/plugins/hooks/). These allow you to jump in " +"to the Jekyll build and add a processing stage before of after Jekyll " +"performs something." +msgstr "" + +msgid "" +"All you have to do is add the code to `_plugins/my-jekyll-plugin-code.rb`, " +"and Jekyll knows to pick it up and call your code on the appropriate time." +msgstr "" + +msgid "Anchor on headers" +msgstr "" + +msgid "" +"Since I wanted to add anchors to headers in all documents, this Jekyll hook " +"works on `:documents` after they have been transformed into HTML, the " +"`:post_render` phase:" +msgstr "" + +msgid "" +"I've derived my implementations from two \"official\"[^official] hooks, " +"[jemoji](https://github.com/jekyll/jemoji) and [jekyll-" +"mentions](https://github.com/jekyll/jekyll-mentions)." +msgstr "" + +msgid "" +"[^official]: I don't know how official they are, I just assumed it because " +"they live in the same organization inside GitHub that Jekyll does." +msgstr "" + +msgid "" +"All I did was to wrap the header tag inside an ``, and set the `href` of " +"that `` to the existing id of the header. Before the hook the HTML looks " +"like:" +msgstr "" + +msgid "And after the hook should turn that into:" +msgstr "" + +msgid "" +"The used regexp tries to match only h1-h6 tags, and keep the rest of the " +"HTML attributes untouched, since this isn't a general HTML parser, but the " +"generated HTML is somewhat under your control. Use at your own risk because " +"[you shouldn't parse HTML with " +"regexps](https://stackoverflow.com/questions/1732348/regex-match-open-tags-" +"except-xhtml-self-contained-tags/1732454#1732454). Also I used this strategy" +" in my environment, where no other plugins are installed. I haven't " +"considered how this approach may conflict with other Jekyll plugins." +msgstr "" + +msgid "" +"In the new anchor tag you can add your custom CSS class to style it as you " +"wish." +msgstr "" + +msgid "Anchor on code blocks" +msgstr "" + +msgid "" +"Adding anchors to code blocks needs a little bit of extra work, because line" +" numbers themselves don't have preexisting ids, so we need to generate them " +"without duplications between multiple code blocks in the same page." +msgstr "" + +msgid "" +"Similarly, this Jekyll hook also works on `:documents` in the `:post_render`" +" phase:" +msgstr "" + +msgid "" +"This solution assumes the default Jekyll toolbox with code line numbers " +"turned on in `_config.yml`:" +msgstr "" + +msgid "" +"The anchors go from B1-L1 to BN-LN, using the `code_block_counter` to track " +"which code block we're in and don't duplicate anchor ids. Before the hook " +"the HTML looks like:" +msgstr "" + +msgid "Happy writing :)" +msgstr "" + +msgid "" +"Jekyll::Hooks.register :documents, :post_render do |doc|\n" +" if doc.output_ext == \".html\"\n" +" doc.output =\n" +" doc.output.gsub(\n" +" /(.*?)<\\/h[1-6]>/,\n" +" '\\5'\n" +" )\n" +" end\n" +"end\n" +msgstr "" + +msgid "" +"...some unmodified text...\n" +"

\n" +" My header\n" +"

\n" +"...more unmodified text...\n" +msgstr "" + +msgid "" +"...some unmodified text...\n" +"\n" +"

\n" +" My header\n" +"

\n" +"
\n" +"...more unmodified text...\n" +msgstr "" + +msgid "" +"PREFIX = '
'\n"
+"POSTFIX = '
'\n" +"Jekyll::Hooks.register :documents, :post_render do |doc|\n" +" if doc.output_ext == \".html\"\n" +" code_block_counter = 1\n" +" doc.output = doc.output.gsub(/
[\\n0-9]+<\\/pre>/) do |match|\n"
+"      line_numbers = match\n"
+"                      .gsub(/
([\\n0-9]+)<\\/pre>/, '\\1')\n"
+"                      .split(\"\\n\")\n"
+"\n"
+"      anchored_line_numbers_array = line_numbers.map do |n|\n"
+"        id = \"B#{code_block_counter}-L#{n}\"\n"
+"        \"#{n}\"\n"
+"      end\n"
+"      code_block_counter += 1\n"
+"\n"
+"      PREFIX + anchored_line_numbers_array.join(\"\\n\") + POSTFIX\n"
+"    end\n"
+"  end\n"
+"end\n"
+msgstr ""
+
+msgid ""
+"kramdown:\n"
+"  syntax_highlighter_opts:\n"
+"    span:\n"
+"      line_numbers: false\n"
+"    block:\n"
+"      line_numbers: true\n"
+msgstr ""
+
+msgid ""
+"...some unmodified text...\n"
+"
1\n"
+"2\n"
+"3\n"
+"4\n"
+"5\n"
+"
\n" +"...more unmodified text...\n" +msgstr "" + +msgid "" +"...some unmodified text...\n" +"
1\n"
+"2\n"
+"3\n"
+"4\n"
+"5
\n" +"...more unmodified text...\n" +msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po b/po/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po new file mode 100644 index 0000000..6030e0c --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po @@ -0,0 +1,119 @@ +# +msgid "" +msgstr "" + +msgid "" +"I commonly use tools like `git log` together with `git show` when inspecting" +" past changes in a repository:" +msgstr "" + +msgid "" +"But I also wanted to not only be able to look at the diff of a specific " +"commit, but to browse the whole repository at that specific commit." +msgstr "" + +msgid "" +"I used to accomplish it the \"brute force\" way: clone the whole repository " +"in another folder and checkout the commit there:" +msgstr "" + +msgid "" +"But git itself allows we to specific the directory of the checkout by using " +"the `--work-tree` global git flag. This is what `man git` says about it:" +msgstr "" + +msgid "" +"So it allows us to set the desired path of the working tree. So if we want " +"to copy the contents of the current working tree into `copy/`:" +msgstr "" + +msgid "" +"After that `copy/` will contain a replica of the code in HEAD. But to " +"checkout a specific, we need some extra parameters:" +msgstr "" + +msgid "" +"There's an extra `-- .` at the end, which initially looks like we're sending" +" Morse signals to git, but we're actually saying to `git-checkout` which sub" +" directory of `` we want to look at. Which means we can do " +"something like:" +msgstr "" + +msgid "" +"And with that `` will only contain what was inside `src/` at " +"``." +msgstr "" + +msgid "" +"After any of those checkouts, you have to `git reset .` to reset your " +"current staging area back to what it was before the checkout." +msgstr "" + +msgid "" +"[GIT: Checkout to a specific folder](https://stackoverflow.com/a/16493707) " +"(StackOverflow)" +msgstr "" + +msgid "" +"git log\n" +"# search for a the commit I'm looking for\n" +"git show \n" +"# see the diff for the commit\n" +msgstr "" + +msgid "" +"git clone /tmp/tmp-repo-clone\n" +"cd /tmp-repo-clone\n" +"git checkout \n" +msgstr "" + +msgid "" +"--work-tree=\n" +" Set the path to the working tree. It can be an absolute path or a path relative to the current working\n" +" directory. This can also be controlled by setting the GIT_WORK_TREE environment variable and the\n" +" core.worktree configuration variable (see core.worktree in git-config(1) for a more detailed\n" +" discussion).\n" +msgstr "" + +msgid "" +"mkdir copy\n" +"git --work-tree=copy/ checkout .\n" +msgstr "" + +msgid "git --work-tree= checkout -- .\n" +msgstr "" + +msgid "git --work-tree= checkout -- src/\n" +msgstr "" + +msgid "title: Browse a git repository at a specific commit" +msgstr "" + +msgid "date: 2020-08-14" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: browse-a-git-repository-at-a-specific-commit" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +msgid "References" +msgstr "" + +#~ msgid "References:" +#~ msgstr "" + +#~ msgid "" +#~ "title: Browse a git repository at a specific commit\n" +#~ "date: 2020-08-14\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: browse-a-git-repository-at-a-specific-commit" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-08-16-search-in-git.po b/po/fr/LC_MESSAGES/_tils/2020-08-16-search-in-git.po new file mode 100644 index 0000000..7b1c6cc --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-08-16-search-in-git.po @@ -0,0 +1,89 @@ +# +msgid "" +msgstr "" + +msgid "Here's a useful trio to know about to help you search things in git:" +msgstr "" + +msgid "`git show `" +msgstr "" + +msgid "`git log --grep=''`" +msgstr "" + +msgid "`git grep '' [commit]`" +msgstr "" + +msgid "1. `git show `" +msgstr "" + +msgid "Show a specific commit and it's diff:" +msgstr "" + +msgid "2. `git log --grep=''`" +msgstr "" + +msgid "Search through the commit messages:" +msgstr "" + +msgid "3. `git grep '' [commit]`" +msgstr "" + +msgid "Search content in git history:" +msgstr "" + +msgid "" +"And if you find an occurrence of the regexp in a specific commit and you " +"want to browse the repository in that point in time, you can [use git " +"checkout for that][0]." +msgstr "" + +msgid "" +"[0]: {% link _tils/2020-08-14-browse-a-git-repository-at-a-specific-" +"commit.md %}" +msgstr "" + +msgid "" +"git show\n" +"# shows the latest commit\n" +"git show \n" +"# shows an specific \n" +"git show v1.2\n" +"# shows commit tagged with v1.2\n" +msgstr "" + +msgid "git log --grep='refactor'\n" +msgstr "" + +msgid "" +"git grep 'TODO'\n" +"# search the repository for the \"TODO\" string\n" +"git grep 'TODO' $(git rev-list --all)\n" +"# search the whole history for \"TODO\" string\n" +msgstr "" + +msgid "title: Search in git" +msgstr "" + +msgid "date: 2020-08-16" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: search-in-git" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +#~ msgid "" +#~ "title: Search in git\n" +#~ "date: 2020-08-16\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: search-in-git" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-08-28-grep-online-repositories.po b/po/fr/LC_MESSAGES/_tils/2020-08-28-grep-online-repositories.po new file mode 100644 index 0000000..a339bb6 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-08-28-grep-online-repositories.po @@ -0,0 +1,184 @@ +# +msgid "" +msgstr "" + +msgid "" +"I often find interesting source code repositories online that I want to grep" +" for some pattern but I can't, because either:" +msgstr "" + +msgid "" +"the repository is on [cgit](https://git.zx2c4.com/cgit/) or a similar code " +"repository that doesn't allow search in files, or;" +msgstr "" + +msgid "" +"the search function is really bad, and doesn't allow me to use regular " +"expressions for searching patterns in the code." +msgstr "" + +msgid "" +"Here's a simple script that allows you to overcome that problem easily:" +msgstr "" + +msgid "" +"It is a wrapper around `git grep` that downloads the repository when " +"missing. Save in a file called `git-search`, make the file executable and " +"add it to your path." +msgstr "" + +msgid "Overview:" +msgstr "" + +msgid "*lines 1~2*:" +msgstr "" + +msgid "" +"Bash shebang and the `set -eu` options to exit on error or undefined " +"variables." +msgstr "" + +msgid "*lines 4~30*:" +msgstr "" + +msgid "Usage text to be printed when providing less arguments than expected." +msgstr "" + +msgid "*line 33*:" +msgstr "" + +msgid "Extract the repository name from the URL, removing trailing slashes." +msgstr "" + +msgid "*lines 34~37*:" +msgstr "" + +msgid "Download the repository when missing and go to the folder." +msgstr "" + +msgid "*line 39*:" +msgstr "" + +msgid "Make the variable `$@` contain the rest of the unused arguments." +msgstr "" + +msgid "*line 40*:" +msgstr "" + +msgid "Perform `git grep`, forwarding the remaining arguments from `$@`." +msgstr "" + +msgid "Example output:" +msgstr "" + +msgid "" +"Subsequent greps on the same repository are faster because no download is " +"needed." +msgstr "" + +msgid "When no argument is provided, it prints the usage text:" +msgstr "" + +msgid "" +"#!/usr/bin/env bash\n" +"set -eu\n" +"\n" +"end=\"\\033[0m\"\n" +"red=\"\\033[0;31m\"\n" +"red() { echo -e \"${red}${1}${end}\"; }\n" +"\n" +"usage() {\n" +" red \"Missing argument $1.\\n\"\n" +" cat < \n" +"\n" +" Arguments:\n" +" REGEX_PATTERN Regular expression that \"git grep\" can search\n" +" REPOSITORY_URL URL address that \"git clone\" can download the repository from\n" +"\n" +"Examples:\n" +" Searching \"make get-git\" in cgit repository:\n" +" git search 'make get-git' https://git.zx2c4.com/cgit/\n" +" git search 'make get-git' https://git.zx2c4.com/cgit/ -- \\$(git rev-list --all)\n" +"EOF\n" +" exit 2\n" +"}\n" +"\n" +"\n" +"REGEX_PATTERN=\"${1:-}\"\n" +"REPOSITORY_URL=\"${2:-}\"\n" +"[[ -z \"${REGEX_PATTERN}\" ]] && usage 'REGEX_PATTERN'\n" +"[[ -z \"${REPOSITORY_URL}\" ]] && usage 'REPOSITORY_URL'\n" +"\n" +"mkdir -p /tmp/git-search\n" +"DIRNAME=\"$(echo \"${REPOSITORY_URL%/}\" | rev | cut -d/ -f1 | rev)\"\n" +"if [[ ! -d \"/tmp/git-search/${DIRNAME}\" ]]; then\n" +" git clone \"${REPOSITORY_URL}\" \"/tmp/git-search/${DIRNAME}\"\n" +"fi\n" +"pushd \"/tmp/git-search/${DIRNAME}\"\n" +"\n" +"shift 3 || shift 2 # when \"--\" is missing\n" +"git grep \"${REGEX_PATTERN}\" \"${@}\"\n" +msgstr "" + +msgid "" +"$ git search 'make get-git' https://git.zx2c4.com/cgit/\n" +"Clonage dans '/tmp/git-search/cgit'...\n" +"remote: Enumerating objects: 542, done.\n" +"remote: Counting objects: 100% (542/542), done.\n" +"remote: Compressing objects: 100% (101/101), done.\n" +"warning: object 51dd1eff1edc663674df9ab85d2786a40f7ae3a5: gitmodulesParse: could not parse gitmodules blob\n" +"remote: Total 7063 (delta 496), reused 446 (delta 441), pack-reused 6521\n" +"Réception d'objets: 100% (7063/7063), 8.69 Mio | 5.39 Mio/s, fait.\n" +"Résolution des deltas: 100% (5047/5047), fait.\n" +"/tmp/git-search/cgit ~/dev/libre/songbooks/docs\n" +"README: $ make get-git\n" +"\n" +"$ git search 'make get-git' https://git.zx2c4.com/cgit/\n" +"/tmp/git-search/cgit ~/dev/libre/songbooks/docs\n" +"README: $ make get-git\n" +msgstr "" + +msgid "" +"$ git search\n" +"Missing argument REGEX_PATTERN.\n" +"\n" +"Usage:\n" +" /home/andreh/dev/libre/dotfiles/scripts/ad-hoc/git-search \n" +"\n" +" Arguments:\n" +" REGEX_PATTERN Regular expression that \"git grep\" can search\n" +" REPOSITORY_URL URL address that \"git clone\" can download the repository from\n" +"\n" +"Examples:\n" +" Searching \"make get-git\" in cgit repository:\n" +" git search 'make get-git' https://git.zx2c4.com/cgit/\n" +" git search 'make get-git' https://git.zx2c4.com/cgit/ -- $(git rev-list --all)\n" +msgstr "" + +msgid "title: Grep online repositories" +msgstr "" + +msgid "date: 2020-08-28" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: grep-online-repositories" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +#~ msgid "" +#~ "title: Grep online repositories\n" +#~ "date: 2020-08-28\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: grep-online-repositories" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-09-04-send-emails-using-the-command-line-for-fun-and-profit.po b/po/fr/LC_MESSAGES/_tils/2020-09-04-send-emails-using-the-command-line-for-fun-and-profit.po new file mode 100644 index 0000000..1409e61 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-09-04-send-emails-using-the-command-line-for-fun-and-profit.po @@ -0,0 +1,98 @@ +# +msgid "" +msgstr "" + +msgid "" +"title: Send emails using the command line for fun and profit!\n" +"date: 2020-09-04\n" +"layout: post\n" +"lang: en\n" +"ref: send-emails-using-the-command-line-for-fun-and-profit" +msgstr "" + +msgid "Here are a few reasons why:" +msgstr "" + +msgid "" +"send yourself and other people notification of cronjobs, scripts runs, CI " +"jobs, *etc.*" +msgstr "" + +msgid "leverage the POSIX pipe `|`, and pipe emails away!" +msgstr "" + +msgid "because you can." +msgstr "" + +msgid "Reason 3 is the fun part, reasons 1 and 2 are the profit part." +msgstr "" + +msgid "" +"First [install and configure " +"SSMTP](https://wiki.archlinux.org/index.php/SSMTP) for using, say, Gmail as " +"the email server:" +msgstr "" + +msgid "" +"Now install [GNU Mailutils](https://mailutils.org/) (`sudo apt-get install " +"mailutils` or the equivalent on your OS), and send yourself your first " +"email:" +msgstr "" + +msgid "" +"And that's about it, you've got mail. Here are some more places where it " +"might be applicable:" +msgstr "" + +msgid "...and so on." +msgstr "" + +msgid "" +"You may consider adding a `alias mail='mail -aFrom:email@example.com'` so " +"you don't keep re-entering the \"From: \" part." +msgstr "" + +msgid "Send yourself some emails to see it working!" +msgstr "" + +msgid "" +"# file /etc/ssmtp/ssmtp.conf\n" +"FromLineOverride=YES\n" +"MailHub=smtp.gmail.com:587\n" +"UseSTARTTLS=YES\n" +"UseTLS=YES\n" +"rewriteDomain=gmail.com\n" +"root=username@gmail.com\n" +"AuthUser=username\n" +"AuthPass=password\n" +msgstr "" + +msgid "echo body | mail -aFrom:email@example.com email@example.com -s subject\n" +msgstr "" + +msgid "" +"# report a backup cronjob, attaching logs\n" +"set -e\n" +"\n" +"finish() {\n" +" status=$?\n" +" if [[ $status = 0 ]]; then\n" +" STATUS=\"SUCCESS (status $status)\"\n" +" else\n" +" STATUS=\"FAILURE (status $status)\"\n" +" fi\n" +"\n" +" mail user@example.com \\\n" +" -s \"Backup job report on $(hostname): ${STATUS}\" \\\n" +" --content-type 'text/plain; charset=utf-8' \\\n" +" -A\"$LOG_FILE\" <<< 'The log report is in the attachment.'\n" +"}\n" +"trap finish EXIT\n" +"\n" +"do-long-backup-cmd-here\n" +msgstr "" + +msgid "" +"# share the output of a cmd with someone\n" +"some-program | mail someone@example.com -s \"The weird logs that I was talking about\"\n" +msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po b/po/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po new file mode 100644 index 0000000..4b43e70 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po @@ -0,0 +1,164 @@ +# +msgid "" +msgstr "" + +msgid "" +"It might be news to you, as it was to me, that \"pull requests\" that you " +"can create on a Git hosting provider's web UI[^pr-webui] like " +"GitLab/Bitbucket/GitHub actually comes from Git itself: `git request-pull`." +msgstr "" + +msgid "" +"[^pr-webui]: And maybe even using the Git hosting provider's API from the " +"command line!" +msgstr "" + +msgid "" +"At the very core, they accomplish the same thing: both the original and the " +"web UI ones are ways for you to request the project maintainers to pull in " +"your changes from your fork. It's like saying: \"hi there, I did some " +"changes on my clone of the repository, what do you think about bringing " +"those in?\"." +msgstr "" + +msgid "" +"The only difference is that you're working with only Git itself, so you're " +"not tied to any Git hosting provider: you can send pull requests across them" +" transparently! You could even use your own " +"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked in by" +" any of them, putting the \"D\" back in \"DVCS\": it's a **distributed** " +"version control system." +msgstr "" + +msgid "`git request-pull` introduction" +msgstr "" + +msgid "Here's the raw output of a `git request-pull`:" +msgstr "" + +msgid "" +"That very first line is saying: \"create me a pull request with only a " +"single commit, defined by `HEAD`, and use the URL defined by `public-" +"origin`\"." +msgstr "" + +msgid "" +"Here's a pitfall: you may try using your `origin` remote at first where I " +"put `public-origin`, but that is many times pointing to something like " +"`git@example.com`, or `git.example.com:repo.git` (check that with `git " +"remote -v | grep origin`). On both cases those are addresses available for " +"interaction via SSH, and it would be better if your pull requests used an " +"address ready for public consumption." +msgstr "" + +msgid "" +"A simple solution for that is for you to add the `public-origin` alias as " +"the HTTPS alternative to the SSH version:" +msgstr "" + +msgid "Every Git hosting provider exposes repositories via HTTPS." +msgstr "" + +msgid "Experiment it yourself, and get acquainted with the CLI." +msgstr "" + +msgid "Delivering decentralized pull requests" +msgstr "" + +msgid "" +"Now that you can create the content of a pull request, you can just [deliver" +" it][cli-email] to the interested parties email:" +msgstr "" + +msgid "" +"[cli-email]: {% link _tils/2020-09-04-send-emails-using-the-command-line-" +"for-fun-and-profit.md %}" +msgstr "" + +msgid "Conclusion" +msgstr "" + +msgid "" +"In practice, I've never used or seen anyone use pull requests this way: " +"everybody is just [sending patches via " +"email](https://drewdevault.com/2018/07/23/Git-is-already-distributed.html)." +msgstr "" + +msgid "" +"If you stop to think about this model, the problem of \"Git hosting " +"providers becoming too centralized\" is a non-issue, and \"Git federation\" " +"proposals are a less attractive as they may sound initially." +msgstr "" + +msgid "" +"Using Git this way is not scary or so weird as the first impression may " +"suggest. It is actually how Git was designed to be used." +msgstr "" + +msgid "Check `git help request-pull` for more info." +msgstr "" + +msgid "" +"$ git request-pull HEAD public-origin\n" +"The following changes since commit 302c9f2f035c0360acd4e13142428c100a10d43f:\n" +"\n" +" db post: Add link to email exchange (2020-09-03 21:23:55 -0300)\n" +"\n" +"are available in the Git repository at:\n" +"\n" +" https://euandreh.xyz/website.git/\n" +"\n" +"for you to fetch changes up to 524c646cdac4153e54f2163e280176adbc4873fa:\n" +"\n" +" db post: better pinpoint sqlite unsuitability (2020-09-03 22:08:56 -0300)\n" +"\n" +"----------------------------------------------------------------\n" +"EuAndreh (1):\n" +" db post: better pinpoint sqlite unsuitability\n" +"\n" +" _posts/2020-08-31-the-database-i-wish-i-had.md | 12 ++++++------\n" +" 1 file changed, 6 insertions(+), 6 deletions(-)\n" +msgstr "" + +msgid "$ git remote add public-origin https://example.com/user/repo\n" +msgstr "" + +msgid "" +"# send a PR with your last commit to the author's email\n" +"git request-pull HEAD public-origin | mail author@example.com -s \"PR: Add thing to repo\"\n" +"\n" +"# send a PR with your last 5 commits to the project's mailing\n" +"# list, including the patch\n" +"git request-pull HEAD~5 public-origin -p | \\\n" +" mail list@example.com -s \"PR: Add another thing to repo\"\n" +"\n" +"# send every commit that is new in \"other-branch\"\n" +"git request-pull master public-origin other-branch | \\\n" +" mail list@example.com -s 'PR: All commits from my \"other-brach\"'\n" +msgstr "" + +msgid "title: Pull requests with Git, the old school way" +msgstr "" + +msgid "date: 2020-09-05" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: pull-requests-with-git-the-old-school-way" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +#~ msgid "" +#~ "title: Pull requests with Git, the old school way\n" +#~ "date: 2020-09-05\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: pull-requests-with-git-the-old-school-way" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-10-11-search-changes-to-a-filename-pattern-in-git-history.po b/po/fr/LC_MESSAGES/_tils/2020-10-11-search-changes-to-a-filename-pattern-in-git-history.po new file mode 100644 index 0000000..baa0d1f --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-10-11-search-changes-to-a-filename-pattern-in-git-history.po @@ -0,0 +1,63 @@ +# +msgid "" +msgstr "" + +msgid "" +"This is [yet][git-til-1] [another][git-til-2] [\"search in Git\"][git-til-3]" +" TIL entry. You could say that Git has a unintuitive CLI, or that is it very" +" powerful." +msgstr "" + +msgid "" +"I wanted to search for an old file that I new that was in the history of the" +" repository, but was deleted some time ago. So I didn't really remember the " +"name, only bits of it." +msgstr "" + +msgid "" +"I immediately went to the list of TILs I had written on searching in Git, " +"but it wasn't readily obvious how to do it, so here it goes:" +msgstr "" + +msgid "" +"You could add globs before the pattern to match things on any directory, and" +" add our `-p` friend to promptly see the diffs:" +msgstr "" + +msgid "" +"[git-til-1]: {% link _tils/2020-08-14-browse-a-git-repository-at-a-specific-" +"commit.md %} [git-til-2]: {% link _tils/2020-08-16-search-in-git.md %} [git-" +"til-3]: {% link _tils/2020-08-28-grep-online-repositories.md %}" +msgstr "" + +msgid "git log -- *pattern*\n" +msgstr "" + +msgid "git log -p -- **/*pattern*\n" +msgstr "" + +msgid "title: Search changes to a filename pattern in Git history" +msgstr "" + +msgid "date: 2020-10-11" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: search-changes-to-a-filename-pattern-in-git-history" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +#~ msgid "" +#~ "title: Search changes to a filename pattern in Git history\n" +#~ "date: 2020-10-11\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: search-changes-to-a-filename-pattern-in-git-history" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-08-find-broken-symlinks-with-find.po b/po/fr/LC_MESSAGES/_tils/2020-11-08-find-broken-symlinks-with-find.po new file mode 100644 index 0000000..a61c474 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-08-find-broken-symlinks-with-find.po @@ -0,0 +1,51 @@ +# +msgid "" +msgstr "" + +msgid "The `find` command knows how to show broken symlinks:" +msgstr "" + +msgid "find . -xtype l\n" +msgstr "" + +msgid "" +"This was useful to me when combined with [Git Annex](https://git-" +"annex.branchable.com/). Its [`wanted`](https://git-annex.branchable.com/git-" +"annex-wanted/) option allows you to have a \"sparse\" checkout of the " +"content, and save space by not having to copy every annexed file locally:" +msgstr "" + +msgid "git annex wanted . 'exclude=Music/* and exclude=Videos/*'\n" +msgstr "" + +msgid "" +"You can `find` any broken symlinks outside those directories by querying " +"with Git Annex itself, but `find . -xtype l` works on other places too, " +"where broken symlinks might be a problem." +msgstr "" + +msgid "title: Find broken symlinks with \"find\"" +msgstr "" + +msgid "date: 2020-11-08" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: find-broken-symlinks-with-find" +msgstr "" + +msgid "eu_categories: shell" +msgstr "" + +#~ msgid "" +#~ "title: Find broken symlinks with \"find\"\n" +#~ "date: 2020-11-08\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: find-broken-symlinks-with-find" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-12-diy-bare-bones-ci-server-with-bash-and-nix.po b/po/fr/LC_MESSAGES/_tils/2020-11-12-diy-bare-bones-ci-server-with-bash-and-nix.po new file mode 100644 index 0000000..f1bf8af --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-12-diy-bare-bones-ci-server-with-bash-and-nix.po @@ -0,0 +1,129 @@ +# +msgid "" +msgstr "" + +msgid "title: DIY bare bones CI server with Bash and Nix" +msgstr "" + +msgid "date: 2020-11-12 3" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: diy-bare-bones-ci-server-with-bash-and-nix" +msgstr "" + +msgid "" +"With a server with Nix installed (no need for NixOS), you can leverage its " +"build isolation for running CI jobs by adding a [post-receive](https://git-" +"scm.com/book/en/v2/Customizing-Git-Git-Hooks) Git hook to the server." +msgstr "" + +msgid "" +"In most of my project I like to keep a `test` attribute which runs the test " +"with `nix-build -A test`. This way, a post-receive hook could look like:" +msgstr "" + +msgid "" +"We initially (lines #5 to #8) create a log file, named after *when* the run " +"is running and for *which* commit it is running for. The `exec` and `tee` " +"combo allows the output of the script to go both to `stdout` *and* the log " +"file. This makes the logs output show up when you do a `git push`." +msgstr "" + +msgid "" +"Lines #10 to #13 create a fresh clone of the repository and line #20 runs " +"the test command." +msgstr "" + +msgid "Upsides" +msgstr "" + +msgid "No vendor lock-in, as all you need is a server with Nix installed." +msgstr "" + +msgid "" +"And if you pin the Nixpkgs version you're using, this very simple setup " +"yields extremely sandboxed runs on a very hermetic environment." +msgstr "" + +msgid "Downsides" +msgstr "" + +msgid "" +"Besides the many missing shiny features of this very simplistic CI, `nix-" +"build` can be very resource intensive. Specifically, it consumes too much " +"memory. So if it has to download too many things, or the build closure gets " +"too big, the server might very well run out of memory." +msgstr "" + +msgid "" +"#!/usr/bin/env bash\n" +"set -Eeuo pipefail\n" +"set -x\n" +"\n" +"LOGS_DIR=\"/data/static/ci-logs/libedn\"\n" +"mkdir -p \"$LOGS_DIR\"\n" +"LOGFILE=\"${LOGS_DIR}/$(date -Is)-$(git rev-parse master).log\"\n" +"exec &> >(tee -a \"${LOGFILE}\")\n" +"\n" +"unset GIT_DIR\n" +"CLONE=\"$(mktemp -d)\"\n" +"git clone . \"$CLONE\"\n" +"pushd \"$CLONE\"\n" +"\n" +"finish() {\n" +" printf \"\\n\\n>>> exit status was %s\\n\" \"$?\"\n" +"}\n" +"trap finish EXIT\n" +"\n" +"nix-build -A test\n" +msgstr "" + +msgid "eu_categories: ci" +msgstr "" + +msgid "" +"After using a similar post-receive hook for a while, I now even generate a " +"simple HTML file to make the logs available ([example " +"project](https://euandreh.xyz/remembering/ci.html)) through the browser." +msgstr "" + +#~ msgid "" +#~ "After using a similar post-receive hook for a while, I now even generate a " +#~ "simple HTML file to make the logs available ([example " +#~ "project](https://euandreh.xyz/remembering/)) through the browser." +#~ msgstr "" + +#~ msgid "" +#~ "After using a similar post-receive hook for a while, I now even generate a " +#~ "simple HTML file to make the [logs available](https://ci.euandreh.xyz/) " +#~ "through the browser." +#~ msgstr "" + +#~ msgid "" +#~ "#!/usr/bin/env bash\n" +#~ "set -Eeuo pipefail\n" +#~ "set -x\n" +#~ "\n" +#~ "LOGS_PREFIX=\"/data/static/ci-logs/libedn\"\n" +#~ "mkdir -p \"$LOGS_DIR\"\n" +#~ "LOGFILE=\"${LOGS_DIR}/$(date -Is)-$(git rev-parse master).log\"\n" +#~ "exec &> >(tee -a \"${LOGFILE}\")\n" +#~ "\n" +#~ "unset GIT_DIR\n" +#~ "CLONE=\"$(mktemp -d)\"\n" +#~ "git clone . \"$CLONE\"\n" +#~ "pushd \"$CLONE\"\n" +#~ "\n" +#~ "finish() {\n" +#~ " printf \"\\n\\n>>> exit status was %s\\n\" \"$?\"\n" +#~ "}\n" +#~ "trap finish EXIT\n" +#~ "\n" +#~ "nix-build -A test\n" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-12-git-bisect-automation.po b/po/fr/LC_MESSAGES/_tils/2020-11-12-git-bisect-automation.po new file mode 100644 index 0000000..09ec261 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-12-git-bisect-automation.po @@ -0,0 +1,53 @@ +# +msgid "" +msgstr "" + +msgid "title: Git bisect automation" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: git-bisect-automation" +msgstr "" + +msgid "" +"It is good to have an standardized way to run builds and tests on the " +"repository of a project, so that you can find when a bug was introduced by " +"using `git bisect run`." +msgstr "" + +msgid "" +"I've already been in the situation when a bug was introduced and I didn't " +"know how it even was occurring, and running Git bisect over hundreds of " +"commits to pinpoint the failing commit was very empowering:" +msgstr "" + +msgid "" +"$ GOOD_COMMIT_SHA=e1fd0a817d192c5a5df72dd7422e36558fa78e46\n" +"$ git bisect start HEAD $GOOD_COMMIT_SHA\n" +"$ git bisect run sn -c './build.sh && ./run-failing-case.sh'\n" +msgstr "" + +msgid "" +"Git will than do a binary search between the commits, and run the commands " +"you provide it with to find the failing commit." +msgstr "" + +msgid "" +"Instead of being afraid of doing a bisect, you should instead leverage it, " +"and make Git help you dig through the history of the repository to find the " +"bad code." +msgstr "" + +msgid "date: 2020-11-12 2" +msgstr "" + +msgid "eu_categories: git" +msgstr "" + +#~ msgid "date: 2020-11-12" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-12-useful-bash-variables.po b/po/fr/LC_MESSAGES/_tils/2020-11-12-useful-bash-variables.po new file mode 100644 index 0000000..6147dec --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-12-useful-bash-variables.po @@ -0,0 +1,94 @@ +# +msgid "" +msgstr "" + +msgid "title: Useful Bash variables" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: useful-bash-variables" +msgstr "" + +msgid "" +"[GNU Bash](https://www.gnu.org/software/bash/) has a few two letter " +"variables that may be useful when typing on the terminal." +msgstr "" + +msgid "`!!`: the text of the last command" +msgstr "" + +msgid "" +"The [`!!` " +"variable](https://www.gnu.org/software/bash/manual/bash.html#Event-" +"Designators) refers to the previous command, and I find useful when " +"following chains for symlinks:" +msgstr "" + +msgid "" +"$ which git\n" +"/run/current-system/sw/bin/git\n" +"$ readlink $(!!)\n" +"readlink $(which git)\n" +"/nix/store/5bgr1xpm4m0r72h9049jbbhagxdyrnyb-git-2.28.0/bin/git\n" +msgstr "" + +msgid "" +"It is also useful when you forget to prefix `sudo` to a command that " +"requires it:" +msgstr "" + +msgid "" +"$ requires-sudo.sh\n" +"requires-sudo.sh: Permission denied\n" +"$ sudo !!\n" +"sudo ./requires-sudo.sh\n" +"# all good\n" +msgstr "" + +msgid "" +"Bash prints the command expansion before executing it, so it is better for " +"you to follow along what it is doing." +msgstr "" + +msgid "`$_`: most recent parameter" +msgstr "" + +msgid "" +"The [`$_` " +"variable](https://www.gnu.org/software/bash/manual/bash.html#Special-" +"Parameters) will give you the most recent parameter you provided to a " +"previous argument, which can save you typing sometimes:" +msgstr "" + +msgid "" +"# instead of...\n" +"$ mkdir -p a/b/c/d/\n" +"$ cd a/b/c/d/\n" +"\n" +"# ...you can:\n" +"$ mkdir -p a/b/c/d/\n" +"$ cd $_\n" +msgstr "" + +msgid "Conclusion" +msgstr "" + +msgid "" +"I wouldn't use those in a script, as it would make the script terser to " +"read, I find those useful shortcut that are handy when writing at the " +"interactive terminal." +msgstr "" + +msgid "date: 2020-11-12 1" +msgstr "" + +msgid "eu_categories: shell" +msgstr "" + +#~ msgid "date: 2020-11-12" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-14-gpodder-as-a-media-subscription-manager.po b/po/fr/LC_MESSAGES/_tils/2020-11-14-gpodder-as-a-media-subscription-manager.po new file mode 100644 index 0000000..141ee40 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-14-gpodder-as-a-media-subscription-manager.po @@ -0,0 +1,49 @@ +# +msgid "" +msgstr "" + +msgid "title: gPodder as a media subscription manager" +msgstr "" + +msgid "date: 2020-11-14" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: gpodder-as-a-media-subscription-manager" +msgstr "" + +msgid "" +"As we [re-discover](https://www.charlieharrington.com/unexpected-useless-" +"and-urgent) the value of Atom/RSS feeds, most useful feed clients I know of " +"don't support media, specifically audio and video." +msgstr "" + +msgid "[gPodder](https://gpodder.github.io/) does." +msgstr "" + +msgid "" +"It is mostly know as a desktop podcatcher. But the thing about podcasts is " +"that the feed is provided through an RSS/Atom feed. So you can just use " +"gPodder as your media feed client, where you have control of what you look " +"at." +msgstr "" + +msgid "" +"I audio and video providers I know of offer an RSS/Atom view of their " +"content, so you can, say, treat any YouTube channel like a feed on its own." +msgstr "" + +msgid "" +"gPodder will then managed your feeds, watched/unwatched, queue downloads, " +"etc." +msgstr "" + +msgid "" +"Being obvious now, it was a big finding for me. If it got you interested, I " +"recommend you giving gPodder a try." +msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-11-30-storing-ci-data-on-git-notes.po b/po/fr/LC_MESSAGES/_tils/2020-11-30-storing-ci-data-on-git-notes.po new file mode 100644 index 0000000..e9cc227 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-11-30-storing-ci-data-on-git-notes.po @@ -0,0 +1,149 @@ +# +msgid "" +msgstr "" + +msgid "title: Storing CI data on Git notes" +msgstr "" + +msgid "date: 2020-11-30" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: storing-ci-data-on-git-notes" +msgstr "" + +msgid "" +"Extending the bare bones CI server I've [talked about before][previous-" +"article], divoplade on Freenode suggested storing CI artifacts on [Git " +"notes][git-notes], such as tarballs, binaries, logs, *etc*." +msgstr "" + +msgid "" +"I've written a small script that will put log files and CI job data on Git " +"notes, and make it visible on the porcelain log. It is a simple extension of" +" the previous article:" +msgstr "" + +msgid "" +"#!/usr/bin/env bash\n" +"set -Eeuo pipefail\n" +"set -x\n" +"\n" +"PREFIX='/srv/ci/vps'\n" +"mkdir -p \"$PREFIX\"\n" +"read -r _ SHA _ # oldrev newrev refname\n" +"FILENAME=\"$(date -Is)-$SHA.log\"\n" +"LOGFILE=\"$PREFIX/$FILENAME\"\n" +"exec &> >(tee -a \"$LOGFILE\")\n" +"\n" +"echo \"Starting CI job at: $(date -Is)\"\n" +"\n" +"finish() {\n" +" STATUS=\"$?\"\n" +" printf \"\\n\\n>>> exit status was %s\\n\" \"$STATUS\"\n" +" echo \"Finishing CI job at: $(date -Is)\"\n" +" popd\n" +" NOTE=$(cat <>> CI logs added as Git note.\"\n" +"}\n" +"trap finish EXIT\n" +"\n" +"unset GIT_DIR\n" +"CLONE=\"$(mktemp -d)\"\n" +"git clone . \"$CLONE\"\n" +"pushd \"$CLONE\"\n" +"git config --global user.email git@euandre.org\n" +"git config --global user.name 'EuAndreh CI'\n" +"\n" +"./container make check site\n" +"./container make publish\n" +msgstr "" + +msgid "The important part is in the `finish()` function:" +msgstr "" + +msgid "" +"#25 stores the exit status and the generated filename separated by spaces;" +msgstr "" + +msgid "#26 adds the log file in a note using the `refs/notes/ci-logs` ref;" +msgstr "" + +msgid "#27 it adds a note to the commit saying how to see the logs." +msgstr "" + +msgid "" +"A commit now has an attached note, and shows it whenever you look at it:" +msgstr "" + +msgid "" +"$ git show 930ba1888f49f11e52a4a715438cd9f5f413dd9c\n" +"commit 930ba1888f49f11e52a4a715438cd9f5f413dd9c (oldvps/master)\n" +"Author: EuAndreh \n" +"Date: Mon Nov 30 01:11:38 2020 -0300\n" +"\n" +" vps.scm: Uncomment mcron job time marker\n" +"\n" +"Notes:\n" +" See CI logs with:\n" +" git notes --ref=refs/notes/ci-logs show 930ba1888f49f11e52a4a715438cd9f5f413dd9c\n" +" git notes --ref=refs/notes/ci-data show 930ba1888f49f11e52a4a715438cd9f5f413dd9c\n" +"\n" +"diff --git a/sync/vps.scm b/sync/vps.scm\n" +"index 3f6ca69..02b9cc6 100644\n" +"--- a/sync/vps.scm\n" +"+++ b/sync/vps.scm\n" +"@@ -280,7 +280,7 @@ pki \" mail-domain \" key \\\"\" (tls-priv-for mail-domain) \"\\\"\")))\n" +" tls-prefixes)))\n" +"\n" +" (define generate-ci-index-html-job\n" +"- #~(job \"* * * * *\" ;; \"*/5 * * * *\"\n" +"+ #~(job \"*/5 * * * *\"\n" +" #$(program-file\n" +" \"generate-ci-index-html.scm\"\n" +" (with-imported-modules (modules:source-module-closure\n" +msgstr "" + +msgid "" +"Other tools such as [cgit][cgit] will also show notes on the web interface: " +"[https://euandreh.xyz/vps.git/commit?id=930ba1888f49f11e52a4a715438cd9f5f413dd9c](https://euandreh.xyz/vps.git/commit?id=930ba1888f49f11e52a4a715438cd9f5f413dd9c)" +msgstr "" + +msgid "" +"You can go even further: since cgit can serve raw blob directly, you can " +"even serve such artifacts (log files, release artifacts, binaries) from cgit" +" itself:" +msgstr "" + +msgid "" +"$ SHA=\"$(git notes --ref=refs/notes/ci-logs list 930ba1888f49f11e52a4a715438cd9f5f413dd9c)\"\n" +"$ echo \"https://euandreh.xyz/vps.git/blob?id=$SHA\"\n" +"https://euandreh.xyz/vps.git/blob?id=b3a6438a0c7a47864c54c61359b6ef50e864dbff\n" +msgstr "" + +msgid "" +"And like that you'll have cgit serving the artifacts for you: " +"[https://euandreh.xyz/vps.git/blob?id=b3a6438a0c7a47864c54c61359b6ef50e864dbff](https://euandreh.xyz/vps.git/blob?id=b3a6438a0c7a47864c54c61359b6ef50e864dbff)" +msgstr "" + +msgid "" +"[previous-article]: {% link _tils/2020-11-12-diy-bare-bones-ci-server-with-" +"bash-and-nix.md %} [git-notes]: https://git-scm.com/docs/git-notes [cgit]: " +"https://git.zx2c4.com/cgit/" +msgstr "" + +msgid "eu_categories: git,ci" +msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.po b/po/fr/LC_MESSAGES/_tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.po new file mode 100644 index 0000000..e671224 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.po @@ -0,0 +1,240 @@ +# +msgid "" +msgstr "" + +msgid "" +"Inspired by Fred Herbert's \"[Awk in 20 Minutes](https://ferd.ca/awk-" +"in-20-minutes.html)\", here's a problem I just solved with a line of Awk: " +"run ShellCheck in all scripts of a repository." +msgstr "" + +msgid "" +"In my repositories I usually have Bash and POSIX scripts, which I want to " +"keep tidy with [ShellCheck](https://www.shellcheck.net/). Here's the first " +"version of `assert-shellcheck.sh`:" +msgstr "" + +msgid "" +"This is the type of script that I copy around to all repositories, and I " +"want it to be capable of working on any repository, without requiring a list" +" of files to run ShellCheck on." +msgstr "" + +msgid "" +"This first version worked fine, as all my scripts had the '.sh' ending. But " +"I recently added some scripts without any extension, so `assert-" +"shellcheck.sh` called for a second version. The first attempt was to try " +"grepping the shebang line:" +msgstr "" + +msgid "" +"$ grep '^#!/' assert-shellcheck.sh\n" +"#!/usr/sh\n" +msgstr "" + +msgid "" +"Good, we have a grep pattern on the first try. Let's try to find all the " +"matching files:" +msgstr "" + +msgid "" +"$ find . -type f | xargs grep -l '^#!/'\n" +"./TODOs.org\n" +"./.git/hooks/pre-commit.sample\n" +"./.git/hooks/pre-push.sample\n" +"./.git/hooks/pre-merge-commit.sample\n" +"./.git/hooks/fsmonitor-watchman.sample\n" +"./.git/hooks/pre-applypatch.sample\n" +"./.git/hooks/pre-push\n" +"./.git/hooks/prepare-commit-msg.sample\n" +"./.git/hooks/commit-msg.sample\n" +"./.git/hooks/post-update.sample\n" +"./.git/hooks/pre-receive.sample\n" +"./.git/hooks/applypatch-msg.sample\n" +"./.git/hooks/pre-rebase.sample\n" +"./.git/hooks/update.sample\n" +"./build-aux/with-guile-env.in\n" +"./build-aux/test-driver\n" +"./build-aux/missing\n" +"./build-aux/install-sh\n" +"./build-aux/install-sh~\n" +"./bootstrap\n" +"./scripts/assert-todos.sh\n" +"./scripts/songbooks\n" +"./scripts/compile-readme.sh\n" +"./scripts/ci-build.sh\n" +"./scripts/generate-tasks-and-bugs.sh\n" +"./scripts/songbooks.in\n" +"./scripts/with-container.sh\n" +"./scripts/assert-shellcheck.sh\n" +msgstr "" + +msgid "" +"This approach has a problem, though: it includes files ignored by Git, such " +"as `builld-aux/install-sh~`, and even goes into the `.git/` directory and " +"finds sample hooks in `.git/hooks/*`." +msgstr "" + +msgid "To list the files that Git is tracking we'll try `git ls-files`:" +msgstr "" + +msgid "" +"$ git ls-files | xargs grep -l '^#!/'\n" +"TODOs.org\n" +"bootstrap\n" +"build-aux/with-guile-env.in\n" +"old/scripts/assert-docs-spelling.sh\n" +"old/scripts/build-site.sh\n" +"old/scripts/builder.bats.sh\n" +"scripts/assert-shellcheck.sh\n" +"scripts/assert-todos.sh\n" +"scripts/ci-build.sh\n" +"scripts/compile-readme.sh\n" +"scripts/generate-tasks-and-bugs.sh\n" +"scripts/songbooks.in\n" +"scripts/with-container.sh\n" +msgstr "" + +msgid "" +"It looks to be almost there, but the `TODOs.org` entry shows a flaw in it: " +"grep is looking for a `'^#!/'` pattern on any part of the file. In my case, " +"`TODOs.org` had a snippet in the middle of the file where a line started " +"with `#!/bin/sh`." +msgstr "" + +msgid "" +"So what we actually want is to match the **first** line against the pattern." +" We could loop through each file, get the first line with `head -n 1` and " +"grep against that, but this is starting to look messy. I bet there is " +"another way of doing it concisely..." +msgstr "" + +msgid "" +"Let's try Awk. I need a way to select the line numbers to replace `head -n " +"1`, and to stop processing the file if the pattern matches. A quick search " +"points me to using `FNR` for the former, and `{ nextline }` for the latter. " +"Let's try it:" +msgstr "" + +msgid "" +"$ git ls-files | xargs awk 'FNR>1 { nextfile } /^#!\\// { print FILENAME; nextfile }'\n" +"bootstrap\n" +"build-aux/with-guile-env.in\n" +"old/scripts/assert-docs-spelling.sh\n" +"old/scripts/build-site.sh\n" +"old/scripts/builder.bats.sh\n" +"scripts/assert-shellcheck.sh\n" +"scripts/assert-todos.sh\n" +"scripts/ci-build.sh\n" +"scripts/compile-readme.sh\n" +"scripts/generate-tasks-and-bugs.sh\n" +"scripts/songbooks.in\n" +"scripts/with-container.sh\n" +msgstr "" + +msgid "" +"Great! Only `TODOs.org` is missing, but the script is much better: instead " +"of matching against any part of the file that may have a shebang-like line, " +"we only look for the first. Let's put it back into the `assert-" +"shellcheck.sh` file and use `NULL` for separators to accommodate files with " +"spaces in the name:" +msgstr "" + +msgid "" +"This is where I've stopped, but I imagine a likely improvement: match " +"against only `#!/bin/sh` and `#!/usr/bin/env bash` shebangs (the ones I use " +"most), to avoid running ShellCheck on Perl files, or other shebangs." +msgstr "" + +msgid "" +"Also when reviewing the text of this article, I found that `{ nextfile }` is" +" a GNU Awk extension. It would be an improvement if `assert-shellcheck.sh` " +"relied on the POSIX subset of Awk for working correctly." +msgstr "" + +msgid "title: 'Awk snippet: ShellCheck all scripts in a repository'" +msgstr "" + +msgid "date: 2020-12-15" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: awk-snippet-shellcheck-all-scripts-in-a-repository" +msgstr "" + +msgid "*Update*" +msgstr "" + +msgid "" +"After publishing, I could remove `{ nextfile }` and even make the script " +"simpler:" +msgstr "" + +msgid "Now both the shell and Awk usage are POSIX compatible." +msgstr "" + +msgid "eu_categories: shell" +msgstr "" + +msgid "updated_at: 2020-12-16" +msgstr "" + +msgid "" +"#!/bin/sh -eux\n" +"\n" +"find . -type f -name '*.sh' -print0 | xargs -0 shellcheck\n" +msgstr "" + +msgid "" +"#!/usr/sh -eux\n" +"\n" +"git ls-files -z | \\\n" +" xargs -0 awk 'FNR>1 { nextfile } /^#!\\// { print FILENAME; nextfile }' | \\\n" +" xargs shellcheck\n" +msgstr "" + +msgid "" +"#!/usr/sh -eux\n" +"\n" +"git ls-files -z | \\\n" +" xargs -0 awk 'FNR==1 && /^#!\\// { print FILENAME }' | \\\n" +" xargs shellcheck\n" +msgstr "" + +#~ msgid "" +#~ "#!/bin/sh\n" +#~ "set -eu\n" +#~ "\n" +#~ "find . -type f -name '*.sh' -print0 | xargs -0 shellcheck\n" +#~ msgstr "" + +#~ msgid "" +#~ "#!/usr/sh\n" +#~ "set -eu\n" +#~ "\n" +#~ "git ls-files -z | \\\n" +#~ " xargs -0 awk 'FNR>1 { nextfile } /^#!\\// { print FILENAME; nextfile }' | \\\n" +#~ " xargs shellcheck\n" +#~ msgstr "" + +#~ msgid "" +#~ "#!/usr/sh\n" +#~ "set -eu\n" +#~ "\n" +#~ "git ls-files -z | \\\n" +#~ " xargs -0 awk 'FNR==1 && /^#!\\// { print FILENAME }' | \\\n" +#~ " xargs shellcheck\n" +#~ msgstr "" + +#~ msgid "" +#~ "title: 'Awk snippet: ShellCheck all scripts in a repository'\n" +#~ "date: 2020-12-15\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: awk-snippet-shellcheck-all-scripts-in-a-repository" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2020-12-29-svg-favicon.po b/po/fr/LC_MESSAGES/_tils/2020-12-29-svg-favicon.po new file mode 100644 index 0000000..863f531 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2020-12-29-svg-favicon.po @@ -0,0 +1,168 @@ +# +msgid "" +msgstr "" + +msgid "" +"I've wanted to change this website's favicon from a plain `.ico` file to a " +"proper SVG. The problem I was trying to solve was to reuse the same image on" +" other places, such as avatars." +msgstr "" + +msgid "" +"Generating a PNG from the existing 16x16 icon was possible but bad: the " +"final image was blurry. Converting the `.ico` to an SVG was possible, but " +"sub-optimal: tools try to guess some vector paths, and the final SVG didn't " +"match the original." +msgstr "" + +msgid "" +"Instead I used a tool to draw the \"vector pixels\" as black squares, and " +"after getting the final result I manually cleaned-up the generated XML:" +msgstr "" + +msgid "" +"\n" +"\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n" +msgstr "" + +msgid "" +"With the new favicon file, I now had to add to the templates' `` a " +"`` to this icon:" +msgstr "" + +msgid "" +"\n" +" \n" +" \n" +" ...\n" +msgstr "" + +msgid "" +"Still missing is a bitmap image for places that can't handle vector images. " +"I used Jekyll generator to create an PNG from the existing SVG:" +msgstr "" + +msgid "" +"module Jekyll\n" +" class FaviconGenerator < Generator\n" +" safe true\n" +" priority :high\n" +"\n" +" SIZE = 420\n" +"\n" +" def generate(site)\n" +" svg = 'static/favicon.svg'\n" +" png = 'static/favicon.png'\n" +" unless File.exist? png then\n" +" puts \"Missing '#{png}', generating...\"\n" +" puts `inkscape -o #{png} -w #{SIZE} -h #{SIZE} #{svg}`\n" +" end\n" +" end\n" +" end\n" +"end\n" +msgstr "" + +msgid "" +"I had to increase the priority of the generator so that it would run before " +"other places that would use a `{% link /static/favicon.png %}`, otherwise " +"the file would be considered missing." +msgstr "" + +msgid "title: SVG favicon" +msgstr "" + +msgid "date: 2020-12-29" +msgstr "" + +msgid "updated_at: 2021-01-12" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: svg-favicon" +msgstr "" + +msgid "" +"The good thing about this new favicon (at " +"[`/static/favicon.svg`](/static/favicon.svg)) is that a) it is simple enough" +" that I feel comfortable editing it manually and b) it is an SVG, which " +"means I can generate any desired size." +msgstr "" + +#~ msgid "" +#~ "title: SVG favicon\n" +#~ "date: 2020-12-29\n" +#~ "layout: post\n" +#~ "lang: en\n" +#~ "ref: svg-favicon" +#~ msgstr "" + +#~ msgid "" +#~ "The good thing about this new favicon is that a) it is simple enough that I " +#~ "feel comfortable editing it manually and b) it is an SVG, which means I can " +#~ "generate any desired size." +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po b/po/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po new file mode 100644 index 0000000..5ed4783 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po @@ -0,0 +1,249 @@ +# +msgid "" +msgstr "" + +msgid "title: 'Awk snippet: send email to multiple recipients with cURL'" +msgstr "" + +msgid "date: 2021-01-12" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: awk-snippet-send-email-to-multiple-recipients-with-curl" +msgstr "" + +msgid "My requirements for the `sendmail` command were:" +msgstr "" + +msgid "store the email in a file, and send it later." +msgstr "" + +msgid "send from different addresses, using different SMTP servers;" +msgstr "" + +msgid "" +"I couldn't find an MTA that could accomplish that, but I was able to quickly" +" write a solution." +msgstr "" + +msgid "The first part was the easiest: store the email in a file:" +msgstr "" + +msgid "" +"# ~/.config/mutt/muttrc:\n" +"set sendmail=~/bin/enqueue-email.sh\n" +"\n" +"# ~/bin/enqueue-email.sh:\n" +"#!/bin/sh -eu\n" +"\n" +"cat - > \"$HOME/mbsync/my-queued-emails/$(date -Is)\"\n" +msgstr "" + +msgid "" +"Now that I had the email file store locally, I needed a program to send the " +"email from the file, so that I could create a cronjob like:" +msgstr "" + +msgid "" +"for f in ~/mbsync/my-queued-emails/*; do\n" +" ~/bin/dispatch-email.sh \"$f\" && rm \"$f\"\n" +"done\n" +msgstr "" + +msgid "" +"The `dispatch-email.sh` would have to look at the `From: ` header and decide" +" which SMTP server to use. As I [found " +"out](https://blog.edmdesigner.com/send-email-from-linux-command-line/) that " +"[curl](https://curl.se/) supports SMTP and is able to send emails, this is " +"what I ended up with:" +msgstr "" + +msgid "Most of curl flags used are self-explanatory, except for `$rcpt`." +msgstr "" + +msgid "" +"curl connects to the SMTP server, but doesn't set the recipient address by " +"looking at the message. My solution was to generate the curl flags, store " +"them in `$rcpt` and use it unquoted to leverage shell word splitting." +msgstr "" + +msgid "" +"To me, the most interesting part was building the `$rcpt` flags. My first " +"instinct was to try grep, but it couldn't print only matches in a regex. As " +"I started to turn towards sed, I envisioned needing something else to loop " +"over the sed output, and I then moved to Awk." +msgstr "" + +msgid "" +"$ H='To: to@example.com, to2@example.com\\nCc: cc@example.com, cc2@example.com\\nBcc: bcc@example.com,bcc2@example.com\\n'\n" +"$ printf \"$H\" | awk '/^To: .*$/ { print $0 }'\n" +"To: to@example.com, to2@example.com\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m }'\n" +"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « m » dans un contexte scalaire\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[0] }'\n" +"To: to@example.com, to2@example.com\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[1] }'\n" +"to@example.com, to2@example.com\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos }'\n" +"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « tos » dans un contexte scalaire\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[0] }'\n" +"\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[1] }'\n" +"to@example.com,\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[2] }'\n" +"to2@example.com\n" +"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[3] }'\n" +"\n" +msgstr "" + +msgid "" +"(This isn't the verbatim interactive session, but a cleaned version to make " +"it more readable.)" +msgstr "" + +msgid "" +"At this point, I realized I needed a for loop over the `tos` array, and I " +"moved the Awk snippet into the `~/bin/dispatch-email.sh`. I liked the final " +"thing:" +msgstr "" + +msgid "" +"match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n" +" split(m[2], tos, \",\")\n" +" for (i in tos) {\n" +" print \"--mail-rcpt \" tos[i]\n" +" }\n" +"}\n" +msgstr "" + +msgid "" +"As I learn more about Awk, I feel that it is too undervalued, as many people" +" turn to Perl or other programming languages when Awk suffices. The " +"advantage is pretty clear: writing programs that run on any POSIX system, " +"without extra dependencies required." +msgstr "" + +msgid "Coding to the standards is underrated." +msgstr "" + +msgid "" +"#!/bin/sh -eu\n" +"\n" +"F=\"$1\"\n" +"\n" +"rcpt=\"$(awk '\n" +" match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n" +" split(m[2], tos, \",\")\n" +" for (i in tos) {\n" +" print \"--mail-rcpt \" tos[i]\n" +" }\n" +" }\n" +"' \"$F\")\"\n" +"\n" +"if grep -qE '^From: .*$' \"$F\"; then\n" +" curl \\\n" +" -s \\\n" +" --url smtp://smtp.server1.org:587 \\\n" +" --ssl-reqd \\\n" +" --mail-from addr@server1.org \\\n" +" $rcpt \\\n" +" --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n" +" --upload-file \"$F\"\n" +"elif grep -qE '^From: .*$' \"$F\"; then\n" +" curl \\\n" +" -s \\\n" +" --url smtp://smtp.server2.org:587 \\\n" +" --ssl-reqd \\\n" +" --mail-from addr@server2.org \\\n" +" $rcpt \\\n" +" --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n" +" --upload-file \"$F\"\n" +"else\n" +" echo 'Bad \"From: \" address'\n" +" exit 1\n" +"fi\n" +msgstr "" + +msgid "" +"In the short Awk snippet, 3 things were new to me: the `match(...)`, " +"`split(...)` and `for () {}`. The only other function I have ever used was " +"`gsub(...)`, but these new ones felt similar enough that I could almost " +"guess their behaviour and arguments. `match(...)` stores the matches of a " +"regex on the given array positionally, and `split(...)` stores the chunks in" +" the given array." +msgstr "" + +msgid "I even did it incrementally:" +msgstr "" + +msgid "" +"As I experiment with [Neomutt](https://neomutt.org/), I wanted to keep being" +" able to enqueue emails for sending later like my previous setup, so that I " +"didn't rely on having an internet connection." +msgstr "" + +#~ msgid "" +#~ "As I experimented with [Neomutt](https://neomutt.org/), I wanted to keep " +#~ "being able to enqueue emails for sending later like my previous setup, so " +#~ "that I didn't rely on having an internet connection." +#~ msgstr "" + +#~ msgid "I even did this incrementally:" +#~ msgstr "" + +#~ msgid "" +#~ "In the short Awk snippet, 3 things were new to me: the `match(...)`, " +#~ "`split(...)` and `for () {}`. The only other function I have ever used was " +#~ "`gsub(...)`, but these new felt similar enough that I could almost guess " +#~ "their behaviour. `match(...)` stores the matches of a regex on the given " +#~ "array positionally, and `split(...)` stores the chunks in the given array." +#~ msgstr "" + +#~ msgid "" +#~ "As I experimented with [Neomutt](https://neomutt.org/), I wanted to keep " +#~ "being able to enqueue emails for sending later, so that I didn't rely on " +#~ "having an internet connection." +#~ msgstr "" + +#~ msgid "" +#~ "#!/bin/sh -eu\n" +#~ "\n" +#~ "F=\"$1\"\n" +#~ "\n" +#~ "rcpt=\"$(awk '\n" +#~ " match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n" +#~ " split(m[2], tos, \",\")\n" +#~ " for (i in tos) {\n" +#~ " print \"--mail-rcpt \" tos[i]\n" +#~ " }\n" +#~ " }\n" +#~ "' \"$F\")\"\n" +#~ "\n" +#~ "if grep -qE '^From: .*$' \"$F\"; then\n" +#~ " curl \\\n" +#~ " -s \\\n" +#~ " --url smtp://smtp.server1.org:587 \\\n" +#~ " --ssl-reqd \\\n" +#~ " --mail-from addr@server1.org \\\n" +#~ " $rcpt \\\n" +#~ " --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n" +#~ " --upload-file \"$F\"\n" +#~ "eliif grep -qE '^From: .*$' \"$F\"; then\n" +#~ " curl \\\n" +#~ " -s \\\n" +#~ " --url smtp://smtp.server2.org:587 \\\n" +#~ " --ssl-reqd \\\n" +#~ " --mail-from addr@server2.org \\\n" +#~ " $rcpt \\\n" +#~ " --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n" +#~ " --upload-file \"$F\"\n" +#~ "else\n" +#~ " echo 'Bad \"From: \" address'\n" +#~ " exit 1\n" +#~ "fi\n" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2021-01-17-posix-sh-and-shebangs.po b/po/fr/LC_MESSAGES/_tils/2021-01-17-posix-sh-and-shebangs.po new file mode 100644 index 0000000..e285d50 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2021-01-17-posix-sh-and-shebangs.po @@ -0,0 +1,97 @@ +# +msgid "" +msgstr "" + +msgid "title: POSIX sh and shebangs" +msgstr "" + +msgid "date: 2021-01-17" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: posix-sh-and-shebangs" +msgstr "" + +msgid "" +"As I [keep moving][posix-awk-0] [towards POSIX][posix-awk-1], I'm on the " +"process of migrating all my Bash scripts to POSIX sh." +msgstr "" + +msgid "" +"As I dropped `[[`, arrays and other Bashisms, I was left staring at the " +"first line of every script, wondering what to do: what is the POSIX sh " +"equivalent of `#!/usr/bin/env bash`? I already knew that POSIX says nothing " +"about shebangs, and that the portable way to call a POSIX sh script is `sh " +"script.sh`, but I didn't know what to do with that first line." +msgstr "" + +msgid "What I had previously was:" +msgstr "" + +msgid "" +"#!/usr/bin/env bash\n" +"set -Eeuo pipefail\n" +"cd \"$(dirname \"${BASH_SOURCE[0]}\")\"\n" +msgstr "" + +msgid "" +"Obviously, the `$BASH_SOURCE` would be gone, and I would have to adapt some " +"of my scripts to not rely on the script location. The `-E` and `-o pipefail`" +" options were also gone, and would be replaced by nothing." +msgstr "" + +msgid "I converted all of them to:" +msgstr "" + +msgid "#!/bin/sh -eu\n" +msgstr "" + +msgid "" +"I moved the `-eu` options to the shebang line itself, striving for " +"conciseness. But as I changed callers from `./script.sh` to `sh script.sh`, " +"things started to fail. Some tests that should fail reported errors, but " +"didn't return 1." +msgstr "" + +msgid "" +"My first reaction was to revert back to `./script.sh`, but the POSIX bug I " +"caught is a strong strain, and when I went back to it, I figured that the " +"callers were missing some flags. Specifically, `sh -eu script.sh`." +msgstr "" + +msgid "" +"Then it clicked: when running with `sh script.sh`, the shebang line with the" +" sh options is ignored, as it is a comment!" +msgstr "" + +msgid "Which means that the shebang most friendly with POSIX is:" +msgstr "" + +msgid "" +"#!/bin/sh\n" +"set -eu\n" +msgstr "" + +msgid "" +"when running via `./script.sh`, if the system has an executable at " +"`/bin/sh`, it will be used to run the script;" +msgstr "" + +msgid "" +"when running via `sh script.sh`, the sh options aren't ignored as " +"previously." +msgstr "" + +msgid "TIL." +msgstr "" + +msgid "" +"[posix-awk-0]: {% link _tils/2020-12-15-awk-snippet-shellcheck-all-scripts-" +"in-a-repository.md %} [posix-awk-1]: {% link _tils/2021-01-12-awk-snippet-" +"send-email-to-multiple-recipients-with-curl.md %}" +msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po b/po/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po new file mode 100644 index 0000000..ab59a4f --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po @@ -0,0 +1,220 @@ +# +msgid "" +msgstr "" + +msgid "title: Clojure auto curry" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: clojure-auto-curry" +msgstr "" + +msgid "A naive `add` definition, alongside its usage and macroexpansion:" +msgstr "" + +msgid "" +"user=> (defcurry add\n" +" [a b c d e]\n" +" (+ 1 2 3 4 5))\n" +"#'user/add\n" +"\n" +"user=> (add 1)\n" +"#object[clojure.core$partial$fn__5857 0x2c708440 \"clojure.core$partial$fn__5857@2c708440\"]\n" +"\n" +"user=> (add 1 2 3 4)\n" +"#object[clojure.core$partial$fn__5863 0xf4c0e4e \"clojure.core$partial$fn__5863@f4c0e4e\"]\n" +"\n" +"user=> ((add 1) 2 3 4 5)\n" +"15\n" +"\n" +"user=> (((add 1) 2 3) 4 5)\n" +"15\n" +"\n" +"user=> (use 'clojure.pprint)\n" +"nil\n" +"\n" +"user=> (pprint\n" +" (macroexpand\n" +" '(defcurry add\n" +" [a b c d e]\n" +" (+ 1 2 3 4 5))))\n" +"(def\n" +" add\n" +" (clojure.core/fn\n" +" ([a b c d e] (+ 1 2 3 4 5))\n" +" ([a] (clojure.core/partial add a))\n" +" ([a b] (clojure.core/partial add a b))\n" +" ([a b c] (clojure.core/partial add a b c))\n" +" ([a b c d] (clojure.core/partial add a b c d))))\n" +"nil\n" +msgstr "" + +msgid "" +"This simplistic `defcurry` definition doesn't support optional parameters, " +"multi-arity, `&` rest arguments, docstrings, etc., but it could certainly " +"evolve to do so." +msgstr "" + +msgid "" +"I like how `defcurry` is so short, and abdicates the responsability of doing" +" the multi-arity logic to Clojure's built-in multi-arity support. Simple and" +" elegant." +msgstr "" + +msgid "Same Clojure as before, now with auto-currying via macros." +msgstr "" + +msgid "" +"Here's a simple macro defined by [Loretta " +"He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to " +"create Clojure functions that are curried on all arguments, relying on " +"Clojure's multi-arity support:" +msgstr "" + +msgid "date: 2021-04-24 1" +msgstr "" + +msgid "" +"(defmacro defcurry\n" +" [name args & body]\n" +" (let [partials (map (fn [n]\n" +" `(~(subvec args 0 n) (partial ~name ~@(take n args))))\n" +" (range 1 (count args)))]\n" +" `(defn ~name\n" +" (~args ~@body)\n" +" ~@partials)))\n" +msgstr "" + +msgid "Comparison with Common Lisp" +msgstr "" + +msgid "My attempt at writing an equivalent for Common Lisp gives me:" +msgstr "" + +msgid "" +"(defun partial (fn &rest args)\n" +" (lambda (&rest args2)\n" +" (apply fn (append args args2))))\n" +"\n" +"(defun curry-n (n func)\n" +" (cond ((< n 0) (error \"Too many arguments\"))\n" +" ((zerop n) (funcall func))\n" +" (t (lambda (&rest rest)\n" +" (curry-n (- n (length rest))\n" +" (apply #'partial func rest))))))\n" +"\n" +"(defmacro defcurry (name args &body body)\n" +" `(defun ,name (&rest rest)\n" +" (let ((func (lambda ,args ,@body)))\n" +" (curry-n (- ,(length args) (length rest))\n" +" (apply #'partial func rest)))))\n" +msgstr "" + +msgid "" +"Without built-in multi-arity support, we have to do more work, like tracking" +" the number of arguments consumed so far. We also have to write `#'partial` " +"ourselves. That is, without dependending on any library, sticking to ANSI " +"Common Lisp." +msgstr "" + +msgid "The usage is pretty similar:" +msgstr "" + +msgid "" +"* (defcurry add (a b c d e)\n" +" (+ a b c d e))\n" +"ADD\n" +"\n" +"* (add 1)\n" +"#\n" +"\n" +"* (funcall (add 1) 2 3 4)\n" +"#\n" +"\n" +"* (funcall (add 1) 2 3 4 5)\n" +"15\n" +"\n" +"* (funcall (funcall (add 1) 2 3) 4 5)\n" +"15\n" +"\n" +"* (macroexpand-1\n" +" '(defcurry add (a b c d e)\n" +" (+ a b c d e)))\n" +"(DEFUN ADD (&REST REST)\n" +" (LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E))))\n" +" (CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST))))\n" +"T\n" +msgstr "" + +msgid "" +"This also require `funcall`s, since we return a `lambda` that doesn't live " +"in the function namespace." +msgstr "" + +msgid "" +"Like the Clojure one, it doesn't support optional parameters, `&rest` rest " +"arguments, docstrings, etc., but it also could evolve to do so." +msgstr "" + +msgid "updated_at: 2021-04-27" +msgstr "" + +#~ msgid "" +#~ "(defmacro defcurry\n" +#~ " [fname args & body]\n" +#~ " (let [partials (map (fn [n]\n" +#~ " `(~(subvec args 0 n) (partial ~fname ~@(take n args))))\n" +#~ " (range 1 (count args)))]\n" +#~ " `(defn ~fname\n" +#~ " (~args ~@body)\n" +#~ " ~@partials)))\n" +#~ msgstr "" + +#~ msgid "date: 2021-04-24" +#~ msgstr "" + +#~ msgid "" +#~ "A simple macro defined by [Loretta " +#~ "He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to " +#~ "create Clojure functions that are curried on all arguments, relying on " +#~ "Clojure's multi-arity support:" +#~ msgstr "" + +#~ msgid "" +#~ "Without built-in multi-arity support, we have to do more work, like tracking" +#~ " the number of arguments consumed so far. That is, without dependending on " +#~ "any library, sticking to ANSI Common Lisp." +#~ msgstr "" + +#~ msgid "" +#~ "(defun curry-n (n fn)\n" +#~ " (if (= 0 n)\n" +#~ " (funcall fn)\n" +#~ " (lambda (&rest rest)\n" +#~ " (curry-n (something n) fn))))\n" +#~ "\n" +#~ "(defun add (a b c d e)\n" +#~ " (curry-n\n" +#~ " (length '(a b c d e))\n" +#~ " (lambda (&rest rest)\n" +#~ " (apply #'+ rest))))\n" +#~ msgstr "" + +#~ msgid "" +#~ "(defun curry-n (n fn)\n" +#~ " (if (= 0 n)\n" +#~ " (funcall fn)\n" +#~ " (lambda (&rest rest)\n" +#~ " (curry-n (something n) fn))))\n" +#~ "\n" +#~ "(defun add (a b c d e)\n" +#~ " (curry-n\n" +#~ " (length '(a b c d e))\n" +#~ " (lambda (&rest rest)\n" +#~ " (apply #'+ rest))))\n" +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po b/po/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po new file mode 100644 index 0000000..6aa66a8 --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po @@ -0,0 +1,210 @@ +# +msgid "" +msgstr "" + +msgid "" +"title: Common Lisp argument precedence order parameterization of a generic " +"function" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "" +"ref: common-lisp-argument-precedence-order-parameterization-of-a-generic-" +"function" +msgstr "" + +msgid "" +"When CLOS dispatches a method, it picks the most specific method definition " +"to the argument list:" +msgstr "" + +msgid "" +"\n" +"* (defgeneric a-fn (x))\n" +"#\n" +"\n" +"* (defmethod a-fn (x) :default-method)\n" +"#\n" +"\n" +"* (defmethod a-fn ((x number)) :a-number)\n" +"#\n" +"\n" +"* (defmethod a-fn ((x (eql 1))) :number-1)\n" +"#\n" +"\n" +"* (a-fn nil)\n" +":DEFAULT-METHOD\n" +"\n" +"* (a-fn \"1\")\n" +":DEFAULT-METHOD\n" +"\n" +"* (a-fn 0)\n" +":A-NUMBER\n" +"\n" +"* (a-fn 1)\n" +":NUMBER-1\n" +msgstr "" + +msgid "" +"CLOS uses a similar logic when choosing the method from parent classes, when" +" multiple ones are available:" +msgstr "" + +msgid "" +"* (defclass class-a () ())\n" +"\n" +"#\n" +"* (defclass class-b () ())\n" +"\n" +"#\n" +"* (defgeneric another-fn (obj))\n" +"\n" +"#\n" +"* (defmethod another-fn ((obj class-a)) :class-a)\n" +"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n" +"; Compiling Top-Level Form:\n" +"\n" +"#\n" +"* (defmethod another-fn ((obj class-b)) :class-b)\n" +"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n" +"; Compiling Top-Level Form:\n" +"\n" +"#\n" +msgstr "" + +msgid "" +"Given the above definitions, when inheriting from `class-a` and `class-b`, " +"the order of inheritance matters:" +msgstr "" + +msgid "" +"* (defclass class-a-coming-first (class-a class-b) ())\n" +"#\n" +"\n" +"* (defclass class-b-coming-first (class-b class-a) ())\n" +"#\n" +"\n" +"* (another-fn (make-instance 'class-a-coming-first))\n" +":CLASS-A\n" +"\n" +"* (another-fn (make-instance 'class-b-coming-first))\n" +":CLASS-B\n" +msgstr "" + +msgid "" +"Combining the order of inheritance with generic functions with multiple " +"arguments, CLOS has to make a choice of how to pick a method given two " +"competing definitions, and its default strategy is prioritizing from left to" +" right:" +msgstr "" + +msgid "" +"* (defgeneric yet-another-fn (obj1 obj2))\n" +"#\n" +"\n" +"* (defmethod yet-another-fn ((obj1 class-a) obj2) :first-arg-specialized)\n" +"#\n" +"\n" +"* (defmethod yet-another-fn (obj1 (obj2 class-b)) :second-arg-specialized)\n" +"#\n" +"\n" +"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n" +":FIRST-ARG-SPECIALIZED\n" +msgstr "" + +msgid "" +"For that, we use the `:argument-precedence-order` option when declaring a " +"generic function:" +msgstr "" + +msgid "" +"* (defgeneric yet-another-fn (obj1 obj2) (:argument-precedence-order obj2 obj1))\n" +"#\n" +"\n" +"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n" +":SECOND-ARG-SPECIALIZED\n" +msgstr "" + +msgid "" +"I liked that the `:argument-precedence-order` option exists. We shouldn't " +"have to change the arguments from `(obj1 obj2)` to `(obj2 obj1)` just to " +"make CLOS pick the method that we want. We can configure its default " +"behaviour if desired, and keep the order of arguments however it best fits " +"the generic function." +msgstr "" + +msgid "Comparison with Clojure" +msgstr "" + +msgid "Clojure has an equivalent, when using `defmulti`." +msgstr "" + +msgid "" +"Since when declaring a multi-method with `defmulti` we must define the " +"dispatch function, Clojure uses it to pick the method definition. Since the " +"dispatch function is required, there is no need for a default behaviour, " +"such as left-to-right." +msgstr "" + +msgid "Conclusion" +msgstr "" + +msgid "" +"Making the argument precedence order configurable for generic functions but " +"not for class definitions makes a lot of sense." +msgstr "" + +msgid "" +"One shouldn't change the order of arguments of a generic function for the " +"sake of tailoring it to the CLOS priority ranking algorithm, but doing it " +"for a class definition is just fine." +msgstr "" + +msgid "TIL." +msgstr "" + +msgid "" +"CLOS has to make a choice between the first and the second definition of " +"`yet-another-fn`, but its choice is just a heuristic. What if we want the " +"choice to be based on the second argument, instead of the first?" +msgstr "" + +msgid "" +"When declaring a class, we can choose the precedence order, and that is " +"about it. But when defining a generic function, the order of arguments is " +"more important to the function semantics, and the argument precedence being " +"left-to-right is just the default behaviour." +msgstr "" + +msgid "References" +msgstr "" + +msgid "" +"[Object-Oriented Programming in Common Lisp: A Programmer's Guide to " +"CLOS](https://en.wikipedia.org/wiki/Object-" +"Oriented_Programming_in_Common_Lisp), by Sonja E. Keene" +msgstr "" + +msgid "date: 2021-04-24 2" +msgstr "" + +#~ msgid "date: 2021-04-24" +#~ msgstr "" + +#~ msgid "" +#~ "CLOS has to make a choice between the first and the second definition of " +#~ "`yet-another-fn`, but its choice is just a heuristic. What if we want to the" +#~ " choice to be based on the second argument first?" +#~ msgstr "" + +#~ msgid "" +#~ "When declaring a class, we can choose the precedence order, and that is " +#~ "about it. But when defining a generic function, the order of argumentws is " +#~ "more important to the function semantics, and the argument precedence being " +#~ "left-to-right is just the default behaviour." +#~ msgstr "" diff --git a/po/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po b/po/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po new file mode 100644 index 0000000..925a00b --- /dev/null +++ b/po/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po @@ -0,0 +1,95 @@ +# +msgid "" +msgstr "" + +msgid "title: Three-way conditional for number signs" +msgstr "" + +msgid "date: 2021-04-24 3" +msgstr "" + +msgid "layout: post" +msgstr "" + +msgid "lang: en" +msgstr "" + +msgid "ref: three-way-conditional-for-number-signs" +msgstr "" + +msgid "" +"A useful macro from Paul Graham's [On " +"Lisp](http://www.paulgraham.com/onlisptext.html) book:" +msgstr "" + +msgid "" +"(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" +msgstr "" + +msgid "" +"The latest example I can think of is section 1.3.3 of [Structure and " +"Interpretation of Computer " +"Programs](https://mitpress.mit.edu/sites/default/files/sicp/index.html), " +"which I was reading recently:" +msgstr "" + +msgid "" +"(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" +msgstr "" + +msgid "" +"(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" +msgstr "" + +msgid "" +"It also avoids `cond`'s extra clunky parentheses for grouping, which is " +"unnecessary but built-in." +msgstr "" + +msgid "" +"As a macro, I personally feel it tilts the balance towards expressivenes " +"despite its extra cognitive load toll." +msgstr "" + +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 "" + +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 "" + +#~ msgid "" +#~ "After I looked at this macro, I started seeing opportunities to using it in " +#~ "many places, and yet I didn't see anyonelse using it." +#~ msgstr "" + +#~ msgid "" +#~ "Not that the book should introduce such macro this early, but I couldn't " +#~ "avoid feeling bothered by not using a `nif` macro, which could even remove " +#~ "the need for the intermediate `test-value` variable:" +#~ msgstr "" -- cgit v1.2.3