mirror of
https://github.com/jbranchaud/til
synced 2026-01-20 15:38:02 +00:00
Compare commits
17 Commits
d03ba56251
...
c5127aaaa6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5127aaaa6 | ||
|
|
138cab4fdc | ||
|
|
5592d4266d | ||
|
|
daf448c1a5 | ||
|
|
aaddc35fcd | ||
|
|
b575534d4e | ||
|
|
ae3ecbf72c | ||
|
|
1cf67b8f1a | ||
|
|
f9c0a566eb | ||
|
|
527038ca23 | ||
|
|
b972673008 | ||
|
|
cc31aae25a | ||
|
|
26f30c3225 | ||
|
|
e14da2f207 | ||
|
|
b7d4a62ecb | ||
|
|
1ad41b9776 | ||
|
|
11716a8fb5 |
21
README.md
21
README.md
@@ -10,7 +10,11 @@ pairing with smart people at Hashrocket.
|
||||
|
||||
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
|
||||
|
||||
_1552 TILs and counting..._
|
||||
_1562 TILs and counting..._
|
||||
|
||||
See some of the other learning resources I work on:
|
||||
- [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators)
|
||||
- [Vim Un-Alphabet](https://www.youtube.com/playlist?list=PL46-cKSxMYYCMpzXo6p0Cof8hJInYgohU)
|
||||
|
||||
---
|
||||
|
||||
@@ -403,12 +407,16 @@ _1552 TILs and counting..._
|
||||
|
||||
- [Access Go Docs Offline](go/access-go-docs-offline.md)
|
||||
- [Add A Method To A Struct](go/add-a-method-to-a-struct.md)
|
||||
- [Basic Delve Debugging Session](go/basic-delve-debugging-session.md)
|
||||
- [Build For A Specific OS And Architecture](go/build-for-a-specific-os-and-architecture.md)
|
||||
- [Check If Cobra Flag Was Set](go/check-if-cobra-flag-was-set.md)
|
||||
- [Combine Two Slices](go/combine-two-slices.md)
|
||||
- [Configure Max String Print Length For Delve](go/configure-max-string-print-length-for-delve.md)
|
||||
- [Connect To A SQLite Database](go/connect-to-a-sqlite-database.md)
|
||||
- [Create A Slice From An Array](go/create-a-slice-from-an-array.md)
|
||||
- [Detect If Stdin Comes From A Redirect](go/detect-if-stdin-comes-from-a-redirect.md)
|
||||
- [Deterministically Seed A Random Number Generator](go/deterministically-seed-a-random-number-generator.md)
|
||||
- [Difference Between Slice And Pointer To Slice](go/difference-between-slice-and-pointer-to-slice.md)
|
||||
- [Do Something N Times](go/do-something-n-times.md)
|
||||
- [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)
|
||||
@@ -446,6 +454,7 @@ _1552 TILs and counting..._
|
||||
- [Adding Alt Text To An Image](html/adding-alt-text-to-an-image.md)
|
||||
- [Determine Which Button Submitted The Form](html/determine-which-button-submitted-the-form.md)
|
||||
- [Disable Auto-Completion For A Form Input](html/disable-auto-completion-for-a-form-input.md)
|
||||
- [Disclose Additional Details](html/disclose-additional-details.md)
|
||||
- [Make Elements Non-Interactive With Inert](html/make-elements-non-interactive-with-inert.md)
|
||||
- [Prevent Search Engines From Indexing A Page](html/prevent-search-engines-from-indexing-a-page.md)
|
||||
- [Render Text As Superscript](html/render-text-as-superscript.md)
|
||||
@@ -654,6 +663,8 @@ _1552 TILs and counting..._
|
||||
- [Run AppleScript Commands Inline In The Terminal](mac/run-applescript-commands-inline-in-the-terminal.md)
|
||||
- [Set A Window To Its Default Zoom Level](mac/set-a-window-to-its-default-zoom-level.md)
|
||||
- [Specify App When Opening From Command Line](mac/specify-app-when-opening-from-command-line.md)
|
||||
- [Start Amphetamine Session With AppleScript](mac/start-amphetamine-session-with-applescript.md)
|
||||
- [Use A Different Font With iTerm2](mac/use-a-different-font-with-iterm2.md)
|
||||
- [Use Default Screenshot Shortcuts With CleanShot X](mac/use-default-screenshot-shortcuts-with-cleanshot-x.md)
|
||||
- [View All Windows Of The Current App](mac/view-all-windows-of-the-current-app.md)
|
||||
- [Write System Clipboard To A File](mac/write-system-clipboard-to-a-file.md)
|
||||
@@ -1027,6 +1038,7 @@ _1552 TILs and counting..._
|
||||
- [Query A Single Value From The Database](rails/query-a-single-value-from-the-database.md)
|
||||
- [Read In Environment-Specific Config Values](rails/read-in-environment-specific-config-values.md)
|
||||
- [Read-Only Models](rails/read-only-models.md)
|
||||
- [Rebuild Tailwind Bundle For Dev Server](rails/rebuild-tailwind-bundle-for-dev-server.md)
|
||||
- [Remove A Database Column From A Table](rails/remove-a-database-column-from-a-table.md)
|
||||
- [Remove The Default Value On A Column](rails/remove-the-default-value-on-a-column.md)
|
||||
- [Render An Alternative ActionMailer Template](rails/render-an-alternative-action-mailer-template.md)
|
||||
@@ -1269,6 +1281,7 @@ _1552 TILs and counting..._
|
||||
- [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md)
|
||||
- [Include Extra Context In A Honeybadger Notify](ruby/include-extra-context-in-a-honeybadger-notify.md)
|
||||
- [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md)
|
||||
- [Install Latest Version Of Ruby With asdf](ruby/install-latest-version-of-ruby-with-asdf.md)
|
||||
- [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md)
|
||||
- [IRB Has Built-In Benchmarking With Ruby 3](ruby/irb-has-built-in-benchmarking-with-ruby-3.md)
|
||||
- [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md)
|
||||
@@ -1301,6 +1314,7 @@ _1552 TILs and counting..._
|
||||
- [Question Mark Operator](ruby/question-mark-operator.md)
|
||||
- [Rake Only Lists Tasks With Descriptions](ruby/rake-only-lists-tasks-with-descriptions.md)
|
||||
- [Read The First Line From A File](ruby/read-the-first-line-from-a-file.md)
|
||||
- [Refer To Implicit Block Argument With It](ruby/refer-to-implicit-block-argument-with-it.md)
|
||||
- [Rendering ERB](ruby/rendering-erb.md)
|
||||
- [Replace The Current Process With An External Command](ruby/replace-the-current-process-with-an-external-command.md)
|
||||
- [Require Entire Gemfile In Pry Session](ruby/require-entire-gemfile-in-pry-session.md)
|
||||
@@ -1563,6 +1577,7 @@ _1552 TILs and counting..._
|
||||
- [Search History](unix/search-history.md)
|
||||
- [Search Man Page Descriptions](unix/search-man-page-descriptions.md)
|
||||
- [Securely Remove Files](unix/securely-remove-files.md)
|
||||
- [See Where asdf Gets Current Tool Version](unix/see-where-asdf-gets-current-tool-version.md)
|
||||
- [Set The asdf Package Version For A Single Shell](unix/set-the-asdf-package-version-for-a-single-shell.md)
|
||||
- [Show A File Preview When Searching With FZF](unix/show-a-file-preview-when-searching-with-fzf.md)
|
||||
- [Show Disk Usage For The Current Directory](unix/show-disk-usage-for-the-current-directory.md)
|
||||
@@ -1856,11 +1871,11 @@ I shamelessly stole this idea from
|
||||
|
||||
* [Today I Learned by Hashrocket](https://til.hashrocket.com)
|
||||
* [jwworth/til](https://github.com/jwworth/til)
|
||||
* [thoughtbot/til](https://github.com/thoughtbot/til)
|
||||
* [til.simonwillison.net](https://til.simonwillison.net/)
|
||||
|
||||
## License
|
||||
|
||||
© 2015-2022 Josh Branchaud
|
||||
© 2015-2025 Josh Branchaud
|
||||
|
||||
This repository is licensed under the MIT license. See `LICENSE` for
|
||||
details.
|
||||
|
||||
63
go/basic-delve-debugging-session.md
Normal file
63
go/basic-delve-debugging-session.md
Normal 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)
|
||||
```
|
||||
29
go/configure-max-string-print-length-for-delve.md
Normal file
29
go/configure-max-string-print-length-for-delve.md
Normal 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)
|
||||
50
go/connect-to-a-sqlite-database.md
Normal file
50
go/connect-to-a-sqlite-database.md
Normal 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")
|
||||
}
|
||||
```
|
||||
55
go/difference-between-slice-and-pointer-to-slice.md
Normal file
55
go/difference-between-slice-and-pointer-to-slice.md
Normal 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)
|
||||
28
html/disclose-additional-details.md
Normal file
28
html/disclose-additional-details.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Disclose Additional Details
|
||||
|
||||
You can add extra details to an HTML page that are only disclosed if the user
|
||||
chooses to disclose them. To do that, we use the `<details>` tag. This tag
|
||||
needs to have a `<summary>` tag nested within it. Anything else nested within
|
||||
`<details>` will be what is disclosed when it is toggled open. The `<summary>`
|
||||
is what is displayed when it is not open.
|
||||
|
||||
Here is a `<detail>` block I recently added to [Ruby Operator
|
||||
Lookup](https://www.visualmode.dev/ruby-operators).
|
||||
|
||||
```html
|
||||
<details className="pt-2 pb-6">
|
||||
<summary>What is this thing?</summary>
|
||||
<p className="pl-3 pt-2 text-gray-700 text-sm">
|
||||
Ruby is an expressive, versatile, and flexible dynamic programming language. That means there are all kinds of syntax features, operators, and symbols we can encounter that might look unfamiliar and are hard to look up. Ruby Operator Lookup is a directory of all these language features.
|
||||
</p>
|
||||
<p className="pl-3 pt-2 text-gray-700 text-sm">
|
||||
Use the search bar to narrow down the results. Then click on a button for the operator or symbol you want to explore further.
|
||||
</p>
|
||||
</details>
|
||||
```
|
||||
|
||||
On page load, the only thing we see is "What is this thing?" with a triangle
|
||||
symbol next to it. If we click the summary, then the entire details block
|
||||
(those two `<p>` tags) are disclosed.
|
||||
|
||||
[source](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
|
||||
37
mac/start-amphetamine-session-with-applescript.md
Normal file
37
mac/start-amphetamine-session-with-applescript.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Start Amphetamine Session With AppleScript
|
||||
|
||||
I use the _Amphetamine_ app on Mac to keep my computer from going to sleep
|
||||
during the day. It is a menu bar app that can be used to start a _Session_ of
|
||||
time where it will keep your computer from going to sleep. At the start of my
|
||||
day, I'll typically start an 8 hour _Session_. This is useful if I have to step
|
||||
away fo 10 minutes or if I'm doing some writing in my notebook, my computer
|
||||
won't go to sleep on me.
|
||||
|
||||
Though these sessions can be controlled from the menu bar app, I was excited to
|
||||
learn that I can also programatically start a session with AppleScript.
|
||||
|
||||
Here is how to start a _Session_ (overriding an existing session) with options
|
||||
that specify it is 8 hours long and the display should not be allowed to sleep.
|
||||
|
||||
```bash
|
||||
$ osascript -e 'tell application "Amphetamine" to start new session with options {duration:8, interval:hours, displaySleepAllowed:false}'
|
||||
```
|
||||
|
||||
The `interval` could also be `minutes` and then I could change the duration to
|
||||
an amount of time that makes sense in minutes, e.g. `90` for 1.5 hours.
|
||||
|
||||
Note: the `with options {...}` segement is all or nothing. All three need to be included or don't include the clause at all.
|
||||
|
||||
Additionally, a session of indefinite duration can be started by including no options:
|
||||
|
||||
```bash
|
||||
$ osascript -e 'tell application "Amphetamine" to start new session'
|
||||
```
|
||||
|
||||
And any existing session can be ended with:
|
||||
|
||||
```bash
|
||||
$ osascript -e 'tell application "Amphetamine" to end session'
|
||||
```
|
||||
|
||||
[source](https://iffy.freshdesk.com/support/solutions/articles/48000078223-applescript-documentation)
|
||||
25
mac/use-a-different-font-with-iterm2.md
Normal file
25
mac/use-a-different-font-with-iterm2.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Use A Different Font With iTerm2
|
||||
|
||||
I wanted to give [`gh-dash`](https://github.com/dlvhdr/gh-dash) a try, but
|
||||
after installing and opening it up, I was seeing a bunch of `?` characters
|
||||
where specialized font icons were missing. Their README recommended installing
|
||||
a [`Nerd Font`](https://github.com/ryanoasis/nerd-fonts) that includes those
|
||||
icons, such as [`Fira Code`](https://github.com/tonsky/FiraCode).
|
||||
|
||||
I was able to install `font-fira-code-nerd-font` with homebrew:
|
||||
|
||||
```bash
|
||||
$ brew install font-fira-code-nerd-font
|
||||
```
|
||||
|
||||
Then to get iTerm2 to start using that font, I had to change the font setting
|
||||
for my current profile.
|
||||
|
||||
Under the _iTerm2_ menu is _Settings..._. From there, I clicked the _Profiles_
|
||||
section. For the _Default_ profile, I went to the _Text_ tab and under _Font_ I
|
||||
selected _FireCode Nerd Font Mono_ from the dropdown.
|
||||
|
||||
That won't take effect on any current iTerm2 windows. Since I have everything
|
||||
running through `tmux`, I could close my current window, open a new one
|
||||
(`Cmd+N`), and reconnect to my existing `tmux` session. Now when I run `gh
|
||||
dash`, I see all the font icons that were missing before.
|
||||
29
rails/rebuild-tailwind-bundle-for-dev-server.md
Normal file
29
rails/rebuild-tailwind-bundle-for-dev-server.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Rebuild Tailwind Bundle For Dev Server
|
||||
|
||||
If you're using the TailwindCSS gem in your Rails app:
|
||||
|
||||
```ruby
|
||||
# Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]
|
||||
gem "tailwindcss-rails"
|
||||
```
|
||||
|
||||
you may find that as you add and adjust styles in your views, refreshing the
|
||||
page doesn't take any styling effects. That is because the tailwind bundle gets
|
||||
built with just the style rules that were used at the time it was generated.
|
||||
|
||||
In development, as we're working, we expect the styles used by our app to
|
||||
actively changed. And we don't mind a little performance hit to have the bundle
|
||||
rebuilt. In that case, we can instruct `puma` to _Live Rebuild_ in
|
||||
`development` with the `tailwindcss` plugin.
|
||||
|
||||
```ruby
|
||||
# config/puma.rb
|
||||
|
||||
# Enable TailwindCSS rebuild in development
|
||||
plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development"
|
||||
```
|
||||
|
||||
This has `rails server` run a watch process in the background that live
|
||||
rebuilds the bundle.
|
||||
|
||||
[source](https://github.com/rails/tailwindcss-rails?tab=readme-ov-file#puma-plugin)
|
||||
54
ruby/install-latest-version-of-ruby-with-asdf.md
Normal file
54
ruby/install-latest-version-of-ruby-with-asdf.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Install Latest Version Of Ruby With asdf
|
||||
|
||||
When I check the `asdf` Ruby plugin for known versions of Ruby:
|
||||
|
||||
```bash
|
||||
$ asdf list-all ruby | fzf
|
||||
```
|
||||
|
||||
I don't find the latest (`3.4`).
|
||||
|
||||
I need to update the plugin. A newer version of the plugin will know about
|
||||
newer Ruby versions.
|
||||
|
||||
```bash
|
||||
$ asdf plugin-update ruby
|
||||
```
|
||||
|
||||
Now, if I run the `list-all` command again, I'll find the version I'm looking
|
||||
for — `3.4.1`.
|
||||
|
||||
Now that `asdf` and I both know about the version to be installed, I can tell
|
||||
`asdf` to install it:
|
||||
|
||||
```bash
|
||||
$ asdf install ruby 3.4.1
|
||||
```
|
||||
|
||||
Now, if I check the current Ruby version, I'll see that it is still set to some
|
||||
other version.
|
||||
|
||||
```bash
|
||||
$ ruby --version
|
||||
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-darwin22]
|
||||
```
|
||||
|
||||
I need to tell `asdf` to start using this newly installed version instead,
|
||||
either globally or locally.
|
||||
|
||||
```bash
|
||||
$ # globally
|
||||
$ asdf global ruby 3.4.1
|
||||
$ # or locally
|
||||
$ asdf local ruby 3.4.1
|
||||
```
|
||||
|
||||
And now I'm all set:
|
||||
|
||||
```bash
|
||||
$ asdf current ruby
|
||||
ruby 3.4.1 /Users/jbranchaud/.tool-versions
|
||||
|
||||
$ ruby --version
|
||||
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin22]
|
||||
```
|
||||
43
ruby/refer-to-implicit-block-argument-with-it.md
Normal file
43
ruby/refer-to-implicit-block-argument-with-it.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Refer To Implicit Block Argument With It
|
||||
|
||||
One of the key features of the Ruby 3.4 release is the `it` implicit block
|
||||
argument.
|
||||
|
||||
The vast majority of inline blocks defined in Ruby code receive a single block
|
||||
argument. Typically we name and reference a block argument explictly like so:
|
||||
|
||||
```ruby
|
||||
items.map { |item| item * item }
|
||||
```
|
||||
|
||||
Ruby likes to cut away excess syntax when possible. To that end, the implicit
|
||||
`it` block argument has been added. This is an identifier we can reference in
|
||||
the context of a block and its value is the current
|
||||
|
||||
```ruby
|
||||
items = [1,2,3,4,5]
|
||||
|
||||
squares = items.map { it * it }
|
||||
|
||||
pp squares
|
||||
#=> [1, 4, 9, 16, 25]
|
||||
```
|
||||
|
||||
Note: we cannot mix numbered parameters (`_1`, `_2`) with the `it` parameter.
|
||||
If we do, we'll get the following error:
|
||||
|
||||
```ruby
|
||||
def method_using_block(a, b)
|
||||
yield(a, b) if block_given?
|
||||
end
|
||||
|
||||
puts method_using_block(4,5) { _2 ** _1 } #=> 625
|
||||
puts method_using_block(4,5) { _2 ** it }
|
||||
# it_block.rb:12: syntax error found (SyntaxError)
|
||||
# 10 |
|
||||
# 11 | puts method_using_block(4,5) { _2 ** _1 }
|
||||
# > 12 | ... it }
|
||||
# | ^~ `it` is not allowed when a numbered parameter is already used
|
||||
```
|
||||
|
||||
[source](https://docs.ruby-lang.org/en/3.4/NEWS_md.html)
|
||||
29
unix/see-where-asdf-gets-current-tool-version.md
Normal file
29
unix/see-where-asdf-gets-current-tool-version.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# See Where asdf Gets Current Tool Version
|
||||
|
||||
The other day I [installed the latest version of
|
||||
Ruby](ruby/install-latest-version-of-ruby-with-asdf.md) with `asdf`. I then set
|
||||
that version (`3.4.1`) as the global default. However, when I then ran `ruby
|
||||
--version`, I was getting a `3.2.x` version. I checked my current project's
|
||||
directory and there was no `.tool-versions` file, so it wasn't being set by my
|
||||
current directory.
|
||||
|
||||
`asdf` looks up the current chain of directories until it encounters a
|
||||
`.tool-versions` file, so it must have been finding one somewhere up there, but
|
||||
before it was getting to the _global_ `.tool-versions` file. But where?
|
||||
|
||||
The `asdf current` command can tell us for a specific tool what the current
|
||||
version it is set to and what file is giving that directive.
|
||||
|
||||
```bash
|
||||
asdf current ruby
|
||||
ruby 3.2.2 /Users/jbranchaud/code/.tool-versions
|
||||
```
|
||||
|
||||
As it turns out, I had a `.tool-versions` file in `$HOME/code` that was setting
|
||||
that `3.2.x` Ruby version.
|
||||
|
||||
I didn't want that directory controlling the Ruby version, so I removed `ruby`
|
||||
from that file. `asdf` was then able to traverse up to `$HOME/.tool-versions`
|
||||
for the global setting.
|
||||
|
||||
See `asdf help` for more details.
|
||||
20
workflow/control-media-with-drop-keyboard.md
Normal file
20
workflow/control-media-with-drop-keyboard.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Control Media With Drop Keyboard
|
||||
|
||||
I have a [Drop CTRL](https://drop.com/buy/drop-ctrl-v2-mechanical-keyboard)
|
||||
mechanical keyboard which mostly works like any other keyboard. It also has a
|
||||
set of functionality that can be accessed via the `fn` (function) key. The
|
||||
function key can be used to configure the keyboard's LEDs, but I tend to set
|
||||
and forget that.
|
||||
|
||||
Instead, I like to use the function key to control media. That is, adjust the
|
||||
volume, play and pause, and skip to the next song.
|
||||
|
||||
Here is a listing of the ones I use:
|
||||
|
||||
- `Fn + Insert` to Pause / Play
|
||||
- `Fn + PgUp/PgDown` to Increase / Decrease the volume
|
||||
- `Fn + Del/End` to go to the Previous / Next song
|
||||
|
||||
Here is a [full listing of the function
|
||||
keys](https://drop.com/talk/9382/how-to-configure-your-drop-keyboard) for Drop
|
||||
keyboards.
|
||||
Reference in New Issue
Block a user