Austin Rude's Blog

Zig IDE: Devlog #02

It's been a month since my initial devlog, and in that time I've made progress on several things. Before getting to that, I want mention how happy I am with the amount of interest in the project. There seem to be a lot of people that miss native apps.

A common piece of feedback I got was that the name I had chosen, Zeal, is already used by a popular open-source documentation viewer. With that, the search for a name continues. I have a few ideas, but I'm not ready to commit to one yet.


Core Ideas

When the user's code is working, they aren't thinking about our language at all – their headspace is all about their program. It's usually only when things go wrong that they notice our implementation.

— Bob Nystrom, Crafting Interpreters

I think this is something worth thinking about in the context of all tooling we use. If I do my job correctly with the IDE, you shouldn't be thinking about much outside of the program you're writing. The goal is to keep you focused, so you never have to stop and reach for the documentation of the IDE, or Zig itself. Based on what you're doing, all information should be right in front of you, or a click/hotkey away if it is too intrusive to display inline. Little sidequests to find what arguments a function takes, lookup a hotkey, etc., should be kept to a minimum. I'll be keeping this in mind as I work on the IDE.

Builtin Popover and the Language Reference

I spent some time working on the design of the Popover that will appear when you click a Zig builtin function like @sin().

Popover that will be displayed when the user clicks a Zig builtin like @sin()
What I want to appear when you click a builtin such as @sin in your source file. I could have been sneaky here and put an @sin in the source file, but I wanted to be up front about it just being a mockup. Also, the Usages section layout bothers me a little bit, but I'll clean that up later.

The functionality provided by the "Usages" section is exciting. When working on Zig code, I find myself searching the standard library for usages frequently. How cool would it be to click the link and get taken to a list of call sites?

I have some further plans in this area too. I'd like the documentation viewer to display tests, and give you a way to click a button and be thrown into a playground with that unit test so you can make changes to the code, and quickly test things.

Zig Autodoc

I spent some time this month writing a sort of Swift importer of the JSON output from the new Zig Autodocs effort. A zig/ziglang Wiki entry goes into detail on how it works, what the goal is, etc.

The autodocs effort is in the middle of a lot of changes right now, which makes building tooling from it a bit of a fool's errand. I knew this going in, but getting a dump of the type/docs info for the standard library was a bit too tempting – and it was much easier than I anticipated so I kept at it. It ended up taking a day and a half to make Swift types to decode all the JSON. There were a few quirks but for the most part it was smooth sailing.

A mockup of the documentation viewer
My Swift package that consumes the autodocs JSON. It's ~1200 LOC. You'll notice some sweet type data in the console output.

To be clear I'm only consuming a JSON file. The hard work is being done by Loris Cro, vallahor, and other contributors, who have dug into the compiler, and transformed the ZIR data into a useful format for frontend display.

I think there is a lot for me to learn from the autodocs codebase, and that was part of the draw to start using it. If I have time I want to follow along as the code evolves and learn as much as I can.

A mockup of the documentation viewer
A mockup of the documentation viewer. It's pretty rough but you can probably see where I'm going with it. I haven't tried feeding it the autodocs data yet.

Learning about Compilers

The opening quote of this post probably gave it away, but I'm still working through Crafting Interpreters. I've just reached the start of Chapter 5.

I'm a little disappointed with how slowly I've been progressing through the book. I lost track of time too many nights this month and didn't do my daily reading. I have plenty of general IDE stuff to do, so it's not blocking progress, but I feel like the sooner I know programming language and compiler fundamentals the better. Having that knowledge will likely affect the design of the IDE and save me from making some bad design decisions.

Line highlight stroke

A small addition this month was adding an optional stroke to the highlighted line.

An optional stroke on the highlighted line is now available
the stroke's the word

Text Selection / Whitespace

One thing most editors do, that you may not have thought about, is that during text selection they add symbols highlighting the whitespace characters. This is a beautiful example of software being context-aware, since when you're making a text selection, that information is usually important, and drives your next action. For example, a selection with 8 spaces of leading white space means you're probably going to have to re-indent it immediately after pasting. Without that whitespace being visible and noted to you when making the selection, it could be slightly jarring when you paste it in and it's not where you expect. Surprises like this are what cause a break in your workflow. I know this seems minor, but these things add up and an accumulation of small touches like this are what make an IDE productive and enjoyable to use.

This month I did a little work on adding these features.

