Subscribe: inessential.com
http://www.inessential.com/xml/rss.xml
Added By: Feedage Forager Feedage Grade B rated
Language: English
Tags:
app  code  don’t  frontier  it’s  i’m  life  pascal  string  strings  support  there’s  things  trump  work   
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: inessential.com

inessential.com



Brent Simmons’s weblog.



 



Save $300 on CocoaConf Next Door

Fri, 14 Apr 2017 13:53:02 -07002017-04-14T13:53:02-07:00

My pals at CocoaConf asked me to remind you that the Early Bird sale ends in two weeks for CocoaConf Next Door — the one taking place in San Jose during WWDC.

I’ll be there. At least in the afternoons.

Check out the speakers list. Yummy, chewy, nutty speakers list.




Frontier Diary #4: The QuickDraw Problem and Where It Led Me

Fri, 14 Apr 2017 13:14:20 -07002017-04-14T13:14:20-07:00

In my fork of Frontier there are still over 600 deprecation warnings. A whole bunch of these are due to QuickDraw calls.

For those who don’t know: QuickDraw was how, in the old days, you drew things to the Mac’s screen. It was amazing for its time and pretty easy to work with. Functions included things like MoveTo, LineTo, DrawLine, FrameOval, and so on. All pretty straightforward.

These days we have Core Graphics instead, and we have higher-level things like NSBezierPath. QuickDraw was simpler — though yes, sure, that was partly because it did less.

* * *

I was looking at all these deprecation warnings for QuickDraw functions and wondering how I’m ever going to get through them.

I could, after all, convert all or most of them to the equivalent Core Graphics thing. But sheesh, what a bunch of work.

And, in the end, it would still be a Carbon app, but with modern drawing.

* * *

So I thought about it from another angle. The goal is to get to the point where it’s a 64-bit Cocoa app. All these QuickDraw calls are in the service of UI — so why not just start over with a Cocoa UI?

The app has some outlines (database browser, script editor, etc.), a basic text editor, and a handful of small dialogs. And all of that is super-easy in Cocoa.

Use an NSOutlineView, NSTextView, and some xibs for the dialogs, and we’re done. (Well, after some work, but not nearly the same amount of work as actually writing an outliner from scratch.)

In other words, instead of going from the bottom up — porting the existing source code — I decided to start from the top down.

I started a new workspace and started a new Frontier project: a Cocoa app with Swift as the default language.

Then I looked at the existing source and thought about how to organize things. I came up with this:

  • Frontier — App UI
  • UserTalk.framework — the language
  • FrontierVerbs.framework - the standard library
  • FrontierDB.framework — the object database
  • FrontierCore.framework — common utility functions and extensions

I like using frameworks, because it helps enforce separation, and it helps in doing unit testing. And frameworks are so easy with Swift these days.

Hardly any of this is filled-in yet. I’ve got the barest start on FrontierVerbs. Ted Howard, my partner in all this, is taking UserTalk.framework and FrontierDB.framework.

In the end, it’s possible that no code from the original code base survives. Which is totally fine. But it also means that this is no quick project.

At this point I should probably put it up on GitHub, since it’s easier to write about it if I can link to the code. I’ll do that soon, possibly on the weekend.




Frontier Diary #3: Built-in Verbs Configuration

Thu, 13 Apr 2017 22:25:41 -07002017-04-13T22:25:41-07:00

Frontier’s standard library is known as its built-in verbs. There are a number of different tables: file, clock, xml, and so on. Each contains a number of verbs: file.readWholeFile, clock.now, and so on. Most of these verbs are implemented in C, in the kernel, rather than as scripts. At the moment, to add one of these kernel verbs, you have to jump through a few hoops: edit a resource, add an integer ID, add to a switch statement, etc. It’s a pain and is error-prone. So I want to re-do this in Swift, because I’m all about Swift. And I want adding verbs to be fool-proof: I don’t want to remember how to configure this every single time I add a verb. Adding a verb needs to be easy. My thinking: Give each table its own class: ClockVerbs, FileVerbs, etc. Have each class report the names of the verbs it supports. These need to be strings, because we get a string at runtime. Run a verb simply by looking up the selector, performing it, and returning the result. To make things easy and obvious, I think it should work like this: the selector for a given verb is its name plus a parameter. Then there’s not even a lookup step. Each verb will take a VerbParameters object and return a VerbResult object. dynamic func readWholeFile(_ params: VerbParameters) -> VerbResult The flow goes like this: We have the string file.readWholeFile. We see the file suffix and so we know we need a FileVerbs object. We check fileVerbs.supportedVerbs (an array) to see if readWholeFile is in the list. It is. We construct a selector using the readWholeFile part of the string and we add a : character: NSSelectorFromString(verbName + ":") This is great! We’re almost home free. Then we run the verb: if let result = perform(selector, with: params) as? VerbResult { return result } That doesn’t work. We get: Cast from 'Unmanaged! to unrelated type 'VerbResult' always fails Nuts. * * * It was so close. In Objective-C this would have worked. And obviously, apparently, I still think in Objective-C. I investigated some other options. At one point enums were abused, because there’s always, in Swift, an enum-abuse step. But everything I tried was more code and was more error-prone, and my goal here is to improve the situation. I think, in the end, I’m going to do something that looks kind of ugly: a switch statement where the cases are string literals. switch(verbName) { case "readWholeFile": return readWholeFile(params) … } “Nooooo!” you cry. I hear ya. My experience as an object-oriented programmer tells me this: if I write a switch statement, I blew it. And my experience as a programmer tells me that string literals are a bad idea. But the above may actually be the easiest to configure and maintain. Each string literal appears only in that one switch statement and nowhere else in the code. And the mapping between a verb name and its function couldn’t be more clear — it’s right there. (Yes, instead of using a string literal, I could create a String enum and switch on that. But that’s actually more code and more room for error. I’m going to have to type those string literals somewhere, so why not right where they’re used?) It does mean that readWholeFile appears three times in the code (the string literal, the call, and the function itself), and in an Objective-C version it would appear only twice (in a supportedVerbs array and the method itself). But. Well. I’m torn between shuddering in abject and complete horror at this solution and thinking, “Hey, that’s pretty straightforward. Anybody could read it. Anybody could edit it.” Which was the plan all along. And I get to stick with Swift, so there’s that. But, sure as shootin’, some day someone’s going to come across this code and say, “Brent, dude, are ya new?” And I’ll send them the link to this page. * * * Update the next day: well, the performSelector thing would work, if only I’d known about Swift Unmanaged objects. Joe Groff told [...]



Frontier Diary #2: Two Good Ideas that Aren’t Good Anymore

Tue, 11 Apr 2017 13:01:55 -07002017-04-11T13:01:55-07:00

