Zed Weekly: #28

December 4th, 2023

The current state of Zed2
The current state of Zed2

The team is hard at work on the Zed2 initiative. Aside from pulling a developer here and there to fix critical issues in Zed1, everyone is laser-focused on getting through this transition. We have broken the work down into 3 phases:

Phase 1: "Get Zed2 runnable"

This phase includes completing the absolute basic core functionality - being able to edit files, autocomplete, have tabs and splits, etc. We are nearly done with this phase. In fact, Mikayla and Max both worked to get a Zed nightly build system running, and we plan to use Zed2 to build Zed2 in the next week or so.

Phase 2: "Making Zed productive"

This phase includes completing features that are important in an editor, but aren't quite at the lowest level of text editing. These are things like collaboration, the terminal, Vim mode, etc. Work on this phase has begun already.

Phase 3: "Full featured"

This phase includes completing the larger flagship features of the editor: Assistant, Copilot, Chat, etc. We will focus on this more once phase 2 nears completion.

Our current goal is bold: "Have a working version of Zed2 out in preview by the end of 2023." We think it is possible, but we will have to see how the rest of the unknown unfolds in the coming weeks. We plan to be open source shortly after Zed2 supersedes Zed1.


It has been a few weeks since I have written a Zed Weekly entry. Since then, I've split my time between smoothing out some rough edges in our telemetry and keeping an eye on the community. During this transition period to Zed2, I'm mainly focusing on reading all community feedback, everywhere I can find it, so we know what to prioritize when we cross the finish line on the port. I'm doing my best to use my gut instincts on what to surface to the team as serious issues vs. things we can address later. Outside of missing features, please (let us know) if you are encountering any major crashes or bugs.

As a sidenote, at some point, the team is going to be doing office hours, where they will work with the community, conduct programming sessions, and answer questions. For me, I wasn't certain how I might fit into that plan as I don't work on the editor itself much, but what I think I can do during that time is maybe have one-on-one sessions with users, through Zed, where users can take the lead and I can identify what sort of friction points come up.


I've been working on porting a lot of the core UI this week – Things like Popovers, Autocomplete menus, refinements to our buttons (see Marshall's far more detailed dive below!) and some of the collab UI.

We are working towards being able to run our weekly meeting in Zed2 next week, so pretty heads down getting things ready for that.

We are excited to show this off to you all soon!


One of the things I did this week was port editor breadcrumbs to Zed2. While the actual breadcrumbs were a minor part, it was extremely cool to collaborate with Nate directly on the type of button API I needed to do it correctly. I'm super excited about the increased level of consistency we are able to achieve now with our new UI construction methodology.


This week I focused on refining some of the UI components that we're using in Zed2.

The first candidate was ListItem, which we use in a number of spots throughout Zed, like the project panel, the command palette, and the various context menus. While these pieces of UI are all rather unique, the foundational need to render a list of items is the same.

Using ListItem in these different contexts involved reworking the API to be more open, allowing it to act as more of a container and not be quite so opinionated about the kinds of children it displays. This change in approach keeps ListItem flexible enough to be used in a variety of different contexts while still allowing us to achieve a consistent style.

After wrapping up ListItem, I moved onto a rework of our buttons that Nate had been exploring. In Zed2 we currently have two different kinds of buttons: Button and IconButton. Before this rework both of these buttons were implemented independently, which made it hard to ensure they were styled similarly and had consistent APIs.

We introduced a new ButtonLike component to provide the base functionality for any component that behaves like a button. While this primarily serves as the basis for our concrete buttons, it can also be used for building different UI components that should have button-like behavior. ButtonLike gives us a centralized spot to deal with button styling, which will help keep our buttons visually consistent.

In order to keep the APIs of our buttons and other components consistent we've started introducing some traits to define common behaviors. For example, we have a Selectable trait that defines the interface for a component that can be selected:

/// A trait for elements that can be selected.
pub trait Selectable {
    /// Sets whether the element is selected.
    fn selected(self, selected: bool) -> Self;

We can then implement this trait for ButtonLike :

impl Selectable for ButtonLike {
    fn selected(mut self, selected: bool) -> Self {
        self.selected = selected;

The selected field is then used in the RenderOnce implementation for ButtonLike to change the visuals of the button when it is rendered.

Since our Button component is built on top of ButtonLike, in order to implement Selectable for Button we can simply delegate the trait to ButtonLike's implementation:

pub struct Button {
    base: ButtonLike,
    // ...
impl Selectable for Button {
    fn selected(mut self, selected: bool) -> Self {
        self.base = self.base.selected(selected);

In other news, Advent of Code starts today (technically last night). I'm using Rust again this year for solving the puzzles, and am looking forward to trying to solve some of them from within Zed2!


I've been fixing frontend-related bugs this week: typescript-language-server started to require more capabilities to send diagnostics, long standing eslint parsing bugs and other smaller ones. In addition to that, prettier got a good pass to become more robust in offline environments. Next, I plan to make eslint more configurable and finish fixing a bug with excluded files that sometimes get open wrongly by Zed.

In parallel, I've been considering options with file finder being able to search in gitignored directories more: I think we could pull that off by turning our input into more than just a text editor. If it starts to accept and highlight queries into ${ignored_directory_root}/${fuzzy_query_part} parts, we could limit the reduce surface to something more acceptable, especially if we go more clever with the fuzzy part and match lower directories better. While this is also an interesting task, fitting this into gpui1 is also a challenge of its own, so feels like I might pause on that before gpui2 is released — that progresses really well so hopefully we will land more and more UI-related features on top, including the search one.