Showing how whitespace is highlighted in the text editor
Here you can see the little circles indicating a space character. I still need to limit them to the highlighted region. The highlighted path also needs some tweaks and rounded corners.

I also explored building out the vim commands to move the cursor when in visual mode, etc. I was able to come up with some ideas for how this might work internally, and it brought some potential challenges to light. I have some work to do on word boundaries – the boundary characters the TextKit2 API uses are different than the ones vim uses. Getting a good vim hotkey implementation is going to be a lot of work, but it's something I'm committed to.

NSTextView No More

While I was writing the last devlog entry, I started a big refactor of the main text editing control to not be an NSTextView. That control is pretty dated and comes with a lot of stuff we don't want or need.

The alternative approach I've adopted is to use TextKit 2, start with an NSView, and build out the text editing stuff myself. Apple's TextKit 2 sample project works this way, and I think it's a logical choice for this project too.

Theme Selector

The theme picker UI got a few upgrades.

New previous/next/random theme buttons.
New Previous/Next/Random theme buttons. They are mapped to the arrow keys, and space bar.

WWDC 2022

WWDC 2022 is just around the corner (June 6th, 2022). It's a little embarrassing how excited I get about a corporate event, but for the most part I like the platforms Apple has built, and getting a year's worth of improvements all at once is amazing. It's also a bit of a relief to know the roadmap for the next year – I have a habit of stalling on things I suspect will be changed at WWDC.

Some things I am hoping for:

  • TextKit 2 ranges are kind of weird, and the interaction between NSRange/NSTextRange/NSTextSelection is awkward. I can work around this by writing extensions, but hopefully, some API improvements come about that save me the trouble.
  • I have to write a lot of boilerplate to make the Preferences/themeing stuff fast. The naive/first approach was awful from a performance perspective. I have a hunch that some new SwiftUI property wrappers will be added to make it easier to add more fine-grained dependencies for View updates. Thankfully I can implement these property wrappers myself if they don't materialize this year.
  • Customization access to more controls. I've written a SplitView and TabView both in SwiftUI and AppKit, all due to not being able to customize basic things. The SwiftUI provided versions are simpler, have nicer animations, and are easier to add custom drawing to. But due to not being able to customize a few aspects of the controls, I have had to use AppKit instead. Hopefully Apple opens up more customization paths and I can switch to the builtin SwiftUI implementation instead – and delete the AppKit/custom SwiftUI ones.
  • The Swift Process API has some ugly edge cases. I'm hoping it gets cleaned up and becomes easier to use with async like URL.
  • An easier way to combine SwiftUI and TextKit 2 without NSViewRepresentable. Maybe a more foundational SwiftUI drawing primitive will be exposed, like CALayer is to NSView?

What's Next?

I like to divide work into two categories: shallow and deep. I do shallow work during the short gaps of time I get. These tasks tend to be small UI components and things like that. The deep work is done in the evenings, or on weekends when I need long chunks of time to try and come up with nice abstractions.

I've pushed off a lot of deep work lately, partly because I think this WWDC will bring changes to foundational areas of the codebase. Following WWDC, it will be time to go back and tackle those issues.

Parsing the language reference

To provide the data for the @sin popover above, I need to have access to the contents of the Zig Language Reference. This means writing a program to transform the data in the HTML/markdown into JSON or something I can more readily make use of and display/search natively.

Working towards a beta release

My goal is to do a sort of beta/MVP release for macOS 13 at the end of the year. It'll be trimmed down, and not fulfill my goal of being a standalone Zig IDE. Instead, I'm imagining the first beta will be a supplemental tool for Zig developers on macOS; offering powerful tools to explore and learn the language. Working on actual codebases will come later.


Metrics

Some useless but fun stats:

  • Days since the first commit: 577
  • Lines of code: ~22,676 (+1,676)
  • Commits: 909 (+168)

(These figures don't include the ~1,265 lines/65 commits I wrote for the Swift Zig Autodocs work)

FYI: Work hasn't been consistent the entire project duration


I wasn't sure I'd do another entry this quickly, but slow steady progress adds up. I'm looking forward to WWDC and tackling some big design decisions after it. That may mean I spend a month or two on work that isn't very visible – but it needs to be done.

As always, thank you to the Zig community for being so helpful.

Thank you for reading!

-- Austin (twitter)


Tagged Zig IDE , Zig , macOS and devlog