Strings in Frontier are usually either Pascal strings or Handles. You probably don’t know what I’m talking about. I’ll explain. Pascal Strings Frontier is a Mac Toolbox app that’s been Carbonized just enough to run on OS X. You may recall that the Mac Toolbox was written so long ago that the original API was in Pascal. That Pascal heritage lived on in many ways, even after everyone switched to C — and one of those ways was Pascal strings. A Pascal string is n bytes long, and the first byte specifies the length of the string, which leaves the rest of the bytes for the actual string. Str255 was probably most common, and certainly is most common in Frontier, but there are also smaller sizes: Str63 and Str31, for instance. Unlike C strings, they’re not zero-terminated, since there’s no need to calculate the length: you always know it from that first byte. You create a literal Pascal string like this… Str255 s = "\pThis is a string"; …and the compiler turns the \p into the correct length (16 in this case). Now, I bet you’re saying to yourself, “Self, those Pascal strings are too small to be useful.” But consider this: every menu item name can fit into a Pascal string. You can fit a window title or a file name into a Pascal string (in fact, memory suggests that file names were even shorter, were Str31 Pascal strings). Any label or message on any bit of UI is probably short enough to fit into a Pascal string. (Especially if you assume English.) So for GUI apps these were terrifically useful, and the 255-byte limit was no problem. (You can fit a tweet in a Pascal string, after all, with a bunch of room left over. [Well, depending on the size of the characters.]) Frontier still uses them internally a ton. (For some reason, in the Frontier code, Str255 strings are called bigstring, which sounds ironic, since they’re so small, but I think it was to differentiate them from even smaller Pascal strings such as Str31.) You might ask what the text encoding was for these strings. “Text whatzit?” I’d reply. “Oh, I see. Just regular.” (MacRoman.) It was a good idea, but its time has come and gone. We have better strings these days. Handles Frontier includes a scripting language and a database, which means it certainly has a need for strings much larger than 255 bytes. It also needs heap storage for other things — binary data, structs, etc. — that could be much larger than 255 bytes. Enter the Handle. A Handle points to a pointer that might move: the memory you access via a Handle is relocatable. Which sounds awful, I know, but it was a smart optimization in the days when your Mac’s memory would be a single-digit number of megabytes, or even less than that. Here’s the problem: your application’s heap space can become fragmented. It could have a whole bunch of gaps in it after a while. So, to regain that memory, the system could compact the heap — it would remove those gaps, which means relocating the memory pointed to via a Handle. This is better than running out of memory, obviously. But it means that you have to be careful when dereferencing a Handle: you have to actually lock it first — HLock(h) — so that it can’t be moved while you’re using it. (And then you unlock it — HUnlock(h) — when finished.) Handles are also resizable — SetHandleSize(h, size) — and resizing a Handle can result in it needing to move, if there’s not enough space where it is. Or other Handles might move. You don’t ever know, and don’t care, and you think this is elegant because the system handles it all for you. All you have to deal with is an additional level of indirection (**h instead of *p), locking and unlocking it when needed, and disposing of it — DisposeHandle(h) — when finished. (No, there’s no reference counting, slacker.) Nowadays, on OS X, Handles don’t ever move and there’s no heap compaction. So there’s no reason for them whatsoever. And they are, as expected, dep[...]



Two Little-Known and Completely Unrelated Facts

Wed, 05 Apr 2017 16:57:59 -07002017-04-05T16:57:59-07:00

One. OmniOutliner’s outline view is implemented as CALayers rather than as a view with subviews. (I don’t think I’m giving away a trade secret here.)

Two. If you eat fenugreek, your armpits will smell like maple syrup.




iOS, JavaScript, and Object Hierarchies

Wed, 05 Apr 2017 14:53:01 -07002017-04-05T14:53:01-07:00

Rob Fahrni:

Given x-callback-url and App URL schemes in general it would be extremely cool to use those to create object hierarchies using JavaScript. Why JavaScript? Well, it’s native to iOS and applications can use the runtime.




CocoaConf Near WWDC

Wed, 05 Apr 2017 14:35:05 -07002017-04-05T14:35:05-07:00

There are a bunch of things happening near WWDC this year. Me, I’ll be at CocoaConf Next Door. I’m not preparing a talk, but I’ll probably be on a panel. And hanging out.

Check out the speakers list, which includes Omni’s own Liz Marley. And a bunch of other people you totally want to see — Manton Reece, Jean MacDonald, Laura Savino, and plenty more.

Also… AltConf and Layers will be near WWDC. If you could be in three places at once, you would. Well, four, including WWDC itself, I suppose. :)




OmniOutliner 5.0 for Mac

Wed, 05 Apr 2017 10:44:45 -07002017-04-05T10:44:45-07:00

I’ve been on the OmniOutliner team for over a year now. Though we don’t have positions like junior and senior developer, I enjoy calling myself the junior developer on the Outliner team, since I’m newest.

I may be a new developer, but I’m not a new user — I’ve been using the app since the days when OmniOutliner 3 came installed on every Mac.

