NSTextView (Plain Text) and the Pasteboard: PasteboardType.string Is Not Handled

For a plain text (not rich text/RTF) NSTextView, I found that: Since NSTextView doesn’t understand the NSPasteboard.PasteboardType.string pasteboard type for reading or writing, I tried two approaches to handle plain text input (pasting) and output (cut/copy): The backport seems to work, but extending supported types sounds like more robust solution.

Continue reading …

Example of High Cohesion and Low Coupling with Presenter, View, and View Model

Here’s a short definition of the two terms: Cohesion is about how well elements within a module belong together and serve a common purpose. Coupling is about how much one module depends or interacts with other modules. Thus, cohesion is an intra-module concern whereas coupling cuts across modules [aka inter-module].

(Devopedia)

Continue reading …

How to Fix When Some Text Changes Don’t Come with Automatic Undo?

When you work with NSTextView and happen to use insertText(_:) to programmatically insert text, you get an undoable action for free. This might give the impression you get undo/redo functionality for free. Eventually, you’ll notice how other changes don’t have an affordance in the “Edit” menu. While it’s possible to get “Undo Typing” and “Undo Set Color” from some function calls, it’s not possible to get “Undo Change Text Attributes” when you use NSTextStorage.addAttributes(_:range:).

Continue reading …

Reactive Code is Sequentially Cohesive

Reactive, declarative code is sequentially cohesive: you have a sequence of events and reactions to events, and it’s pieces are tied together real close. The processing chain itself is then a function or feature of the app. The chain of operators is a thing itself; the step-by-step transformation is then reified into a sequence in one place: it has a beginning, an end, a sequential order of steps.

Continue reading …

Drawing Studies: Tonal Values

This time I remembered to record our weekly sketch-together over Discord. Here’s a 4x speed version with narration of this evening’s sketches. The focus was on tonal values, so no colors, just pen and ink, then ink washes on watercolor paper. The paper I used here is the Moleskine watercolor pocket book (Affiliate link). I don’t like that paper for watercolor paintings, but it’s great for ink washes, because it absorbs the ink quite rapidly (unlike regular drawing paper).

Continue reading …

Schedule End of the Work Day Using Org

To get more structure into my day so I get work stuff done in time and have free time in the evenings to tackle other things, I’m now experimenting with notifications to end the work day. The following is a translated version of the current data. I am using the German term "Feierabend" (which you can shout well); “end of work” is a bit clumsy, and it doesn’t sound like an exclamation.

Continue reading …

Disambiguate Code Signing Identities

I’ve recently added the code signing identities for a client to my dev Mac. Some old code signing scripts then failed to run: 🛑 Apple Development: ambiguous (matches “Apple Development: Christian Tietze (xxxxxxxxxx)” and “Apple Development: Christian Tietze (xxxxxxxxxx)” in /Users/myuser/Library/Keychains/login.keychain-db)

Continue reading …

New Library Pages

I’ve added a new section to this site. Wanted to call it /books, but that’s taken and about my books :)

So I added the new /library index. It shows books added to my personal library sorted by year I read them.

At the moment, there’re only these three, all of which I needed (wanted) for the previous post:

This collection is bound to grow. I missed something like this for a couple of years. An overview of posts about book would’ve been nice for lots of reasons.

Now the basics are prepared.

TDD Is About Writing Counter-Factual Statements

Writing unit tests first, in the manner of test-driven development, is some kind of “wishful programming”: you create a counter-factual situation in the test code, e.g. one that uses types and methods that don’t even exist. Then you add the implementation to make the counter-factual statements (and failing tests) the actual reality.

Continue reading …

Key Binding to Select Paragraph or Org Element

I used to rely on M-h to mark the structural element in Emacs; in text buffers, that’d be the paragraph, in org buffers, that was the whole outline item (when the cursor was in the heading line, at least). Ever since I installed Emacs for Mac OS X which now is also on Emacs 28.1, this shortcut wouldn’t work for me anymore, because my Meta key is my left Command key, and Cmd-H is the macOS shortcut to hide the frontmost app.

Continue reading …

TableFlip v1.4.0 Released

I’ve released an update to existing users of TableFlip last week. It works well so far, so now’s the time for the official announcement of the new version, available for direct download.

Most notable changes:

  • TableFlip now guesses sophistically determines the delimiter in CSV files, if needed. So you can use ; or \t just fine, which means export from Numbers works out of the box.
  • Non-comma-delimiters also “stick” when saving. No auto-replacement to comma anymore.
  • The CSV loading and saving is more robust, especially with quoted content. There’s been issued reported in the past, and these should now be fixed. Thanks for your emails and sample files, folks! ❤️

For my nerdy readers, behind the scenes I also upgraded Sparkle from the XPC branch to the actual Sparkle 2.0 stuff. I sincerely hope it will ingest the upcoming updates, too. (It’d not be the first time I broke the update mechanism of one of my apps, heh.)

What is TableFlip, you ask?

TableFlip is a fast tabular data editor – the ideal companion app for Markdown users who want beautiful tables in their documents. Open the file in both TableFlip and your text editor, and you’re set: TableFlip lets you edit all tables it finds inside your document and updates live as you edit your text.

Well, and you can edit CSV files, too, and export to LaTeX.

TableFlip v1.4.0 is available from the website and the Mac App Store.

DevCleaner for Xcode

Found DevCleaner for Xcode yesterday and gave it a spin. It’s freeware on the Mac App Store with a tip jar.

Developers who ever nuked their Derived Data folder (I have an alias in my .profile for that) know how much stuff Xcode collects over the years. And then there’s outdated iOS Simulator versions nobody needs anymore. And log files, of course, by Xcode.

I’m pleased to say that DevCleaner does a good job at enabling me to select what I want to remove from the set of things that could be obsolete.

I have Xcode 14 beta installed (to my dismay), so DevCleaner suggested all Xcode 13.x related things could go away. It tries to be smart and helpful here, but I kept the Xcode 13.4.1 logs just in case. The option is there.

Where in the past I would occasionally nuke all Derived Data, DevCleaner shows these folders in a sensible way, with a reference to the project location. I usually create throwaway projects to test and debug something in my Downloads folder. The derived data of these projects is absolutely useless after a month, week, or sometimes even a day. Since DevCleaner shows where the original project was located, I’ve been able to delete data for every long-gone project that was in my Downloads folder.

I cannot stress enough how cool I find this.

Deleting derived data folders is often hard to do by name alone: when I download a new version of a 3rd part dependency that I am using in my apps, and open the project in my Downloads folder, and play around with it, then I have two derived data folders for this dependency, but only one is relevant for the actual project. Either I don’t care and delete both when I know building them is trivial, or I don’t bother at all and they stay around forever.

I really, really like this feature.

Would be even better if I could sort or filter by origin path, but it’s ok the way it is.

Shift-Click in Emacs to Select – A Simple Change With a Complex History

Sometimes I actually do wonder why the Emacs defaults are whatever they are. Someone somewhere decided that clicking with the left mouse button while holding shift should pop up an appearance menu where you can change font size and things like that. The behavior I expected from my personal history of 25 years or so of using computers is to extend the selection up to the clicked point.

Continue reading …

Magit’s Killer Feature #1: Commit Text Completion Based on the Diff

Teaser image

I’m using the Emacs git frontend (‘porcelain’) Magit for all my projects nowadays. I fire up GitUp (which is great) only to traverse the commit history visually. Here’s one of the reasons: With auto-completion framework company, I get completion suggestions when I type my commit message. These are based on the actual code diff of the commit.

Continue reading …

Happy People = Mac Users

I talked about my “job” the other day and, again, pointed out that I’m making apps, but for Mac, not iPhone. No, no, I also do iPhone. I just don’t like to, and avoid it if I can. But using a Mac, that is fun, and working on a Mac is great. The machines are good, the OS is still good. That’s what I believe the most. For the things I’m interested in making, the Mac is a good platform. It’s a platform to get serious stuff done. And I can be a part in making the experience enjoyable and make “work” fell less like a chore. That’s what I’m interested in.

Continue reading …

Dependency Injection and the Tree of Knowledge

On Twitter, Manuel Schulze (@zet_manu shared the Swift package Resolver that does dependency injection in a very convenient way with little boilerplate thanks to property wrappers: Mr Dr Dominik Hauser replied, and that’s how it entered my Twitter timeline. I was curious why people use packages like this – I know the concept from Java, but have always found constructor injection and maybe a Service Locator here and there to suffice.

Continue reading …

STTextView: A TextKit 2 Text Editor without NSTextView

Teaser image

In my recent post about the TextKit 2 sample app, commenter Frizlab pointed out that Marcin Krzyzanowski (@krzyzanowskim on Twitter) is doing TextKit 2 stuff. I didn’t notice that in my Twitter timeline even though I follow him for years now, so I was confused, nay, angry about the state of my Twitter timeline since Musk’s takeover /s.

And yes, Marcin does have a very extensive open source sample project that explores TextKit 2! He’s working on Swift Studio, a pure Swift IDE and his STTextView is a part of that.

So meet STTextView, a “TextKit2 text view without NSTextView baggage”.

Check out the video demo!

One thing I love about the code comments for the UI compoents is the ASCII diagrams of layer contents, e.g. in STTextView.swift:

//  STTextView
//      |---selectionLayer (CALayer)
//      |---contentLayer (CALAyer)
//              |---(STInsertionPointLayer | TextLayoutFragmentLayer)
//

Am totally going to adopt this :)

Clean Downloads Folder on Mac with Hazel

Teaser image

I have a confession to make. I eased into this by sharing the same info on Twitter/Mastodon already. My ~/Downloads folder is a mess. It’s much less messy than your Downloads folder, most likely, but still. I achieved relative de-messification by automatically filing old downloads into sub-folders, one per month, like ~/Downloads/2022-05 Downloaded. That was amazing because the actual Downloads folder was clean, and old stuff was somewhat highlighted.

Continue reading …

Weak Self – Closure Rules of Thumb

In Swift, you can weak-ify references to self in escaping closures, and then you need to deal with the case that the reference is gone when the block is called. Last month, Benoit Pasquier and Chris Downie presented different takes on the problem. That discussion was excellent. It prompted me to take some more time to revisit this problem systematically, and I took away a couple of notes for future-me.

Continue reading …

How to Upgrade Sendy from Version 5 to 6 from the Shell via SSH

I’m using Sendy for our newsletters. Recently, verison 6 was released. Here’s how I updated like a pro on my VPS via SSH. The beginner-friendly but ultimately drag-and-drop/FTP-based online instructions assume that you will be moving files over from “new location” to “existing location”. That’s quite cumbersome when all you have is SSH.

Continue reading …

Aergrind by Knock Coffee Grinder, and Their Amazing Customs Duty Service

Teaser image

I bought a hand grinder that would replace our 40+ years old, dull antique. Of course I looked for advice on James Hoffmann’s YT channel and figured the Aergrind by Knock would be a great fit. As the man coffee scientist himself says, the grinder is so good it would’ve blown away any cheaper competition from his other video, so he included it in the premium segment comparison. That was one reason I considered this.

Continue reading …

Add Numbers to Emacs tab-bar-mode Tab Titles for Quick Access

Teaser image

For about two months now, I’ve been using tab-bar-mode in Emacs to have multiple “workspaces” open. I was fine with buffer switching, too. But tab-bar-mode not only allows you to switch between buffers, but also window configurations – that means one tab will have 1 window with 1 buffer visiting a file, while another might have a gazillion split panes. So the main upside for me is to arrange stuff into panes aka windows, and then open a new tab to do something in a single-pane view.

Continue reading …

Copy Dropbox Link to File Using Maestral

Joel Rendall on the Keyboard Maestro forums published a macro collection for Maestral users. Since my switch to Maestro from the macOS native Dropbox app with all its annoying features, there’s only one thing I missed from the Dropbox app – copying links to files in my Dropbox to share them with others. I do this quite often with video recordings for bug reports, I found.

Continue reading …

I Uninstalled the Dropbox App in Favor of Maestral

Today I have uninstalled the Dropbox app from my Mac. I’ve been an early Dropbox user and invited friends until I got up to 10 GiB, which was a ton of storage back in the day. But the native apps gets more and more annoying; they have a history of faking system standard dialogs to “trick” you into installing the kernel extension with root privileges; and resource consumption was at times confusingly high. Stuff like that made me tired of the app.

Continue reading …

Closing Circe IRC Buffers in Emacs Without Leaving the Room

It’s a hack but it works: To stay in a room (or rather: let the bouncer stay there) and still close the buffer locally, it helps to change the major mode of the circe buffer: M-x fundamental-mode RET. If you change the buffer’s mode to any text mode, the circe-mode specific teardown hooks won’t be triggered and you can close the buffer without leaving the room.

Continue reading …