aboutsummaryrefslogtreecommitdiff
path: root/src/content/tils/2020/08
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-11-18 08:21:58 -0300
committerEuAndreh <eu@euandre.org>2024-11-18 08:44:57 -0300
commit960e4410f76801356ebd42801c914b2910a302a7 (patch)
tree615d379416f72956d0c1666c63ce062859041fbe /src/content/tils/2020/08
parentRemove jekyll infrastructure setup (diff)
downloadeuandre.org-main.tar.gz
euandre.org-main.tar.xz
v0 migration to mkwbHEADmain
Diffstat (limited to 'src/content/tils/2020/08')
-rw-r--r--src/content/tils/2020/08/12/filename-timestamp.adoc44
-rw-r--r--src/content/tils/2020/08/13/code-jekyll.adoc155
-rw-r--r--src/content/tils/2020/08/14/browse-git.adoc84
-rw-r--r--src/content/tils/2020/08/16/git-search.adoc59
-rw-r--r--src/content/tils/2020/08/28/grep-online.adoc139
5 files changed, 481 insertions, 0 deletions
diff --git a/src/content/tils/2020/08/12/filename-timestamp.adoc b/src/content/tils/2020/08/12/filename-timestamp.adoc
new file mode 100644
index 0000000..7495fc9
--- /dev/null
+++ b/src/content/tils/2020/08/12/filename-timestamp.adoc
@@ -0,0 +1,44 @@
+---
+
+title: Simple filename timestamp
+
+date: 2020-08-12
+
+updated_at:
+
+layout: post
+
+lang: en
+
+ref: simple-filename-timestamp
+
+eu_categories: shell
+
+---
+
+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`.
+
+```shell
+./my-program.sh > my-program.$(date -I).log
+cp post-template.md _posts/$(date -I)-post-slug.md
+```
+
+Using this built-in GNU/Linux tool allows you to `touch $(date -I).md` to readily
+create a `2020-08-12.md` file.
+
+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:
+
+```shell
+# inside my-program.sh
+echo "Program started at $(date -Is)"
+# output is:
+# Program started at 2020-08-12T09:04:58-03:00
+```
+
+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.
diff --git a/src/content/tils/2020/08/13/code-jekyll.adoc b/src/content/tils/2020/08/13/code-jekyll.adoc
new file mode 100644
index 0000000..6566928
--- /dev/null
+++ b/src/content/tils/2020/08/13/code-jekyll.adoc
@@ -0,0 +1,155 @@
+---
+title: Anchor headers and code lines in Jekyll
+date: 2020-08-13
+layout: post
+lang: en
+ref: anchor-headers-and-code-lines-in-jekyll
+---
+The default Jekyll toolbox ([Jekyll][0], [kramdown][1] and [rouge][2]) doesn't
+provide with a configuration option to add anchors to headers and code blocks.
+
+[0]: https://jekyllrb.com/
+[1]: https://kramdown.gettalong.org/
+[2]: http://rouge.jneen.net/
+
+The best way I found of doing this is by creating a simple Jekyll plugin, more
+specifically, a [Jekyll hook][3]. These allow you to jump in to the Jekyll build
+and add a processing stage before of after Jekyll performs something.
+
+[3]: https://jekyllrb.com/docs/plugins/hooks/
+
+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.
+
+## Anchor on headers
+
+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:
+
+```ruby
+Jekyll::Hooks.register :documents, :post_render do |doc|
+ if doc.output_ext == ".html"
+ doc.output =
+ doc.output.gsub(
+ /<h([1-6])(.*?)id="([\w-]+)"(.*?)>(.*?)<\/h[1-6]>/,
+ '<a href="#\3"><h\1\2id="\3"\4>\5</h\1></a>'
+ )
+ end
+end
+```
+
+I've derived my implementations from two "official"[^official] hooks,
+[jemoji][4] and [jekyll-mentions][5].
+
+[4]: https://github.com/jekyll/jemoji
+[5]: https://github.com/jekyll/jekyll-mentions
+[^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.
+
+All I did was to wrap the header tag inside an `<a>`, and set the `href` of that
+`<a>` to the existing id of the header. Before the hook the HTML looks like:
+
+```html
+...some unmodified text...
+<h2 id="my-header">
+ My header
+</h2>
+...more unmodified text...
+```
+
+And after the hook should turn that into:
+
+```html
+...some unmodified text...
+<a href="#my-header">
+ <h2 id="my-header">
+ My header
+ </h2>
+</a>
+...more unmodified text...
+```
+
+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][6]. 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.
+
+[6]: https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454
+
+In the new anchor tag you can add your custom CSS class to style it as you wish.
+
+## Anchor on code blocks
+
+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.
+
+Similarly, this Jekyll hook also works on `:documents` in the `:post_render`
+phase:
+
+```ruby
+PREFIX = '<pre class="lineno">'
+POSTFIX = '</pre>'
+Jekyll::Hooks.register :documents, :post_render do |doc|
+ if doc.output_ext == ".html"
+ code_block_counter = 1
+ doc.output = doc.output.gsub(/<pre class="lineno">[\n0-9]+<\/pre>/) do |match|
+ line_numbers = match
+ .gsub(/<pre class="lineno">([\n0-9]+)<\/pre>/, '\1')
+ .split("\n")
+
+ anchored_line_numbers_array = line_numbers.map do |n|
+ id = "B#{code_block_counter}-L#{n}"
+ "<a id=\"#{id}\" href=\"##{id}\">#{n}</a>"
+ end
+ code_block_counter += 1
+
+ PREFIX + anchored_line_numbers_array.join("\n") + POSTFIX
+ end
+ end
+end
+```
+
+This solution assumes the default Jekyll toolbox with code line numbers turned
+on in `_config.yml`:
+
+```yaml
+kramdown:
+ syntax_highlighter_opts:
+ span:
+ line_numbers: false
+ block:
+ line_numbers: true
+```
+
+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:
+
+```html
+...some unmodified text...
+<pre class="lineno">1
+2
+3
+4
+5
+</pre>
+...more unmodified text...
+```
+
+And after the hook should turn that into:
+
+```html
+...some unmodified text...
+<pre class="lineno"><a id="B1-L1" href="#B1-L1">1</a>
+<a id="B1-L2" href="#B1-L2">2</a>
+<a id="B1-L3" href="#B1-L3">3</a>
+<a id="B1-L4" href="#B1-L4">4</a>
+<a id="B1-L5" href="#B1-L5">5</a></pre>
+...more unmodified text...
+```
+
+Happy writing :)
diff --git a/src/content/tils/2020/08/14/browse-git.adoc b/src/content/tils/2020/08/14/browse-git.adoc
new file mode 100644
index 0000000..d06f0c1
--- /dev/null
+++ b/src/content/tils/2020/08/14/browse-git.adoc
@@ -0,0 +1,84 @@
+---
+
+title: Browse a git repository at a specific commit
+
+date: 2020-08-14
+
+layout: post
+
+lang: en
+
+ref: browse-a-git-repository-at-a-specific-commit
+
+eu_categories: git
+
+---
+
+I commonly use tools like `git log` together with `git show` when inspecting
+past changes in a repository:
+
+```shell
+git log
+# search for a the commit I'm looking for
+git show <my-commit>
+# see the diff for the commit
+```
+
+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.
+
+I used to accomplish it the "brute force" way: clone the whole repository in
+another folder and checkout the commit there:
+
+```shell
+git clone <original-repo> /tmp/tmp-repo-clone
+cd /tmp-repo-clone
+git checkout <my-commit>
+```
+
+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:
+
+```txt
+--work-tree=<path>
+ Set the path to the working tree. It can be an absolute path or a path relative to the current working
+ directory. This can also be controlled by setting the GIT_WORK_TREE environment variable and the
+ core.worktree configuration variable (see core.worktree in git-config(1) for a more detailed
+ discussion).
+```
+
+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/`:
+
+```shell
+mkdir copy
+git --work-tree=copy/ checkout .
+```
+
+After that `copy/` will contain a replica of the code in HEAD. But to checkout a
+specific, we need some extra parameters:
+
+```shell
+git --work-tree=<dir> checkout <my-commit> -- .
+```
+
+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 `<my-commit>` we want to look at. Which means we can do
+something like:
+
+```shell
+git --work-tree=<dir> checkout <my-commit> -- src/
+```
+
+And with that `<dir>` will only contain what was inside `src/` at `<commit>`.
+
+After any of those checkouts, you have to `git reset .` to reset your current
+staging area back to what it was before the checkout.
+
+
+## References
+
+1. [GIT: Checkout to a specific folder][0] (StackOverflow)
+
+[0]: https://stackoverflow.com/a/16493707
diff --git a/src/content/tils/2020/08/16/git-search.adoc b/src/content/tils/2020/08/16/git-search.adoc
new file mode 100644
index 0000000..f3ae6f0
--- /dev/null
+++ b/src/content/tils/2020/08/16/git-search.adoc
@@ -0,0 +1,59 @@
+---
+
+title: Search in git
+
+date: 2020-08-16
+
+layout: post
+
+lang: en
+
+ref: search-in-git
+
+eu_categories: git
+
+---
+
+Here's a useful trio to know about to help you search things in git:
+
+1. `git show <commit>`
+2. `git log --grep='<regexp>'`
+3. `git grep '<regexp>' [commit]`
+
+## 1. `git show <commit>`
+
+Show a specific commit and it's diff:
+
+```shell
+git show
+# shows the latest commit
+git show <commit>
+# shows an specific <commit>
+git show v1.2
+# shows commit tagged with v1.2
+```
+
+## 2. `git log --grep='<regexp>'`
+
+Search through the commit messages:
+
+```shell
+git log --grep='refactor'
+```
+
+## 3. `git grep '<regexp>' [commit]`
+
+Search content in git history:
+
+```shell
+git grep 'TODO'
+# search the repository for the "TODO" string
+git grep 'TODO' $(git rev-list --all)
+# search the whole history for "TODO" string
+```
+
+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].
+
+[0]: {% link _tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md %}
diff --git a/src/content/tils/2020/08/28/grep-online.adoc b/src/content/tils/2020/08/28/grep-online.adoc
new file mode 100644
index 0000000..8b3b63f
--- /dev/null
+++ b/src/content/tils/2020/08/28/grep-online.adoc
@@ -0,0 +1,139 @@
+---
+
+title: Grep online repositories
+
+date: 2020-08-28
+
+layout: post
+
+lang: en
+
+ref: grep-online-repositories
+
+eu_categories: git
+
+---
+
+I often find interesting source code repositories online that I want to grep for
+some pattern but I can't, because either:
+
+- the repository is on [cgit][cgit] or a similar code repository that doesn't
+ allow search in files, or;
+- the search function is really bad, and doesn't allow me to use regular expressions for searching patterns in the code.
+
+[cgit]: https://git.zx2c4.com/cgit/
+
+Here's a simple script that allows you to overcome that problem easily:
+
+```shell
+#!/usr/bin/env bash
+set -eu
+
+end="\033[0m"
+red="\033[0;31m"
+red() { echo -e "${red}${1}${end}"; }
+
+usage() {
+ red "Missing argument $1.\n"
+ cat <<EOF
+Usage:
+ $0 <REGEX_PATTERN> <REPOSITORY_URL>
+
+ Arguments:
+ REGEX_PATTERN Regular expression that "git grep" can search
+ REPOSITORY_URL URL address that "git clone" can download the repository from
+
+Examples:
+ Searching "make get-git" in cgit repository:
+ git search 'make get-git' https://git.zx2c4.com/cgit/
+ git search 'make get-git' https://git.zx2c4.com/cgit/ -- \$(git rev-list --all)
+EOF
+ exit 2
+}
+
+
+REGEX_PATTERN="${1:-}"
+REPOSITORY_URL="${2:-}"
+[[ -z "${REGEX_PATTERN}" ]] && usage 'REGEX_PATTERN'
+[[ -z "${REPOSITORY_URL}" ]] && usage 'REPOSITORY_URL'
+
+mkdir -p /tmp/git-search
+DIRNAME="$(echo "${REPOSITORY_URL%/}" | rev | cut -d/ -f1 | rev)"
+if [[ ! -d "/tmp/git-search/${DIRNAME}" ]]; then
+ git clone "${REPOSITORY_URL}" "/tmp/git-search/${DIRNAME}"
+fi
+pushd "/tmp/git-search/${DIRNAME}"
+
+shift 3 || shift 2 # when "--" is missing
+git grep "${REGEX_PATTERN}" "${@}"
+```
+
+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.
+
+Overview:
+
+- *lines 1~2*:
+
+ Bash shebang and the `set -eu` options to exit on error or undefined
+ variables.
+
+- *lines 4~30*:
+
+ Usage text to be printed when providing less arguments than expected.
+
+- *line 33*:
+
+ Extract the repository name from the URL, removing trailing slashes.
+
+- *lines 34~37*:
+
+ Download the repository when missing and go to the folder.
+
+- *line 39*:
+
+ Make the variable `$@` contain the rest of the unused arguments.
+
+- *line 40*:
+
+ Perform `git grep`, forwarding the remaining arguments from `$@`.
+
+Example output:
+```shell
+$ git search 'make get-git' https://git.zx2c4.com/cgit/
+Clonage dans '/tmp/git-search/cgit'...
+remote: Enumerating objects: 542, done.
+remote: Counting objects: 100% (542/542), done.
+remote: Compressing objects: 100% (101/101), done.
+warning: object 51dd1eff1edc663674df9ab85d2786a40f7ae3a5: gitmodulesParse: could not parse gitmodules blob
+remote: Total 7063 (delta 496), reused 446 (delta 441), pack-reused 6521
+Réception d'objets: 100% (7063/7063), 8.69 Mio | 5.39 Mio/s, fait.
+Résolution des deltas: 100% (5047/5047), fait.
+/tmp/git-search/cgit ~/dev/libre/songbooks/docs
+README: $ make get-git
+
+$ git search 'make get-git' https://git.zx2c4.com/cgit/
+/tmp/git-search/cgit ~/dev/libre/songbooks/docs
+README: $ make get-git
+```
+
+Subsequent greps on the same repository are faster because no download is needed.
+
+When no argument is provided, it prints the usage text:
+```shell
+$ git search
+Missing argument REGEX_PATTERN.
+
+Usage:
+ /home/andreh/dev/libre/dotfiles/scripts/ad-hoc/git-search <REGEX_PATTERN> <REPOSITORY_URL>
+
+ Arguments:
+ REGEX_PATTERN Regular expression that "git grep" can search
+ REPOSITORY_URL URL address that "git clone" can download the repository from
+
+Examples:
+ Searching "make get-git" in cgit repository:
+ git search 'make get-git' https://git.zx2c4.com/cgit/
+ git search 'make get-git' https://git.zx2c4.com/cgit/ -- $(git rev-list --all)
+```