← 返回博客

Zed Weekly: #23

2023年10月13日


Julia

本周我终于将自动完成文档合并到了主分支。在此期间,我研究了一个长期存在的问题,即补全时的类型性能不佳。

显示自动完成有两个主要阶段:请求和过滤。当用户开始输入时,我们还不知道任何补全,我们必须要求语言服务器提供一个列表,这就是请求。一旦我们有了一个列表,我们就可以执行自己的模糊排序和修剪,以删除多余的项目,并将最接近的匹配项放在列表的顶部,这称为过滤。

仅一次请求是不够的,我们需要不断重新请求最准确的列表,因为服务器提供的内容可能会随着用户继续输入而发生变化。但是,当我们等待服务器响应时,重新过滤我们已有的列表以根据用户进一步的输入重新排序可能是有用的。理想情况下,这应该提供更流畅的体验并隐藏一些延迟。

不幸的是,在进行此重新过滤时,我们阻止了UI线程,直到过滤完成,从而导致卡顿并增加输入延迟。因此,我们也一直等到它完成才请求完成列表的新副本,从而进一步加剧了与语言服务器通信的固有延迟,尤其是在网络上。这不应该发生,因为过滤API非常明确地在我们的后台工作线程组中运行该工作。

棘手的是,仅仅因为一个子系统将繁重的工作卸载到后台工作线程并通过异步正确协调,更高层的调用站点仍然可能滥用它,而这正是这里发生的事情。重新过滤被触发,它将工作转移到后台,并等待它;然后我们获取生成的未来并在其返回时阻止整个线程。简而言之,整个UI线程停止运行,什么也不做,只是等待后台线程完成过滤。

经过一番努力,我能够重新配置完成菜单的状态以允许多工作线程同步,并设置此重新过滤以不阻塞并与重新请求竞争。这允许重新过滤在重新请求花费一段时间时改善体验,但不会过度干扰。重新请求新列表将不再等待重新过滤完成,希望降低该延迟。此外,在使用大量补全输入时,UI不会卡顿或结巴。

Marshall

我本周的一个重要重点是完成我在上周末开始的迁移,即将所有 UI 组件迁移到最新版本的 GPUI。 以前,我们是针对较旧的快照进行构建的,并且自那时以来,GPUI 发生了一些更大的基础性变化。

我很高兴地报告,我们新的 UI 工作现在完全在最新版本的 GPUI 上运行。

当我开始愤怒地使用这个新版本的 GPUI 时,我一直与 Nathan 和 Antonio 密切合作,以在我们更接近实际使用时继续改进它。

本周还对我们构建 UI 故事的方式进行了一些更改,以改善 UI 组件的工作体验。

以前,组件的故事位于 storybook crate 中,而组件定义本身位于 ui crate 中。 这种分离意味着在这两个 crate 之间来回跳转很多次。

我们现在在每个组件的模块中都有一个单独的 stories 模块,允许我们在其相应组件旁边定义故事

// icon.rs
 
#[cfg(feature = "stories")]
pub use stories::*;
 
#[cfg(feature = "stories")]
mod stories {
    use crate::Story;
 
    #[derive(Element, Default)]
    pub struct IconStory {}
 
    impl IconStory {
        fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
            let icons = Icon::iter();
 
            Story::container(cx)
                .child(Story::title_for::<_, IconElement>(cx))
                .child(Story::label(cx, "All Icons"))
                .child(div().flex().gap_3().children(icons.map(IconElement::new)))
        }
    }
}

Nate

由于休假一周和一场让我晕倒了几天的感冒,我本周没有太多可说的,除了 gpui2ui 工作正在进行中。

我们越来越接近许多 UI 元素的视觉均等,并且在某些地方,尤其是在项目面板和协作面板等地方,已经获得了比旧 UI 更好的改进。 从共享组件构建的元素使统一 UI 和重构变得更快。

希望在接下来的几周内,我可以开始分享一些视觉效果,并谈论我们为实现更好的对比度、主题中更多的自定义、可扩展的 UI 等方面所做的改进。 (并非所有这些内容都会与新的 UI 同时发布,但启用它们的基础工作将使它们更容易完成。)

否则,我一直在我的个人项目中编写大量的 Rust 代码,以便更熟悉该语言和生态系统。 当我在 TypeScript 世界中时,我已经开始感到想回到 Rust 的冲动,这里的其他人对此幸灾乐祸 😤

Piotr

正如我在上期 Zed Weekly 条目中所承诺的那样,我本周主要致力于 Vue.js 集成。 它将在下周三(10 月 18 日)的预览版中发布。 除此之外,我还修复了 Rust 异步函数的补全功能。

Conrad

致力于 Zed 的协作方面:我们如何让人们可以轻松地与我们合作开发 Zed 本身,并提高协作工具的质量?

我花了大量时间与 Apple 的 Entitlements 作斗争,因此,我认为我们现在可以发布 Universal Links(因此将来会有一个链接,可将您直接带到 Zed,而无需通过网站跳转)。

接下来是对频道进行公共访问:允许人们参与通话,但不能控制通话。 这里的大部分工作是定义它的行为方式,但是该实现并不像预期的那样简单,因为 Zed 当前允许权限向下级联频道树。

Max

本周,我修复了跟踪中的一些错误,这些错误是我上周在推广跟踪工作方式的过程中引入的。

我还一直在为 Zed 开发一个通知面板,以便我们可以将 @-提及 添加到 Zed 的聊天中,并且被提及的用户将有一个地方可以查看通知。

Kirill

这周对一些事情来说是一个好的结束。

  • macOS Sonoma 升级现在对 Zed 项目来说是可能的,因为修复了回溯问题(通过尝试 beta XCode 解决)和 curl 问题(最终我自己修复了 https://github.com/alexcrichton/curl-rust/issues/524)

  • 我发现并修复了一个诊断指示器错误,现在它可以根据 LSP 服务器通知正确更新。这个问题困扰我一段时间了,但花了一些时间才理解它的出现模式。讽刺的是,修复这个问题放大了 rust-analyzer 在误报诊断方面的问题,现在是尝试分离出一个孤立的例子,甚至修复语言服务器本身的好时机。

  • 最后,prettier 集成的第一个版本将随下一个预览版一起发布。它的目标是覆盖所有现有语言(因此,使用 Tailwind 和 Svelte 的插件),在协作场景中工作,从项目的 package.json 中检测 prettier 或提供默认的 prettier,以及其他一些小功能。让我们看看覆盖范围有多好。

Nathan

下周我将前往意大利与 Antonio 并肩工作。接下来的一周,整个公司将齐聚博洛尼亚参加我们的秋季峰会。我的目标是准备好新版本的 GPUI,让每个人都能一起进行过渡。

这有点模糊,但这周的亮点包括细化视图如何在其他视图中嵌套,以及将元素与在帧之间持续存在的状态相关联的能力。 GPUI 的核心前提是文档对象模型是无状态的。 我们可以添加缓存以节省能源,但我们已将框架设计为能够以最小的延迟重新渲染整个窗口。

当元素需要是有状态的时,这种无状态会带来挑战,例如在实现单击处理程序时。单击定义为鼠标在同一元素上按下和抬起,但是如果在按下鼠标时发生视图更新,我们需要记住单击了哪个元素。为了支持这一点,我们要求有状态的元素与一个标识符相关联。起初这看起来很烦人,但后来我意识到 React 要求子元素具有 ID 以实现高效的差异化。我们不需要进行差异化,因为我们是无状态的,但另一方面,我们需要任何需要状态的元素的标识符。 看起来这是一个值得的权衡。

GPUI 2 的主要剩余组件包括焦点和键盘处理、拖放、滚动、IME 和一个使用自定义逻辑来避免布局屏幕外元素的列表组件。很高兴能够从 Web 平台中提取最好的想法,但可以利用我们需要的所有低级控制来使一切都变得快速。