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

Compare commits

...

10 Commits

Author SHA1 Message Date
Mohammad Alyetama
d03ba56251 Merge bc767a0ad3 into 5e19d53382 2024-12-30 11:55:02 +11: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
Mohammad Alyetama
bc767a0ad3 Update bew cask command 2022-11-24 17:49:13 -05:00
10 changed files with 341 additions and 2 deletions

View File

@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
_1544 TILs and counting..._
_1552 TILs and counting..._
---
@@ -383,6 +383,7 @@ _1544 TILs and counting..._
- [Untrack A Directory Of Files Without Deleting](git/untrack-a-directory-of-files-without-deleting.md)
- [Untrack A File Without Deleting It](git/untrack-a-file-without-deleting-it.md)
- [Update The URL Of A Remote](git/update-the-url-of-a-remote.md)
- [Use External Diff Tool Like Difftastic](git/use-external-diff-tool-like-difftastic.md)
- [Using Commands With A Relative Date Format](git/using-commands-with-a-relative-date-format.md)
- [Verbose Commit Message](git/verbose-commit-message.md)
- [Viewing A File On Another Branch](git/viewing-a-file-on-another-branch.md)
@@ -405,19 +406,23 @@ _1544 TILs and counting..._
- [Build For A Specific OS And Architecture](go/build-for-a-specific-os-and-architecture.md)
- [Check If Cobra Flag Was Set](go/check-if-cobra-flag-was-set.md)
- [Combine Two Slices](go/combine-two-slices.md)
- [Create A Slice From An Array](go/create-a-slice-from-an-array.md)
- [Detect If Stdin Comes From A Redirect](go/detect-if-stdin-comes-from-a-redirect.md)
- [Deterministically Seed A Random Number Generator](go/deterministically-seed-a-random-number-generator.md)
- [Do Something N Times](go/do-something-n-times.md)
- [Find Executables Installed By Go](go/find-executables-installed-by-go.md)
- [Format Date And Time With Time Constants](go/format-date-and-time-with-time-constants.md)
- [Not So Random](go/not-so-random.md)
- [Parse A String Into Individual Fields](go/parse-a-string-into-individual-fields.md)
- [Parse Flags From CLI Arguments](go/parse-flags-from-cli-arguments.md)
- [Pass A Struct To A Function](go/pass-a-struct-to-a-function.md)
- [Produce The Zero Value Of A Generic Type](go/produce-the-zero-value-of-a-generic-type.md)
- [Redirect File To Stdin During Delve Debug](go/redirect-file-to-stdin-during-delve-debug.md)
- [Replace The Current Process With An External Command](go/replace-the-current-process-with-an-external-command.md)
- [Sleep For A Duration](go/sleep-for-a-duration.md)
- [Sort Slice In Ascending Or Descending Order](go/sort-slice-in-ascending-or-descending-order.md)
- [Upgrading From An Older Version On Mac](go/upgrading-from-an-older-version-on-mac.md)
- [Write A Custom Scan Function For File IO](go/write-a-custom-scan-function-for-file-io.md)
### GROQ
@@ -1214,6 +1219,7 @@ _1544 TILs and counting..._
- [Check If A URL Resolves To 200](ruby/check-if-a-url-resolves-to-200.md)
- [Check If An Object Includes A Module](ruby/check-if-an-object-includes-a-module.md)
- [Check Return Status Of Running A Shell Command](ruby/check-return-status-of-running-a-shell-command.md)
- [Clamp To An Endless Range](ruby/clamp-to-an-endless-range.md)
- [Click On Text With Capybara](ruby/click-on-text-with-capybara.md)
- [Colorful Output With MiniTest](ruby/colorful-output-with-minitest.md)
- [Comparing Class Hierarchy Relationships](ruby/comparing-class-hierarchy-relationships.md)
@@ -1780,6 +1786,7 @@ _1544 TILs and counting..._
- [Add Subtitles To Existing Mux Video Asset](workflow/add-subtitles-to-existing-mux-video-asset.md)
- [Access 1Password Credential From CLI](workflow/access-1password-credential-from-cli.md)
- [Allow Key-Repeating With Cursor](workflow/allow-key-repeating-with-cursor.md)
- [Break Justfile Into Separate Hidden Steps](workflow/break-justfile-into-separate-hidden-steps.md)
- [Change Window Name In iTerm](workflow/change-window-name-in-iterm.md)
- [Configure Email Redirect With Cloudflare](workflow/configure-email-redirect-with-cloudflare.md)
- [Convert An ePub Document To PDF On Mac](workflow/convert-an-epub-document-to-pdf-on-mac.md)
@@ -1797,6 +1804,7 @@ _1544 TILs and counting..._
- [See Overlaps For A Set Of Time Zones](workflow/see-overlaps-for-a-set-of-time-zones.md)
- [Send A Message To A Discord Channel](workflow/send-a-message-to-a-discord-channel.md)
- [Set Recurring Reminders In Slack](workflow/set-recurring-reminders-in-slack.md)
- [Show Linting Errors In Zed](workflow/show-linting-errors-in-zed.md)
- [Toggle Between Stories In Storybook](workflow/toggle-between-stories-in-storybook.md)
- [Update asdf Plugins With Latest Package Versions](workflow/update-asdf-plugins-with-latest-package-versions.md)
- [View The PR For The Current GitHub Branch](workflow/view-the-pr-for-the-current-github-branch.md)

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

