1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-14 12:38:01 +00:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Mohammad Alyetama
7657138d75 Merge bc767a0ad3 into b329d36888 2024-11-29 22:06:47 +05:45
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
Mohammad Alyetama
bc767a0ad3 Update bew cask command 2022-11-24 17:49:13 -05:00
8 changed files with 266 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).
_1514 TILs and counting..._
_1520 TILs and counting..._
---
@@ -41,6 +41,7 @@ _1514 TILs and counting..._
* [Internet](#internet)
* [Java](#java)
* [JavaScript](#javascript)
* [jj](#jj)
* [jq](#jq)
* [Kitty](#kitty)
* [Linux](#linux)
@@ -310,6 +311,7 @@ _1514 TILs and counting..._
- [Find And Remove Files That Match A Name](git/find-and-remove-files-that-match-a-name.md)
- [Find The Date That A File Was Added To The Repo](git/find-the-date-that-a-file-was-added-to-the-repo.md)
- [Find The Initial Commit](git/find-the-initial-commit.md)
- [Get Latest Commit Timestamp For A File](git/get-latest-commit-timestamp-for-a-file.md)
- [Get The Name Of The Current Branch](git/get-the-name-of-the-current-branch.md)
- [Get The Short Version Of The Latest Commit](git/get-the-short-version-of-the-latest-commit.md)
- [Grab A Single File From A Stash](git/grab-a-single-file-from-a-stash.md)
@@ -568,6 +570,10 @@ _1514 TILs and counting..._
- [Yarn Commands Without The Emojis](javascript/yarn-commands-without-the-emojis.md)
- [Yup Schemas Are Validated Asynchronously](javascript/yup-schemas-are-validated-asynchronously.md)
### jj
- [Colocate jj And git Directories For Project](jj/colocate-jj-and-git-directories-for-project.md)
### jq
- [Combine An Array Of Objects Into A Single Object](jq/combine-an-array-of-objects-into-a-single-object.md)
@@ -1182,6 +1188,7 @@ _1514 TILs and counting..._
- [Audit Your Ruby Project For Any CVEs](ruby/audit-your-ruby-project-for-any-cves.md)
- [Assoc For Hashes](ruby/assoc-for-hashes.md)
- [Block Comments](ruby/block-comments.md)
- [Block Syntaxes Have Different Precedence](ruby/block-syntaxes-have-different-precedence.md)
- [Build HTTP And HTTPS URLs](ruby/build-http-and-https-urls.md)
- [Chaining Multiple RSpec Change Matchers](ruby/chaining-multiple-rspec-change-matchers.md)
- [Check For Any Overlaps In List Of Ranges](ruby/check-for-any-overlaps-in-list-of-ranges.md)
@@ -1225,6 +1232,7 @@ _1514 TILs and counting..._
- [Finding The Source of Ruby Methods](ruby/finding-the-source-of-ruby-methods.md)
- [Format A Hash Into A String Template](ruby/format-a-hash-into-a-string-template.md)
- [Forward All Arguments To Another Method](ruby/forward-all-arguments-to-another-method.md)
- [Gather Positional Arguments In Method Definition](ruby/gather-positional-arguments-in-method-definition.md)
- [Generate A Signed JWT Token](ruby/generate-a-signed-jwt-token.md)
- [Generate Ruby Version And Gemset Files With RVM](ruby/generate-ruby-version-and-gemset-files-with-rvm.md)
- [Get Info About Your RubyGems Environment](ruby/get-info-about-your-ruby-gems-environment.md)
@@ -1292,6 +1300,7 @@ _1514 TILs and counting..._
- [Specify How Random Array#sample Is](ruby/specify-how-random-array-sample-is.md)
- [Split A Float Into Its Integer And Decimal](ruby/split-a-float-into-its-integer-and-decimal.md)
- [Squeeze Out The Extra Space](ruby/squeeze-out-the-extra-space.md)
- [Stack Heredocs In A Method Call](ruby/stack-heredocs-in-a-method-call.md)
- [String Interpolation With Instance Variables](ruby/string-interpolation-with-instance-variables.md)
- [Summing Collections](ruby/summing-collections.md)
- [Triple Equals: The Case Equality Operator](ruby/triple-equals-the-case-equality-operator.md)
@@ -1537,6 +1546,7 @@ _1514 TILs and counting..._
- [Switch Versions of a Brew Formula](unix/switch-versions-of-a-brew-formula.md)
- [Tell direnv To Load The Env File](unix/tell-direnv-to-load-the-env-file.md)
- [Touch Access And Modify Times Individually](unix/touch-access-and-modify-times-individually.md)
- [Type Fewer Paths With Brace Expansion](unix/type-fewer-paths-with-brace-expansion.md)
- [Undo Changes Made To Current Terminal Prompt](unix/undo-changes-made-to-current-terminal-prompt.md)
- [Undo Some Command Line Editing](unix/undo-some-command-line-editing.md)
- [Unrestrict Where ripgrep Searches](unix/unrestrict-where-ripgrep-searches.md)

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,59 @@
# Colocate jj And git Directories For Project
When doing a standard clone of a git repository with `jj`, you'll get a copy of
the project with a `.jj` directory containing the version control information.
```bash
$ jj git clone git@github.com:jbranchaud/my-repo
Fetching into new repo in "/path/of/local/repo"
...
$ exa --tree --all -L 1
.
├── .gitignore
├── .jj
├── Cargo.lock
├── Cargo.toml
└── src
```
This is fine if I'm completely familiar with using
[jujutsu](https://martinvonz.github.io/jj/latest/). However, if I'm coming from
`git` and still learning, then it would be nice to be able to fallback to
familiar `git` commands when needed.
But without a `.git` directory, I get this:
```bash
$ git log
fatal: not a git repository (or any of the parent directories): .git
```
When cloning a git repo with `jj`, I can instruct it to _colocate_ which means
that it will create both the `.jj` and the `.git` data directories in the
project.
```bash
$ jj git clone --colocate git@github.com:jbranchaud/my-repo
Fetching into new repo in "/path/of/local/repo"
...
$ exa --tree --all -L 1
.
├── .git
├── .gitignore
├── .jj
├── Cargo.lock
├── Cargo.toml
└── src
```
Now I can run `jj` commands or `git` commands:
```bash
$ git log
commit 0c72abbb83657096677f9a3d5ddc7bce20839165 (HEAD, origin/trunk, trunk)
...
```
[source](https://martinvonz.github.io/jj/latest/git-compatibility/#co-located-jujutsugit-repos)

View File

@@ -0,0 +1,29 @@
# Block Syntaxes Have Different Precedence
There are two syntaxes for defining a block in Ruby. The semantically shorthand
syntax uses the curly braces (`{}`). The semantically multi-line syntax uses
`do` and `end`. For nearly all intents and purposes they are interchangable.
It is, however, worth noting that the `do`/`end` version has a lower precedence
than the already low precedence of `{}`. That said, you have to write some
weird code for this to become an issue.
Let's say we have two methods, `method_one` and `method_two`. They are both
called on the same line like below and then followed by a block argument. Which
method receives the block argument?
```ruby
method_one method_two { |n|
puts "Executing a block: #{n}"
}
method_one method_two do |n|
puts "Executing a block: #{n}"
end
```
In the first case, with the curly braces, `method_two` receives the block as an
argument. In the second case, with the `do`/`end`, `method_one` receives the
block as an argument.
[source](http://localhost:3131/ruby-operators/curly-braces#block-shorthand)

View File

@@ -0,0 +1,55 @@
# Gather Positional Arguments In Method Definition
The `*` symbol can be used in Ruby in a method definition to gather up an
arbitrary number of positional arguments.
For instance, we can gather all positional arguments with this method
definition:
```ruby
def gather_all(*args)
puts args
end
```
Or we can isolate the first positional arg and then gather the rest:
```ruby
def first_and_rest(first, *rest)
puts "First: #{first}, Rest: #{rest}"
end
```
We can even do something a bit more interesting like isolating the first and
last arguments while gathering up everything else in the middle:
```ruby
def pop_parens(left, *middle, right)
if left != '(' || right != ')'
raise "Uh oh!"
else
if middle.size == 1
puts "Found: #{middle.first}"
else
pop_parens(*middle)
end
end
end
```
Here is what it looks like if we splat some different sets of arguments into
that method call:
```ruby
> tokens1 = "((((4))))".split('')
=> ["(", "(", "(", "(", "4", ")", ")", ")", ")"]
> tokens2 = "((4))))".split('')
=> ["(", "(", "4", ")", ")", ")", ")"]
> pop_parens(*tokens1)
Found: 4
=> nil
> pop_parens(*tokens2)
(irb):87:in `pop_parens': Uh oh! (RuntimeError)
```
[source](https://ruby-doc.org/3.3.6/syntax/methods_rdoc.html#label-Array-2FHash+Argument)

View File

@@ -0,0 +1,37 @@
# Stack Heredocs In A Method Call
When you put a heredoc directly in a method call as an argument, it is only the
opening identifier that goes in the argument list.
That looks like this:
```ruby
execute_in_transaction(<<~SQL)
update reading_statuses
set status = 'abandoned'
where started_at < (now() - '2 years'::interval)
and finished_at is null;
SQL
```
You might imagine then that we can put multiple heredocs in a method call. That
leads to [_stacked
heredocs_](https://www.visualmode.dev/ruby-operators/heredoc#stacked-heredocs).
```ruby
execute_in_transaction(<<~SQL1, <<~SQL2, <<~SQL3)
update reading_statuses
set status = 'abandoned'
where started_at < (now() - '2 years'::interval)
and finished_at is null;
SQL1
insert into activity_log (name, description)
values ('abandon_books', 'Mark unread books as abandoned');
SQL2
delete from background_jobs
where id = #{job_id}; -- better to sanitize values like this
SQL3
```
Notice we terminate the body of each heredoc with its closing identifier and
immediately begin the body of the next one.

View File

@@ -0,0 +1,49 @@
# Type Fewer Paths With Brace Expansion
Bash has a feature called _brace expansion_ that allows us to do a kind of
shorthand when writing out file paths. We can specify multiple variants
comma-separated between curly braces and they'll each be expanded into separate
arguments.
It's easier to understand this by seeing it. If we type the following (don't
hit `Enter` yet):
```bash
$ mkdir src/{one,two,three}
```
And then hit _Tab_:
```bash
$ mkdir src/one src/two src/three
```
Bash uses the portion in braces to expand into separate arguments. The part
outside the braces gets reused for each. That's where we get some savings from
typing out the same path each time.
Here is another example where we use `mv` to rename a file deeply nested in our
project:
```bash
$ mv projects/project1/src/app/utils/{names,constants}.js
```
We don't even have to _Tab_ it out. We can hit _Enter_ directly and `mv` gets
both arguments.
Similarly, how about we change the extension of our renamed file:
```bash
$ mv projects/project1/src/app/utils/constants.{js,ts}
```
I've always found this feature most useful with paths and filenames, but you
can do brace expansion with any arguments.
```bash
$ echo 1{3,1,6,4,9,2,7,5}
13 11 16 14 19 12 17 15
```
[source](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html)

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`: