本周对团队来说意义重大。我们公开发布了我们的 预览频道 并关闭了一些排名靠前的功能请求。我们也在继续探索编辑器中的人工智能,并通过 Zed 推进 Zed 的开源工作。
Joseph
本周早些时候,我对通话仪表板进行了一些改进。 其中一些更改包括添加一些图表,按通话时长和通话开始时间对通话进行分类。
我一直想公开发布我们的 预览频道 已经有一段时间了,所以我写了一篇小的 博客文章,并帮助调整了一些 zed.dev 代码,以便将其发布。 我很高兴在将新功能发布到稳定频道之前,能够对它们进行更多的测试覆盖。
最后,本周我想解决一些较小的任务。 其中之一是调整应用内反馈提交机制,为用户提供反馈已发送的确认信息,同时防止任何后续尝试重新提交相同的反馈。 我觉得这很有必要,因为我们数据库中重复反馈的频率一直在增加。
Mikayla
上周,我添加了一堆功能,并且在周末,我还决定开始研究搜索和替换:D。我希望 Zed 在我们开始直播之前,所有这些闪亮的功能都能稳定下来。 本周主要关注的是稳定和调整这些功能并修复错误。
Piotr
上周,我致力于 PHP LSP 集成,并继续进行树结构查找表的工作。 它的 PR 已经提交,那边的人似乎很高兴看到这个变化(或者至少对此充满热情)。 下一周,我计划回到 Zed,并在我们的 UI 上做更多的工作。
Kirill
我继续进行终端高亮显示和使用 Cmd+hover 进行导航的工作,并且已经发布了第一个版本 - 我真的很怀念 Zed 中的这一点,现在我是一个快乐的用户。 很高兴看到人们对其中的小问题提供反馈; 希望他们的体验仍然有所改善。
这个基本实现带来的一种很大的可能性是通往外部文件拖放的路径:我们现在有处理“尝试打开这个抽象事物”的逻辑,经过测试并准备好接受文件系统路径。
在本周剩余的时间里,我主要修复了错误。 最值得注意的部分是键盘绑定及其在系统和 Zed 菜单中的显示:现在它们可以正确显示用户覆盖。
Antonio
我们开发 CRDB 非常愉快,我们设想它成为我们平台的支柱,最终将开源(在此处找到更多详细信息:https://zed.rust-lang.net.cn/blog/open-sourcing-zed-on-zed)。
最近,我们的注意力集中在探索用于操作的有向无环图 (DAG) 表示。 使用 DAG 封装操作使我们能够清楚地了解每个操作的因果历史。 这对于有效地跟踪副本和分支之间的并发性(无需版本向量)至关重要。
Conrad
我专注于改进 Vim 仿真。 本周的主要功能是搜索和相关命令:/
和 ?
,*
和 #
,n
和 N
现在都可以正常工作了。 Vim 搜索建立在 Zed 的内置搜索之上,以使其感觉流畅并与其余体验集成。 我还阅读并整理了所有我能找到的与 Vim 相关的反馈,并优先考虑了下一步的工作 – 敬请关注!
Kyle
本周,我们继续推进语义索引。 值得注意的是,Max 和我重做了我们的树结构查询引擎,用于解析嵌入的符号对象,以包括在需要时折叠嵌套对象的选项。 这大大减少了令牌数量,同时保持了大型分层上下文,加快了嵌入时间并减少了冗余搜索结果。 除此之外,我们还花了一些时间重构我们的重新索引过程,以允许更细致的重新索引作业,并在重新设计的项目搜索 UI 中添加了语义搜索作为选项。
Julia
除了查看各种崩溃之外,本周我处理的一件有趣的事情是将 ctrl-click 视为右键单击。 作为 macOS 应用程序的标准功能,我们从未注意到我们不支持它,因为团队中所有使用触控板的人都使用双指单击。 这提出了一个有趣的难题,因为 Zed 最终将成为一个跨平台应用程序; Windows 和 Linux 都没有任何类似行为的约定。 这意味着我们可能不想在应用程序代码中处理它,因为通常最好将特定于平台的问题保留在平台层中,从而允许核心应用程序代码与平台无关。 所以我进入了我们的 macOS 平台事件代码并过滤掉了按下 control 的鼠标左键按下事件。 现在,每当操作系统向我们发送一个时,我们都会用鼠标右键按下替换它,然后用鼠标右键弹起,从而允许核心应用程序代码只看到一个正常的右键单击。
Max
这周,除了和 Kyle 一起做语义搜索之外,我还处理了一个有趣的 bug,它会在 Zed 在非常大的 git 仓库中打开时出现(比如 Webkit
),在这种仓库中,git status
命令需要很长时间才能运行。在这样的仓库中,缓慢的 git status 调用导致我们的文件系统扫描(通常在每个 CPU 核心上并行运行)由于某些锁竞争而以单线程方式运行,这导致项目文件加载非常缓慢。我仍在研究应该如何以及何时检索文件的 git 状态,以避免在巨型仓库中出现这个问题。
Derek
这周,我主要与 Nathan 合作进行新的 GPUI 更新,并与 Mikayla 合作进行一些 UI 更新。我为文件图标和其他各种 UI 图标需求创建了一个初始图标集,并为其他人在开发的新搜索 UI 进行了更新,以添加更多功能。敬请期待这个 UI 在不久的将来出现在应用程序中。
Nathan
我与 Derek 合作,改进了我们的 UI 布局和样式方法,但我将大部分工程时间用于与 Antonio 合作开发 CRDB。
一个值得分享的有趣方面是我们采用的网络和消息传递方法。目前,Zed 中的协作依赖于 Protocol Buffers 来处理所有的网络消息,但是维护一个外部模式在很多方面都有点笨拙。对于 CRDB,我很想知道我们是否能找到一种纯 Rust 的方法。所以我们尝试了一个名为 serde-bare
的 crate,它是 Bare Messages 的一个实现,Bare Messages 是一种紧凑的二进制序列化格式,允许我们在 Rust 中完整定义消息类型。
我们有两种消息:一种将通过 LiveKit 数据通道 广播,以最大限度地减少与协作者共享编辑时的延迟。另一种是请求,将发送到我们的服务器以进行持久化。我们用不同的信封枚举来包装每种消息,就像这样。
// These are sent to our server
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RequestEnvelope {
PublishRepo(PublishRepo),
CloneRepo(CloneRepo),
SyncRepo(SyncRepo),
PublishOperations(PublishOperations),
}
// These are sent via LiveKit data channels.
// Currently we only implement one type of message, but this could expand.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum MessageEnvelope {
Operation(Operation),
}
在这些枚举中,我们都实现了一个 unwrap
方法,该方法返回一个带有其内容的 Box<dyn Any>
。然后,我们可以使用基于每个消息的 TypeId
的动态分发,将消息路由到适当的处理程序。为了反方向操作,每个消息都实现了 Into<RequestEnvelope>
或 Into<MessageEnvelope>
。我们可以用宏来覆盖这些。
一旦我们理顺了网络,我们就实现了同步。这是基于向量时钟的,它将根据为存储库创建的副本总数进行缩放。为每个操作发送这些信息太昂贵了,但它们对于同步非常有用,同步本质上是两个副本包含的操作集合之间的分布式集合联合。与服务器同步时,客户端发送一个向量时钟,表示它已经看到的一切。然后,服务器发回它拥有的、客户端上不存在的任何操作,以及它自己的表示服务器拥有的内容的向量时钟。然后,客户端跟进发送服务器缺少的任何内容。
解决了同步问题后,我们开始应用操作,这很有趣。每个操作都与一个父级 RevisionId
相关联,它表示应用该操作的存储库的修订版本。一个 RevisionId
包含一个或多个并发 OperationId
。为了应用操作,我们需要检索和/或构造一个与该 ID 匹配的修订版本。如果我们已经有一个与该 ID 匹配的缓存修订版本,我们可以直接使用它。如果我们没有,我们会向后遍历 DAG,找到一个代表修订 ID 中列出的所有操作的共同祖先的修订版本,我们有一个缓存的快照,然后应用操作向前重建它。
最初,我们将维护每个状态的快照,因此找到共同祖先应该非常便宜。随着时间的推移,我们将垃圾回收旧的快照,因此重建更早的状态可能会变得更加昂贵,但这无论如何都是一项粗粒度的操作。
我们认为我们有一个可用的修订重建版本,并且我们目前正在基于它实现一个编辑操作。穿越和构建写时复制 B 树的有趣时光。
感谢阅读!