View File

@@ -0,0 +1,22 @@
# Clamp To An Endless Range
The
[`Comparable#clamp`](https://ruby-doc.org/3.3.6/Comparable.html#method-i-clamp)
method allows us to specify the bounds of a value we want. If the target value
is between the bounds, then we get that value. Otherwise, we gets the nearest
end of the bounds.
We can even pass a range to `#clamp` instead of separate lower and upper bound
values. Because Ruby has beginless and endless ranges, this gives us the
ergonomics to, say, clamp to any non-negative value with a `0..` endless range.
Here is what that looks like:
```ruby
> 22.clamp(0..)
=> 22
> (-33).clamp(0..)
=> 0
> 0.clamp(0..)
=> 0
```

View File

@@ -0,0 +1,48 @@
# Break Justfile Into Separate Hidden Steps
With `just` and a project's `justfile`, I can get a summary of the commands
available to run against my project by running `just --list`. If I try to
breakdown a complex, multi-step command into separate `just` commands, it will
be nice for organization, but it will clutter the list output. I can mark
specific commands as hidden or internal by preceding them with an underscore
(`_`).
Here is a `justfile` from one of my projects that only lists a single command
`setup` which itself is supported by three internal commands: `_check-brew`,
`_install-deps`, and `_install-go-tools`.
```justfile
# Install all required development dependencies
setup: _check-brew _install-deps _install-go-tools
# Check if brew is installed
_check-brew:
#!/usr/bin/env bash
if ! command -v brew &> /dev/null; then
echo "Error: Homebrew is not installed"
echo "Please install from https://brew.sh"
exit 1
fi
brew_deps := '''
go
sqlite3
'''
# Install brew dependencies
_install-deps:
#!/usr/bin/env bash
deps=$(echo '{{brew_deps}}' | tr -s '[:space:]' ' ' | xargs)
for pkg in $deps; do
if ! brew list $pkg &>/dev/null; then
echo "Installing $pkg..."
brew install $pkg
else
echo "✓ $pkg already installed"
fi
done
# Install Go development tools
_install-go-tools:
go install github.com/pressly/goose/v3/cmd/goose@latest
```

View File

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

View File

@@ -0,0 +1,22 @@
# Show Linting Errors In Zed
When working in a language like TypeScript or Go, the language server tooling
in [Zed](https://zed.dev/) can draw my attention to errors in my code. This
could be an unrecognized function or variable, a type error, or a syntax error.
When these linting errors are detected, the editor underlines them with a red
squiggly. I can hover over offending token or statement and see what the error
is.
There are also a few mouse-free ways to do this.
First, I can hit `F8` to jump to the next one of these errors in the current
file. That will move my cursor to that location and display a small overlay
with the error details.
Second, assuming Vim mode, I can navigate my cursor over a specific highlighted
token and then hit `Shift+k`. That will pop open the same small overlay to
display the error details.
Third, I can hit `Cmd+Shift+M` to open the _Project Diagnostics_ tab which
displays a series of file buffer results with the offending lines and the error
description.