Every time I start a talk, I outline it first. I organize the work I need to do in my side-project apps in OmniOutliner. And — don’t tell the OmniFocus guys, who are literally right here — sometimes I even use it for to-do management in general. I’d be lost without a great outliner.

Anyway… there’s a new version: OmniOutliner 5.0. It’s my first dot-oh release at Omni, and I’m proud of it and proud of the team.

As is common with our apps, we have two levels: a regular level and a Pro level. The regular level is called “Essentials” and is just $9.99. There’s a demo so you can try it out first.

It syncs with iOS and with other Macs, by the way. Sync is free. And of course it comes with extensive documentation, and Omni’s awesome support humans are standing by.

Get it while it’s hot!




Frontier Diary #1: VM Life

Mon, 03 Apr 2017 13:44:34 -07002017-04-03T13:44:34-07:00

It’s been years since I could build the Frontier kernel — but I finally got it building.

It’s really a ’90s Mac app that’s been Carbonized just enough to run on MacOS, but it’s by no means modern: it uses QuickDraw and early Carbon APIs. It’s written entirely in C.

I got it building by installing MacOS 10.6.8 Server in VMWare. Installed Xcode 3.2.6. And now, finally, I can build and run it.

What is Frontier?

Frontier — as some of you know — was a UserLand Software product in the ’90s and 2000s. I worked there for about six years.

The app is a development environment and runtime: a persistent, hierarchical database with a scripting language and a GUI for browsing and editing the database and for writing, debugging, and running scripts.

The Nerd’s Guide to Frontier gives some idea of what it’s like, though it was written before many of the later advances.

Maybe you’ve never heard of it. But here’s the thing: it was in Frontier that the following were either invented or popularized and fleshed-out: scripted and templated websites, weblogs, hosted weblogs, web services over http, RSS, RSS readers, and OPML. (And things I’m forgetting.)

Those innovations were due to the person — Dave Winer — and to the times, the relatively early web days. But they were also in part due to the tool: Frontier was a fantastic tool for implementing and iterating quickly.

The Goal

The high-level goal is to make that tool available again, because I think we need it.

The plan is to turn it into a modern Mac app, a 64-bit Cocoa app, and then add new features that make sense these days. (There are so many!) But that first step is a big one.

The first part of the first step is simple, and it’s where I am now: mass deletions of code. Every reference to THINK_C and MPWC has to go. All references to the 68K and PPC versions must go. There was a Windows port, and all that code is getting tossed. And then I’ll see the scale of what needs to be done.

(Note: my repo is a fork, and it’s not even on the web yet. The code I’m deleting is never really gone.)

I’m doing a blog diary on it because it helps keep me focused. Otherwise I’m jumping around on my side projects. But if I have to write about it, then I’ll stay on target.




The Goal

Fri, 31 Mar 2017 13:47:44 -07002017-03-31T13:47:44-07:00

The goal isn’t specifically impeachment and conviction. It’s for Trump to leave office.

The stretch goal is that he dies broke and in prison.

But we could settle for him going down in history as our worst President, as the worst person ever to become President, with the name Trump held in less esteem than that of Benedict Arnold, with Trumpism — that pseudo-populist white nationalism for the benefit of the super-rich — thoroughly loathed and seen for the brutish scam that it is.

I think there comes a point before an actual trial in the Senate where Republican leaders — in Congress, in the Cabinet, wherever — realize that Trump can no longer govern, and they tell him so and urge him to resign.

And I think he actually does resign at that point. He’s been through bankruptcy, and he’s shown that when there’s no path to winning, he’ll take the easiest route out of the situation, the route that leaves him the most status. He doesn’t have the stick-to-it-iveness to go to trial in the Senate: he’d quit.

I don’t know what it will take to bring Republican leaders to this point. Their ongoing cowardice is the real scandal — when faced with a threat to our democracy, they play along because they’re hoping for some goodies.

I don’t think they get to this point unless the public gets to this point, and so I look to the approval polls. If it gets below 30%, it’s probably there because of further revelations in the Russia affair, and it’s probably at the point where even cowards feel safe in doing the right thing — even if only to save their own necks, which will need saving.

But right now Speaker Ryan won’t even replace Devin Nunes as chair of the house intelligence committee. So there’s still a long way to go.




My CocoaConf Yosemite 2017 Talk

Sat, 25 Mar 2017 11:55:21 -07002017-03-25T11:55:21-07:00

Yosemite 2017 was so great. It always is. Below is the rough draft of my first-night talk. A few notes… The actual spoken version is probably not even close to the text, which was written before any rehearsal, and of course it’s never my intent to memorize it exactly. The bit with Laura Savino was a quick three-chord rock medley. We both played acoustic guitar and sang. It went like this: B: Louie Louie, oh baby, we gotta go L: Yeah yeah yeah yeah yeah B: Louie Louie, oh baby, we gotta go L: Yeah yeah yeah yeah yeah B: I live on an apartment on the 99th floor of my block L: Hang on Sloopy, Sloopy hang on B: I look out my window imagining the world has stopped L: Hang on Sloopy, Sloopy hang on [Slight change of chords] B & L: Teenage wasteland, oh yeah, only teenage wasteland [repeated] Here’s my favorite video for Brimful of Asha. During the Squirrel Picture interlude (slide #3) I told the Squirrel Story, which wasn’t planned or recently rehearsed, but I’ve told it often enough that it didn’t really need rehearsal. I dedicated the performance of Hallelujah to Dori Smith. The talk was meant to be about 20 minutes long. Afterward I went around the room with a microphone and each person introduced themselves. (The talk’s job is to be a first-night ice-breaker talk.) I spent about 10 hours on rehearsal for those 20 minutes. Here’s the talk: Slide #1: Three Chord Rock Hi. I’m Brent. Before I get started — seeing my friend Brad Ellis reminded me of the most rock-n-roll moment of my life. Where’s Brad? Hi Brad. Anyway — I was at a party at my friend Chris’s house, and he let me borrow his guitar and do a sing-along. I think we did White Rabbit and Me and Bobby McGee and Hotel California. Well, here’s the problem — I have a hard time hanging on to a guitar pick. Especially after a few beers. So at one point the pick goes flying, and I’m strumming with my fingers. But I had a hangnail, and it got a bit aggravated as I was strumming. At the end I noticed that there was my actual blood on the guitar. I felt bad about it, but Chris was gracious, of course, and I thought that right then: that’s rock and roll. You can use this as metaphor. Bleeding? Keep right on playing. Maybe you won’t even notice that you’re bleeding, at least not until you stop. Chris told me later that the guitar cleaned up fine, so all was well. Okay. On to the actual talk… I bet most of you have heard the phrase “three chord rock n roll.” Or have heard that “rock is so great because you only need three chords.” What you may not realize is that it’s even easier than that: it’s three specific chords. Always the same three chords. They might be in any key but they’re the first, fourth, and fifth. In the key of C, the first is C, the fourth is F, and the fifth is G. In the key of A it’s A, D, and E. And when a song does have more than those three chords, it has at least those three chords. They’re the foundation for almost all pop and rock. One part of music is building tension and then resolving it. I’ll demonstrate on guitar. [On guitar] Play the first .... and you’re fine. You’re home. Play the fourth .... and there’s a little tension. Not a ton, but some. But you want to go back to the first, to home. Then play the fifth ... and you have maximum tension. You definitely want to go back home to the first. So with those three chords you have everything you need to write a thousand songs. Now for a little demo, I’d like to invite Laura Savino up to help me out. [music] Thanks, Laura! SO LET ME MAKE TWO POINTS VERY CLEAR. ONE. If you’re writing apps or a website or doing a podcast or whatever — if you’re just starting out and only know the equivalent of three chords, don’t worry — you [...]



Them That’s Got Shall Get

Tue, 07 Mar 2017 18:29:27 -08002017-03-07T18:29:27-08:00

I try — earnestly, with good faith — to understand the Republican ideologies.

And I think I’ve figured out one of them: they want to make life harder for poor people so that they have more incentive to become rich, and they want to make life better for rich people to reward success, since it should be rewarded, and since doing so provides even more incentive for poor people to become rich.

If you look at it just the right way, you can see it’s not entirely wrong. If the government made material life pretty sweet for everybody, then some people wouldn’t bother to work to earn a living. I wouldn’t bother — I’d just make software and give it away for free.

If the government made life semi-sweet — well, anybody who wants the full sweet would want a job. But some people would be fine with semi-sweet, and they wouldn’t work.

I think that’s where Republicans stand: they think the government has made life semi-sweet, enough so that a bunch of people just take and don’t work. Republicans think: we need to give them an incentive to work.

This explains the health care bill: it takes from the poor, who need incentives to work, and gives to the wealthy, who need rewards for their success. (So the Republicans think.)

* * *

It’s as if the Republicans have no realistic conception of what it’s like to be poor. The choice isn’t between health care and an iPhone, as one Republican suggested — it’s between food and rent, or worse, and forget health care and iPhones entirely.

I was “poor” in my very early 20s. I put that in quotes because I was never in danger of starving or becoming homeless — my parents would have helped me. (They did plenty, in fact.)

But still, even this small experience gives me some insight. I remember buying generic macaroni and cheese because I literally didn’t have enough money for Kraft. And forget hot dogs. And forget vegetables.

I don’t mean that I had some money lying around that I’d put aside; I mean that I had a few dollars to last a week, and if I bought Kraft, which was a few dimes more, I would run out of money before the week was over.

(My bank had a $5 minimum balance for my account. I could withdraw as little as $5 — and in those days ATMs were free — but that would have meant having more than $10 in my account to get that $5. I got so angry because I had, as I recall, $6.91 but couldn’t get at it. I remember thinking that another $5 would change my life.)

I’m not complaining about this, or saying that I had things particularly tough. Not at all.

I’m saying that if you take that experience, and take away any possibility of help from family, and then stretch it out for years and decades — with the inevitable issues, health and otherwise, that happen to everybody — then you have a life where getting ahead is really, really difficult. I can’t imagine; I can only try.

But it’s no semi-sweet life. Not even close.




Don’t Be Scared If You Have to Get an MRI

Thu, 23 Feb 2017 13:37:39 -08002017-02-23T13:37:39-08:00

“Totally normal,” said my neurologist of the results of the MRI on my head. No worries.

I was afraid to get an MRI in the first place.

I got a crown last week, and that didn’t worry me — it’s my ninth. Breathe the gas and just chill for a while. No big deal. It’s almost sad when it’s over.

But I was afraid to get the MRI, because I’m slightly claustrophobic, and all I knew was that they’d put me in a big tube and then walk away.

How It Went

I didn’t have any dietary restrictions in advance. They didn’t inject me with anything. I was told to wear comfortable clothes with no metal — so I wore sweatpants, a T-shirt, and a sweatshirt. I was able to leave my rings (gold, two small diamonds) on.

Beforehand I did a three-sixty in front of a ferrous metal detector. Then I was led through the doors with the giant warnings about extremely powerful magnets.

I put in earplugs that the technician gave me, and then put on headphones. He asked me what music I’d like, and I replied, “80s. Bowie.” I lied down on the thing. There was a firm but not painful thing to hold my head still and give it something to rest on. Under the lower half of my legs was a foam thing that kept them elevated a little. It was comfortable.

He told me it would take about 20 minutes. He also gave me a bulb to hold onto and to squeeze as an alert, and he said they could pause the tests if needed.

Then he slid me in. The tube was more narrow than I expected. And for the first couple seconds I did feel panic rising a little bit, and I thought about squeezing the bulb — but I didn’t. I oriented myself and took some deep breaths.

I was staring up at the top of the tube (I was on my back), but there was this mirror contraption (two mirrors? hard to tell) that I was looking at, and so I was looking out through the end of the tube. What I was actually seeing was a nice, calm painting on the wall — a river and some trees — and I could see the length of my body and my feet, which were free of the tube. I told myself I could scramble out on my own if I had to.

The music started with a Bowie song — “Life on Mars.” Later there were songs by Talking Heads and similar bands. It was good to have music because I could note the passage of time that way. (I guess I was listening to a Pandora station or something similar.)

The machine was noisy, but I had plenty enough ear protection, and the different scans had different patterns. One scan near the end included a bit of vibration. The technician talked to me through the headphones a couple times to let me know how much time was remaining. I just kept my eyes on that painting the whole time.

I had no trouble being still, except when I had to swallow. I just did. It was otherwise comfortable. And I could have gone another 20 minutes, easy.

* * *

Of course, I’m lucky. I have very good insurance through Omni, and it paid for this. And, even luckier, the results were totally normal.

Hear that, world? The inside of my head is totally normal. I don’t mind feeling good about some good news for a change.

Update 4:15 pm: I’ve heard that not all MRIs are so nice. They might not have the mirrors and the music. In that case, well, I’m sorry. Just remember that they won’t forget you’re in there, and they’ll let you out at the end. Stay cool.




OmniOutliner Essentials

Wed, 22 Feb 2017 10:17:48 -08002017-02-22T10:17:48-08:00

Omni introduces OmniOutliner Essentials:

We didn’t want to just reach out to our existing audience; we wanted to introduce the joys and benefits of outlining to a much larger audience. We decided that meant two things: we needed to make the app much simpler, and we needed to make it much more affordable.

It’s in public preview now. You can check it out.

I’ve been the junior developer on the OmniOutliner team for a couple years, and it’s a joy to work on an app that I’ve loved for years as a user. We’re not finished yet with this release, but I’m very happy with how it’s turning out.

PS I like that Ken mentions MORE in the blog post:

We shipped the first beta of OmniOutliner while Mac OS X was still in beta, and doing so introduced us to a passionate community of outliners who had been using great outlining tools like MORE for over a decade.

MORE was by Living Videotext, which was Dave Winer’s company. Later I went to work at Dave’s company UserLand Software, which also included an outliner in its app Frontier, which I worked on. So there is a sort-of family tree connection from OmniOutliner back to MORE.




How Trump’s Support Erodes

Sat, 04 Feb 2017 16:25:30 -08002017-02-04T16:25:30-08:00

Even Trump’s supporters know he’s not a good and competent man — nevertheless, they think they can get what they want from him. It’s a cynical deal, and bad, but you can understand it.

Trump’s vagueness and flip-flops, and the suggestion that he not be taken literally, all help him with this: his supporters, who don’t all want the same things, see what they want to see.

Many Republicans wanted a corporatist to replace Scalia on the Supreme Court, so that decisions like Roe v. Wade could be over-turned and, especially, so that more decisions like Citizens United would be made. It’s likely they’ll get that with a Gorsuch confirmation, no matter how Democrats fight (and they should fight).

But beyond that, every time Trump actually does something specific — as opposed to just saying hard-to-pin-down things — he erodes some support.

For example: many Republicans — Vice President Pence perhaps foremost, along with the Christian Sharia — want to see LGBTQ protections rolled back. But other Republicans don’t, and Ivanka Trump and Jared Kushner reportedly managed to prevent (at least for now) an Executive Order to that effect.

Many Republicans support multilateral free trade (as do I), and in particular agreements that strengthen our ties in Asia as a balance against emerging Chinese power. Well, TPP is not going to happen, and the future of NAFTA is in question.

Many Republicans do not support a Muslim ban which would make our country less safe and demonstrate to the world that we are not the beacon of liberty we’ve claimed.

Many Republicans support a strong NATO alliance and consider Russia one of our biggest threats — but Trump doesn’t. The jettisoning of the post-war American peace in favor of allying with Russia in a clash of civilizations with Islam is not what every Republican wants to see. (What is the winning condition — or final solution — for that kind of clash?)

Not every Republican is willing to spend taxpayer billions on a big, beautiful wall. They all know that Mexico is not paying for it.

Yes, there are some supporters who’ve been happy with everything.

But with each specific move, or lack of move, more supporters learn they’re not going to get what they want, and they learn they’ll get some things they don’t want.

Trump campaigned as almost a Rorschach test, where a large-enough coalition could believe he was on their side. As he makes specific moves, elements of that coalition learn that he’s not.

And that’s how his support erodes — because once you realize he’s not on your side, all you have left to support is his narcissism, mendacity, cruelty, corruption, and incompetence.




Web Developer Position Open at Omni

Tue, 31 Jan 2017 12:57:22 -08002017-01-31T12:57:22-08:00

Check out Omni’s jobs page:

The Omni Group is seeking a senior front-end web developer to develop and maintain a world-class website for our Mac and iOS products. The position is part of the Design Department and will focus on bringing mockups to life.

Omni makes great apps and it’s a wonderful place to work.




First Week Notes

Mon, 30 Jan 2017 12:03:28 -08002017-01-30T12:03:28-08:00

It’s not Russian Roulette when there’s a bullet in every chamber — it’s just Russian.

* * *

It should be clear by now that Democrats in Congress should resist every single thing Trump attempts. Every nominee. Every law. Every single thing. Do not collaborate.

* * *

The next thing might be a “Religious Freedom” executive order that permits anti-LGBTQ discrimination.

* * *

Things move fast. History:

Jan 30, 1933: Hitler becomes Chancellor of Germany.

Feb 27, 1933: Reichstag fire.

Mar 23, 1933: Enabling Act, which establishes the dictatorship.

Things move faster these days, seems like. The question is: what will be the equivalent of the Reichstag Fire?

It has to be an emergency where Trump can claim “temporary” expanded powers.

Would massive, continuous protests be enough? Quite possibly. (Which is not an argument against protests. I’m quite definitely in favor of protests.)

But don’t be surprised when those powers end protest, free speech, and the free press, in the name of national security and order.

You might think Trump isn’t historically aware enough to know the would-be dictator’s playbook. Maybe he is, maybe he isn’t. I don’t know.

But Bannon is.




Mighty Yosemite

Tue, 24 Jan 2017 21:01:48 -08002017-01-24T21:01:48-08:00

A little birdie — okay, it was Sol-meister K. — tells me that CocoaConf Yosemite is close to selling out.

Don’t miss out! It’s so beautiful. This will be my third trip — because I miss it when I’m not there, and because the people are awesome.




Omni’s Roadmap and Scripting

Tue, 24 Jan 2017 12:22:06 -08002017-01-24T12:22:06-08:00

Omni: Looking Back, Looking Ahead—2017 Edition:

In 2016 we scratched the surface with URL automation on iOS, but in 2017 we plan to roll out user automation on iOS in a big way across all our apps with a much richer set of capabilities. This automation support won’t be limited to a simple set of URL primitives; instead, we’re adding support for running JavaScript code: code that has the same level of deep support for manipulating the data in our apps as we’ve previously exposed to AppleScript…

Right before the holidays I approached Sal [Soghoian] to review the automation work we’ve been doing, and over the past weeks he’s been enthusiastically exploring the boundaries of what’s already possible as well as helping us see what else we need to build before shipping this.




Today

Fri, 20 Jan 2017 10:10:02 -08002017-01-20T10:10:02-08:00

Today wasn’t so bad. Sure, the enemies of democracy, the Constitution, rationality, compassion, national and international institutions, decency, competence, ethics, art, science, and truth itself — and of anyone who isn’t a white man — now darken the offices of power. But they haven’t done much yet. The bad days are still to come.

My loathing and contempt for President Trump feels complete — but it isn’t. It will continue to deepen.