1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-07 09:08:01 +00:00

Compare commits

...

523 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
c58bfbb37f Reorder commands: commit before pull --rebase
Co-authored-by: jbranchaud <694063+jbranchaud@users.noreply.github.com>
2026-01-01 00:18:25 +00:00
copilot-swe-agent[bot]
9b5af6a535 Simplify pull command to use configured upstream
Co-authored-by: jbranchaud <694063+jbranchaud@users.noreply.github.com>
2026-01-01 00:17:23 +00:00
copilot-swe-agent[bot]
62d194f492 Add git pull --rebase to notes:push task
Co-authored-by: jbranchaud <694063+jbranchaud@users.noreply.github.com>
2026-01-01 00:16:23 +00:00
copilot-swe-agent[bot]
7a7a0faf94 Initial plan 2026-01-01 00:14:07 +00:00
jbranchaud
d980514bff Add Create Interactive Picker For Set Of Subtasks as a Taskfile TIL 2025-12-31 12:33:50 -07:00
jbranchaud
db26fc97c6 Add Set Up Forwarding Prefix For Nested Session as a tmux TIL 2025-12-31 12:10:52 -07:00
jbranchaud
8094448877 Add Join URI Path Parts as a Ruby TIL 2025-12-30 10:39:03 -07:00
jbranchaud
883b3e6ee6 Add Run Dev Processes With Overmind Instead Of Foreman as a Rails TIL 2025-12-28 10:21:35 -06:00
jbranchaud
57c4954d6f Add Regenerate Lock File With Newer Bundler as a Ruby TIL 2025-12-26 11:33:07 -06:00
jbranchaud
86a7815a9f Add Specify Default Team And App For Project as a Heroku TIL 2025-12-22 20:46:45 -06:00
jbranchaud
676038e992 Add Create A Module Of Utility Functions as a Ruby TIL 2025-12-17 16:54:43 -06:00
jbranchaud
01fd503a92 Add Run Rails Console With Remote Dokku App as a Rails TIL 2025-12-15 22:27:47 -06:00
jbranchaud
8b718aee4f Add Describe Current Changes And Create New Change as a jj TIL 2025-12-10 11:34:13 -06:00
jbranchaud
88f49de7f3 Add Reference The Full Match In The Replacement as a Sed TIL 2025-12-01 14:07:25 -06:00
jbranchaud
9f9fce7835 Add Make Structs Easier To Use With Keyword Initialization as a Ruby TIL 2025-12-01 06:35:43 -06:00
jbranchaud
65a4d0ef3d Add Rename A Bunch Of Files By Constructing mv Commands as a Unix TIL 2025-11-30 20:10:59 -06:00
jbranchaud
6c8a5eb36d Add new newsletter URL 2025-11-29 15:10:43 -06:00
jbranchaud
fed722d7fe Add Access Your GitHub Profile Photo as a GitHub TIL 2025-11-29 14:40:34 -06:00
jbranchaud
fbebc3e5ee Add Install And Require Gems Inline Without Gemfile as a Ruby TIL 2025-11-28 23:24:00 -06:00
jbranchaud
83d55c420e Add Use .ruby Extension For Template File as a Rails TIL 2025-11-27 10:29:56 -06:00
jbranchaud
8dbbfe0eda Add Create Mock Class That Can Be Overridden as a Ruby TIL 2025-11-25 22:18:00 -06:00
jbranchaud
c38d9f090e Add Monitor Usage Limits From CLI as a Claude Code TIL 2025-11-22 08:43:26 -06:00
jbranchaud
bae3527baf Add Determine ipv4 And ipv6 Public IP Addresses as a Unix TIL 2025-11-21 16:43:08 -06:00
jbranchaud
53a0b88eff Add Get Idea Of What Is In A JSON Column as a MySQL TIL 2025-11-20 09:06:08 -06:00
jbranchaud
665c8f994f Add List All Git Aliases From gitconfig as a Git TIL 2025-11-19 14:39:41 -06:00
jbranchaud
5f11b1665b Remove dprint config to never text wrap
This was causing multi-line sequences of text in TIL markdown files to be
unwrapped into one long line.
2025-11-18 13:20:58 -06:00
jbranchaud
ce5ff038c0 Add Generate A Sequence Of Numbered Items as a Unix TIL 2025-11-18 13:20:49 -06:00
jbranchaud
486a6ef5a9 Add Open Current Prompt In Default Editor as a Claude Code TIL 2025-11-18 12:54:50 -06:00
jbranchaud
c1ce559452 Add Add A Bunch Of CLI Utilities With corutils as a Mac TIL 2025-11-16 22:21:45 -06:00
jbranchaud
07c4aa86b7 Add Squash Changes Into Parent Commit Interactively as a jj TIL 2025-11-16 17:31:42 -06:00
jbranchaud
a0c2a29a96 Add See What Databases You Have Access To as a Planetscale TIL 2025-11-16 10:34:44 -06:00
jbranchaud
45b269abf1 Add Launch Some Confetti as a Mac TIL 2025-11-14 18:52:45 -06:00
jbranchaud
44dc6f2b1f Add Install Go Packages In Brewfile as a Brew TIL 2025-11-14 18:19:43 -06:00
jbranchaud
821a7e5c67 Add Do Project Time Tracking From The CLI as a Workflow TIL 2025-11-14 00:32:13 -06:00
jbranchaud
c0f20267bb Add Shorten SSH Commands With Aliases as a Unix TIL 2025-11-12 15:00:19 -06:00
jbranchaud
50deb6175f Add Detect How Long A User Has Been Idle as a Mac TIL 2025-11-11 17:13:36 -06:00
jbranchaud
d1f41884ce Add Set Default Tasks For Rake To Run as a Ruby TIL 2025-11-10 18:06:12 -06:00
jbranchaud
91149fe7cc Add Show Summary Stats For Current Branch as a Git TIL 2025-11-10 17:25:24 -06:00
jbranchaud
e2eb31a4a9 Add Reference Hash Key With Safe Navigation as a Ruby TIL 2025-11-09 17:12:09 -05:00
jbranchaud
113b7b2dfe Add Prevent Sleep With The Caffeinate Command as a Mac TIL 2025-11-09 13:50:03 -05:00
jbranchaud
16074c021f Add Convert JSON Field To Hash With Indifferent Access as a Rails TIL 2025-11-08 08:55:41 -05:00
jbranchaud
9e76753540 Add Open File On Remote Like GitHub as a VSCode TIL 2025-11-03 14:19:14 -05:00
jbranchaud
eb4dea611e Add Inspect Assertions Preventing Sleep as a Mac TIL 2025-11-02 15:21:31 -06:00
jbranchaud
6ef998b024 Add Check If A File Is Under Version Control as a Git TIL 2025-11-02 11:01:30 -06:00
jbranchaud
6e066ec72a Add Target Another Repo When Creating A PR as a GitHub TIL 2025-11-02 08:18:41 -06:00
jbranchaud
060ce8262d Add Set Up A Project-Local Cluster With Postgres.app as a Postgres TIL 2025-11-01 08:41:56 -05:00
jbranchaud
96fd138837 Add Exclude A Specific File From fd Results as a Unix TIL 2025-10-31 16:09:44 -05:00
jbranchaud
a51d716e45 Add Reword A Commit Message With Fugitive as a Vim TIL 2025-10-29 22:26:37 -05:00
jbranchaud
59de2fef0d Add Add Bindings To Split Panes To Current Directory as a tmux TIL 2025-10-29 21:38:06 -05:00
jbranchaud
fdd2461b75 Add Check If A File Has Changed In A Script as a Git TIL 2025-10-28 12:25:43 -05:00
jbranchaud
e8c2e01d6f Add better status check for notes:push 2025-10-28 08:29:15 -05:00
jbranchaud
ed9cedc870 Add Run A Task If It Meets Criteria as a Taskfile TIL 2025-10-28 08:26:39 -05:00
jbranchaud
da585ec5a4 Add Allow Cursor To Be Launched From CLI as a Cursor TIL 2025-10-27 21:37:59 -05:00
jbranchaud
35d1a81ea7 Move recent TIL to new GitHub category 2025-10-27 17:08:55 -05:00
jbranchaud
d69fefe9f0 Use status instead of precondition to avoid error 1 2025-10-27 17:07:21 -05:00
jbranchaud
1cc612294e Run notes:push steps only if there are changes 2025-10-27 16:45:03 -05:00
jbranchaud
d79264395b Add Open A PR To An Unforked Repo as a GitHub TIL 2025-10-27 15:14:00 -05:00
jbranchaud
2d5abd9cbf Revert to excluding entire README formatting
The `unorderedListMarker` setting was hallucinated.
2025-10-26 18:20:47 -05:00
jbranchaud
2efaf27066 Add Tell gh What The Default Repo Is as a Git TIL 2025-10-26 17:58:42 -05:00
jbranchaud
6b4b2c588c Rework notes task to make edit the primary one
What was 'edit' has been renamed to 'open'. And 'edit' is now what was
not so clearly named 'save'.
2025-10-26 17:14:51 -05:00
jbranchaud
e473fa781d Move notes higher up, it is most common command 2025-10-26 17:09:51 -05:00
jbranchaud
5ce5eccb0a Add Jump Between Changes In Current File as a Neovim TIL 2025-10-26 16:52:24 -05:00
jbranchaud
db4961a8eb Don't error if you escape from fzf 2025-10-25 13:40:17 -05:00
jbranchaud
ff227a39ed Turn of only dprint's unordered list formatting 2025-10-25 12:51:25 -05:00
jbranchaud
0d3975eb9c Disable dprint for README for bullet formatting 2025-10-25 12:49:33 -05:00
jbranchaud
d171c3784b Get rid of the help task, not needed now 2025-10-25 11:51:27 -05:00
jbranchaud
e6d00a94f3 Add an interactive picker for notes tasks 2025-10-25 11:50:22 -05:00
jbranchaud
0e934d8dd3 Add a default task to list all tasks 2025-10-25 10:05:38 -05:00
jbranchaud
c30b17dd68 Add a taskfile for managing notes submodule 2025-10-25 09:59:34 -05:00
jbranchaud
757e163c2e Ignore all changes to the notes submodule 2025-10-25 00:57:38 -05:00
jbranchaud
cf037f13f7 Tell the submodule to use the main branch 2025-10-25 00:50:16 -05:00
jbranchaud
08fb235e81 Add submodule for including private notes file 2025-10-25 00:37:04 -05:00
jbranchaud
95dc00d748 Add Get The Names Of The Month as a Ruby TIL 2025-10-24 15:18:40 -05:00
jbranchaud
ece12aac76 Add Clean Up Your Brew Installations as a Brew TIL 2025-10-23 14:23:11 -05:00
jbranchaud
9a6a40bdd6 Add Capture Screenshot To Clipboard From CLI as a Mac TIL 2025-10-22 15:40:50 -05:00
Jake Worth
4b4bd2350f Fix typo 2025-10-19 22:44:16 -05:00
jbranchaud
5924edf4c0 Add Set Up GPG Signing Key as a Git commit 2025-10-19 15:06:09 -05:00
jbranchaud
5eb21b3aa2 Add Transform Text To Lowercase as a Unix TIL 2025-10-17 21:49:38 -05:00
jbranchaud
5b3f1536fd Add Format Specific html.erb Template Files as a Rails TIL 2025-10-16 08:55:51 -05:00
jbranchaud
ec0e84664f Add Prevent Mailer Previews From Cluttering Database as a Rails TIL 2025-10-06 08:52:25 -05:00
jbranchaud
3912276599 Add Allow Number Input To Accept Decimal Values as an HTML TIL 2025-10-04 10:24:36 -05:00
jbranchaud
d166ffac0b Add Scope Records To A Lower Or Upper Bound as a Rails TIL 2025-10-03 19:59:00 -05:00
jbranchaud
e8b953ba6d Add Disable And Enable A Button as a Tailwind TIL 2025-09-29 18:54:05 -05:00
jbranchaud
8613c21f41 Add Avoid Double Negation With Minitest Refute as a Ruby TIL 2025-09-16 09:33:48 -05:00
jbranchaud
2b5df03981 Fix ordering of two TILs in README 2025-09-16 09:32:46 -05:00
jbranchaud
aef15d53b0 Add Parameterize A String With Underscores as a Rails TIL 2025-09-12 12:05:26 -05:00
jbranchaud
0c31fb6363 Add Clear Entries From Git Stash as a Git TIL 2025-08-05 09:10:20 -05:00
jbranchaud
cb94142042 Add Decompose Unicode Character With Diacritic Mark as a Ruby TIL 2025-07-21 17:38:41 -05:00
jbranchaud
ae2974e3b8 Add Authorize A cURL Request as a Unix TIL 2025-07-02 12:25:32 -05:00
jbranchaud
0ed4d84bc6 Add Get Specific Values From Hashes And Arrays as a Ruby TIL 2025-07-02 10:09:48 -05:00
jbranchaud
3b7e3258fe Add View A Nicely-Formatted CSV In Terminal as a Workflow TIL 2025-06-27 16:13:28 -05:00
jbranchaud
d00796b054 Add Manage Timestamps With Upsert as a Rails TIL 2025-06-26 09:21:17 -05:00
jbranchaud
8fecb0e863 Add References Target Primary Key By Default as a Postgres TIL 2025-06-19 09:59:12 -05:00
jbranchaud
14942c20d7 Add Provide Fake Form Helper To Controllers as a Rails TIL 2025-06-16 10:28:18 -05:00
jbranchaud
e901ae3b77 Add Restore File From One Branch To The Current as a Git TIL 2025-06-11 09:08:59 -05:00
jbranchaud
a4fee08596 Add a couple links to the About section of README 2025-06-09 09:44:40 -05:00
jbranchaud
6e518763c7 Add Check The Size Of Databases In A Cluster as a Postgres TIL 2025-05-06 21:21:57 -05:00
jbranchaud
bb40353512 Add Customize Template For New Schema Migration as a Rails TIL 2025-05-03 21:15:07 -05:00
jbranchaud
917f9e516e Add Cherry Pick Multiple Commits At Once as a git TIL 2025-05-02 23:14:16 -05:00
jbranchaud
d8dfcce0fc Add Format DateTime With Builtin Formats as a Rails TIL 2025-04-30 23:18:32 -05:00
jbranchaud
0d173ccaaf Add Interpret Cron Schedule From The CLI as a Unix TIL 2025-04-24 15:46:19 -05:00
jbranchaud
8dd9f86b80 Add Highlight Small Change On Single Line as a Git TIL 2025-04-17 18:19:12 -05:00
jbranchaud
2bb8af2880 Add Vimium course under other learning resources 2025-04-17 17:22:17 -05:00
jbranchaud
e16c2525be Add Run nvim With Factory Defaults as a Neovim TIL 2025-04-12 16:32:22 -05:00
jbranchaud
a55fff68e1 Add Exclude A Directory During A Command as a Git TIL 2025-04-12 16:03:06 -05:00
jbranchaud
162a7ceea3 Add Format A List Of Items By Locale as a JavaScript TIL 2025-04-11 17:47:33 -05:00
jbranchaud
f578727349 Add Make Neovim The Default Way To View Man Pages as a Unix TIL 2025-04-09 21:25:17 -05:00
jbranchaud
4ba53dca7d Add Create And Execute SQL Statements With \gexec as a Postgres TIL 2025-04-07 17:52:13 -05:00
jbranchaud
571f465fe6 Fix some typos in an old git TIL 2025-04-07 17:18:05 -05:00
jbranchaud
a547b9cee2 Add Create A Filename With The Current Date as a Unix TIL 2025-04-02 09:26:38 -05:00
jbranchaud
99ce5aee7b Add Bypass On-Save Tooling When Writing File as a Vim TIL 2025-04-01 10:56:25 -05:00
jbranchaud
60b6aa40ad Add Open Current Tab In New Window With Vimium as a Chrome TIL 2025-03-31 10:18:13 -05:00
jbranchaud
f97634a61e Add Have Script ShellCheck Itself When Executing as a Unix TIL 2025-03-29 09:20:39 -05:00
jbranchaud
34ba60d313 Add List RDS Snapshots With Matching Identifier Prefix as an AWS TIL 2025-03-28 11:25:31 -05:00
jbranchaud
3a178e901e Add Filter ActiveModel Validation Errors as a Rails TIL 2025-03-27 10:41:35 -05:00
jbranchaud
db07125ba9 Add Output CLI Results In Different Formats as an AWS TIL 2025-03-25 10:53:22 -05:00
jbranchaud
b6cf4ba0ad Add Search Tabs With The Vimium Vomnibar as a Chrome TIL 2025-03-24 20:22:52 -05:00
jbranchaud
e4d695e465 Add Show Reconstructed Constraints For A Table as a Postgres TIL 2025-03-22 12:02:03 -05:00
jbranchaud
5c9a3888fd Add Find And Copy A Value From Large JSON Output as a Unix TIL 2025-03-21 10:22:50 -05:00
jbranchaud
22541826d6 Add Go To Beginning And End Of Line as a Vim TIL 2025-03-19 11:50:10 -05:00
jbranchaud
b39ee94c90 Add Run SQL Script Against Postgres Container as a Docker TIL 2025-03-19 09:50:23 -05:00
jbranchaud
efad7da916 Add Turn Off Output Pager For A Command as an AWS TIL 2025-03-18 18:34:11 -05:00
jbranchaud
ca3327bda3 Add Show The Bundler Location Of An Installed Gem as a Ruby TIL 2025-03-18 11:05:38 -05:00
jbranchaud
595ac85f17 Add Fetch Data From An Endpoint In SQL as a Postgres TIL 2025-03-17 17:31:32 -05:00
jbranchaud
92d732c769 Add Check Postgres Version Running In Docker Container as a Docker TIL 2025-03-15 14:03:55 -05:00
jbranchaud
d6ebe52523 Add Run A Command With Specific Tool Version as a Mise TIL 2025-03-14 16:34:39 -05:00
jbranchaud
93398ab950 Add Add Color To The IRB Console Prompt as a Rails TIL 2025-03-13 10:31:32 -05:00
jbranchaud
b1b2aa8982 Add Break Debugger On First Line Of Program as a Python TIL 2025-03-12 10:35:08 -05:00
jbranchaud
6cbf1cb974 Add Download A Google Doc As Specific Format as an Internet TIL 2025-03-11 17:03:40 -05:00
jbranchaud
79faae1047 Add Create Umbrella Task For All Test Tasks as a Mise TIL 2025-03-10 18:07:38 -05:00
jbranchaud
1316eb70ec Add Grab The RSS Feed For A Substack Blog as an Internet TIL 2025-03-09 19:10:33 -05:00
jbranchaud
ddf1c51fd9 Add Filter ActiveStorage Blobs To Only Images as a Rails TIL 2025-03-08 16:18:44 -06:00
jbranchaud
60020d6e0e Add Preserve Color Output For Task Command as a Mise TIL 2025-03-08 16:07:39 -06:00
jbranchaud
ef9f88f3c8 Add Prevent Invisible Elements From Being Clicked as a CSS TIL 2025-03-07 21:30:52 -06:00
jbranchaud
c8445c45a9 Add Read Existing Dot Env File Into Env Vars as a Mise TIL 2025-03-05 13:19:08 -06:00
jbranchaud
497b0ff3b7 Add Files With Local Changes Cannot Be Removed as a Git TIL 2025-03-04 18:05:58 -06:00
jbranchaud
64df6d16d7 Add Find All Tool Version Files Containing Postgres as a Unix TIL 2025-03-04 17:41:03 -06:00
jbranchaud
7dac057246 Add List The Files Being Loaded By Mise as a Mise TIL 2025-03-04 09:24:27 -06:00
jbranchaud
8961c67026 Add Create Todo Items In Logseq as a Workflow TIL 2025-03-03 17:06:58 -06:00
jbranchaud
4ff24a7336 Add Restart Puma Server By Touching Restart File as a Rails TIL 2025-03-01 09:48:48 -06:00
jbranchaud
2916fbc3b5 Add Create And Jump Into A Directory as a Zsh TIL 2025-02-28 10:39:23 -06:00
jbranchaud
e3fc10edd8 Fix alphabetical ordering of Rails TILs 2025-02-26 16:53:08 -06:00
jbranchaud
4fe0817b2d Add Buy Me A Coffee Link to README 2025-02-26 16:52:32 -06:00
jbranchaud
fc74264040 Add Adjust The Production Log Level as a Rails TIL 2025-02-26 16:52:13 -06:00
jbranchaud
2b38e1caf8 Add SSH Into An ECS Container as an AWS TIL 2025-02-25 12:12:52 -06:00
jbranchaud
db6d18f086 Add Enforce Locals Passed To A Partial as a Rails TIL 2025-02-24 19:15:52 -06:00
jbranchaud
84548b7a7f Add List The PID And Name Of Current Shell Process as a Unix TIL 2025-02-23 10:12:52 -06:00
jbranchaud
f9b966a0f1 Add Use Specific AWS Profile With CLI as an AWS TIL 2025-02-23 09:57:30 -06:00
jbranchaud
871d555e95 Add Filter Blur Requires Expensive Calculation as a CSS TIL 2025-02-21 15:29:14 -06:00
jbranchaud
cea3bc05b5 Add Fix Previous Command With fc as a Unix TIL 2025-02-20 17:42:32 -06:00
jbranchaud
ee31f5b70d Add Find And Follow Server Logs as an AWS TIL 2025-02-19 09:00:35 -06:00
jbranchaud
5b6a88b327 Remove the amplify TOC item, no longer exists 2025-02-19 09:00:11 -06:00
jbranchaud
49ebb8dd78 Add A Better Way To Reload ZSH Configuration as a ZSH TIL 2025-02-18 17:06:35 -06:00
jbranchaud
6ff8f19d08 Add OpenStruct Has Bad Performance Characteristics as a Ruby TIL 2025-02-17 15:32:15 -06:00
jbranchaud
14e6635383 Add Fix Shim Path After asdf Upgrade as a Unix TIL 2025-02-17 10:31:58 -06:00
jbranchaud
0a0a509827 Link to groff in latest TIL 2025-02-17 09:52:06 -06:00
jbranchaud
bb331577ca Collapse Amplify category into the AWS category 2025-02-17 09:46:02 -06:00
jbranchaud
0e0dcbf2b4 Add AWS CLI Requires Groff Executable as an AWS TIL 2025-02-17 09:44:27 -06:00
jbranchaud
fe9b62a631 Add Prevent Containers From Running On Startup as a Docker TIL 2025-02-13 11:44:38 -06:00
jbranchaud
eb3369d296 Add Limit Protocols Used In A cURL Command as a Unix TIL 2025-02-10 17:10:15 -06:00
jbranchaud
6f47e2f057 Add Uninstall LogiTech G Hub From Mac as a Mac TIL 2025-02-10 15:24:15 -06:00
jbranchaud
409201611f Add Get Word Count For All Files In Git Repo as a Unix TIL 2025-02-08 18:07:54 -06:00
jbranchaud
77cc07a908 Add Reference Commits Earlier Than Reflog Remembers as a Git TIL 2025-02-07 22:09:28 -06:00
jbranchaud
633c1fa0a5 Add Count The Number Of Words On A Webpage as a Unix TIL 2025-02-05 11:28:06 -06:00
jbranchaud
96c394c198 Add Extract Capture Group Matches With String Slices as a Ruby TIL 2025-02-03 15:29:56 -06:00
jbranchaud
0251157dc4 Add Determine The Configured Primary Key Type as a Rails TIL 2025-02-02 21:50:16 -06:00
jbranchaud
97c8701a5a Add Use Labels To Block PR Merge as a GitHub Actions PR 2025-02-01 14:10:25 -06:00
jbranchaud
1fd64e478a Clarify some things in the latest TIL 2025-01-31 14:34:53 -06:00
jbranchaud
8ea123369b Add Trim Leading And Trailing Space From String as a Postgres TIL 2025-01-31 14:23:34 -06:00
jbranchaud
43c6e08b34 Add Add A Generated Column To A PostgreSQL Table as a Rails TIL 2025-01-30 23:10:23 -06:00
jbranchaud
61fc021f52 Add Unable To Infer Data Type In Production as a Postgres TIL 2025-01-28 18:40:09 -06:00
jbranchaud
46ad33df7e Add Set Meta Tags In ERB Views as a Rails TIL 2025-01-28 18:30:12 -06:00
jbranchaud
2028f6cb09 Add List All Fonts On Your Machine as a Unix TIL 2025-01-27 23:34:44 -06:00
jbranchaud
1f039a8958 Add Default Rails Deploy Script On Hatchbox as a devops TIL 2025-01-26 21:12:39 -06:00
jbranchaud
c6eefeac98 Add Count The Number Of Items In An Array as a Postgres TIL 2025-01-25 19:02:13 -06:00
jbranchaud
31a0224fb7 Add Send A PDF To Your Kindle as a Workflow TIL 2025-01-24 15:27:25 -06:00
jbranchaud
aa71ff5f8b Add Override Text Displayed By Form Label as a Rails TIL 2025-01-24 12:36:46 -06:00
jbranchaud
48278c4908 Add Set Up Domain For Hatchbox Rails App as a devops TIL 2025-01-23 11:43:37 -06:00
jbranchaud
8b3ef4872c Add Apply Basic HTML Formatting To Block Of Text as a Rails TIL 2025-01-21 15:48:40 -06:00
jbranchaud
c2184a5ecf Add Hatchbox Exports Env Vars With asdf as a Devops TIL 2025-01-21 15:36:44 -06:00
jbranchaud
e2a8e815e9 Add Inspect Configuration Of Database Connection as a Rails TIL 2025-01-20 10:06:13 -06:00
jbranchaud
c61ddcb326 Add Temporarily Hide CleanShot X Capture Previews as a Workflow TIL 2025-01-19 13:56:45 -06:00
jbranchaud
7632664200 Add Scaffold Auth Functionality With Rails 8 Generator as a Rails TIL 2025-01-15 16:54:29 -06:00
jbranchaud
872a1d2a00 Add Count Number Of Commits On A Branch as a git TIL 2025-01-14 17:02:19 -06:00
jbranchaud
d52a126767 Add Pop Videos Out As Picture-in-Picture as a Workflow TIL 2025-01-12 11:40:29 -06:00
jbranchaud
d9080cc583 Add List All Files Added During Span Of Time as a Git TIL 2025-01-11 13:58:07 -06:00
jbranchaud
654c65c8f6 Add missing README changes for latest TIL 2025-01-11 13:57:32 -06:00
jbranchaud
138cab4fdc Add Control Media With Drop Keyboard as a Workflow TIL 2025-01-10 16:16:01 -06:00
jbranchaud
5592d4266d Add Use A Different Font With iTerm2 as a Mac TIL 2025-01-09 11:13:17 -06:00
jbranchaud
daf448c1a5 Add Rebuild Tailwind Bundle For Dev Server as a Rails TIL 2025-01-08 19:39:41 -06:00
jbranchaud
aaddc35fcd Add Disclose Additional Details as an HTML TIL 2025-01-07 13:31:31 -06:00
jbranchaud
b575534d4e Add Difference Between Slice And Pointer To Slice as a Go TIL 2025-01-06 16:43:30 -06:00
jbranchaud
ae3ecbf72c Add Start Amphetamine Session With AppleScript as a Mac TIL 2025-01-05 19:03:26 -06:00
jbranchaud
1cf67b8f1a Add Configure Max String Print Length For Delve as a Go TIL 2025-01-04 13:07:13 -06:00
jbranchaud
f9c0a566eb Add See Where asdf Gets Current Tool Version as a Unix TIL 2025-01-03 12:11:02 -06:00
jbranchaud
527038ca23 Fix TIL count, it was off by 1 2025-01-02 13:58:26 -06:00
jbranchaud
b972673008 Add Simon Willison's TIL to list of other TILs 2025-01-02 13:54:50 -06:00
jbranchaud
cc31aae25a Update copyright date to 2025, time flies 2025-01-02 13:52:57 -06:00
jbranchaud
26f30c3225 Update README with a few learning resource links 2025-01-02 13:52:24 -06:00
jbranchaud
e14da2f207 Add Basic Delve Debugging Session as a Go TIL 2025-01-02 13:45:16 -06:00
jbranchaud
b7d4a62ecb Add Refer To Implicit Block Argument With It as a Ruby TIL 2025-01-01 12:16:53 -06:00
jbranchaud
1ad41b9776 Add Connect To A SQLite Database as a Go TIL 2024-12-31 10:48:01 -06:00
jbranchaud
11716a8fb5 Add Install Latest Version Of Ruby With asdf as a Ruby TIL 2024-12-30 19:20:33 -07:00
jbranchaud
5e19d53382 Add Pass A Struct To A Function as a Go TIL 2024-12-29 10:26:55 -07:00
jbranchaud
c8aa6ee506 Add Break Justfile Into Separate Hidden Steps as a Workflow TIL 2024-12-28 09:20:00 -07:00
jbranchaud
9c0c9222f9 Add Create A Slice From An Array as a Go TIL 2024-12-26 09:47:12 -07:00
jbranchaud
855251e478 Add Clamp To An Endless Range as a Ruby TIL 2024-12-25 22:07:58 -07:00
jbranchaud
4e5ba0ce4c Add Write A Custom Scan Function For File IO as a Go TIL 2024-12-24 11:12:32 -06:00
jbranchaud
63a92cbc29 Add Use External Diff Tool Like Difftastic as a Git TIL 2024-12-23 15:41:11 -06:00
jbranchaud
8438025005 Add Deterministically Seed A Random Number Generator as a Go TIL 2024-12-22 15:04:31 -06:00
jbranchaud
a3be570a32 Add Show Linting Errors In Zed as a Workflow TIL 2024-12-21 19:14:48 -06:00
jbranchaud
464a2af6db Add Produce The Zero Value Of A Generic Type as a Go TIL 2024-12-20 15:19:10 -06:00
jbranchaud
8801f39df0 Add Manually Pass Two Git Files To Delta as a Unix TIL 2024-12-19 18:24:27 -06:00
jbranchaud
aeb55efc3c Add Detect If Stdin Comes From A Redirect as a Go TIL 2024-12-18 11:05:29 -06:00
jbranchaud
a92af09fea Add Explore The Database Schema as a SQLite TIL 2024-12-17 12:28:13 -06:00
jbranchaud
43e6433fd6 Add Check If Cobra Flag Was Set as a Go TIL 2024-12-17 01:08:50 -06:00
jbranchaud
88e675b9a3 Add Better Diffs With Delta as a Git TIL 2024-12-15 18:31:25 -06:00
jbranchaud
f5286c1f41 Add Format Date And Time With Time Constants as a Go TIL 2024-12-14 10:52:36 -06:00
jbranchaud
8787e43458 Add Fix Whitespace Errors Throughout Branch Commits as a Git TIL 2024-12-13 14:32:11 -06:00
jbranchaud
f658a31435 Add Redirect File To Stdin During Delve Debug as a Go TIL 2024-12-12 18:40:23 -06:00
jbranchaud
db00ec69c2 Add Highlight Extra Whitespace In Diff Output as a Git TIL 2024-12-11 18:43:08 -06:00
jbranchaud
7274b3d563 Add Sort Slice In Ascending Or Descending Order as a Go TIL 2024-12-10 11:54:04 -06:00
jbranchaud
1c9e12b96f Add Disable Interpolation For A Heredoc String as a Ruby TIL 2024-12-09 22:11:08 -06:00
jbranchaud
a8ba753c92 Add Add A Method To A Struct as a Go TIL 2024-12-08 19:10:14 -06:00
jbranchaud
77f3c6a43d Add Synchronize Vim Clipboard With System Clipboad as a VSCode TIL 2024-12-07 10:18:29 -06:00
jbranchaud
bf6a10e2cd Add Combine Two Slices as a Go TIL 2024-12-06 14:45:33 -06:00
jbranchaud
5083c8e9f1 Add Output Explain Query Plan In Different Formats as a Postgres TIL 2024-12-05 20:50:35 -06:00
jbranchaud
a4c67c33a3 Add List TXT DNS Records For A Domain as a Unix TIL 2024-12-05 18:01:18 -06:00
jbranchaud
dce54bd689 Fix codeblock in recent TIL 2024-12-04 17:20:38 -06:00
jbranchaud
f1cc33fe40 Add Parse Flags From CLI Arguments as a Go TIL 2024-12-04 15:38:02 -06:00
jbranchaud
9dcd9daf0a Add Verify Site Ownership With DNS Record as internet TIL 2024-12-03 12:46:02 -06:00
jbranchaud
9afe6503ec Add Fetch Specific Number Of Results as a Postgres TIL 2024-12-03 08:52:38 -06:00
jbranchaud
b376f32a67 Add Parse A String Into Individual Fields as a Go TIL 2024-12-02 18:49:14 -06:00
jbranchaud
3abfa92b64 Add Write System Clipboard To A File as a Mac TIL 2024-12-01 09:58:15 -06:00
jbranchaud
d086d3b943 Add Find System-wide Config File For User as a jj TIL 2024-11-30 14:38:52 -06:00
jbranchaud
f64257f02c Add Organize Pages In Route Groups as a Next.js TIL 2024-11-29 12:21:50 -06:00
jbranchaud
b329d36888 Add Block Syntaxes Have Different Precedence as a Ruby TIL 2024-11-28 14:06:07 -06:00
jbranchaud
e0db60f6ce Add Colocate jj And git Directories For Project as a jj TIL 2024-11-27 08:41:23 -06:00
jbranchaud
5c81ddc151 Add Type Fewer Paths With Brace Expansion as a Unix TIL 2024-11-26 17:55:12 -06:00
jbranchaud
6af86bd407 Add Stack Heredocs In A Method Call as a Ruby TIL 2024-11-25 16:00:16 -06:00
jbranchaud
98d8249cf1 Add Get Latest Commit Timestamp For A File as a Git TIL 2024-11-24 23:37:16 -06:00
jbranchaud
7f1c243310 Add Gather Positional Arguments In Method Definition as a Ruby TIL 2024-11-23 10:11:49 -06:00
jbranchaud
4f2399de13 Add Useful ActiveSupport Constants For Durations as a Rails TIL 2024-11-22 09:45:20 -06:00
jbranchaud
7573119c59 Add Allow Key-Repeating With Cursor as a Workflow TIL 2024-11-21 11:11:17 -06:00
jbranchaud
86972f41cc Add Set Default As SQL Function In Migration as a Rails TIL 2024-11-20 10:10:04 -06:00
jbranchaud
93a663cc9c Adjust formatting, add source link to pg TIL 2024-11-20 09:32:45 -06:00
jbranchaud
0c1dd29d8d Add Output Bytecode For A Ruby Program as a Ruby TIL 2024-11-18 11:22:35 -06:00
jbranchaud
b492a9d765 Add Override The Boolean Context Of A Class as a Python TIL 2024-11-17 09:44:55 -06:00
jbranchaud
543a82730d Add Forward All Arguments To Another Method as a Ruby TIL 2024-11-16 12:32:21 -06:00
jbranchaud
877537228f Add Gracefully Exit A Script With Trap as a Unix TIL 2024-11-15 19:55:22 -06:00
jbranchaud
1513611857 Add Execute Several Commands With Backtick Heredoc as a Ruby TIL 2024-11-14 23:47:07 -06:00
jbranchaud
74514b462d Add a caveat to the latest TIL 2024-11-13 20:31:25 -06:00
jbranchaud
484dec8e24 Add Empty find_by Returns First Record as a Rails TIL 2024-11-13 20:24:59 -06:00
jbranchaud
8574113dc6 Add Dunder Methods as a Python TIL 2024-11-12 17:45:53 -06:00
jbranchaud
1c4e37ed8a Add Count All Files Of Specific Type Tracked By Git as a Git TIL 2024-11-11 20:15:43 -06:00
jbranchaud
581aa1decb Add Add Line Numbers To A Code Block With Counter as a CSS TIL 2024-11-10 12:43:41 -06:00
jbranchaud
0c4795c1d2 Change codeblock language to ruby in latest TIL 2024-11-09 17:48:32 -06:00
jbranchaud
9bbde247a5 Add Create Table With bigint Id As Primary Key as a Rails TIL 2024-11-09 17:28:47 -06:00
jbranchaud
36ca71bfb1 Add Store And Access Immutable Data In A Tuple as a Python TIL 2024-11-08 09:16:45 -06:00
jbranchaud
8a682e3a89 Add Open New Splits To The Current Directory as a tmux TIL 2024-11-07 09:43:46 -06:00
jbranchaud
c7a38c8267 Add Ignore All Errors In A TypeScript File as a TypeScript TIL 2024-11-06 10:18:44 -06:00
jbranchaud
71d3e56b3d Add Styled Alerts To GitHub Markdown Documents as an Internet TIL 2024-11-05 12:44:14 -06:00
jbranchaud
af3974d3fe Add Do Something N Times as a Go TIL 2024-11-05 11:53:23 -06:00
jbranchaud
adc6b2e903 Add Digraph Unicode Characters Have A Titlecase as a Internet TIL 2024-11-04 08:18:52 -06:00
jbranchaud
9a6ebd4c6b Add Table Names Are Treated As Lower-Case By Default as a Postgres TIL 2024-11-03 23:19:17 -06:00
jbranchaud
6df0693804 Add a few more notes to the latest TIL 2024-11-02 13:47:16 -05:00
jbranchaud
507602ef0c Add Prefer select_all Over execute For Read Queries as a Rails TIL 2024-11-02 13:29:54 -05:00
jbranchaud
18bdcc88b8 Add example of output to latest TIL 2024-11-01 14:42:07 -05:00
jbranchaud
95115c7ebc Add Generate Random Alphanumeric Identifier as a Postgres TIL 2024-11-01 12:46:18 -05:00
jbranchaud
4e859b93d2 Add a clarification to the latest TIL 2024-10-31 20:01:26 -05:00
jbranchaud
23c20e99bf Add Undo Changes Made To Current Terminal Prompt as a Unix TIL 2024-10-31 19:57:05 -05:00
jbranchaud
63bb627716 Add Prevent Hidden Element From Flickering On Load as a JavaScript TIL 2024-10-30 15:11:41 -05:00
jbranchaud
21385f4491 Add Drizzle Tracks Migrations In A Log Table as a Drizzle TIL 2024-10-29 16:18:55 -05:00
jbranchaud
5b47326ab3 Add Get The SHA256 For A File as a Unix TIL 2024-10-29 16:09:58 -05:00
jbranchaud
c16d80fd94 Add Get Fields For Inserted Row as a Drizzle TIL 2024-10-28 15:40:24 -05:00
jbranchaud
edf38308da Add Set DateTime To Include Time Zone In Migrations as a Rails TIL 2024-10-28 11:34:34 -05:00
jbranchaud
dc7159c16c Add a bit more to the latest TIL 2024-10-27 22:45:13 -05:00
jbranchaud
33f780a69f Add Concatenate Strings With A Separator as a Postgres TIL 2024-10-27 22:38:59 -05:00
jbranchaud
dfe9c002ee Add Add Unique Constraint Using Existing Index as a Postgres TIL 2024-10-26 10:03:23 -05:00
jbranchaud
3e34636d80 Add Analyze Your Website Performance as an Internet TIL 2024-10-25 12:38:46 -05:00
jbranchaud
dcef57d344 Add Make Truly Deep Clone With Structured Clone as a JavaScript TIL 2024-10-25 08:36:46 -05:00
jbranchaud
6580393b7a Add Create bigint Identity Column For Primary Key as a Drizzle TIL 2024-10-24 17:39:55 -05:00
jbranchaud
17d7f0933b Add Add Subscriber To Kit Form Via API as a Workflow TIL 2024-10-23 19:12:52 -05:00
jbranchaud
e4abc56f4c Add Add Hotkeys For Specific Raycast Extensions as a Workflow TIL 2024-10-22 14:30:59 -05:00
jbranchaud
43ea7acd74 Add Use A Space To Exclude Command Fromm History as a Zsh TIL 2024-10-21 11:21:21 -05:00
jbranchaud
d7d331b688 Add Put Unique Constraint On Generated Column as a Postgres TIL 2024-10-21 11:04:04 -05:00
jbranchaud
b743dc2ac0 Add Exclude AI Overview From Google Search as an Internet TIL 2024-10-20 19:38:08 -05:00
jbranchaud
4a72c63e42 Add Enforce Uniqueness On Column Expression as a Postgres TIL 2024-10-19 19:13:30 -05:00
jbranchaud
431507fd0e Add Send A Message To A Discord Channel as a Workflow TIL 2024-10-18 17:59:08 -05:00
jbranchaud
fb153f35bf Add Postgre Does Not Support Unsigned Integers as a PostgreSQL TIL 2024-10-18 17:43:46 -05:00
jbranchaud
f4ba6a9ef7 Add Override The Global Git Ignore File as a Git TIL 2024-10-18 15:55:40 -05:00
jbranchaud
0dee39d3c5 Add Configure Email Redirect With Cloudflare as a Workflow TIL 2024-10-17 11:09:04 -05:00
jbranchaud
5ebdd9a1a9 Add Convert JPEG To PNG With ffmpeg as a Unix TIL 2024-10-16 12:43:18 -05:00
jbranchaud
33c5cd748f Fix codeblock example in latest TIL 2024-10-15 15:07:55 -05:00
jbranchaud
ff515c8d6a Add Get URL For GitHub User Profile Photo as a Workflow TIL 2024-10-15 15:07:19 -05:00
jbranchaud
fad36e0691 Add Check How A File Is Being Ignored as a Git TIL 2024-10-15 12:19:55 -05:00
jbranchaud
4d1d8e7134 Add Switch Moving End Of Visual Selection as a Vim TIL 2024-10-14 20:20:41 -05:00
jbranchaud
567637497c Add Ensure Resources Always Get Closed as a Java TIL 2024-10-14 16:04:07 -05:00
jbranchaud
028b76ba6b Add Generate Types For A Content Collection as an Astro TIL 2024-10-13 17:03:25 -05:00
jbranchaud
1934c8f63e Add Make Direnv Less Noisy as a Unix TIL 2024-10-13 16:25:44 -05:00
jbranchaud
e5a003dbaf Add Markdown Files Are Of Type MarkdownInstance as an Astro TIL 2024-10-13 11:46:36 -05:00
jbranchaud
ab9d2b5bf6 Add Check Media Queries From JavaScript as a JavaScript TIL 2024-10-12 12:30:07 -05:00
jbranchaud
aa00c55b06 Add Jump To Problems In The Current File as a VSCode TIL 2024-10-12 10:35:52 -05:00
jbranchaud
cc858382d8 Add Temporarily Turn Off Pending Migrations Error as a Rails TIL 2024-10-11 15:05:31 -05:00
jbranchaud
dbb8c585c1 Add updated note to TIL about godoc 2024-10-11 13:57:47 -05:00
jbranchaud
f25064031f Add Export List Of Everything Installed By Brew as a Brew TIL 2024-10-11 10:57:42 -05:00
jbranchaud
cfbe640eb0 Add Keyboard Shortcuts For Interacting With Text Areas as a Mac TIL 2024-10-10 11:52:22 -05:00
jbranchaud
bf04dfcca5 Add Rollback A Couple Migrations as a Rails TIL 2024-10-09 17:44:45 -05:00
jbranchaud
24b1b02d52 Add Define The Root Path For The App as a Rails TIL 2024-10-09 13:23:09 -05:00
jbranchaud
8ef2cfdc69 Add Prevent erb_lint From Removing Opening Tags as a Ruby TIL 2024-10-09 10:53:39 -05:00
jbranchaud
02086e7115 Add Link A Scalar To An Array as a Zsh TIL 2024-10-07 18:51:57 -05:00
jbranchaud
0ecc41bd29 Add Add To The Path Via Path Array as a Zsh TIL 2024-10-07 18:37:23 -05:00
jbranchaud
569220e734 Add Find Any Dotfiles That Modify Path Env Var as a Unix TIL 2024-10-07 13:44:21 -05:00
jbranchaud
594ec08636 Add Download A File With Curl as a Unix TIL 2024-10-04 12:46:21 -05:00
jbranchaud
475f125f4b Add List Running Docker Containers as a Docker TIL 2024-10-03 11:38:13 -05:00
jbranchaud
ba6492d46e Add Run A Hello World Program In Eclipse as a Java TIL 2024-10-02 21:22:43 -05:00
jbranchaud
3ac3014659 Add table of contents entry for Java 2024-10-02 21:22:23 -05:00
jbranchaud
4b6833c437 Add Install Java On Mac With Brew as a Java TIL 2024-10-01 19:21:14 -05:00
jbranchaud
fc93ecfed4 Add Validate Column Data With Check Constraints as a Rails TIL 2024-09-30 19:50:52 -05:00
jbranchaud
a07a19e6d9 Add Generate Modern Primary Key Columns as a Postgres TIL 2024-09-27 09:57:33 -05:00
jbranchaud
951a2f04ad Add Find Executables Installed By Go as a Go TIL 2024-09-26 20:54:41 -05:00
jbranchaud
6b9ec224b8 Add Connect To A Database By Color as a Heroku TIL 2024-09-26 08:47:31 -05:00
jbranchaud
c33be14ec2 Add Skip The Front Of An Array With Drop as a Ruby TIL 2024-09-25 22:43:04 -05:00
jbranchaud
2922bbdd6a Add Check Network Quality Stats From The Command Line as a Mac TIL 2024-09-24 11:08:38 -05:00
jbranchaud
2e72ec1160 Add Generate A Model as a Rails TIL 2024-09-20 20:54:52 -05:00
jbranchaud
baab5738e7 Add Convert SVG To Favicon as a Unix TIL 2024-09-15 12:24:18 -05:00
jbranchaud
191c9d6d9d Add Generate A Rails App From The Main Branch as a Rails TIL 2024-09-09 11:57:10 -05:00
jbranchaud
25b5677260 Add Open Dashboard For Specific Add-On as Heroku TIL 2024-08-23 13:29:47 -05:00
jbranchaud
df3492d4ef Add Configure Tests To Run In Random Order as an RSpec TIL 2024-08-22 11:19:50 -05:00
jbranchaud
bd49b31bb0 Add Multi-Line Comments as a Ruby TIL 2024-08-22 11:12:28 -05:00
jbranchaud
4ff1a381d1 Add Avoid Accidentally Disabling Pry as an rspec TIL 2024-08-14 10:09:07 -05:00
jbranchaud
0bfeb0e236 Add Avoid Conflicting Files as a Next.js TIL 2024-07-16 10:43:03 -05:00
jbranchaud
e91b163571 Add Echo A Message From A SQL File as a MySQL TIL 2024-05-31 10:07:23 -05:00
jbranchaud
84e2c9c6f4 Add Override Table Name For Prisma Model as a Prisma TIL 2024-05-20 09:05:44 -05:00
jbranchaud
39614e975e Add Find Top-Level Directories Matching A Pattern as a Unix TIL 2024-05-19 10:08:45 -05:00
jbranchaud
44e626a086 Add source link for latest TIL 2024-05-16 14:50:34 -05:00
jbranchaud
48d2ecffa0 Add Get Row Count For Most Recent Query as a Postgres TIL 2024-05-16 14:49:37 -05:00
jbranchaud
6fb3b95ade Add Check If Database And Schema Are Not In Sync as a Prisma TIL 2024-05-15 12:21:38 -05:00
jbranchaud
51880975d4 Add Set Value On Null JSON Column as a MySQL TIL 2024-05-14 11:01:17 -05:00
jbranchaud
03980ab291 Add Format Time Zone Identifier as a JavaScript TIL 2024-05-13 12:59:15 -05:00
jbranchaud
bef492fe3a Add Generate Base64 Encoding Without Newlines as a Unix TIL 2024-05-05 11:39:10 -05:00
jbranchaud
36004e6d20 Add Remove Untracked Files From A Directory as a Git TIL 2024-05-03 10:11:00 -05:00
jbranchaud
18e52b9dbb Add Get A List Of Locales On Your System as a Unix TIL 2024-05-02 14:31:01 -05:00
jbranchaud
01c9c0d19b Add Add Only Tracked Files From A Directory as a Git TIL 2024-05-01 09:31:52 -05:00
jbranchaud
c06bb2ea7b Add Find The Location Of User Settings JSON File as a VSCode TIL 2024-04-28 20:28:57 -05:00
jbranchaud
7dad6508d0 Fix typo in code snippet for latest TIL 2024-04-27 23:00:38 -05:00
jbranchaud
5bcdbbb3c7 Add Include Columns In A Covering Index as a Postgres TIL 2024-04-27 22:48:32 -05:00
jbranchaud
41f5b526d2 Add Ensure Lookup Can Be Retried as an Inngest TIL 2024-04-26 23:26:51 -05:00
jbranchaud
e974a184c6 Add Check If Clusters Are Upgrade Compatible as a Postgres TIL 2024-04-25 20:25:48 -05:00
jbranchaud
c832b9a70d Add Look Up Time Zone Info For Identifier as a Rails TIL 2024-04-25 10:50:49 -05:00
jbranchaud
42854fdc38 Add Create A Cluster In A Specific Data Directory as a Postgres TIL 2024-04-23 18:04:45 -05:00
jbranchaud
eff2c548cd Add List All Services Managed By Brew as a Brew TIL 2024-04-23 15:41:01 -05:00
jbranchaud
1b229b39f1 Add Use The llm CLI With Claude Models as an LLM TIL 2024-04-22 20:54:58 -05:00
jbranchaud
2543651ec0 Add Use pipx To Install End User Apps as a Python TIL 2024-04-22 19:47:09 -05:00
jbranchaud
f3d7cf8a06 Add Access 1Password Credential From CLI as a Workflow TIL 2024-04-21 19:57:10 -05:00
jbranchaud
72089e11db Add Send cURL To Claude Text Completion API as an LLM TIL 2024-04-21 19:06:13 -05:00
jbranchaud
b766f20012 Add Define Multiline Strings With Heredocs as a Ruby TIL 2024-04-21 13:46:04 -05:00
jbranchaud
505220d9de Add Convert Seconds To Date Object as a JavaScript TIL 2024-04-19 14:38:40 -05:00
jbranchaud
9684c6a6db Add Get Formatted UTC Offset Value as a Rails TIL 2024-04-18 14:32:46 -05:00
jbranchaud
3b0d76e805 Add Get UTC Offset For Different Time Zones as a Ruby TIL 2024-04-18 10:49:29 -05:00
jbranchaud
b6c8192a04 Add Make Elements Non-Interactive With Inert as an HTML TIL 2024-04-12 11:54:52 -06:00
jbranchaud
c2f30615c3 Add Print DateTime Represented By Unix Timestamp as a Unix TIL 2024-04-08 09:24:09 -05:00
jbranchaud
f54eab20e7 Add Unrestrict Where ripgrep Searches as a Unix TIL 2024-04-04 13:24:51 -05:00
jbranchaud
b2ddce62fd Add Audit Your Ruby Project For Any CVEs as a Ruby TIL 2024-04-02 11:08:37 -05:00
jbranchaud
63a57c6bdd Add Turn Off Display Of Tabs For Files as a VS Code TIL 2024-03-28 20:01:32 -05:00
jbranchaud
87d116a4cd Add List Files In A Single Column as a Unix TIL 2024-03-27 17:21:54 -05:00
jbranchaud
71598d647b Add Add Subtitles To Existing Mux Video Asset as a Workflow TIL 2024-03-20 10:48:20 -05:00
jbranchaud
11859a096f Add Precedence Of Dot Env Files as a Next.js TIL 2024-03-18 13:57:33 -05:00
jbranchaud
6096f5af10 Add Format A Hash Into A String Template as a Ruby TIL 2024-03-18 09:34:06 -05:00
jbranchaud
b6e5ea4c03 Add Fetch Does Not Work In API Serverless Function as a Next.js TIL 2024-03-15 15:02:27 -05:00
jbranchaud
74a3dd3c3a Add Include Ignore Files In Ripgrep Search as a Unix TIL 2024-03-14 16:45:22 -05:00
jbranchaud
7208fad280 Add Specify How Random Array Sample Is as a Ruby TIL 2024-03-12 19:07:55 -05:00
jbranchaud
0b994346fe Add Survey Of User-Defined Ordering Of Records as a Postgres TIL 2024-03-11 10:45:41 -05:00
jbranchaud
daa0590684 Add Run A Basic PostgreSQL Server In Docker as a Docker TIL 2024-03-10 13:29:25 -05:00
jbranchaud
2d10ade553 Add Apply Tailwind Classes To Existing CSS Class as a Tailwind TIL 2024-03-10 13:13:01 -05:00
jbranchaud
d1f83edea7 Add Run A Bash Script From A Node Script as a JavaScript TIL 2024-03-08 18:17:43 -06:00
jbranchaud
a05840633f Add Run SQL Against Remote Postgres Database as a Heroku TIL 2024-03-07 17:25:29 -06:00
jbranchaud
22fde22447 Add Get A Slice Of The Ends Of An Array as a jq TIL 2024-03-07 10:59:20 -06:00
jbranchaud
c4e349f518 Add See Overlaps For A Set Of Time Zones as a Workflow TIL 2024-03-05 19:26:48 -06:00
jbranchaud
1b10e393d9 Add Configure Brew Environment Variables as a Brew TIL 2024-03-04 11:12:32 -06:00
jbranchaud
c20d19b024 Add Tell direnv To Load The Env File as a Unix TIL 2024-03-03 20:34:09 -06:00
jbranchaud
8394d5bfaa Add Show Description Of All npm Config Options as a JavaScript TIL 2024-03-02 09:46:39 -06:00
jbranchaud
5412e2e8b1 Add Connect To A Database In Safe Update Mode as a MySQL TIL 2024-03-01 17:20:10 -06:00
jbranchaud
18f3159626 Add View The Source For A Brew Formula as a Unix TIL 2024-02-29 19:42:09 -06:00
jbranchaud
b3eb0f34d1 Add Interactively Switch asdf Package Versions as a Unix TIL 2024-02-29 15:21:05 -06:00
jbranchaud
9a9cebaa11 Add Open Global npm Config File as a JavaScript TIL 2024-02-28 12:40:48 -06:00
jbranchaud
24278989d8 Add Get Readable Errors From Schema Parse as a Zod TIL 2024-02-27 19:47:32 -06:00
jbranchaud
d0690a3b5a Add Check Connected Stripe Account Name as a Unix TIL 2024-02-26 15:15:43 -06:00
jbranchaud
00d614a106 Add Load And Use Env Var In Node Script as a JavaScript TIL 2024-02-25 21:48:30 -06:00
jbranchaud
cc1275aec5 Add an additional note to the latest TIL 2024-02-25 11:41:52 -06:00
jbranchaud
9a237572aa Add Trigger Commands From The Devtools Command Palette as a Chrome TIL 2024-02-25 11:39:50 -06:00
jbranchaud
5e68fb8c64 Add Interactively Checkout Specific Files From A Stash as a Git TIL 2024-02-24 17:47:19 -06:00
jbranchaud
a83ce7cc10 Add Set Path Alias For Cleaner Imports as a TypeScript TIL 2024-02-24 14:54:18 -06:00
jbranchaud
a61a22f707 Add Configure Different Host And Container Ports as a Docker TIL 2024-02-24 12:44:23 -06:00
jbranchaud
fe8d06b94a Add Pop Open The Quick Fix Window as a VS Code TIL 2024-02-24 11:29:24 -06:00
jbranchaud
80eff6f897 Add Alter The Rails Setup Script as a Rails TIL 2024-02-22 22:54:40 -06:00
jbranchaud
d5470db75b Add attribution to the latest TIL 2024-02-21 13:20:49 -06:00
jbranchaud
5a3ef11820 Add Turn Off npm Funding Message as a JavaScript TIL 2024-02-21 13:18:51 -06:00
jbranchaud
57eb2d73ae Add Run Statements In A Transaction as a MySQL TIL 2024-02-20 17:22:02 -06:00
jbranchaud
613f1f8e37 Add Extend Git With Custom Commands as a git TIL 2024-02-19 18:04:45 -06:00
jbranchaud
e86c36eff4 Add Manage Major Versions With Brew And Direnv as a Postgres TIL 2024-02-18 13:06:55 -06:00
jbranchaud
4e4b9b3d25 Add Run Commands With Specific Rails Version as a Rails TIL 2024-02-17 07:38:40 -06:00
jbranchaud
030a3f9791 Add Search For Homebrew Packages To Install as a Unix TIL 2024-02-16 23:38:21 -06:00
jbranchaud
d02d6e006b Add Select A Specific Rails Version To Install as a Rails TIL 2024-02-16 19:56:38 -06:00
jbranchaud
8100432fad Add Step Through Project-Wide Search Results as a VS Code TIL 2024-02-01 14:37:24 -06:00
jbranchaud
f6882f9fec Add Match Middleware On Groups Of Paths as a Next.js TIL 2024-01-27 17:25:12 -06:00
jbranchaud
11d32fad0d Update an old SSH TIL with a link to details 2024-01-23 11:41:25 -06:00
jbranchaud
63097d0feb Add Get The Last Item From An Array as a jq TIL 2024-01-14 14:34:35 -06:00
jbranchaud
83fddacd29 Add Short Circuit Concurrently When Process Fails as a JavaScript TIL 2024-01-04 10:53:16 -06:00
jbranchaud
bf814b4833 Add Exit Function Early Without Retries as an Inngest TIL 2024-01-02 11:42:22 -06:00
jbranchaud
0c8cb341d6 Add Set Custom Error Message For Nonempty Array as a Zod TIL 2023-12-28 08:53:09 -07:00
jbranchaud
5f20cd569e Add Run Multiple Node Scripts Concurrently as a JavaScript TIL 2023-12-22 10:20:03 -06:00
jbranchaud
678f327cb9 Add Redirect An Unauthorized User as a Next.js TIL 2023-12-21 09:48:37 -06:00
jbranchaud
ff2f3635cb Add Select Rows After An Offset as a MySQL TIL 2023-12-11 12:50:25 -06:00
jbranchaud
fefada8de8 Add Sum A Bunch Of Numbers In The Current File as a Vim TIL 2023-12-07 14:12:45 -06:00
jbranchaud
dd13203ade Add Progress Reporting To Long Running Script as a Ruby TIL 2023-12-05 16:28:05 -06:00
jbranchaud
c591565058 Add Adjust The Shape Of The User Type as a NextAuth TIL 2023-12-04 09:38:30 -06:00
jbranchaud
851af3776d Add Display Results In Readable Column Format as a SQLite TIL 2023-12-02 22:16:14 -06:00
jbranchaud
6f2ae93e45 Add Create An Index Across Two Columns as a Postgres TIL 2023-11-29 16:23:24 -06:00
jbranchaud
f03bf4cb70 Add Zip Two JSON Files Together Based On Shared ID as a jq TIL 2023-11-28 16:16:50 -06:00
jbranchaud
4edc43e4bb Add Print Data To Formatted Table as a Ruby TIL 2023-11-28 12:01:38 -06:00
jbranchaud
5bcd67946c Add Filter Out Results Based On List Of Values as a jq TIL 2023-11-27 17:46:42 -06:00
jbranchaud
778555636e Add Add A Database Index If It Does Not Already Exist as a Rails TIL 2023-11-14 11:22:25 -06:00
jbranchaud
b1994cfe21 Add a bit more detail to latest TIL 2023-11-09 10:12:49 -06:00
jbranchaud
52d31fa41b Add Configure Client To Log SQL Queries as a Prisma TIL 2023-11-09 10:09:56 -06:00
jbranchaud
8789d89e31 Add Add Item To An Array Of References In Sanity as a JavaScript TIL 2023-11-03 10:59:04 -05:00
jbranchaud
5d61f4c9d7 Add Keep File Locally With git rm as a Git TIL 2023-10-27 12:04:48 -05:00
jbranchaud
5811268d3f Add Create A Local Sanity Dataset Backup as a Workflow TIL 2023-10-25 11:15:54 -05:00
jbranchaud
d472a900c7 Add Check Your Public IP Address as an Internet TIL 2023-10-20 11:47:18 -05:00
jbranchaud
94afc729f9 Add Generate Random 20-Character Hex String as a Unix TIL 2023-10-12 09:41:08 -05:00
jbranchaud
ee3c671c47 Add Search For Gem Versions Available To Install as a Ruby TIL 2023-10-11 08:53:51 -05:00
jbranchaud
9bcbcbc7c0 Add Turn A List From A Command Into JSON as a jq TIL 2023-10-05 12:50:39 -05:00
jbranchaud
a726b2ec30 Add Count The Lines In A CSV Where A Column Is Empty as a Unix TIL 2023-10-04 15:39:55 -05:00
jbranchaud
7387786343 Add Format Test Results As A JSON File as an RSpec TIL 2023-10-04 09:16:48 -05:00
jbranchaud
5e63e420bc Add Output The Last N Bytes Of A Large File as a Unix TIL 2023-09-19 16:43:16 -05:00
jbranchaud
129cd11940 Add Check The Installed OpenSSL Version as a Unix TIL 2023-09-08 11:34:00 -05:00
jbranchaud
c1d2f64558 Fix lowercasing error in trigger TIL 2023-09-07 12:33:30 -05:00
jbranchaud
62ddc97d1b Add Mock Rails Environment With An Inquiry Instance as a Rails TIL 2023-08-22 14:18:13 -05:00
jbranchaud
2dcb0dd5e1 Add Produce A Lowercase V4 UUID as a Unix TIL 2023-08-19 12:06:50 -05:00
jbranchaud
5f0d29885b Add Make A String Attribute Easy To Inquire About as a Rails TIL 2023-08-17 12:55:56 -05:00
jbranchaud
66fd1e6c19 Add Combine An Array Of Objects Into A Single Object as a jq TIL 2023-08-17 10:14:00 -05:00
jbranchaud
fba4cb171f Add Print Milliseconds In Human-Readable Format as a Unix TIL 2023-08-14 14:57:56 -05:00
jbranchaud
fb33d03d5a Add Use A Trigger To Mirror Inserts To Another Table as a Postgres TIL 2023-08-09 20:28:04 -05:00
jbranchaud
aaa0edee98 Add Change The Owner Of A Sequence as a Postgres TIL 2023-08-09 16:46:16 -05:00
jbranchaud
67e8996f99 Add Look Through All Files That Have Been Git Stashed as a Unix TIL 2023-08-07 12:30:47 -05:00
jbranchaud
a3927ee02e Add Different Ways To Define An Interval as a PostgreSQL TIL 2023-08-04 12:57:03 -05:00
jbranchaud
544d580ede Fix typo in tmux TIL 2023-07-19 09:07:02 -07:00
jbranchaud
6fad82d653 Add xargs Ignores Alias Substitution By Default as a Unix TIL 2023-07-19 09:06:21 -07:00
jbranchaud
cee26f173d Add Format A Decimal To A Fixed Number Of Digits as a JavaScript TIL 2023-07-17 16:27:01 -05:00
jbranchaud
5cb7d74933 Add Shift The Month On A Date Object as a Ruby TIL 2023-07-13 13:45:11 -05:00
jbranchaud
127329e22c Add Use Variables In An Anonymous Function as a Postgres TIL 2023-07-08 10:11:46 -05:00
jbranchaud
5a8b381de8 Add xargs Default Command Is echo as a Unix TIL 2023-07-07 10:11:29 -05:00
jbranchaud
32706827e9 Add Parse Request Params In Rack::Attack Block as a Rails TIL 2023-07-06 13:41:14 -05:00
jbranchaud
5445916004 Add Run A cURL Command Without The Progress Meter as a Unix TIL 2023-06-28 12:03:29 -05:00
jbranchaud
ccc047549b Update source links in latest TIL 2023-06-27 10:34:08 -05:00
jbranchaud
cc2d84ac19 Add Ignore Duplicates When Inserting Records as a MySQL TIL 2023-06-27 10:21:56 -05:00
jbranchaud
c185ac18c5 Add Find Occurrences Of Multiple Values With Ripgrep as a Unix TIL 2023-06-23 15:16:55 -05:00
jbranchaud
3c7899c67d Add Disable A Workflow With The gh CLI as a GitHub Actions TIL 2023-06-23 13:57:28 -05:00
jbranchaud
570dbdb745 Add Ensure Record Saved With after_commit Callback as a Rails TIL 2023-06-22 13:37:37 -05:00
jbranchaud
b3a6c52c24 Add Trigger A Workflow Via An API Call as a GitHub Actions TIL 2023-06-20 13:40:47 -04:00
jbranchaud
dcdfae4a1e Add Find All Files With A Specific Extension With fd as a Unix TIL 2023-06-19 13:01:29 -04:00
jbranchaud
7da6d33f9d Add a couple links to the latest TIL 2023-06-15 15:02:05 -05:00
jbranchaud
72e3d551f3 Add Generate An Initial tsconfig File as a TypeScript TIL 2023-06-15 15:00:34 -05:00
jbranchaud
6f99af3ec5 Add Tell Node To Treat JS Files As ESM as a JavaScript TIL 2023-06-15 13:44:58 -05:00
jbranchaud
4840461afa Add Load Env Vars In Bash Script as a Unix TIL 2023-06-15 10:47:10 -05:00
jbranchaud
fa20b1aa66 Add Cache Playwright Dependencies Across Workflows as a GitHub Actions TIL 2023-06-14 16:40:23 -05:00
jbranchaud
00481bb71a Add Get The Time Components Of A Date as a JavaScript TIL 2023-06-14 12:50:06 -05:00
jbranchaud
7e2b60e2f9 Add Set Default Branch Name For New Repos as a git TIL 2023-06-12 12:37:33 -05:00
jbranchaud
951b7f953f Add Print The Current Date In Human-Readable Format as a Unix TIL 2023-06-02 11:39:07 -05:00
jbranchaud
c0fdfebc0c Add Open Connections To Multiple Databases as a Prisma TIL 2023-05-31 11:54:44 -05:00
jbranchaud
3cfd11f1e6 Add Batch Insert Records With createMany as a Prisma TIL 2023-05-30 09:53:32 -05:00
jbranchaud
85db06d051 Add Count The Number Of ripgrep Pattern Matches as a Unix TIL 2023-05-24 12:40:49 -05:00
jbranchaud
96d4572786 Add Return The Thing Being Printed as a Ruby TIL 2023-05-19 11:51:36 -05:00
jbranchaud
8bac2d832d Add Find Duplicate Lines In A File as a Unix TIL 2023-05-17 13:57:39 -05:00
jbranchaud
629d8b7f7b Add Replace Pattern Across Many Files In A Project as a Unix TIL 2023-05-12 10:42:13 -05:00
jbranchaud
746957ca75 Add Allow Associations To Be Optional as a Rails TIL 2023-05-09 17:07:08 -05:00
jbranchaud
34b38244c4 Add Params Is A Hash With Indifferent Access as a Rails TIL 2023-05-05 09:25:38 -05:00
jbranchaud
0ec717b64c Add Get The First Item For Every Top-Level Key as a jq TIL 2023-05-03 16:14:08 -05:00
jbranchaud
fd947a5cf1 Add Run A Command Repeatedly Several Times as a Unix TIL 2023-04-30 13:28:20 -05:00
jbranchaud
c2e4a29629 Add Negative Look-Ahead Search With ripgrep as a Unix TIL 2023-04-28 09:04:29 -05:00
jbranchaud
03604ee03a Add Change Base Directory Without Detaching as a tmux TIL 2023-04-12 11:52:53 -05:00
jbranchaud
fd3da2c985 Add List The Installed Version Of A Specific Package as a pnpm TIL 2023-03-29 11:48:13 -05:00
jbranchaud
ab60deea73 Add Check If A URL Resolves To 200 as a Ruby TIL 2023-03-28 11:01:59 -05:00
jbranchaud
10554905ad Add Check SSH Key Fingerprints Of Known Hosts as a Unix TIL 2023-03-27 12:57:45 -05:00
jbranchaud
54b71bbf24 Add Add Generic Typing To An Anonymous Function as a TypeScript TIL 2023-03-08 12:16:14 -06:00
jbranchaud
80f502f661 Add Find All Objects In An Array Where Key Is Set as a jq TIL 2023-03-07 15:10:31 -06:00
jbranchaud
a09ec39aa1 Add Show Used And Available System Memory as a Linux TIL 2023-03-04 09:46:51 -06:00
jbranchaud
5a72dcfb95 Add Fetch Warns About Superseding Block Argument as a Ruby TIL 2023-03-03 10:35:39 -06:00
jbranchaud
12178cf153 Add Count Each Collection In A JSON Object as a jq TIL 2023-02-28 15:28:48 -06:00
jbranchaud
f7313218c1 Add Count The Number Of Things In A JSON File as a jq TIL 2023-02-25 19:16:35 -06:00
jbranchaud
0dda4ab55a Add Get A Quick Approximate Count Of A Large Table as a Rails TIL 2023-02-24 10:10:57 -06:00
jbranchaud
6bc8897e1e Add Write A JavaScript Object To A JSON File as a JavaScript TIL 2023-02-21 12:14:09 -06:00
jbranchaud
fb79ce1f14 Add Review Commits From Before A Certain Date as a Git TIL 2023-02-15 13:22:44 -06:00
jbranchaud
198e40fc01 Add Swap The Position Of Two Split Windows as a Vim TIL 2023-02-03 13:57:11 -06:00
jbranchaud
7212785cb3 Add Ensure A Rake Task Cannot Write Data as a Rails TIL 2023-02-03 10:44:55 -06:00
jbranchaud
ead1ba4c12 Add Ignore A Directory During ripgrep Search as a Unix TIL 2023-02-02 12:54:51 -06:00
jbranchaud
0811ee8c1b Add Different Ways To Generate A v4 UUID as a Unix TIL 2023-01-31 13:41:40 -06:00
jbranchaud
4ee289e41c Add Safely Edit The Sudoers File With Vim as a Unix TIL 2023-01-27 10:32:05 -06:00
jbranchaud
10cc283948 Add Loop Over A List Of Dictionaries as an Ansible TIL 2023-01-26 14:57:23 -06:00
jbranchaud
d7e7350a24 Update link to ansible inventory docs 2023-01-26 14:09:45 -06:00
jbranchaud
9732f5a18a Add Create A Schema That Matches On Any Object as a Zod TIL 2023-01-25 14:02:14 -06:00
jbranchaud
2fcf2829c5 Add Check If File Exists Before Reading It as a JavaScript TIL 2023-01-24 09:54:37 -06:00
jbranchaud
e2cbec17bf Add Find All Objects With A Matching Key Value Pair as a jq TIL 2023-01-20 09:36:08 -06:00
jbranchaud
15dd720cee Add Test For A Subset Of Attributes On A Model as a Rails TIL 2023-01-12 14:51:29 -06:00
jbranchaud
93d5e69f97 Add Reduce Object To Just Entries Of A Specific Type as a jq TIL 2023-01-10 14:28:55 -06:00
jbranchaud
e80721bb6f Add Incorporate Existing Type Into Zod Schema as a Zod TIL 2022-12-22 14:02:32 -06:00
jbranchaud
678a533865 Add Get The Return Type Of An Async Function as a TypeScript TIL 2022-12-17 12:22:07 -06:00
jbranchaud
f8dec09218 Add Globally Install Specific Version Of PNPM as a JavaScript TIL 2022-12-05 13:31:46 -06:00
jbranchaud
d8c280513a Add Split A Float Into Its Integer And Decimal as a Ruby TIL 2022-12-05 09:59:01 -06:00
jbranchaud
16d8ad7849 Add Run Tests With Documentation Formatting as an RSpec TIL 2022-11-10 20:57:16 -06:00
jbranchaud
b589f1ced8 Add Display Titles For Each Pane In A Window as a tmux TIL 2022-11-09 09:27:49 -06:00
jbranchaud
d26be13cd4 Add List autocmds Configured For The Current Buffer as Vim TIL 2022-11-07 09:51:29 -06:00
jbranchaud
b8f8310421 Add Apply Separate Formatting With A Blank Line as a Prisma TIL 2022-11-06 12:32:02 -06:00
jbranchaud
55ee820786 Add Dump And Restore With A Single gzip File as a MongoDB TIL 2022-11-05 15:33:18 -05:00
jbranchaud
06b0db1209 Add Check If User Role Exists For Database as a Postgres TIL 2022-11-03 19:57:02 -05:00
jbranchaud
29656fd7d6 Add Create A Non-Empty Array Type as a TypeScript TIL 2022-10-30 21:57:17 -05:00
jbranchaud
a92b6a3848 Move Check If An Object Is Empty With Zod to Zod section 2022-10-28 18:36:16 -05:00
jbranchaud
e7457a9e54 Add Why Redirect And Return In Controllers as a Rails TIL 2022-10-28 18:30:50 -05:00
jbranchaud
117856c2aa Add Precedence Of Logical Operators as a Ruby TIL 2022-10-24 20:05:23 -05:00
jbranchaud
542ff35250 Add Run A Lua Statement From The Command Prompt as a Neovim TIL 2022-10-22 12:37:18 -05:00
jbranchaud
9e13593d22 Add Pin Specific pnpm Version For Builds as a Vercel TIL 2022-10-20 21:12:40 -05:00
jbranchaud
02a56c7971 Move Vim-Plug Neovim Setup TIL to Neovim Section 2022-10-20 20:53:44 -05:00
jbranchaud
4dcaa95fae Move Neovim System Clipboard TIL to the Neovim section 2022-10-20 20:52:01 -05:00
473 changed files with 17409 additions and 21 deletions

5
.gitmodules vendored Normal file
View File

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

12
.vimrc
View File

@@ -9,3 +9,15 @@ function! CountTILs()
endfunction
nnoremap <leader>c :call CountTILs()<cr>
augroup DisableMarkdownFormattingForTILReadme
autocmd!
autocmd BufRead ~/code/til/README.md autocmd! Format
augroup END
" local til_readme_group = vim.api.nvim_create_augroup('DisableMarkdownFormattingForTILReadme', { clear = true })
" vim.api.nvim_create_autocmd('BufRead', {
" command = 'autocmd! Format',
" group = til_readme_group,
" pattern = vim.fn.expand '~/code/til/README.md',
" })

571
README.md

File diff suppressed because it is too large Load Diff

79
Taskfile.yml Normal file
View File

@@ -0,0 +1,79 @@
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:
- git submodule update --remote {{.NOTES_DIR}}
- cd {{.NOTES_DIR}} && git checkout main
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:pull:
desc: Pull latest changes (alias for sync)
cmds:
- task notes:sync
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

@@ -0,0 +1,33 @@
# Loop Over A List Of Dictionaries
Ansible's `loop` can iterate over a list of dictionaries in a task. That task
will be evaluated for each `item` in that list. Since each `item` is a
dictonary, we can access the fields on the `item` directory with dot notation —
`item.name`.
Here is what this would look like for a task that is setting up authorized SSH
keys.
```yaml
---
- hosts: all
vars:
dev_users:
- name: alice
ssh_key_url: https://github.com/dev1.keys
- name: bob
ssh_key_url: https://github.com/dev2.keys
tasks:
- name: Set authorized keys taken from url
ansible.posix.authorized_key:
user: "{{ item.name }}"
state: present
key: "{{ item.ssh_key_url }}"
loop: "{{ dev_users }}"
```
Notice the `loop` over the `dev_users` variable gives us access to an `item` in
the task. Because each `item` has a `name` and an `ssh_key_url`, we can access
those fields in the task.
[source](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html#standard-loops)

View File

@@ -0,0 +1,56 @@
# Generate Types For A Content Collection
Let's say I'm using Astro to publish posts via markdown. One of the best ways
to do that is as a _Content Collection_. The posts will live in `src/content`
probably under a `posts` directory. Plus a config file will define the
collection and specify validations for the frontmatter.
```typescript
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const postsCollection = defineCollection({
schema: z.object({
title: z.string(),
description: z.string(),
tags: z.array(z.string())
})
});
export const collections = {
'posts': postsCollection,
};
```
When I first add this to my project and get the collection, it won't know what
the types are.
```astro
---
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const blogEntries = await getCollection("posts");
// ^^^ any
return blogEntries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
---
```
I can tell Astro to generate a fresh set of types for things like content
collections by running the [`astro sync`
command](https://docs.astro.build/en/reference/cli-reference/#astro-sync).
```bash
$ npm run astro sync
```
This updates auto-generated files under the `.astro` directory which get pulled
in to your project's `env.d.ts` file.
All of these types will also be synced anytime I run `astro dev`, `astro
build`, or `astro check`.

View File

@@ -0,0 +1,53 @@
# Markdown Files Are Of Type MarkdownInstance
One of the things Astro excels at is rendering markdown files as HTML pages in
your site. And at some point we'll want to access a listing of those markdown
files in order to do something like display a list of them on an index page.
For that, we'll use
[`Astro.glob()`](https://docs.astro.build/en/reference/api-reference/#astroglob).
```typescript
---
const allPosts = await Astro.glob("../posts/*.md");
---
<ul>
{allPosts.map(post => {
return <Post title={post.frontmatter.title} slug={post.frontmatter.slug} />
})}
</ul>
```
This looks great, but we'll run into a type error on that first line:
`'allPosts' implicitly has type 'any'`. We need to declare the type
of these post instances that are being read-in by Astro.
These are of [type
`MarkdownInstance`](https://docs.astro.build/en/reference/api-reference/#markdown-files).
That's a generic though, so we need to tell it a bit more about the shape of a
post.
```typescript
import type { MarkdownInstance } from "astro";
export type BarePost = {
layout: string;
title: string;
slug: string;
tags: string[];
};
export type Post = MarkdownInstance<BarePost>;
```
We can then update that first line:
```typescript
const allPosts: Post[] = await Astro.glob("../posts/*.md");
```
Alternatively, you can specify the generic on `glob`:
```typescript
const allPosts = await Astro.glob<BarePost>("../posts/*.md");
```

View File

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

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

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

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

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

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

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

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

@@ -0,0 +1,28 @@
# Configure Brew Environment Variables
The `brew` CLI can be configured with a ton of different environment variables.
A full listing of those can be found in the [Environment section of their
docs](https://docs.brew.sh/Manpage#environment).
If you want to change the defaults of any of those values, you can either set
them directly in your environment:
```bash
$ set HOMEBREW_BAT=1
```
Or you can set them in a more dedicated place like one of Homebrew's
environment files. There are a couple possible locations for these files. I
prefer to use `$HOME/.homebrew/brew.env` (i.e. `~/.homebrew/brew.env`).
```
HOMEBREW_BAT=1
```
This file and directly likely don't exist, so you may have to set them up the
first time:
```
$ mkdir $HOME/.homebrew
$ touch $HOME/.homebrew/brew.env
```

View File

@@ -0,0 +1,48 @@
# Export List Of Everything Installed By Brew
If you're on a Mac using Homebrew to install various tools and utilities, there
may come a time when you want a listing of what is installed.
Run this command:
```bash
$ brew bundle dump
```
It may take 10 or so seconds. When it is done, you'll have a `Brewfile` in your
current directory.
Open it up and you'll see a bunch of lines like the following:
```
tap "heroku/brew"
tap "homebrew/bundle"
tap "homebrew/services"
tap "mongodb/brew"
tap "planetscale/tap"
tap "stripe/stripe-cli"
brew "asdf"
brew "bat"
brew "direnv"
brew "entr"
brew "exa"
brew "fd"
brew "ffmpeg"
brew "fx"
brew "fzf"
brew "gcc"
brew "gh"
brew "planetscale/tap/pscale"
brew "stripe/stripe-cli/stripe"
cask "1password-cli"
vscode "ms-playwright.playwright"
vscode "ms-vsliveshare.vsliveshare"
vscode "prisma.prisma"
```
Notice there are `tap`, `brew`, `cask`, and even `vscode` directives.
This is a file you could export and then run on a 'new' machine to install all
the programs you're used to having available on your current machine.
[source](https://danmunoz.com/setting-up-a-new-computer-with-homebrew/)

View File

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

@@ -0,0 +1,28 @@
# List All Services Managed By Brew
Daemonized services, such as PostgreSQL, can be installed and managed with
Homebrew. Under the hood `brew` uses `launchctl` on Mac to manage these
services — i.e. starting, restarting, and stopping them.
Assuming you've already installed some services, you can run `brew services
list` to see what services there are and what their current status is.
```bash
$ brew services list
Name Status User File
mailhog none
mysql none
postgresql@11 started jbranchaud ~/Library/LaunchAgents/homebrew.mxcl.postgresql@11.plist
postgresql@13 none
postgresql@16 none
unbound none
```
This is the default behavior if you just run `brew services` without a subcommand.
This is helpful if you are, for instance, trying to see which PostgreSQL server
version you are currently running and which other ones are available to run. I
might then issue a `stop` to `postgresql@11` so that I can then `start` the
`postgresql@16` service.
See `brew services --help` for more details.

View File

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

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

@@ -0,0 +1,25 @@
# Trigger Commands From The Devtools Command Palette
There are a ton of tabs, drop downs, and nested menus in Chrome's devtools. If
I know what I am looking for, that is great, I can navigate to it without much
trouble. But for other features and commands, I'm stumped and can end up
spending minutes looking around.
For example, where is the option to 'Disable JavaScript'?
I don't know. And I don't need to know.
Instead of searching around for it, I can pop open the devtools _command
palette_ with `cmd+shift+p`. This is a modal menu that prompts me to search for
a command to run. I start typing `disab` and already `Disable JavaScript`
appears as one of the top options. I can select that option and JavaScript will
be disabled.
When I'm ready to turn it back on. I can hit `cmd+shift+p` again and search for
`enab`. The `Enable JavaScript` option appears and I can select it to turn it
back on.
Note: you'll need to have the devtools panel open and your focus will need to
be on it for the keybinding to be picked up.
[source](https://developer.chrome.com/docs/devtools/command-menu)

View File

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

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

@@ -0,0 +1,51 @@
# Add Line Numbers To A Code Block With Counter
The
[`counter`](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_counter_styles/Using_CSS_counters)
feature in CSS is a stateful feature that allows you to increment and display a
number based on elements' locations in the document. This feature is useful for
adding numbers to headings and lists, but it can also be used to add line
numbers to a code block.
We need to initialize the counter to start using it. This will give it a name
and default it to the value 0. We'll tie this to a `pre` tag which wraps our
lines of code.
```css {{ title: 'globals.css' }}
pre.shiki {
counter-reset: line-number;
}
```
Then we need to increment the counter for every line of code that appears in
the code block
```css {{ title: 'globals.css' }}
pre.shiki .line {
counter-increment: line-number;
}
```
Last, we need to display these incrementing `line-number` values _before_ each
line.
```css {{ title: 'globals.css }}
pre.shiki .line:not(:last-of-type)::before {
content: counter(line-number);
/*
* plus any styling and spacing of the numbers
*/
}
```
This essentially attaches an element to the front (`::before`) of the line
whose content is the current value of `line-number`. It is applied to all but
the last `.line` because [shiki](https://shiki.matsu.io/) includes an empty
`.line` at the end.
Here is [the real-world example of
this](https://github.com/pingdotgg/uploadthing/blob/4954c9956c141a25a5405991c34cc5ce8d990085/docs/src/styles/tailwind.css#L13-L37)
that I referenced for this post.
Note: the counter can be incremented, decremented, or even explicitly set to a
specific value.

View File

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

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

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

@@ -19,4 +19,4 @@ host `staging` like so:
staging ansible_host=192.168.1.50
```
[source](http://docs.ansible.com/ansible/intro_inventory.html)
[source](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#inventory-aliases)

View File

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

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

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

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

@@ -0,0 +1,34 @@
# Configure Different Host And Container Ports
A `docker-compose.yml` file that sets up something like a PostgreSQL service
will proxy a port from your host machine to a port on the docker container.
A basic PostgreSQL service will look like this tying `5432` to `5432` under the
`ports` section.
```yaml
version: "3.7"
services:
postgres:
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- "5432:5432"
volumes:
- ./postgres-data:/var/lib/postgresql/data
```
Requests like queries from a `psql` instance that we send to `localhost:5432`
will be proxied to `docker-container:5432`.
Since those numbers are the same on both sides, it's not necessarily clear
which is which. The left is the _host_ and the right is the _container_ --
`[host-port]:[container-port]`.
If you need to use a port other than 5432 on your host machine (e.g. maybe
you're running multiple Postgres servers at once), then you can just change the
port number on the left side. How about `9876:5432`.

View File

@@ -0,0 +1,22 @@
# List Running Docker Containers
The `docker` CLI has a `ps` command that will list all running container by
default.
When I run it, I can see that I have a container running a Postgres database
and another running a MySQL database.
```bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba792e185734 postgres:latest "docker-entrypoint.s…" 12 days ago Up 12 days 0.0.0.0:9876->5432/tcp better_reads-postgres-1
7ca7c1e882e0 mysql:8.0 "docker-entrypoint.s…" 19 months ago Up 8 seconds 33060/tcp, 0.0.0.0:3309->3306/tcp some-app-db-1
```
It lists several pieces of info about the containers: the container id, the
image it is based off, when it was created, the running status, the port
configuration, and the name of the container
If I run `docker ps --help` I can see some additional options. One option is
the `--all` flag which will display all known docker container instead of just
the running ones.

View File

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

@@ -0,0 +1,36 @@
# Run A Basic PostgreSQL Server In Docker
Here is a basic `docker-compose.yml` file for spinning up a Docker container
that runs a PostgreSQL server on port 5432. This is what I use to create a
locally-running PostgreSQL server that lives inside a docker container.
```yaml
version: "3.7"
services:
postgres:
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- "5432:5432"
volumes:
- ./postgres-data:/var/lib/postgresql/data
```
To create the docker container and start it up, run the following command from
the same directory where you put this file:
```bash
$ docker compose up
```
This command knows to look for the `docker-compose.yml` file though you can
always be explicit about the file with the `-f` option.
This configuration points at `postgres:latest` which currently is `16.1`. To
run a different major version, you can change the `image` to something like
`postgres:15`. See [Docker Hub](https://hub.docker.com/_/postgres) for more
options.

View File

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

4
dprint.json Normal file
View File

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

View File

@@ -0,0 +1,48 @@
# Create bigint Identity Column For Primary Key
Using the Drizzle ORM with Postgres, here is how we can create a table that
uses a [`bigint` data
type](https://orm.drizzle.team/docs/column-types/pg#bigint) as a primary key
[identity
column](https://www.postgresql.org/docs/current/ddl-identity-columns.html).
```typescript
import {
pgTable,
bigint,
text,
timestamp,
} from "drizzle-orm/pg-core";
// Users table
export const users = pgTable("users", {
id: bigint({ mode: 'bigint' }).primaryKey().generatedAlwaysAsIdentity(),
email: text("email").unique().notNull(),
name: text("name").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
```
There are a couple key pieces here:
1. We import `bigint` so that we can declare a column of that type.
2. We specify that it is a primary key with `.primaryKey()`.
3. We declare its default value as `generated always as identity` via
`.generatedAlwaysAsIdentity()`.
Note: you need to specify the `mode` for `bigint` or else you will see a
`TypeError: Cannot read properties of undefined (reading 'mode')` error.
If we run `npx drizzle-kit generate` the SQL migration file that gets
generated will contain something like this:
```sql
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "users" (
"id" bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "users_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
"email" text NOT NULL,
"name" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "users_email_unique" UNIQUE("email")
);
```

View File

@@ -0,0 +1,39 @@
# Drizzle Tracks Migrations In A Log Table
When I generate (`npx drizzle-kit generate`) and apply (`npx drizzle-kit
migrate`) schema migrations against my database with Drizzle, there are SQL
files that get created and run.
How does Drizzle know which SQL files have been run and which haven't?
Like many SQL schema migration tools, it uses a table in the database to record
this metadata. Drizzle defaults to calling this table `__drizzle_migrations`
and puts it in the `drizzle` schema (which is like a database namespace).
Let's take a look at this table for a project with two migrations:
```sql
postgres> \d drizzle.__drizzle_migrations
Table "drizzle.__drizzle_migrations"
Column | Type | Collation | Nullable | Default
------------+---------+-----------+----------+----------------------------------------------------------
id | integer | | not null | nextval('drizzle.__drizzle_migrations_id_seq'::regclass)
hash | text | | not null |
created_at | bigint | | |
Indexes:
"__drizzle_migrations_pkey" PRIMARY KEY, btree (id)
postgres> select * from drizzle.__drizzle_migrations;
id | hash | created_at
----+------------------------------------------------------------------+---------------
1 | 8961353bf66f9b3fe1a715f6ea9d9ef2bc65697bb8a5c2569df939a61e72a318 | 1730219291288
2 | b75e61451e2ce37d831608b1bc9231bf3af09e0ab54bf169be117de9d4ff6805 | 1730224013018
(2 rows)
```
Notice that Drizzle stores each migration record as [a SHA256 hash of the
migration
file](https://github.com/drizzle-team/drizzle-orm/blob/526996bd2ea20d5b1a0d65e743b47e23329d441c/drizzle-orm/src/migrator.ts#L52)
and a timestamp of when the migration was run.
[source](https://orm.drizzle.team/docs/drizzle-kit-migrate#applied-migrations-log-in-the-database)

View File

@@ -0,0 +1,56 @@
# Get Fields For Inserted Row
With Drizzle, we can insert a row with a set of values like so:
```typescript
await db
.insert(todoItems)
.values({
title,
userId,
description,
})
```
The result of this is `QueryResult<never>`. In other words, nothing useful is
coming back to us from the database.
Sometimes an insert is treated as a fire-and-forget (as long as it succeeds) or
since we know what data we are inserting, we don't need the database to
response. But what about values that are generated or computed by the database
-- such as an id from a sequence, timestamp columns that default to `now()`, or
generated columns.
To get all the fields of a freshly inserted row, we can tack on [the
`returning()` function](https://orm.drizzle.team/docs/insert#insert-returning)
(which likely adds something like [`returning
*`](https://www.postgresql.org/docs/current/dml-returning.html)) to the insert
query under the hood).
```typescript
await db
.insert(todoItems)
.values({
title,
userId,
description,
})
.returning()
```
This will have a return type of `Array<type todoItems>` which means that for
each inserted row we'll have all the fields (columns) for that row.
Alternatively, if we just need the generated ID for the new row(s), we can use
a partial return like so:
```typescript
await db
.insert(todoItems)
.values({
title,
userId,
description,
})
.returning({ id: todoItems.id })
```

View File

@@ -0,0 +1,26 @@
# Add Only Tracked Files From A Directory
The two extremes of staging files in a git repo are to either selectively pick
each individual chunk of changes with `git add --patch` (my preference!) or to
run `git add -A` to add everything.
Now let's say I have large directory full of files that get generated during
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
test run.
I want to stage the changes to files that are already tracked, but hold off on
doing anything with the new files.
Running `git add spec/cassettes` won't do the trick because that will pull in
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
means it will only stage already tracked files.
```bash
$ git add -u spec/cassettes
```
That will stage every change to any already known files in `spec/cassettes`.
See `man git-add` for more details.

View File

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

@@ -0,0 +1,28 @@
# Check How A File Is Being Ignored
There are a few places on your machine where you can specify the files that git
should ignore. The most common is a repository's `.gitignore` file. The other
places those excludes are specified can be more obscure. Fortunately, `git
check-ignore` is a command that can show you specifically where.
For instance, let's check why my `notes.md` file is being ignored.
```bash
$ git check-ignore -v .DS_Store
.git/info/exclude:7:notes.md notes.md
```
At some point I added it to my repo's `.git/info/exclude` file. The `-v` flag
(_verbose_) when included with `check-ignore` tells me the file location.
How about these pesky `.DS_Store` directories? How are those being ignored?
```bash
$ git check-ignore -v .DS_Store
/Users/jbranchaud/.gitignore:3:.DS_Store .DS_Store
```
Ah yes, I had added it to my _global exclude file_ which I've configured in
`~/.gitconfig` to be the `~/.gitignore` file.
See `man git-check-ignore` for more details.

View File

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

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

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

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

@@ -0,0 +1,27 @@
# Count All Files Of Specific Type Tracked By Git
I want to get a count of all the markdown files in my [TIL
repo](https://github.com/jbranchaud/til). Since all the files I care about are
tracked by `git`, I can use `git ls-files` to get a listing of all files. That
command on its own lists all files tracked by your git repository. Though there
are many other flags we can apply, that will do for my purposes.
By giving `git ls-files` a pattern to match against, I can turn up just, for
instance, markdown files (`*.md`). I can pipe that to `wc -l` to get a count
rather than exploding my terminal with a list of file names.
```bash
git ls-files '*.md' | wc -l
1503
```
That command includes `README.md` and `CONTRIBUTING.md`, but really I only want
to count the markdown files that constitute a TIL. Those all happen to be
nested under a single directory. So I can tweak the glob pattern like so:
```bash
git ls-files '*/*.md' | wc -l
1501
```
See `man git-ls-files` for more details.

View File

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

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

@@ -0,0 +1,26 @@
# Extend Git With Custom Commands
I recently learned about the [`git
absorb`](https://github.com/tummychow/git-absorb) command. It is interesting in
its own right, but I bring it up because it isn't a command that is built in to
git. When I was looking at the installation instructions for it, it didn't say
anything about how to _register_ the command with `git`.
How is git supposed to know about it? How do you extend git with custom
commands?
What I learned exploring those questions is that `git` will execute any command
on your _path_ with a `git-<command>` naming convention.
So, if I create a executable binary called `git-taco`, add it to my path, and
then run `git taco` (notice, no dash when I run it), `git` will run my custom
binary.
In the same way, if you download `git-absorb` and add it to your path, `git`
will run it for you when you enter `git absorb ...`.
You can even type something like `where git-` and then hit tab to prompt your
shell to display a list of a varity of other `git` commands, most of which
probably ship with `git`.
[source](https://twitter.com/jbrancha/status/1756361704160530555)

View File

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

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

@@ -0,0 +1,25 @@
# Get Latest Commit Timestamp For A File
The `git log` command can tell you all the commits that touched a file. That
can be narrowed down to the latest commit for that file with the `-1` flag. The
commit that it reports can then be further formatted to with the `--format`
flag.
The `%ai` format pattern gives the date the commit was authored in an ISO
8601-like format. The `%aI` (capital `I`) gives the date the commit was
authored strictly in the ISO 8601 format.
Here are examples of both side by side:
```bash
git log -1 --format=%ai -- README.md
2024-10-15 13:59:09 -0500
git log -1 --format=%aI -- README.md
2024-10-15T13:59:09-05:00
```
I made use of this in a script where I needed to get an idea of when various
files were most recently modified.
See `man git-log` and the `PRETTY FORMATS` section for more details.

View File

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

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

@@ -0,0 +1,18 @@
# Interactively Checkout Specific Files From A Stash
This command will prompt you with a list of the stashes in your current git
repo. Once you select one of them from the interactive fzf prompt, you will
then be prompted with another fzf prompt, this second one allow multi-select.
From there you can tab select the files you want to checkout. Once you've
marked the ones you want, hit enter and those files will be checked out to your
index.
```bash
git stash show --name-only $(
git stash list \
| fzf --height=20% --reverse \
| sed 's/:.*//'
) \
| fzf --height=20% --multi --sync \
| xargs -I {} sh -c 'git checkout stash@{0} -- {}'
```

View File

@@ -0,0 +1,20 @@
# Keep File Locally With `git rm`
Let's say I've added a new file `data.json` to my repo as part of the most
recent commit. I realize this isn't the point at which I want to add that file.
So, I do `git rm data.json` and then `git commit --amend` to rework that
commit.
However, when I look in my working tree, or even just my file system, I'll
notice that `data.json` is gone. The `git rm` command completely removed the
file since it was previously an untracked file.
To keep `git rm` from tossing out my file like that, I can include the
`--cached` flag which will remove the file from the index (stages it to be
`deleted`), but restore it to the working directory.
```bash
$ git rm --cached data.json
```
See `man git-rm` for more details on the `--cached` flag.

View File

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

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

@@ -0,0 +1,33 @@
# Override The Global Git Ignore File
One of the places that `git` looks when deciding whether to pay attention to or
ignore a file is in your global _ignore_ file. By default, `git` will look for
this file at `$XDG_CONFIG_HOME/git/ignore` or `$HOME/.config/git/ignore`.
I don't have `$XDG_CONFIG_HOME` set on my machine, so it will fall back to the
config directory under `$HOME`.
I may have to create the `git` directory and `ignore` file.
```bash
$ mkdir $HOME/.config/git
$ touch $HOME/.config/git/ignore
```
Then I can add file and directories to exclude to that `ignore` file just like
I would any other `.gitignore` file.
If I'd prefer for the global _ignore_ file to live somewhere else, I can
specify that location and filename in my `$HOME/.gitconfig` file.
```
[core]
excludesFile = ~/.gitignore
```
Setting this will override the default, meaning the default file mentioned
above will be ignored ("now you know how it feels, ignore file!"). In this
case, I'll need to create the `.gitignore` file in my home directory and add
any of my ignore rules.
[source](https://git-scm.com/docs/gitignore)

View File

@@ -0,0 +1,34 @@
# Reference Commits Earlier Than Reflog Remembers
While preparing some stats for a recent blog post on [A Decade of
TILs](https://www.visualmode.dev/a-decade-of-tils), I ran into an issue
referencing 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

@@ -0,0 +1,26 @@
# Remove Untracked Files From A Directory
Let's say I have a directory (`spec/cassettes`) full of a ton of generated YAML
files. Most of these files are tracked by git. However, I just generated a
bunch of new ones that are untracked. For whatever reason, I don't want these
files. I need to delete them.
Running `rm` on each of them is going to be too tedious. And it is tricky to
target them for a bulk delete since there are a ton of other files in that
directory that I want to keep.
One way to approach this is have `git ls-files` help out with listing all files in the
directory that are untracked. The `--others` flag filters to untracked files.
```bash
git ls-files --others --exclude-standard spec/cassettes
```
From there, I can pipe it to `rm` (with `xargs` collapsing all the files into a
single line):
```bash
git ls-files --others --exclude-standard spec/cassettes | xargs rm
```
See `man git-ls-files` for more details.

View File

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

@@ -0,0 +1,28 @@
# Review Commits From Before A Certain Date
I was recently looking at data in a 3rd-party tool and saw that there was a
very distinct shift in what was being recorded a couple years prior on a
specific date. I wanted to see what changes had been made to the codebase a day
or two before the shift.
Rather than scrolling all the way back in `git log`, I can tell `git log` to
show me all commits from before a certain date.
Let's say that date of interest is May 1st, 2021. I can use the `--until` flag
with `git log`. However, I should note that `--until` is an exclusive range, so
I'll need to specify `May 2 2021` if I want to start seeing commits on May 1.
```bash
$ git log --until='May 2 2021'
```
Because `git log` shows commits in reverse chronological order, I'll start
seeing commits from May 1st and then as I scroll, I'll see older and older
commits.
From here I can scan commits messages and look for one that I want to dig into.
I'd then use `git show <sha>` to explore a specific one further.
This is synonymous with `--before`.
See `man git-log` for more details.

View File

@@ -0,0 +1,22 @@
# Set Default Branch Name For New Repos
When you run `git init` in a directory, it will initialize that directory as a
`git` repository. The default branch name for any new git repository is
`master`. A better name for the base branch would be something like `main`.
To set `main` as the new default for all new repos, you can run the following
`git` command.
```bash
$ git config --global init.defaultBranch main
```
This will update your `.gitconfig` file to contain the following lines.
```
[init]
defaultBranch = main
```
Try running `git init` in a fresh directory and then `git branch
--show-current` to see that the base branch is now defaulting to `main`.

View File

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

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

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

@@ -0,0 +1,43 @@
# Cache Playwright Dependencies Across Workflows
With the help of `actions/cache@v3`, I can cache the dependency install and
setup involved with using Playwright in GitHub Actions. That setup, in my
experience, typically takes ~45s. When it is already cached, it is able to skip
that step entirely greatly reducing the overall run time of the script.
First, I need to define a cache (`playwright-cache`). Second, I need to only
install the Playwright dependencies when that cache isn't available (`cache-hit
!= 'true'`).
Here is a striped down workflow demonstrating that.
```yaml
name: Playwright Script
on:
workflow_dispatch:
jobs:
Cached-Playwright-Script:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- uses: actions/cache@v3
id: playwright-cache
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Install playwright deps
run: npx playwright install --with-deps chromium
if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: node playwright-script.js
```
If I add the caching step and the cache-conditional `playwright install` steps
to another workflow in this project, the cache will be available to both of
them. That means they both benefit from the savings of that work having already
been cached.
[source](https://justin.poehnelt.com/posts/caching-playwright-in-github-actions/)

View File

@@ -0,0 +1,41 @@
# Disable A Workflow With The gh CLI
You may want to temporarily disable a GitHub Actions workflow without deleting
the file for the workflow. In my case, this is handy because I want to keep a
scheduled workflow around as a point of reference, but I don't want it running
all the time.
This can be done with [the `workflow` subcommand of the `gh`
CLI](https://docs.github.com/en/actions/using-workflows/disabling-and-enabling-a-workflow?tool=cli).
First, list the workflows for your current repo so that you can figure out the
workflow ID that you want to disable.
```bash
$ gh workflow list
GitHub Actions Demo active 60018591
Playwright Demo active 60142509
Scheduled Actions Demo active 60028624
```
Now, copy the ID of the workflow you want to disable. In my case, it is
`60028624`.
Then, run the `disable` command for that workflow ID:
```bash
$ gh workflow disable 60028624
✓ Disabled Scheduled Actions Demo
```
That workflow is now disabled and it is no longer going to show up in the
default listing of workflows.
If you want to see it in the list though, you can include the `--all` flag.
```bash
$ gh workflow list --all
GitHub Actions Demo active 60018591
Playwright Demo active 60142509
Scheduled Actions Demo disabled_manually 60028624
```

View File

@@ -0,0 +1,37 @@
# Trigger A Workflow Via An API Call
We can set up a GitHub Actions workflow to run when triggered by an API call.
This is done with the [`workflow_dispatch`
event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch).
First, we add `workflow_dispatch` to our workflow as a triggering event:
```yaml
on:
workflow_dispatch:
```
Second, we create a fine-grained personal GitHub access token that has permissions
for dispatching to GitHub Actions. More details on that in the [GitHub
docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token).
Then, we can use `cURL` or some other tool for issuing an HTTP POST request to
[the workflow dispatch API
endpoint](https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event). The `cURL` request will look something like this:
```bash
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <YOUR-TOKEN>"\
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/OWNER/REPO/actions/workflows/WORKFLOW_ID/dispatches \
-d '{"ref":"topic-branch","inputs":{"name":"Mona the Octocat","home":"San Francisco, CA"}}'
```
Note: we need to alter that URL with the `OWNER` and `REPO` that the workflow
lives in as well as the `WORKFLOW_ID` which can be the name of the workflow
file (e.g. `my-dispatchable-workflow.yml`).
This event also means that we can manually trigger the workflow from the
GitHub Actions UI for that workflow.

View File

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

View File

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

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

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

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

@@ -15,4 +15,10 @@ $ godoc -http=:6060
and then visit `localhost:6060`.
Note: if you do not already have `godoc` installed, you can install it with:
```bash
$ go install golang.org/x/tools/cmd/godoc@latest
```
[source](http://www.andybritcliffe.com/post/44610795381/offline-go-lang-documentation)

View File

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

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

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

51
go/combine-two-slices.md Normal file
View File

@@ -0,0 +1,51 @@
# Combine Two Slices
The `append` function can be used to create a new slice with the contents of
the given slice and one or more items added to the end.
We can add one or more items like so:
```go
s1 := []int{1, 2, 3, 4}
s2 := append(s1, 5)
s3 := append(s2, 6, 7, 8)
fmt.Println(s1) //=> [1 2 3 4]
fmt.Println(s2) //=> [1 2 3 4 5]
fmt.Println(s3) //=> [1 2 3 4 5 6 7 8]
```
But what if we have a second slice instead of individual items? We could import
`slices` and use its `Concat` function. Or we can stick with `append` and
unpack that slice as a series of arguments into the second part of `append`
using `slice...`.
```go
s4 := append(s2, s1...)
fmt.Println(s4) //=> [1 2 3 4 5 1 2 3 4]
```
Here is the full example:
```go
package main
import (
"fmt"
)
func main() {
s1 := []int{1, 2, 3, 4}
s2 := append(s1, 5)
s3 := append(s2, 6, 7, 8)
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
s4 := append(s2, s1...)
fmt.Println(s4)
}
```
[source](https://pkg.go.dev/builtin#append)

View File

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

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

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

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

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

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

@@ -0,0 +1,56 @@
# Do Something N Times
With Go 1.23 there is a new for-range syntax that makes looping a bit easier
and more compact.
Instead of needing to set up our 3-part for-loop syntax, we can say we want to
do something `N` times with `for range N`.
```go
for range n {
// do something
}
```
Let's look at an actual, runnable example:
```go
package main
import "fmt"
import "math/rand"
import "time"
func main() {
rand.Seed(time.Now().UnixNano())
food := []string{"taco", "burrito", "torta", "enchilada", "tostada"}
for range 5 {
randomIndex := rand.Intn(len(food))
fmt.Println(food[randomIndex])
}
}
```
The output is random and might look something like this:
```bash
$ go run loop.go
taco
burrito
tostada
taco
enchilada
```
I appreciate this syntax addition because it feels very akin to Ruby's `#times`
method:
```ruby
5.times do
# do something
end
```
[source](https://eli.thegreenplace.net/2024/ranging-over-functions-in-go-123/)

View File

@@ -0,0 +1,26 @@
# Find Executables Installed By Go
When you install an executable using `go install`, it puts that executable in
the `bin` directory designated by the `GOBIN` environment variable. If that env
var isn't set, then it falls back to one of `$GOPATH/bin` or `$HOME/go/bin`.
When I run `go help install`, it tells me as much:
```
Executables are installed in the directory named by the GOBIN environment
variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
environment variable is not set.
```
So, if I am to install something like [`tern`](https://github.com/jackc/tern),
```bash
$ go install github.com/jackc/tern/v2@latest
```
it is going to place that binary in `~/go/bin` for me.
```bash
$ which tern
/Users/jbranchaud/go/bin/tern
```

View File

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

@@ -0,0 +1,39 @@
# Parse A String Into Individual Fields
Let's say you're reading in data from a file or otherwise dealing with an
arbitrary string of data. If that string has a series of values separated by
whitespace, you can parse it into individual fields with
[`strings.Fields`](https://pkg.go.dev/strings#Fields).
```go
import (
"fmt"
"strings"
)
func main() {
data := "3 5 2 6 7 1 9"
fields := strings.Fields(data)
fmt.Printf("Fields: %v", fields)
// [3 5 2 6 7 1 9]
}
```
Here is another example where we can see that `strings.Fields` deals with
multiple whitespace and surrounding whitespace:
```go
import (
"fmt"
"strings"
)
func main() {
data := " go java c++ rust "
fields := strings.Fields(data)
fmt.Printf("%v", fields)
// [go java c++ rust]
}
```

View File

@@ -0,0 +1,65 @@
# Parse Flags From CLI Arguments
Though we can grab the arguments to a Go program from `os.Args`, it requires
some manual parsing. With the built-in `flag` package, we can declare specific
flags our program accepts, by type. When we parse them, they will be separated
out from the rest of the positional arguments.
Here is an example of the program that accepts a boolean `debug` flag. This
will work with either `-debug` or `--debug`.
```go
package main
import (
"flag"
"fmt"
"os"
)
func main() {
var debug bool
flag.BoolVar(&debug, "debug", false, "turns on debug mode, extra logging")
flag.Parse()
positionalArgs := flag.Args()
if len(positionalArgs) < 1 {
fmt.Println("Please specify which part to run: 1 or 2")
os.Exit(1)
}
if debug {
fmt.Println("We are in debug mode...")
fmt.Println("Received the following argument:", positionalArgs[0])
}
// ...
}
```
We can run the program in debug mode like so:
```bash
$ go run . --debug 123
We are in debug mode...
Received the following argument: 123
```
We can also take advantage of the `help` flag that we get for free:
```bash
$ go run . --help
Usage of /var/folders/62/lx9pcjbs1zbd83zg6twwym2r0000gn/T/go-build3212087168/b001/exe/test:
-debug
turns on debug mode, extra logging
```
Note: any recognized flags need to come before any of the position arguments.
The `debug` flag won't be picked up if we run the program like this:
```bash
$ go run . 123 --debug
```
[source](https://pkg.go.dev/flag)

View File

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

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

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

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

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