In this post, Protesilaos answers an email by one of his readers. In the email, the sender seems to assume that Emacs is bloated by definition, and that e.g. Vim isn’t, because it comes with less stuff baked-in and works well with piping – the core way to compose in *nix command lines.
The sender asks:
This video [of Luke] really provide some good reasons why to invest on ‘coreutils’ to build a small, maintainable and decentralized system rather than investing on a giant mutable system.
Emacs being the giant, mutable system, and the pipe-able Unix command-line tools comprising the “maintainable and decentralized system”. (That way of asking is loaded with assumptions already.)
Prot does a very good job at not preaching, and actually bringing forth useful arguments.
Vim has a lot of stuff built-in, like a terminal emulator, and isn’t that different from Emacs in that way. (Plain vi is a different beast.)
Prot treats Emacs “as a layer of interactivity on top of Unix”. That’s a very good description, I think.
There is non-negligible overhead in composing a system of many independent pieces. You end up writing a lot of glue code, so to speak. (And it can be rather brittle.)
Emacs ties things together into a coherent software where you can share stuff between pieces of functionality easily. You can copy from the Emacs shell and paste in a text buffer. You can perform mass text replacement from a UI you already know instead of having to learn syntax. (Opposed to sed/awk/…)
In closing, Prot points out that the underlying issue can be binary thinking (which is rather limited and avoids entertaining opposing opinions):
This hints at the kind of thinking that treats the world in simplistic, binary terms: Unix is simple VS Emacs is complex; Arch Linux is for hackers VS Ubuntua is for simpletons… Those are stereotypes that rest on misunderstandings about the intent and the purpose of each of those paradigms, their context-specific pros and cons, as well as the potentially numerous reasons one may have to opt for a given choice.
Worth a read during this time “between the years.”
Since COVID-19 doesn’t seem to go away any time soon, I figured I might as well continue with #IndieSupportWeeks to show you what I use and can recommend.
A dev tool I use on iOS is Working Copy. Usually, I don’t interact with my project code at all from iOS, but when I do, I check git stuff with this app.
Over the past 10 years or so I’ve tried a couple git clients for light work on mobile, but Working Copy sticked with me ever since I was participating in the TestFlight beta.
For a casual git fan-person, Working Copy’s settings might be a bit overwhelming, but for developers, I think this is a very fine app to browse, search, push and pull, and even commit changes.
Now the “commiting changes from mobile” part in someone’s daily workflow is utterly confusing to me, because I cannot imagine what that’d be like on an iPad, say.
I have edited posts on my website this way to fix typos. That went well. I also used it for light maintenance of Open Source projects. But I haven’t tried to commit to my Swift projects, because I don’t see how editing Swift files without a compiler would be a good idea. Then again it’s not my job to figure out user personas for a mobile git client – I’m here to tell you that if you’re in the market for such a tool, Working Copy is good at that.
The one thing I can testament to is that it works without a hassle, and it works well. That’s not much, but that may also be all you truly care about.
Working Copy is a free download + a $19.99 one-time in-app-purchase to unlock all the features. It also has a 4.9-star rating on the App Store, so, wow!
I played around with Nicolas Rougier’s NANO Emacs configuration because it looks so hot and I wanted to try some of his tasteful settings myself. One thing that let me down for a couple days since I started eyeballing the package was performance. In my huge org files to organize app development tasks, scrolling was so-so. Pixel scrolling, which I discovered through Nicolas’s configuration ((pixel-scroll-mode +1)), didn’t work at all on my machine. I have a MacBook Pro 13” from 2020. This is a text editor. Something’s not right with my config.
Sadly it’s only for macOS11.0+, so for projects pre-Big Sur, you have bad luck. But it’s written with SwiftUI, so you may still learn one thing or another, or adapt the code to your project if you want!
I somehow found Abin Simon’s post about how he made pasting text in his Emacs “pulse”, aka temporarily highlight the pasted region. In Emacs parlance, pasting is called “yanking”. His post sadly covers only one use case: Emacs with evil-mode, which adds vim keybindings and apparently also adds a special evil-yank command in place of the regular yank.
I installed Treemacs the other day and found out, to my excitement!, that you can not only hit TAB to expand folders, but also to expand files! When you “expand” a Markdown file, you see its headings in the file explorer. That is bonkers, and so useful for larger writing projects to get a unified overview!
I don’t know about you, but sometimes, and the end of an exhausting day, I find the prospect of filling out yet another form almost frightening. At the very least intimidating. Some days, I’m just not in the mood to be bothered. Even with tracking open loops meticulously, this opens up the potential to let things stay undone for far too long.
In case you’re prone to behave like that, I don’t want you to fall into this trap for your indie app business. So here’s good news. I checked out Apple’s App Store Small Business Program enrollment.
The App Store Small Business Program is literally just a handful of checkboxes to tick. That’s it. I completed it in 2 minutes, most of it spent in the login form, I guess.
If you earn less than 1mio USD in revenue per year and want to see your App Store fees halved from 30% to 15%, apply as soon as possible.
If you apply before Dec 18th (this Friday!), your enrollment is expected to be done in time for January 2021.
It takes a handful of deep breaths to get through that. And I totally get why some of us at the moment absolutely need some breathing room as 2020 draws to a close. If yet another form to fill out is not your cup of tea, give this checkbox-based form a chance. You’ll not regret it.
If you have no dignity (like me), you might enjoy displaying emoji in Emacs. I actually really like that when composing/reading email, and when I want to add colorful stuff like stars in my to-do lists. There’s this package, emacs-emojify, you might want to check out. When you install the package, it will download EmojiOne images by default. You can set up your own, and I found the OpenMoji set to look very nice. Clear lines, crisp shapes, very recognizable expressions in big and small sizes. Love it.
There are many ways to affect the glyphs that are used to show text on screen. Since macOS10.11 El Capitan (released in 2015), possibly the simplest override points are in NSLayoutManagerDelegate. Another, arguably more ancient way to replace glyphs on-the-fly is to override and customize NSGlyphGenerator. This predates the existence of NSLayoutManagerDelegate, and it’s not even available on iOS, so that’s how arcane the approach outlines here will be.
TableFlip v1.3.0 just passed App Store Review. Direct customers had access to the update since yesterday evening. Here’s what’s new: Credits got to Alex Käßner for iterating on the “classic” TableFlip icon and bringing it to the Big Sur era of superellipses, soft gradients, and smooth arrows!
TL;DR: The Sparkle 2.x release branch is working fine for production when you switch from the ui-separation-and-xpc branch and enable DSA signing of updates. While updating TableFlip for macOS Big Sur, I figured I might just as well update my dependency on Sparkle to whatever they came up with in the past 18 months or so.
During app development, I track the tasks in an org-mode task list. And I track the stuff I finished and want to highlight in the release notes in a Markdown block right there. When I release an update, I’ll copy & paste the Markdown part to the “Release Notes” of the app and push the changes to the server online.
This week I noticed that a ton of files like *message*-20201029-134012 piled up in my home folder. These are email drafts from message-mode, and the numbers are a date-time-stamp. These didn’t appear ever before. So I figured it might have something to do with autosaving after looking at the change history of my configuration file – and it sure does.
Think personal wiki of knowledge. But instead of merely cartographing what is in the world, you create new stuff from the things you collect, building up layers upon layers of ideas by connecting what you already have, and then making a big hypertext from it.
At first you have atomic ideas, then you begin to link them and think and write about their connection.
In other words, it’s a way to add layers of abstractions to your thinking and writing.
I use something like it for 11+ years now and the amount of cross-connections is very cool. Also, by using my Zettelkasten properly, I “accidentally” prepare blog posts for this site: every note is self-contained and written in a semi-publishable manner, so I could just copy and paste notes together to make an article. That’s the sweetest part of it: how it accelerates my writing.
I noticed that in macOS’s dark mode, a window without a visible title bar won’t draw a light border. It will draw a dark/black border, unlike all the other windows, and thus be a lot less visible than it needs to be. So for a floating helper window, I had to make the title bar visible, and then hide all traffic light buttons in the window’s top-left corner:
Some commands in Emacs and its various packages are destructive. They require a confirmation by the user. These usually use yes-or-no-p, which won’t complete the command until the user replies by writing “yes” and then hits enter, or “no”, or aborts the command with C-g. Some of the commands that require confirmation in this way are overly protective, I find. Like projectile-kill-buffers (C-p k) which closes all open buffers for a project at once. I use this heavily when e.g. editing my website: jump into the project, edit a file or two, commit, then leave. I don’t want to type “yes” and hit enter just for that. (Please note that killing a buffer this way will still ask me if I want to save or discard changes, so the kill command alone is not destructive.)
If you ever wondered how to programmatically trigger a click on a link in a NSTextView, here’s one way to do so. This assumes that clickable links are not stored as temporary attributes in the NSLayoutManager, but permanently as part of the “model” in your NSTextStorage. You can then ask the storage for the attribute at the cursor/insertion point location:
I’m looking for a PHP developer starting now. Vanilla PHP and Laravel are both welcome. Update 2020-10-27: I added more details about what I would love to see in your application, and a rough battle plan. The goal is to self-host a list of online video courses. The course modules are only available to paying customers.
I noticed that I still had the journaling app Day One (macOS) on my computer. I haven’t touched it in ages. So I figured it’d be time to export to plain text and then shove all the goodness from 2004 and onward into my Emacs org-mode diary.org. Turns out there’s no Day One to org-mode exporter.
If your customers get this message when downloading your app from the Mac App Store: XYZ is damaged, remove it and download again from App Store. … it might be because you’re parsing the App Store receipt dates wrong! Apparently, Apple began to change Mac App Store receipt date formats recently: When you parse receipt dates, account for both variants. To make things easier for you, strongly consider to use ISO8601DateFormatter (NSISO8601DateFormatter in Objective-C) which should (!) handle multiple variants of ISO-8601 dates for you.
I am working on code that reads Apple Reminders data. To fetch reminders from an EKEventStore in EventKit, you need to request permissions. But you can only request permissions for calendar, event, or reminders access if your app’s Info.plist contains the appropriate key.
In the past months, I deployed a couple of app updates. Not as many as planned, but still. My app downloads are compressed DMG files, or disk images. With these, you don’t need a Zip. DMGs usually come with the app bundle and an alias to /Application so you can “install” an app quickly via drag & drop. This is probably the most successful and easiest way to ship downloads that work with macOS App Translocation. If users run an unzipped app bundle from their downloads folder, they’re screwed.
Over the years, I tried a couple of approaches, and I found that I had the most success with DropDMG. The visual preview is very accurate, and I never had any problem with the resulting DMG files. It beats fiddling with the command line every day.
DropDMG is an essential tool in my workflow to ship applications. It costs US$24 at the moment, and it’s worth the money if you do indie app development to make money.
No matter if you use exec-path-from-shell or not, Emacs will not be able to know your RVM-managed Ruby information. This drove me crazy. Most Emacs shell commands are invoked in an “inferior” mode, aka a “dumb” shell. This includes M-!, M-x shell, and also the projectile compile commands. That’s when some of your user login scripts will not automatically load, like the entirety of rvm, the Ruby Version Manager.
Google brought up this weird lifetime access to the paid FastComments tier. It’s $79 for life instead of $50 per year.
I asked the FastComments support people if this was scam or a legitimate deal, because I didn’t know anything about bypeople.com – and they verified this is absolutely legit and part of their marketing masterplan.
So if you want to get FastComments on your site and want to get it cheap, here’s a link to the $79 deal. With the weak dollar, thats about 69 EUR at the moment, in case you wonder.
Emacs comes with a lot of stuff out of the box, but I was missing TextMates “Insert Entity” action that lets me search through HTML entities by name and then insert &quot; or &trade; for me. I can never remember the names of typographic quotation marks in German, for example.
As will all things on the internet, Disqus don’t charge for their commenting service, so they probably do something with the collected data. There’ve been privacy concerns over the years and folks like Brett Terpstra have migrated away from Disqus quite some time ago.
I wanted to make sure that I’m up-to-date in regards to Swift’s lazy initialization of static attributes. So here’s a demonstration of a Swift property wrapper that produces debug output to check what’s going on, aka caveman debugging (because of the log statement, y’know). The output is as follows, demonstrating that the static var is initialized lazily when you access it:
I found an answer in the community portal about grid-based movement, but they’re using tweens to animate. That’s an interesting approach, but I think it’s a bit too much of this modern day technology for my stomach.
I played around with Godot and found that when my player character moved too fast, it would not collect items in its path. Here’s a short visual comparison of two approaches to move things in an engine like Godot. If you don’t know Godot: it is an engine, tool, and IDE to create cross-platform 2D and 3D games and GUIs. It’s basically Unity, but open source.
I want to decode JSON that’s human readable but still represents a Swift.OptionSet. Traditionally, OptionSets are implemented with an integer-based rawValue, because that gives you the set algebra for free. Here’s my type: Here, all represents the whole text of a document, for example, and selected stands for the current selected text, if any.
Helge Heß published an Open Source component to use the modern FastSpring web API so you can display a sheet to purchase a license of your app within your app. It’s not yet a native in-app purchase UI or anything, but you can The last part is probably the most important to me. It’s what I like most about the
Today, I propose a microformat for the open web: the /now Page. Let’s call it h-now. A microformat is a convention to markup your content in a way that helps software to identify content. Like addresses for navigation, contact cards for quick import into contact files via browser extensions, or events for calendar integration.
This is an overview of a short series of posts I wrote about TableFlip’s 2020 bug. People were getting a “You don’t have permissions” error, a Sandboxing error, when they worked with .txt files, but not with .md files, even though the app treated them the same. The issue boiled down to a misconfiguration on my side that went by unnoticed until I enabled Sandboxing. I was wrongly defining document types in the app’s Info.plist, and I was reporting supported file types in the NSDocument subclass in a manner that didn’t work out well.
All previous installments in this series were written some time during the past 6 weeks or so. I couldn’t spend a lot of consecutive time on eitherthe coding problem or the posts, so it became a pain to keep up with all the details and experiments – I hope I have nevertheless told a somewhat intelligible story so far.
NSDocument’s save panel comes prepared with a file format picker that contains the app’s registered document types. This is a very nice convenience, but when you run into trouble with the default picker, as I did, you wonder if writing your own from scratch would be easier.
In my quest to vanquish bugs from TableFlip, we intially observed that file extensions would attempt to change after an external file change. It turnes out that this was my fault because I effectively always passed "net.daringfireball.markdown", even when the document type originally was "public.plain-text". Passing the wrong file type to NSDocument.revert(toContentsOf:ofType:) was causing the issue. Trying to use the optional NSDocument.fileType property first, and then providing a fallback, solved the file extension problem.
In my initial post about this problem, I talked about the observations and how I began to figure out where the permission problem came from. I turned out to be an attempt at changing the file extension from .txt to .md. When the user opens a .txt file in your app, macOS makes sure you only get access to that exact file path by default. You cannot just write willy-nilly anywhere else without the user’s permission. File extension changes are included in this protection.
When I researched what caused TableFlip to lose permissions to write out files, I learned about “related items” in the Sandbox. A good example from the docs is to open a movie file plus its subtitle captions together. The user would select the movie in an NSOpenPanel. This usually grants access to the movie file directly per Sandboxing restrictions. You can declare the subtitles file to be a related item so that the Sandbox allows you to read both. That’s clever.
Users have reported problems with TableFlip saving their files recently. One wrote about it in the Zettelkasten forums, if you want to see the problem in context. To reproduce the problem: when you open foo.txt in TableFlip and a text editor, then change the file in the editor rapidly, TableFlip would show a “You don’t have permissions” error once you tried to save changes from TableFlip later.
Back in January when I drafted this post, I had just discovered Apple’s NaturalLanguage.framework. I still don’t know how powerful it really is, but it’s useful for a very simple task already: Counting words. In English and German, I can get pretty accurate results with a String.split at punctuation marks and whitespace. In French, you will get skewed results because these nices folks decided to put whitespace between quotation marks and quoted text.
When you delete a character or the current selection, you usually hit C-d (Control + d) in Emacs. I got into the habit of revising drafts by deleting whole words, and the M-d (Meta + d) key combination is super useful for that. It also works into the other direction with backspace. It’s essentially the same effect of ⌥+backspace everywhere else in macOS.
beorg is a bit weird. It’s basically a task manager and calendar, but based upon plain text files that I sync via Dropbox. It’s not a particularly user-friendly application, and its UI didn’t win any prizes, unlike e.g. Things or OmniFocus (I’m often confused by the app icons and lack of labels, but also glad because my iPhone 5S screen is so smol). So why did I pick this app, then?
beorg is a mobile companion for my Emacs org mode files. It’s capable of handling org mode outlines, and parts of these outlines can be tasks or TODOs, and you can group them in projects, and then display an overview or “Agenda” – and things get out of hand quickly from there. Emacs is ridiculously customizable, and org mode is no different. beorg makes these information available on mobile.
So since over the years I moved from OmniFocus 1 to Things to OmniFocus 2 to Emacs, I got used to viewing tasks on my mobile phone and iPad; and I really much like the capability to capture information on the go. A piece of paper will do most of the time; but having a web clipping synced to my computer directly is nice.
You can even write Scheme scripts inside beorg! I haven’t touched that topic at all. The REPL (yes, it has a REPL!) provides a sandbox for experimentation, and by convention beorg will load and run init.org file from your list of files right after bootstrapping. You can even customize the app’s UI with this. Writing org files that auto-execute during launch to customize the behavior of the editor is a long-running theme, see this random example (source).
Regarding the business model: most stuff is free, and the free version will get you really, really far. You currently can buy access to additional features:
“Properties” will let you add custom key/value pairs to any item; it’s mostly a UI affordance for the plain text underpinnings
“Encryption” to, well, encrypt your items or files
“Task Timers” to track how long you work on a task (ahem, I suggest an automated service like Timing for that; note: this is an affiliate link)
“Export Themes” are CSS styles to generate HTML from your outlines because, well, org mode is supposed to be a structured markup language for HTML and LaTeX export and such thing
“UI Themes” for Solarized and additional dark modes in the app
“Saved Searches” to more quickly access the results of complex searches
“Box Sync” to … sync to Box.net (beats me why this of all things is an add-on)
The developer provides release notes for updates in the app, which I absolutely adore for this kind of “make it your own” pro user application, to make sure I keep up-to-date with the good stuff. The tip jar that goes along with it is probably the main source of his income – at least as much as I’m concerned. The updates are really good and much appreciated.
In this awkward time of COVIC-19 lockdowns, folks will begin to struggle to make ends meet. I know from some folks that their salary was reduced to 60%, which is better than 0%, but still troubling. Indie developers of most non-video conferencing software suffer from similar declines in income. That where #IndieSupportWeeks come into play: share some of your favorite indie apps to spread the word and help the developers stay afloat.
This time, I want to point you towards Soulver by Zac Cohen. Zac is a very friendly and helpful person, and Soulver is a great app, so I hadn’t had to think twice.
I use the iPad app whenever I try to make sense of a change in expenses, e.g. when I move, when I compare contracts for my phone or insurance, or want to roughly plan a vacation. It’s really great for back-of-the-envelope calculations.
Soulver is a line-based text editor that performs calculations for you, with some understanding of semantics as well: For example, the phrase 30% of $800 will evaluate to $240. And with support for variables, you can begin to make more complex calculations that are perfectly readable in the long term.
Here’s a crude UI mockup, where the right column is the computed result, and monthly rent is a variable:
This post is mostly for people googling for a similar error message as I did, being stuck clueless. Here it is, a message in the Xcode log that you can get when you load an NSImage: extractOptions:147: *** unknown hint identifier ‘kCGImageSourceTypeIdentifierHint:dyn.age80q2pssvu1g8pftb4gn5xxrf106’ – ignoring…
I’m looking to hire on help for my Mac app projects. You can apply now and I’ll be looking forward to pick someone in March. Ordered by importance: Have another look at my apps to see what kind of stuff I work on. This list of stuff is mostly about self-contained modules. You can think of these to be greenfield projects, so you don’t need to deal with existing code most of the time. We will design components from UI to API together and you’ll get to be as creative as you want and the project allows.
I ran into a situation with a window that is movable by its background and a text field inside it. The text field draws neither border nor background, so to the user, it looks like an input field directly on the window’s background. Much like the Spotlight search box. Even when a window’s isMovableByWindowBackground is enabled, a NSTextField captures click and drag events, and it changes the pointer to a text insertion variant (NSCursor.iBeam). All that is weird when you don’t know there’s a text field at that point. And you cannot know how large the text field is if nothing is drawn there. When the background is gone, this feels pretty weird.
There’s not a lot to do, but the documentation is (1) old, (2) not maintained anymore, (3) very wordy. The steps involved are actually very simple. I’ll go through them and provide detail and links for further reading. Open the Script Editor app. You’ll want to use that for test-driving your app.
Here’s NSProgress subclass that allows block-based callbacks for finishing the progress in a new callback called finishHandler that should work the same as the existing handlers. By default NSProgress (or with Swift just Progress) comes with handlers for resumeing, pausing, and cancellation events, but not for finishing. I don’t know why.
I was getting back to fix a couple of small issues in The Archive and release an update when I noticed that one new feature I added, a statistics status bar, made most sense when hidden by default to avoid UI clutter. But how do people notice the new feature, then? Well, that’s what the “What’s New” window is for. To make it support a history of amazing changes, I adapted my very own WhatsNewKit to support this. And there you go, WhatsNewKit version 1.2.0 is out now and supports multiple update notices!
Here is a transaction type to copy & paste into projects to encapsulates thread-safe read/write access: Just make sure to not use the main queue, because .sync call from main to main will deadlock your app! It ensures you read values synchronously, which isn’t dangerous, and enqueue and execute write operations in order. This is useful if you need to access any resource from multiple threads and want to avoid the overhead of mutex locks.
When you look at the docs for String.index(_:offsetBy:limitedBy:), you get this description: Returns an index that is the specified distance from the given index, unless that distance is beyond a given limiting index.
I recently dropped blog posts rendered via MultiMarkdown. I used MMD to support citations, but this is not a book, this is a website! So I retired my MultiMarkdown processor for nanoc, the static site generator that I use. If you need something like it for your project, here it is:
I stumbled upon an interesting coding problem in a recent macOS project related to in-app purchases. IAP can be represented by a feature option set in code. How do you secure UserDefaults access in such a way that accessing values can be locked via the IAP available feature options? (This also applies to tiered licenses, like a “Basic” and a “Pro” feature set.)
This is how I made dark NSButton with the NSButton.BezelStyle.recessed display legible light text on dark background with macOS Mojave an up. Recently, a user of The Archive pointed out that the in-app guide doesn’t display properly with a light system appearance. In dark mode, you wouldn’t notice the problem, but in light mode, the button colors rendered them illegible. Only when you press a button does its text light up properly for its background color. Have a look:
I often forget the name of this thing, then I search for it, and forget it again later. It’s the Whole Value Pattern. The “Whole Value” pattern means you should get rid of using primitive or literal data types as quickly as possible. (Since Swift has no non-object primitives, you have to look a bit harder to spot these, but “literal value” is a pretty good indicator.)
Joe Fabsevich (@mergesort) proposes to call data to configure UI elements “View Data” and keep the objects dumb. From part 1: In my experience, things become harder to maintain when they start becoming a crutch, as a place to put your code if it doesn’t neatly fall into the Model, View, or Controller label.
Oskar Groth published a modern iteration of the “LetsMove” framework where you can show a dialog at app launch, asking the user if she wants to move the app to /Applications first.
This is still a crucial feature if you distribute downloads that unpack into the ~/Downloads folder: Gatekeeper’s App Translocation will actually start it from a random sandboxed folder. To prevent this from happening, distribute your apps as a DMG with a shortcut to /Applications to nudge your users to move the app there directly.
This is not a pun on the U.S. president. Going through stuff from the past year, I just noticed how much more amazing daily life feels with a community. In the past 2 years, I helped found two communities: Without the local group of Urban Sketchers, I wouldn’t have progressed with my watercolor skills; and without the forums, there wouldn’t be a lot of places to hang out to talk about what I find most interesting about personal knowledge management: creating new insights!