Zed Weekly: #22

October 6th, 2023


This week has been mostly themed around adding code/dashboards to track Zed's CPU load and memory consumption. We want to have a more concrete idea of how many users are experiencing anomalous usage levels and be able to investigate those cases more easily.


I've spent this week working on integrating Vue.js LSP and tree-sitter queries; in the process I have explored a protocol for semantic highlighting with LSP, which looks like a cool feature to have in the future. As of today I have a working version of syntax highlighting for Vue files, so for the next week I plan to get into your shoes and iron out all the wrinkles to make it nice. :)


This week I've continued work on the new UI system. I spent some time pairing with Nathan on the upcoming version of GPUI, which has really bolstered my understanding of the library. I also began the process of migrating the UI components Nate and I have built so far over to the new version of GPUI.


This week was mostly a deep dive into Zed's collaboration features for me. Firstly smoothing off some of the most obvious rough edges with joining channels and sharing projects: you can now see who's hosting a shared project in the title bar, and following should be a lot more reliable.

The next step is to build a mechanism for people outside of Zed (the company) to help us build Zed (the editor). We're building public-access channels, and as part of that adding support for deep links into the app itself. In an upcoming release you'll be able to invite people to channels by just giving them a link.

On the personal side, I also blogged about my experience picking up Rust; and I'm trying to get back to the bi-weekly blogging habit (that I last sustained in 2012 :D). If you're interested, you can read the details of What does = do in Rust?

Antonio & Nathan

We joined forces to work together on revamping GPUI and this week we've mostly been working on porting the Metal renderer to the new version, taking the opportunity to innovate and clean things up as we saw fit. As part of this effort, we've now switched to using plane-split to determine the drawing order of the primitives. The only missing piece for the renderer is the drawing of BΓ©zier curves, which we should complete early next week.

Another cool aspect of the new GPUI is that entities can now be accessed from multiple threads. However, certain actions, such as interacting with most native UI APIs, still need to be performed from the main thread. Most functions/methods in a GPUI application take a "context", which is essentially a reference to the entire state in the system and lets users interact with the app, the window, and other entities. This week we introduced a new MainThread<T: Context>(T) type: when on the main thread, each context will be wrapped around this new type, which ensures we can call those native APIs in a thread-safe way.


Channels are really starting to shape up! This week I've been working on adding change notifications to both our buffers and our chat, so you're actually able to see when there's something to read. In the process though, our channels have become a bit unwieldy, see how much is going on in our screenshots of the channel UI. While we push forward on core features, like notifications and public channels, we're also taking a step back and rethinking the core ideas of this feature. Fundamentally, we have two use cases:

  • Internal project management for technical teams. This is why we have channel notes and structure things like a file system (Directed Acyclic Graph or DAG).
  • Internal project communication, like Slack or Discord. This is where a lot of the chat and notification style features come in.

But these two use cases pull against each other in fundamental ways. Project management is about effectively organizing information and surfacing long-term information. Shaping it like a DAG allows you to index into all the ways you can think about a project's structure. For example, a new feature might have parts of it that correspond to the backend, frontend, and design teams. Each one needs to know their respective parts of the problem and needs to look over each other's shoulder's to coordinate their effort. Forcing a document like 'API design' to have a singular 'owner' (backend or front end) injects needless friction into a process that is fundamentally a negotiation between multiple parties.

Meanwhile communication is best served by rapid access to uncertain information. Having to pick your way through a document heirarchy just to figure out where to ask a question is a miserable experience. It's much better to have a simple, coarse-grained structure like Slack's channels that can get you close enough to the best recipient for your message that the human social graph can takeover.

Right now our channels are kind of in the worst of both worlds. Our channel notes are tucked away behind a normally-invisible button with no UI guidance on their purpose, there's way too many different places to talk with no way to know who is reading what, and it's just overwhelming to even look at.

So how do we streamline this problem? Unbundle the two use cases to where they're most useful.

So something a bit more like this:

Zed Industries
    πŸ“„ Zed UI rewrite tracker πŸ”—
    πŸ“„ simplifying channels πŸ”—
      πŸ“„ Channel use cases
    πŸ“„ Zed UI rewrite tracker πŸ”—
    πŸ“„ simplifying channels πŸ”—
      πŸ“„ Channel use cases
    πŸ“„ notifications
    πŸ“„ public channels

Clicking on a chat channel would open up a chat. Clicking on a document would open up the document. Channel notes can still be in multiple places but chat channels wouldn't be. The project management and document store features are tucked away until you want them and the communication features are front and center. This would be paired with a system a lot like Slack's 'Browse Channels' and 'Channel Memberships' features, so you wouldn't even need to see channels that aren't relevant to you. My view of this organization might be as simple as:

 >  #design
 \/ #livestreaming
    πŸ“„ simplifying channels πŸ”—
      πŸ“„ Channel use cases
    πŸ“„ notifications
    πŸ“„ public channels

Which will hopefully make it a lot easier to navigate and use. We'll probably be working on some variation of this over the next week or two, so stay tuned!


I've spent most of my heads down time this week on tying up the loose ends of auto-complete documentation. We already had markdown rendering for displaying hover popups and my initial demo effectively copy pasted that code. One interesting a bit of work I've done this week was to wrangle it into a reusable API which allowed me to more easily preprocess the documentation markdown up front by separating the parsing and rendering stages.

Rendering is what we call building the element tree which is actually rasterized to the screen, and previously the hover popup would re-parse its markdown whenever it needed to rebuild its element subtree. This was fine as we do this relatively infrequently and the markdown is usually small, but I couldn't do this for completion documentation as we need to allow for the case when a specific language's grammer hasn't been loaded yet to syntax highlight a code block in the markdown. I attempted a bit of a gross workaround to handle this but it would add flicker when first displaying a completion's documentation which was a non-starter.

Furthermore, conflaiting these two steps meant I had to do significantly more work to expose editor styling to these code paths handling markdown so they would be able to look up how the various markdown sections should look with the selected theme, font, and scale. By reworking it heavily I've been able to signficiantly improve the code quality for UI items needing to handle markdown and as a cool side effect they should render a little bit faster now! :)


This week, Mikayla and I finished up adding a status indicator to each Zed channel, so that you can see which channels have changes to their channel notes or new chat messages, that you haven't yet seen.

On Thursday, I fixed a long-standing bug in Zed's following feature, where you couldn't follow a collaborator into a view if that view was originally created by them following you. This bug was due to our attempts to prevent infinite loops when peers followed each other, so I had to find a less restrictive way of preventing the infinite loop.

After that, I started work on notifications. To make channel messages more useful, we need to be able to @-mention other users, and make sure that they are notified. Notifications will probably go into another side panel, similar to the collaboration and chat panels.