Butter Beans & Kale

published on 2024-02-16 in uncategorized

Transcribing a recipe for posterity. I keep telling people this tastes like bacon, and it does!

Butter Beans & Kale


  • 3 tbsp olive oil
  • ¼ tsp ccrushed red pepper flakes
  • 15oz can butter beans, rinsed & drained & patted dry
  • 2 garlic cloves, roughly chopped
  • 1 ½ cups kale, tough stems removed, torn into bite sized pieces
  • sea salt & ground pepper
  • 1 tsbp fresh lemon juice
  • fresh parm for serving


  1. Heat oil in a large saucepan over medium heat.
  2. Add red pepper and cook for 30 seconds, stirring often. Add beans, cook 4-5 minutes then flip and cook additional 4-5 minutes.
  3. Stir in garlic, kale, salt & pepper to taste.
  4. Cook until kale wilts ~2 minutes.
  5. Mix in lemon juicce, cook 1 minute longer & all is evenly coated.

Setting up the Vortex Race 3 for Mac

published on 2024-01-08 in computing

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.

  1. Reset everything by pressing L3+R1 for 5 seconds. Left LED will blink white color while you're holding the keys. Release them after it stopeed blinking.
  2. Get into one of the programmable layers (R2+RShift) – red is fine.
  3. Put the keyboard in Windows Mode (R2+W), it's the least problematic one.
  4. Go into programming mode: Fn+R3 right LED should light up white.
  5. Then hit the L2 then L3, then Pn (LED shines white) to finish first move.
  6. Then hit the L3 then L2, then Pn (LED shines white) to finish 2nd move.
  7. R2+R3 to get out of programming mode (LED goes off).


Date/Time SublimeText Plugin

published on 2023-12-07 in computing

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:

  1. In Sublime Text, go to "Tools" > "Developer" > "New Plugin...".
  2. Replace the default code with the following Python script:
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()

        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')
  1. Save the file with somethign like insert_date_time.py in your Sublime Text "Packages" directory.

  2. 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!

published on 2021-11-10 in computing

Awk associative arrays rule!


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


baz 132
foo 517
bar 866

Now, do this on a file with 100,000 lines.

2019 Total Lunar Eclipse

published on 2019-01-23 in science

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.


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.

3D Printed Xmas Tree Ornaments...of your house!

published on 2018-12-23 in howto

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!

3D Printing Plumbing Tools

published on 2018-02-17 in howto

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...


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

published on 2018-02-11 in computing

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",
var days7 =  ["label4",

function auto_delete_mail(userLabel,days) {
  var label = GmailApp.getUserLabelByName(userLabel);
  if(label == null){
    var delayDays = days // Enter # of days before messages are moved to trash
    var maxDate = new Date();
    var threads = label.getThreads();
    for (var i = 0; i < threads.length; i++) {
      if (threads[i].getLastMessageDate()<maxDate){

days31.forEach( function(s) {
} );

days7.forEach( function(s) {
} );

I've also posted it on Github, if you see changes I should make, send me a pull request!

Set Vim as the default editor

published on 2017-01-28 in computing

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


$ 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

Uncomplicated FireWall (UFW) on Ubuntu

published on 2017-01-16 in computing

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

Here's what these rules look like:

# ufw status
Status: active

To                         Action      From
--                         ------      ----
Anywhere                   DENY             
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             
[ 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