1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-18 06:28:02 +00:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Mohammad Alyetama
fa55891c05 Merge bc767a0ad3 into eb3369d296 2025-02-12 17:15:38 +02:00
jbranchaud
eb3369d296 Add Limit Protocols Used In A cURL Command as a Unix TIL 2025-02-10 17:10:15 -06:00
jbranchaud
6f47e2f057 Add Uninstall LogiTech G Hub From Mac as a Mac TIL 2025-02-10 15:24:15 -06:00
jbranchaud
409201611f Add Get Word Count For All Files In Git Repo as a Unix TIL 2025-02-08 18:07:54 -06:00
jbranchaud
77cc07a908 Add Reference Commits Earlier Than Reflog Remembers as a Git TIL 2025-02-07 22:09:28 -06:00
jbranchaud
633c1fa0a5 Add Count The Number Of Words On A Webpage as a Unix TIL 2025-02-05 11:28:06 -06:00
jbranchaud
96c394c198 Add Extract Capture Group Matches With String Slices as a Ruby TIL 2025-02-03 15:29:56 -06:00
jbranchaud
0251157dc4 Add Determine The Configured Primary Key Type as a Rails TIL 2025-02-02 21:50:16 -06:00
jbranchaud
97c8701a5a Add Use Labels To Block PR Merge as a GitHub Actions PR 2025-02-01 14:10:25 -06:00
jbranchaud
1fd64e478a Clarify some things in the latest TIL 2025-01-31 14:34:53 -06:00
jbranchaud
8ea123369b Add Trim Leading And Trailing Space From String as a Postgres TIL 2025-01-31 14:23:34 -06:00
Mohammad Alyetama
bc767a0ad3 Update bew cask command 2022-11-24 17:49:13 -05:00
11 changed files with 317 additions and 2 deletions

View File

@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
_1580 TILs and counting..._
_1589 TILs and counting..._
See some of the other learning resources I work on:
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
@@ -356,6 +356,7 @@ See some of the other learning resources I work on:
- [Quicker Commit Fixes With The Fixup Flag](git/quicker-commit-fixes-with-the-fixup-flag.md)
- [Rebase Commits With An Arbitrary Command](git/rebase-commits-with-an-arbitrary-command.md)
- [Reference A Commit Via Commit Message Pattern Matching](git/reference-a-commit-via-commit-message-pattern-matching.md)
- [Reference Commits Earlier Than Reflog Remembers](git/reference-commits-earlier-than-reflog-remembers.md)
- [Remove Untracked Files From A Directory](git/remove-untracked-files-from-a-directory.md)
- [Rename A Remote](git/rename-a-remote.md)
- [Renaming A Branch](git/renaming-a-branch.md)
@@ -407,6 +408,7 @@ See some of the other learning resources I work on:
- [Disable A Workflow With The gh CLI](github-actions/disable-a-workflow-with-the-gh-cli.md)
- [Reference An Encrypted Secret In An Action](github-actions/reference-an-encrypted-secret-in-an-action.md)
- [Trigger A Workflow Via An API Call](github-actions/trigger-a-workflow-via-an-api-call.md)
- [Use Labels To Block PR Merge](github-actions/use-labels-to-block-pr-merge.md)
### Go
@@ -669,6 +671,7 @@ See some of the other learning resources I work on:
- [Set A Window To Its Default Zoom Level](mac/set-a-window-to-its-default-zoom-level.md)
- [Specify App When Opening From Command Line](mac/specify-app-when-opening-from-command-line.md)
- [Start Amphetamine Session With AppleScript](mac/start-amphetamine-session-with-applescript.md)
- [Uninstall LogiTech G Hub From Mac](mac/uninstall-logitech-g-hub-from-mac.md)
- [Use A Different Font With iTerm2](mac/use-a-different-font-with-iterm2.md)
- [Use Default Screenshot Shortcuts With CleanShot X](mac/use-default-screenshot-shortcuts-with-cleanshot-x.md)
- [View All Windows Of The Current App](mac/view-all-windows-of-the-current-app.md)
@@ -899,6 +902,7 @@ See some of the other learning resources I work on:
- [Timestamp Functions](postgres/timestamp-functions.md)
- [Toggling The Pager In PSQL](postgres/toggling-the-pager-in-psql.md)
- [Track psql History Separately Per Database](postgres/track-psql-history-separately-per-database.md)
- [Trim Leading And Trailing Space From String](postgres/trim-leading-and-trailing-space-from-string.md)
- [Truncate All Rows](postgres/truncate-all-rows.md)
- [Truncate Tables With Dependents](postgres/truncate-tables-with-dependents.md)
- [Turning Timing On](postgres/turn-timing-on.md)
@@ -991,6 +995,7 @@ See some of the other learning resources I work on:
- [Define The Root Path For The App](rails/define-the-root-path-for-the-app.md)
- [Delete Paranoid Records](rails/delete-paranoid-records.md)
- [Demodulize A Class Name](rails/demodulize-a-class-name.md)
- [Determine The Configured Primary Key Type](rails/determine-the-configured-primary-key-type.md)
- [Different Ways To Add A Foreign Key Reference](rails/different-ways-to-add-a-foreign-key-reference.md)
- [Disambiguate Where In A Joined Relation](rails/disambiguate-where-in-a-joined-relation.md)
- [Empty find_by Returns First Record](rails/empty-find-by-returns-first-record.md)
@@ -1276,6 +1281,7 @@ See some of the other learning resources I work on:
- [Exit A Process With An Error Message](ruby/exit-a-process-with-an-error-message.md)
- [Expect A Method To Be Called And Actually Call It](ruby/expect-a-method-to-be-called-and-actually-call-it.md)
- [Extract A Column Of Data From A CSV File](ruby/extract-a-column-of-data-from-a-csv-file.md)
- [Extract Capture Group Matches With String Slices](ruby/extract-capture-group-matches-with-string-slices.md)
- [FactoryGirl Sequences](ruby/factory-girl-sequences.md)
- [Fail](ruby/fail.md)
- [Fetch Warns About Superseding Block Argument](ruby/fetch-warns-about-superseding-block-argument.md)
@@ -1494,6 +1500,7 @@ See some of the other learning resources I work on:
- [Count The Lines In A CSV Where A Column Is Empty](unix/count-the-lines-in-a-csv-where-a-column-is-empty.md)
- [Count The Number Of Matches In A Grep](unix/count-the-number-of-matches-in-a-grep.md)
- [Count The Number Of ripgrep Pattern Matches](unix/count-the-number-of-ripgrep-pattern-matches.md)
- [Count The Number Of Words On A Webpage](unix/count-the-number-of-words-on-a-webpage.md)
- [Create A File Descriptor with Process Substitution](unix/create-a-file-descriptor-with-process-substitution.md)
- [Create A Sequence Of Values With A Step](unix/create-a-sequence-of-values-with-a-step.md)
- [Curl With Cookies](unix/curl-with-cookies.md)
@@ -1530,6 +1537,7 @@ See some of the other learning resources I work on:
- [Get Matching Filenames As Output From Grep](unix/get-matching-filenames-as-output-from-grep.md)
- [Get The SHA256 Hash For A File](unix/get-the-sha256-hash-for-a-file.md)
- [Get The Unix Timestamp](unix/get-the-unix-timestamp.md)
- [Get Word Count For All Files In Git Repo](unix/get-word-count-for-all-files-in-git-repo.md)
- [Global Substitution On The Previous Command](unix/global-substitution-on-the-previous-command.md)
- [Globbing For All Directories In Zsh](unix/globbing-for-all-directories-in-zsh.md)
- [Globbing For Filenames In Zsh](unix/globbing-for-filenames-in-zsh.md)
@@ -1548,6 +1556,7 @@ See some of the other learning resources I work on:
- [Killing A Frozen SSH Session](unix/killing-a-frozen-ssh-session.md)
- [Last Argument Of The Last Command](unix/last-argument-of-the-last-command.md)
- [Less With Style](unix/less-with-style.md)
- [Limit Protocols Used In A cURL Command](unix/limit-protocols-used-in-a-curl-command.md)
- [List All Fonts On Your Machine](unix/list-all-fonts-on-your-machine.md)
- [List All The Enabled ZSH Options](unix/list-all-the-enabled-zsh-options.md)
- [List All Users](unix/list-all-users.md)

View File

@@ -0,0 +1,34 @@
# Reference Commits Earlier Than Reflog Remembers
While preparing some stats for a recent blog post on [A Decade of
TILs](https://www.visualmode.dev/a-decade-of-tils), I ran into an issue
referencing chuncks of time further back than 2020.
```bash
git diff --diff-filter=A --name-only HEAD@{2016-02-06}..HEAD@{2017-02-06} -- "*.md"
warning: log for 'HEAD' only goes back to Sun, 20 Dec 2020 00:26:27 -0600
warning: log for 'HEAD' only goes back to Sun, 20 Dec 2020 00:26:27 -0600
```
This is because `HEAD@...` is a reference to the `reflog`. The `reflog` is a
local-only log of objects and activity in the repository. That date looks
suspiciously like the time that I got this specific machine and cloned the
repo.
In order to access this information, I need a different approach of finding
references that bound these points in time.
How about asking `rev-list` for the first commit it can find before the given
dates in 2017 and 2016 and then using those.
```bash
git rev-list -1 --before="2017-02-07 00:00" HEAD
17db6bc4468616786a8f597a10d252c24183d82e
git rev-list -1 --before="2016-02-07 00:00" HEAD
f1d3d1f796007662ff448d6ba0e3bbf38a2b858d
git diff --diff-filter=A --name-only f1d3d1f796007662ff448d6ba0e3bbf38a2b858d..17db6bc4468616786a8f597a10d252c24183d82e -- "*.md"
# git outputs a bunch of files ...
```

View File

@@ -0,0 +1,41 @@
# Use Labels To Block PR Merge
Let's say our GitHub project has custom tags for both `no merge` and `wip`
(_work in progress_). Whenever either of those labels has been applied to a PR,
we want there to be a failed check so as to block the merge. This is useful to
ensure automated tools (as well as someone not looking closely enough) don't
merge a PR that isn't _ready to go_.
This can be achieved with a basic GitHub Actions workflow that requires no
3rd-party actions. We can add the following as
`.github/workflows/block-labeled-prs.yml` in our project.
```yaml
name: Block Labeled PR Merges
on:
pull_request:
types: [labeled, unlabeled, opened, edited, synchronize]
jobs:
prevent-merge:
if: ${{ contains(github.event.*.labels.*.name, 'no merge') || contains(github.event.*.labels.*.name, 'wip') }}
name: Prevent Merging
runs-on: ubuntu-latest
steps:
- name: Check for label
run: |
echo "Pull request label prevents merging."
echo "Labels: ${{ join(github.event.*.labels.*.name, ', ') }}"
echo "Remove the blocking label(s) to skip this check."
exit 1
```
This workflow is run when a pull request is opened, when it is edited or
synchronized, and when a label change is made. The job `prevent-merge` sees if
any of the label names match `no merge` or `wip`. If so, we echo out some
details in the ubuntu container and then `exit 1` to fail the check.
Shoutout to [Jesse Squire's
implementation](https://www.jessesquires.com/blog/2021/08/24/useful-label-based-github-actions-workflows/#updated-21-march-2022)
which I've heavily borrowed from here.

View File

@@ -0,0 +1,17 @@
# Uninstall LogiTech G Hub From Mac
I rarely uninstall software from my Mac. And unless the software is nice enough
to provide a clear 'Uninstall' flow, it is not straightforward how to do it. In
fact, it probably varies quite a bit from app to app.
In the case of LogiTech's G Hub, I was able to find the following instructions
for uninstalling it. The thing of note is that the updater app can take an
`--uninstall` flag.
```bash
sudo /Applications/lghub.app/Contents/MacOS/lghub_updater.app/Contents/MacOS/lghub_updater --uninstall
```
I still had to remove the app launcher from my `Applications` directory.
[source](https://www.reddit.com/r/LogitechG/comments/bluth5/comment/lbhctx1/)

View File

@@ -0,0 +1,58 @@
# Trim Leading And Trailing Space From String
PostgreSQL has a bunch of [string
functions](https://www.postgresql.org/docs/current/functions-string.html),
including several for doing various string trimming.
We can use the simplest form of `trim` to remove leading and trailing space
characters from a string.
```sql
> select trim(' Taco Cat ');
+----------+
| btrim |
|----------|
| Taco Cat |
+----------+
```
The syntax for calling `trim` is a bit odd relative to other PostgreSQL
functions and functions in other languages. Here is the "grammar" as described
in the docs:
```
trim ( [ LEADING | TRAILING | BOTH ] [ characters text ] FROM string text ) → text
```
We pick `leading`, `trailing`, or `both`, with `both` being the default. Then
we specify the character(s) we want to remove. This is also optional, the
default being the space character. Then we say `from` what string we want to
trim those characters.
Here we remove all sequential spaces from `both` ends of the given string:
```sql
> select trim(both from ' Taco Cat ');
+----------+
| btrim |
|----------|
| Taco Cat |
+----------+
```
To further demonstrate how `trim` works, here we remove all sequences made up
of any of spaces, uppercase `T`, and lowercase `t` from `both` ends of the
string:
```sql
> select trim(both ' Tt' from ' Taco Cat ');
+--------+
| btrim |
|--------|
| aco Ca |
+--------+
```
Notice that in all the above examples the column name of the result is `btrim`.
That's probably because `btrim` (_trim both ends_) is being called under the
hood for the `both` option.

View File

@@ -0,0 +1,35 @@
# Determine The Configured Primary Key Type
I noticed an interesting helper function in the database migration generated by
`bin/rails active_storage:install`.
```ruby
class CreateActiveStorageTables < ActiveRecord::Migration[8.0]
def change
# Use Active Record's configured type for primary and foreign keys
primary_key_type, foreign_key_type = primary_and_foreign_key_types
# ...
end
private
def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[ primary_key_type, foreign_key_type ]
end
end
```
The `primary_and_foreign_key_types` method looks in the generators config for
the ORM (`:active_record`) to determine the configured `:primary_key_type`. By
default this will return `nil`. This method then uses `:primary_key` as a
fallback value which will be `bigint`. That's why the `foreign_key_type` falls
back to `:bigint`.
If desired, this can be manually configured in `config/application.rb` like
shown in the [ActiveRecord Migrations
docs](https://guides.rubyonrails.org/active_record_migrations.html#enabling-uuids-in-rails).

View File

@@ -0,0 +1,37 @@
# Extract Capture Group Matches With String Slices
Ruby's _string slice_ syntax allows us to use the square brackets to access
portions of a string. It's most common to pass positional integer index
arguments or a range. However, in true Ruby fashion, another way of thinking
about defining the slice of a string is based on a regex match.
We can pass a regex and an int (specifying which match we want) to extract some
portion of a string based on the regex match. That includes capture groups.
Here are a couple examples of extracting matching capture groups as well as
getting the entire regex match:
```ruby
> "me+abc123@email.com"[/.+\+(.+)@(.+)/, 1]
=> "abc123"
> "me+abc123@email.com"[/.+\+(.+)@(.+)/, 2]
=> "email.com"
> "me+abc123@email.com"[/.+\+(.+)@(.+)/, 0]
=> "me+abc123@email.com"
> "me+abc123@email.com"[/.+\+(.+)@(.+)/]
=> "me+abc123@email.com"
```
The `0`th match (which is the default) corresponds to the full match. Each
integer position after that corresponds to any capture groups. This maps
directly to the underlying `MatchData` object:
```ruby
> /.+\+(.+)@(.+)/.match("me+abc123@email.com")
=> #<MatchData "me+abc123@email.com" 1:"abc123" 2:"email.com">
```
[source](https://ruby-doc.org/3.3.6/String.html#class-String-label-String+Slices)

View File

@@ -0,0 +1,25 @@
# Count The Number Of Words On A Webpage
I was reading through a couple sections of the `postfix` documentation and I
was astounded at how large the webpage is, and that is just for the `main.cf`
file format.
Curiosity got the best of me and I wanted to get a sense of the magnitude of
the page. A word count seemed like a good measure.
Using `pandoc` and a couple other unix utilities, I was able to quickly get
that number.
```bash
curl -s http://www.postfix.org/postconf.5.html\#virtual_mailbox_maps | pandoc -f html -t plain | wc -w
88383
```
Generically, that is:
```bash
curl -s url | pandoc -f html -t plain | wc -w
```
Pandoc produces a plain-text version of the HTML page that was pulled in by
`curl` and then we use `wc` to get a word (`-w`) count.

View File

@@ -0,0 +1,32 @@
# Get Word Count For All Files In Git Repo
As part of gathering numbers for [A Decade of TILs](), I wanted to get an word
count of all the TIL markdown files I've committed to this project over its 10
year history. By using `git ls-files` with a pattern, I can get a list of all
file names. Then with `xargs` I can pass that entire list to `wc -w` which
gives a word count of each. The final line that `wc -w` outputs is a sum total
of all the file word counts. Lastly, piping that through `tail -n1` gives me
just that last total count line.
```bash
$ git ls-files "*/**.md" | xargs wc -w | tail -n1
206816 total
```
Since the `tail -n1` obfuscates what the `wc -w` is doing, here is what that
looks like before that final pipe.
```bash
$ git ls-files "*/**.md" | tail -n3 | xargs wc -w
115 zsh/add-to-the-path-via-path-array.md
190 zsh/link-a-scalar-to-an-array.md
214 zsh/use-a-space-to-exclude-command-from-history.md
519 total
```
I can even clean up the final output a bit more with `awk`:
```bash
$ git ls-files "*/**.md" | xargs wc -w | tail -n1 | awk '{print $1}'
206816
```

View File

@@ -0,0 +1,27 @@
# Limit Protocols Used In A cURL Command
I was about to install [`atuin`](https://github.com/atuinsh/atuin). I went to
their _Quick Start_ section to grab whatever command I would need to install
it. It was a `curl` statement piped to `sh`. The thing that caught my attention
though was I `curl` flag that I didn't recognize — `--proto`.
> Tells curl to limit what protocols it may use for transfers.
Using `curl --proto '=https' ...` we can enforce that only an `https` URL can
be used in this command.
Here is what happens if I try to run the `atuin`-provided `curl` command after
I have downgraded their URL to be `http`:
```bash
curl --proto '=https' --tlsv1.2 -LsSf http://setup.atuin.sh | sh
curl: (1) Protocol "http" not supported or disabled in libcurl
```
It doesn't even attempt the request. The protocol is considered unsupported and
the command immediately fails.
In addition to only installing software we trust, we should make sure we are
only doing so over a protocol we trust (namely, `https`).
See `man curl` for more details, including about the modifiers (`=`, `+`, `-`).

View File

@@ -6,7 +6,7 @@ convert it using the `ebook-convert` binary from `Calibre`.
First, install `Calibre`:
```bash
$ brew cask install calibre
$ brew install --cask calibre
```
Then convert your ePub using `ebook-convert`: