TextBuddy Custom Links

Part of the Automation series

TextBuddy is a macOS utility app I love that lets you process text in all sorts of interesting ways. I actually intend to talk about it in detail more some time, or more likely write several posts about it highlighting specific use cases. Today I learned about a feature of TextBuddy called Custom Links that I’d been woefully unaware of.

Custom Links basically applies regular expressions to any text in TextBuddy’s text window and turns matches for any of the regular expressions into clickable links based on your specification.

Huh?

It sounds more confusing than it is. Here’s an example that works perfectly, even if it’s not necessarily the best or only way to solve this problem. But it is a an instance of something that produces unhelpful link fragments that I want to convert to useful, clickable links.

Let’s say you get emails from your ticketing system and they include links to the ticket in question that look like the following:

TicketEmail

<URL: /Ticket/Display.html?id=89285 > is not a useful link, but if you add your RT instance’s domain name to it, it can be. That’s where TextBuddy’s Custom Links feature comes in.

First of all, copying text from any app to TextBuddy is simple – just highlight the text, and choose Services - Send to TextBuddy from the app menu (the menu with the app’s name in it, like Chrome in this case) or right-click the highlighted text and choose Services - Send to TextBuddy.

ServicesMenu

This results in the following text in TextBuddy’s text window in my case.

TextBuddyNoLink

Yeah, that Ticket URL is still not helpful.

To set up the Custom Link, click the TextBuddy Scripts menu and choose “Reveal Secret Custom Links File”. This opens a finder window to ~/Library/Application Support/com.clickontyler.TextBuddy, revealing a file called CustomLinks.txt.

CustomLinksFileMenuOption

CustomLinksTextFile

Open the file in an editor. If you haven’t added anything to it previously, it’ll be empty. This file should contain two lines per Custom Link – the first line for the regular expression and the second line to act as a template for the URL to create for the Custom Link. In my example case, I added the following two lines:

Ticket <URL\: \/Ticket\/Display\.html\?id=([0-9]{4,6}) >
https://rt.domain.com/Ticket/Display.html?id={{1}}

This looks for anything that looks like <URL: /Ticket/Display.html?id=12345 > , where 12345 can be any 4 to 6 digit number, and uses that number to create a URL of https://rt.domain.com/Ticket/Display.html?id=12345 from it.

I guess in retrospect I could have included everything from Ticket through the number in the capture group instead of just the number itself. Then I could have simplified the url template string. That method looks like this:

Ticket <URL\: (\/Ticket\/Display\.html\?id=[0-9]{4,6}) >
https://rt.domain.com{{1}}

The change to the regular expression is subtle – I move the first parenthesis for the capture group from right in front of [0-9] to right in front of \/Ticket instead.

Once you have what you want, save the file so that your regular expression and URL template string can go into effect.

Now you can highlight the offending text in your email and choose Services - Send to TextBuddy from your browser’s app menu (the menu with the browser’s name, such as Chrome in this example) to get it into TextBuddy’s text window.

And thanks to the magic of Custom Links, although the link in the copied text LOOKS the same in TextBuddy, it’s now a clickable link with the correct URL as the target.

TextBuddyClickableLink

By the way, I tested my regular expression in BBEdit using its Pattern Playground feature. If you have BBEdit and you haven’t used this yet, you can find it in the File menu under “New - Pattern Playground”, or in the Search menu’s “Pattern Playground” option.

BBEditPatternPlayground

11 Ways to Check Linux/Unix Operating System Uptime - Adamsdesk

Well, this is a fun one from Adam Douglas. I knew most of these, but a couple are new. And that video? Definitely new to me. 😄

The system uptime can be a useful metric to determine when was the last time a computer or device was booted when paired with an issue or incident. By its self it is not always a vital metric, even though historically some wish to achieve the longest uptime possible. It all depends on the circumstances. No matter what your reasoning might be, let’s take a look at the definition of system uptime, the test environment, assumptions, the various methods used to obtain a GNU/Linux or Unix operating system’s uptime and finally the conclusion with a fun entertaining bonus.

11 Ways to Check Linux/Unix Operating System Uptime - Adamsdesk

Small Web, Indie Web

If you’re the kind of person I imagine would find and read this, you’ve read a ton of words already on the concepts of small web, indie web, and personal websites. I’m not going to pretend that my post is the one you have been waiting for on the topic, but I do want to say a couple things about the inspiration I’ve received from some of these people.

I’ve had my own website for years and years in various incarnations. No one ever reads it, to the best of my knowledge, and (like my podcasts) I’m kind of shouting into the void. But I don’t care, and here’s why:

I love the indie web. I love the modern take on personal websites. They are about linking and sharing and going down rabbit holes in a way that the way USED to be about, but now with modern design and personal touches of whimsy. In a way, as terrible as the mainstream web has become, infected with an almost certainly incurable cancer of advertising-driven enshiteification (sic), the indie web, the small web, the personal web is better than ever. And it makes the internet better than ever too, if you just focus your attention.

Nowhere is this better presented than Rachel’s The internet used to be fun project, which I’ve spotlighted in my current Cool Site Spotlight on my Links page. In case you’re a doubter, or you just haven’t noticed yet that many good people are actively trying to bring back the soul of the internet, Rachel’s got link after link of smart person after smart person talking about this trend and its importance.

The internet used to be fun

And it is important, dammit. The web doesn’t have to be total garbage. The people that have ruined everything with advertising technology that makes the web impossible to read and allows bad actors to stuff it full of malware don’t care about you, and it’s time to stop caring about them. To hell with them and the dumb billion dollar horsey they rode in on. It’s time to focus on the good and @#$@ those other guys and their terrible way of making a living.1

Anyway, here’s to Rachel and here’s to all the sites she links to. Let’s all link to them, and let’s all link to each other.

Footnotes

  1. I want to make it VERY clear that I wholly support and endorse small sites and podcasts that also make a living with sponsors, but who don’t employ user-hostile ad technology. I’m talking about the Six Colors and MacStories and Daring Fireballs of the world, stuff like that . Things you know with sponsors that don’t piss you off every time you visit them.

Cool Site Spotlight

Did you know my Links page has an ever-changing Cool Site Spotlight? I’ve mentioned it tangentially before, but I want to mention both it and my Links page specifically now because I think both are pretty cool.

I started my Links page in January of 2024 with the intention of making it a blogroll, but it’s much more than that now. For one thing, right at the top is a Cool Site Spotlight highlighting one site I’ve stumbled across that I think is unusually neat. I rotate entries out into the Cool Sites Archive section of the Links page as I highlight a new one.

Not only does this keep me interested and looking around me, it should serve as a good idea and interest generator for my readers too.

If the web is ever going to be cool again, this is how it starts: finding and linking to things that make it a better place.

Really Specifically

Here’s a pitch for you: how’d you like to listen to a podcast that is both fascinating from the perspective of being about tech nerdery and podcasts in general AND that is also part of a PhD project? There can only be one that fits this definition, and it’s Martin Feld’s Really Specific Stories podcast.

If you haven’t listened, you should. Don’t start with the latest episode though (featuring yours truly), start from the beginning or pick any other episode at random and get a feel for what this project is all about.

I really enjoy the intentional way that Martin delves into the topic of what podcasts mean to people and how they interact with and/or produce them. He digs deeply into people’s relationships with podcasting in a way that I haven’t heard anywhere else.

I’m sure Adam Curry has uttered more words on the concept of podcasting, but I’d be hard pressed to imagine any of it is as illuminating or focused on understanding what podcasting is all about as Really Specific Stories is.

ScreenFloat Your Screenshots

One of the brilliant features of macOS is its built-in screenshot tools. Not all operating systems are as aware of the fact that people need to take screenshots and edit and annotate them quickly as macOS appears to be. Even so, many excellent third-party utilities exist to take this to eleven.

The App – ScreenFloat

If I start talking about the options and making comparisons, I’m going to get into a holy war and I don’t want that.1 Therefore, I’m treating my coverage of macOS screenshot utilities like it’s a Highlander. THERE CAN BE ONLY ONE! And that one’s name is ScreenFloat.

ScreenFloat Windows

ScreenFloat has a lot of ideas, and those ideas are translated into features. It can be a bit overwhelming, but in reality it’s fairly easy to wrap your head around the features you’ll use most, and then you can dig into customizing the app and really getting some work done. That second point is important because when I first started using ScreenFloat, I was missing some of my workflow from Shottr. But the good news is I was able to get back quick annotation and copy to clipboard functionality with ScreenFloat just by making a couple of tweaks.

The Premise

ScreenFloat’s main premise is that you may want to take a screenshot and then float it above other windows so you can use it as a reference or so that you can drag it easily into other apps. The good news is that this can be very helpful. The bad news is that sometimes floating windows get in the way. The good news is that you can close a floating window with a keyboard shortcut or by clicking on its window close control, and ScreenFloat will keep it in the Shots Browser to be recalled at any time.

ScreenFloat Shots Browser

If you use the keyboard shortcut to close (actually hide) the floating screenshot, you can open it again (unhide, technically) with the same keyboard shortcut. Once you close by clicking the window close control, however, you’ll have to open the Shots Browser window and double-click it to get it back into Floating Shot mode.

The Features

Floating Shots can have actions performed on them – annotating, exporting, cropping, sharing, dragging, and dropping, and more.

Dragging and Dropping

Dragging and dropping and super quick file saving can be performed by the Floating Shot’s File Drag Control2.

ScreenFloat Drag and Drop Control

This lets you quickly drag the screenshot into Messages , an email, or even into Finder to quick save the image to disk.

Note that you can still export the file with options by clicking on the Floating Shot’s Action Menu3, clicking Export… and making some simple choices.

ScreenFloat Action Menu

Speaking of that Action Menu…

Action Menu

The Action Menu has a lot of the things you’d expect – Copy, Open Copy With, Export, Crop, Annotate, and more.

ScreenFloat Action Menu Options

One of the “more” things is Data Detection. ScreenFloat lets you detect text and copy it or redact it as desired. It’s really pretty magical.

Another thing I use all the time in the Action Menu is Annotate. The annotation options are comprehensive and are customizable before and after creating an annotation. For example, you can double click the rectangle outline tool to customize it or you can just click it once, draw a rectangle, and then click the Select tool to edit the rectangle you’ve just drawn. This same methodology holds true for all the annotation tools: Draw, Rectangle, Oval, Line, Arrow, Star, Checkmark, X-mark, Text, Numbered List, Callout, and Redact.

ScreenFloat Rectangle Options

ScreenFloat Rectangle Editing

Numbered List isn’t exactly what it sounds like. It lets you drop numbers on an image in order to call out steps or set the order of items of interest. If you’re making a screenshot to show someone the order to click things on a UI, this is what you want.

ScreenFloat Numbered List Options

Redact lets you redact with a solid color, complete with the ability to set the color from swatches or a color picker, or the common pixelation redaction, or with a strange gradient looking blur effect that I don’t think I’ll ever use. This is in addition to the Data Detection and its ability to redact, although the redactions are the same style and can also be edited in the same way as the manual redactions by selecting them with the Select tool.

ScreenFloat Redaction Options

Double-Click Workflows

The eagle-eyed amongst you may have noticed that Annotate is stuck in the Action Menu and therefore it takes extra clicking after grabbing a screenshot to be able to annotate it. Other apps, like Shottr, drop you into a view that shows you annotation tools immediately after capturing the screenshot. The good news is, ScreenFloat lets you create double-click workflows that get you very close to that simplicity.

In ScreenFloat’s settings, on the Floating Shots tab, you can set actions that occur when double-clicking with or without modifier keys. In my case, if I double-click a floating shot without modifiers, it copies the image to the clipboard. If I double-click it while holding command, it immediately jumps into Annotate mode without me having to use the Action Menu to select it.

ScreenFloat Double-Click Copy Workflow

ScreenFloat Double-Click Annotate Workflow

I also have modifiers to double-click and resize the floating window up or down by 50%.

It’s a very clever and endlessly customizable way to create shortcuts to editing actions that you’ll use all the time.

Shots Browser

Floating screen shots are one thing, but what about if you want to recall one, or annotate it or export or otherwise save it later? ScreenFloat has you covered. Every snapshot you take goes into the Shots Browser, which can be recalled at any time with a keyboard shortcut, such as ⌘-⇧-1.

ScreenFloat Shots Browser

With Shots Browser, you can double-click an image to make it a Floating Shot again, so you can annotate or do whatever you want with it. But you can also drag images straight from the Shots Browser to other apps, which makes it handy for taking a bunch of screenshots for, say, a blog post, closing the resulting Floating Shot, and then getting them from the Shots Browser later when you’re ready to use them in your writing.

The Shots Browser feature is really nice if you’re using screenshots to document a procedure and you want to get all your shots in one place to edit and choose from later.

You can also go really crazy and create folders, smart folders, tags, descriptions, and ratings. Like I said, ScreenFloat does not skimp on features.

Export Options

Of course besides the usual drag and drop and open copy in options, you can export a Floating Shot using the Actions menu and Choosing Export. You can choose options related to naming, format, whether or not to include annotations, size, alpha, and whether or not to reduce dpi resolution.

ScreenFloat Export Options

The Conclusion

Honestly, what pushed me back to using ScreenFloat wholeheartedly was discovering the customization options for all the annotations and the double-click workflows. Being able to quickly copy something to the clipboard or jump right into annotating it are things I can’t live without.

ScreenFloat is a very powerful, very customizable screenshot tool for the Mac that I think trounces most of the competition. The other one I’d recommend is Shottr, which takes a much simpler but still feature-rich approach. It’s another great application. For me though, ScreenFloat wins easily with its Shots Browser, Floating Shots, and easy customization with workflows and tool options.

Footnotes

  1. xNapper fans are especially zealous, in my experience. I understand – it’s a great app, but still. Breathe, people.

  2. I don’t know if that’s what Matthias calls it, but it’s what I call it until I find out otherwise.

  3. Again, I have no idea if this is the correct name for this UI element, but it sounds good.

Raycast Script Command for Text Parsing

Raycast

Part of the Raycast series

I previously wrote about using Raycast script commands to switch default browsers. Raycast script commands are really good for scripting all kinds of other things too. One example is a Python script command I created yesterday for the purpose of grabbing a couple values from a JSON file and formatting them into a markdown hyperlink and putting it on the clipboard.

On my site’s Links page, I have a Cool Site Spotlight section at the top which I use to showcase some cool site or other for a short, random period of time. The data for this Cool Site Spotlight is saved in a JSON file that looks like this:

src/data/spotlight.json
{
"Site": "https://ericportis.com/posts/2024/okay-color-spaces/",
"Title": "Okay, Color Spaces",
"Description": "What is a color space? Why should you care? Do you like interactive visualizations to help you learn things? Do you like cool sites regardless of topic? If the answer to at least one of these questions is \"YEAH, I LIKE THAT!!!!!?!!!\", then you need to spend some time here.",
"Image": "OkColorSpaces-036630FA-D437-4101-A5AB-7C7338DCD953"
}

My Astro Links page uses an Astro component to create the web view based on this data in spotlight.json.

src/components/Spotlight.astro
---
import { Icon } from "astro-icon/components";
import { Image } from "astro:assets";
import spotlight from "../data/spotlight.json";
---
<div class="spotlight">
<h1>Cool Site Spotlight</h1>
<div class="spotlight-details">
<div>
<a href={spotlight.Site}>
<Image
src={import(`../assets/images/posts/${spotlight.Image}.png`)}
width="300"
densities={[2, 3]}
alt={spotlight.Title}
/>
</a>
</div>
<div>
<h4><a href={spotlight.Site}>{spotlight.Title}</a></h4>
<p>{spotlight.Description}</p>
<p>
<a href={spotlight.Site}><Icon name="fluent:globe-star-20-regular" /></a
>
<a href={spotlight.Site}>{spotlight.Site}</a>
</p>
</div>
</div>
</div>

You can probably argue about why I used a JSON file for this section, but basically it’s because the view is complicated enough that letting Astro create it from Markdown wasn’t going to work and I did not want to mix data and UI in my Spotlight.astro component. Having an Astro component map JSON file data, on the other hand, is super easy and lets me keep the site info separate from the Cool Site Spotlight UI implementation.

Everything else in the Links page comes from a standard markdown content page located in src/content/links/links.md. The Cool Sites section of the Links page comes from this portion of links.md:

src/content/links/links.md
## Cool Sites
- [Lene Saile, developer and designer living in Madrid](https://www.lenesaile.com/)
- [omg.lol - A lovable web page and email address, just for you](https://home.omg.lol/)
- [PDX Food Weeks](https://pdx-food-weeks.vercel.app/)
- [samwho](https://samwho.dev/)
- [VKC.sh | Veronica Explains – Veronica explains even more](https://vkc.sh/)
- [The Yesterweb - Reclaiming the Internet](https://yesterweb.org/)

When I want to change the site that I’m spotlighting, I put the currently spotlighted site in this section of links.md and then put the new site data in the JSON file. Up until now, this has meant manually copying the Title value and the Site value out of spotlight.json and manually writing out the markdown link in the Cool Sites section of links.md.

Yesterday I finally realized I was tired of copying twice and pasting twice and typing all the markdown formatting characters just to move a link to a website from one part of my Links page to another. My solution was to create a Raycast script command that does it for me.

I created my script command the standard way by using the Raycast “Create Script Command” command and filling in some information. I chose the Python template, set it to Full Output just so I can see what the transformation looks like, gave it the title Spotlight Site to Cool Site, which is what this command will show up in Raycast as, and gave it a description and a package name.

I don’t actually know what the package name does for me, but I like to set similar items to the same Package Name just to be sure. All script commands that are for working on the website go in the Website package name.

Creating the Spotlight Site to Cool Site script command

This creates a relatively empty command script in the directory of my choosing (I put them all in a folder called ~/Scripts/Raycast/script commands) containing one line of Python. I tend to edit my script commands in BBEdit (as opposed to VSCode, which I use for website development and some other types of programming), so I fired it up and made the following very small, very simple Python script.

~/Scripts/Raycast/script commands/spotlight-site-to-cool-site.py
#!/usr/bin/env python3
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Spotlight site to Cool Site
# @raycast.mode fullOutput
# Optional parameters:
# @raycast.packageName Website
# Documentation:
# @raycast.description Coverts Spotlight.json to markdown link
# @raycast.author scott_willsey
# @raycast.authorURL https://raycast.com/scott_willsey
import pyperclip
import json
# Open the Spotlight JSON file
with open('/Users/scott/Sites/scottwillsey/src/data/spotlight.json', 'r') as f:
data = json.load(f)
# Get the 'Site' and 'Title' values
site = data.get('Site')
title = data.get('Title')
# Create a markdown link
markdown_link = f'- [{title}]({site})'
pyperclip.copy(markdown_link)

A full half of it is headers for things Raycast needs to know. The other half is the Python script. It’s very simple.

First it opens /Users/scott/Sites/scottwillsey/src/data/spotlight.json for reading and loads the data as JSON. It then grabs the values for the “Site” and “Title” keys. It then creates a variable called markdown_link formatted as - [{title}]({site}) with those values inserted correctly to create a markdown hyperlink, and copies that to the clipboard using pyperclip.copy.

Regarding pyperclip: “Pyperclip is a cross-platform Python module for copy and paste clipboard functions. It works with Python 2 and 3.”.

You can install pyperclip using pip, which brings up a whole thing about Python and how you install it and how that affects importing things using pip, but I won’t go there today. But suffice it to say that the Python world is a mess when it comes to ease of use and maintainability. A whole lot of someones should be super ashamed of themselves for letting this situation occur and then fester.

Suffice it to say that you need to install pyperclip on your Mac for this to work. Good luck.

To run the command script, I hit the Raycast hotkey (⌘-, in my case), and start typing “Spotlight”. When I see what I want, I hit Return if it’s the first in the list, or ⌘ and the number of its place in the list if not. Bam – it executes and I have my link in my clipboard.

Running the Spotlight Site to Cool Site script command

This is an extremely simple example of a Raycast script command, but it illustrates that you can very easily perform all kinds of scripted actions without having to write a full Raycast extension or without having to open the Finder or terminal, go to a script directory, and running a script manually. Running a command script through Raycast will always be quicker.