Jim Mitchell

I try to diligently plan the tasks I want to get done each day, but there’s always a fire that has to be put out, pushing the planned tasks to the next day - until they become fires of their own.

Tomorrow is a new chance. I’ll just keep telling myself that…

Upped my Micro.blog plan to the premium level over the weekend. Great to have the newsletter option now. Mulling some potential topics for a regular Microcast as well.

I gave in and purchased a Mimestream subscription a little early. I can share the subscription with my wife so that makes the price more palletable. Plus the fact that it’s a damn good 1.0 release made me want to support the development team all the more.

Across the Irvine valley. 📷

Across the valley

Purchased a license for Shottr, a macOS screenshot tool, based on a Micro.blog discussion thread I stumbled on and it’s probably the best $4 I’ve spent in a year. Normally it would be $8, but took advantage of the first week coupon code.

Remembering those who gave it all for our freedom. 📷

Memorial Day remembrance ceremony.

HB Northside Lineup 📷

HB Northside Surf Lineup

If you have multiple domains you’d like to redirect to your Micro.blog domain (or any domain for that matter), and know how to manage your own DNS records, I highly recommend using ForwardDomain.net as a redirect solution.

Blooming cactus 📷

Blooming cactus

Giving Mimestream as spin as my mail client on macOS since I use Google Workspace for my domains. It’s impressive, but a $50/year subscription might be a little steep for me. We’ll see in 12 days.

I’m developing a love/hate relationship with the Copado CI/CD platform for Salesforce deployments. When it works, it’s a dream. When it doesn’t, it’s a pain to figure out why.

I’ve been a WordPress user since the early days and have carried my content with me from one host to another. I think it’s time to put the old content to rest and start fresh with micro.blog.

A Better AppleScript Password Generator

As I continue to explore ChatGPT’s AppleScript code generation capabilities, I fed it a password generation script I came up with years ago and asked it to make it better.

The results were impressive.

My original script didn’t have error-checking or user bailout points. ChatGPT was smart enough to add them for me, along with some other smart “decisions” when it came to copying out the generated password. I did have to make a few edits for correctness.

This is the result, which I’ve opted to start using instead of my old script:

property allowedCharacters : {33, 35, 36, 37, 38, 42, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 61, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}
property givenPasswordLength : 21

repeat while true
        set givenPasswordLength to text returned of (display dialog "Enter desired password length:" with title "Password Generator" default answer givenPasswordLength)
        set givenPasswordLength to givenPasswordLength as integer
        if givenPasswordLength is not greater than 0 then error "Please enter a valid positive integer."
        exit repeat
    on error errMsg
        display alert "Error" message errMsg as warning
        return -- added to ensure proper script exit
    end try
end repeat

repeat while true
        set generatedPassword to generatePassword()
        set dialogResult to (display dialog "New generated password:" & return & return & generatedPassword with title "Password Generator" buttons {"Refresh", "Copy", "Cancel"} default button "Refresh" cancel button "Cancel")
        if button returned of dialogResult is "Copy" then
            set the clipboard to generatedPassword as string
            exit repeat
        else if button returned of dialogResult is "Cancel" then
            exit repeat
        end if
    on error errMsg
        display alert "Error" message errMsg as warning
        return -- added to ensure proper script exit
    end try
end repeat

on generatePassword()
    set generatedPassword to ""
    repeat givenPasswordLength times
        set randomCharacterPosition to random number from 1 to count allowedCharacters
        set generatedPassword to generatedPassword & (ASCII character item randomCharacterPosition of allowedCharacters)
    end repeat
    return generatedPassword
end generatePassword

As always, this improved script works great with FastScripts.

AppleScript to Compress Files or Folders

A while ago, I created an AppleScript that allows you to compress files and folders by simply dropping them onto the applet. A reader left a comment asking for a way to achieve the following tasks:

  1. Select a folder from Finder.
  2. Store the folder name as “x”.
  3. Compress all files and sub-folders within the folder “x”, including their paths.
  4. Rename the resulting zip file as “x.zip”.
  5. Delete all the files that were used to create the zip file.
With the help of ChatGPT, I was able to come up with a solution to this challenge, which can be a great way to manage archives if you’re into that sort of thing.

I must admit that ChatGPT did a decent job in generating the AppleScript, but there were some bugs that I had to fix manually. Nevertheless, it’s both scary and exciting to have a tool that can generate usable code.

As always, you can run this script using FastScripts from your menu bar for quick and easy access.

-- choose files or folders to archive since AppleScript can't seem to allow both at once...
set archiveOption to button returned of (display dialog "Archive files or folders?" buttons {"Cancel", "Folders", "Files"} default button 3)

-- now let's choose what we want to archive...
if archiveOption is "Files" then
    set selectedItems to choose file with prompt "Select files you want to compress:" with multiple selections allowed
else if archiveOption is "Folders" then
    set selectedItems to choose folder with prompt "Select folders you want to compress:" with multiple selections allowed
else if archiveOption is "Cancel" then
end if

-- set the array of files or folders selected...
if the selectedItems is {} then
else if (selectedItems count) is equal to 1 then
    set thePathFilename to the quoted form of POSIX path of (selectedItems as string)
    set thePathFilename to {}
    repeat with i from 1 to (selectedItems count)
        copy (quoted form of POSIX path of (item i of selectedItems as string)) & space to end of thePathFilename
    end repeat
    set thePathFilename to thePathFilename as string
end if

-- coerce a date string for the archive name
set currentDate to current date
set yearStr to year of currentDate as string
set monthStr to (month of currentDate as integer) as string
if length of monthStr = 1 then set monthStr to "0" & monthStr
set dayStr to day of currentDate as string
if length of dayStr = 1 then set dayStr to "0" & dayStr
set currentDateStr to yearStr & "-" & monthStr & "-" & dayStr

-- next, let's name our archive, which defaults to "Archive" & the currentDateStr we just coerced
set archiveName to text returned of (display dialog "Enter a name for your archive:" default answer "Archive " & currentDateStr buttons {"Cancel", "OK"} default button 2)

-- then, let's choose where to save the archive and compress it with the shell "zip" command
set archiveFile to POSIX path of (choose folder with prompt "Choose a location to save the archive:")
do shell script "cd " & quoted form of archiveFile & " && zip -r " & quoted form of archiveName & ".zip " & thePathFilename

-- finally, let's delete the files we just archived if we decide we don't need them around anymore.
set deleteFiles to button returned of (display dialog "Do you want to delete the original files?" buttons {"Yes", "No"} default button 2)
set deleteOption to false
if deleteFiles is "Yes" then
    set deleteOption to true
end if
if deleteOption is equal to true then
    if selectedItems is not {} then
        set fileList to {}
        repeat with itemPath in selectedItems
            set end of fileList to quoted form of POSIX path of itemPath
        end repeat
        repeat with fileItem in fileList
            do shell script "rm " & fileItem
        end repeat
    end if
end if

The Ant Mound

One of my earliest childhood memories still haunts me to this day. I was just a three-and-a-half-year-old boy living with my mother, stepfather, and newborn sister in an old house in the middle of the desert in Lancaster, California. My mother was preoccupied with taking care of my baby sister, so I was often left to my own devices.

One day, I stumbled upon an ant mound in the open area behind our house. Intrigued, I decided to befriend the ants by sitting down next to their mound. Little did I know, these were not your ordinary ants - they were large, red and black ones with powerful jaws. As soon as I sat down, the ants swarmed me, biting me all over my body.

The pain was excruciating, and I panicked. I tried to brush the ants off, but they kept coming. In a frenzy, I stripped off my clothes and ran naked towards the house, screaming for my mother. When I burst into the room where she was nursing my sister, she was shocked to see her little boy covered in red welts, crying uncontrollably.

My mother quickly tended to my wounds, squishing the remaining ants in my hair and applying ointment to soothe the bites. Her care helped calm me down, but the experience left a lasting impression on me. My mother found the whole ordeal hilarious, but for me, it was a traumatic lesson learned.

Since that day, I’ve developed a fear of ants. Even the smallest ones make me jittery, and I can’t shake off the feeling of panic when I see them crawling on me. I’ve never sat on an ant mound again, knowing the consequences all too well. My mother and I reminisced about that incident many times over the years, and it’s a memory that still lingers with me, half a century later.

Memorable Cigarettes

Almost fifty years have passed, and I can still vividly recall the first time I lit a cigarette. I was just a seven-year-old boy, living on a farm in rural Colorado with my mother, step-father (if you could call him that), and half-sister. There were no kids my age nearby to play with, so I often found myself engaging in activities that little boys should not be doing. I had stolen a pack of my mother’s Kool Menthol 100s and a pack of matches, and I thought I could smoke just like the adults in my life.

I sneaked outside and hid behind the juniper trees, feeling a sense of rebellion and curiosity. I opened the pack, took out one of the long cigarettes, put it between my lips, struck a match, and lit up, taking a puff just like I had seen the grown-ups do. To my surprise, I didn’t find the taste repulsive. In fact, I kind of liked it. I remember the sensation of menthol on my tongue, the slight burn in my throat, and feeling strangely grown up.

As I grew older, I experimented with smoking occasionally, but it never really stuck. I would smoke here and there but would eventually lose interest. That changed when I met Tracy, a boy my age who had just moved into the neighborhood. He was already a pack-a-day smoker, and one summer evening, he offered me a Marlboro Red from his hard pack box, explaining that soft packs were not cool. I started taking him up on his offers and before I knew it, I was smoking every day, even bumming cigarettes from friends whenever I could.

Then came the moment I realized I was hooked: I wanted to smoke even when I was alone. My mother, in her unique parenting style, decided to buy cigarettes for me openly rather than have me hide my habit. She hoped I would come to hate smoking and quit, but that didn’t quite go as planned. By the time I was sixteen, I was a confirmed pack-a-day smoker. It wasn’t about being cool like other kids; it was about feeding my nicotine addiction. Twelve years passed in a blur of cigarettes, until I met Pam.

I remember our first date like it was yesterday. We were running across a busy street in Santa Monica, heading to a club to see a band. In the middle of the street, my hard pack of Marlboro Lights fell from my shirt pocket with a loud thud. I quickly picked them up, but when we reached the sidewalk, Pam told me, “I don’t date people who smoke.” It felt like a punch to the face, but it was a wake-up call I needed.

From that moment on, I didn’t light up on any of our dates or any day after that. Pam became my best friend, and we’ve been married for 25 years now. I made the choice to quit smoking because of her, and I’m proud to say that I haven’t touched a cigarette since before we were engaged. I remember many cigarettes I smoked throughout my life, but thanks to someone special, I can’t recall the very last one. And for that, I’m eternally grateful.

AppleScript to Add Files in the Mac Finder

Today I had the need to add a bunch of named text files to a folder in the Finder on my Mac.

I found it a major pain to open BBEdit, make a new document, save it to where I wanted it, and then manually copy & rename the file back in the Finder. A lot of effort just to get 7 or 8 empty files with different names.

So, I threw together this little AppleScript to add empty files instead. The gist is once launched in the Finder (using FastScripts by Red Sweater naturally. Keystroke: cmd+option+shift+N), a dialog pops up that lets you enter a file title. Then the Finder creates that file in the front-most window. If no window is open, the file is added to your Desktop.

I found this to be more than twice as fast as the “traditional” method of making several files. Hopefully, it can help you out too. Remember, use it with FastScripts for quick keystroke access. Save as a script in the “Finder” scripts folder (“~/Library/Scripts/Applications/Finder/”).

property defaultFileName : "newFile.txt"
tell me to activate
set theFileName to text returned of (display dialog "Enter a file name:" default answer defaultFileName)
tell application "Finder"
    if the (count of windows) is not 0 then
        set theFolder to (folder of the front window) as text
        set theFolder to POSIX path of theFolder
        set theFolder to POSIX path of (get path to desktop)
    end if
    set addedFile to (theFolder & theFileName)
    do shell script "touch '" & addedFile & "'"
    if the (count of windows) is not 0 then
        set addedFile to (POSIX file addedFile) as alias
        select addedFile
    end if
end tell

AppleScript to Toggle the Mac Desktop

Here’s an AppleScript I use to quickly toggle desktop visibility for taking screenshots and recording screencasts that I thought might be useful for others.

Copy and paste the code below into AppleScript Editor, or your editor of choice, compile and save. As always, scripts like this work best using FastScripts from Red Sweater Software.

tell application "System Events"
    set frontMostApp to short name of the first process whose frontmost is true
end tell
    set theDefault to ((do shell script "defaults read com.apple.finder CreateDesktop") as integer) as boolean
on error -- if the default value doesn't already exist, create it.
    do shell script "defaults write com.apple.finder CreateDesktop 1"
    set theDefault to ((do shell script "defaults read com.apple.finder CreateDesktop") as integer) as boolean
end try
do shell script "defaults write com.apple.finder CreateDesktop " & (((not theDefault) as integer) as string)
tell application "Finder" to quit
delay 1
tell application "Finder" to launch
tell application "System Events"
    set the frontmost of process frontMostApp to true
end tell

Note: This single script turns off the desktop if it’s on, and turns it on if it’s off - just to clear up the question should it need to be asked.