set the channel description: what did you learn today?
Amazon’s Code has this too, super nice. Can also open multiple files in the same package in one window, but separate tabs
til you can git add a subset of the changes in the files by interactively selecting the lines to stage with git add --patch
I have done this with Sourcetree in the past, but it's nice to finally see the commands behind it! I don't use Sourcetree anymore so this might come in handy.
Hmm can’t say I’m familiar with Sourcetree. What is that?
til you can use --alow-empty to make an empty commit, useful for when you have some CI steps that run on pushes to your remote:
git commit -m "trigger image build" --allow-empty
Seems kind of noisy for git history though. Don't most CICD tools allow you to trigger a pipeline manually by selecting a target branch?
We default to squash-merge when actually merging our PRs to the main branch, so one commit in the end doesn’t bloat production tree
selecting a target branchThat’s what this is doing. A lot of our dev tooling puts standard image builds as a part of CI. CI runs on PRs the infra team says to use PRs
til something that i’m embarrassed to admit I didn’t know about. Apparently you can search your man pages using the -f (complete word matches) and -k (soft matches) flags e.g.
kandelin@lyft-mbp2 telematicsingest % man -f pid
pidof(1) - get the PID of processes by name
pid(ntcl) - Retrieve process identifiers
rwbypid.d(1m) - read/write calls by PID. Uses DTrace
pid(ntcl) - Retrieve process identifiers
rwbypid.d(1m) - read/write calls by PID. Uses DTrace
kandelin@lyft-mbp2 telematicsingest % man -k pid
pidof(1) - get the PID of processes by name
nfs4mapid(8) - shows NFSv4 mappings from uids or gids to over the wire string names and string names to uids or gids
pid(ntcl) - Retrieve process identifiers
pidpersec.d(1m) - print new PIDs per sec. Uses DTrace
rwbypid.d(1m) - read/write calls by PID. Uses DTrace
syscallbypid.d(1m) - syscalls by process ID. Uses DTrace
CURLOPT_TCP_KEEPIDLE(3) - TCP keep-alive idle time wait
Proc::Killfam(3pm) - kill a list of pids, and all their sub-children
Sub::Exporter::Cookbook(3pm) - useful, demonstrative, or stupid Sub::Exporter tricks
Tcl_DetachPids(3tcl), Tcl_ReapDetachedProcs(3tcl), Tcl_WaitPid(3tcl) - manage child processes in background
getpid(2), getppid(2) - get parent or calling process identification
nfs4mapid(8) - shows NFSv4 mappings from uids or gids to over the wire string names and string names to uids or gids
pid(ntcl) - Retrieve process identifiers
pidpersec.d(1m) - print new PIDs per sec. Uses DTrace
pthread_setugid_np(2) - Set the per-thread userid and single groupid
rwbypid.d(1m) - read/write calls by PID. Uses DTrace
syscallbypid.d(1m) - syscalls by process ID. Uses DTrace
wait(2), wait3(2), wait4(2), waitpid(2) - wait for process termination
git(1) - the stupid content tracker
til about gron. next time you find yourself trying to extract/manipulate some json data with jq, give gron a try instead 👍
Unnests json into greppable lines:
▶ gron "" | fgrep "commit.author"
json[0].commit.author = {};
json[0].commit.author.date = "2016-07-02T10:51:21Z";
json[0].commit.author.email = "mail@tomnomnom.com";
json[0].commit.author.name = "Tom Hudson";
▶ gron "" | fgrep "commit.author" | gron --ungron
[
{
"commit": {
"author": {
"date": "2016-07-02T10:51:21Z",
"email": "mail@tomnomnom.com",
"name": "Tom Hudson"
}
}
}
]
haha, managing 9 person team now, so there is 0 time for coding. It is fun though, but maybe after this recession ill mix it up again
Last we spoke you mentioned you were gonna look for a new job as an IC
yeah, but with the change in the economy, im gonna hunker down for a bit
til about the pandas.DataFrame.to_clipboard method.
So now I have this handy function in my PYTHONSTARTUP=~/.local/lib/pythonstartup.py file:
def to_clipboard(obj):
import pandas as pd
pd.DataFrame([obj]).to_clipboard(index=False, header=False)
til there is no need for 3rd party software on macs to snap windows to left/right/top/bottom 🙌
You can simply do:
Ctrl﹢Option﹢Return (⌃⌥⏎): Zoom
Ctrl﹢Option﹢Left (⌃⌥←): Move Window to Left of Screen
Ctrl﹢Option﹢Right (⌃⌥→): Move Window to Right of Screen
Ctrl﹢Option﹢Up (⌃⌥↑): Move Window to Top of Screen
Ctrl﹢Option﹢Down (⌃⌥↓): Move Window to Bottom of Screen
One of the biggest annoyances with my mac so far is remembering which combination of shift + ctrl + opt + cmd I need to press for which command
lol isn’t that generalizable to any keyboard shortcut on any operating system?
No, for windows at least, most shortcuts only use one of those, but Mac seems to like using at least two for everything
til how to undo the amended changes from a git commit --amend.
HEAD@{1} gives you the commit that HEAD pointed to before it was moved to where it currently points at (ie before your --amend commit). I can see all my changes from the amended commit with git diff HEAD@{1}.
So then to break apart the original commit and the --amend into two separate commits:
# move head to point to the first commit, but leave the current index intact
git reset --soft HEAD@{1}
# now head is back to your original unmodified commit, with your mistakenly amended
# changes staged in the working tree. so at this point all you need to do is just
# create a new commit like you should have done in the first place.
git commit -m 'second set of changes in a separate commit'
Damn, that's awesome. I had no idea you could split it after amending. That is good to know, since I use amend all the time. Thanks for sharing !
I use it all the time as well. And then this morning I amended a commit with tons of separate unrelated changes I was planning to commit separately. Super pleased to have learned about this ability for sure
git head@{N} is a clutch command. Never knew about the ability to split as well, super useful!
til (i) how to find which commit deleted a file, and (ii) which commit deleted a line of code
Which commit deleted a file?
git rev-list -n1 HEAD — # Exact commit
kandelin yeoman-generators [master] git rev-list -n1 HEAD -- generators/services/generator-service/generators/python/templates/docs/_README.md
e5fbebf606973d40de89565685ad3cebf5282258
# What happened? (moved or deleted)
kandelin yeoman-generators [master] git diff e5fbebf^ e5fbebf | grep -m1 -A3 generators/services/generator-service/generators/python/templates/docs/_README.md
similarity index 100%
rename from generators/services/generator-service/generators/python/templates/docs/_README.md
rename to generators/generator-service/generators/python/templates/docs/_README.md
Twas moved.
Which commit deleted a line of code?
git blame --reverse will show you each line with the last commit in which it still existed 🙌kandelin yeoman-generators [master] git blame --reverse e5fbebf.. generators/generator-service/generators/python/templates/docs/_README.md | grep -A3 'not allowed to use
unittest
'
be8bccbf2 (Prem Santosh 2021-03-12 14:58:59 -0800 95) *For new services going forward, you are not allowed to use unittest
anywhere.*
be8bccbf2 (Prem Santosh 2021-03-12 14:58:59 -0800 96) Assertions should be made
be8bccbf2 (Prem Santosh 2021-03-12 14:58:59 -0800 97) with the built-in assert
statement. Py.test overloads this to do introspection, and
be8bccbf2 (Prem Santosh 2021-03-12 14:58:59 -0800 98) provides very detailed test output, which you don't get when you use unittest
asserts.
Prem Santosh be8bccbf2 I got ya now bish. Edit: actually, the culprit is one commit laterkandelin yeoman-generators [master] git log --oneline be8bccbf2..HEAD | tail -n1
52d2c24c Remove repeated new python project boilerplate (#1144)
52d2c24c got ya now bish
Am I blind? Where are you specifying the line number in that second one?
Where are you specifying the line number in that second one?Are you asking what line I’m trying to find?
not allowed to use unittest
it’s the only way to live. i keep most every application with text at 80% zoom. and my web browser
i usually configure it in the application preferences/settings
@brandon how are you enjoying your new found information density?
It's good so far. I've been at 80% for slack and gmail and haven't switched back!
@r.taylor i think you mentioned wanting a tool like this
It’s a combination of git, bat, and fzf. I’ve had and used them all for a while. But this fzf-git.sh project combines them magically. Found it in the fzf docs:
You can install it with:
❯ curl -sL > ~/.fzf-git.sh
❯ echo '[ -f ~/.fzf-git.sh ] && source ~/.fzf-git.sh' >> ~/.zshrc
It is amazing. I used ctrl-g ctrl-f in my gif above. Here are the other key bindings (fzf-git.sh only):
@andelink finally getting around to installing this today. Wondering why you provided the "install with git" instructions instead of homebrew. Do you prefer it because you have more control over the manipulation of zshrc?
AFAIK there is no brew formula for fzf-git. I installed fzf via homebrew but wasn’t aware I could with fzf-git
yeah i don’t see fzf-git in homebrew
❯ brew search fzf | xargs -I{} echo '{}'
fzf
fzy
fff
I wonder if it's conflicting with some other keybinding I have installed
Wait nevermind. I was thinking of something else
If you’ve got fzf-git setup right, you should be able to see results with this command:
$ which _fzf_git_fzf
_fzf_git_fzf () {
fzf-tmux -p80%,60% -- --layout=reverse --multi --height=50% --min-height=20 --border --color='header:italic:underline' --preview-window='right,50%,border-left' --bind='ctrl-/:change-preview-window(down,50%,border-top|hidden|)' "$@"
}
I keep CTRL pressed, and then hit G followed by F
I didn't do this step during fzf installation
# To install useful key bindings and fuzzy completion:
$(brew --prefix)/opt/fzf/install
Do you see any of these:
telematicsingest on master (1be4a24) +3 -3 [!?] via 🐍 v3.8.12 (telematicsingest venv) 16:03:13
❯ print -l ${(ok)functions} | grep -E 'fzf[_-]git'
__fzf_git_init
__fzf_git_join
_fzf_git_branches
_fzf_git_check
_fzf_git_each_ref
_fzf_git_files
_fzf_git_fzf
_fzf_git_hashes
_fzf_git_remotes
_fzf_git_stashes
_fzf_git_tags
_zsh_autosuggest_bound_1_fzf-git-branches-widget
_zsh_autosuggest_bound_1_fzf-git-each_ref-widget
_zsh_autosuggest_bound_1_fzf-git-files-widget
_zsh_autosuggest_bound_1_fzf-git-hashes-widget
_zsh_autosuggest_bound_1_fzf-git-remotes-widget
_zsh_autosuggest_bound_1_fzf-git-stashes-widget
_zsh_autosuggest_bound_1_fzf-git-tags-widget
fzf-git-branches-widget
fzf-git-each_ref-widget
fzf-git-files-widget
fzf-git-hashes-widget
fzf-git-install
fzf-git-remotes-widget
fzf-git-stashes-widget
fzf-git-tags-widget
I didn’t do this step during fzf installationalso yes do that
success! I think the main issue was the missing newline in my .zshrc file causing the source not to be loaded.
How do you trigger this on mac? ALT-A just creates a unicode character for me.
ALT-A (show all branches)I'm trying to read fzf-git.sh but haven't found the answer yet
AFAIK, the ALT- commands are used within the other fzf-git views. So to show all branches:
If that’s what you’re already doing, then my best guess is you need to configure ALT as a meta key within iterm. See the FAQ:
Q: How do I make the option/alt key act like Meta or send escape codes?
A: Go to Preferences > Profiles tab. Select your profile on the left, and then open the Keyboard tab. At the bottom is a set of buttons that lets you select the behavior of the Option key. For most users, Esc+ will be the best choice.
til that shell functions natively operate on stdin if available. most folks probably already knew this, but i did not!
e.g. just do a command within your function
# Accepts arbitrary jq options e.g. --slurp
function jqtable() {
jq -r '(.[0] | keys_unsorted | @tsv), (.[] |map(.) | @tsv)' "$@"
}
# data
❯ cat /tmp/data.json
{"filename":"app/workers/s3_event_worker.py","line_number":97}
{"filename":"app/coreservices/reports/report_squeezer.py","line_number":285}
{"filename":"app/coreservices/reports/report_squeezer.py","line_number":296}
{"filename":"app/coreservices/reports/report_squeezer.py","line_number":382}
{"filename":"app/coreservices/workers/create_worker_job.py","line_number":188}
# pipe stdin to your function
❯ cat /tmp/data.json | jqtable --slurp | column -t
filename line_number
app/workers/s3_event_worker.py 97
app/coreservices/reports/report_squeezer.py 285
app/coreservices/reports/report_squeezer.py 296
app/coreservices/reports/report_squeezer.py 382
app/coreservices/workers/create_worker_job.py 188
# or not
❯ jqtable --slurp /tmp/data.json | column -t
filename line_number
app/workers/s3_event_worker.py 97
app/coreservices/reports/report_squeezer.py 285
app/coreservices/reports/report_squeezer.py 296
app/coreservices/reports/report_squeezer.py 382
app/coreservices/workers/create_worker_job.py 188
til how to remap keys with hidutiil
my keyboards fn key is on the right side rather than the left, and my mac isn’t registering my right-fn key presses at all, so i basically don’t have a fn key. i don’t use my right-ctrl key ever, so i remapped it to fn with hidutil:
# Get current key mapping
$ hidutil property --get "UserKeyMapping"
(null)
# remap right_control --> fn
$ hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc": 0x7000000E4, "HIDKeyboardModifierMappingDst": 0xFF00000003}]}'
# Now we see a populated mapping
$ hidutil property --get "UserKeyMapping"
(
{
HIDKeyboardModifierMappingDst = 1095216660483;
HIDKeyboardModifierMappingSrc = 30064771300;
}
)
# You can clear any mappings with:
$ hidutil property --set '{"UserKeyMapping":[]}'
To get the proper key codes I used this handy tool:
The key hex values can be seen here:
You can calculate the correct hidutil key codes from the source hex values with:
# python
>>> right_control = '0xE4'
>>> hex(int(right_control, 16) + 0x700000000)
'0x7000000e4'
# javascript
❯ let right_control = '0xE4';
❯0x${(parseInt(right_control, 16) + 0x700000000).toString(16)}
;
'0x7000000e4'
woah woah woah… tinker? this is me solving a business problem! if i don’t have a fn key, certain key combos won’t work, and we get paid to type, so all combos have to work
Ran into the issue of my key mapping not surviving reboots. Had to create a launch agent that runs the hidutil command every time I login.
til finally how to clear notification center via command line, which means i can map it to a keyboard shortcut. why one doesn’t exist natively who knows.
# ~/.zshrc
function clearnc() {
local url=
local filename=~/bin/clear-notifications
if [[ "$1" == "which" ]]; then
echo "${filename}"
return
elif [[ ! -f "${filename}" || "$@" =~ -u ]]; then
echo "Installing latest..."
mkdir -p "$(dirname filename)"
{
echo '#!/usr/bin/env osascript -l JavaScript\n';
curl -sL "${url}"
} > ${filename}
chmod +x ${filename}
fi
${filename} > /dev/null 2>&1
}
# clear notification banners
$ clearnc
# clear notification banners and install latest version of script
$ clearnc -u
Installing latest...
# ... or
$ clearnc --upgrade
Installing latest...
# where's the executable
$ clearnc which
/Users/andelink/bin/clear-notifications
til about . Not sure how I never stumbled upon this before now, but, after skimming, it seems to provide some good deep-dives into why and how to be security-minded, or some summarized recommendations if you can't be assed to do the research but are curious about alternatives.
For example, a list of Android OS alternatives in order of recommendation with a summary of the OS but plenty of links to follow if you want to look deeper
Nice! I’m excited to read after I get out of the shower
Like with everything in life, privacy is all about trade offs. Many of the privacy focused recommendations I assess and think nahh I’m good I’ll take the convenience
Definitely. I've actually grown to appreciate the lack of convenience that comes with it though 😆 it was too convenient to just waste time (or at least, my opinion on what I consider a waste of my personal time)
For me what these enable I don’t view these as a waste of time. These make interacting with my phone so much more pleasant. I’m often wishing I could do more things from a locked phone so I can run shortcuts that do all sorts of things more easily
But then again, I guess with Face ID it should unlock when I look at my phone
If the two seconds that unlocking my phone adds to an operation makes it not worth it, it wasn't worth it in the first place haha
When you do it however many times a day, that adds up fast
That is a pretty specific case though, I was speaking more towards losing my curated lists when I stopped being automatically signed in to websites, for example
Yeah, I agree. But it was seeing these specific recommendations that prompted my comment lol
Because these specific ones I’ve thought about very intentionally in the past and went against
But yeah, the auto signing into websites is a big one
Because these specific ones I’ve thought about very intentionally in the past and went againstThe amount of people that all best privacy practices apply to at all times is probably a very, very small number. I don't think anybody is saying it is realistic to do so, and, if they are, they live in a very different reality 😆 makes sense to make your own decisions
i meant to try this out yesterday but didn’t. let me give it a spin
the reality is git is the greatest tool ever, and too its own detriment, simply because of how much it can do. it’s massive
I love all the stats. What makes this one the best? Is it more accurate for some reason?
What makes this one the best?Oh, simply because of all the stats lol I like all the descriptions, the drop-downs for each of the stats to show the individual measurements. I just think it’s cool
@brandon you had some packet loss! Does it go into any detail about that? What do you see when you hit the packet loss test drop-down?
I don't have the tab anymore unfortunately. I ran the test again though and the packet loss went away so hopefully not a common occurrence!
til about the zen of github api
❯ gh api zen
Responsive is better than fast.
❯ repeat 10 echo $(gh api zen)
Encourage flow.
Favor focus over features.
Avoid administrative distraction.
Practicality beats purity.
Design for failure.
Avoid administrative distraction.
Non-blocking is better than blocking.
Practicality beats purity.
Mind your words, they are important.
Keep it logically awesome.
❯ curl -L -H "Authorization: Bearer ${GITHUB_TOKEN}"
Speak like a human.
@spkaplan another clipboard manager for you to consider:
til about the install command which is basically just an enhanced cp. That's fine and all. But what I like is that I learned about it from a Tinder open source project 😆
The docs mentioned Spotify API keys but I've been using it just fine with Apple Music and no keys supplied by me. I haven't provisioned any keys and I've downloaded like 30 songs maybe today?
Copy to clipboard: If you miss the thumbnail, you can take a screenshot directly to the clipboard by holding the Control key while capturing (e.g., Control + Shift + Command + 3). Then paste it (Command + V) into your desired application.
copy screenshot to clipboard, so you can then just paste it into an llm, vs clicking on "upload image", and finding it in the Finder, etc...
Good tip! It may be that I started on Windows which has this behavior, but one of the first things I did when I got a MacBook for work was to just swap the keybinds so that I copy screenshots to clipboard by default. I think I can count on one hand the number of times that I’ve had to save a screenshot as a file 😆 clipboard is so much more convenient
haha yes, holding control key is a must! Also if you want to grab a snippet of the screen instead of the whole thing, use 4 instead of 3. You don't need to hold control the whole time, just when you click and drag.
I feel like I am pretty good with keybindings, but I cannot get the mac screen capture key binds to stick. I can barely remember one of them
til about this example Chrome extension that "will steal literally everything it can"
The accompanying blog post is a great read and shows how easy it is to work against the users interests without them noticing. I only had four extensions enabled, but it inspired me to uninstall one because it did have somewhat broad permissions and I really don't need it.
The author designed the extension above to, instead of actually exfiltrate the data it collects, to simply present all collected data to you in its popup modal. If you want to do a (very) lazy validation of his claim before installing it as a dev extension, I asked Claude 4 Sonnet to verify it so I don't have to pepe-hacker
I ran it and yeah, it's collected a lot of data. Everything works as expected except for the geolocation capture. I didn't look into why, whether it's outdated or I have some permission disabled somewhere - idk.
I will post a screenshot of my results. It is a 37 page PDF. Most of it is cookies, so let me remove those first and then I'll share
Here you go. I removed 25 pages of cookie values. The remainder is whatever
I like how it takes screenshots of the tab I am viewing
til about the Google udm=14 query parameter and udm14.com. You can append &qdm=14 to your Google search URL to get an ad free, ai free, unnecessary-modal free search. Details in this blog post:
You can update your browser to (or Kagi !g bang) to always include it by default e.g. here's my updated Google search query string: