1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-16 13:38:02 +00:00

Compare commits

2 Commits

Author SHA1 Message Date
Mohammad Alyetama
9327c4225c Merge bc767a0ad3 into 77f3c6a43d 2024-12-07 20:35:56 +02:00
Mohammad Alyetama
bc767a0ad3 Update bew cask command 2022-11-24 17:49:13 -05:00
206 changed files with 17 additions and 7707 deletions

5
.gitmodules vendored
View File

@@ -1,5 +0,0 @@
[submodule "notes"]
path = notes
url = git@github.com:jbranchaud/til-notes-private.git
branch = main
ignore = all

256
README.md
View File

@@ -6,32 +6,22 @@ A collection of concise write-ups on small things I learn day to day across a
variety of languages and technologies. These are things that don't really variety of languages and technologies. These are things that don't really
warrant a full blog post. These are things I've picked up by [Learning In warrant a full blog post. These are things I've picked up by [Learning In
Public™](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and Public™](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and
working across different projects via [VisualMode](https://www.visualmode.dev/). pairing with smart people at Hashrocket.
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter). For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
_1728 TILs and counting..._ _1531 TILs and counting..._
See some of the other learning resources I work on:
- [Get Started with Vimium](https://egghead.io/courses/get-started-with-vimium~3t5f7)
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
- [Vim Un-Alphabet](https://www.youtube.com/playlist?list=PL46-cKSxMYYCMpzXo6p0Cof8hJInYgohU)
If you've learned something here, support my efforts writing daily TILs by
[buying me a coffee](https://buymeacoffee.com/jbranchaud) 💜
--- ---
### Categories ### Categories
* [Ack](#ack) * [Ack](#ack)
* [Amplify](#amplify)
* [Ansible](#ansible) * [Ansible](#ansible)
* [Astro](#astro) * [Astro](#astro)
* [AWS](#aws)
* [Brew](#brew) * [Brew](#brew)
* [Chrome](#chrome) * [Chrome](#chrome)
* [Claude Code](#claude-code)
* [Clojure](#clojure) * [Clojure](#clojure)
* [CSS](#css) * [CSS](#css)
* [Deno](#deno) * [Deno](#deno)
@@ -41,7 +31,6 @@ If you've learned something here, support my efforts writing daily TILs by
* [Elixir](#elixir) * [Elixir](#elixir)
* [Gatsby](#gatsby) * [Gatsby](#gatsby)
* [Git](#git) * [Git](#git)
* [GitHub](#github)
* [GitHub Actions](#github-actions) * [GitHub Actions](#github-actions)
* [Go](#go) * [Go](#go)
* [GROQ](#groq) * [GROQ](#groq)
@@ -58,7 +47,6 @@ If you've learned something here, support my efforts writing daily TILs by
* [Linux](#linux) * [Linux](#linux)
* [LLM](#llm) * [LLM](#llm)
* [Mac](#mac) * [Mac](#mac)
* [Mise](#mise)
* [MongoDB](#mongodb) * [MongoDB](#mongodb)
* [MySQL](#mysql) * [MySQL](#mysql)
* [Neovim](#neovim) * [Neovim](#neovim)
@@ -84,7 +72,6 @@ If you've learned something here, support my efforts writing daily TILs by
* [SQLite](#sqlite) * [SQLite](#sqlite)
* [Streaming](#streaming) * [Streaming](#streaming)
* [Tailwind CSS](#tailwind-css) * [Tailwind CSS](#tailwind-css)
* [Taskfile](#taskfile)
* [tmux](#tmux) * [tmux](#tmux)
* [TypeScript](#typescript) * [TypeScript](#typescript)
* [Unix](#unix) * [Unix](#unix)
@@ -106,6 +93,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Case-Insensitive Search](ack/case-insensitive-search.md) - [Case-Insensitive Search](ack/case-insensitive-search.md)
- [List Available File Types](ack/list-available-file-types.md) - [List Available File Types](ack/list-available-file-types.md)
### Amplify
- [Sign Up User With Email And Password](amplify/sign-up-user-with-email-and-password.md)
### Ansible ### Ansible
- [Loop Over A List Of Dictionaries](ansible/loop-over-a-list-of-dictionaries.md) - [Loop Over A List Of Dictionaries](ansible/loop-over-a-list-of-dictionaries.md)
@@ -115,24 +106,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Generate Types For A Content Collection](astro/generate-types-for-a-content-collection.md) - [Generate Types For A Content Collection](astro/generate-types-for-a-content-collection.md)
- [Markdown Files Are Of Type MarkdownInstance](astro/markdown-files-are-of-type-markdown-instance.md) - [Markdown Files Are Of Type MarkdownInstance](astro/markdown-files-are-of-type-markdown-instance.md)
### AWS
- [AWS CLI Requires Groff Executable](aws/aws-cli-requires-groff-executable.md)
- [Find And Follow Server Logs](aws/find-and-follow-server-logs.md)
- [List RDS Snapshots With Matching Identifier Prefix](aws/list-rds-snapshots-with-matching-identifier-prefix.md)
- [Output CLI Results In Different Formats](aws/output-cli-results-in-different-formats.md)
- [Sign Up User With Email And Password](aws/sign-up-user-with-email-and-password.md)
- [SSH Into An ECS Container](aws/ssh-into-an-ecs-container.md)
- [Turn Off Output Pager For A Command](aws/turn-off-output-pager-for-a-command.md)
- [Use Specific AWS Profile With CLI](aws/use-specific-aws-profile-with-cli.md)
### Brew ### Brew
- [Clean Up Your Brew Installations](brew/clean-up-your-brew-installations.md)
- [Configure Brew Environment Variables](brew/configure-brew-environment-variables.md) - [Configure Brew Environment Variables](brew/configure-brew-environment-variables.md)
- [Export List Of Everything Installed By Brew](brew/export-list-of-everything-installed-by-brew.md) - [Export List Of Everything Installed By Brew](brew/export-list-of-everything-installed-by-brew.md)
- [Install From Nonstandard Brewfile](brew/install-from-nonstandard-brewfile.md)
- [Install Go Packages In Brewfile](brew/install-go-packages-in-brewfile.md)
- [List All Services Managed By Brew](brew/list-all-services-managed-by-brew.md) - [List All Services Managed By Brew](brew/list-all-services-managed-by-brew.md)
### Chrome ### Chrome
@@ -143,12 +120,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Duplicate The Current Tab](chrome/duplicate-the-current-tab.md) - [Duplicate The Current Tab](chrome/duplicate-the-current-tab.md)
- [Easier Access To Network Throttling Controls](chrome/easier-access-to-network-throttling-controls.md) - [Easier Access To Network Throttling Controls](chrome/easier-access-to-network-throttling-controls.md)
- [Keybinding To Focus The Address Bar](chrome/keybinding-to-focus-the-address-bar.md) - [Keybinding To Focus The Address Bar](chrome/keybinding-to-focus-the-address-bar.md)
- [Open Current Tab In New Window With Vimium](chrome/open-current-tab-in-new-window-with-vimium.md)
- [Pause JavaScript From The Source DevTools Panel](chrome/pause-javascript-from-the-source-devtools-panel.md) - [Pause JavaScript From The Source DevTools Panel](chrome/pause-javascript-from-the-source-devtools-panel.md)
- [Navigate The Browser History With Vimium](chrome/navigate-the-browser-history-with-vimium.md) - [Navigate The Browser History With Vimium](chrome/navigate-the-browser-history-with-vimium.md)
- [Pretty Print Tabular Data](chrome/pretty-print-tabular-data.md) - [Pretty Print Tabular Data](chrome/pretty-print-tabular-data.md)
- [Reference The Selected Node](chrome/reference-the-selected-node.md) - [Reference The Selected Node](chrome/reference-the-selected-node.md)
- [Search Tabs With The Vimium Vomnibar](chrome/search-tabs-with-the-vimium-vomnibar.md)
- [Selecting DOM Elements Faster Than Ever](chrome/selecting-dom-elements-faster-than-ever.md) - [Selecting DOM Elements Faster Than Ever](chrome/selecting-dom-elements-faster-than-ever.md)
- [Simulating Various Connection Speeds](chrome/simulating-various-connection-speeds.md) - [Simulating Various Connection Speeds](chrome/simulating-various-connection-speeds.md)
- [Toggle Device Mode](chrome/toggle-device-mode.md) - [Toggle Device Mode](chrome/toggle-device-mode.md)
@@ -156,13 +131,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Trigger Commands From The Devtools Command Palette](chrome/trigger-commands-from-the-devtools-command-palette.md) - [Trigger Commands From The Devtools Command Palette](chrome/trigger-commands-from-the-devtools-command-palette.md)
- [View Network Traffic For New Tabs](chrome/view-network-traffic-for-new-tabs.md) - [View Network Traffic For New Tabs](chrome/view-network-traffic-for-new-tabs.md)
### Claude Code
- [Allow Edits From The Start](claude-code/allow-edits-from-the-start.md)
- [Monitor Usage Limits From CLI](claude-code/monitor-usage-limits-from-cli.md)
- [Open Current Prompt In Default Editor](claude-code/open-current-prompt-in-default-editor.md)
- [Resume Specific Session](claude-code/resume-specific-session.md)
### Clojure ### Clojure
- [Aggregation Using merge-with](clojure/aggregation-using-merge-with.md) - [Aggregation Using merge-with](clojure/aggregation-using-merge-with.md)
@@ -204,22 +172,16 @@ If you've learned something here, support my efforts writing daily TILs by
- [Define HSL Colors With Alpha Values](css/define-hsl-colors-with-alpha-values.md) - [Define HSL Colors With Alpha Values](css/define-hsl-colors-with-alpha-values.md)
- [Display Responsive iframe Maintaining Aspect Ratio](css/display-responsive-iframe-maintaining-aspect-ratio.md) - [Display Responsive iframe Maintaining Aspect Ratio](css/display-responsive-iframe-maintaining-aspect-ratio.md)
- [Dry Up SCSS With Mixins](css/dry-up-scss-with-mixins.md) - [Dry Up SCSS With Mixins](css/dry-up-scss-with-mixins.md)
- [Filter Blur Requires Expensive Calculation](css/filter-blur-requires-expensive-calculation.md)
- [Give Elements The Same Width With Flexbox](css/give-elements-the-same-width-with-flexbox.md) - [Give Elements The Same Width With Flexbox](css/give-elements-the-same-width-with-flexbox.md)
- [Let Pointer Events Pass Through An Element](css/let-pointer-events-pass-through-an-element.md) - [Let Pointer Events Pass Through An Element](css/let-pointer-events-pass-through-an-element.md)
- [Lighten And Darken With CSS Brightness Filter](css/lighten-and-darken-with-css-brightness-filter.md) - [Lighten And Darken With CSS Brightness Filter](css/lighten-and-darken-with-css-brightness-filter.md)
- [Lighten And Darken With SCSS](css/lighten-and-darken-with-scss.md) - [Lighten And Darken With SCSS](css/lighten-and-darken-with-scss.md)
- [Make A Block Of Text Respect New Lines](css/make-a-block-of-text-respect-new-lines.md) - [Make A Block Of Text Respect New Lines](css/make-a-block-of-text-respect-new-lines.md)
- [Parameterized SCSS Mixins](css/parameterized-scss-mixins.md) - [Parameterized SCSS Mixins](css/parameterized-scss-mixins.md)
- [Prevent Invisible Elements From Being Clicked](css/prevent-invisible-elements-from-being-clicked.md)
- [:root Has Higher Specificity Than html](css/root-has-higher-specificity-than-html.md) - [:root Has Higher Specificity Than html](css/root-has-higher-specificity-than-html.md)
- [Style A Background With A Linear Gradient](css/style-a-background-with-a-linear-gradient.md) - [Style A Background With A Linear Gradient](css/style-a-background-with-a-linear-gradient.md)
- [Using Maps In SCSS](css/using-maps-in-scss.md) - [Using Maps In SCSS](css/using-maps-in-scss.md)
### Cursor
- [Allow Cursor To Be Launched From CLI](cursor/allow-cursor-to-be-launched-from-cli.md)
### Deno ### Deno
- [Read In The Contents Of A File](deno/read-in-the-contents-of-a-file.md) - [Read In The Contents Of A File](deno/read-in-the-contents-of-a-file.md)
@@ -233,27 +195,21 @@ If you've learned something here, support my efforts writing daily TILs by
- [Check The Status of All Services](devops/check-the-status-of-all-services.md) - [Check The Status of All Services](devops/check-the-status-of-all-services.md)
- [Check The Syntax Of nginx Files](devops/check-the-syntax-of-nginx-files.md) - [Check The Syntax Of nginx Files](devops/check-the-syntax-of-nginx-files.md)
- [Connect To An RDS PostgreSQL Database](devops/connect-to-an-rds-postgresql-database.md) - [Connect To An RDS PostgreSQL Database](devops/connect-to-an-rds-postgresql-database.md)
- [Default Rails Deploy Script On Hatchbox](devops/default-rails-deploy-script-on-hatchbox.md)
- [Determine The IP Address Of A Domain](devops/determine-the-ip-address-of-a-domain.md) - [Determine The IP Address Of A Domain](devops/determine-the-ip-address-of-a-domain.md)
- [Hatchbox Exports Env Vars With asdf](devops/hatchbox-exports-env-vars-with-asdf.md)
- [Path Of The Packets](devops/path-of-the-packets.md) - [Path Of The Packets](devops/path-of-the-packets.md)
- [Push Non-master Branch To Heroku](devops/push-non-master-branch-to-heroku.md) - [Push Non-master Branch To Heroku](devops/push-non-master-branch-to-heroku.md)
- [Reload The nginx Configuration](devops/reload-the-nginx-configuration.md) - [Reload The nginx Configuration](devops/reload-the-nginx-configuration.md)
- [Resolve The Public IP Of A URL](devops/resolve-the-public-ip-of-a-url.md) - [Resolve The Public IP Of A URL](devops/resolve-the-public-ip-of-a-url.md)
- [Running Out Of inode Space](devops/running-out-of-inode-space.md) - [Running Out Of inode Space](devops/running-out-of-inode-space.md)
- [Set Up Domain For Hatchbox Rails App](devops/set-up-domain-for-hatchbox-rails-app.md)
- [SSH Into A Docker Container](devops/ssh-into-a-docker-container.md) - [SSH Into A Docker Container](devops/ssh-into-a-docker-container.md)
- [SSL Certificates Can Cover Multiple Domains](devops/ssl-certificates-can-cover-multiple-domains.md) - [SSL Certificates Can Cover Multiple Domains](devops/ssl-certificates-can-cover-multiple-domains.md)
- [Wipe A Heroku Postgres Database](devops/wipe-a-heroku-postgres-database.md) - [Wipe A Heroku Postgres Database](devops/wipe-a-heroku-postgres-database.md)
### Docker ### Docker
- [Check Postgres Version Running In Docker Container](docker/check-postgres-version-running-in-docker-container.md)
- [Configure Different Host And Container Ports](docker/configure-different-host-and-container-ports.md) - [Configure Different Host And Container Ports](docker/configure-different-host-and-container-ports.md)
- [List Running Docker Containers](docker/list-running-docker-containers.md) - [List Running Docker Containers](docker/list-running-docker-containers.md)
- [Prevent Containers From Running On Startup](docker/prevent-containers-from-running-on-startup.md)
- [Run A Basic PostgreSQL Server In Docker](docker/run-a-basic-postgresql-server-in-docker.md) - [Run A Basic PostgreSQL Server In Docker](docker/run-a-basic-postgresql-server-in-docker.md)
- [Run SQL Script Against Postgres Container](docker/run-sql-script-against-postgres-container.md)
### Drizzle ### Drizzle
@@ -327,52 +283,40 @@ If you've learned something here, support my efforts writing daily TILs by
- [Add Only Tracked Files From A Directory](git/add-only-tracked-files-from-a-directory.md) - [Add Only Tracked Files From A Directory](git/add-only-tracked-files-from-a-directory.md)
- [Amend Author Of Previous Commit](git/amend-author-of-previous-commit.md) - [Amend Author Of Previous Commit](git/amend-author-of-previous-commit.md)
- [Auto-Squash Those Fixup Commits](git/auto-squash-those-fixup-commits.md) - [Auto-Squash Those Fixup Commits](git/auto-squash-those-fixup-commits.md)
- [Better Diffs With Delta](git/better-diffs-with-delta.md)
- [Caching Credentials](git/caching-credentials.md) - [Caching Credentials](git/caching-credentials.md)
- [Change The Start Point Of A Branch](git/change-the-start-point-of-a-branch.md) - [Change The Start Point Of A Branch](git/change-the-start-point-of-a-branch.md)
- [Check How A File Is Being Ignored](git/check-how-a-file-is-being-ignored.md) - [Check How A File Is Being Ignored](git/check-how-a-file-is-being-ignored.md)
- [Check If A File Has Changed In A Script](git/check-if-a-file-has-changed-in-a-script.md)
- [Check If A File Is Under Version Control](git/check-if-a-file-is-under-version-control.md)
- [Checking Commit Ancestry](git/checking-commit-ancestry.md) - [Checking Commit Ancestry](git/checking-commit-ancestry.md)
- [Checkout Old Version Of A File](git/checkout-old-version-of-a-file.md) - [Checkout Old Version Of A File](git/checkout-old-version-of-a-file.md)
- [Checkout Previous Branch](git/checkout-previous-branch.md) - [Checkout Previous Branch](git/checkout-previous-branch.md)
- [Cherry Pick A Range Of Commits](git/cherry-pick-a-range-of-commits.md) - [Cherry Pick A Range Of Commits](git/cherry-pick-a-range-of-commits.md)
- [Cherry Pick Multiple Commits At Once](git/cherry-pick-multiple-commits-at-once.md)
- [Clean Out All Local Branches](git/clean-out-all-local-branches.md) - [Clean Out All Local Branches](git/clean-out-all-local-branches.md)
- [Clean Out Working Copy With Patched Restore](git/clean-out-working-copy-with-patched-restore.md) - [Clean Out Working Copy With Patched Restore](git/clean-out-working-copy-with-patched-restore.md)
- [Clean Up Old Remote Tracking References](git/clean-up-old-remote-tracking-references.md) - [Clean Up Old Remote Tracking References](git/clean-up-old-remote-tracking-references.md)
- [Clear Entries From Git Stash](git/clear-entries-from-git-stash.md)
- [Clone A Repo Just For The Files, Without History](git/clone-a-repo-just-for-the-files-without-history.md) - [Clone A Repo Just For The Files, Without History](git/clone-a-repo-just-for-the-files-without-history.md)
- [Clone A Repo Locally From .git](git/clone-a-repo-locally-from-git.md) - [Clone A Repo Locally From .git](git/clone-a-repo-locally-from-git.md)
- [Configure Global gitignore File](git/configure-global-gitignore-file.md) - [Configure Global gitignore File](git/configure-global-gitignore-file.md)
- [Configuring The Pager](git/configuring-the-pager.md) - [Configuring The Pager](git/configuring-the-pager.md)
- [Copy A File From Another Branch](git/copy-a-file-from-another-branch.md) - [Copy A File From Another Branch](git/copy-a-file-from-another-branch.md)
- [Count All Files Of Specific Type Tracked By Git](git/count-all-files-of-specific-type-tracked-by-git.md) - [Count All Files Of Specific Type Tracked By Git](git/count-all-files-of-specific-type-tracked-by-git.md)
- [Count Number Of Commits On A Branch](git/count-number-of-commits-on-a-branch.md)
- [Create A New Branch With Git Switch](git/create-a-new-branch-with-git-switch.md) - [Create A New Branch With Git Switch](git/create-a-new-branch-with-git-switch.md)
- [Delete All Untracked Files](git/delete-all-untracked-files.md) - [Delete All Untracked Files](git/delete-all-untracked-files.md)
- [Determine Absolute Path Of Top-Level Project Directory](git/determine-absolute-path-of-top-level-project-directory.md)
- [Determine The Hash Id For A Blob](git/determine-the-hash-id-for-a-blob.md) - [Determine The Hash Id For A Blob](git/determine-the-hash-id-for-a-blob.md)
- [Diffing With Patience](git/diffing-with-patience.md) - [Diffing With Patience](git/diffing-with-patience.md)
- [Dropping Commits With Git Rebase](git/dropping-commits-with-git-rebase.md) - [Dropping Commits With Git Rebase](git/dropping-commits-with-git-rebase.md)
- [Dry Runs in Git](git/dry-runs-in-git.md) - [Dry Runs in Git](git/dry-runs-in-git.md)
- [Exclude A File From A Diff Output](git/exclude-a-file-from-a-diff-output.md) - [Exclude A File From A Diff Output](git/exclude-a-file-from-a-diff-output.md)
- [Exclude A Directory During A Command](git/exclude-a-directory-during-a-command.md)
- [Excluding Files Locally](git/excluding-files-locally.md) - [Excluding Files Locally](git/excluding-files-locally.md)
- [Extend Git With Custom Commands](git/extend-git-with-custom-commands.md) - [Extend Git With Custom Commands](git/extend-git-with-custom-commands.md)
- [Files With Local Changes Cannot Be Removed](git/files-with-local-changes-cannot-be-removed.md)
- [Find And Remove Files That Match A Name](git/find-and-remove-files-that-match-a-name.md) - [Find And Remove Files That Match A Name](git/find-and-remove-files-that-match-a-name.md)
- [Find The Date That A File Was Added To The Repo](git/find-the-date-that-a-file-was-added-to-the-repo.md) - [Find The Date That A File Was Added To The Repo](git/find-the-date-that-a-file-was-added-to-the-repo.md)
- [Find The Initial Commit](git/find-the-initial-commit.md) - [Find The Initial Commit](git/find-the-initial-commit.md)
- [Fix Whitespace Errors Throughout Branch Commits](git/fix-whitespace-errors-throughout-branch-commits.md)
- [Get Latest Commit Timestamp For A File](git/get-latest-commit-timestamp-for-a-file.md) - [Get Latest Commit Timestamp For A File](git/get-latest-commit-timestamp-for-a-file.md)
- [Get The Name Of The Current Branch](git/get-the-name-of-the-current-branch.md) - [Get The Name Of The Current Branch](git/get-the-name-of-the-current-branch.md)
- [Get The Short Version Of The Latest Commit](git/get-the-short-version-of-the-latest-commit.md) - [Get The Short Version Of The Latest Commit](git/get-the-short-version-of-the-latest-commit.md)
- [Grab A Single File From A Stash](git/grab-a-single-file-from-a-stash.md) - [Grab A Single File From A Stash](git/grab-a-single-file-from-a-stash.md)
- [Grep For A Pattern On Another Branch](git/grep-for-a-pattern-on-another-branch.md) - [Grep For A Pattern On Another Branch](git/grep-for-a-pattern-on-another-branch.md)
- [Grep Over Commit Messages](git/grep-over-commit-messages.md) - [Grep Over Commit Messages](git/grep-over-commit-messages.md)
- [Highlight Extra Whitespace In Diff Output](git/highlight-extra-whitespace-in-diff-output.md)
- [Highlight Small Change On Single Line](git/highlight-small-change-on-single-line.md)
- [Ignore Changes To A Tracked File](git/ignore-changes-to-a-tracked-file.md) - [Ignore Changes To A Tracked File](git/ignore-changes-to-a-tracked-file.md)
- [Ignore Files Specific To Your Workflow](git/ignore-files-specific-to-your-workflow.md) - [Ignore Files Specific To Your Workflow](git/ignore-files-specific-to-your-workflow.md)
- [Include A Message With Your Stashed Changes](git/include-a-message-with-your-stashed-changes.md) - [Include A Message With Your Stashed Changes](git/include-a-message-with-your-stashed-changes.md)
@@ -383,9 +327,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Interactively Unstage Changes](git/interactively-unstage-changes.md) - [Interactively Unstage Changes](git/interactively-unstage-changes.md)
- [Keep File Locally With `git rm`](git/keep-file-locally-with-git-rm.md) - [Keep File Locally With `git rm`](git/keep-file-locally-with-git-rm.md)
- [Last Commit A File Appeared In](git/last-commit-a-file-appeared-in.md) - [Last Commit A File Appeared In](git/last-commit-a-file-appeared-in.md)
- [List All Files Added During Span Of Time](git/list-all-files-added-during-span-of-time.md)
- [List All Files Changed Between Two Branches](git/list-all-files-changed-between-two-branches.md) - [List All Files Changed Between Two Branches](git/list-all-files-changed-between-two-branches.md)
- [List All Git Aliases From gitconfig](git/list-all-git-aliases-from-gitconfig.md)
- [List Branches That Contain A Commit](git/list-branches-that-contain-a-commit.md) - [List Branches That Contain A Commit](git/list-branches-that-contain-a-commit.md)
- [List Commits On A Branch](git/list-commits-on-a-branch.md) - [List Commits On A Branch](git/list-commits-on-a-branch.md)
- [List Different Commits Between Two Branches](git/list-different-commits-between-two-branches.md) - [List Different Commits Between Two Branches](git/list-different-commits-between-two-branches.md)
@@ -402,18 +344,15 @@ If you've learned something here, support my efforts writing daily TILs by
- [Quicker Commit Fixes With The Fixup Flag](git/quicker-commit-fixes-with-the-fixup-flag.md) - [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) - [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 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) - [Remove Untracked Files From A Directory](git/remove-untracked-files-from-a-directory.md)
- [Rename A Remote](git/rename-a-remote.md) - [Rename A Remote](git/rename-a-remote.md)
- [Renaming A Branch](git/renaming-a-branch.md) - [Renaming A Branch](git/renaming-a-branch.md)
- [Resetting A Reset](git/resetting-a-reset.md) - [Resetting A Reset](git/resetting-a-reset.md)
- [Resolve A Merge Conflict From Stash Pop](git/resolve-a-merge-conflict-from-stash-pop.md) - [Resolve A Merge Conflict From Stash Pop](git/resolve-a-merge-conflict-from-stash-pop.md)
- [Restore File From One Branch To The Current](git/restore-file-from-one-branch-to-the-current.md)
- [Review Commits From Before A Certain Date](git/review-commits-from-before-a-certain-date.md) - [Review Commits From Before A Certain Date](git/review-commits-from-before-a-certain-date.md)
- [Run A Git Command From Outside The Repo](git/run-a-git-command-from-outside-the-repo.md) - [Run A Git Command From Outside The Repo](git/run-a-git-command-from-outside-the-repo.md)
- [Set A Custom Pager For A Specific Command](git/set-a-custom-pager-for-a-specific-command.md) - [Set A Custom Pager For A Specific Command](git/set-a-custom-pager-for-a-specific-command.md)
- [Set Default Branch Name For New Repos](git/set-default-branch-name-for-new-repos.md) - [Set Default Branch Name For New Repos](git/set-default-branch-name-for-new-repos.md)
- [Set Up GPG Signing Key](git/set-up-gpg-signing-key.md)
- [Shorthand To Force Push A Branch](git/shorthand-to-force-push-a-branch.md) - [Shorthand To Force Push A Branch](git/shorthand-to-force-push-a-branch.md)
- [Show All Commits For A File Beyond Renaming](git/show-all-commits-for-a-file-beyond-renaming.md) - [Show All Commits For A File Beyond Renaming](git/show-all-commits-for-a-file-beyond-renaming.md)
- [Show Changes For Files That Match A Pattern](git/show-changes-for-files-that-match-a-pattern.md) - [Show Changes For Files That Match A Pattern](git/show-changes-for-files-that-match-a-pattern.md)
@@ -421,13 +360,11 @@ If you've learned something here, support my efforts writing daily TILs by
- [Show File Diffs When Viewing Git Log](git/show-file-diffs-when-viewing-git-log.md) - [Show File Diffs When Viewing Git Log](git/show-file-diffs-when-viewing-git-log.md)
- [Show List Of Most Recently Committed Branches](git/show-list-of-most-recently-committed-branches.md) - [Show List Of Most Recently Committed Branches](git/show-list-of-most-recently-committed-branches.md)
- [Show Only Commits That Touch Specific Lines](git/show-only-commits-that-touch-specific-lines.md) - [Show Only Commits That Touch Specific Lines](git/show-only-commits-that-touch-specific-lines.md)
- [Show Summary Stats For Current Branch](git/show-summary-stats-for-current-branch.md)
- [Show The diffstat Summary Of A Commit](git/show-the-diffstat-summary-of-a-commit.md) - [Show The diffstat Summary Of A Commit](git/show-the-diffstat-summary-of-a-commit.md)
- [Show The Good And The Bad With Git Bisect](git/show-the-good-and-the-bad-with-git-bisect.md) - [Show The Good And The Bad With Git Bisect](git/show-the-good-and-the-bad-with-git-bisect.md)
- [Show What Is In A Stash](git/show-what-is-in-a-stash.md) - [Show What Is In A Stash](git/show-what-is-in-a-stash.md)
- [Single Key Presses in Interactive Mode](git/single-key-presses-in-interactive-mode.md) - [Single Key Presses in Interactive Mode](git/single-key-presses-in-interactive-mode.md)
- [Skip A Bad Commit When Bisecting](git/skip-a-bad-commit-when-bisecting.md) - [Skip A Bad Commit When Bisecting](git/skip-a-bad-commit-when-bisecting.md)
- [Skip Git Hooks As Needed](git/skip-git-hooks-as-needed.md)
- [Skip Pre-Commit Hooks](git/skip-pre-commit-hooks.md) - [Skip Pre-Commit Hooks](git/skip-pre-commit-hooks.md)
- [Staging Changes Within Vim](git/staging-changes-within-vim.md) - [Staging Changes Within Vim](git/staging-changes-within-vim.md)
- [Staging Stashes Interactively](git/staging-stashes-interactively.md) - [Staging Stashes Interactively](git/staging-stashes-interactively.md)
@@ -443,7 +380,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Untrack A Directory Of Files Without Deleting](git/untrack-a-directory-of-files-without-deleting.md) - [Untrack A Directory Of Files Without Deleting](git/untrack-a-directory-of-files-without-deleting.md)
- [Untrack A File Without Deleting It](git/untrack-a-file-without-deleting-it.md) - [Untrack A File Without Deleting It](git/untrack-a-file-without-deleting-it.md)
- [Update The URL Of A Remote](git/update-the-url-of-a-remote.md) - [Update The URL Of A Remote](git/update-the-url-of-a-remote.md)
- [Use External Diff Tool Like Difftastic](git/use-external-diff-tool-like-difftastic.md)
- [Using Commands With A Relative Date Format](git/using-commands-with-a-relative-date-format.md) - [Using Commands With A Relative Date Format](git/using-commands-with-a-relative-date-format.md)
- [Verbose Commit Message](git/verbose-commit-message.md) - [Verbose Commit Message](git/verbose-commit-message.md)
- [Viewing A File On Another Branch](git/viewing-a-file-on-another-branch.md) - [Viewing A File On Another Branch](git/viewing-a-file-on-another-branch.md)
@@ -451,13 +387,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [What Is The Current Branch?](git/what-is-the-current-branch.md) - [What Is The Current Branch?](git/what-is-the-current-branch.md)
- [Whitespace Warnings](git/whitespace-warnings.md) - [Whitespace Warnings](git/whitespace-warnings.md)
### GitHub
- [Access Your GitHub Profile Photo](github/access-your-github-profile-photo.md)
- [Open A PR To An Unforked Repo](github/open-a-pr-to-an-unforked-repo.md)
- [Target Another Repo When Creating A PR](github/target-another-repo-when-creating-a-pr.md)
- [Tell gh What The Default Repo Is](github/tell-gh-what-the-default-repo-is.md)
### GitHub Actions ### GitHub Actions
- [Cache Playwright Dependencies Across Workflows](github-actions/cache-playwright-dependencies-across-workflows.md) - [Cache Playwright Dependencies Across Workflows](github-actions/cache-playwright-dependencies-across-workflows.md)
@@ -465,36 +394,20 @@ If you've learned something here, support my efforts writing daily TILs by
- [Disable A Workflow With The gh CLI](github-actions/disable-a-workflow-with-the-gh-cli.md) - [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) - [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) - [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 ### Go
- [Access Go Docs Offline](go/access-go-docs-offline.md) - [Access Go Docs Offline](go/access-go-docs-offline.md)
- [Add A Method To A Struct](go/add-a-method-to-a-struct.md)
- [Basic Delve Debugging Session](go/basic-delve-debugging-session.md)
- [Build For A Specific OS And Architecture](go/build-for-a-specific-os-and-architecture.md) - [Build For A Specific OS And Architecture](go/build-for-a-specific-os-and-architecture.md)
- [Check If Cobra Flag Was Set](go/check-if-cobra-flag-was-set.md)
- [Combine Two Slices](go/combine-two-slices.md) - [Combine Two Slices](go/combine-two-slices.md)
- [Configure Max String Print Length For Delve](go/configure-max-string-print-length-for-delve.md)
- [Connect To A SQLite Database](go/connect-to-a-sqlite-database.md)
- [Create A Slice From An Array](go/create-a-slice-from-an-array.md)
- [Detect If Stdin Comes From A Redirect](go/detect-if-stdin-comes-from-a-redirect.md)
- [Deterministically Seed A Random Number Generator](go/deterministically-seed-a-random-number-generator.md)
- [Difference Between Slice And Pointer To Slice](go/difference-between-slice-and-pointer-to-slice.md)
- [Do Something N Times](go/do-something-n-times.md) - [Do Something N Times](go/do-something-n-times.md)
- [Find Executables Installed By Go](go/find-executables-installed-by-go.md) - [Find Executables Installed By Go](go/find-executables-installed-by-go.md)
- [Format Date And Time With Time Constants](go/format-date-and-time-with-time-constants.md)
- [Not So Random](go/not-so-random.md) - [Not So Random](go/not-so-random.md)
- [Parse A String Into Individual Fields](go/parse-a-string-into-individual-fields.md) - [Parse A String Into Individual Fields](go/parse-a-string-into-individual-fields.md)
- [Parse Flags From CLI Arguments](go/parse-flags-from-cli-arguments.md) - [Parse Flags From CLI Arguments](go/parse-flags-from-cli-arguments.md)
- [Pass A Struct To A Function](go/pass-a-struct-to-a-function.md)
- [Produce The Zero Value Of A Generic Type](go/produce-the-zero-value-of-a-generic-type.md)
- [Redirect File To Stdin During Delve Debug](go/redirect-file-to-stdin-during-delve-debug.md)
- [Replace The Current Process With An External Command](go/replace-the-current-process-with-an-external-command.md) - [Replace The Current Process With An External Command](go/replace-the-current-process-with-an-external-command.md)
- [Sleep For A Duration](go/sleep-for-a-duration.md) - [Sleep For A Duration](go/sleep-for-a-duration.md)
- [Sort Slice In Ascending Or Descending Order](go/sort-slice-in-ascending-or-descending-order.md)
- [Upgrading From An Older Version On Mac](go/upgrading-from-an-older-version-on-mac.md) - [Upgrading From An Older Version On Mac](go/upgrading-from-an-older-version-on-mac.md)
- [Write A Custom Scan Function For File IO](go/write-a-custom-scan-function-for-file-io.md)
### GROQ ### GROQ
@@ -505,23 +418,19 @@ If you've learned something here, support my efforts writing daily TILs by
### Heroku ### Heroku
- [Check Ruby Version For Production App](heroku/check-ruby-version-for-production-app.md)
- [Connect To A Database By Color](heroku/connect-to-a-database-by-color.md) - [Connect To A Database By Color](heroku/connect-to-a-database-by-color.md)
- [Deploy A Review App To A Different Stack](heroku/deploy-a-review-app-to-a-different-stack.md) - [Deploy A Review App To A Different Stack](heroku/deploy-a-review-app-to-a-different-stack.md)
- [Diagnose Problems In A Heroku Postgres Database](heroku/diagnose-problems-in-a-heroku-postgres-database.md) - [Diagnose Problems In A Heroku Postgres Database](heroku/diagnose-problems-in-a-heroku-postgres-database.md)
- [Open Dashboard For Specific Add-On](heroku/open-dashboard-for-specific-add-on.md) - [Open Dashboard For Specific Add-On](heroku/open-dashboard-for-specific-add-on.md)
- [Run SQL Against Remote Postgres Database](heroku/run-sql-against-remote-postgres-database.md) - [Run SQL Against Remote Postgres Database](heroku/run-sql-against-remote-postgres-database.md)
- [Set And Show Heroku Env Variables](heroku/set-and-show-heroku-env-variables.md) - [Set And Show Heroku Env Variables](heroku/set-and-show-heroku-env-variables.md)
- [Specify Default Team And App For Project](heroku/specify-default-team-and-app-for-project.md)
- [SSH Into Heroku Server Hosting App](heroku/ssh-into-heroku-server-hosting-app.md) - [SSH Into Heroku Server Hosting App](heroku/ssh-into-heroku-server-hosting-app.md)
### HTML ### HTML
- [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md) - [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md)
- [Allow Number Input To Accept Decimal Values](html/allow-number-input-to-accept-decimal-values.md)
- [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md) - [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md)
- [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md) - [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md)
- [Disclose Additional Details](html/disclose-additional-details.md)
- [Make Elements Non-Interactive With Inert](html/make-elements-non-interactive-with-inert.md) - [Make Elements Non-Interactive With Inert](html/make-elements-non-interactive-with-inert.md)
- [Prevent Search Engines From Indexing A Page](html/prevent-search-engines-from-indexing-a-page.md) - [Prevent Search Engines From Indexing A Page](html/prevent-search-engines-from-indexing-a-page.md)
- [Render Text As Superscript](html/render-text-as-superscript.md) - [Render Text As Superscript](html/render-text-as-superscript.md)
@@ -543,15 +452,12 @@ If you've learned something here, support my efforts writing daily TILs by
- [Analyze Your Website Performance](internet/analyze-your-website-performance.md) - [Analyze Your Website Performance](internet/analyze-your-website-performance.md)
- [Check Your Public IP Address](internet/check-your-public-ip-address.md) - [Check Your Public IP Address](internet/check-your-public-ip-address.md)
- [Digraph Unicode Characters Have A Titlecase](internet/digraph-unicode-characters-have-a-titlecase.md) - [Digraph Unicode Characters Have A Titlecase](internet/digraph-unicode-characters-have-a-titlecase.md)
- [Download A Google Doc As Specific Format](internet/download-a-google-doc-as-specific-format.md)
- [Enable Keyboard Shortcuts In Gmail](internet/enable-keyboard-shortcuts-in-gmail.md) - [Enable Keyboard Shortcuts In Gmail](internet/enable-keyboard-shortcuts-in-gmail.md)
- [Exclude AI Overview From Google Search](internet/exclude-ai-overview-from-google-search.md) - [Exclude AI Overview From Google Search](internet/exclude-ai-overview-from-google-search.md)
- [Exclude Whitespace Changes From GitHub Diffs](internet/exclude-whitespace-changes-from-github-diffs.md) - [Exclude Whitespace Changes From GitHub Diffs](internet/exclude-whitespace-changes-from-github-diffs.md)
- [Figure Out Your Public IP Address](internet/figure-out-your-public-ip-address.md) - [Figure Out Your Public IP Address](internet/figure-out-your-public-ip-address.md)
- [Focus The URL Bar](internet/focus-the-url-bar.md) - [Focus The URL Bar](internet/focus-the-url-bar.md)
- [Get Random Images From Unsplash](internet/get-random-images-from-unsplash.md) - [Get Random Images From Unsplash](internet/get-random-images-from-unsplash.md)
- [Grab The RSS Feed For A Substack Blog](internet/grab-the-rss-feed-for-a-substack-blog.md)
- [Hide Overflowing Text For Google Sheets Column](internet/hide-overflowing-text-for-google-sheets-column.md)
- [Search Tweets By Author](internet/search-tweets-by-author.md) - [Search Tweets By Author](internet/search-tweets-by-author.md)
- [Show All Pivotal Stories With Blockers](internet/show-all-pivotal-stories-with-blockers.md) - [Show All Pivotal Stories With Blockers](internet/show-all-pivotal-stories-with-blockers.md)
- [Verify Site Ownership With DNS Record](internet/verify-site-ownership-with-dns-record.md) - [Verify Site Ownership With DNS Record](internet/verify-site-ownership-with-dns-record.md)
@@ -598,7 +504,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Find Where Yarn Is Installing Binaries](javascript/find-where-yarn-is-installing-binaries.md) - [Find Where Yarn Is Installing Binaries](javascript/find-where-yarn-is-installing-binaries.md)
- [for...in Iterates Over Object Properties](javascript/for-in-iterates-over-object-properties.md) - [for...in Iterates Over Object Properties](javascript/for-in-iterates-over-object-properties.md)
- [Format A Decimal To A Fixed Number Of Digits](javascript/format-a-decimal-to-a-fixed-number-of-digits.md) - [Format A Decimal To A Fixed Number Of Digits](javascript/format-a-decimal-to-a-fixed-number-of-digits.md)
- [Format A List Of Items By Locale](javascript/format-a-list-of-items-by-locale.md)
- [Format Time Zone Identifier](javascript/format-time-zone-identifier.md) - [Format Time Zone Identifier](javascript/format-time-zone-identifier.md)
- [Formatting Values With Units For Display](javascript/formatting-values-with-units-for-display.md) - [Formatting Values With Units For Display](javascript/formatting-values-with-units-for-display.md)
- [Freeze An Object, Sorta](javascript/freeze-an-object-sorta.md) - [Freeze An Object, Sorta](javascript/freeze-an-object-sorta.md)
@@ -672,9 +577,7 @@ If you've learned something here, support my efforts writing daily TILs by
### jj ### jj
- [Colocate jj And git Directories For Project](jj/colocate-jj-and-git-directories-for-project.md) - [Colocate jj And git Directories For Project](jj/colocate-jj-and-git-directories-for-project.md)
- [Describe Current Changes And Create New Change](jj/describe-current-changes-and-create-new-change.md)
- [Find System-wide Config File For User](jj/find-system-wide-config-file-for-user.md) - [Find System-wide Config File For User](jj/find-system-wide-config-file-for-user.md)
- [Squash Changes Into Parent Commit Interactively](jj/squash-changes-into-parent-commit-interactively.md)
### jq ### jq
@@ -716,24 +619,18 @@ If you've learned something here, support my efforts writing daily TILs by
- [Access All Screen And Video Capture Options](mac/access-all-screen-and-video-capture-options.md) - [Access All Screen And Video Capture Options](mac/access-all-screen-and-video-capture-options.md)
- [Access System Information On OS X](mac/access-system-information-on-osx.md) - [Access System Information On OS X](mac/access-system-information-on-osx.md)
- [Access Unsupported Screen Resolutions With RDM](mac/access-unsupported-screen-resolutions-with-rdm.md) - [Access Unsupported Screen Resolutions With RDM](mac/access-unsupported-screen-resolutions-with-rdm.md)
- [Add A Bunch Of CLI Utilities With coreutils](mac/add-a-bunch-of-cli-utilities-with-coreutils.md)
- [Capture Screenshot To Clipboard From CLI](mac/capture-screenshot-to-clipboard-from-cli.md)
- [Check Network Quality Stats From The Command Line](mac/check-network-quality-stats-from-the-command-line.md) - [Check Network Quality Stats From The Command Line](mac/check-network-quality-stats-from-the-command-line.md)
- [Clean Up Old Homebrew Files](mac/clean-up-old-homebrew-files.md) - [Clean Up Old Homebrew Files](mac/clean-up-old-homebrew-files.md)
- [Convert An HEIC Image File To JPG](mac/convert-an-heic-image-file-to-jpg.md) - [Convert An HEIC Image File To JPG](mac/convert-an-heic-image-file-to-jpg.md)
- [Default Screenshot Location](mac/default-screenshot-location.md) - [Default Screenshot Location](mac/default-screenshot-location.md)
- [Detect How Long A User Has Been Idle](mac/detect-how-long-a-user-has-been-idle.md)
- [Disable Swipe Navigation For A Specific App](mac/disable-swipe-navigation-for-a-specific-app.md) - [Disable Swipe Navigation For A Specific App](mac/disable-swipe-navigation-for-a-specific-app.md)
- [Display A Message With Alfred](mac/display-a-message-with-alfred.md) - [Display A Message With Alfred](mac/display-a-message-with-alfred.md)
- [Find The Process Using A Specific Port](mac/find-the-process-using-a-specific-port.md) - [Find The Process Using A Specific Port](mac/find-the-process-using-a-specific-port.md)
- [Gesture For Viewing All Windows Of Current App](mac/gesture-for-viewing-all-windows-of-current-app.md) - [Gesture For Viewing All Windows Of Current App](mac/gesture-for-viewing-all-windows-of-current-app.md)
- [Insert A Non-Breaking Space Character](mac/insert-a-non-breaking-space-character.md) - [Insert A Non-Breaking Space Character](mac/insert-a-non-breaking-space-character.md)
- [Inspect Assertions Preventing Sleep](mac/inspect-assertions-preventing-sleep.md)
- [Keyboard Shortcuts For Interesting With Text Areas](mac/keyboard-shortcuts-for-interacting-with-text-areas.md) - [Keyboard Shortcuts For Interesting With Text Areas](mac/keyboard-shortcuts-for-interacting-with-text-areas.md)
- [Launch Some Confetti](mac/launch-some-confetti.md)
- [List All The Say Voices](mac/list-all-the-say-voices.md) - [List All The Say Voices](mac/list-all-the-say-voices.md)
- [Open Finder.app To Specific Directory](mac/open-finder-app-to-specific-directory.md) - [Open Finder.app To Specific Directory](mac/open-finder-app-to-specific-directory.md)
- [Prevent Sleep With The Caffeinate Command](mac/prevent-sleep-with-the-caffeinate-command.md)
- [Quickly Type En Dashes And Em Dashes](mac/quickly-type-en-dashes-and-em-dashes.md) - [Quickly Type En Dashes And Em Dashes](mac/quickly-type-en-dashes-and-em-dashes.md)
- [Require Additional JS Libraries In Postman](mac/require-additional-js-libraries-in-postman.md) - [Require Additional JS Libraries In Postman](mac/require-additional-js-libraries-in-postman.md)
- [Resize App Windows With AppleScript](mac/resize-app-windows-with-applescript.md) - [Resize App Windows With AppleScript](mac/resize-app-windows-with-applescript.md)
@@ -742,22 +639,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Run AppleScript Commands Inline In The Terminal](mac/run-applescript-commands-inline-in-the-terminal.md) - [Run AppleScript Commands Inline In The Terminal](mac/run-applescript-commands-inline-in-the-terminal.md)
- [Set A Window To Its Default Zoom Level](mac/set-a-window-to-its-default-zoom-level.md) - [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) - [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) - [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) - [View All Windows Of The Current App](mac/view-all-windows-of-the-current-app.md)
- [Write System Clipboard To A File](mac/write-system-clipboard-to-a-file.md) - [Write System Clipboard To A File](mac/write-system-clipboard-to-a-file.md)
### Mise
- [Create Umbrella Task For All Test Tasks](mise/create-umbrella-task-for-all-test-tasks.md)
- [List The Files Being Loaded By Mise](mise/list-the-files-being-loaded-by-mise.md)
- [Look In Ruby Version Dotfile](mise/look-in-ruby-version-dotfile.md)
- [Preserve Color Output For Task Command](mise/preserve-color-output-for-task-command.md)
- [Read Existing Dot Env File Into Env Vars](mise/read-existing-dot-env-file-into-env-vars.md)
- [Run A Command With Specific Tool Version](mise/run-a-command-with-specific-tool-version.md)
### MongoDB ### MongoDB
- [Determine The Database Version](mongodb/determine-the-database-version.md) - [Determine The Database Version](mongodb/determine-the-database-version.md)
@@ -775,7 +660,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Doing Date Math](mysql/doing-date-math.md) - [Doing Date Math](mysql/doing-date-math.md)
- [Dump A Database To A File](mysql/dump-a-database-to-a-file.md) - [Dump A Database To A File](mysql/dump-a-database-to-a-file.md)
- [Echo A Message From A SQL File](mysql/echo-a-message-from-a-sql-file.md) - [Echo A Message From A SQL File](mysql/echo-a-message-from-a-sql-file.md)
- [Get Idea Of What Is In A JSON Column](mysql/get-idea-of-what-is-in-a-json-column.md)
- [Ignore Duplicates When Inserting Records](mysql/ignore-duplicates-when-inserting-records.md) - [Ignore Duplicates When Inserting Records](mysql/ignore-duplicates-when-inserting-records.md)
- [List Databases And Tables](mysql/list-databases-and-tables.md) - [List Databases And Tables](mysql/list-databases-and-tables.md)
- [Run Statements In A Transaction](mysql/run-statements-in-a-transaction.md) - [Run Statements In A Transaction](mysql/run-statements-in-a-transaction.md)
@@ -789,9 +673,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Allow Neovim To Copy/Paste With System Clipboard](neovim/allow-neovim-to-copy-paste-with-system-clipboard.md) - [Allow Neovim To Copy/Paste With System Clipboard](neovim/allow-neovim-to-copy-paste-with-system-clipboard.md)
- [Create User Command To Open Init Config](neovim/create-user-command-to-open-init-config.md) - [Create User Command To Open Init Config](neovim/create-user-command-to-open-init-config.md)
- [Jump Between Changes In Current File](neovim/jump-between-changes-in-current-file.md)
- [Run A Lua Statement From The Command Prompt](neovim/run-a-lua-statement-from-the-command-prompt.md) - [Run A Lua Statement From The Command Prompt](neovim/run-a-lua-statement-from-the-command-prompt.md)
- [Run nvim With Factory Defaults](neovim/run-nvim-with-factory-defaults.md)
- [Set Up Vim-Plug With Neovim](neovim/set-up-vim-plug-with-neovim.md) - [Set Up Vim-Plug With Neovim](neovim/set-up-vim-plug-with-neovim.md)
### Netlify ### Netlify
@@ -829,7 +711,6 @@ If you've learned something here, support my efforts writing daily TILs by
### Planetscale ### Planetscale
- [See What Databases You Have Access To](planetscale/see-what-databases-you-have-access-to.md)
- [Seed Production Data Into Another Branch](planetscale/seed-production-data-into-another-branch.md) - [Seed Production Data Into Another Branch](planetscale/seed-production-data-into-another-branch.md)
### pnpm ### pnpm
@@ -856,7 +737,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Check If The Local Server Is Running](postgres/check-if-the-local-server-is-running.md) - [Check If The Local Server Is Running](postgres/check-if-the-local-server-is-running.md)
- [Check If User Role Exists For Database](postgres/check-if-user-role-exists-for-database.md) - [Check If User Role Exists For Database](postgres/check-if-user-role-exists-for-database.md)
- [Check Table For Any Oprhaned Records](postgres/check-table-for-any-orphaned-records.md) - [Check Table For Any Oprhaned Records](postgres/check-table-for-any-orphaned-records.md)
- [Check The Size Of Databases In A Cluster](postgres/check-the-size-of-databases-in-a-cluster.md)
- [Checking Inequality](postgres/checking-inequality.md) - [Checking Inequality](postgres/checking-inequality.md)
- [Checking The Type Of A Value](postgres/checking-the-type-of-a-value.md) - [Checking The Type Of A Value](postgres/checking-the-type-of-a-value.md)
- [Clear The Screen In psql](postgres/clear-the-screen-in-psql.md) - [Clear The Screen In psql](postgres/clear-the-screen-in-psql.md)
@@ -870,14 +750,12 @@ If you've learned something here, support my efforts writing daily TILs by
- [Convert A String To A Timestamp](postgres/convert-a-string-to-a-timestamp.md) - [Convert A String To A Timestamp](postgres/convert-a-string-to-a-timestamp.md)
- [Count How Many Records There Are Of Each Type](postgres/count-how-many-records-there-are-of-each-type.md) - [Count How Many Records There Are Of Each Type](postgres/count-how-many-records-there-are-of-each-type.md)
- [Count Records By Type](postgres/count-records-by-type.md) - [Count Records By Type](postgres/count-records-by-type.md)
- [Count The Number Of Items In An Array](postgres/count-the-number-of-items-in-an-array.md)
- [Count The Number Of Trues In An Aggregate Query](postgres/count-the-number-of-trues-in-an-aggregate-query.md) - [Count The Number Of Trues In An Aggregate Query](postgres/count-the-number-of-trues-in-an-aggregate-query.md)
- [Create A Cluster In A Specific Data Directory](postgres/create-a-cluster-in-a-specific-data-directory.md) - [Create A Cluster In A Specific Data Directory](postgres/create-a-cluster-in-a-specific-data-directory.md)
- [Create A Composite Primary Key](postgres/create-a-composite-primary-key.md) - [Create A Composite Primary Key](postgres/create-a-composite-primary-key.md)
- [Create A Table From The Structure Of Another](postgres/create-a-table-from-the-structure-of-another.md) - [Create A Table From The Structure Of Another](postgres/create-a-table-from-the-structure-of-another.md)
- [Create An Index Across Two Columns](postgres/create-an-index-across-two-columns.md) - [Create An Index Across Two Columns](postgres/create-an-index-across-two-columns.md)
- [Create An Index Without Locking The Table](postgres/create-an-index-without-locking-the-table.md) - [Create An Index Without Locking The Table](postgres/create-an-index-without-locking-the-table.md)
- [Create And Execute SQL Statements With \gexec](postgres/create-and-execute-sql-statements-with-gexec.md)
- [Create Database Uses Template1](postgres/create-database-uses-template1.md) - [Create Database Uses Template1](postgres/create-database-uses-template1.md)
- [Create hstore From Two Arrays](postgres/create-hstore-from-two-arrays.md) - [Create hstore From Two Arrays](postgres/create-hstore-from-two-arrays.md)
- [Create Table Adds A Data Type](postgres/create-table-adds-a-data-type.md) - [Create Table Adds A Data Type](postgres/create-table-adds-a-data-type.md)
@@ -902,7 +780,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Escaping String Literals With Dollar Quoting](postgres/escaping-string-literals-with-dollar-quoting.md) - [Escaping String Literals With Dollar Quoting](postgres/escaping-string-literals-with-dollar-quoting.md)
- [Export Query Results To A CSV](postgres/export-query-results-to-a-csv.md) - [Export Query Results To A CSV](postgres/export-query-results-to-a-csv.md)
- [Extracting Nested JSON Data](postgres/extracting-nested-json-data.md) - [Extracting Nested JSON Data](postgres/extracting-nested-json-data.md)
- [Fetch Data From An Endpoint In SQL](postgres/fetch-data-from-an-endpoint-in-sql.md)
- [Fetch Specific Number Of Results](postgres/fetch-specific-number-of-results.md) - [Fetch Specific Number Of Results](postgres/fetch-specific-number-of-results.md)
- [Find Duplicate Records In Table Without Unique Id](postgres/find-duplicate-records-in-table-without-unique-id.md) - [Find Duplicate Records In Table Without Unique Id](postgres/find-duplicate-records-in-table-without-unique-id.md)
- [Find Records That Contain Duplicate Values](postgres/find-records-that-contain-duplicate-values.md) - [Find Records That Contain Duplicate Values](postgres/find-records-that-contain-duplicate-values.md)
@@ -961,7 +838,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Prevent A Query From Running Too Long](postgres/prevent-a-query-from-running-too-long.md) - [Prevent A Query From Running Too Long](postgres/prevent-a-query-from-running-too-long.md)
- [Print The Query Buffer In psql](postgres/print-the-query-buffer-in-psql.md) - [Print The Query Buffer In psql](postgres/print-the-query-buffer-in-psql.md)
- [Put Unique Constraint On Generated Column](postgres/put-unique-constraint-on-generated-column.md) - [Put Unique Constraint On Generated Column](postgres/put-unique-constraint-on-generated-column.md)
- [References Target Primary Key By Default](postgres/references-target-primary-key-by-default.md)
- [Remove Not Null Constraint From A Column](postgres/remove-not-null-constraint-from-a-column.md) - [Remove Not Null Constraint From A Column](postgres/remove-not-null-constraint-from-a-column.md)
- [Renaming A Sequence](postgres/renaming-a-sequence.md) - [Renaming A Sequence](postgres/renaming-a-sequence.md)
- [Renaming A Table](postgres/renaming-a-table.md) - [Renaming A Table](postgres/renaming-a-table.md)
@@ -972,11 +848,9 @@ If you've learned something here, support my efforts writing daily TILs by
- [Set Inclusion With hstore](postgres/set-inclusion-with-hstore.md) - [Set Inclusion With hstore](postgres/set-inclusion-with-hstore.md)
- [Set A Seed For The Random Number Generator](postgres/set-a-seed-for-the-random-number-generator.md) - [Set A Seed For The Random Number Generator](postgres/set-a-seed-for-the-random-number-generator.md)
- [Set A Statement Timeout Threshold For A Session](postgres/set-a-statement-timeout-threshold-for-a-session.md) - [Set A Statement Timeout Threshold For A Session](postgres/set-a-statement-timeout-threshold-for-a-session.md)
- [Set Up A Project-Local Cluster With Postgres.app](postgres/set-up-a-project-local-cluster-with-postgres-app.md)
- [Sets With The Values Command](postgres/sets-with-the-values-command.md) - [Sets With The Values Command](postgres/sets-with-the-values-command.md)
- [Shorthand Absolute Value Operator](postgres/shorthand-absolute-value-operator.md) - [Shorthand Absolute Value Operator](postgres/shorthand-absolute-value-operator.md)
- [Show All Versions Of An Operator](postgres/show-all-versions-of-an-operator.md) - [Show All Versions Of An Operator](postgres/show-all-versions-of-an-operator.md)
- [Show Reconstructed Constraints For A Table](postgres/show-reconstructed-constraints-for-a-table.md)
- [Show The Hidden Queries Behind Backslash Commands](postgres/show-the-hidden-queries-behind-backslash-commands.md) - [Show The Hidden Queries Behind Backslash Commands](postgres/show-the-hidden-queries-behind-backslash-commands.md)
- [Sleeping](postgres/sleeping.md) - [Sleeping](postgres/sleeping.md)
- [Special Math Operators](postgres/special-math-operators.md) - [Special Math Operators](postgres/special-math-operators.md)
@@ -993,14 +867,12 @@ If you've learned something here, support my efforts writing daily TILs by
- [Timestamp Functions](postgres/timestamp-functions.md) - [Timestamp Functions](postgres/timestamp-functions.md)
- [Toggling The Pager In PSQL](postgres/toggling-the-pager-in-psql.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) - [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 All Rows](postgres/truncate-all-rows.md)
- [Truncate Tables With Dependents](postgres/truncate-tables-with-dependents.md) - [Truncate Tables With Dependents](postgres/truncate-tables-with-dependents.md)
- [Turning Timing On](postgres/turn-timing-on.md) - [Turning Timing On](postgres/turn-timing-on.md)
- [Two Ways To Compute Factorial](postgres/two-ways-to-compute-factorial.md) - [Two Ways To Compute Factorial](postgres/two-ways-to-compute-factorial.md)
- [Two Ways To Escape A Quote In A String](postgres/two-ways-to-escape-a-quote-in-a-string.md) - [Two Ways To Escape A Quote In A String](postgres/two-ways-to-escape-a-quote-in-a-string.md)
- [Types By Category](postgres/types-by-category.md) - [Types By Category](postgres/types-by-category.md)
- [Unable To Infer Data Type In Production](postgres/unable-to-infer-data-type-in-production.md)
- [Union All Rows Including Duplicates](postgres/union-all-rows-including-duplicates.md) - [Union All Rows Including Duplicates](postgres/union-all-rows-including-duplicates.md)
- [Use A psqlrc File For Common Settings](postgres/use-a-psqlrc-file-for-common-settings.md) - [Use A psqlrc File For Common Settings](postgres/use-a-psqlrc-file-for-common-settings.md)
- [Use A Trigger To Mirror Inserts To Another Table](postgres/use-a-trigger-to-mirror-inserts-to-another-table.md) - [Use A Trigger To Mirror Inserts To Another Table](postgres/use-a-trigger-to-mirror-inserts-to-another-table.md)
@@ -1029,7 +901,6 @@ If you've learned something here, support my efforts writing daily TILs by
### Python ### Python
- [Access Instance Variables](python/access-instance-variables.md) - [Access Instance Variables](python/access-instance-variables.md)
- [Break Debugger On First Line Of Program](python/break-debugger-on-first-line-of-program.md)
- [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md) - [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md)
- [Dunder Methods](python/dunder-methods.md) - [Dunder Methods](python/dunder-methods.md)
- [Override The Boolean Context Of A Class](python/override-the-boolean-context-of-a-class.md) - [Override The Boolean Context Of A Class](python/override-the-boolean-context-of-a-class.md)
@@ -1039,25 +910,21 @@ If you've learned something here, support my efforts writing daily TILs by
### Rails ### Rails
- [Access Secrets In A Rails 5.2 App](rails/access-secrets-in-a-rails-5-2-app.md)
- [ActiveRecord Query For This Or That](rails/active-record-query-for-this-or-that.md)
- [Add A Check Constraint To A Table](rails/add-a-check-constraint-to-a-table.md) - [Add A Check Constraint To A Table](rails/add-a-check-constraint-to-a-table.md)
- [Add A Database Index If It Does Not Already Exist](rails/add-a-database-index-if-it-does-not-already-exist.md) - [Add A Database Index If It Does Not Already Exist](rails/add-a-database-index-if-it-does-not-already-exist.md)
- [Add A Foreign Key Reference To A Table](rails/add-a-foreign-key-reference-to-a-table.md) - [Add A Foreign Key Reference To A Table](rails/add-a-foreign-key-reference-to-a-table.md)
- [Add A Generated Column To A PostgreSQL Table](rails/add-a-generated-column-to-a-postgresql-table.md)
- [Add A Reference Column With An Index](rails/add-a-reference-column-with-an-index.md) - [Add A Reference Column With An Index](rails/add-a-reference-column-with-an-index.md)
- [Add ActiveRecord Error Not Tied To Any Attribute](rails/add-activerecord-error-not-tied-to-any-attribute.md) - [Add ActiveRecord Error Not Tied To Any Attribute](rails/add-activerecord-error-not-tied-to-any-attribute.md)
- [Add Color To The IRB Console Prompt](rails/add-color-to-the-irb-console-prompt.md)
- [Add React With Webpacker To A New Rails App](rails/add-react-with-webpacker-to-a-new-rails-app.md) - [Add React With Webpacker To A New Rails App](rails/add-react-with-webpacker-to-a-new-rails-app.md)
- [Add timestamptz Columns With The Migration DSL](rails/add-timestamptz-columns-with-the-migration-dsl.md) - [Add timestamptz Columns With The Migration DSL](rails/add-timestamptz-columns-with-the-migration-dsl.md)
- [Adjust The Production Log Level](rails/adjust-the-production-log-level.md) - [Access Secrets In A Rails 5.2 App](rails/access-secrets-in-a-rails-5-2-app.md)
- [ActiveRecord Query For This Or That](rails/active-record-query-for-this-or-that.md)
- [Advance The Date](rails/advance-the-date.md) - [Advance The Date](rails/advance-the-date.md)
- [Allow Associations To Be Optional](rails/allow-associations-to-be-optional.md) - [Allow Associations To Be Optional](rails/allow-associations-to-be-optional.md)
- [Allow List Params Anywhere With Strong Params](rails/allow-list-params-anywhere-with-strong-params.md) - [Allow List Params Anywhere With Strong Params](rails/allow-list-params-anywhere-with-strong-params.md)
- [All or Nothing Database Transactions](rails/all-or-nothing-database-transactions.md) - [All or Nothing Database Transactions](rails/all-or-nothing-database-transactions.md)
- [Alphabetize Schema Columns To Keep Them Consistent](rails/alphabetize-schema-columns-to-keep-them-consistent.md) - [Alphabetize Schema Columns To Keep Them Consistent](rails/alphabetize-schema-columns-to-keep-them-consistent.md)
- [Alter The Rails Setup Script](rails/alter-the-rails-setup-script.md) - [Alter The Rails Setup Script](rails/alter-the-rails-setup-script.md)
- [Apply Basic HTML Formatting To Block Of Text](rails/apply-basic-html-formatting-to-block-of-text.md)
- [Assert Two Arrays Have The Same Items With RSpec](rails/assert-two-arrays-have-the-same-items-with-rspec.md) - [Assert Two Arrays Have The Same Items With RSpec](rails/assert-two-arrays-have-the-same-items-with-rspec.md)
- [Attach A File With Capybara](rails/attach-a-file-with-capybara.md) - [Attach A File With Capybara](rails/attach-a-file-with-capybara.md)
- [Attribute Getter without the Recursion](rails/attribute-getter-without-the-recursion.md) - [Attribute Getter without the Recursion](rails/attribute-getter-without-the-recursion.md)
@@ -1078,7 +945,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Comparing DateTimes Down To Second Precision](rails/comparing-datetimes-down-to-second-precision.md) - [Comparing DateTimes Down To Second Precision](rails/comparing-datetimes-down-to-second-precision.md)
- [Conditional Class Selectors in Haml](rails/conditional-class-selectors-in-haml.md) - [Conditional Class Selectors in Haml](rails/conditional-class-selectors-in-haml.md)
- [Convert A Symbol To A Constant](rails/convert-a-symbol-to-a-constant.md) - [Convert A Symbol To A Constant](rails/convert-a-symbol-to-a-constant.md)
- [Convert JSON Field To Hash With Indifferent Access](rails/convert-json-field-to-hash-with-indifferent-access.md)
- [Count The Number Of Records By Attribute](rails/count-the-number-of-records-by-attribute.md) - [Count The Number Of Records By Attribute](rails/count-the-number-of-records-by-attribute.md)
- [Create A Custom Named References Column](rails/create-a-custom-named-references-column.md) - [Create A Custom Named References Column](rails/create-a-custom-named-references-column.md)
- [Create A Join Table With The Migration DSL](rails/create-a-join-table-with-the-migration-dsl.md) - [Create A Join Table With The Migration DSL](rails/create-a-join-table-with-the-migration-dsl.md)
@@ -1086,26 +952,19 @@ If you've learned something here, support my efforts writing daily TILs by
- [Creating Records of Has_One Associations](rails/creating-records-of-has-one-associations.md) - [Creating Records of Has_One Associations](rails/creating-records-of-has-one-associations.md)
- [Custom Validation Message](rails/custom-validation-message.md) - [Custom Validation Message](rails/custom-validation-message.md)
- [Customize Paths And Helpers For Devise Routes](rails/customize-paths-and-helpers-for-devise-routes.md) - [Customize Paths And Helpers For Devise Routes](rails/customize-paths-and-helpers-for-devise-routes.md)
- [Customize Template For New Schema Migration](rails/customize-template-for-new-schema-migration.md)
- [Customize The Path Of A Resource Route](rails/customize-the-path-of-a-resource-route.md) - [Customize The Path Of A Resource Route](rails/customize-the-path-of-a-resource-route.md)
- [Define The Root Path For The App](rails/define-the-root-path-for-the-app.md) - [Define The Root Path For The App](rails/define-the-root-path-for-the-app.md)
- [Delete Paranoid Records](rails/delete-paranoid-records.md) - [Delete Paranoid Records](rails/delete-paranoid-records.md)
- [Demodulize A Class Name](rails/demodulize-a-class-name.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) - [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) - [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) - [Empty find_by Returns First Record](rails/empty-find-by-returns-first-record.md)
- [Enforce Locals Passed To A Partial](rails/enforce-locals-passed-to-a-partial.md)
- [Ensure A Rake Task Cannot Write Data](rails/ensure-a-rake-task-cannot-write-data.md) - [Ensure A Rake Task Cannot Write Data](rails/ensure-a-rake-task-cannot-write-data.md)
- [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md) - [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md)
- [Ensure Record Saved With after_commit Callback](rails/ensure-record-saved-with-after-commit-callback.md) - [Ensure Record Saved With after_commit Callback](rails/ensure-record-saved-with-after-commit-callback.md)
- [Filter ActiveModel Validation Errors](rails/filter-active-model-validation-errors.md)
- [Filter ActiveStorage Blobs To Only Images](rails/filter-active-storage-blobs-to-only-images.md)
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md) - [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md) - [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md) - [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
- [Format DateTime With Builtin Formats](rails/format-datetime-with-builtin-formats.md)
- [Format Specific html.erb Template Files](rails/format-specific-html-erb-template-files.md)
- [Generate A Model](rails/generate-a-model.md) - [Generate A Model](rails/generate-a-model.md)
- [Generate A Rails App From The Main Branch](rails/generate-a-rails-app-from-the-main-branch.md) - [Generate A Rails App From The Main Branch](rails/generate-a-rails-app-from-the-main-branch.md)
- [Generating And Executing SQL](rails/generating-and-executing-sql.md) - [Generating And Executing SQL](rails/generating-and-executing-sql.md)
@@ -1122,7 +981,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Hash Slicing](rails/hash-slicing.md) - [Hash Slicing](rails/hash-slicing.md)
- [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md) - [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md)
- [Include Devise Helpers In Your Controller Tests](rails/include-devise-helpers-in-your-controller-tests.md) - [Include Devise Helpers In Your Controller Tests](rails/include-devise-helpers-in-your-controller-tests.md)
- [Inspect Configuration Of Database Connection](rails/inspect-configuration-of-database-connection.md)
- [Inspect Previous Changes To ActiveRecord Object](rails/inspect-previous-changes-to-activerecord-object.md) - [Inspect Previous Changes To ActiveRecord Object](rails/inspect-previous-changes-to-activerecord-object.md)
- [Link To The Current Page With Query Params](rails/link-to-the-current-page-with-query-params.md) - [Link To The Current Page With Query Params](rails/link-to-the-current-page-with-query-params.md)
- [List All Installable Rails Versions](rails/list-all-installable-rails-versions.md) - [List All Installable Rails Versions](rails/list-all-installable-rails-versions.md)
@@ -1135,7 +993,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Make A String Attribute Easy To Inquire About](rails/make-a-string-attribute-easy-to-inquire-about.md) - [Make A String Attribute Easy To Inquire About](rails/make-a-string-attribute-easy-to-inquire-about.md)
- [Make ActionMailer Synchronous In Test](rails/make-action-mailer-synchronous-in-test.md) - [Make ActionMailer Synchronous In Test](rails/make-action-mailer-synchronous-in-test.md)
- [Make Remove Column Migration Reversible](rails/make-remove-column-migration-reversible.md) - [Make Remove Column Migration Reversible](rails/make-remove-column-migration-reversible.md)
- [Manage Timestamps With Upsert](rails/manage-timestamps-with-upsert.md)
- [Manually Run A Migration From Rails Console](rails/manually-run-a-migration-from-rails-console.md) - [Manually Run A Migration From Rails Console](rails/manually-run-a-migration-from-rails-console.md)
- [Mark For Destruction](rails/mark-for-destruction.md) - [Mark For Destruction](rails/mark-for-destruction.md)
- [Mask An ActiveRecord Attribute](rails/mask-an-activerecord-attribute.md) - [Mask An ActiveRecord Attribute](rails/mask-an-activerecord-attribute.md)
@@ -1143,8 +1000,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Migrating Up Down Up](rails/migrating-up-down-up.md) - [Migrating Up Down Up](rails/migrating-up-down-up.md)
- [Mock Rails Environment With An Inquiry Instance](rails/mock-rails-environment-with-an-inquiry-instance.md) - [Mock Rails Environment With An Inquiry Instance](rails/mock-rails-environment-with-an-inquiry-instance.md)
- [Order Matters For `rescue_from` Blocks](rails/order-matters-for-rescue-from-blocks.md) - [Order Matters For `rescue_from` Blocks](rails/order-matters-for-rescue-from-blocks.md)
- [Override Text Displayed By Form Label](rails/override-text-displayed-by-form-label.md)
- [Parameterize A String With Underscores](rails/parameterize-a-string-with-underscores.md)
- [Params Includes Submission Button Info](rails/params-includes-submission-button-info.md) - [Params Includes Submission Button Info](rails/params-includes-submission-button-info.md)
- [Params Is A Hash With Indifferent Access](rails/params-is-a-hash-with-indifferent-access.md) - [Params Is A Hash With Indifferent Access](rails/params-is-a-hash-with-indifferent-access.md)
- [Parse Query Params From A URL](rails/parse-query-params-from-a-url.md) - [Parse Query Params From A URL](rails/parse-query-params-from-a-url.md)
@@ -1153,13 +1008,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md) - [Polymorphic Path Helpers](rails/polymorphic-path-helpers.md)
- [Prefer select_all Over execute For Read Queries](rails/prefer-select-all-over-execute-for-read-queries.md) - [Prefer select_all Over execute For Read Queries](rails/prefer-select-all-over-execute-for-read-queries.md)
- [Pretend Generations](rails/pretend-generations.md) - [Pretend Generations](rails/pretend-generations.md)
- [Prevent Mailer Previews From Cluttering Database](rails/prevent-mailer-previews-from-cluttering-database.md)
- [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md) - [Prevent Writes With A Sandboxed Rails Console](rails/prevent-writes-with-a-sandboxed-rails-console.md)
- [Provide Fake Form Helper To Controllers](rails/provide-fake-form-helper-to-controllers.md)
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md) - [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
- [Read In Environment-Specific Config Values](rails/read-in-environment-specific-config-values.md) - [Read In Environment-Specific Config Values](rails/read-in-environment-specific-config-values.md)
- [Read-Only Models](rails/read-only-models.md) - [Read-Only Models](rails/read-only-models.md)
- [Rebuild Tailwind Bundle For Dev Server](rails/rebuild-tailwind-bundle-for-dev-server.md)
- [Remove A Database Column From A Table](rails/remove-a-database-column-from-a-table.md) - [Remove A Database Column From A Table](rails/remove-a-database-column-from-a-table.md)
- [Remove The Default Value On A Column](rails/remove-the-default-value-on-a-column.md) - [Remove The Default Value On A Column](rails/remove-the-default-value-on-a-column.md)
- [Render An Alternative ActionMailer Template](rails/render-an-alternative-action-mailer-template.md) - [Render An Alternative ActionMailer Template](rails/render-an-alternative-action-mailer-template.md)
@@ -1168,19 +1020,14 @@ If you've learned something here, support my efforts writing daily TILs by
- [Rescue From](rails/rescue-from.md) - [Rescue From](rails/rescue-from.md)
- [Rescue From With A Separate Method](rails/rescue-from-with-a-separate-method.md) - [Rescue From With A Separate Method](rails/rescue-from-with-a-separate-method.md)
- [Respond With JSON Regardless of Content Type](rails/respond-with-json-regardless-of-content-type.md) - [Respond With JSON Regardless of Content Type](rails/respond-with-json-regardless-of-content-type.md)
- [Restart Puma Server By Touching Restart File](rails/restart-puma-server-by-touching-restart-file.md)
- [Retrieve An Object If It Exists](rails/retrieve-an-object-if-it-exists.md) - [Retrieve An Object If It Exists](rails/retrieve-an-object-if-it-exists.md)
- [Rollback A Couple Migrations](rails/rollback-a-couple-migrations.md) - [Rollback A Couple Migrations](rails/rollback-a-couple-migrations.md)
- [Rollback A Specific Migration Out Of Order](rails/rollback-a-specific-migration-out-of-order.md) - [Rollback A Specific Migration Out Of Order](rails/rollback-a-specific-migration-out-of-order.md)
- [Rounding Numbers With Precision](rails/rounding-numbers-with-precision.md) - [Rounding Numbers With Precision](rails/rounding-numbers-with-precision.md)
- [Run A Rake Task Programmatically](rails/run-a-rake-task-programmatically.md) - [Run A Rake Task Programmatically](rails/run-a-rake-task-programmatically.md)
- [Run Commands With Specific Rails Version](rails/run-commands-with-specific-rails-version.md) - [Run Commands With Specific Rails Version](rails/run-commands-with-specific-rails-version.md)
- [Run Dev Processes With Overmind Instead Of Foreman](rails/run-dev-processes-with-overmind-instead-of-foreman.md)
- [Run Rails Console With Remote Dokku App](rails/run-rails-console-with-remote-dokku-app.md)
- [Run Some Code Whenever Rails Console Starts](rails/run-some-code-whenever-rails-console-starts.md) - [Run Some Code Whenever Rails Console Starts](rails/run-some-code-whenever-rails-console-starts.md)
- [Scaffold Auth Functionality With Rails 8 Generator](rails/scaffold-auth-functionality-with-rails-8-generator.md)
- [Schedule Sidekiq Jobs Out Into The Future](rails/schedule-sidekiq-jobs-out-into-the-future.md) - [Schedule Sidekiq Jobs Out Into The Future](rails/schedule-sidekiq-jobs-out-into-the-future.md)
- [Scope Records To A Lower Or Upper Bound](rails/scope-records-to-a-lower-or-upper-bound.md)
- [Secure Passwords With Rails And Bcrypt](rails/secure-passwords-with-rails-and-bcrypt.md) - [Secure Passwords With Rails And Bcrypt](rails/secure-passwords-with-rails-and-bcrypt.md)
- [Select A Select By Selector](rails/select-a-select-by-selector.md) - [Select A Select By Selector](rails/select-a-select-by-selector.md)
- [Select A Specific Rails Version To Install](rails/select-a-specific-rails-version-to-install.md) - [Select A Specific Rails Version To Install](rails/select-a-specific-rails-version-to-install.md)
@@ -1190,7 +1037,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Set DateTime To Include Time Zone In Migrations](rails/set-datetime-to-include-time-zone-in-migrations.md) - [Set DateTime To Include Time Zone In Migrations](rails/set-datetime-to-include-time-zone-in-migrations.md)
- [Set Default As SQL Function In Migration](rails/set-default-as-sql-function-in-migration.md) - [Set Default As SQL Function In Migration](rails/set-default-as-sql-function-in-migration.md)
- [Set default_url_options For Entire Application](rails/set-default-url-options-for-entire-application.md) - [Set default_url_options For Entire Application](rails/set-default-url-options-for-entire-application.md)
- [Set Meta Tags In ERB Views](rails/set-meta-tags-in-erb-views.md)
- [Set Schema Search Path](rails/set-schema-search-path.md) - [Set Schema Search Path](rails/set-schema-search-path.md)
- [Set Statement Timeout For All Postgres Connections](rails/set-statement-timeout-for-all-postgres-connections.md) - [Set Statement Timeout For All Postgres Connections](rails/set-statement-timeout-for-all-postgres-connections.md)
- [Set The Default Development Port](rails/set-the-default-development-port.md) - [Set The Default Development Port](rails/set-the-default-development-port.md)
@@ -1209,7 +1055,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Update Column Versus Update Attribute](rails/update-column-versus-update-attribute.md) - [Update Column Versus Update Attribute](rails/update-column-versus-update-attribute.md)
- [Upgrading Your Manifest For Sprocket's 4](rails/upgrading-your-manifest-for-sprockets-4.md) - [Upgrading Your Manifest For Sprocket's 4](rails/upgrading-your-manifest-for-sprockets-4.md)
- [Use IRB And Ruby Flags With Rails Console](rails/use-irb-and-ruby-flags-with-rails-console.md) - [Use IRB And Ruby Flags With Rails Console](rails/use-irb-and-ruby-flags-with-rails-console.md)
- [Use .ruby Extension For Template File](rails/use-ruby-extension-for-template-file.md)
- [Useful ActiveSupport Constants For Durations](rails/useful-active-support-constants-for-durations.md) - [Useful ActiveSupport Constants For Durations](rails/useful-active-support-constants-for-durations.md)
- [Validate Column Data With Check Constraints](rails/validate-column-data-with-check-constraints.md) - [Validate Column Data With Check Constraints](rails/validate-column-data-with-check-constraints.md)
- [Verify And Read A Signed Cookie Value](rails/verify-and-read-a-signed-cookie-value.md) - [Verify And Read A Signed Cookie Value](rails/verify-and-read-a-signed-cookie-value.md)
@@ -1349,9 +1194,8 @@ If you've learned something here, support my efforts writing daily TILs by
- [Add Progress Reporting To Long-Running Script](ruby/add-progress-reporting-to-long-running-script.md) - [Add Progress Reporting To Long-Running Script](ruby/add-progress-reporting-to-long-running-script.md)
- [Are They All True?](ruby/are-they-all-true.md) - [Are They All True?](ruby/are-they-all-true.md)
- [Assert About An Object's Attributes With RSpec](ruby/assert-about-an-objects-attributes-with-rspec.md) - [Assert About An Object's Attributes With RSpec](ruby/assert-about-an-objects-attributes-with-rspec.md)
- [Assoc For Hashes](ruby/assoc-for-hashes.md)
- [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md) - [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md)
- [Avoid Double Negation With Minitest Refute](ruby/avoid-double-negation-with-minitest-refute.md) - [Assoc For Hashes](ruby/assoc-for-hashes.md)
- [Block Comments](ruby/block-comments.md) - [Block Comments](ruby/block-comments.md)
- [Block Syntaxes Have Different Precedence](ruby/block-syntaxes-have-different-precedence.md) - [Block Syntaxes Have Different Precedence](ruby/block-syntaxes-have-different-precedence.md)
- [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md) - [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md)
@@ -1360,7 +1204,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Check If A URL Resolves To 200](ruby/check-if-a-url-resolves-to-200.md) - [Check If A URL Resolves To 200](ruby/check-if-a-url-resolves-to-200.md)
- [Check If An Object Includes A Module](ruby/check-if-an-object-includes-a-module.md) - [Check If An Object Includes A Module](ruby/check-if-an-object-includes-a-module.md)
- [Check Return Status Of Running A Shell Command](ruby/check-return-status-of-running-a-shell-command.md) - [Check Return Status Of Running A Shell Command](ruby/check-return-status-of-running-a-shell-command.md)
- [Clamp To An Endless Range](ruby/clamp-to-an-endless-range.md)
- [Click On Text With Capybara](ruby/click-on-text-with-capybara.md) - [Click On Text With Capybara](ruby/click-on-text-with-capybara.md)
- [Colorful Output With MiniTest](ruby/colorful-output-with-minitest.md) - [Colorful Output With MiniTest](ruby/colorful-output-with-minitest.md)
- [Comparing Class Hierarchy Relationships](ruby/comparing-class-hierarchy-relationships.md) - [Comparing Class Hierarchy Relationships](ruby/comparing-class-hierarchy-relationships.md)
@@ -1371,18 +1214,14 @@ If you've learned something here, support my efforts writing daily TILs by
- [Create a CSV::Table Object](ruby/create-a-csv-table-object.md) - [Create a CSV::Table Object](ruby/create-a-csv-table-object.md)
- [Create A Hash From An Array Of Arrays](ruby/create-a-hash-from-an-array-of-arrays.md) - [Create A Hash From An Array Of Arrays](ruby/create-a-hash-from-an-array-of-arrays.md)
- [Create Listing Of All Middleman Pages](ruby/create-listing-of-all-middleman-pages.md) - [Create Listing Of All Middleman Pages](ruby/create-listing-of-all-middleman-pages.md)
- [Create Mock Class That Can Be Overridden](ruby/create-mock-class-that-can-be-overridden.md)
- [Create A Module Of Utility Functions](ruby/create-a-module-of-utility-functions.md)
- [Create Named Structs With Struct.new](ruby/create-named-structs-with-struct-new.md) - [Create Named Structs With Struct.new](ruby/create-named-structs-with-struct-new.md)
- [Create Thumbnail Image For A PDF](ruby/create-thumbnail-image-for-a-pdf.md) - [Create Thumbnail Image For A PDF](ruby/create-thumbnail-image-for-a-pdf.md)
- [Decompose Unicode Character With Diacritic Mark](ruby/decompose-unicode-character-with-diacritic-mark.md)
- [Defaulting To Frozen String Literals](ruby/defaulting-to-frozen-string-literals.md) - [Defaulting To Frozen String Literals](ruby/defaulting-to-frozen-string-literals.md)
- [Define A Custom RSpec Matcher](ruby/define-a-custom-rspec-matcher.md) - [Define A Custom RSpec Matcher](ruby/define-a-custom-rspec-matcher.md)
- [Define A Method On A Struct](ruby/define-a-method-on-a-struct.md) - [Define A Method On A Struct](ruby/define-a-method-on-a-struct.md)
- [Define Multiline Strings With Heredocs](ruby/define-multiline-strings-with-heredocs.md) - [Define Multiline Strings With Heredocs](ruby/define-multiline-strings-with-heredocs.md)
- [Destructure The First Item From An Array](ruby/destructure-the-first-item-from-an-array.md) - [Destructure The First Item From An Array](ruby/destructure-the-first-item-from-an-array.md)
- [Destructuring Arrays In Blocks](ruby/destructuring-arrays-in-blocks.md) - [Destructuring Arrays In Blocks](ruby/destructuring-arrays-in-blocks.md)
- [Disable Interpolation For A Heredoc String](ruby/disable-interpolation-for-a-heredoc-string.md)
- [Disassemble Some Codes](ruby/disassemble-some-codes.md) - [Disassemble Some Codes](ruby/disassemble-some-codes.md)
- [Double Splat To Merge Hashes](ruby/double-splat-to-merge-hashes.md) - [Double Splat To Merge Hashes](ruby/double-splat-to-merge-hashes.md)
- [Edit Previous Parts Of The Pry Buffer History](ruby/edit-previous-parts-of-the-pry-buffer-history.md) - [Edit Previous Parts Of The Pry Buffer History](ruby/edit-previous-parts-of-the-pry-buffer-history.md)
@@ -1395,7 +1234,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Exit A Process With An Error Message](ruby/exit-a-process-with-an-error-message.md) - [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) - [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 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) - [FactoryGirl Sequences](ruby/factory-girl-sequences.md)
- [Fail](ruby/fail.md) - [Fail](ruby/fail.md)
- [Fetch Warns About Superseding Block Argument](ruby/fetch-warns-about-superseding-block-argument.md) - [Fetch Warns About Superseding Block Argument](ruby/fetch-warns-about-superseding-block-argument.md)
@@ -1407,8 +1245,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Generate A Signed JWT Token](ruby/generate-a-signed-jwt-token.md) - [Generate A Signed JWT Token](ruby/generate-a-signed-jwt-token.md)
- [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md) - [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md)
- [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md) - [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md)
- [Get Specific Values From Arrays And Hashes](ruby/get-specific-values-from-hashes-and-arrays.md)
- [Get The Names Of The Month](ruby/get-the-names-of-the-month.md)
- [Get The Output Of Running A System Program](ruby/get-the-output-of-running-a-system-program.md) - [Get The Output Of Running A System Program](ruby/get-the-output-of-running-a-system-program.md)
- [Get UTC Offset For Different Time Zones](ruby/get-utc-offset-for-different-time-zones.md) - [Get UTC Offset For Different Time Zones](ruby/get-utc-offset-for-different-time-zones.md)
- [Identify Outdated Gems](ruby/identify-outdated-gems.md) - [Identify Outdated Gems](ruby/identify-outdated-gems.md)
@@ -1416,18 +1252,14 @@ If you've learned something here, support my efforts writing daily TILs by
- [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md) - [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md)
- [Include Extra Context In A Honeybadger Notify](ruby/include-extra-context-in-a-honeybadger-notify.md) - [Include Extra Context In A Honeybadger Notify](ruby/include-extra-context-in-a-honeybadger-notify.md)
- [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md) - [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md)
- [Install And Require Gems Inline Without Gemfile](ruby/install-and-require-gems-inline-without-gemfile.md)
- [Install Latest Version Of Ruby With asdf](ruby/install-latest-version-of-ruby-with-asdf.md)
- [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md) - [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md)
- [IRB Has Built-In Benchmarking With Ruby 3](ruby/irb-has-built-in-benchmarking-with-ruby-3.md) - [IRB Has Built-In Benchmarking With Ruby 3](ruby/irb-has-built-in-benchmarking-with-ruby-3.md)
- [Join URI Path Parts](ruby/join-uri-path-parts.md)
- [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md) - [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md)
- [Last Raised Exception In The Call Stack](ruby/last-raised-exception-in-the-call-stack.md) - [Last Raised Exception In The Call Stack](ruby/last-raised-exception-in-the-call-stack.md)
- [Limit Split](ruby/limit-split.md) - [Limit Split](ruby/limit-split.md)
- [List The Running Ruby Version](ruby/list-the-running-ruby-version.md) - [List The Running Ruby Version](ruby/list-the-running-ruby-version.md)
- [Listing Local Variables](ruby/listing-local-variables.md) - [Listing Local Variables](ruby/listing-local-variables.md)
- [Make An Executable Ruby Script](ruby/make-an-executable-ruby-script.md) - [Make An Executable Ruby Script](ruby/make-an-executable-ruby-script.md)
- [Make Structs Easier To Use With Keyword Initialization](ruby/make-structs-easier-to-use-with-keyword-initialization.md)
- [Map With Index Over An Array](ruby/map-with-index-over-an-array.md) - [Map With Index Over An Array](ruby/map-with-index-over-an-array.md)
- [Mock Method Chain Calls With RSpec](ruby/mock-method-chain-calls-with-rspec.md) - [Mock Method Chain Calls With RSpec](ruby/mock-method-chain-calls-with-rspec.md)
- [Mocking Requests With Partial URIs Using Regex](ruby/mocking-requests-with-partial-uris-using-regex.md) - [Mocking Requests With Partial URIs Using Regex](ruby/mocking-requests-with-partial-uris-using-regex.md)
@@ -1435,7 +1267,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Named Regex Captures Are Assigned To Variables](ruby/named-regex-captures-are-assigned-to-variables.md) - [Named Regex Captures Are Assigned To Variables](ruby/named-regex-captures-are-assigned-to-variables.md)
- [Navigate Back In The Browser With Capybara](ruby/navigate-back-in-the-browser-with-capybara.md) - [Navigate Back In The Browser With Capybara](ruby/navigate-back-in-the-browser-with-capybara.md)
- [Next And Previous Floats](ruby/next-and-previous-floats.md) - [Next And Previous Floats](ruby/next-and-previous-floats.md)
- [OpenStruct Has Bad Performance Characteristics](ruby/open-struct-has-bad-performance-characteristics.md)
- [Or Operator Precedence](ruby/or-operator-precedence.md) - [Or Operator Precedence](ruby/or-operator-precedence.md)
- [Output Bytecode For A Ruby Program](ruby/output-bytecode-for-a-ruby-program.md) - [Output Bytecode For A Ruby Program](ruby/output-bytecode-for-a-ruby-program.md)
- [Override The Initial Sequence Value](ruby/override-the-initial-sequence-value.md) - [Override The Initial Sequence Value](ruby/override-the-initial-sequence-value.md)
@@ -1453,9 +1284,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Question Mark Operator](ruby/question-mark-operator.md) - [Question Mark Operator](ruby/question-mark-operator.md)
- [Rake Only Lists Tasks With Descriptions](ruby/rake-only-lists-tasks-with-descriptions.md) - [Rake Only Lists Tasks With Descriptions](ruby/rake-only-lists-tasks-with-descriptions.md)
- [Read The First Line From A File](ruby/read-the-first-line-from-a-file.md) - [Read The First Line From A File](ruby/read-the-first-line-from-a-file.md)
- [Refer To Implicit Block Argument With It](ruby/refer-to-implicit-block-argument-with-it.md)
- [Reference Hash Key With Safe Navigation](ruby/reference-hash-key-with-safe-navigation.md)
- [Regenerate Lock File With Newer Bundler](ruby/regenerate-lock-file-with-newer-bundler.md)
- [Rendering ERB](ruby/rendering-erb.md) - [Rendering ERB](ruby/rendering-erb.md)
- [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md) - [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md)
- [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md) - [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md)
@@ -1470,11 +1298,9 @@ If you've learned something here, support my efforts writing daily TILs by
- [Scripting With RVM](ruby/scripting-with-rvm.md) - [Scripting With RVM](ruby/scripting-with-rvm.md)
- [Scroll To Top Of Page With Capybara](ruby/scroll-to-top-of-page-with-capybara.md) - [Scroll To Top Of Page With Capybara](ruby/scroll-to-top-of-page-with-capybara.md)
- [Search For Gem Versions Available To Install](ruby/search-for-gem-versions-available-to-install.md) - [Search For Gem Versions Available To Install](ruby/search-for-gem-versions-available-to-install.md)
- [Set Default Tasks For Rake To Run](ruby/set-default-tasks-for-rake-to-run.md)
- [Set RVM Default Ruby](ruby/set-rvm-default-ruby.md) - [Set RVM Default Ruby](ruby/set-rvm-default-ruby.md)
- [Shift The Month On A Date Object](ruby/shift-the-month-on-a-date-object.md) - [Shift The Month On A Date Object](ruby/shift-the-month-on-a-date-object.md)
- [Show Public Methods With Pry](ruby/show-public-methods-with-pry.md) - [Show Public Methods With Pry](ruby/show-public-methods-with-pry.md)
- [Show The Bundler Location Of An Installed Gem](ruby/show-the-bundler-location-of-an-installed-gem.md)
- [Silence The Output Of A Ruby Statement In Pry](ruby/silence-the-output-of-a-ruby-statement-in-pry.md) - [Silence The Output Of A Ruby Statement In Pry](ruby/silence-the-output-of-a-ruby-statement-in-pry.md)
- [Single And Double Quoted String Notation](ruby/single-and-double-quoted-string-notation.md) - [Single And Double Quoted String Notation](ruby/single-and-double-quoted-string-notation.md)
- [Skip Specific CVEs When Auditing Your Bundle](ruby/skip-specific-cves-when-auditing-your-bundle.md) - [Skip Specific CVEs When Auditing Your Bundle](ruby/skip-specific-cves-when-auditing-your-bundle.md)
@@ -1515,7 +1341,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [OSX sed Does Regex A Bit Different](sed/osx-sed-does-regex-a-bit-different.md) - [OSX sed Does Regex A Bit Different](sed/osx-sed-does-regex-a-bit-different.md)
- [Output Only Lines Involved In A Substitution](sed/output-only-lines-involved-in-a-substitution.md) - [Output Only Lines Involved In A Substitution](sed/output-only-lines-involved-in-a-substitution.md)
- [Reference A Capture In The Regex](sed/reference-a-capture-in-the-regex.md) - [Reference A Capture In The Regex](sed/reference-a-capture-in-the-regex.md)
- [Reference The Full Match In The Replacement](sed/reference-the-full-match-in-the-replacement.md)
- [Use An Alternative Delimiter In A Substitution](sed/use-an-alternative-delimiter-in-a-substitution.md) - [Use An Alternative Delimiter In A Substitution](sed/use-an-alternative-delimiter-in-a-substitution.md)
### Shell ### Shell
@@ -1526,7 +1351,6 @@ If you've learned something here, support my efforts writing daily TILs by
### SQLite ### SQLite
- [Display Results In Readable Column Format](sqlite/display-results-in-readable-column-format.md) - [Display Results In Readable Column Format](sqlite/display-results-in-readable-column-format.md)
- [Explore The Database Schema](sqlite/explore-the-database-schema.md)
### Streaming ### Streaming
@@ -1536,19 +1360,12 @@ If you've learned something here, support my efforts writing daily TILs by
- [Apply Tailwind Classes To Existing CSS Class](tailwind/apply-tailwind-classes-to-existing-css-class.md) - [Apply Tailwind Classes To Existing CSS Class](tailwind/apply-tailwind-classes-to-existing-css-class.md)
- [Base Styles For Text Link](tailwind/base-styles-for-text-link.md) - [Base Styles For Text Link](tailwind/base-styles-for-text-link.md)
- [Disable And Enable A Button](tailwind/disable-and-enable-a-button.md)
- [Specify Paths For Purging Unused CSS](tailwind/specify-paths-for-purging-unused-css.md) - [Specify Paths For Purging Unused CSS](tailwind/specify-paths-for-purging-unused-css.md)
- [Use Tailwind Typography Prose In Dark Mode](tailwind/use-tailwind-typography-prose-in-dark-mode.md) - [Use Tailwind Typography Prose In Dark Mode](tailwind/use-tailwind-typography-prose-in-dark-mode.md)
### Taskfile
- [Create Interactive Picker For Set Of Subtasks](taskfile/create-interactive-picker-for-set-of-subtasks.md)
- [Run A Task If It Meets Criteria](taskfile/run-a-task-if-it-meets-criteria.md)
### tmux ### tmux
- [Access Past Copy Buffer History](tmux/access-past-copy-buffer-history.md) - [Access Past Copy Buffer History](tmux/access-past-copy-buffer-history.md)
- [Add Bindings To Split Panes To Current Directory](tmux/add-bindings-to-split-panes-to-current-directory.md)
- [Adjusting Window Pane Size](tmux/adjusting-window-pane-size.md) - [Adjusting Window Pane Size](tmux/adjusting-window-pane-size.md)
- [Break Current Pane Out To Separate Window](tmux/break-current-pane-out-to-separate-window.md) - [Break Current Pane Out To Separate Window](tmux/break-current-pane-out-to-separate-window.md)
- [Change Base Directory Of Existing Session](tmux/change-base-directory-of-existing-session.md) - [Change Base Directory Of Existing Session](tmux/change-base-directory-of-existing-session.md)
@@ -1566,7 +1383,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Kill Other Connections To A Session](tmux/kill-other-connections-to-a-session.md) - [Kill Other Connections To A Session](tmux/kill-other-connections-to-a-session.md)
- [Kill The Current Session](tmux/kill-the-current-session.md) - [Kill The Current Session](tmux/kill-the-current-session.md)
- [List All Key Bindings](tmux/list-all-key-bindings.md) - [List All Key Bindings](tmux/list-all-key-bindings.md)
- [List Processes Running Across All Session](tmux/list-processes-running-across-all-sessions.md)
- [List Sessions](tmux/list-sessions.md) - [List Sessions](tmux/list-sessions.md)
- [Open New Splits To The Current Directory](tmux/open-new-splits-to-the-current-directory.md) - [Open New Splits To The Current Directory](tmux/open-new-splits-to-the-current-directory.md)
- [Open New Window With A Specific Directory](tmux/open-new-window-with-a-specific-directory.md) - [Open New Window With A Specific Directory](tmux/open-new-window-with-a-specific-directory.md)
@@ -1579,7 +1395,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Reset An Option Back To Its Default Value](tmux/reset-an-option-back-to-its-default-value.md) - [Reset An Option Back To Its Default Value](tmux/reset-an-option-back-to-its-default-value.md)
- [Set Environment Variables When Creating Session](tmux/set-environment-variables-when-creating-session.md) - [Set Environment Variables When Creating Session](tmux/set-environment-variables-when-creating-session.md)
- [Set Session Specific Environment Variables](tmux/set-session-specific-environment-variables.md) - [Set Session Specific Environment Variables](tmux/set-session-specific-environment-variables.md)
- [Set Up Forwarding Prefix For Nested Session](tmux/set-up-forwarding-prefix-for-nested-session.md)
- [Show The Current Value For An Option](tmux/show-the-current-value-for-an-option.md) - [Show The Current Value For An Option](tmux/show-the-current-value-for-an-option.md)
- [Swap Split Panes](tmux/swap-split-panes.md) - [Swap Split Panes](tmux/swap-split-panes.md)
- [Switch To A Specific Session And Window](tmux/switch-to-a-specific-session-and-window.md) - [Switch To A Specific Session And Window](tmux/switch-to-a-specific-session-and-window.md)
@@ -1613,8 +1428,6 @@ If you've learned something here, support my efforts writing daily TILs by
### Unix ### Unix
- [All The Environment Variables](unix/all-the-environment-variables.md) - [All The Environment Variables](unix/all-the-environment-variables.md)
- [Apply Successive Filters To Lines In Less](unix/apply-successive-filters-to-lines-in-less.md)
- [Authorize A cURL Request](unix/authorize-a-curl-request.md)
- [Cat A File With Line Numbers](unix/cat-a-file-with-line-numbers.md) - [Cat A File With Line Numbers](unix/cat-a-file-with-line-numbers.md)
- [Cat Files With Color Using Bat](unix/cat-files-with-color-using-bat.md) - [Cat Files With Color Using Bat](unix/cat-files-with-color-using-bat.md)
- [Change Default Shell For A User](unix/change-default-shell-for-a-user.md) - [Change Default Shell For A User](unix/change-default-shell-for-a-user.md)
@@ -1636,19 +1449,14 @@ If you've learned something here, support my efforts writing daily TILs by
- [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 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 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 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 File Descriptor with Process Substitution](unix/create-a-file-descriptor-with-process-substitution.md)
- [Create A Filename With The Current Date](unix/create-a-filename-with-the-current-date.md)
- [Create A Sequence Of Values With A Step](unix/create-a-sequence-of-values-with-a-step.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) - [Curl With Cookies](unix/curl-with-cookies.md)
- [Curling For Headers](unix/curling-for-headers.md) - [Curling For Headers](unix/curling-for-headers.md)
- [Curling With Basic Auth Credentials](unix/curling-with-basic-auth-credentials.md) - [Curling With Basic Auth Credentials](unix/curling-with-basic-auth-credentials.md)
- [Determine ipv4 And ipv6 Public IP Addresses](unix/determine-ipv4-and-ipv6-public-ip-addresses.md)
- [Diff Two Files In Unified Format](unix/diff-two-files-in-unified-format.md)
- [Different Ways To Generate A v4 UUID](unix/different-ways-to-generate-a-v4-uuid.md) - [Different Ways To Generate A v4 UUID](unix/different-ways-to-generate-a-v4-uuid.md)
- [Display All The Terminal Colors](unix/display-all-the-terminal-colors.md) - [Display All The Terminal Colors](unix/display-all-the-terminal-colors.md)
- [Display Free Disk Space](unix/display-free-disk-space.md) - [Display Free Disk Space](unix/display-free-disk-space.md)
- [Display Line Numbers While Using Less](unix/display-line-numbers-while-using-less.md)
- [Display The Contents Of A Directory As A Tree](unix/display-the-contents-of-a-directory-as-a-tree.md) - [Display The Contents Of A Directory As A Tree](unix/display-the-contents-of-a-directory-as-a-tree.md)
- [Do A Dry Run Of An rsync](unix/do-a-dry-run-of-an-rsync.md) - [Do A Dry Run Of An rsync](unix/do-a-dry-run-of-an-rsync.md)
- [Do Not Overwrite Existing Files](unix/do-not-overwrite-existing-files.md) - [Do Not Overwrite Existing Files](unix/do-not-overwrite-existing-files.md)
@@ -1656,14 +1464,11 @@ If you've learned something here, support my efforts writing daily TILs by
- [Enable Multi-Select Of Results With fzf](unix/enable-multi-select-of-results-with-fzf.md) - [Enable Multi-Select Of Results With fzf](unix/enable-multi-select-of-results-with-fzf.md)
- [Exclude A Command From The ZSH History File](unix/exclude-a-command-from-the-zsh-history-file.md) - [Exclude A Command From The ZSH History File](unix/exclude-a-command-from-the-zsh-history-file.md)
- [Exclude A Directory With Find](unix/exclude-a-directory-with-find.md) - [Exclude A Directory With Find](unix/exclude-a-directory-with-find.md)
- [Exclude A Specific File From fd Results](unix/exclude-a-specific-file-from-fd-results.md)
- [Exclude Certain Files From An rsync Run](unix/exclude-certain-files-from-an-rsync-run.md) - [Exclude Certain Files From An rsync Run](unix/exclude-certain-files-from-an-rsync-run.md)
- [Figure Out The Week Of The Year From The Terminal](unix/figure-out-the-week-of-the-year-from-the-terminal.md) - [Figure Out The Week Of The Year From The Terminal](unix/figure-out-the-week-of-the-year-from-the-terminal.md)
- [File Type Info With File](unix/file-type-info-with-file.md) - [File Type Info With File](unix/file-type-info-with-file.md)
- [Find All Files Matching A Name With fd](unix/find-all-files-matching-a-name-with-fd.md) - [Find All Files Matching A Name With fd](unix/find-all-files-matching-a-name-with-fd.md)
- [Find All Files With A Specific Extension With fd](unix/find-all-files-with-a-specific-extension-with-fd.md) - [Find All Files With A Specific Extension With fd](unix/find-all-files-with-a-specific-extension-with-fd.md)
- [Find All Tool Version Files Containing Postgres](unix/find-all-tool-version-files-containing-postgres.md)
- [Find And Copy A Value From Large JSON Output](unix/find-and-copy-a-value-from-large-json-output.md)
- [Find Any Dotfiles That Modify Path Env Var](unix/find-any-dotfiles-that-modify-path-env-var.md) - [Find Any Dotfiles That Modify Path Env Var](unix/find-any-dotfiles-that-modify-path-env-var.md)
- [Find A File Installed By Brew](unix/find-a-file-installed-by-brew.md) - [Find A File Installed By Brew](unix/find-a-file-installed-by-brew.md)
- [Find Duplicate Lines In A File](unix/find-duplicate-lines-in-a-file.md) - [Find Duplicate Lines In A File](unix/find-duplicate-lines-in-a-file.md)
@@ -1671,19 +1476,15 @@ If you've learned something here, support my efforts writing daily TILs by
- [Find Newer Files](unix/find-newer-files.md) - [Find Newer Files](unix/find-newer-files.md)
- [Find Occurrences Of Multiple Values With Ripgrep](unix/find-occurrences-of-multiple-values-with-ripgrep.md) - [Find Occurrences Of Multiple Values With Ripgrep](unix/find-occurrences-of-multiple-values-with-ripgrep.md)
- [Find Top-Level Directories Matching A Pattern](unix/find-top-level-directories-matching-a-pattern.md) - [Find Top-Level Directories Matching A Pattern](unix/find-top-level-directories-matching-a-pattern.md)
- [Fix Previous Command With fc](unix/fix-previous-command-with-fc.md)
- [Fix Shim Path After asdf Upgrade](unix/fix-shim-path-after-asdf-upgrade.md)
- [Fix Unlinked Node Binaries With asdf](unix/fix-unlinked-node-binaries-with-asdf.md) - [Fix Unlinked Node Binaries With asdf](unix/fix-unlinked-node-binaries-with-asdf.md)
- [Forward Multiple Ports Over SSH](unix/forward-multiple-ports-over-ssh.md) - [Forward Multiple Ports Over SSH](unix/forward-multiple-ports-over-ssh.md)
- [Generate A SAML Key And Certificate Pair](unix/generate-a-saml-key-and-certificate-pair.md) - [Generate A SAML Key And Certificate Pair](unix/generate-a-saml-key-and-certificate-pair.md)
- [Generate A Sequence Of Numbered Items](unix/generate-a-sequence-of-numbered-items.md)
- [Generate Base64 Encoding Without Newlines](unix/generate-base64-encoding-without-newlines.md) - [Generate Base64 Encoding Without Newlines](unix/generate-base64-encoding-without-newlines.md)
- [Generate Random 20-Character Hex String](unix/generate-random-20-character-hex-string.md) - [Generate Random 20-Character Hex String](unix/generate-random-20-character-hex-string.md)
- [Get A List Of Locales On Your System](unix/get-a-list-of-locales-on-your-system.md) - [Get A List Of Locales On Your System](unix/get-a-list-of-locales-on-your-system.md)
- [Get Matching Filenames As Output From Grep](unix/get-matching-filenames-as-output-from-grep.md) - [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 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 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) - [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 All Directories In Zsh](unix/globbing-for-all-directories-in-zsh.md)
- [Globbing For Filenames In Zsh](unix/globbing-for-filenames-in-zsh.md) - [Globbing For Filenames In Zsh](unix/globbing-for-filenames-in-zsh.md)
@@ -1691,21 +1492,17 @@ If you've learned something here, support my efforts writing daily TILs by
- [Grep For Files Without A Match](unix/grep-for-files-without-a-match.md) - [Grep For Files Without A Match](unix/grep-for-files-without-a-match.md)
- [Grep For Files With Multiple Matches](unix/grep-for-files-with-multiple-matches.md) - [Grep For Files With Multiple Matches](unix/grep-for-files-with-multiple-matches.md)
- [Grep For Multiple Patterns](unix/grep-for-multiple-patterns.md) - [Grep For Multiple Patterns](unix/grep-for-multiple-patterns.md)
- [Have Script ShellCheck Itself When Executing](unix/have-script-shellcheck-itself-when-executing.md)
- [Hexdump A Compiled File](unix/hexdump-a-compiled-file.md) - [Hexdump A Compiled File](unix/hexdump-a-compiled-file.md)
- [Ignore A Directory During ripgrep Search](unix/ignore-a-directory-during-ripgrep-search.md) - [Ignore A Directory During ripgrep Search](unix/ignore-a-directory-during-ripgrep-search.md)
- [Ignore The Alias When Running A Command](unix/ignore-the-alias-when-running-a-command.md) - [Ignore The Alias When Running A Command](unix/ignore-the-alias-when-running-a-command.md)
- [Include Ignore Files In Ripgrep Search](unix/include-ignore-files-in-ripgrep-search.md) - [Include Ignore Files In Ripgrep Search](unix/include-ignore-files-in-ripgrep-search.md)
- [Interactively Browse Available Node Versions](unix/interactively-browse-availabile-node-versions.md) - [Interactively Browse Available Node Versions](unix/interactively-browse-availabile-node-versions.md)
- [Interactively Switch asdf Package Versions](unix/interactively-switch-asdf-package-versions.md) - [Interactively Switch asdf Package Versions](unix/interactively-switch-asdf-package-versions.md)
- [Interpret Cron Schedule From The CLI](unix/interpret-cron-schedule-from-the-cli.md)
- [Jump To The Ends Of Your Shell History](unix/jump-to-the-ends-of-your-shell-history.md) - [Jump To The Ends Of Your Shell History](unix/jump-to-the-ends-of-your-shell-history.md)
- [Kill Everything Running On A Certain Port](unix/kill-everything-running-on-a-certain-port.md) - [Kill Everything Running On A Certain Port](unix/kill-everything-running-on-a-certain-port.md)
- [Killing A Frozen SSH Session](unix/killing-a-frozen-ssh-session.md) - [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) - [Last Argument Of The Last Command](unix/last-argument-of-the-last-command.md)
- [Less With Style](unix/less-with-style.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 The Enabled ZSH Options](unix/list-all-the-enabled-zsh-options.md)
- [List All Users](unix/list-all-users.md) - [List All Users](unix/list-all-users.md)
- [List Files In A Single Column](unix/list-files-in-a-single-column.md) - [List Files In A Single Column](unix/list-files-in-a-single-column.md)
@@ -1715,14 +1512,11 @@ If you've learned something here, support my efforts writing daily TILs by
- [List Parent pid With ps](unix/list-parent-pid-with-ps.md) - [List Parent pid With ps](unix/list-parent-pid-with-ps.md)
- [List Stats For A File](unix/list-stats-for-a-file.md) - [List Stats For A File](unix/list-stats-for-a-file.md)
- [List The Available JDKs](unix/list-the-available-jdks.md) - [List The Available JDKs](unix/list-the-available-jdks.md)
- [List The PID And Name Of Current Shell Process](unix/list-the-pid-and-name-of-current-shell-process.md)
- [List The Stack Of Remembered Directories](unix/list-the-stack-of-remembered-directories.md) - [List The Stack Of Remembered Directories](unix/list-the-stack-of-remembered-directories.md)
- [List TXT DNS Records For A Domain](unix/list-txt-dns-records-for-a-domain.md) - [List TXT DNS Records For A Domain](unix/list-txt-dns-records-for-a-domain.md)
- [Load Env Vars In Bash Script](unix/load-env-vars-in-bash-script.md) - [Load Env Vars In Bash Script](unix/load-env-vars-in-bash-script.md)
- [Look Through All Files That Have Been Git Stashed](unix/look-through-all-files-that-have-been-git-stashed.md) - [Look Through All Files That Have Been Git Stashed](unix/look-through-all-files-that-have-been-git-stashed.md)
- [Make Direnv Less Noisy](unix/make-direnv-less-noisy.md) - [Make Direnv Less Noisy](unix/make-direnv-less-noisy.md)
- [Make Neovim The Default Way To View Man Pages](unix/make-neovim-the-default-way-to-view-man-pages.md)
- [Manually Pass Two Git Files To Delta](unix/manually-pass-two-git-files-to-delta.md)
- [Map A Domain To localhost](unix/map-a-domain-to-localhost.md) - [Map A Domain To localhost](unix/map-a-domain-to-localhost.md)
- [Negative Look-Ahead Search With ripgrep](unix/negative-look-ahead-search-with-ripgrep.md) - [Negative Look-Ahead Search With ripgrep](unix/negative-look-ahead-search-with-ripgrep.md)
- [Occupy A Local Port With Netcat](unix/occupy-a-local-port-with-netcat.md) - [Occupy A Local Port With Netcat](unix/occupy-a-local-port-with-netcat.md)
@@ -1739,7 +1533,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Produce A Lowercase V4 UUID](unix/produce-a-lowercase-v4-uuid.md) - [Produce A Lowercase V4 UUID](unix/produce-a-lowercase-v4-uuid.md)
- [Provide A Fallback Value For Unset Parameter](unix/provide-a-fallback-value-for-unset-parameter.md) - [Provide A Fallback Value For Unset Parameter](unix/provide-a-fallback-value-for-unset-parameter.md)
- [Remove A Directory Called `-p`](unix/remove-a-directory-called-dash-p.md) - [Remove A Directory Called `-p`](unix/remove-a-directory-called-dash-p.md)
- [Rename A Bunch Of Files By Constructing mv Commands](unix/rename-a-bunch-of-files-by-constructing-mv-commands.md)
- [Repeat Yourself](unix/repeat-yourself.md) - [Repeat Yourself](unix/repeat-yourself.md)
- [Replace Pattern Across Many Files In A Project](unix/replace-pattern-across-many-files-in-a-project.md) - [Replace Pattern Across Many Files In A Project](unix/replace-pattern-across-many-files-in-a-project.md)
- [Run A Command Repeatedly Several Times](unix/run-a-command-repeatedly-several-times.md) - [Run A Command Repeatedly Several Times](unix/run-a-command-repeatedly-several-times.md)
@@ -1751,13 +1544,10 @@ If you've learned something here, support my efforts writing daily TILs by
- [Search History](unix/search-history.md) - [Search History](unix/search-history.md)
- [Search Man Page Descriptions](unix/search-man-page-descriptions.md) - [Search Man Page Descriptions](unix/search-man-page-descriptions.md)
- [Securely Remove Files](unix/securely-remove-files.md) - [Securely Remove Files](unix/securely-remove-files.md)
- [See Where asdf Gets Current Tool Version](unix/see-where-asdf-gets-current-tool-version.md)
- [Set The asdf Package Version For A Single Shell](unix/set-the-asdf-package-version-for-a-single-shell.md) - [Set The asdf Package Version For A Single Shell](unix/set-the-asdf-package-version-for-a-single-shell.md)
- [Shorten SSH Commands With Aliases](unix/shorten-ssh-commands-with-aliases.md)
- [Show A File Preview When Searching With FZF](unix/show-a-file-preview-when-searching-with-fzf.md) - [Show A File Preview When Searching With FZF](unix/show-a-file-preview-when-searching-with-fzf.md)
- [Show Disk Usage For The Current Directory](unix/show-disk-usage-for-the-current-directory.md) - [Show Disk Usage For The Current Directory](unix/show-disk-usage-for-the-current-directory.md)
- [Show The Size Of Everything In A Directory](unix/show-the-size-of-everything-in-a-directory.md) - [Show The Size Of Everything In A Directory](unix/show-the-size-of-everything-in-a-directory.md)
- [Show Tree View Of Processes And Subprocesses](unix/show-tree-view-of-processes-and-subprocesses.md)
- [Skip Paging If Output Fits On Screen With Less](unix/skip-paging-if-output-fits-on-screen-with-less.md) - [Skip Paging If Output Fits On Screen With Less](unix/skip-paging-if-output-fits-on-screen-with-less.md)
- [SSH Escape Sequences](unix/ssh-escape-sequences.md) - [SSH Escape Sequences](unix/ssh-escape-sequences.md)
- [SSH With Port Forwarding](unix/ssh-with-port-forwarding.md) - [SSH With Port Forwarding](unix/ssh-with-port-forwarding.md)
@@ -1766,7 +1556,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Switch Versions of a Brew Formula](unix/switch-versions-of-a-brew-formula.md) - [Switch Versions of a Brew Formula](unix/switch-versions-of-a-brew-formula.md)
- [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md) - [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md)
- [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md) - [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md)
- [Transform Text To Lowercase](unix/transform-text-to-lowercase.md)
- [Type Fewer Paths With Brace Expansion](unix/type-fewer-paths-with-brace-expansion.md) - [Type Fewer Paths With Brace Expansion](unix/type-fewer-paths-with-brace-expansion.md)
- [Undo Changes Made To Current Terminal Prompt](unix/undo-changes-made-to-current-terminal-prompt.md) - [Undo Changes Made To Current Terminal Prompt](unix/undo-changes-made-to-current-terminal-prompt.md)
- [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md) - [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md)
@@ -1808,7 +1597,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Breaking The Undo Sequence](vim/breaking-the-undo-sequence.md) - [Breaking The Undo Sequence](vim/breaking-the-undo-sequence.md)
- [Buffer Time Travel](vim/buffer-time-travel.md) - [Buffer Time Travel](vim/buffer-time-travel.md)
- [Build And Install A Go Program](vim/build-and-install-a-go-program.md) - [Build And Install A Go Program](vim/build-and-install-a-go-program.md)
- [Bypass On-Save Tooling When Writing File](vim/bypass-on-save-tooling-when-writing-file.md)
- [Case-Aware Substitution With vim-abolish](vim/case-aware-substitution-with-vim-abolish.md) - [Case-Aware Substitution With vim-abolish](vim/case-aware-substitution-with-vim-abolish.md)
- [Case-Insensitive Substitution](vim/case-insensitive-substitution.md) - [Case-Insensitive Substitution](vim/case-insensitive-substitution.md)
- [Center The Cursor](vim/center-the-cursor.md) - [Center The Cursor](vim/center-the-cursor.md)
@@ -1849,7 +1637,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Generate and Edit Rails Migration](vim/generate-and-edit-rails-migration.md) - [Generate and Edit Rails Migration](vim/generate-and-edit-rails-migration.md)
- [Get The pid Of The Session](vim/get-the-pid-of-the-session.md) - [Get The pid Of The Session](vim/get-the-pid-of-the-session.md)
- [Go Back To The Previous Window](vim/go-back-to-the-previous-window.md) - [Go Back To The Previous Window](vim/go-back-to-the-previous-window.md)
- [Go To Beginning And End Of Line](vim/go-to-beginning-and-end-of-line.md)
- [Go To File With Line Number](vim/go-to-file-with-line-number.md) - [Go To File With Line Number](vim/go-to-file-with-line-number.md)
- [Grepping Through The Vim Help Files](vim/grepping-through-the-vim-help-files.md) - [Grepping Through The Vim Help Files](vim/grepping-through-the-vim-help-files.md)
- [Head of File Name](vim/head-of-file-name.md) - [Head of File Name](vim/head-of-file-name.md)
@@ -1911,7 +1698,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Replace A Character](vim/replace-a-character.md) - [Replace A Character](vim/replace-a-character.md)
- [Reset Target tslime Pane](vim/reset-target-tslime-pane.md) - [Reset Target tslime Pane](vim/reset-target-tslime-pane.md)
- [Reverse A Group Of Lines](vim/reverse-a-group-of-lines.md) - [Reverse A Group Of Lines](vim/reverse-a-group-of-lines.md)
- [Reword A Commit Message With Fugitive](vim/reword-a-commit-message-with-fugitive.md)
- [Rotate Everything By 13 Letters](vim/rotate-everything-by-13-letters.md) - [Rotate Everything By 13 Letters](vim/rotate-everything-by-13-letters.md)
- [Rotate The Orientation Of Split Windows](vim/rotate-the-orientation-of-split-windows.md) - [Rotate The Orientation Of Split Windows](vim/rotate-the-orientation-of-split-windows.md)
- [Running Bundle With vim-bundler](vim/running-bundle-with-vim-bundler.md) - [Running Bundle With vim-bundler](vim/running-bundle-with-vim-bundler.md)
@@ -1960,7 +1746,6 @@ If you've learned something here, support my efforts writing daily TILs by
- [Find The Location Of User Settings JSON File](vscode/find-the-location-of-user-settings-json-file.md) - [Find The Location Of User Settings JSON File](vscode/find-the-location-of-user-settings-json-file.md)
- [Jump To Problems In The Current File](vscode/jump-to-problems-in-the-current-file.md) - [Jump To Problems In The Current File](vscode/jump-to-problems-in-the-current-file.md)
- [Open An Integrated Terminal Window](vscode/open-an-integrated-terminal-window.md) - [Open An Integrated Terminal Window](vscode/open-an-integrated-terminal-window.md)
- [Open File On Remote Like GitHub](vscode/open-file-on-remote-like-github.md)
- [Pop Open The Quick Fix Window](vscode/pop-open-the-quick-fix-window.md) - [Pop Open The Quick Fix Window](vscode/pop-open-the-quick-fix-window.md)
- [Step Through Project-Wide Search Results](vscode/step-through-project-wide-search-results.md) - [Step Through Project-Wide Search Results](vscode/step-through-project-wide-search-results.md)
- [Synchronize Vim Clipboard With System Clipboard](vscode/synchronize-vim-clipboard-with-system-clipboard.md) - [Synchronize Vim Clipboard With System Clipboard](vscode/synchronize-vim-clipboard-with-system-clipboard.md)
@@ -1982,15 +1767,11 @@ If you've learned something here, support my efforts writing daily TILs by
- [Add Subtitles To Existing Mux Video Asset](workflow/add-subtitles-to-existing-mux-video-asset.md) - [Add Subtitles To Existing Mux Video Asset](workflow/add-subtitles-to-existing-mux-video-asset.md)
- [Access 1Password Credential From CLI](workflow/access-1password-credential-from-cli.md) - [Access 1Password Credential From CLI](workflow/access-1password-credential-from-cli.md)
- [Allow Key-Repeating With Cursor](workflow/allow-key-repeating-with-cursor.md) - [Allow Key-Repeating With Cursor](workflow/allow-key-repeating-with-cursor.md)
- [Break Justfile Into Separate Hidden Steps](workflow/break-justfile-into-separate-hidden-steps.md)
- [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md) - [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md)
- [Configure Email Redirect With Cloudflare](workflow/configure-email-redirect-with-cloudflare.md) - [Configure Email Redirect With Cloudflare](workflow/configure-email-redirect-with-cloudflare.md)
- [Control Media With Drop Keyboard](workflow/control-media-with-drop-keyboard.md)
- [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md) - [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md)
- [Create A Local Sanity Dataset Backup](workflow/create-a-local-sanity-dataset-backup.md) - [Create A Local Sanity Dataset Backup](workflow/create-a-local-sanity-dataset-backup.md)
- [Create A Public URL For A Local Server](workflow/create-a-public-url-for-a-local-server.md) - [Create A Public URL For A Local Server](workflow/create-a-public-url-for-a-local-server.md)
- [Create Todo Items In Logseq](workflow/create-todo-items-in-logseq.md)
- [Do Project Time Tracking From The CLI](workflow/do-project-time-tracking-from-the-cli.md)
- [Enable Dev Tools For Safari](workflow/enable-dev-tools-for-safari.md) - [Enable Dev Tools For Safari](workflow/enable-dev-tools-for-safari.md)
- [Forward Stripe Events To Local Server](workflow/forward-stripe-events-to-local-server.md) - [Forward Stripe Events To Local Server](workflow/forward-stripe-events-to-local-server.md)
- [Get URL For GitHub User Profile Photo](workflow/get-url-for-github-user-profile-photo.md) - [Get URL For GitHub User Profile Photo](workflow/get-url-for-github-user-profile-photo.md)
@@ -1998,18 +1779,13 @@ If you've learned something here, support my efforts writing daily TILs by
- [Import A Github Project Into CodeSandbox](workflow/import-a-github-project-into-codesandbox.md) - [Import A Github Project Into CodeSandbox](workflow/import-a-github-project-into-codesandbox.md)
- [Interactively Kill A Process With fkill](workflow/interactively-kill-a-process-with-fkill.md) - [Interactively Kill A Process With fkill](workflow/interactively-kill-a-process-with-fkill.md)
- [Open Slack's Keyboard Shortcuts Reference Panel](workflow/open-slacks-keyboard-shortcuts-reference-panel.md) - [Open Slack's Keyboard Shortcuts Reference Panel](workflow/open-slacks-keyboard-shortcuts-reference-panel.md)
- [Pop Videos Out As Picture-in-Picture](workflow/pop-videos-out-as-picture-in-picture.md)
- [Prune The Excess From node_modules](workflow/prune-the-excess-from-node-modules.md) - [Prune The Excess From node_modules](workflow/prune-the-excess-from-node-modules.md)
- [Rotate An Image To Be Oriented Upright](workflow/rotate-an-image-to-be-oriented-upright.md) - [Rotate An Image To Be Oriented Upright](workflow/rotate-an-image-to-be-oriented-upright.md)
- [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md) - [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md)
- [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md) - [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md)
- [Send A PDF To Your Kindle](workflow/send-a-pdf-to-your-kindle.md)
- [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md) - [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md)
- [Show Linting Errors In Zed](workflow/show-linting-errors-in-zed.md)
- [Temporarily Hide CleanShot X Capture Previews](workflow/temporarily-hide-cleanshot-x-capture-previews.md)
- [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md) - [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md)
- [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md) - [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md)
- [View A Nicely-Formatted CSV In Terminal](workflow/view-a-nicely-formatted-csv-in-terminal.md)
- [View The PR For The Current GitHub Branch](workflow/view-the-pr-for-the-current-github-branch.md) - [View The PR For The Current GitHub Branch](workflow/view-the-pr-for-the-current-github-branch.md)
### XState ### XState
@@ -2040,9 +1816,7 @@ If you've learned something here, support my efforts writing daily TILs by
### Zsh ### Zsh
- [A Better Way To Reload ZSH Configuration](zsh/a-better-way-to-reload-zsh-configuration.md)
- [Add To The Path Via Path Array](zsh/add-to-the-path-via-path-array.md) - [Add To The Path Via Path Array](zsh/add-to-the-path-via-path-array.md)
- [Create And Jump Into A Directory](zsh/create-and-jump-into-a-directory.md)
- [Link A Scalar To An Array](zsh/link-a-scalar-to-an-array.md) - [Link A Scalar To An Array](zsh/link-a-scalar-to-an-array.md)
- [Use A Space To Exclude Command From History](zsh/use-a-space-to-exclude-command-from-history.md) - [Use A Space To Exclude Command From History](zsh/use-a-space-to-exclude-command-from-history.md)
@@ -2054,10 +1828,6 @@ current number of TILs and display the result in the command tray.
## About ## About
I've written more about how this repo came to be in [How I Built a Learning
Machine](https://dev.to/jbranchaud/how-i-built-a-learning-machine-45k9) and [A
Decade of TILs](https://www.visualmode.dev/a-decade-of-tils).
I shamelessly stole this idea from I shamelessly stole this idea from
[thoughtbot/til](https://github.com/thoughtbot/til). [thoughtbot/til](https://github.com/thoughtbot/til).
@@ -2065,11 +1835,11 @@ I shamelessly stole this idea from
* [Today I Learned by Hashrocket](https://til.hashrocket.com) * [Today I Learned by Hashrocket](https://til.hashrocket.com)
* [jwworth/til](https://github.com/jwworth/til) * [jwworth/til](https://github.com/jwworth/til)
* [til.simonwillison.net](https://til.simonwillison.net/) * [thoughtbot/til](https://github.com/thoughtbot/til)
## License ## License
© 2015-2026 Josh Branchaud © 2015-2022 Josh Branchaud
This repository is licensed under the MIT license. See `LICENSE` for This repository is licensed under the MIT license. See `LICENSE` for
details. details.

View File

@@ -1,73 +0,0 @@
version: '3'
vars:
NOTES_DIR: notes
NOTES_FILE: '{{.NOTES_DIR}}/NOTES.md'
EDITOR: '{{.EDITOR | default "nvim"}}'
tasks:
default:
desc: Show available commands
cmds:
- task --list
notes:
desc: Interactive picker for notes tasks
cmds:
- |
TASK=$(task --list | grep "^\* notes:" | sed 's/^\* notes://' | sed 's/\s\+/ - /' | fzf --prompt="Select notes task: " --height=40% --reverse) || true
if [ -n "$TASK" ]; then
TASK_NAME=$(echo "$TASK" | awk '{print $1}' | sed 's/:$//')
task notes:$TASK_NAME
fi
interactive: true
silent: true
notes:edit:
desc: All-in-one edit, commit, and push notes
cmds:
- task notes:open
- task notes:push
notes:sync:
desc: Sync latest changes from the notes submodule
cmds:
- cd {{.NOTES_DIR}} && git checkout main && git pull
silent: false
notes:open:
desc: Opens NOTES.md (syncs latest changes first) in default editor
deps: [notes:sync]
cmds:
- $EDITOR {{.NOTES_FILE}}
interactive: true
notes:push:
desc: Commit and push changes to notes submodule
dir: '{{.NOTES_DIR}}'
cmds:
- git add NOTES.md
- git commit -m "Update notes - $(date '+%Y-%m-%d %H:%M')"
- git pull --rebase
- git push
status:
- git diff --exit-code NOTES.md
silent: false
notes:status:
desc: Check status of notes submodule
dir: '{{.NOTES_DIR}}'
cmds:
- git status
notes:diff:
desc: Show uncommitted changes in notes
dir: '{{.NOTES_DIR}}'
cmds:
- git diff NOTES.md
notes:log:
desc: Show recent commit history for notes
dir: '{{.NOTES_DIR}}'
cmds:
- git log --oneline -10

View File

@@ -1,30 +0,0 @@
# AWS CLI Requires Groff Executable
I have the AWS CLI installed on this machine, but when I went to run certain
commands like `aws logs tail my_log_group` or even `aws logs tail help`, I'd
get the following error:
```
$ aws logs tail help
Could not find executable named 'groff'
```
This may only be an issue on MacOS Ventura for older versions of the CLI, per
[this PR](https://github.com/aws/aws-cli/pull/7413):
> The CLI's help commands are currently broken on macOS Ventura because Ventura has replaced groff with mandoc. This PR fixes the issue by falling back on mandoc if groff doesn't exist in the path.
There are two ways of dealing with this. One would be to install the missing
dependency, [`groff`](https://www.gnu.org/software/groff/):
```bash
$ brew install groff
```
The other is to update the AWS CLI to one that falls back to `mandoc`.
Depending on how you originally installed the AWS CLI, you can either [follow
their official install/upgrade
instructions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html),
`pip install --upgrade awscli`, or upgrade view homebrew (`brew upgrade
awscli`).

View File

@@ -1,46 +0,0 @@
# Find And Follow Server Logs
Let's say you are authenticated with the AWS CLI and have the appropriate
CloudWatch permissions. You have a few services running in production with
associated logs. One of those is a Rails server.
We want to run `aws logs tail`, but first we check how that command works.
```bash
$ aws logs tail help
```
We see a bunch of options, but the only required one is `group_name` ("The name
of the CloudWatch Logs group."). We may also notice the `--follow` flag which
we'll want to use as well to keep incoming logs flowing.
We need to determine the log group name for the Rails server. We can do that
from the CLI as well (no need to dig into the web UI).
```bash
$ aws logs describe-log-groups
{
"logGroups": [
{
"logGroupName": "/aws/codebuild/fc-rails-app-abcefg-123456",
"creationTime": 1739476650823,
"metricFilterCount": 0,
"arn": "arn:aws:logs:us-east-2:123456789:log-group:/aws/codebuild/fc-rails-app-abcefg-123456:*",
"storedBytes": 65617,
"logGroupClass": "STANDARD",
"logGroupArn": "arn:aws:logs:us-east-2:123456789:log-group:/aws/codebuild/fc-rails-app-abcefg-123456"
},
...
]
}
```
Because the group name is descriptive enough, we can find the log group we are
interested in: `/aws/codebuild/fc-rails-app-abcefg-123456`.
Now we know what we want to `tail`.
```bash
$ aws logs tail /aws/codebuild/fc-rails-app-abcefg-123456 --follow
```

View File

@@ -1,29 +0,0 @@
# List RDS Snapshots With Matching Identifier Prefix
I'm working on a script that manually creates a snapshot which it will then
restore to a temporary database that I can scrub and dump. The snapshots that
this script takes are _manual_ and they are named with identifiers that have a
defining prefix (`dev-snapshot-`). Besides the few snapshots created by this
script, there are tons of automated snapshots that RDS creates for
backup/recovery purposes.
I want to list any snapshots that have been created by the script. I can do
this with the `describe-db-snapshots` command and some filters.
```bash
$ aws rds describe-db-snapshots \
--snapshot-type manual \
--query "DBSnapshots[?starts_with(DBSnapshotIdentifier, 'dev-snapshot-')].DBSnapshotIdentifier" \
--no-cli-pager
[
"dev-snapshot-20250327-155355"
]
```
There are two key pieces. The `--snapshot-type manual` filter excludes all
those automated snapshots. The `--query` both filters to any snapshots whose
identifier `?starts_with` the prefix `dev-snapshot-` and then refines the
output to just the `DBSnapshotIdentifier` instead of the entire JSON object.
[source](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-snapshots.html)

View File

@@ -1,49 +0,0 @@
# Output CLI Results In Different Formats
The AWS CLI can output the results of commands in three different formats.
- Text
- JSON
- Table
The _default_ output format for my AWS CLI is currently configured to `json`.
```bash
$ aws configure get output
json
```
I can either accept the default or I can override it with the `--output` flag.
```bash
$ aws rds describe-db-instances \
--query 'DBInstances[*].Endpoint' \
--no-cli-pager
[
{
"Address": "fc-database-abcefg-ab1c23de.asdfgh4zxcvb.us-east-2.rds.amazonaws.com",
"Port": 5432,
"HostedZoneId": "A1BCDE2FG345H6"
}
]
$ aws rds describe-db-instances \
--query 'DBInstances[*].Endpoint' \
--no-cli-pager \
--output table
----------------------------------------------------------------------------------------------------
| DescribeDBInstances |
+-----------------------------------------------------------------------+-----------------+--------+
| Address | HostedZoneId | Port |
+-----------------------------------------------------------------------+-----------------+--------+
| fc-database-abcefg-ab1c23de.asdfgh4zxcvb.us-east-2.rds.amazonaws.com | A1BCDE2FG345H6 | 5432 |
+-----------------------------------------------------------------------+-----------------+--------+
$ aws rds describe-db-instances \
--query 'DBInstances[*].Endpoint' \
--no-cli-pager \
--output text
fc-database-abcefg-ab1c23de.asdfgh4zxcvb.us-east-2.rds.amazonaws.com A1BCDE2FG345H6 5432
```
[source](https://docs.aws.amazon.com/cli/v1/userguide/cli-usage-output-format.html)

View File

@@ -1,50 +0,0 @@
# SSH Into An ECS Container
In [Connect To Production Rails Console on AWS /
Flightcontrol](https://www.visualmode.dev/connect-to-production-rails-console-aws-flightcontrol),
I went into full detail about how to access `rails console` for a production
Rails app running in an ECS container.
A big part of that process was establishing an SSH connection to the ECS container.
To do that, I need to know my region, container ID, and task ID. I can get the
first two by listing my clusters and finding the cluster/container that houses
the Rails app.
```bash
$ aws ecs list-clusters
{
"clusterArns": [
"arn:aws:ecs:us-east-2:123:cluster/rails-app-abc123"
]
}
```
The region then is `us-east-2` and the container ID is `rails-app-abc123`.
I can use that to find the task ID:
```bash
$ aws ecs list-tasks --region us-east-2 --cluster rails-app-abc123
{
"taskArns": [
"arn:aws:ecs:us-east-2:123:task/rails-app-abc123/8526b3191d103bb1ff90c65a655ad004"
]
}
```
The task ID is the final portion of the URL:
`8526b3191d103bb1ff90c65a655ad004`.
Putting this all together I can SSH into the ECS container with a bash profile
like so:
```bash
$ aws ecs execute-command \
--region us-east-2 \
--cluster rails-app-abc123 \
--container rails-app-abc123 \
--task 8526b3191d103bb1ff90c65a655ad004 \
--interactive \
--command "/bin/bash"
```

View File

@@ -1,38 +0,0 @@
# Turn Off Output Pager For A Command
It is not uncommon for an AWS CLI command to return a ton of output. When that
happens, it is nice that the results end up in pager program (like `less`)
where you can search and review them, copy a value of interest, and then exit.
The pager prevents that wall of output from cluttering your terminal history.
However, sometimes I am running a command that I know is going to return a
small result. I'd rather have the results go to stdout where I can see them in
the terminal history rather than to an ephemeral pager.
For that situation I can tack on the `--no-cli-pager` flag.
```bash
$ aws rds describe-db-instances \
--query 'DBInstances[*].EngineVersion' \
--output json \
--no-cli-pager
[
"13.15",
"16.8"
]
```
Here I've asked the AWS CLI to tell me the engine versions of all my RDS
Postgres databases. Because I know the results are only going to include a
couple results for my couple of DBs, I'd like to skip the pager —
`--no-cli-pager`.
Though I think it is better to do this on a case by case basis, it is also
possible to turn off the pager via the CLI configuration file.
```bash
$ aws configure set cli_pager ""
```
[source](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-pagination.html#cli-usage-pagination-clientside)

View File

@@ -1,37 +0,0 @@
# Use Specific AWS Profile With CLI
I have multiple AWS profiles authenticated with the AWS CLI. For some projects
I need to use the `default` one and for others I need to use the other.
First, I can list the available profiles like so:
```bash
$ aws configure list-profiles
default
dev-my-app
```
For one-off commands I can specify the profile for any AWS CLI command using
the `--profile` flag.
```bash
$ aws ecs list-clusters --profile josh-visualmode
```
However, I don't want to have to specify that flag every time when I'm working
on a specific project. Instead I can specify the profile with an environment
variable. The [`direnv`](https://direnv.net/) tool is a great way to do this on
a per-project / per-directory basis.
I can create or update the `.envrc` file (assuming I have `direnv` installed)
adding the following line (and re-allowing the changed file):
```
# .envrc
export AWS_PROFILE=dev-my-app
```
Now, any AWS command I issue from that directory or its subdirectories will use
that profile by default.
[source](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html#cli-configure-files-using-profiles)

View File

@@ -1,40 +0,0 @@
# Clean Up Your Brew Installations
Over time as you upgrade brew-installed programs and make changes to your
`Brewfile`, your machine will have artifacts left behind that you no longer
need.
Periodically, it is good to clean things up.
First, you can get a summary of stale and outdated files that brew has
installed. Use the `--dry-run` flag.
```bash
$ brew cleanup --dry-run
```
If you feel good about what you see in the output, then give things a clean.
```bash
$ brew cleanup
```
Second, if you are using a `Brewfile` to manage what `brew` installs, then you
can instruct `brew` to uninstall any dependencies that aren't specified in that
file.
By default it operates as a dry run and the `--force` flag will be needed to
actually do the cleanup. And specify the filename if it doesn't match the
default of `Brewfile`.
```bash
$ brew bundle cleanup --file=Brewfile.personal
```
If the output looks good, then force the cleanup:
```bash
$ brew bundle cleanup --force --file=Brewfile.personal
```
See `brew cleanup --help` and `brew bundle --help` for more details.

View File

@@ -1,25 +0,0 @@
# Install From Nonstandard Brewfile
When you want to install the packages listed in the `Brewfile` for your current
project (or dotfiles), you can run:
```bash
$ brew bundle
```
And `brew` knows to look for and use the `Brewfile` in the current directory.
If, however, you are trying to run `brew bundle` for a `Brewfile` located
somewhere besides the current directory *OR* you want to target a file with a
non-standard name (like
[`Brewfile.personal`](https://github.com/jbranchaud/dotfiles/blob/main/Brewfile.personal)),
then you can use the `--file` flag.
```bash
$ brew bundle --file Brewfile.personal
```
This is what I do [here in my `dotfiles`
repo](https://github.com/jbranchaud/dotfiles/blob/b053f6251cae7ed52f698fc2a2c40ba82c5881b0/installer/mac-setup.sh#L42-L48).
See `man brew` and find the section on `brew bundle` for more details.

View File

@@ -1,27 +0,0 @@
# Install Go Packages In Brewfile
Typically my `Brewfile` is only full of `brew` and `cask` directives. That's
starting to change now that `brew` supports installing Go packages listed in the
`Brewfile`.
Use the `go` directive and the URL to the hosted Go package.
Here is an example of a `Brewfile` that includes a `cask`, `brew`, and `go`
directive.
```
# screen resolution tool
cask "betterdisplay"
# Mac keychain management, gpg key
brew "pinentry-mac"
# Sanitized production Postgres dumps
go "github.com/jackc/pg_partialcopy"
```
I've recently added the exact package from above to my [`dotfiles`
repo](https://github.com/jbranchaud/dotfiles/commit/e83e9d19504f0e2f95eba33123f907f999bf865e).
Here is the [PR to `brew`](https://github.com/Homebrew/brew/pull/20798) where
this functionality was added back in October of 2025.

View File

@@ -1,14 +0,0 @@
# Open Current Tab In New Window With Vimium
Sometime I have a busy Chrome window going with a bunch of tabs open for
various lines of work as well as a number of tabs that I've neglected to close.
I then open a new tab, find something useful, and realize I'm at a "branching
point". I'm about to start in on a specific chunk of work that will probably
involve opening several more tabs and switch back and forth between some
dashboards. I want to start all of this from a fresh slate -- or at least from
a fresh Chrome window.
With [Vimium](https://github.com/philc/vimium), I can hit `W` (`Shift-w`) to
have the current tab move from the current window to a new window. The original
window, minus that one tab, will be left as is so that I can go back to it as
needed.

View File

@@ -1,22 +0,0 @@
# Search Tabs With The Vimium Vomnibar
If you use Chrome like I do, then you eventually end up with several windows
with dozens if not 100+ tabs open. It can start to get tedius with that many
tabs to find and navigate to a given tab. Someone might suggest closing a few
dozen tabs as a solution to this predicament. However, Vimium offers a solution
that doesn't require I [_kill my
darlings_](https://en.wiktionary.org/wiki/kill_one%27s_darlings).
The Vomnibar, a Vimium-powered search bar, can be summoned with `T` to only
search through open tabs.
When I hit `T`, I see a text area (for refining the search) and then a bunch of
entries populate below that which I immediately recognize as many of those tabs
that I'm going to get back to one of these days.
To narrow down to the specific thing I'm looking for, I type something into the
input. Then I arrow to the result I'm looking for and hit enter. And I'm
transported to that tab.
If I don't like where I ended up, I can also go back to the tab I had been on
with `^`.

View File

@@ -1,35 +0,0 @@
# Allow Edits From The Start
A common pattern for me when using Claude Code is that I start it up in a
project, I prompt it with a question or feature spec, it either comes up with a
plan or just starts working, and as soon as it is ready to make its first edits
to a file, it prompts me something like:
```
Do you want to make this edit to Taskfile.yml?
1. Yes
2. Yes, allow all edits during this session (shift+tab)
3. Type here to tell Claude what to do differently
```
That's a nice default so that I don't get surprised by Claude Code editing a
bunch of files.
However, if I'm in a git-backed project and I'm going into a session intending
to make edits, then I can skip the formalities. I can tell Claude Code when
starting up the session that edits are allowed.
```sh
$ claude --permission-mode acceptEdits
```
When I do this, I'll see the following indicator below the prompt input field:
```
⏵⏵ accept edits on (shift+tab to cycle)
```
If I've already started `claude` but I forgot to specify that permission mode, I
can also toggle right into _accept edits_ by hitting `Shift+Tab`.
[source](https://www.youtube.com/watch?v=_IK18goX4X8)

View File

@@ -1,18 +0,0 @@
# Monitor Usage Limits From CLI
When I first started using Claude Code enough to push the usage limits, I would
periodically switch over to the browser to check
`https://claude.ai/settings/usage` to see how close I was getting. That page
would tell me what percentage of my allotted usage I had consumed so far for the
current 5-hour session and then how long until that 5-hour usage window resets.
This can also be viewed directly in Claude Code for the CLI.
First, run the `/status` slash command and then _tab_ over to the _Usage_
section. There you will see the same details as in the web view.
I'm also learned, as I write this, that you can go directly to the _Usage_
section by typing the `/usage` slash command.
See [the docs](https://code.claude.com/docs/en/slash-commands) for a listing of
all slash commands.

View File

@@ -1,15 +0,0 @@
# Open Current Prompt In Default Editor
[Claude Code](https://www.claude.com/product/claude-code) gives you a single
line to write a prompt. You can write and write as much as you want, but it will
all be on that single line. And avoid accidentally hitting 'Enter' before you're
done.
I found myself wanting to space out my thoughts, create a code block as part of
a prompt, and generally have a scratch pad instead of just a text box. By
hitting `ctrl-g`, I can move the current prompt into my default editor (in my
case, `nvim`). From there I can continue to write, edit, and format with all the
affordances of an editor.
Once I'm done crafting the prompt, I can save (e.g. `:wq`) and Claude Code will
be primed with that text. I can then hit 'Enter' to let `claude` do its thing.

View File

@@ -1,22 +0,0 @@
# Resume Specific Session
There are a few different ways to resume a [Claude
Code](https://code.claude.com/docs/en/overview) session.
First, if I have exited a session for the current project and I want to pick
back up with that most recent one, then I can use `claude --continue`.
If I have had a few recent sessions for the current project and I want to
remember what they were and pick up where I left off with one of them, then I
can use `claude --resume` (with no argument). That will open a picker where I
can browser through a summary of the recent sessions based on their starting
prompt. The one I pick is the session that will be resumed.
Finally, if I have grabbed a specific session ID (UUID) during the session from
the `/status` output, then I can reference that value directly.
```sh
$ claude --resume 92170532-be31-4a91-b2a9-025b8fa78232
```
See `claude --help` for more details.

View File

@@ -1,29 +0,0 @@
# Filter Blur Requires Expensive Calculation
I had [a
page](https://www.visualmode.dev/connect-to-production-rails-console-aws-flightcontrol)
on my blog that was experiencing some odd rendering behavior. The issue was
manifesting a couple ways.
- Resizing and scrolling were janky and causing entire page layers to re-render
causing the page to flash in and out.
- Sometimes entire layer chunks would fail to paint leaving a white block
missing from the page.
The issue was occurring with and without JavaScript turned on for a
statically-built page. I suspected that some aspect of the CSS was at fault.
I was going back and forth with Dillon Hafer about what the issue could be and
he wondered, "could it be the backdrop-blur class from tailwind?". I tried
removing that class and the responsiveness of the page immediately improved.
The [`filter:
blur`](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/blur)
and [`backdrop-filter:
blur`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter) both
use an expensive [Gaussian blur](https://en.wikipedia.org/wiki/Gaussian_blur)
calculation. One of these on a modern machine and browser probably won't have a
noticable impact. However, a bunch of them, as in the case of my page with a
recurring component, can have quite the performance hit.
[source](https://github.com/tailwindlabs/tailwindcss/issues/15256)

View File

@@ -1,29 +0,0 @@
# Prevent Invisible Elements From Being Clicked
I have a nav element that when clicked reveals a custom drop-down menu. It
reveals it using CSS transitions and transformations (`opacity` and `scale`).
When the nav element is clicked again, the reverse of these transformations is
applied to "hide" the menu. This gives a nice visual effect.
It only makes the menu invisible and doesn't actually make it go away. That
means that menu could be invisible, but hovering over the top of a button on
the screen. The button cannot be clicked now because the menu is intercepting
that [_pointer
event_](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).
The fix is to apply CSS (or a class) when the drop-down menu is closed that
tells it to ignore _pointer events_.
```css
.pointer-events-none {
pointer-events: none;
}
```
This is more of less what [the `pointer-events-none` TailwindCSS
utility](https://tailwindcss.com/docs/pointer-events) looks like.
This class is applied by default to the drop-down menu. Then when the nav item
is clicked, some JavaScript removes that class at the same moment that the menu
is visually appearing. When a menu item is selected or the menu otherwise
closed, it transitions away and the `pointer-events-none` class is reapplied.

View File

@@ -1,32 +0,0 @@
# Allow Cursor To Be Launched From CLI
It is nice to be able to open Cursor for a specific project directly from the
terminal like so:
```bash
$ cd ~/dev/my/project
$ cursor .
```
For the `cursor` launcher binary to be available like that, we have to find it
and add it to the path.
It is probably located in the `/Applications` folder and within that nested down
a couple directories is a `bin` directory that contains the binary we're looking
for.
```bash
ls /Applications/Cursor.app/Contents/Resources/app/bin
 bin/
├──  code*
├──  cursor*
└──  cursor-tunnel*
```
The `cursor` binary is what we want, so let's add that to our path. In my case,
I'll add this to my `~/.zshrc` file.
```bash
export PATH="/Applications/Cursor.app/Contents/Resources/app/bin:$PATH"
```

View File

@@ -1,28 +0,0 @@
# Default Rails Deploy Script On Hatchbox
I deployed a Rails app to [Hatchbox](https://hatchbox.io) recently. When
following along in the log during a deploy, I can see most of what is happening
as part of the deploy. Though it is too verbose to look through every line. I'd
rather see the contents of the deploy script.
I did quite a bit of digging around while SSH'd into my hatchbox server, but I
couldn't find if or where that file might be stored.
Instead, there is a [_Help Center_
article](https://hatchbox.relationkit.io/articles/55-what-is-the-default-rails-deploy-script)
where Chris Oliver shares what is in the script.
```bash
bundle install -j $(nproc)
yarn install
bundle exec rails assets:precompile
[[ -n "${CRON}" ]] && bundle exec rails db:migrate
```
It does a parallelized `bundle install`, then a `yarn install` (make sure your
project is using `yarn.lock`), Rails asset precompilation, and then if `CRON`
is set (Cron role is available by checking _Cron_ under _Server
Responsibilities_ for your Hatchbox server), it will run Rails migrations.
From app settings, the deploy script can be overridden, or pre- and post-deploy
steps can be added.

View File

@@ -1,44 +0,0 @@
# Hatchbox Exports Env Vars With asdf
When you add env vars through the [Hatchbox](https://hatchbox.io/) UI, they get
exported to the environment of the asdf-shimmed processes. This is handled by
the [`asdf-vars` plugin](https://github.com/excid3/asdf-vars). That plugin
looks for `.asdf-vars` in the current chain of directories.
I can see there are many `.asdf-vars` files:
```bash
$ find . -name ".asdf-vars" -type f
./.asdf-vars
./my-app/.asdf-vars
./my-app/releases/20250120195106/.asdf-vars
./my-app/releases/20250121041054/.asdf-vars
```
And it is the one in my app's directory that contains the env vars that I set
in the UI.
```bash
$ cat my-app/.asdf-vars
BUNDLE_WITHOUT=development:test
DATABASE_URL=postgresql://user_123:123456789012345@10.0.1.1/my_app_db
PORT=9000
RACK_ENV=production
RAILS_ENV=production
RAILS_LOG_TO_STDOUT=true
RAILS_MASTER_KEY=abc123
SECRET_KEY_BASE=abc123efg456
```
When I run a shimmed process like `ruby`, those env vars are loaded into the
process's environment.
```bash
$ cd my-app/current
$ which ruby
/home/deploy/.asdf/shims/ruby
$ ruby -e "puts ENV['DATABASE_URL']"
postgresql://user_123:123456789012345@10.0.1.1/my_app_db
```
[source](https://www.visualmode.dev/hatchbox-manages-env-vars-with-asdf)

View File

@@ -1,24 +0,0 @@
# Set Up Domain For Hatchbox Rails App
When we deploy a Rails app with [Hatchbox](https://hatchbox.io), we are given
an internal URL for publicly accessing our app. It is something like
`https://123abc.hatchboxapp.com`. That's useful as we are getting things up and
running, but eventually we want to point our own domain at the app.
The first step is to tell Hatchbox what domain we are going to use.
From our app's _Domain & SSL_ page we can enter a domain into the _Add A
Domain_ input. For instance, I have the
[visualmode.dev](https://visualmode.dev) domain and I want the
[still.visualmode.dev](https://still.visualmode.dev) subdomain pointing at my
Rails app. I submit the full name `still.visualmode.dev` and I get an _A
Record_ ipv4 address (e.g. `23.12.234.82`).
The second step is to configure a DNS record with our domain registrar.
From the DNS settings of our registrar (e.g. Cloudflare) we can add an _A
Record_ where we specify the name (e.g. `still`) and then include the ipv4
address provided by Hatchbox. We can save this and wait a minute for it to
propagate.
And soon enough we can visit our Rails app at the custom domain.

View File

@@ -1,28 +0,0 @@
# Check Postgres Version Running In Docker Container
I have a docker container that I'm using to run a PostgreSQL development
database on my local machine. It was a while ago when I set it up, so I can't
remember specifically which major version of PostgreSQL I am using.
I use `docker ps` to list the names of each container.
```bash
$ docker ps --format "{{.Names}}"
still-postgres-1
better_reads-postgres-1
```
I grab the one I am interested in. In this case, that is `still-postgres-1`.
Then I can execute a `select version()` statement with `psql` against the
container with that name like so:
```bash
$ docker exec still-postgres-1 psql -U postgres -c "select version()";
version
---------------------------------------------------------------------------------------------------------------------
PostgreSQL 16.2 (Debian 16.2-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 row)
```
And there I have it. I'm running Postgres v16 in this container.

View File

@@ -1,53 +0,0 @@
# Prevent Containers From Running On Startup
I have a bunch of docker containers managed by Docker Desktop. Some are related
to projects I'm actively working on. Whereas many others are inactive projects.
When I restart my machine, regardless of which containers I had running or
turned off, several of them are booted into a running state on startup. This is
becaue their restart policy is set to `always`. That's fine for the project I'm
actively working on, but the others I would like to be _off_ by default.
I need to update each of their restart policies from `always` to `no`.
First, I need to figure out their container IDs:
```bash
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eb7b40aeba2d postgres:latest "docker-entrypoint.s…" 3 months ago Up 11 minutes 0.0.0.0:9875->5432/tcp still-postgres-1
eb9ab2213f2b postgres:latest "docker-entrypoint.s…" 3 months ago Exited (0) 11 minutes ago next-drizzle-migration-repro-app-postgres-1
ba792e185734 postgres:latest "docker-entrypoint.s…" 4 months ago Up 11 minutes 0.0.0.0:9876->5432/tcp better_reads-postgres-1
3139f9beae76 postgres:latest "docker-entrypoint.s…" 9 months ago Exited (128) 7 months ago basic-next-prisma-postgres-1
```
Referencing the `CONTAINER ID` and `NAMES` columns, I'm able to then inspect
each container and see the current `RestartPolicy`:
```bash
$ docker inspect eb9ab2213f2b | grep -A3 RestartPolicy
"RestartPolicy": {
"Name": "always",
"MaximumRetryCount": 0
},
```
I can then update the `RestartPolicy` to be `no`:
```bash
$ docker update --restart no eb9ab2213f2b
```
Inpsecting that container again, I can see the updated policy:
```bash
$ docker inspect eb9ab2213f2b | grep -A3 RestartPolicy
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
```
Rinse and repeat for each of the offending containers.
[source](https://stackoverflow.com/questions/45423334/stopping-docker-containers-from-being-there-on-startup)

View File

@@ -1,42 +0,0 @@
# Run SQL Script Against Postgres Container
I've been using dockerized Postgres for local development with several projects
lately. This is typically with framework tooling (like Rails) where schema
migrations and query execution are handled by the tooling using the specified
connection parameters.
However, I was experimenting with and iterating on some Postgres functions
outside of any framework tooling. I needed a way to run the SQL script that
(re)creates the function via `psql` on the docker container.
With a local, non-containerized Postgres instance, I'd redirect the file to
`psql` like so:
```bash
$ psql -U postgres -d postgres < experimental-functions.sql
```
When I tried doing this with `docker exec` though, it was silently failing /
doing nothing. As far as I can tell, there was a mismatch with redirection
handling across the bounds of the container.
To get around this, I first copy the file into the `/tmp` directory on the
container:
```bash
$ docker cp experimental-functions.sql still-postgres-1:/tmp/experimental-functions.sql
```
Then the `psql` command that docker executes can be pointed directly at a
local-to-it SQL file.
```bash
$ docker exec still-postgres-1 psql \
-U postgres \
-d postgres \
-f /tmp/experimental-functions.sql
```
There are probably other ways to handle this, but I got into a nice rhythm with
this file full of `create or replace function ...` definitions where I could
modify, copy over, execute, run some SQL to verify, and repeat.

View File

@@ -1,4 +0,0 @@
{
"excludes": ["README.md"],
"plugins": ["https://plugins.dprint.dev/markdown-0.16.0.wasm"]
}

View File

@@ -9,10 +9,10 @@ test runs. Most of these files are tracked (already checked in to the
repository). There are also many new files generated as part of the most recent repository). There are also many new files generated as part of the most recent
test run. test run.
I want to stage the changes to files that are already tracked, but hold off on I want to staging the changes to files that are already tracked, but hold off
doing anything with the new files. on doing anything with the new files.
Running `git add spec/cassettes` won't do the trick because that will pull in Running `git add spec/cassettes` won't do the track because that will pull in
everything. Running `git add --patch spec/cassettes` will take long and be everything. Running `git add --patch spec/cassettes` will take long and be
tedious. Instead what I want is the `-u` flag. It's short for _update_ which tedious. Instead what I want is the `-u` flag. It's short for _update_ which
means it will only stage already tracked files. means it will only stage already tracked files.

View File

@@ -1,43 +0,0 @@
# Better Diffs With Delta
A `git diff` from the command line is relatively bare bones. It shows you
removed lines and added lines that make up a changeset with the former text in
red and the later text in green. All other contextual text is in white. I've
found this to be good enough for most of the life of my git usage. I've been
missing out though.
By using [`delta`](https://github.com/dandavison/delta) as the pager and diff
filter for `git`, I get a bunch of nice visual improvements.
- Removals and additions are red and green shaded backgrounds
- Syntax highlighting for most languages
- Highlight specific part of a line that has changed
- Visual spacing and layout is clearer
To get all of this, all I had to do was install `delta`:
```bash
$ brew install delta
```
And then add `delta` as both the _core_ pager and `diffFilter` in my global git
config file:
```
[core]
pager = delta
[interactive]
singleKey = true # unrelated, but nice to have
diffFilter = delta --color-only
```
It's also recommended that you use `zdiff3` for your merge conflict style,
which I already had:
```
[merge]
conflictstyle = zdiff3
```
Once you have ths all configred, try a `git diff` or `git add --patch` and see
how much more visual info you get.

View File

@@ -1,38 +0,0 @@
# Check If A File Has Changed In A Script
If I'm at the command line and I want to check if a file has changed, I can run
`git diff` and see what has changed. If I want to be more specific, I can run
`git diff README.md` to see if there are changes to that specific file.
If I'm trying to do this check in a script though, I want the command to clearly
tell the script _Yes_ or _No_. Usually a script looks for an exit code to
determine what path to take. But as long as `git diff` runs successfully,
regardless of whether or not their are changes, it is going to have an
affirmative exit code of `0`.
This is why `git diff` offers the `--exit-code` flag.
> Make the program exit with codes similar to diff(1). That is, it exits with 1
> if there were differences and 0 means no differences.
With that in mind, we can wire up a script with `git diff` that takes different
paths depending on whether or not there are changes.
```bash
if ! git diff --exit-code README.md; then
echo "README.md has changes"
else
echo "README.md is clean"
fi
```
We can take this a step further and instead use the `--quiet` flag.
> Disable all output of the program. Implies --exit-code. Disables execution of
> external diff helpers whose exit code is not trusted
This exhibits the same behavior as `--exit-code` and goes the additional step of
silencing diff output and disabling execution of external diff helpers like
`delta`.
See `man git-diff` for more details.

View File

@@ -1,36 +0,0 @@
# Check If A File Is Under Version Control
The `git ls-files` command can be used with the `--error-unmatch` flag to check
if a file is under version control. It does this by checking if any of the
listed files appears on the _index_. If any does not, it is treated as an error.
In a project, I have a `README.md` that is under version control. And I have
`node_modules` that shouldn't be under version control (which is why they are
listed in my `.gitignore` file). I can check the README and a file somewhere in
`node_modules`.
```bash
git ls-files --error-unmatch README.md
README.md
git ls-files --error-unmatch node_modules/@ai-sdk/anthropic/CHANGELOG.md
error: pathspec 'node_modules/@ai-sdk/anthropic/CHANGELOG.md' did not match any file(s) known to git
Did you forget to 'git add'?
```
Notice the second command results in an error because of the untracked
`CHANGELOG.md` file in `node_modules`.
Here is another example of this at work while specifying multiple files:
```bash
git ls-files --error-unmatch README.md node_modules/@ai-sdk/anthropic/CHANGELOG.md package.json
README.md
package.json
error: pathspec 'node_modules/@ai-sdk/anthropic/CHANGELOG.md' did not match any file(s) known to git
Did you forget to 'git add'?
```
Each tracked file gets listed and then the untracked file results in an error.
See `man git-ls-files` for more details.

View File

@@ -1,35 +0,0 @@
# Cherry Pick Multiple Commits At Once
I've always thought of `git cherry-pick` as being a command that you can run
against a single commit by specifying the SHA of that commit. That's how I've
always used it.
The man page for `git-cherry-pick` plainly states:
> Given one or more existing commits, apply the change each one introduces,
> recording a new commit for each.
We can cherry pick multiple commits at once in a single command. They will be
applied one at a time in the order listed.
Here we can see an example of applying two commits to the current branch and
the accompanying output as they are auto-merged.
```bash
$ git cherry-pick 5206af5 6362f41
Auto-merging test/services/event_test.rb
[jb/my-feature-branch 961f3deb] Use the other testing syntax
Date: Fri May 2 10:50:14 2025 -0500
1 file changed, 7 insertions(+), 7 deletions(-)
Auto-merging test/services/event_test.rb
[jb/my-feature-branch b15835d0] Make other changes to the test
Date: Fri May 2 10:54:48 2025 -0500
1 file changed, 7 insertions(+), 7 deletions(-)
```
If the commits cannot be cleanly merged, then you may need to do some manual
resolution as they are applied. Or maybe you want to try including the
`-Xpatience` merge strategy.
See `man git-cherry-pick` for more details. Make sure to look at the _Examples_
section which contains much more advanced examples beyond what is shown above.

View File

@@ -1,26 +0,0 @@
# Clear Entries From Git Stash
I often stash changes as I'm moving between branches, rebasing, or pulling in
changes from the remote. Usually these are changes that I will want to restore
with a `git stash pop` in a few moments.
However, sometimes these stashed changes are abandoned to time.
When I run `git stash list` on an active project, I see that there are nine
entries in the list. When I do `git show stash@{0}` and `git show stash@{1}` to
see the changes that comprise the latest two entries, I don't see anything I
care about.
I can get rid of those individual entries with, say, `git stash drop
stash@{0}`.
But I'm pretty confident that I don't care about any of the nine entries in my
stash list, so I want to _clear_ out all of them. I can do that with:
```bash
$ git stash clear
```
Now when I run `git stash list`, I see nothing.
See `man git-stash` for more details.

View File

@@ -1,48 +0,0 @@
# Count Number Of Commits On A Branch
The `git rev-list` command will show all commits that fit the given revision
criteria. By adding in the `--count` flag, we get a count of the number of
commits that would have been displayed. Knowing this, we can get the count of
commits for the current branch like so:
```bash
$ git rev-list --count HEAD
4
```
This finds and counts commits from `HEAD` (usually the top of the current
branch) all the back in reverse chronological order to the beginning of the
branch (typically the beginning of the repository). This works exactly as
expected for a the `main` branch.
What about when we are on a feature branch though?
Let's say we've branched off `main` and made a few commits. And now we want the
count.
```bash
$ git rev-list --count HEAD
7
```
Unfortunately, that is counting up the commits on the feature branch but it
keeps counting all the way back to the beginning of the repo.
If we want a count of just the commits on the current branch, then we can
specify a range: from whatever `main` was when we branched to the `HEAD` of
this branch.
```bash
$ git rev-list --count HEAD
3
```
This is the same as saying, I want all commits on `HEAD`, but exclude (`^`) the
commits on `main`:
```bash
git rev-list --count HEAD ^main
3
```
See `man git-rev-list` for more details.

View File

@@ -1,39 +0,0 @@
# Determine Absolute Path Of Top-Level Project Directory
The `git rev-parse` command is a git plumbing command for parsing different
kinds of things in git into a canonical form that can be used in a deterministic
way by scripts. I would typically think of using it to work with branch names,
tags, and other kinds of refs.
There is a handy, sorta off-label use for it in determining the absolute path of
the root directory for the current git repository. Use the `--show-toplevel`
flag with no other arguments.
```bash
git rev-parse --show-toplevel
/Users/lastword/dev/jbranchaud/til
```
Here, I am in the local copy of [my TIL repo](https://github.com/jbranchaud/til). This command gives me the absolute
path of the top-level directory where that `.git` directory resides.
This is useful for scripts that need to orient themselves to the current
project's top-level directory regardless of what directory they are being
executed from. This is useful for things like a git hook script or monorepos
with scripts located in a specific sub-project directory.
Also worth mentioning is the `--show-superproject-working-tree` flag. In my TIL
repo, I have a private repository included as a submodule. Within that directory
`--show-toplevel` will produce the absolute path to the submodule. If I instead
want the absolute path of the _super project_ (in this case TIL), then I can use
this other flag.
```bash
git rev-parse --show-toplevel
/Users/lastword/dev/jbranchaud/til/notes
git rev-parse --show-superproject-working-tree
/Users/lastword/dev/jbranchaud/til
```
See `man git-rev-parse` for more details.

View File

@@ -1,32 +0,0 @@
# Exclude A Directory During A Command
Many of the git commands we use, such as `git add`, `git restore`, etc., target
files and paths relative to the current directory. This is typically exactly
what we want, to stage and unstage and so forth the files and directories in
front of us.
I recently ran into a situation where I needed to restore a small subset of
changes. At the same time, I had a massive number of auto-generated files
recording HTTP interactions (hundreds of files, modified on the working tree).
I wanted to run a `git restore`, but wading through all those HTTP recording
files was not feasible.
I needed to exclude those files. They all belonged to a `spec/cassettes`
directory. I could exclude them with a _pathspec_ magic signature pattern which
is used to alter and limit the paths in a git command.
A _pathspec_ magic signature is a special pattern made up of a `:` followed by
some signature declaring what the pattern means.
The `(exclude)`, `!`, and `^` magic signatures all mean the same thing —
exclude. So, we can exclude a directory from a `git restore` command like so:
```bash
$ git restore --patch -- . ':!spec/cassettes'
```
We've employed two pathspec patterns here. The first, `.`, scopes everything to
the current directory. The second, `':!spec/cassettes'` excludes everything in
the `spec/cassettes` directory.
See `man gitglossary` for more on _pathspecs_.

View File

@@ -1,26 +0,0 @@
# Files With Local Changes Cannot Be Removed
This is a nice quality-of-life feature in `git` that should help you avoid
accidentally discarding changes that won't be retrievable.
```bash
git rm .tool-versions
error: the following file has local modifications:
.tool-versions
(use --cached to keep the file, or -f to force removal)
```
My `.tool-versions` file has some local changes. I don't realize that and I go
to issue a `git rm` command on that file. Instead of quietly wiping out my
changes, `git` lets me know I'm doing something destructive (these local
changes won't be in the diff or the reflog).
I can force the removal if I know what I'm doing with the `-f` flag. Or I can
take the two step approach of calling `git restore` on that file and then `git
rm`.
The `--cached` flag is also interesting because it doesn't actually delete the
file from my file system, but it does stage the file deletion with `git`. That
means the file now shows up as one of my untracked files.
See `man git-rm` for more details.

View File

@@ -1,39 +0,0 @@
# Fix Whitespace Errors Throughout Branch Commits
Let's say we've been working on some changes to our repository on a branch.
We've made several commits. We are close to putting up a PR, but we want to
make sure everything is tidied up.
We run a check and see that there are some whitespace errors that should be
fixed.
```bash
$ git diff main --check
README.md:1: trailing whitespace.
+# git-playground
script.sh:9: trailing whitespace.
+
```
This post isn't able to show the highlighted whitespace errors, but we can see
the warnings above.
Rather than cluttering things with an additional commit that fixes these errors
or manually cleaning up each commit, we can ask `git` to fix it for us.
```bash
$ git rebase --whitespace=fix main
```
That will do a manual rebase of each commit addressing the whitespace errors.
We can run the error check again and see no output, which means we are good to
go.
```bash
$ git diff main --check
```
See the section on `--whitespace` in `man git-apply` for more details.
[source](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration)

View File

@@ -1,30 +0,0 @@
# Highlight Extra Whitespace In Diff Output
When running a `git diff` (or `git add --patch`) I'll sometimes come across
lines that don't have any visible changes. This is usually because some
whitespace characters were either added (on accident) or removed (often by a
autoformatter).
Depending on the `core.whitespace` config, you'll probably see at least some of
the whitespace errors that git provides. By default, git only highlights
whitespace errors on added (`new`) lines. However if some extra whitespace was
originally committed and is now being removed, it won't be highlighted on the
`old` line in the diff.
We can have git always highlight whitespace errors by setting
`wsErrorHighlight` to `all` in the global git config.
```bash
$ git config --global diff.wsErrorHighlight all
```
Which updates the global gitconfig file with the following line:
```
[diff]
wsErrorHighlight = all
```
The `all` option is a shorthand for `old,new,context`.
See `man git-diff` for more details.

View File

@@ -1,44 +0,0 @@
# Highlight Small Change On Single Line
Sometimes a change gets made on a single, long line of text in a Git tracked
file. If it is a small, subtle change, then it can be hard to pick out when
looking at the diff. A standard diff will show a green line of text stacked on
a red line of text with no more granular information.
There are two ways we can improve the diff output in these situations.
The first is built-in to git. It is the `--word-diff` flag which will visually
isolate the portions of the line that have changed.
```bash
git diff --word-diff README.md
```
Which will produce something like this:
```diff
A collection of concise write-ups on small things I learn [-day to day-]{+day-to-day+} across a
```
The outgoing part is wrapped in `[-...-]` and the incoming part is wrapped in
`{+...+}`.
The second (and my preference) is to use
[`delta`](https://github.com/dandavison/delta) as an external differ and pager
for git.
```bash
git -c core.pager=delta diff README.md
```
I cannot visually demonstrate the difference in a standard code block. So I'll
describe it. We see a red and green line stacked on each other, but with muted
background colors. Then the specific characters that are different stand out
because they are highlighted with brighter red and green. I [posted a visual
here](https://bsky.app/profile/jbranchaud.bsky.social/post/3ln245orlxs2j).
`delta` can also be added as a standard part of your config like I demonstrate
in [Better Diffs With Delta](git/better-diffs-with-delta.md).
h/t to [Dillon Hafer's post on
`--word-diff`](https://til.hashrocket.com/posts/t994rwt3fg-finds-diffs-in-long-line)

View File

@@ -1,49 +0,0 @@
# List All Files Added During Span Of Time
I wanted to get an idea of all the TIL posts I wrote during 2024. Every TIL I
write is under version control in a [git repo on
github](https://github.com/jbranchaud/til). That means git has all the info I
need to figure that out.
The `git diff` command is a good way at this problem. With the
`--diff-filter=A` flag I can restrict the results to just files that were
_Added_. And with `--name-only` I can cut all the other diff details out and
get just filenames.
But filenames added to which commits? We need to specify a ref range. There is
a ton of flexibility in how you define a ref, including [a date specification
suffix](https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-emltrefnamegtltdategtemegemmasteryesterdayememHEAD5minutesagoem)
that points to the value of the ref at an earlier point in time.
So, how about from the beginning of 2024 to the beginning of 2025:
```
HEAD@{2024-01-01}..HEAD@{2025-01-01}
```
Putting that all together, we this command and potentially a big list of files.
```bash
$ git diff --diff-filter=A --name-only HEAD@{2024-01-01}..HEAD@{2025-01-01}
```
I wanted to restrict the results to just markdown files, so I added a filename
pattern.
```bash
$ git diff --diff-filter=A --name-only HEAD@{2024-01-01}..HEAD@{2025-01-01} -- "*.md"
```
I could even go a step further to see only the files added to a specific
directory.
```bash
$ git diff --diff-filter=A --name-only HEAD@{2024-01-01}..HEAD@{2025-01-01} -- "postgres/*.md"
```
As a final bonus, I can spit out the github URLs for all those files with a bit of `awk`.
```bash
$ git diff --diff-filter=A --name-only HEAD@{2024-01-01}..HEAD@{2025-01-01} -- "postgres/*.md" |
awk '{print "https://github.com/jbranchaud/til/blob/master/" $0}'
```

View File

@@ -1,28 +0,0 @@
# List All Git Aliases From gitconfig
Running the `git config --list` command will show all of the configuration
settings you have for `git` relative to your current location. Though most of
these setting probably live in `~/.gitconfig`, you may also have some locally
specified ones in `.git/config`. This will grab them all including any `alias`
entries.
We can narrow things down to just `alias` entries using the `--get-regexp` flag.
```bash
$ git config --get-regexp '^alias\.'
alias.ap add --patch
alias.authors shortlog -s -n -e
alias.co checkout
alias.st status
alias.put push origin HEAD
alias.fixup commit --fixup
alias.squash commit --squash
alias.doff reset HEAD^
alias.add-untracked !git status --porcelain | awk '/\?\?/{ print $2 }' | xargs git add
alias.reset-authors commit --amend --reset-author -CHEAD
```
I use `git doff` all the time on feature branches to "pop" the latest commmit
onto the working copy. I was trying to remember exactly what the `git doff`
command is and this was an easy way to check.

View File

@@ -1,34 +0,0 @@
# 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 chunks 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

@@ -1,20 +0,0 @@
# Restore File From One Branch To The Current
On one feature branch I have created some files and made changes to some
existing files as part of spiking a feature. Now I'm on a different branch
taking another shot at it. I want changes from one or two of the files. In the
past I've used `git-checkout` for this task. However, I believe this is one of
the use cases they had in mind when they added `git-restore`.
What I want to do is _restore_ the state of a file as it appears on some source
branch to my current branch. Here is what that looks like:
```bash
$ git restore --source=some-feature-branch app/models/contact.rb
```
Now when I check `git status` I'll see the state of that file on the
`some-feature-branch` branch overlayed on my current working copy. If the file
doesn't exist, it will be created.
See `man git-restore` for more details.

View File

@@ -1,56 +0,0 @@
# Set Up GPG Signing Key
I wanted to have that "Verified" icon start showing up next to my commits in
GitHub. To do that, I need to generate a GPG key, configure the secret key in
GitHub, and then configure the public signing key with my git config.
```bash
# generate a gpg key
$ gpg --full-generate-key
# Pick the following options when prompted
# - Choose "RSA and RSA" (Options 1)
# - Max out key size at 4096
# - Choose expiration date (e.g. 0 for no expiration)
# - Enter "Real name" and "Email"
(I matched those to what is in my global git config)
# - Set passphrase (I had 1password generate a 4-word passphrase)
```
It may take a few seconds to create.
I can see it was created by listing my GPG keys.
```bash
$ gpg --list-secret-keys --keyid-format=long
[keyboxd]
---------
sec rsa4096/1A8656918A8D016B 2025-10-19 [SC]
...
```
I'll need the `1A8656918A8D016B` portion of that response for the next command
and it is what I set as my public signing key in my git config.
First, though, I add the full key block to my GitHub profile which I can copy
like so:
```bash
$ gpg --armor --export 1A8656918A8D016B | pbcopy
```
And then I paste that as a new GPG Key on GitHub under _Settings_ -> _SSH and
GPG Keys_.
Last, I update my global git config with the signing key and the preference to
sign commits:
```bash
git config --global user.signingkey 1A8656918A8D016B
git config --global commit.gpgsign true
```
Without `commit.gpgsign`, I would have to specify the `-S` flag every time I
want to create a signed commit.
[source](https://git-scm.com/book/ms/v2/Git-Tools-Signing-Your-Work)

View File

@@ -1,26 +0,0 @@
# Show Summary Stats For Current Branch
When I push a branch up to GitHub as a PR, there is a part of the UI that shows
you how many lines you've added and removed for this branch. It bases that off
the target branch which is typically your `main` branch.
The `git diff` command can provide those same stats right in the terminal. The
key is to specify the `--shortstat` flag which tells `git` to exclude other diff
output and only show:
- Number of files changed
- Number of insertions
- Number of deletions
Here is the summary stats for a branch I'm working on:
```bash
git diff --shortstat main
8 files changed, 773 insertions(+), 25 deletions(-)
```
We have to be on our feature branch and then we point to the branch (or whatever
ref) we want to diff against. Since I want to know how my feature branch
compares to `main`, I specify that.
See `man git-diff` for more details.

View File

@@ -1,33 +0,0 @@
# Skip Git Hooks As Needed
Projects have Git hooks configured for all sorts of reasons. Most common are
`pre-commit` hooks which verify certain aspects of the contents of a commit.
A `pre-commit` hook could check that the tests all pass, that the changes don't
include any debugging statements, and so forth. There are all kinds of hooks
though, like `pre-rebase` and `post-checkout`.
These hooks can sometimes get in the way and we may need to skip or disable them
on a one-off basis.
Several Git commands offer a `--no-verify` flag which can skip running the hook
associated with that command.
- `git commit --no-verify` (skips `pre-commit` and `commit-msg` hooks)
- `git push --no-verify` (skips `pre-push` hook)
- `git merge --no-verify` (skips `pre-merge-commit` hook)
- `git am --no-verify` (skips `applypatch-msg` and `pre-applypatch` hooks)
If you look in the `.git/hooks` directory, there are several other hooks not
covered by the above. So, what if I am doing an action like `git checkout` and I
want to skip the `post-checkout` hook?
I can override the `hooksPath` config for that one command with the `-c` flag.
```sh
$ git -c core.hooksPath=/dev/null checkout ...
```
By setting it to `/dev/null`, it will find *no* hooks available, so none will be
executed for this command.
See `man git-config` for more details on `core.hooksPath`.

View File

@@ -1,23 +0,0 @@
# Use External Diff Tool Like Difftastic
Assuming we already have a tool like `difft`
([difftastic](https://difftastic.wilfred.me.uk/introduction.html)) available on
our machine, we can use it as a diff viewer for the various `git` commands that
display a diff.
This requires a manual override which involve two pieces — an inline
configuration of `diff.external` specifying the binary of the external differ
and the `--ext-diff` flag which tells these commands to use the external diff
binary.
Here is what `git show` looks like with `difft`:
```bash
$ git -c diff.external=difft show --ext-diff
```
Without the `--ext-diff` flag, it will fallback to the default differ despite
`diff.external` being set.
See `man git-diff` and friends for the `--ext-diff` flag. See `man git-config`
for `diff.external`.

View File

@@ -1,41 +0,0 @@
# 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

@@ -1,25 +0,0 @@
# Access Your GitHub Profile Photo
Let's say I have my [GitHub profile](https://github.com/jbranchaud) pulled up in
the browser.
```
https://github.com/jbranchaud
```
If I then add `.png` to the end of that in the URL bar:
```
https://github.com/jbranchaud.png
```
I'll be redirected to the URL where the full image file lives. In my case:
```
https://avatars.githubusercontent.com/u/694063?v=4
```
You can pull up yours `https://github.com/<username>.png` to access your profile
image.
[source](https://dev.to/10xlearner/how-to-get-the-profile-picture-of-a-github-account-1d82)

View File

@@ -1,19 +0,0 @@
# Open A PR To An Unforked Repo
Sometimes I will clone a repo to explore the source code or to look into a
potential bug. If my curiosity takes me far enough to make some changes, then I
jump through the hoops of creating a fork, reconfiguring branches, pushing to my
fork, and then opening the branch as a PR against the original repo.
The `gh` CLI allows me to avoid all that hoop-jumping. Directly from the cloned
repo I can use `gh` to create a new PR. It will prompt me to creat a fork. If I
accept, it will seamlessly create it and then open a PR from my fork to the
original.
```bash
$ gh pr create
```
This allows me to create the PR with a few prompts from the CLI. If you prefer,
you can include the `--web` flag to open the PR creation screen directly in the
browser.

View File

@@ -1,20 +0,0 @@
# Target Another Repo When Creating A PR
I have a [`dotfiles` repo](https://github.com/jbranchaud/dotfiles) that I forked
from [`dkarter/dotfiles`](https://github.com/dkarter/dotfiles). I'm adding a
bunch of my own customizations on a `main` branch while continually pulling in
and merging upstream changes.
The primary remote according to `gh` is `jbranchaud/dotfiles`. 98% of the time
that is what I want. However, I occasionally want to share some changes upstream
via a PR. Running `gh pr create` as is will create a PR against my fork. To
override this on a one-off basis, I can use the `--repo` flag.
```bash
$ gh pr create --repo dkarter/dotfiles
```
This will create a PR against `dkarter:master` from my branch (e.g.
[`jbranchaud:jb/fix-hardcoded-paths`](https://github.com/dkarter/dotfiles/pull/373)).
See `man gh-pr-create` for more details.

View File

@@ -1,38 +0,0 @@
# Tell gh What The Default Repo Is
I recently forked [dkarter/dotfiles](https://github.com/dkarter/dotfiles) as a
way of bootstrapping a robust dotfile config for a new machine that I could
start making customizations to. I'm maintaining a `my-dotfiles` branch and keep
things in sync with the original upstream repo.
When trying to go to *my* fork of the repo
([jbranchaud/dotfiles](https://github.com/jbranchaud/dotfiles)) in the web with
the `gh` CLI tool, I ran into a weird issue. It was instead opening up to
`dkarter/dotfiles`.
`gh` was under the wrong impression which repo should be considered the default.
To clarify things for `gh`, there is a command to set the default repo.
```bash
$ gh repo set-default jbranchaud/dotfiles
✓ Set jbranchaud/dotfiles as the default repository for the current directory
```
Now when I run `gh repo view --web`, it opens the browser to my fork of the
dotfiles.
But where does this setting live?
Opening this repo's `.git/config` file I can see a section for the `origin`
remote that includes a new line for `gh-resolved`. This being set to `base`
tells `gh` that this remote is the one to treat as the default repo.
```
[remote "origin"]
url = git@github.com:jbranchaud/dotfiles.git
fetch = +refs/heads/*:refs/remotes/origin/*
gh-resolved = base
```
See `gh repo set-default --help` for more details.

View File

@@ -1,70 +0,0 @@
# Add A Method To A Struct
Given a `struct` in Go, we can attach a method to that struct. Put another way,
we can define a method whose receiver is that struct. Then with an instance of
that struct, we can call the method.
Let's say we are modeling a turtle that can move around a 2D grid. A turtle has
a heading (the direction it is headed) and a location (its current X,Y
coordinate).
```go
type Heading string
const (
UP Heading = "UP"
RIGHT Heading = "RIGHT"
DOWN Heading = "DOWN"
LEFT Heading = "LEFT"
)
type Turtle struct {
Direction Heading
X int
Y int
}
```
We can then add a method like so by specifying the receiver as the first part
of the declaration:
```go
func (turtle *Turtle) TurnRight() {
switch turtle.Direction {
case UP:
turtle.Direction = RIGHT
case RIGHT:
turtle.Direction = DOWN
case DOWN:
turtle.Direction = LEFT
case LEFT:
turtle.Direction = UP
}
}
```
The receiver is a pointer to a `Turtle`. The method is called `TurnRight`.
There are no parameters or return values.
Here are a sequence of calls to demonstrate how it works:
```go
func main() {
turtle := Turtle{UP, 5, 5}
fmt.Println("Turtle Direction:", turtle.Direction)
//=> Turtle Direction: UP
turtle.TurnRight()
fmt.Println("Turtle Direction:", turtle.Direction)
//=> Turtle Direction: RIGHT
turtle.TurnRight()
fmt.Println("Turtle Direction:", turtle.Direction)
//=> Turtle Direction: DOWN
}
```
[source](https://go.dev/tour/methods/1)

View File

@@ -1,63 +0,0 @@
# Basic Delve Debugging Session
When using [delve](https://github.com/go-delve/delve) to debug a Go program,
these are the series of things I usually find myself doing.
First, I start running the program with `dlv` including any arguments after a `--` (in my case, the `solve` subcommand and a filename).
```bash
$ dlv debug . -- solve samples/001.txt
```
`dlv` starts up and is ready to run my program from the beginning. I'll need to
set a couple breakpoints before continuing. I do this with the `break` command,
specifying the filename and line number.
```
(dlv) break main.go:528
Breakpoint 1 set at 0x10c1a5bea for main.traversePuzzleIterative() ./main.go:528
(dlv) break main.go:599
Breakpoint 2 set at 0x10c1a6dcc for main.traversePuzzleIterative() ./main.go:599
```
Now I can continue which will run the program until hitting a breakpoint.
```
(dlv) continue
> [Breakpoint 2] main.traversePuzzleIterative() ./main.go:599 (hits goroutine(1):1 total:1) (PC: 0x10c1a6dcc)
594: }
595: }
596:
597: topStackFrame := stack[len(stack)-1]
598: // if the current stack frame has more values, try the next
=> 599: if len(topStackFrame.PossibleValues) > 0 {
600: nextValue := topStackFrame.PossibleValues[0]
601: topStackFrame.PossibleValues = topStackFrame.PossibleValues[1:]
602: topStackFrame.CurrValue = nextValue
603:
604: // Undo the last placement and make a new one
```
I can see the context around the line we've stopped on. From here I can dig
into the current state of the program by looking at local variables (`locals`)
or printing out a specific value (`print someVar`). I can continue to step
through the program line by line with `next` or eventually run `continue` to
proceed to the next breakpoint.
```
(dlv) locals
diagnostics = main.Diagnostics {BacktrackCount: 0, NodeVisitCount: 1, ValidityCheckCount: 2,...+2 more}
stack = []main.StackData len: 1, cap: 1, [...]
emptyCellPositions = [][]int len: 3, cap: 4, [...]
emptyCellIndex = 1
status = "Invalid"
topStackFrame = main.StackData {RowIndex: 1, ColumnIndex: 7, PossibleValues: []int len: 8, cap: 8, [...],...+1 more}
(dlv) print topStackFrame
main.StackData {
RowIndex: 1,
ColumnIndex: 7,
PossibleValues: []int len: 8, cap: 8, [2,3,4,5,6,7,8,9],
CurrValue: 1,}
(dlv) next
> main.traversePuzzleIterative() ./main.go:600 (PC: 0x10c1a6dea)
```

View File

@@ -1,41 +0,0 @@
# Check If Cobra Flag Was Set
When using [Cobra](https://github.com/spf13/cobra) to define a CLI, we can
specify a flag for a command like so:
```go
var Seed int64
myCmd.PersistentFlags().Int64VarP(&Seed, "seed", "", -1, "set a seed")
```
This `--seed` flag has a _default_ of `-1`. If the flag isn't specified, then
when we access that flag's value, we'll get `-1`.
But how do we differentiate between the _default_ `-1` and someone passing `-1`
to the `--seed` flag when running the program?
In the command definition, we can look at the flags and see, by name, if
specific ones were changed by user input rather than being the defaults.
```go
myCommand := &cobra.Command{
// coommand setup ...
Run: func(cmd *cobra.Command, args []string) {
if cmd.Flags().Changed("seed") {
seed, err := cmd.Flags().GetInt64("seed")
if err != nil {
fmt.Println("Seed flag is missing from `cmdFlags()`")
os.Exit(1)
}
fmt.Printf("Seed was set to %d\n", seed)
} else {
fmt.Println("Seed was not set")
}
}
}
```
If we don't want to rely on the default and instead want to specify some other
behavior when the flag is not manually set by the user, we can detect that
scenario like this.

View File

@@ -1,29 +0,0 @@
# Configure Max String Print Length For Delve
During a [Delve](https://github.com/go-delve/delve) debugging session, we can
print out the value of a given variable with the `print` command. Similarly, we
can see the values of all local variables with the `locals` command.
Whenever Delve is printing out strings and slices, it will truncate what it
displays to 64 characters (or items) by default.
```go
(dlv) print diagnostics.Solutions[0]
"295743861\n431865972\n876192543\n387459216\n612387495\n549216738\n7635...+25 more"
```
This can be overridden by [changing the `config` of
`max-string-len`](https://github.com/derekparker/delve/blob/237c5026f40e38d2dd6f62a7362de7b25b00c1c7/Documentation/cli/expr.md?plain=1#L59)
to something longer. In my case here, all I need are about 90 characters to
display my full string, so run `config max-string-len 90` from the `dlv`
session.
```go
(dlv) config max-string-len 90
(dlv) print diagnostics.Solutions[0]
"295743861\n431865972\n876192543\n387459216\n612387495\n549216738\n763524189\n928671354\n154938627"
```
Now I can see the entire string instead of the truncated version.
[source](https://stackoverflow.com/a/52416264/535590)

View File

@@ -1,50 +0,0 @@
# Connect To A SQLite Database
Using the `database/sql` module and the `github.com/mattn/go-sqlite3` package,
we can connect to a SQLite database and run some queries. In my case, I have a
SQLite connection string exported to my environment, so I can access that with
`os.Getenv`. It's a local SQLite file, `./test.db`.
Calling `sql.Open`, I'm able to connect with a SQLite3 driver to the database
at that connection string. The `setupDatabase` function returns that database
connection pointer. Things like `Exec` and `QueryRow` can be called on `db`. I
also need to make sure I close the connection to the database with a `defer`.
Here is a full example of connecting to a local SQLite database and inserting a
record:
```go
package main
import (
"database/sql"
"fmt"
"os"
_ "github.com/mattn/go-sqlite3"
)
func setupDatabase() *sql.DB {
databaseString := os.Getenv("GOOSE_DBSTRING")
if len(databaseString) == 0 {
fmt.Println("Error retrieving `GOOSE_DBSTRING` from env")
os.Exit(1)
}
db, err := sql.Open("sqlite3", databaseString)
if err != nil {
fmt.Printf("Error opening database: %v\n", err)
os.Exit(1)
}
return db
}
func main() {
db := setupDatabase()
defer db.Close()
sql := `insert into users (name) values (?);`
db.Exec(sql, "Josh")
}
```

View File

@@ -1,44 +0,0 @@
# Create A Slice From An Array
Slices in Go are a flexible abstraction over arrays. We can create a slice from
an array with the `[n:m]` _slicing_ syntax. We specify the left and right
(exclusive) bounds of the array that we want to create the slice relative to.
We can exclude the lower bound which translates to the `0` index of the array.
We can exclude the left bound which translates to the end of the array. We can
even exclude both ends of the _slicing_ syntax which means creating a slice of
the entire array.
Here is an example of each of those:
```go
package main
import "fmt"
func main() {
arr := [...]string{
"taco",
"burrito",
"torta",
"enchilada",
"quesadilla",
"pozole",
}
firstTwo := arr[:2]
lastTwo := arr[len(arr)-2:]
all := arr[:]
fmt.Println("First two:", firstTwo)
// First two: [taco burrito]
fmt.Println("Last two:", lastTwo)
// Last two: [quesadilla pozole]
fmt.Println("All:", all)
// All: [taco burrito torta enchilada quesadilla pozole
}
```
[source](https://go.dev/blog/slices-intro#slices)

View File

@@ -1,59 +0,0 @@
# Detect If Stdin Comes From A Redirect
Reading lines of input from `stdin` is flexible. And we may need our program to
behave differently depending on where that input is coming from. For instance,
if data is redirected or piped to our program, we scan and process it directly.
Otherwise, we need to prompt the user to enter in specific info and go from
there.
We can detect whether [`os.Stdin`](https://pkg.go.dev/os#pkg-variables) is
being piped to, redirected to, or whether we should prompt the user by looking
at the file mode descriptor of
[`os.Stdin.Stat()`](https://pkg.go.dev/os#File.Stat).
```go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Stdin.Stat()
if err != nil {
fmt.Printf("Error checking stdin: %v\n", err)
os.Exit(1)
}
fromTerminal := (file.Mode() & os.ModeCharDevice) != 0
fromAPipe := (file.Mode() & os.ModeNamedPipe) != 0
if fromTerminal {
fmt.Println("This is Char Device mode, let's prompt user for input")
termScanner := bufio.NewScanner(os.Stdin)
for termScanner.Scan() {
fmt.Printf("- %s\n", termScanner.Text())
break;
}
} else if fromAPipe {
fmt.Println("This is Named Pipe mode, contents piped in")
pipeScanner := bufio.NewScanner(os.Stdin)
for pipeScanner.Scan() {
fmt.Printf("- %s\n", pipeScanner.Text())
}
} else {
fmt.Println("This means the input was redirected")
redirectScanner := bufio.NewScanner(os.Stdin)
for redirectScanner.Scan() {
fmt.Printf("- %s\n", redirectScanner.Text())
}
}
}
```
If `os.ModeCharDevice` then we are connected to a character device, like the
terminal. We can see if input is being piped in by checking against
`os.ModeNamedPipe`. Otherwise, there are a variety of file modes and I'm
willing to assume we're dealing with a regular file redirect at that point.

View File

@@ -1,49 +0,0 @@
# Deterministically Seed A Random Number Generator
If you need a random number in Go, you can always reach for the various
functions in the `rand` package.
```go
package main
import (
"fmt"
"math/rand"
)
func main() {
for range 5 {
roll := rand.Intn(6) + 1
fmt.Printf("- %d\n", roll)
}
}
```
Each time I run that, I get a random set of values. Often in programming, we
want some control over the randomness. We want to _seed_ the randomness so that
it is deterministic. We want random, but the kind of random where we know how
we got there.
```go
package main
import (
"fmt"
"math/rand"
)
func main() {
seed := int64(123)
src := rand.NewSource(seed)
rng := rand.New(src)
for range 5 {
roll := rng.Intn(6) + 1
fmt.Printf("- %d\n", roll)
}
}
```
In this second snippet, we create a `Source` with a specific seed value that we
can use with a custom `Rand` struct. We can then deterministically get random
numbers from it.

View File

@@ -1,55 +0,0 @@
# Difference Between Slice And Pointer To Slice
Though a slice can be thought of and used as a flexible, variable-length
array-like data structure, it is important to understand that it is also a
special kind of pointer to an underlying array.
This matters when we a function receives a slice versus a pointer to a slice as
an argument, depending on what it is doing with that slice.
If the function is access or updating elements in the slice, there is no
difference. There is no meaningful difference between these two functions and
we might as well use the former.
```go
func replaceAtIndex(slice []string, index int, value string) {
slice[index] = value
}
func replaceAtIndexPtr(slice *[]string, index int, value string) {
(*slice)[index] = value
}
```
On the other hand, if the receiving function needs to append to or replace the
slice, then we need to pass a pointer to the slice. A direct slice argument
will result in only the function-local copy getting replaced.
```go
package main
import (
"fmt"
)
func main() {
s1 := []int{8, 6, 7, 9}
s2 := []int{8, 6, 7, 9}
addItem(s1, 11)
fmt.Printf("s1: %v\n", s1) //=> s1: [8 6 7 9]
addItemPtr(&s2, 11)
fmt.Printf("s2: %v\n", s2) //=> s2: [8 6 7 9 11]
}
func addItem(slice []int, value int) {
slice = append(slice, value)
}
func addItemPtr(slice *[]int, value int) {
(*slice) = append(*slice, value)
}
```
[source](https://go.dev/tour/moretypes/8)

View File

@@ -1,51 +0,0 @@
# Format Date And Time With Time Constants
The Go [`time` package](https://pkg.go.dev/time) has a [`Format`
function](https://pkg.go.dev/time#Time.Format) for displaying the parts of a
date and time in standard and custom ways. It works a bit different than you
might be used to from other languages. Rather than using `strftime` identifiers
like in this string `"%B %d, %Y"`, there is a canonical date that is used as a
reference point.
That canonical date is from Janary 2nd, 2006. That was a Monday. It was at 5
seconds after 3:04PM. The Unix format of it looks like `"Mon Jan _2 15:04:05
MST 2006"`.
```
package main
import (
"fmt"
"time"
)
func main() {
// This specific time pulled from `time.Format` docs
t, _ := time.Parse(time.UnixDate, "Wed Feb 25 11:06:39 PST 2015")
// Reference date and time:
// "Mon Jan _2 15:04:05 MST 2006"
strf1 := t.Format("|2006|02|01|03:04:05|Day: Mon|")
fmt.Println("strf1:", strf1)
// strf1: |2015|25|02|11:06:39|Day: Wed|
strf2 := t.Format(time.DateTime)
strf3 := t.Format(time.RubyDate)
strf4 := t.Format(time.Kitchen)
fmt.Println("DateTime:", strf2) // DateTime: 2015-02-25 11:06:39
fmt.Println("RubyDate:", strf3) // RubyDate: Wed Feb 25 11:06:39 +0000 2015
fmt.Println("Kitchen:", strf4) // Kitchen: 11:06AM
}
```
Though there are a [variety of useful formatting
constants](https://pkg.go.dev/time#pkg-constants) already available like
`DateTime`, `RubyDate`, `Kitchen`, etc., we can also define our own formatting
string by using the reference values for each part of a date and time.
If you want to reference the year, whether as `YYYY` or `YY`, it is always
going to be a form of `2006`, so `2006` or `06` respectively. Even though the
above time variable is in February, our format strings will always need to use
one of `Jan`, `January`, `01` or `1`.

View File

@@ -1,65 +0,0 @@
# Pass A Struct To A Function
Go operates as _pass-by-value_ which means that when we pass a struct to a
function, the receiving function gets a copy of the struct. Two things worth
noticing about that are 1) an extra memory allocation happens when calling the
function and 2) altering the struct does not affect the original in the calling
context.
On the other hand, we can have a function that takes a pointer to a struct.
When we call that function, we have a reference to the memory location of the
struct instead of a copy of the struct. That means no additional allocation and
modifications to the dereferenced struct are modifications to the original in
the calling context.
Here is an example that demonstrates both of these. Notice the printed output
that is included in comments at the end which shows memory locations and
contents of the struct at various points.
```go
package main
import "fmt"
type Order struct {
Item string
Quantity int
DineIn bool
}
func main() {
order := Order{Item: "taco", Quantity: 3, DineIn: true}
fmt.Println("Order:", order)
fmt.Printf("main - Loc: %p\n", &order)
doubledOrder := doubleOrder(order)
fmt.Println("Double Order:", doubledOrder)
fmt.Println("Original Order:", order)
doubleOrderPtr(&order)
fmt.Println("Double Order Ptr:", order)
}
func doubleOrder(order Order) Order {
fmt.Printf("doubleOrder - Loc: %p\n", &order)
order.Quantity *= 2
return order
}
func doubleOrderPtr(order *Order) {
fmt.Printf("doubleOrderPtr - Loc: %p\n", order)
(*order).Quantity *= 2
}
// Order: {taco 3 true}
// main - Loc: 0xc0000b4000
// doubleOrder - Loc: 0xc0000b4040
// Double Order: {taco 6 true}
// Original Order: {taco 3 true}
// doubleOrderPtr - Loc: 0xc0000b4000
// Double Order Ptr: {taco 6 true}
```

View File

@@ -1,32 +0,0 @@
# Produce The Zero Value For A Generic Type
While writing a _pop_ function that would work with slices of a generic type, I
ran into the issue of needing to produce a zero value of type `T` when
returning early for an empty slice.
The way to arbitrarily get the zero value of a generic in Go is with `*new(T)`.
I was able to use this in my `Pop` function like so:
```go
func Pop[T any](slice []T) (T, error) {
if len(slice) == 0 {
return *new(T), fmt.Errorf("cannot pop an empty slice")
}
lastItem := slice[len(slice)-1]
slice = slice[:len(slice)-1]
return lastItem, nil
}
```
If this is happening in multiple functions and we want a more self-documenting
approach, we can pull it out into a function `zero`:
```go
func zero[T any]() T {
return *new(T)
}
```

View File

@@ -1,39 +0,0 @@
# Redirect File To Stdin During Delve Debug
I have a go program that accepts input from stdin. The way I've been running
the program as I develop it is to redirect the output of some sample files to
the program.
```bash
$ go run . < sample/001.txt
```
When I then go to debug this program with
[Delve](https://github.com/go-delve/delve), I'd still like to be able to
redirect a file into the program to reproduce the exact behavior I'm seeing.
The following won't work:
```bash
$ dlv debug . < samples/001.txt
Stdin is not a terminal, use '-r' to specify redirects for the target process or --allow-non-terminal-interactive=true if you really want to specify a redirect for Delve
```
Fortunately, `dlv` sees what I'm trying to do and makes a recommendation. The
`-r` flag can be used to specify redirects for the target process. The [`dlv`
redirect
docs](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_redirect.md)
explain that `-r` can be passed a `source:destination`. The `source` is `stdin`
by default, but can also be `stdout` and `stderr`.
I can redirect my file into the debugging session of my program like so:
```bash
$ dlv debug . -r stdin:samples/001.txt
```
Or even more succinctly:
```bash
$ dlv debug . -r samples/001.txt
```

View File

@@ -1,52 +0,0 @@
# Sort Slice In Ascending Or Descending Order
The [`slices.Sort`](https://pkg.go.dev/slices#Sort) function defaults to
sorting a slice in ascending order. If we want to control the sort order, we
have to do a little more work. We can reach for the
[`slices.SortFunc`](https://pkg.go.dev/slices#SortFunc) function. This allows
us to define a sort function and in that function we can control whether the
sort order is ascending or descending.
Here I've defined `SortItems` which takes a list of items constrained by the
[`cmp.Ordered`](https://pkg.go.dev/cmp#Ordered) interface (so things like
`int`, `string`, `uint64`, etc.). It takes a direction (`ASC` or `DESC`) as a
second argument. It does the directional sort based on that second argument.
```go
import (
"cmp"
"fmt"
"slices"
)
type Direction int
const (
ASC Direction = iota
DESC
)
func SortItems[T cmp.Ordered](items []T, dir Direction) {
slices.SortFunc(items, func(i, j T) int {
if dir == ASC {
return cmp.Compare(i, j)
} else if dir == DESC {
return cmp.Compare(j, i)
} else {
panic(fmt.Sprintf("Unrecognized sort direction: %d", dir))
}
})
}
// items := []int{3,2,8,1}
// SortItems(items, ASC)
// // items => [1,2,3,8]
// SortItems(items, DESC)
// // items => [8,3,2,1]
```
Because `slices.SortFunc` expects a negative value, zero, or positive value to
determine the sort order, we use
[`cmp.Compare`](https://pkg.go.dev/cmp#Compare) which returns those kinds of
values. For ascending, we compare `i` to `j`. For descending, we swap them,
comparing `j` to `i` to get the reverse sort order.

View File

@@ -1,58 +0,0 @@
# Write A Custom Scan Function For File IO
By default a [`bufio.Scanner`](https://pkg.go.dev/bufio#Scanner) will scan
input line-by-line. In other words, splitting on newlines such that each
iteration will emit everything up to the next newline character.
We can write our own `SplitFunc` and override the default one by calling
`scanner.Split` with it. Our custom scan function needs to match the type
signature of [`SplitFunc`](https://pkg.go.dev/bufio#SplitFunc).
Here is a custom one that emits each individual character but omits the
newlines.
```go
func ScanChar(data []byte, atEOF bool) (int, []byte, error) {
if atEOF || len(data) == 0 {
return 0, nil, nil
}
start := 0
for start < len(data) {
if !utf8.FullRune(data[start:]) {
return 0, nil, nil
}
r, size := utf8.DecodeRune(data[start:])
if r == utf8.RuneError {
return 0, nil, fmt.Errorf("invalid UTF-8 encoding")
}
if r != '\n' {
return start + size, data[start:start+size], nil
}
// found a \n, advance the start position
start += size
}
return start, nil, nil
}
```
We can then use thi `ScanChar` function with a `bufio.Scanner` like so:
```go
func ReadFileByCharacter(file io.Reader) {
scanner := bufio.NewScanner(file)
// override default SplitFunc
scanner.Split(scanChar)
for scanner.Scan() {
char := scanner.Text()
fmt.Printf("- %s\n", char)
}
}
```

View File

@@ -1,32 +0,0 @@
# Check Ruby Version For Production App
While deploying a fresh Rails app to Heroku recently, I ran into an issue. The
`it` block argument wasn't working despite being on Ruby 4.0. Or so I thought.
Running the following command reported the Ruby version of that Heroku server
instance:
```bash
heroku run -- ruby --version
Running ruby --version on ⬢ my-app... up, run.3090
ruby 3.3.9 (2025-07-24 revision f5c772fc7c) [x86_64-linux]
```
I was on `3.3.9` which must have been the fallback default at the time.
Though I had set the Ruby version in my `.ruby-version` file, I had neglected to
specify it in the `Gemfile` as well. Once I added it to the `Gemfile` and
redeployed, my Heroku server instance was running the expected version of Ruby.
```bash
heroku run -- ruby --version
Running ruby --version on ⬢ my-app... up, run.5353
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
```
Note: because [I have set `HEROKU_ORGANIZATION` and
`HEROKU_APP`](set-default-team-and-app-for-project.md) in my environment
(`.envrc`) for the local copy of the app, I don't need to specify those when
running the `heroku run` command above.
See `heroku run --help` for more details.

View File

@@ -1,34 +0,0 @@
# Specify Default Team And App For Project
Typically when you run commands with the Heroku CLI you'll need to specify the
name of the app on Heroku you're targeting with the `--app` flag. However, to
first see the names of the apps you may want to run `heroku apps` (or `heroku
list`). That will list the apps for your default team.
If you need to see apps for a different team (i.e. organization), you'll need to
specify that team either with the `--team` flag or by setting that as an
environment variable.
Here I do the latter in an `.envrc` file:
```
# Heroku
export HEROKU_ORGANIZATION=visualmode
```
Once that is set and the environment reloaded, running `heroku apps` will show
the apps specific to that team on Heroku.
Similarly, if you want to set a default app for your project so that you don't
have to always specify the `--app` flag, you can update your `.envrc`
accordingly.
```
# Heroku
export HEROKU_ORGANIZATION=visualmode
export HEROKU_APP=my-app
```
I had a hard time finding official documentation for this which is why I'm
writing this up here. I've manually verified this works with my own team and
app.

View File

@@ -1,39 +0,0 @@
# Allow Number Input To Accept Decimal Values
Here is a number input element:
```html
<input type="number" id="amount" required class="border" />
```
This renders an empty number input box with up and down arrows which will, by
default, increment or decrement the value by **1**.
Of course, I can manually edit the input typing in a value like `1.25`.
However, when I submit that via an HTML form, the submission will be prevented
and the browser will display a validation error.
> Please enter a valid value. The two nearest valid values are 1 and 2.
If I want to be able to input a decimal value like this, I need to change the
`step` value. It defaults to `1`, but I could change it to `2`, `10`, or in
this case to `0.01`.
```html
<input type="number" step="0.01" id="amount" required class="border" />
```
Notice now that as you click the up and down arrows, the value is incremented
and decremented by **0.01** at a time.
If I want to maintain the step value of `1` while allowing decimal values, I
can instead set the `step` value to be `any`.
```html
<input type="number" step="any" id="amount" required class="border" />
```
See the [MDN docs on number
inputs](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number)
for more details.

View File

@@ -1,28 +0,0 @@
# Disclose Additional Details
You can add extra details to an HTML page that are only disclosed if the user
chooses to disclose them. To do that, we use the `<details>` tag. This tag
needs to have a `<summary>` tag nested within it. Anything else nested within
`<details>` will be what is disclosed when it is toggled open. The `<summary>`
is what is displayed when it is not open.
Here is a `<detail>` block I recently added to [Ruby Operator
Lookup](https://www.visualmode.dev/ruby-operators).
```html
<details className="pt-2 pb-6">
<summary>What is this thing?</summary>
<p className="pl-3 pt-2 text-gray-700 text-sm">
Ruby is an expressive, versatile, and flexible dynamic programming language. That means there are all kinds of syntax features, operators, and symbols we can encounter that might look unfamiliar and are hard to look up. Ruby Operator Lookup is a directory of all these language features.
</p>
<p className="pl-3 pt-2 text-gray-700 text-sm">
Use the search bar to narrow down the results. Then click on a button for the operator or symbol you want to explore further.
</p>
</details>
```
On page load, the only thing we see is "What is this thing?" with a triangle
symbol next to it. If we click the summary, then the entire details block
(those two `<p>` tags) are disclosed.
[source](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)

View File

@@ -1,34 +0,0 @@
# Download A Google Doc As Specific Format
I was recently given a public Google Doc URL and I was curious if I could
download it from the command line. I didn't want to have to install special CLI
though. I was hoping to use something like `curl`.
A brief chat with Claude and I learned that not only can I use `curl`, but I
can specify the format in the _export_ URL.
```bash
$ export GOOGLE_DOC_URL="https://docs.google.com/document/d/157rMgHeBf76T9TZnUjtrUyyS2XPwG0tObr-OjYNfMaI"
$ echo $GOOGLE_DOC_URL
https://docs.google.com/document/d/157rMgHeBf76T9TZnUjtrUyyS2XPwG0tObr-OjYNfMaI
$ curl -L "$GOOGLE_DOC_URL/export?format=pdf" -o doc.pdf
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 414 0 414 0 0 2763 0 --:--:-- --:--:-- --:--:-- 2895
100 16588 0 16588 0 0 56214 0 --:--:-- --:--:-- --:--:-- 167k
$ ls doc.pdf
doc.pdf
```
I append `/export` and then include the `?format=pdf` query param to specify
that I want the document to be exported in PDF format. With the `-o` flag I can
specify the name and extension of the output file.
This is a handy on its own, but noticing that Google Docs supports other export
formats, I thought it would be useful to go back-and-forth with Claude to
sketch out a script that can do this and prompt me (with `fzf`) for the file
type -- [here is the gist for
`gdoc-download`](https://gist.github.com/jbranchaud/cf3d2028107a1bd8484eed7cca0fcdab).

View File

@@ -1,27 +0,0 @@
# Grab The RSS Feed For A Substack Blog
I've been attempting to put more energy into finding and reading blog posts via
an RSS feed reader. This as opposed to scrolling and scrolling and hoping that
the algorithm turns up an interesting article or two.
A lot of people who have been blogging for a while have a handy RSS feed link
prominently displayed on their site. We love to see it!
There are a few people whose writing I really enjoy that distribute their words
via Substack. I couldn't find a prominent or not prominent RSS feed link
anywhere on someone's Substack. What I did learn, after some searching, is that
you can tack `/feed` onto the end of someone's Substack URL and that will give
you the XML feed.
For example:
```
Substack blog landing page URL:
https://registerspill.thorstenball.com
Substack blog RSS feed URL:
https://registerspill.thorstenball.com/feed
```
Grab that feed URL and paste it into your feed reader and you should start
seeing their stuff show up.

View File

@@ -1,12 +0,0 @@
# Hide Overflowing Text For Google Sheets Column
I imported a big CSV into a new Google Sheets document. This included a
"Description" column with many of the descriptions varying between 50 and 80
characters. The bottom line is that the description column was flowing over the
top of the columns next to it. Instead of expanding the width of that column as
far as the largest description, I wanted to hide the _overflow_.
The way to do this in Google Sheets is to highlight the entire column by
clicking on the column grouping. Then under the _Format_ menu item is a
_Wrapping_ submenu. The _Clip_ option is what I was looking for because it clips
the text that gets shown at the edge of the column.

View File

@@ -1,42 +0,0 @@
# Format A List Of Items By Locale
The `Intl` module includes a [`ListFormat`
object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat)
which can be used to format a list of items in a consistent way across locales.
I've reinvented the wheel of writing a helper function numerous times across
projects for formatting a list of items that accounts for formatting based on
how many items there are. This built-in function handles that with the added
benefit of working across locales.
Here are lists of three, two, and one items formatted in the `long` styles for
US english.
```javascript
> const formatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
undefined
> formatter.format(['Alice', 'Bob', 'Carla'])
'Alice, Bob, and Carla'
> formatter.format(['Coffee', 'Tea'])
'Coffee and Tea'
> formatter.format(['Taco'])
'Taco'
```
The difference between `long` and `short` style for a `conjunction` is _and_
versus _&_. In addition to the type`conjunction`, you could also use
`disjunction` which will do an _or_ instead of an _and_. I'm not sure what
you'd use the `unit` type for.
You could use another locale, such as French, as well:
```javascript
> const formatter = new Intl.ListFormat('fr', { style: 'long', type: 'conjunction' });
undefined
> formatter.format(['café', 'thé'])
'café et thé'
```

View File

@@ -1,28 +0,0 @@
# Describe Current Changes And Create New Change
One of the first patterns I learned with `jj` was a pair of commands to
essentially "commit" the working copy and start a fresh, new change. So if I am
done making some changes, I can add a description to the `(no description)`
working copy and then start a new working copy _change_.
```bash
$ jj describe -m "Add status subcommand to show current status"
$ jj new
```
I learned from [Steve](https://steveklabnik.com/) in the [jj
discord](https://discord.gg/dkmfj3aGQN) that a shorthand for this pattern is to
use the `jj commit` command directly.
> When called without path arguments or `--interactive`, `jj commit` is
> equivalent to `jj describe` followed by `jj new`.
That means, instead of the above pair of commands, I could have done:
```bash
$ jj commit -m "Add status subcommand to show current status"
```
That would have had the same result in my case. However, notice the caveats
mentioned in the quote above and check out `man jj-commit` for more details on
that.

View File

@@ -1,31 +0,0 @@
# Squash Changes Into Parent Commit Interactively
While I have some changes in progress as part of the working copy, I can squash
them into the previous / parent commit with the `jj squash` command. Running
that command as is will apply all the working copy changes to the parent leaving
the current revision empty.
I can also interactively squash those changes similar in spirit to how I might
use `git add --patch` to stage and then amend specific changes into the previous
commit with `git`. This can be done with [`jj`](https://github.com/jj-vcs/jj)
using `squash` with the `-i` flag.
```bash
jj squash -i # or --interactive
```
This will open up a TUI where I can click around or use keys. Each file in the
source revision (in my case, the working copy) will be listed. I can move the
cursor between them hitting _space_ to toggle them in or out of the squash
selection.
I can also hit `f` over a given file to toggle _folding_. When folding is on, a
diff of the file will be disclosed with checkboxes for toggling individual
hunks and lines.
Once I'm satisfied with my interactive selection, I can hit `c` to confirm and
only the selected files and changes will be squashed into the parent.
See `man jj-squash` for more details.
[source](https://steveklabnik.github.io/jujutsu-tutorial/real-world-workflows/the-squash-workflow.html)

View File

@@ -1,51 +0,0 @@
# Add A Bunch Of CLI Utilities With coreutils
The [`coreutils`](https://www.gnu.org/software/coreutils/) project is a
collection of useful utilities that every operating system ought to have.
> The GNU Core Utilities are the basic file, shell and text manipulation
> utilities of the GNU operating system. These are the core utilities which are
> expected to exist on every operating system.
While many of these utilities are redundant with BSD utilities that MacOS
chooses to ship with, there are some differences in the overlapping ons and then
many additions from `coreutils`.
They can be installed with Homebrew:
```bash
$ brew install coreutils
```
And then you should have some new things available on your path. Take `shuf`, for
instance. This utility can shuffle and select items from a file or incoming
lines from another command. Here I use it to randomly grab a number between 1
and 5 (with the help of `seq`):
```bash
seq 1 5 | shuf -n 1
3
seq 1 5 | shuf -n 1
2
seq 1 5 | shuf -n 1
5
```
Or how about some utilities for manipulating file names? Among others there is
`realpath`, `basename`, and `dirname`.
```bash
realpath README.md
/Users/lastword/dev/jbranchaud/til/README.md
realpath README.md | xargs basename
README.md
realpath README.md | xargs dirname
/Users/lastword/dev/jbranchaud/til
```
See the [manual](https://www.gnu.org/software/coreutils/manual/coreutils.html)
for many more details.

View File

@@ -1,27 +0,0 @@
# Capture Screenshoot To Clipboard From CLI
MacOS comes with a `screencapture` utility that you can run from the terminal
to activate the built-in screenshot functionality on Mac.
Usually when I am taking a screenshot, I want to do something with it right
away. Such as paste it into an application or group chat. The `-c` flag forces
the screen capture to go the clipboard.
I also generally want to capture a specific area of the screen so that the
captured image includes the right amount of context and nothing more. The `-i`
flag puts you in interactive screen capture mode. That means your cursor will
turn into a crosshair that you can use to make a drag selection of the capture
area.
```bash
$ screencapture -ic
```
Select an area to capture, it's now on your clipboard, paste it where you need
it.
Note: The first time you run this command, your terminal program (e.g. iTerm2)
may prompt you for the necessary OS permissions in order to capture images of
your screen. You'll need to grant those permissions and then rerun the command.
See `man screencapture` for more details.

View File

@@ -1,39 +0,0 @@
# Detect How Long A User Has Been Idle
The `ioreg` utility on MacOS dumps the I/O Kit registry tree. This lets us look
at the state of all hardware devices and drivers registered with I/O Kit.
Looking specifically at the Human Interface Device subsystem (`IOHIDSystem`), we
can find a handful of properties including the `HIDIdleTime`.
```bash
$ ioreg -c IOHIDSystem | awk '/HIDIdleTime/'
| | | "HIDIdleTime" = 91831000
```
That value is the number of nanoseconds since a human input device was last
interacted with. That is the amount of time the user (me) has been idle.
I can convert this to seconds, which is the small amount of time between me
hitting enter in the terminal and the command finding the idle time.
```bash
$ ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {printf "%.2f seconds\n", $NF/1000000000}'
0.13 seconds
```
I can run this in `watch` to see the elapsed idle time increment.
```bash
watch -n 1 "echo -n 'Idle time: '; ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {printf \"%.1f seconds\\n\", \$NF/1000000000}'"
```
After watching the _idle time_ increment for a bit, I can move the mouse and
watch it reset on the next `watch` loop.
This could be used as part of a script that takes certain actions after the user
has been idle for a while, like putting the display to sleep or stopping a time
tracker app.
There is a _lot_ going on in the `ioreg` output and it's hard to make sense of
hardly any of it. I found running `ioreg -c IOHIDSystem | less`, searching for
`IdleTime`, and browsing from there to be a good starting point.

View File

@@ -1,41 +0,0 @@
# Inspect Assertions Preventing Sleep
The `pmset` command is for inspecting and manipulating _Power Management
Settings_ on MacOS. The `-g` flag is for _getting_ details. We can get a summary
of power assertions with `-g assertions`. These assertions are ways that the
system and display are prevented from sleeping.
A common assertion preventing sleep is the user being active. Another example of
an assertion is a program like `caffeinate` that sets a timeout preventing sleep
for a fixed period of time.
Here I activate a 30 minute (1600 second) `caffeinate` session and then I
inspect the power management assertions which shows the details of that
assertion as well as two others.
```bash
caffeinate -t 1600 &
[1] 98217
pmset -g assertions
2025-11-02 13:20:57 -0600
Assertion status system-wide:
BackgroundTask 0
ApplePushServiceTask 0
UserIsActive 1
PreventUserIdleDisplaySleep 0
PreventSystemSleep 0
ExternalMedia 0
PreventUserIdleSystemSleep 1
NetworkClientActive 0
Listed by owning process:
pid 98217(caffeinate): [0x00045477000194b3] 00:00:03 PreventUserIdleSystemSleep named: "caffeinate command-line tool"
Details: caffeinate asserting for 1600 secs
Localized=THE CAFFEINATE TOOL IS PREVENTING SLEEP.
Timeout will fire in 1597 secs Action=TimeoutActionRelease
pid 145(WindowServer): [0x00044f2f00099212] 00:00:00 UserIsActive named: "com.apple.iohideventsystem.queue.tickle serviceID:10009be9e service:AppleUserHIDEventService product:CTRL Keyboard eventType:3"
Timeout will fire in 600 secs Action=TimeoutActionRelease
pid 80(powerd): [0x00044f2f00019216] 00:22:34 PreventUserIdleSystemSleep named: "Powerd - Prevent sleep while display is on"
```
See `man pmset` and `man caffeinate` for more details.

View File

@@ -1,36 +0,0 @@
# Launch Some Confetti
If you have [Raycast](https://www.raycast.com/) installed on your machine, then
you have quick access to some confetti via their quick command palette. Trigger
the command palette to open, start typing `confetti` until it appears as the
focused option, and then hit enter.
🎉
We can launch confetti other ways, including programmatically from scripts.
To do this, we need to first find the _deeplink_ for the Raycast _confetti_
program. Trigger the command palette and type out `confetti` again. However,
this time instead of hitting enter, hit `Cmd+k` to open other actions. Find the
_Copy Deeplink_ option.
You should now have this on your clipboard:
```
raycast://extensions/raycast/raycast/confetti
```
With this deeplink in hand, we can now trigger confetti other places. The
easiest way to do this is to open a terminal and pass that deep link as an
argument to `open`.
```bash
$ open raycast://extensions/raycast/raycast/confetti
```
Now you can wrap that up in any old bash script or even just tack it on to the
end of a run of your test suite:
```bash
$ rails test && open raycast://extensions/raycast/raycast/confetti
```

View File

@@ -1,30 +0,0 @@
# Prevent Sleep With The Caffeinate Command
MacOS has a built-in utility `caffeinate` that can programatically prevent your
machine from sleeping. There are two kinds of sleep that it can prevent via
_assertions_.
> caffeinate creates assertions to alter system sleep behavior.
The two kinds of sleep behavior are _display sleep_ and _system idle sleep_. An
assertion to prevent display sleep can be created with `-d` and system idle
sleep with `-i`.
We can combine those to prevent both and then specify a duration (_timeout_)
with `-t` (with a value in seconds).
```bash
caffeinate -d -i -t 600
```
This creates assertions with 10 minute timeouts for both display and system idle
sleep.
The `caffeinate` command is blocking, so if you want to start it in the
background, you can do that like so:
```bash
caffeinate -d -i -t 600 &
```
See `man caffeinate` for more details.

View File

@@ -1,37 +0,0 @@
# Start Amphetamine Session With AppleScript
I use the _Amphetamine_ app on Mac to keep my computer from going to sleep
during the day. It is a menu bar app that can be used to start a _Session_ of
time where it will keep your computer from going to sleep. At the start of my
day, I'll typically start an 8 hour _Session_. This is useful if I have to step
away fo 10 minutes or if I'm doing some writing in my notebook, my computer
won't go to sleep on me.
Though these sessions can be controlled from the menu bar app, I was excited to
learn that I can also programatically start a session with AppleScript.
Here is how to start a _Session_ (overriding an existing session) with options
that specify it is 8 hours long and the display should not be allowed to sleep.
```bash
$ osascript -e 'tell application "Amphetamine" to start new session with options {duration:8, interval:hours, displaySleepAllowed:false}'
```
The `interval` could also be `minutes` and then I could change the duration to
an amount of time that makes sense in minutes, e.g. `90` for 1.5 hours.
Note: the `with options {...}` segement is all or nothing. All three need to be included or don't include the clause at all.
Additionally, a session of indefinite duration can be started by including no options:
```bash
$ osascript -e 'tell application "Amphetamine" to start new session'
```
And any existing session can be ended with:
```bash
$ osascript -e 'tell application "Amphetamine" to end session'
```
[source](https://iffy.freshdesk.com/support/solutions/articles/48000078223-applescript-documentation)

View File

@@ -1,17 +0,0 @@
# 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

@@ -1,25 +0,0 @@
# Use A Different Font With iTerm2
I wanted to give [`gh-dash`](https://github.com/dlvhdr/gh-dash) a try, but
after installing and opening it up, I was seeing a bunch of `?` characters
where specialized font icons were missing. Their README recommended installing
a [`Nerd Font`](https://github.com/ryanoasis/nerd-fonts) that includes those
icons, such as [`Fira Code`](https://github.com/tonsky/FiraCode).
I was able to install `font-fira-code-nerd-font` with homebrew:
```bash
$ brew install font-fira-code-nerd-font
```
Then to get iTerm2 to start using that font, I had to change the font setting
for my current profile.
Under the _iTerm2_ menu is _Settings..._. From there, I clicked the _Profiles_
section. For the _Default_ profile, I went to the _Text_ tab and under _Font_ I
selected _FireCode Nerd Font Mono_ from the dropdown.
That won't take effect on any current iTerm2 windows. Since I have everything
running through `tmux`, I could close my current window, open a new one
(`Cmd+N`), and reconnect to my existing `tmux` session. Now when I run `gh
dash`, I see all the font icons that were missing before.

View File

@@ -1,53 +0,0 @@
# Create Umbrella Task For All Test Tasks
When I was first sketching out the [`mise`
tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
the following two tasks. One is for running all the `rspec` tests. The Other is
for running all the `vitest` (JavaScript) tests.
```toml
[tasks."test:rspec"]
run = "unbuffer bundle exec rspec"
description = "Run RSpec tests"
depends = ["bundle-install"]
[tasks."test:vitest"]
run = "unbuffer yarn test run"
description = "Run Vitest tests"
depends = ["node-install"]
```
I didn't want to have to invoked both of this individually every time I wanted
to run the full suite. So I added a `test:all` task to do it all.
```toml
[tasks."test:all"]
description = "Run all tests (RSpec and Vitest)"
run = [
"unbuffer bundle exec rspec",
"unbuffer yarn test run",
]
description = "Run RSpec tests"
depends = ["bundle-install", "node-install"]
```
This worked (for now). But it ate at me, for a couple reasons. I had to
duplicate everything about the existing `test:rspec` and `test:vitest` tasks.
And this didn't account for a new kind of test task being added (e.g.
`test:e2e`).
Instead, I can rely on `depends` and wildcards to achieve this without the
duplication which makes it more future-proof.
```toml
[tasks."test:all"]
description = "Run all tests (RSpec and Vitest)"
depends = ["test:*"]
```
Running `mise run test:all` won't execute its own command, but because it
depends on all other `test:*` tasks, the tests will get run through those
dependencies.
This task naming pattern also allows for calling all tests with `mise run
"test:**"`.

View File

@@ -1,29 +0,0 @@
# List The Files Being Loaded By Mise
While running `mise` for the first time, after adding a `mise.toml` file to a
project, I noticed something strange. Instead of invoking the command I had
specified (`mise run dev`), several parellel tool downloads were kicked off. In
addition to Ruby, it was installing an older version of Postgres, and lua. What
gives?
By running `mise cfg`, I can list all the files being loaded by `mise` and get
to the bottom of this.
```bash
mise cfg
Path Tools
~/.tool-versions node, ruby, postgres, lua
~/code/still/.ruby-version ruby
~/code/still/Gemfile (none)
~/code/still/.tool-versions ruby
~/code/still/mise.toml (none)
```
I was only thinking about the files local to my project and I forgot that I
have a system-wide `.tool-versions` file. As we can see from the output, that
file specifies `postgres` and `lua` as well. Mise wanted to ensure that it had
downloaded the specified versions of each of those tools before running my
task.
[source](https://mise.jdx.dev/configuration.html)

View File

@@ -1,27 +0,0 @@
# Look In Ruby Version Dotfile
Newer versions of [`mise`](https://mise.jdx.dev/dev-tools/) specifically only
look for tool versions in `mise.toml` as well as the asdf `.tool-versions` file.
A lot of Ruby projects use the `.ruby-version` file to indicate the Ruby version
of a project. To continue to use the `.ruby-version` file instead of migrating
to `mise.toml`, you need to tell `mise` that you prefer to use the idiomatic
version file.
I added the following line to my
[`~/.config/mise/config.toml`](https://github.com/jbranchaud/dotfiles/commit/8edeb7a9c53500e89e88b4079cbd1859ebebcbda)
file:
```toml
idiomatic_version_file_enable_tools = ["ruby"]
```
Now, whenever `mise` is looking for the specified Ruby version of a project, it
will also look for `.ruby-version`.
Here is a [full list of idomatic version files supported by
`mise`](https://mise.jdx.dev/configuration.html#idiomatic-version-files).
See
[`idiomatic_version_file_enable_tools`](https://mise.jdx.dev/configuration/settings.html#idiomatic_version_file_enable_tools)
as well as the [Ruby-specific documentation](https://mise.jdx.dev/lang/ruby.html#ruby-version-and-gemfile-support)
for more details.

View File

@@ -1,45 +0,0 @@
# Preserve Color Output For Task Command
I decided to wrap a couple test running commands for a project into a single
`test:all` mise task. It looked something like this:
```toml
[tasks."test:all"]
run = """
bundle exec rspec
yarn test run
"""
description = "Run all tests (RSpec and Vitest)"
depends = ["bundle-install", "node-install"]
```
I can run this with `mise run test:all` and it works. However, there is a
glaring issue that immediately juts out. All of the test runner output is
uncolored text. I'm used to and strongly prefer greens (passes), reds (fails),
and yellows (skips) of test runner output.
The test runners lose the text coloring when run through `mise` because they
believe they are not running in _interactive_ mode.
The [`expect`](https://linux.die.net/man/1/expect) tools (`brew install
expect`) install with another binary called
[`unbuffer`](https://linux.die.net/man/1/unbuffer). `unbuffer` can coerce a
command to run in interactive mode. Prepending these test runner commands with
`unbuffer` will preserve the colors as the results are output to the terminal.
Here is the update `test:all` task:
```toml
[tasks."test:all"]
run = """
unbuffer bundle exec rspec
unbuffer yarn test run
"""
description = "Run all tests (RSpec and Vitest)"
depends = ["bundle-install", "node-install"]
```
For some commands, it seems able to stream out (rather than _buffer_) the
results (e.g. with `vitest`). Whereas with `rspec`, the test suite runs to
completion and is then output to the terminal. I'm still investigating
streaming the `rspec` results.

View File

@@ -1,28 +0,0 @@
# Read Existing Dot Env File Into Env Vars
Just about any web app that I've worked on has had a `.env` file as a way of
configuring aspects of the app specific to that environment. These typically
are read into the environment with a language-specific
[dotenv](https://github.com/bkeepers/dotenv) tool.
Mise supports this convention. In addition to specifying individual non-secret
env vars, you can also instruct `mise` to read-in a `.env` file like so:
```toml
[env]
PORT=3344
_.file = ".env"
```
The `_.file` line tells `mise` that there is a file `.env` with key-value pairs
that it should read in. It can even handle `.env.json` and `.env.toml` file
formats.
To ensure that `mise` is picking up the values from the `.env` file, you can
run the following command and make sure they show up in the output:
```bash
$ mise env
```
[source](https://mise.jdx.dev/environments/secrets.html)

View File

@@ -1,39 +0,0 @@
# Run A Command With Specific Tool Version
Because I'm using `mise` to manage the versions of tools like Node, I can
execute commands in the context of specific versions. Behind the scenes `mise`
makes sure I have the necessary tool(s) installed at the desired version(s).
So, [`mise exec` command](https://mise.jdx.dev/cli/exec.html) will default to
using the latest version of a tool if I haven't been more specific. At the time
of this writing, for Node, that is v23.
```bash
$ mise exec node -- node --version
v23.9.0
```
To be specific I could specify the major version with `node@23` like so:
```bash
mise exec node@23 -- npx repomix
Need to install the following packages:
repomix@0.2.39
Ok to proceed? (y) y
...
```
Or if I wanted to use a different, older version of Node, I could specify that
as well. We can see it will first install that and then execute the command:
```bash
$ mise exec node@22 -- npx repomix
gpg: Signature made Tue Feb 11 04:44:53 2025 CST
gpg: using RSA key C0D6248439F1D5604AAFFB4021D900FFDB233756
gpg: Good signature from "Antoine du Hamel <duhamelantoine1995@gmail.com>" [unknown]
📦 Repomix v0.2.39
...
```

View File

@@ -1,40 +0,0 @@
# Get Idea Of What Is In A JSON Column
While digging through some data trying to reacquaint myself with the overall
schema and data model, I ran into an issue selecting rows from this
`content_resource` table. There was so much text packed in to the `"body"`,
`"summary"`, and `"description"` key-value pairs of `fields` JSON column that a
simple `select * ... limit 3;` was overwhelming the screen with text and table
formatting characters (i.e. `+------+-------`).
I figured the `fields` JSON followed a reliable structure, at least for records
of the same `type`. So, let's start by only grabbing the
[`json_keys`](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#function_json-keys)
so that I can get a sense of the shape of the JSON.
```sql
select id, json_keys(fields)
from content_resource
where type = 'post'
limit 3;
+-----+-----------------------------------------------------------------------------------------------------------+
| id | json_keys(`fields`) |
+-----+-----------------------------------------------------------------------------------------------------------+
| 1 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
| 2 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
| 3 | ["body", "slug", "state", "title", "summary", "postType", "visibility", "description", "originalLessonId"] |
+-----+-----------------------------------------------------------------------------------------------------------+
```
For the `post` type, I see the same keys for this sampling of rows. Now I have
an idea what keys are present and can start digging in further.
My next query might look something like this:
```sql
select id, fields->'$.slug', fields->'$.title', fields->'$.state'
from content_resource
where type = 'post'
limit 3;
```

View File

@@ -1,46 +0,0 @@
# Jump Between Changes In Current File
With the [gitsigns.nvim plugin](https://github.com/lewis6991/gitsigns.nvim) for
Neovim, I get some handy Git-related capabilities like gutter highlighting of
additions, deletions, and changes to lines in the current file. These contiguous
sections of modification to the versioned state of a file are called hunks.
Here are two mappings (in Lua) for gitsigns that allow me to jump to the next
(`]h`) or previous (`[h`) hunk in the current file.
```lua
---@type LazyKeysSpec[]
M.gitsigns_mappings = {
-- Navigation
{
']h',
function()
if vim.wo.diff then
vim.cmd.normal { ']c', bang = true }
else
require('gitsigns').nav_hunk 'next'
end
end,
desc = 'Next Hunk',
},
{
'[h',
function()
if vim.wo.diff then
vim.cmd.normal { '[c', bang = true }
else
require('gitsigns').nav_hunk 'prev'
end
end,
desc = 'Prev Hunk',
},
}
```
This is particularly useful when I've just opened a big file and I want to jump
directly to active changes in that file.
I got this mapping directly from [Dorian's
dotfiles](https://github.com/dkarter/dotfiles).

View File

@@ -1,23 +0,0 @@
# Run nvim With Factory Defaults
Most of the fun of using Neovim is tailoring it to your exact needs with custom
configurations. Your configuration can be made up of environment variables,
`init.lua`/`init.vim`, and user directories on the `runtimepath`.
Perhaps though, you want to load neovim with its "factory defaults". You want
to ignore all your custom config and your _shada_ (shared data) file. I wanted
to do just that recently to verify that neovim has the `ft-manpage` plugin
enabled by default (as opposed to enabled somewhere in the labryinth of my
config files).
The `--clean` flag does just this. It loads built-in plugins, but none of the
user defined config.
```bash
$ nvim --clean
```
This is different than `nvim -u NONE` which excludes all plugins, including
built-in ones.
See `man nvim` and `:help --clean` for more details.

1
notes

Submodule notes deleted from 897184eb02

Some files were not shown because too many files have changed in this diff Show More