Transcribing a recipe for posterity. I keep telling people this tastes like bacon, and it does!
Every year or so, my Vortex Race 3 keyboard seems to reset itsself. Not sure if it's me, or a combo of how my various docks interact w/it, but I find myself stuck on the default layout and having to research how to set it up for a Mac again. For posterity and anyone else having this issue, here's my steps to a Mac user's minimal maintenance setup on the Race 3:
Keys look like this:
[ L1 ][ L2 ][ L3 ][ Space ][ R1 ][ R2 ][ R3 ]
We're going to reset it, swap to a programmable layer, switch to windows mode (it's the least problematic) and then swap the alt and command keys (L2/L3). That's it.
L3+R1
for 5 seconds. Left LED will blink white color while you're holding the keys. Release them after it stopeed blinking.R2+RShift
) – red is fine.R2+W
), it's the least problematic one.Fn+R3
right LED should light up white.L2
then L3
, then Pn
(LED shines white) to finish first move. L3
then L2
, then Pn
(LED shines white) to finish 2nd move. R2+R3
to get out of programming mode (LED goes off).References:
I keep a daily log in a markdown doc and have been manually typing the day and time in for a few months now. My editor is SublimeText, which supports python plugins so I figured this could be done pretty easily. Here's what I came up with after a few minutes:
import sublime import sublime_plugin from datetime import datetime, timezone class InsertDateTimeCommand(sublime_plugin.TextCommand): def run(self, edit, date_or_time): if date_or_time == "date": content = self.generate_date_string() elif date_or_time == "time": content = self.generate_time_string() else: return self.insert_content(edit, content) def generate_date_string(self): now = datetime.now() formatted_date = now.strftime("%A %Y-%m-%d") return f"{formatted_date}\n{'=' * len(formatted_date)}" def generate_time_string(self): now = datetime.now(timezone.utc) local_time = now.astimezone() utc_time = now.strftime("%H:%M:%S UTC") local_time_str = local_time.strftime("%I:%M:%S %p %Z") return f"{local_time_str} ({utc_time})" def insert_content(self, edit, content): for region in self.view.sel(): self.view.insert(edit, region.begin(), content + '\n')
Save the file with somethign like insert_date_time.py
in your Sublime Text "Packages" directory.
Now, you can create a key binding to trigger this command. Go to "Preferences" > "Key Bindings" and add a binding similar to the following:
[ { "keys": ["ctrl+shift+d"], "command": "insert_date_time", "args": {"date_or_time": "date"} }, { "keys": ["ctrl+shift+t"], "command": "insert_date_time", "args": {"date_or_time": "time"} } ]
Now, when you press ctrl+shift+d
, it will insert the current date, and pressing ctrl+shift+t
will insert the current time along with UTC time.
Looks like this:
Thursday 2023-12-07
===================
And this:
12:38:05 PM CST (18:38:05 UTC)
Awk associative arrays rule!
file.dat:
foo 234
bar 43
baz 109
bar 823
foo 283
baz 23
awk '{a[$1] += $2} END {for (i in a) print i,a[i]}' file.dat
output:
baz 132
foo 517
bar 866
Now, do this on a file with 100,000 lines.
The Total Lunar Eclipse this past weekend was amazing! I had set up some new photography gear to take pictures and was really looking forward to some great shots. I set up my camera gear, which was a Fuji X-T2 mated to an older Canon FD300mmF4L mounted on an Omegon Mini Track LX2. The Mini Track is a mechanical wind-up motorized equatorial mount for astrophotography.
Unfortunately, the cloud cover was huge. I got a few early shots just after the partial started and then the clouds took over. It wasn't until 2 hours later I noticed a break in the clouds headed our way.
YES!
And there it was! So pretty! Really incredible, and am I seeing purple? Definitely my favorite shot of the 100 or so I took.
The clouds were clear for a few moments, so I dragged both my sleeping kids out of their warm bed into the 20 degree night to show them the sky. Neither of them cared and only wanted to go back inside. Youth!
Clouds started to come back in so I got a few wide angle shots to capture the beauty of the night sky during the total.
I also shot some bracketed exposures and spent a few hours aligning and processing to produce this detailed image.
I took a ton of shots. I think the mini track really helped as I didn't have to worry about lengthy exposure times with the longer lens. And I didn't have to move the camera every couple minutes. It's going to be a great addition to my astrophotography setup.
My gallery of shots here.
A few weeks ago, I made a model of our house in 3D. We've been discussing a home remodel project and I've been trying to get better at CAD...so it seemed like a useful way to learn a bit more. I fired up my software of choice (OpenSCAD), did a bunch of measuring, and modeled out an accurate scale representation of our humble abode. I made functions for everything: a building with a gable roof, gabled dormers, shed porch, chimney, etc. After I was satisfied with the accuracy, I sat down to show the rendering to my wife so we could discuss the remodel. And, just for fun, I had printed up the result (in PLA at 150 microns). It was 1mm for each foot which made it 304:1 scale.
Her first comment:
"This would be a great Christmas tree ornament! Hey, you should make these for our family this year! Maybe paint them and put snow on the roof too?"
Now, that's a fantastic idea! Never done anything like this before! That week I picked up some modeling paint, some fake snow for the roof, and some tiny hooks.
At home, I was able to quickly go outside with a measuring tape and get all the dimensions I'd need. But some of my family lives 2000+ miles away, and I didn't want to give it away by asking questions. However, most property tax records are public and many of them include building dimensions. I was able to look up all my relatives but one. Looked like this:
One of my brothers didn't have a sophisticated county website with dimensions, but I was able to find basic dimensions from his deed and used pictures and views from Google maps to approximate the rest.
I had to write some more modules for bay windows, decks, porches with decks, porches with columns, etc - and after that was done it only took me about 30-45 min per house to do the modeling. I'd say I spent an hour per night on it, for about a week.
Once I had the CAD done, I got to printing. Printed in PLA at 150 microns on my Prusa MK2S. Some of the models needed tweaking, the columns didn't work, or I got updated info on dimensions..."Hey, did your tree touch the ceiling this year? Nice one, Griswold. So....how tall was that?" etc.
After the models were printed, I sat down one Saturday afternoon, and got to work. The most uncertain part of this project was determining where the center of gravity would be for the hook, so they would hang straight on the tree. Houses are not especially symmetrical, one was even shaped like a U! I used some sharp tools and grabbed the little houses by the edges to get a rough idea and then just kinda winged it. Tested my method out on one of the early non-usable prints I made - drilled a tiny hole with the drill and tested it out - nailed it! I was able to get them all close enough that balance could be adjusted with a little bit of angle on the screw-in hook.
Painting is't something I'm good at or have done much of, but gotta start somewhere. Unscrewed the hooks and got out the paints. I chose gold, with white accents and a red front door. It seemed Christmas-y to me. 2 coats of paint were needed, the print layers seemed to absorb the paint. It was painstaking work and I felt like I was going to go blind, but they looked pretty great in the end. Painting the red front door was hard and took forever, but worth it! As I finished up, I made a mistake with white paint near a roofline...but realized it looked like an icicle. So, I added little icicles to them all, super cute looking.
The snow I had ordered was made from crushed glass - and I tested it out on a test house - I coated the roof of the house with glue and poured it on. Wow! It was really beautiful and sparkly...but the bits were too big. Didn't look like snow. So, I just used some white glitter instead and it looked much more realistic.
Boy they look good! The gold paint is shiny!
I was struggling to figure out what to put these neat little ornaments in...cardboard boxes were all way too big and weren't nice enough - so at the last minute I decided to design and print a clear box, so they'd have something to store them in each year. And made it oddly shaped while I was at it, because why not!
I mailed 2 of them off and gave the rest out at family xmas a few days later. They were a hit! Check out the pics of them on the tree!
Merry Christmas!
This weekend, I was doing a little kitchen faucet replacement and ran into some trouble removing the old Moen hardware. Moen faucets come with this install tool that's similar to a thin-wall deep socket but longer, thinner, and completely hollow. And, I’ve learned if you don’t have the tool, it’s neary impossible to remove the faucet without damaging the sink. Especially when it's 20 years old and corroded like the one I'm removing. Earlier this week, I had tried in vain to remove it without the tool...and ended up at Home Depot advicing with the plumbing dude, who sold me a tool that would definitely do the trick. Fast forward to today, I have the sink tore apart, discovered the HD basin wrench is hopeless for the Moen faucet, and realized the only way to remove this thing is to buy a $17 plastic tool from Moen (part # 118305)...that I’ll never use again. It looks like one of these, my faucet probably came with top right:
This tool is not available anywhere locally. The fastest I could get it here is next week, which means I have to reassemble everything so the family can use the kitchen in the mean time. I confessed to my wife the situation I'd created, and was considering drastic measures aka. brute force, without the tool (miserable). She asked what the Moen tool looked like - when I told her it was a plastic tool, she said "Plastic? Why don't you just print one?" Damn, I wish I'd thought of that earlier! 😍
So, set to work immediatly to make my own. I did some measuring & designed one in OpenSCAD. Mine has a 1/2 socket in the bottom for a wrench and knobs to turn it by hand. It should slip right over the nut and twist it off...if it's strong enough. Here's what my Moen tool looks like:
Here it is ready for printing:
I printed it in black PLA, at 100% infill with a 0.35mm layer height...it took about an hour and cost me 65 cents in material. Here is a video of it printing, if you're so inclined. And here it is going to work:
At this point, I just assumed that the first twist would snap something. But instead...
SUCCESS!
I can't believe it worked...I had read about other folks actually breaking the plastic Moen tool so I was skeptical it would hold up to the stress of a corroded & rusted nut. How I was wrong...I squeezed the hell out of it with vice grips and torqued on it hard with a socket wrench. Right out of the gate I turned it the wrong direction a whole turn before I realized it - if it was ever gonna break, it would have broken then. It's got serious battle scars but performed flawlessly!
If you find this useful, I've uploaded the files here and also to Thingiverse. If you're searching the web for this exact problem and don't have a 3D printer, let me know and I'll mail you my used 3D-printed tool. It's still good! 😎
P.S. New Hotness:
Automating GMail cleanup tasks turned out to be a great time saver for me. I get a lot of mail from automated processes I need to see, but don't need to keep for long. One example is monitoring alerts, another is admin/root type emails. Yet another is email notifications from services like NextDoor, YouTube, Google Calendar, etc. I get a ton of these and I just don't need to reference them beyond a few days. Part of my weekly (sometimes daily) routine included cleaning these up. At best, a 30 second interruption. At worst, kill my email for half an hour with the dreaded "Temporary Error". So, I wrote a little script to do this for me automatically, based on labels. Now I just read & archive them (or whatever) and the script does the rest. No more cleanups and my mailbox is far more tolerable for searching.
My script is below. Follow the instructions on the GMail page here and paste the content of my script instead. Name it 'Email Cleanup' or something like that. You'll need to update the labels to match the labels you want to use to clean up.
var days31 = ["label1",
"label2",
"label3"];
var days7 = ["label4",
"label5",
"label6",
"label7"];
function auto_delete_mail(userLabel,days) {
var label = GmailApp.getUserLabelByName(userLabel);
if(label == null){
GmailApp.createLabel(userLabel);
}
else{
var delayDays = days // Enter # of days before messages are moved to trash
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()-delayDays);
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
if (threads[i].getLastMessageDate()<maxDate){
threads[i].moveToTrash();
}
}
}
}
days31.forEach( function(s) {
auto_delete_mail(s,"31")
} );
days7.forEach( function(s) {
auto_delete_mail(s,"7")
} );
I've also posted it on Github, if you see changes I should make, send me a pull request!
It just kills me when I type git commit or some other such command on a newly configured machine and up comes nano or (worse!) pico. And, I so infrequently have to do this that I can never remember it - so, for posterity:
To set your default editor (to Vim) on Ubuntu:
update-alternatives --config editor
Ex:
$ sudo update-alternatives --config editor
There are 4 choices for the alternative editor (providing /usr/bin/editor).
Selection Path Priority Status
-----------------------------------------------------------
0 /bin/nano 40 auto mode
1 /bin/ed -100 manual mode
2 /bin/nano 40 manual mode
* 3 /usr/bin/vim.basic 30 manual mode
4 /usr/bin/vim.tiny 10 manual mode
Press <enter> to keep the current choice[*], or type selection number: 3
UFW is a pretty simple to use firewall wrapper for Ubuntu. Recently, I have been using it to block spammers on a little service I run for the Nashville Tech community. I used to do this with iptables directly, but this is far simpler.
Here's a quick primer on firing it up and blocking a particular IP address. It's disabled by default so you need to allow your services and then turn it on:
ufw allow ssh/tcp ufw allow 80/tcp ufw logging on ufw enable ufw status
Order matters - once a rule is matched the others will not be evaluated. So, to block that IP, you need to insert it early:
ufw insert 1 deny from 16.16.9.0/24
Here's what these rules look like:
# ufw status Status: active To Action From -- ------ ---- Anywhere DENY 16.16.9.0/24 22/tcp ALLOW Anywhere 80/tcp ALLOW Anywhere 22/tcp (v6) ALLOW Anywhere (v6) 80/tcp (v6) ALLOW Anywhere (v6)
And you can number the output to make it easy to clean up or delete your rules:
# ufw status numbered Status: active To Action From -- ------ ---- [ 1] Anywhere DENY IN 16.16.9.0/24 [ 2] 22/tcp ALLOW IN Anywhere [ 3] 80/tcp ALLOW IN Anywhere [ 4] 22/tcp (v6) ALLOW IN Anywhere (v6) [ 5] 80/tcp (v6) ALLOW IN Anywhere (v6)
To delete one it'd be ex: ufw delete 1