Introducing Zeal: Devlog #01
Zeal is my closed-source Zig IDE written entirely in Swift and Zig. I'm at about 21,000 lines of code, and while I've just gotten started, I'm excited about how things are shaping up.
Today I want to share the design decisions, my reasons for using Swift instead of going all-in on Zig, and what I want Zeal to be able to do when it's ready for primetime.
The Vision
Articulating (or even knowing) the roadmap/features this early is difficult! Instead, I want to share some of the goals or themes of the IDE:
Everything should be available in the IDE
Leaving the IDE to go check documentation often ends up consuming a lot of time. Instead, I would like my IDE to have a powerful documentation viewer and code browser so I don't have to switch to my browser and start searching GitHub or docs.
I also want to explore displaying type-specific information in the popups that appear when you click on built-in types. As an example, clicking the i16
keyword would display the min/max values for the integer sizes. I haven't memorized them, and I don't like having to open a calculator every time I need to know. If you notice when looking at the table that a different integer size suits you better, just click it and it's replaced.
Spark joy
It's a bit of a meme at this point, but Software doesn't have to be boring. I want to build something that is fun to use – so fun that users will want to explore it. I'm talking tons of little tools, cheatsheets, and interactive UIs that are ready to help you write Zig code.
Use font/color to reflect actual code semantics
I think there's a general lack of consistency in most developer tools. Especially when it comes to font and color.
I want to explore heavily using the semantics of the code to drive the font/color choices in syntax highlighting, etc. I think this will help users understand the codebases they work in. I spent quite a bit of time several years ago implementing a perceptually uniform color space from a paper, which I plan to use for this.
Developer tools don't have to be restrictive
Sometimes when I start working in an IDE, I feel like I am trapped in a sort of container. I want to avoid that. Jotting down a quick note, or testing out some syntax should be care-free. I shouldn't have to create a new file, add it to .gitignore
, etc. just to take some notes or maintain a to-do list. Same for trying out some code – I want to just click "New Playground", and get thrown into a temporary sandbox so I can experiment.
It's a Graphical User Interface, NOT Text!
Gone are the days of being limited to 80 characters of text on a line. A modern IDE should make use of that extra space and help me do my job of writing software. This means providing context when editing code, adjusting settings, and wherever else it is useful.
Don't make the user remember every damn thing
Most editors have plenty of hotkeys, the problem is remembering them! Command palettes have helped a great deal with this, but I want to explore taking this further and making other parts of the IDE "interactive". For instance, what if when a build fails, the hotkeys to navigate backward/forward between build errors appear in the text editor? What if we did this for everything. The fewer hotkeys I have to remember, the better.
Customizable
Since we live in our tools, we should be able to make them our own. Zeal already has the most fun theming system I've ever used.
P.S. Yes, there will be Vim-style hotkeys.
Why Swift and not Zig?
This was a tough decision, and I'd be lying if I said I don't second guess it frequently and investigate re-writing everything in Zig. But, I've written quite a bit of code at this point and have some reasons I think Swift is a better choice for my goals:
- I'm trying to build the best IDE possible. That means I want to have every platform idiom and quirk working – no surprises or inconsistencies. I don't think that's achievable today unless you build a native application.
- It's easier for me to leverage the frameworks Apple provides. The scope of the IDE I want to build is huge, so being able to throw a PDF viewer together in a week using PDFKit is a major benefit.
- I have a lot of experience working on macOS software with Swift. I feel like the stars have aligned with SwiftUI being released since I love making UIs too.
- When I started, Zig didn't have a library I liked for doing vector graphics. Now we have nanovg-zig, and more are in the works.
As an aside, I started learning about 2D rendering to make the entire IDE in Zig. I got scared of the added scope of something like that plus an IDE. But I hope someone does it – a 2D graphics framework built on WebGPU/mach could be the future of desktop applications.
Anyway, software development is full of trade-offs, and the path I've chosen has many I like.
Architecture
As mentioned, the IDE will be a native macOS app, built with Apple's blessed tech stack: Swift/SwiftUI. I am also using TextKit 2 which is a recently released, more performant text engine.
No Language Server Protocol
I'm going off the beaten path here, and choosing not to use the Language Server Protocol (LSP) to do the IDE bits. I plan to write all the syntax highlighting, code completion, and other IDE things myself in Zig. Communication between Zig and Swift will be done with the C FFI.
This is in contrast to most tools today, which are embracing the LSP. While I think the LSP is great, and personally benefit (and appreciate) that we now have editor/IDE support for so many languages, I do think there is still room for focused tools. I know that not using the LSP will be very difficult, but I think a custom solution will help me deliver an IDE with better performance and more Zig-specific features.
Status Update/Recent Progress
What I've been working on
Most of my time so far has been spent probing how to design different systems and make them flexible. This has been tricky with SwiftUI being relatively new. Figuring out how to make the Preferences window searchable/filterable, and list rows/Views of different types took some time. SwiftUI in general has been pretty difficult to figure out when going beyond basic examples – but I feel like designing things is coming easier for me the more I use it.
Here's a quick overview of what things look like currently:
Theme Switching
Preferences
Build Options
Command Palette
Source Screenshot
Playground/Sandbox
Ziglings
Metrics
Some useless but fun stats:
- Days since the first commit: 546
- Lines of code: ~21,000
Work hasn't been consistent the entire project duration. SwiftUI was much less capable last year, so I would run into issues and shelve the project
Designing the Theme Switcher
I feel like in some IDEs the OOP architecture of the settings is pretty transparent. Every setting is either a string
, double
, or bool
. And the UI is a text input, slider, or checkbox. That is boring and no different than editing a text file. We can do better than that in a GUI! Some controls deserve extra attention, and the theme picker is one of those.
Creating this UI was pretty fun. I like the structure of my sketch more than what I made. Showing a mini text editor seems like it is a better preview than the little rectangles demoing the theme colors. I plan to make this look more like my sketch in the future. I'll probably need to use SwiftUIs Canvas
to make it performant enough. Scrolling was pretty janky since there are over 200 themes – but using .drawingGroup()
fixed that.
I think with the number of themes, I need to have good filtering capabilities. The fancy color library I mentioned earlier should let me have a color wheel where the user picks a color, and the themes are then sorted by how well they match the selected color. Also, a filter for dark/light themes would be a nice addition.
What's Next?
My usual strategy is just to run the IDE, poke around a bit, and pick something to work on. But some things I want to do next are:
Syntax Highlighting
I'm slowly working through "Crafting Interpreters" and the awesome Zig Compiler Internals posts to try and learn. As mentioned, I plan to use Zig directly to get syntax highlighting, rather than regular expressions. I think this will be a big step towards the IDE feeling more real.
I also want to experiment with using variable fonts to structure things.
Welcome Window
I've got a nice sketch, and am looking forward to making a Welcome Window/Screen, that will be displayed when you load the IDE and haven't selected a project.
Splitviews
I spent quite a bit of time working on the splitviews, but there are a lot of bugs, missing features, and other issues. I think I designed this part of the IDE a few times and left pieces of each design scattered throughout the UI code. I need to go through it and clean everything up. I also have some neat UI ideas for managing splitviews that I want to implement.
Make Theming stuff beta release ready
The theming stuff is pretty close, and it would be nice to have a feature fully implemented. I'll probably hold off until after WWDC 2022. I have a hunch that Apple will change things related to SwiftUIs data management which will make the theme code a lot less verbose.
Zig specific stuff
I want to get to more Zig-specific things, like displaying compile errors in the IDE, and parsing build.zig options, etc. But I think those won't for a few more months. I just have too many general IDE things left to do.
Cleanup
I've got a lot of code already (~20K LoC), most of which I'd call "prototype" quality. A pass cleaning things up would be beneficial. Every old piece of SwiftUI code I look at has some issues I now know how to fix.
What's the endgame?
I plan to keep it closed-source and sell it. To be able to provide consistent updates, and keep up with Zig/macOS changes it will probably be a subscription. I've thought a lot about it and think this approach will allow me to work on it full-time and flesh out all the ideas I've accumulated.
If I was building a cross-platform IDE, or one targeting multiple languages I think I'd try and do it all open-source and funded with sponsors instead. But that's not the direction I'm going. The goal is to build the best IDE ever, crafted to help you write Zig. Not something that supports every language, with compromises.
This is my first devlog, so bear with me while I figure out the format.
My original plan was to try and do an update at the end of each month. But after writing this post, I am worried about the time commitment and may aim for publishing a post every other month instead. We'll see!
Thank you to the Zig community for being so helpful, and thank you to my friend @TankorSmash for helping me improve this post.
Thank you for reading!
-- Austin (twitter)
Tagged Zig IDE , Zig , macOS , devlog and Zeal