Compare commits

..

132 Commits

Author SHA1 Message Date
Antonio Scandurra
bfa12d92ef Remove assistant_tooling crate
Co-Authored-By: Nathan <nathan@zed.dev>
2024-07-27 15:20:39 +02:00
Antonio Scandurra
f6b8fad275 Remove tool calling from protobuf
Co-Authored-By: Nathan <nathan@zed.dev>
2024-07-27 15:19:39 +02:00
Antonio Scandurra
14b26034d8 Add debugging info when a symbol is not found
Co-Authored-By: Nathan <nathan@zed.dev>
2024-07-27 15:03:09 +02:00
Antonio Scandurra
70e895a8c7 Fix regression that caused Anthropic custom models to error (#15329)
/cc: @bennetbo 

Release Notes:

- N/A

Co-authored-by: Nathan <nathan@zed.dev>
2024-07-27 14:45:18 +02:00
Matin Aniss
4bd935b409 gpui: Add support for animated images (#13809)
This PR adds support for animated images. The image requires a id for it
to actually animate across frames.

Currently it only has support for `GIF`, I tried adding decoding a
animated `WebP` into frames but it seems to error. This issue in the
image crate seems to document this
https://github.com/image-rs/image/issues/2263.

Not sure if this is the best way or the desired way for animated images
to work in GPUI but I would really like support for animated images.
Open to feedback.

Example Video:


https://github.com/zed-industries/zed/assets/76515905/011f790f-d070-499b-96c9-bbff141fb002



Closes https://github.com/zed-industries/zed/issues/9993

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Nathan <nathan@zed.dev>
2024-07-27 14:05:37 +02:00
Marshall Bowers
c0df1e1846 Run clippy for Windows (#15318)
This PR fixes running clippy on Windows, as it broke in #13223.

We can't run shell scripts on Windows, so we need to use something else.

Release Notes:

- N/A
2024-07-26 21:38:34 -04:00
rimuy
e9d0768e3c Suppress unused parameter warning on remote/ssh_session.rs (#15315)
This was probably an oversight from
https://github.com/zed-industries/zed/pull/15129.


![image](https://github.com/user-attachments/assets/5867e307-f581-4b40-8492-2fb80e87c18c)

Release Notes:

- N/A
2024-07-26 21:11:28 -04:00
Marshall Bowers
380a99038b live_kit_server: Re-remove protocol submodule (#15317)
This PR re-removes the `protocol` submodule from `live_kit_server`,
since it was incorrectly added back in #15313.

Release Notes:

- N/A
2024-07-26 21:10:56 -04:00
apricotbucket28
88653c4e3e linux: Respect window_min_size property (#15314)
https://github.com/zed-industries/zed/pull/13126 added the
`window_min_size` property for window creation, but it was only
implemented for macOS. This PR implements the property on Linux as well.

Release Notes:

- N/A
2024-07-26 18:02:31 -07:00
Calin Martinconi
3751f67730 fix: Typos (#15313)
Fixed typos in the code base according with output from `codespell`
tool.

Release Notes:

- N/A
2024-07-26 17:52:37 -07:00
张小白
6af385c09e windows: Fix some weird IME window panic (#15286)
Previously, we used messages greater than `WM_USER` to pass information
between `WindowsPlatform` and `WindowsWindow`. For example, to close a
window, we handled it as follows:
1. The window sends a message with `WM_USER + 2` to `WindowsPlatform`.
2. `WindowsPlatform`, upon receiving this message, casts the `lparam` to
`HWND` and closes the window.

According to Microsoft's documentation, it is safe to use values between
`WM_USER` and `0xBFFF` as messages. However, certain versions of
Microsoft's IME use `WM_USER + 2` for UNKNOWN purposes. This causes step
2 to be erroneously triggered. The IME window's `lparam` value could be
arbitrary, leading to an attempt to close an arbitrary `HWND` and
resulting in errors.

It is quite surprising that Microsoft indicates using `WM_USER + 2` is
safe, yet Microsoft itself breaks this convention. I mean, well done
Microsoft!

This PR addresses the issue by using the `wparam` with a specific random
value for validation purpose when sending the aforementioned message.
Before `WindowsPlatform` attempts to close the window, it will first
verify the `wparam` value.

Special thanks to @shenjackyuanjie for helping me on this.


Co-authored-by: shenjackyuanjie <3695888@qq.com>


Release Notes:

- Fixed weird panic when IME window is closing(#15185, #12563).

---------

Co-authored-by: shenjack <3695888@qq.com>
2024-07-26 17:40:55 -07:00
张小白
e6cd1cf22b windows: Remove Send and Sync implementation of DirectWrite (#15263)
This PR uses the `AgileReference` provided by the `windows-rs` crate to
correctly implement `Send` and `Sync` for `DirectWrite`.

Release Notes:

- N/A
2024-07-26 16:46:06 -07:00
Mikayla Maki
a1bd7a1297 Feature/fallback fonts (#15306)
Supersedes https://github.com/zed-industries/zed/pull/12090

fixes #5180
fixes #5055

See original PR for an example of the feature at work.

This PR changes the settings interface to be backwards compatible, and
adds the `ui_font_fallbacks`, `buffer_font_fallbacks`, and
`terminal.font_fallbacks` settings.

Release Notes:

- Added support for font fallbacks via three new settings:
`ui_font_fallbacks`, `buffer_font_fallbacks`, and
`terminal.font_fallbacks`.(#5180, #5055).

---------

Co-authored-by: Junkui Zhang <364772080@qq.com>
2024-07-26 16:42:21 -07:00
Conrad Irwin
3e31955b7f SSH remote ui (#15129)
Still TODO:
* [x] hide this UI unless you have some ssh projects in settings
* [x] add the "open folder" flow with the new open picker
* [ ] integrate with recent projects / workspace restoration

Release Notes:

- N/A
2024-07-26 16:45:44 -06:00
Conrad Irwin
be86852f95 Allow binding to motions in insert mode (#15308)
Release Notes:

- vim: Allow binding motions in insert mode
2024-07-26 16:33:31 -06:00
Marshall Bowers
bde02a350e settings_ui: Add line number settings controls (#15310)
This PR adds settings controls for the line numbers and relative line
numbers settings.

Release Notes:

- N/A
2024-07-26 18:31:45 -04:00
renovate[bot]
4c9311ba40 Update Rust crate palette to v0.7.6 (#15307)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [palette](https://togithub.com/Ogeon/palette) | workspace.dependencies
| patch | `0.7.5` -> `0.7.6` |

---

### Release Notes

<details>
<summary>Ogeon/palette (palette)</summary>

###
[`v0.7.6`](https://togithub.com/Ogeon/palette/blob/HEAD/CHANGELOG.md#Version-076---2024-04-28)

[Compare
Source](https://togithub.com/Ogeon/palette/compare/0.7.5...0.7.6)

- \[[#&#8203;390](https://togithub.com/Ogeon/palette/issues/390)]\[390]:
Add `From` implementations for changing `Rgb` component types between
`u8`, `f32` and `f64`.
- \[[#&#8203;342](https://togithub.com/Ogeon/palette/issues/342)]\[342]:
Implement CAM16. Closes
\[[#&#8203;199](https://togithub.com/Ogeon/palette/issues/199)]\[199].
- \[[#&#8203;386](https://togithub.com/Ogeon/palette/issues/386)]\[386]:
Fix angle conversion from `f32` to `u8`. Closes
\[[#&#8203;385](https://togithub.com/Ogeon/palette/issues/385)]\[385].
- \[[#&#8203;384](https://togithub.com/Ogeon/palette/issues/384)]\[384]:
Add traits for color schemes from traditional color theory.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 18:20:59 -04:00
Conrad Irwin
c8bc49fa18 vim: Fix count in visual indent (#15296)
Co-Authored-By: tobbe@tlundberg.com

Release Notes:

- vim: Added {count} for `>`/`<` in visual mode
2024-07-26 16:03:41 -06:00
Marshall Bowers
bcd972fbb4 Upgrade dashmap to v6 (#15305)
This PR upgrades `dashmap` to v6.0.1.

Release Notes:

- N/A
2024-07-26 17:58:37 -04:00
Marshall Bowers
e423f03ba6 Upgrade base64 to v0.22 (#15304)
This PR upgrades the `base64` dependency to v0.22.

Supersedes #15300.

Release Notes:

- N/A
2024-07-26 17:40:38 -04:00
Marshall Bowers
03ebbcbef6 live_kit_server: Replace jwt with jsonwebtoken (#15302)
This PR replaces `live_kit_server`'s usage of `jwt` with `jsonwebtoken`.

`jwt` hasn't been updated in 2 years and seems unmaintained.

`jsonwebtoken` has significantly more downloads and appears to be a
healthier crate overall.

Release Notes:

- N/A
2024-07-26 17:20:01 -04:00
Marshall Bowers
27f97ba762 settings_ui: Add font ligature settings controls (#15301)
This PR adds settings controls for changing whether ligatures are
enabled for the UI and buffer fonts.

Release Notes:

- N/A
2024-07-26 17:06:14 -04:00
Vitaly Slobodin
769ae8b101 ruby: Adjust language servers languages (#15297)
Hi. This is a small pull request that changes the "language" field to
the "languages" field
because the `language` field is deprecated.
Additionally, allow the Ruby LSP to run in `*.erb` files.

Release Notes:

- N/A
2024-07-26 15:58:50 -04:00
renovate[bot]
d27fef7b2c Update Python to v3.12.4 (#15136)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [python](https://togithub.com/containerbase/python-prebuild) |
dependencies | patch | `3.12.1` -> `3.12.4` |

---

### Release Notes

<details>
<summary>containerbase/python-prebuild (python)</summary>

###
[`v3.12.4`](https://togithub.com/containerbase/python-prebuild/releases/tag/3.12.4)

[Compare
Source](https://togithub.com/containerbase/python-prebuild/compare/3.12.3...3.12.4)

##### Bug Fixes

-   **deps:** update dependency python to v3.12.4

###
[`v3.12.3`](https://togithub.com/containerbase/python-prebuild/releases/tag/3.12.3)

[Compare
Source](https://togithub.com/containerbase/python-prebuild/compare/3.12.2...3.12.3)

##### Bug Fixes

-   **deps:** update dependency python to v3.12.3

###
[`v3.12.2`](https://togithub.com/containerbase/python-prebuild/releases/tag/3.12.2)

[Compare
Source](https://togithub.com/containerbase/python-prebuild/compare/3.12.1...3.12.2)

##### Bug Fixes

-   **deps:** update dependency python to v3.12.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 15:27:46 -04:00
renovate[bot]
f4bbbe69b4 Update Rust crate waker-fn to v1.2.0 (#15289)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [waker-fn](https://togithub.com/smol-rs/waker-fn) | dependencies |
minor | `1.1.0` -> `1.2.0` |

---

### Release Notes

<details>
<summary>smol-rs/waker-fn (waker-fn)</summary>

###
[`v1.2.0`](https://togithub.com/smol-rs/waker-fn/blob/HEAD/CHANGELOG.md#Version-120)

[Compare
Source](https://togithub.com/smol-rs/waker-fn/compare/v1.1.1...v1.2.0)

-   Add a new `portable-atomic` feature that allows for the usage of the
`portable-atomic` crate to implement `waker-fn`.
([#&#8203;10](https://togithub.com/smol-rs/waker-fn/issues/10))

###
[`v1.1.1`](https://togithub.com/smol-rs/waker-fn/blob/HEAD/CHANGELOG.md#Version-111)

[Compare
Source](https://togithub.com/smol-rs/waker-fn/compare/v1.1.0...v1.1.1)

- Reimplement using 100% safe code.
([#&#8203;7](https://togithub.com/smol-rs/waker-fn/issues/7))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-07-26 13:05:29 -04:00
Marshall Bowers
c937a2fcdd ui: Add functions for generating textual representations of key bindings (#15287)
This PR adds some helper functions in the `ui` crate that can be used to
get textural representations of keystrokes or key bindings.

Release Notes:

- N/A
2024-07-26 12:52:59 -04:00
Nate Butler
a5279cc48a Tool bar: Remove tool grouping for clarity (#15285)
This PR makes the spacing between items in the tool bar (quick action
bar) consistent vs grouped by type. The idea was to add clarity to the
types of tools, but we haven't built this system out enough for these
groupings to be recognizable. So for now, let's make the spacing
consistent.

Before:
![CleanShot 2024-07-26 at 11 58
22@2x](https://github.com/user-attachments/assets/9135fcce-fcf8-4bdf-a71b-6d6c7e5b3f63)


After:

![CleanShot 2024-07-26 at 11 57
02@2x](https://github.com/user-attachments/assets/0aceb981-01b6-466f-8d7e-97b564d014f9)

Release Notes:

- N/A
2024-07-26 12:36:49 -04:00
CharlesChen0823
4d56252bae linux: Allow skipping "Unsupported GPU" warning (#15271)
I just want using Zed in virtual machine, current implement must read
code and set env `ZED_ALLOW_EMULATED_GPU` then can work.

Release Notes:

- N/A
2024-07-26 10:26:14 -06:00
Thorsten Ball
0360cda543 tasks: Use environment variables from project (#15266)
This fixes #12125 and addresses what's described in here:

-
https://github.com/zed-industries/zed/issues/4977#issuecomment-2162094388

Before the changes in this PR, when running tasks, they inherited the
Zed process environment, but that might not be the process environment
that you'd get if you `cd` into a project directory.

We already ran into that problem with language servers and we fixed it
by loading the shell environment in the context of a projects root
directory and then passing that to the language servers when starting
them (or when looking for their binaries).

What the change here does is to add the behavior for tasks too: we use
the project-environment as the base environment with which to spawn
tasks. Everything else still works the same, except that the base env is
different.

Release Notes:

- Improved the environment-variable detection when running tasks so that
tasks can now access environment variables as if the task had been
spawned in a terminal that `cd`ed into a project directory. That means
environment variables set by `direnv`/`asdf`/`mise` and other tools are
now picked up.
([#12125](https://github.com/zed-industries/zed/issues/12125)).

Demo:


https://github.com/user-attachments/assets/8bfcc98f-0f9b-4439-b0d9-298aef1a3efe
2024-07-26 18:19:53 +02:00
Danilo Leal
5e04753d1c Add note about used context in the model selector (#15235)
When pressing <kbd>control</kbd> + <kbd>enter</kbd>, the AI-powered
inline transformation input displays an icon button and a token count,
which should show roughly the same numbers you'd see on your assistant
panel. At a first glance, though, the token count not being zero can be
confusing, where you'd wonder where that's coming from. That's because
the inline input uses whatever piece of context and/or information of
the currently selected assistant tab to suggest more accurate edits.

So, this PR introduces an informative piece of text to the
`ModelSelector` menu, on the inline transformation input, which delivers
exactly this bit of info, aimed at clarifying the connection between
these two methods of interacting with LLMs.

I've also took the opportunity to change the icon button's icon to one
that's a bit easier to see, still representing the affordance of "click
to configure something".

Release Notes:

- Add note about how inline edits consume context from the assistant
panel to clarify interaction with LLMs.

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-07-26 12:48:06 -03:00
renovate[bot]
71312e5692 Update Rust crate log to v0.4.22 (#15283)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [log](https://togithub.com/rust-lang/log) | workspace.dependencies |
patch | `0.4.21` -> `0.4.22` |

---

### Release Notes

<details>
<summary>rust-lang/log (log)</summary>

###
[`v0.4.22`](https://togithub.com/rust-lang/log/blob/HEAD/CHANGELOG.md#0422---2024-06-27)

[Compare
Source](https://togithub.com/rust-lang/log/compare/0.4.21...0.4.22)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 11:27:00 -04:00
Nate Butler
05825e9804 Add Markdown Preview Toggle (#15215)
Add a "Preview Markdown" button to the quick action bar when in a
markdown editor.

While it isn't my favorite, I went with the basic eye icon to be a bit
more generic so we can extend this control to allow opening other
previews such as SVGs like @jansol mentioned.

![CleanShot 2024-07-26 at 11 02
16@2x](https://github.com/user-attachments/assets/415963ce-d19e-432d-b8c2-37e7c6e52683)


https://github.com/user-attachments/assets/5980272c-eab9-4f69-86b6-0c593c25b525

---

Release Notes:

- Added a button to preview Markdown files in the toolbar.
`Option|Alt+Click` will open the preview to the side.
2024-07-26 11:08:42 -04:00
renovate[bot]
73d682c010 Update Rust crate oo7 to v0.3.3 (#15281)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [oo7](https://togithub.com/bilelmoussaoui/oo7) | dependencies | patch
| `0.3.0` -> `0.3.3` |

---

### Release Notes

<details>
<summary>bilelmoussaoui/oo7 (oo7)</summary>

###
[`v0.3.3`](https://togithub.com/bilelmoussaoui/oo7/releases/tag/0.3.3)

[Compare
Source](https://togithub.com/bilelmoussaoui/oo7/compare/0.3.2...0.3.3)

Bilal Elmoussaoui:

-   client/item: Force tuple usage when serializing
-   client: Use async UnixStream

###
[`v0.3.2`](https://togithub.com/bilelmoussaoui/oo7/releases/tag/0.3.2)

[Compare
Source](https://togithub.com/bilelmoussaoui/oo7/compare/0.3.1...0.3.2)

Kévin Commaille:

- [client: Fix compile issue with tracing
feature](8720514d56)
- [client: Do not create features for optional deps already behind a
feature](c4cad3dbd4)
-   Various clippy fixes

###
[`v0.3.1`](https://togithub.com/bilelmoussaoui/oo7/releases/tag/0.3.1)

[Compare
Source](https://togithub.com/bilelmoussaoui/oo7/compare/0.3.0...0.3.1)

Daiki Ueno:

- [portal: Support migration from legacy keyring
format](0e4d787372)

Dhanuka Warusadura:

- [portal: Add rekeying support for
oo7::portal::Keyring](96dd3c4292)

Felix Häcker:

- [service: Use correct signal name for
CollectionDeleted](19499a6499)
- [service: Add signals for collection
create/delete/change](c4e68b8e76)
- [collection: Add path to public
api](7effc007d4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 11:08:17 -04:00
Antonio Scandurra
e59e47fe7f Revert "Avoid buffering line content to compute indent guides" (#15282)
Reverts zed-industries/zed#15167

Release Notes:

- N/A
2024-07-26 11:05:24 -04:00
Marshall Bowers
4abf7f058e Upgrade env_logger to v0.11 (#15278)
This PR upgrades `env_logger` to v0.11.

There were some breaking changes in the style API. I followed the
[migration
guide](73bb418802/CHANGELOG.md (migration-guide))
to update the usage.

Visually there shouldn't be any changes:

### Before

<img width="1068" alt="Screenshot 2024-07-26 at 10 20 07 AM"
src="https://github.com/user-attachments/assets/9abdbba2-5a34-46df-a62b-3d6c2d9d1137">

### After

<img width="1061" alt="Screenshot 2024-07-26 at 10 37 35 AM"
src="https://github.com/user-attachments/assets/c81bc3cc-1738-43f7-ba19-4c4be058427f">

Release Notes:

- N/A
2024-07-26 10:48:07 -04:00
renovate[bot]
f980e40993 Update Rust crate semver to v1.0.23 (#15277)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [semver](https://togithub.com/dtolnay/semver) | workspace.dependencies
| patch | `1.0.18` -> `1.0.23` |

---

### Release Notes

<details>
<summary>dtolnay/semver (semver)</summary>

### [`v1.0.23`](https://togithub.com/dtolnay/semver/releases/tag/1.0.23)

[Compare
Source](https://togithub.com/dtolnay/semver/compare/1.0.22...1.0.23)

- Resolve unexpected_cfgs warning
([#&#8203;318](https://togithub.com/dtolnay/semver/issues/318))

### [`v1.0.22`](https://togithub.com/dtolnay/semver/releases/tag/1.0.22)

[Compare
Source](https://togithub.com/dtolnay/semver/compare/1.0.21...1.0.22)

-   Fix unused_imports warnings when compiled by rustc 1.78

### [`v1.0.21`](https://togithub.com/dtolnay/semver/releases/tag/1.0.21)

[Compare
Source](https://togithub.com/dtolnay/semver/compare/1.0.20...1.0.21)

- Update proc-macro2 to fix caching issue when using a rustc-wrapper
such as sccache

### [`v1.0.20`](https://togithub.com/dtolnay/semver/releases/tag/1.0.20)

[Compare
Source](https://togithub.com/dtolnay/semver/compare/1.0.19...1.0.20)

- Add a method for comparing versions by precedence
([#&#8203;305](https://togithub.com/dtolnay/semver/issues/305))

### [`v1.0.19`](https://togithub.com/dtolnay/semver/releases/tag/1.0.19)

[Compare
Source](https://togithub.com/dtolnay/semver/compare/1.0.18...1.0.19)

- Improve test coverage
([#&#8203;299](https://togithub.com/dtolnay/semver/issues/299), thanks
[@&#8203;CXWorks](https://togithub.com/CXWorks))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 10:36:41 -04:00
renovate[bot]
57b2cb6f60 Update Rust crate backtrace to v0.3.73 (#15275)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [backtrace](https://togithub.com/rust-lang/backtrace-rs) |
dependencies | patch | `0.3.69` -> `0.3.73` |
| [backtrace](https://togithub.com/rust-lang/backtrace-rs) |
dev-dependencies | patch | `0.3.69` -> `0.3.73` |

---

### Release Notes

<details>
<summary>rust-lang/backtrace-rs (backtrace)</summary>

###
[`v0.3.73`](https://togithub.com/rust-lang/backtrace-rs/releases/tag/0.3.73)

[Compare
Source](https://togithub.com/rust-lang/backtrace-rs/compare/0.3.72...0.3.73)

This basically just is bugfixes so that backtrace works on Windows 7
again.

#### What's Changed

- Fix signature of resolve_legacy for Windows 7 target by
[@&#8203;aapanfilovv](https://togithub.com/aapanfilovv) in
[https://github.com/rust-lang/backtrace-rs/pull/631](https://togithub.com/rust-lang/backtrace-rs/pull/631)
- Update some comments by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/630](https://togithub.com/rust-lang/backtrace-rs/pull/630)
- Update object to 0.36.0. by
[@&#8203;afranchuk](https://togithub.com/afranchuk) in
[https://github.com/rust-lang/backtrace-rs/pull/633](https://togithub.com/rust-lang/backtrace-rs/pull/633)

#### New Contributors

- [@&#8203;aapanfilovv](https://togithub.com/aapanfilovv) made their
first contribution in
[https://github.com/rust-lang/backtrace-rs/pull/631](https://togithub.com/rust-lang/backtrace-rs/pull/631)
- [@&#8203;afranchuk](https://togithub.com/afranchuk) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/633](https://togithub.com/rust-lang/backtrace-rs/pull/633)

**Full Changelog**:
https://github.com/rust-lang/backtrace-rs/compare/0.3.72...0.3.73

###
[`v0.3.72`](https://togithub.com/rust-lang/backtrace-rs/releases/tag/0.3.72)

[Compare
Source](https://togithub.com/rust-lang/backtrace-rs/compare/0.3.71...0.3.72)

This release removes a lot of dead code. Some feature flags that haven't
done anything in a long time are gone. If you depend on those features,
Cargo's resolver will not update you to 0.3.72.

If your code runs on Windows, or you want it to run on visionOS,
however, you should probably update to this version. It contains a
number of fixes for both OS. It also uses the latest version of a number
of dependencies.

#### What's Changed

- Revert "Use rustc from stage0 instead of stage0-sysroot (rust-lang/ba…
by [@&#8203;Nilstrieb](https://togithub.com/Nilstrieb) in
[https://github.com/rust-lang/backtrace-rs/pull/603](https://togithub.com/rust-lang/backtrace-rs/pull/603)
- Remove dead code by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/605](https://togithub.com/rust-lang/backtrace-rs/pull/605)
- Fix CI and remove rustc-serialize by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/596](https://togithub.com/rust-lang/backtrace-rs/pull/596)
- Use correct base address and update comment by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/604](https://togithub.com/rust-lang/backtrace-rs/pull/604)
- Windows AArch64: Break out of tracing when no longer making progress
by [@&#8203;dpaoliello](https://togithub.com/dpaoliello) in
[https://github.com/rust-lang/backtrace-rs/pull/610](https://togithub.com/rust-lang/backtrace-rs/pull/610)
- Remove obsolete rustc-serialize references by
[@&#8203;atouchet](https://togithub.com/atouchet) in
[https://github.com/rust-lang/backtrace-rs/pull/614](https://togithub.com/rust-lang/backtrace-rs/pull/614)
- Update `object` and `addr2line` dependencies by
[@&#8203;a1phyr](https://togithub.com/a1phyr) in
[https://github.com/rust-lang/backtrace-rs/pull/612](https://togithub.com/rust-lang/backtrace-rs/pull/612)
- Fix tests for rust 1.79 by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/621](https://togithub.com/rust-lang/backtrace-rs/pull/621)
- Remove unused `libbacktrace` and `gimli-symbolize` features by
[@&#8203;Enselic](https://togithub.com/Enselic) in
[https://github.com/rust-lang/backtrace-rs/pull/615](https://togithub.com/rust-lang/backtrace-rs/pull/615)
- remove some instances of dead_code by
[@&#8203;klensy](https://togithub.com/klensy) in
[https://github.com/rust-lang/backtrace-rs/pull/619](https://togithub.com/rust-lang/backtrace-rs/pull/619)
- Reduce panics in dbghelp by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/608](https://togithub.com/rust-lang/backtrace-rs/pull/608)
- Add Apple visionOS support by
[@&#8203;QuentinPerez](https://togithub.com/QuentinPerez) in
[https://github.com/rust-lang/backtrace-rs/pull/613](https://togithub.com/rust-lang/backtrace-rs/pull/613)
- Update cc crate to v1.0.97 by
[@&#8203;jfgoog](https://togithub.com/jfgoog) in
[https://github.com/rust-lang/backtrace-rs/pull/623](https://togithub.com/rust-lang/backtrace-rs/pull/623)
- chore: add docs for the global re-entrant lock by
[@&#8203;Gankra](https://togithub.com/Gankra) in
[https://github.com/rust-lang/backtrace-rs/pull/609](https://togithub.com/rust-lang/backtrace-rs/pull/609)
- Test with lld-compatible args by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/627](https://togithub.com/rust-lang/backtrace-rs/pull/627)
- Bump rustc-demangle version by
[@&#8203;michaelwoerister](https://togithub.com/michaelwoerister) in
[https://github.com/rust-lang/backtrace-rs/pull/624](https://togithub.com/rust-lang/backtrace-rs/pull/624)
- cleanup dead_code around cpp_demangle feature by
[@&#8203;klensy](https://togithub.com/klensy) in
[https://github.com/rust-lang/backtrace-rs/pull/622](https://togithub.com/rust-lang/backtrace-rs/pull/622)
- Cut backtrace 0.3.72 by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/628](https://togithub.com/rust-lang/backtrace-rs/pull/628)

#### New Contributors

- [@&#8203;Enselic](https://togithub.com/Enselic) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/615](https://togithub.com/rust-lang/backtrace-rs/pull/615)
- [@&#8203;QuentinPerez](https://togithub.com/QuentinPerez) made their
first contribution in
[https://github.com/rust-lang/backtrace-rs/pull/613](https://togithub.com/rust-lang/backtrace-rs/pull/613)
- [@&#8203;Gankra](https://togithub.com/Gankra) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/609](https://togithub.com/rust-lang/backtrace-rs/pull/609)

**Full Changelog**:
https://github.com/rust-lang/backtrace-rs/compare/0.3.71...0.3.72

###
[`v0.3.71`](https://togithub.com/rust-lang/backtrace-rs/releases/tag/0.3.71)

[Compare
Source](https://togithub.com/rust-lang/backtrace-rs/compare/0.3.70...0.3.71)

This is mostly CI changes, with a very mild bump to our effective cc
crate version recorded, and a small modification to a previous changeset
to allow backtrace to run at its current checked-in MSRV on Windows.
Sorry about that! We will be getting 0.3.70 yanked shortly.

#### What's Changed

- Make sgx functions exist with cfg(miri) by
[@&#8203;saethlin](https://togithub.com/saethlin) in
[https://github.com/rust-lang/backtrace-rs/pull/591](https://togithub.com/rust-lang/backtrace-rs/pull/591)
- Update version of cc crate by
[@&#8203;jfgoog](https://togithub.com/jfgoog) in
[https://github.com/rust-lang/backtrace-rs/pull/592](https://togithub.com/rust-lang/backtrace-rs/pull/592)
- Pull back MSRV on Windows by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/598](https://togithub.com/rust-lang/backtrace-rs/pull/598)
- Force frame pointers on all i686 tests by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/601](https://togithub.com/rust-lang/backtrace-rs/pull/601)
- Use rustc from stage0 instead of stage0-sysroot by
[@&#8203;Nilstrieb](https://togithub.com/Nilstrieb) in
[https://github.com/rust-lang/backtrace-rs/pull/602](https://togithub.com/rust-lang/backtrace-rs/pull/602)
- Cut backtrace 0.3.71 by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/599](https://togithub.com/rust-lang/backtrace-rs/pull/599)

#### New Contributors

- [@&#8203;jfgoog](https://togithub.com/jfgoog) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/592](https://togithub.com/rust-lang/backtrace-rs/pull/592)
- [@&#8203;Nilstrieb](https://togithub.com/Nilstrieb) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/602](https://togithub.com/rust-lang/backtrace-rs/pull/602)

**Full Changelog**:
https://github.com/rust-lang/backtrace-rs/compare/0.3.70...0.3.71

###
[`v0.3.70`](https://togithub.com/rust-lang/backtrace-rs/releases/tag/0.3.70)

[Compare
Source](https://togithub.com/rust-lang/backtrace-rs/compare/0.3.69...0.3.70)

#### New API

- A `BacktraceFrame` can now have `resolve(&mut self)` called on it
thanks to [@&#8203;fraillt](https://togithub.com/fraillt) in
[https://github.com/rust-lang/backtrace-rs/pull/526](https://togithub.com/rust-lang/backtrace-rs/pull/526)

#### Platform Support

We added support for new platforms in this release!

- Thanks to [@&#8203;bzEq](https://togithub.com/bzEq) in
[https://github.com/rust-lang/backtrace-rs/pull/508](https://togithub.com/rust-lang/backtrace-rs/pull/508)
we now have AIX support!
- Thanks to [@&#8203;sthibaul](https://togithub.com/sthibaul) in
[https://github.com/rust-lang/backtrace-rs/pull/567](https://togithub.com/rust-lang/backtrace-rs/pull/567)
we now have GNU/Hurd support!
- Thanks to [@&#8203;dpaoliello](https://togithub.com/dpaoliello) in
[https://github.com/rust-lang/backtrace-rs/pull/587](https://togithub.com/rust-lang/backtrace-rs/pull/587)
we now support "emulation-compatible" AArch64 Windows (aka arm64ec)

##### Windows

- Rewrite msvc backtrace support to be much faster on 64-bit platforms
by [@&#8203;wesleywiser](https://togithub.com/wesleywiser) in
[https://github.com/rust-lang/backtrace-rs/pull/569](https://togithub.com/rust-lang/backtrace-rs/pull/569)
- Fix i686-pc-windows-gnu missing dbghelp module by
[@&#8203;wesleywiser](https://togithub.com/wesleywiser) in
[https://github.com/rust-lang/backtrace-rs/pull/571](https://togithub.com/rust-lang/backtrace-rs/pull/571)
- Fix build errors on `thumbv7a-*-windows-msvc` targets by
[@&#8203;kleisauke](https://togithub.com/kleisauke) in
[https://github.com/rust-lang/backtrace-rs/pull/573](https://togithub.com/rust-lang/backtrace-rs/pull/573)
- Fix panic in backtrace symbolication on win7 by
[@&#8203;roblabla](https://togithub.com/roblabla) in
[https://github.com/rust-lang/backtrace-rs/pull/578](https://togithub.com/rust-lang/backtrace-rs/pull/578)
- remove few unused windows ffi fn by
[@&#8203;klensy](https://togithub.com/klensy) in
[https://github.com/rust-lang/backtrace-rs/pull/576](https://togithub.com/rust-lang/backtrace-rs/pull/576)
- Make dbghelp look for PDBs next to their exe/dll. by
[@&#8203;michaelwoerister](https://togithub.com/michaelwoerister) in
[https://github.com/rust-lang/backtrace-rs/pull/584](https://togithub.com/rust-lang/backtrace-rs/pull/584)
- Revert 32-bit dbghelp to a version WINE (presumably) likes by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/588](https://togithub.com/rust-lang/backtrace-rs/pull/588)
- Update for Win10+ by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/589](https://togithub.com/rust-lang/backtrace-rs/pull/589)

##### SGX

Thanks to

- Adjust frame IP in SGX relative to image base by
[@&#8203;mzohreva](https://togithub.com/mzohreva) in
[https://github.com/rust-lang/backtrace-rs/pull/566](https://togithub.com/rust-lang/backtrace-rs/pull/566)

#### Internals

We did a bunch more work on our CI and internal cleanups

- Modularise CI workflow and validate outputs for binary size checks. by
[@&#8203;detly](https://togithub.com/detly) in
[https://github.com/rust-lang/backtrace-rs/pull/549](https://togithub.com/rust-lang/backtrace-rs/pull/549)
- Commit Cargo.lock by [@&#8203;bjorn3](https://togithub.com/bjorn3) in
[https://github.com/rust-lang/backtrace-rs/pull/562](https://togithub.com/rust-lang/backtrace-rs/pull/562)
- Enable calling build.rs externally v2 by
[@&#8203;pitaj](https://togithub.com/pitaj) in
[https://github.com/rust-lang/backtrace-rs/pull/568](https://togithub.com/rust-lang/backtrace-rs/pull/568)
- Upgrade to 2021 ed and inline panics by
[@&#8203;nyurik](https://togithub.com/nyurik) in
[https://github.com/rust-lang/backtrace-rs/pull/538](https://togithub.com/rust-lang/backtrace-rs/pull/538)
- Fix deny(unused) of an unused import with SGX + Miri by
[@&#8203;saethlin](https://togithub.com/saethlin) in
[https://github.com/rust-lang/backtrace-rs/pull/581](https://togithub.com/rust-lang/backtrace-rs/pull/581)
- Fix unused_imports warning on latest nightly by
[@&#8203;ChrisDenton](https://togithub.com/ChrisDenton) in
[https://github.com/rust-lang/backtrace-rs/pull/575](https://togithub.com/rust-lang/backtrace-rs/pull/575)
- Fix CI by [@&#8203;saethlin](https://togithub.com/saethlin) in
[https://github.com/rust-lang/backtrace-rs/pull/582](https://togithub.com/rust-lang/backtrace-rs/pull/582)
- Use `addr_of!` by
[@&#8203;GrigorenkoPV](https://togithub.com/GrigorenkoPV) in
[https://github.com/rust-lang/backtrace-rs/pull/585](https://togithub.com/rust-lang/backtrace-rs/pull/585)
- Write down MSRV policy by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/rust-lang/backtrace-rs/pull/561](https://togithub.com/rust-lang/backtrace-rs/pull/561)
- Apply clippy::uninlined_format_args fixes by
[@&#8203;nyurik](https://togithub.com/nyurik) in
[https://github.com/rust-lang/backtrace-rs/pull/486](https://togithub.com/rust-lang/backtrace-rs/pull/486)
- ignore clippy lints in `symbolize/gimli/stash.rs` by
[@&#8203;onur-ozkan](https://togithub.com/onur-ozkan) in
[https://github.com/rust-lang/backtrace-rs/pull/586](https://togithub.com/rust-lang/backtrace-rs/pull/586)

#### New Contributors

- [@&#8203;nyurik](https://togithub.com/nyurik) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/538](https://togithub.com/rust-lang/backtrace-rs/pull/538)
- [@&#8203;bzEq](https://togithub.com/bzEq) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/508](https://togithub.com/rust-lang/backtrace-rs/pull/508)
- [@&#8203;bjorn3](https://togithub.com/bjorn3) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/562](https://togithub.com/rust-lang/backtrace-rs/pull/562)
- [@&#8203;sthibaul](https://togithub.com/sthibaul) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/567](https://togithub.com/rust-lang/backtrace-rs/pull/567)
- [@&#8203;mzohreva](https://togithub.com/mzohreva) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/566](https://togithub.com/rust-lang/backtrace-rs/pull/566)
- [@&#8203;wesleywiser](https://togithub.com/wesleywiser) made their
first contribution in
[https://github.com/rust-lang/backtrace-rs/pull/569](https://togithub.com/rust-lang/backtrace-rs/pull/569)
- [@&#8203;kleisauke](https://togithub.com/kleisauke) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/573](https://togithub.com/rust-lang/backtrace-rs/pull/573)
- [@&#8203;roblabla](https://togithub.com/roblabla) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/578](https://togithub.com/rust-lang/backtrace-rs/pull/578)
- [@&#8203;michaelwoerister](https://togithub.com/michaelwoerister) made
their first contribution in
[https://github.com/rust-lang/backtrace-rs/pull/584](https://togithub.com/rust-lang/backtrace-rs/pull/584)
- [@&#8203;dpaoliello](https://togithub.com/dpaoliello) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/587](https://togithub.com/rust-lang/backtrace-rs/pull/587)
- [@&#8203;GrigorenkoPV](https://togithub.com/GrigorenkoPV) made their
first contribution in
[https://github.com/rust-lang/backtrace-rs/pull/585](https://togithub.com/rust-lang/backtrace-rs/pull/585)
- [@&#8203;fraillt](https://togithub.com/fraillt) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/526](https://togithub.com/rust-lang/backtrace-rs/pull/526)
- [@&#8203;onur-ozkan](https://togithub.com/onur-ozkan) made their first
contribution in
[https://github.com/rust-lang/backtrace-rs/pull/586](https://togithub.com/rust-lang/backtrace-rs/pull/586)

**Full Changelog**:
https://github.com/rust-lang/backtrace-rs/compare/0.3.69...0.3.70

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 09:43:39 -04:00
renovate[bot]
af014a2530 Update Rust crate cargo_toml to v0.20.4 (#15276)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [cargo_toml](https://lib.rs/cargo_toml)
([source](https://gitlab.com/lib.rs/cargo_toml)) |
workspace.dependencies | patch | `0.20.2` -> `0.20.4` |

---

### Release Notes

<details>
<summary>lib.rs/cargo_toml (cargo_toml)</summary>

###
[`v0.20.4`](https://gitlab.com/lib.rs/cargo_toml/compare/v0.20.3...v0.20.4)

[Compare
Source](https://gitlab.com/lib.rs/cargo_toml/compare/v0.20.3...v0.20.4)

###
[`v0.20.3`](https://gitlab.com/lib.rs/cargo_toml/compare/v0.20.2...v0.20.3)

[Compare
Source](https://gitlab.com/lib.rs/cargo_toml/compare/v0.20.2...v0.20.3)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 09:40:57 -04:00
Kirill Bulatov
243fb3562c Auto fold directories in the project panel by default (#15273) 2024-07-26 15:26:20 +03:00
Kirill Bulatov
e830865eb1 Return an empty measurement instead of panicking (#15269)
Follow-up of https://github.com/zed-industries/zed/pull/15256

Returns zero size for no items to render.

Incorrect worktree state made the uniform list to have 0 items to
render, so
```Rust
let mut items = (self.render_items)(item_ix..item_ix + 1, cx);
let mut item_to_measure = items.pop().unwrap();
```
panicked as the first line returned an empty array despite a
single-element range provided.


Release Notes:

- N/A
2024-07-26 14:21:09 +03:00
CharlesChen0823
7aa6f4788d regression: Fix a panic when removing git-containing worktree from the project panel (#15256)
Follow-up of #14989

Opening a project with git metadata and clicking "Remove from Project" will panic:
![image](https://github.com/user-attachments/assets/ba00dc55-d299-4edc-9a1f-01e92f0dd9ca)

Release Notes:

- N/A
2024-07-26 14:20:59 +03:00
Thorsten Ball
18daf17d0e refactoring: Use helper instead of adjusting selection manually (#15262)
I added `newest_adjusted` recently and now just bumped into the old code
that didn't use it.

Release Notes:

- N/A
2024-07-26 11:12:33 +02:00
Joseph T. Lyons
856d9632e4 Add repl events (#15259)
Release Notes:

- N/A

---------

Co-authored-by: Kyle Kelley <rgbkrk@gmail.com>
2024-07-26 03:31:41 -04:00
Marshall Bowers
745d2e4d3b collab: Extract contributor endpoints to their own module (#15251)
This PR extracts the contributor endpoints to their own module for
organizational purposes.

Release Notes:

- N/A
2024-07-25 23:02:32 -04:00
Marshall Bowers
50dbab0747 collab: Add renovate[bot] to the GET /contributor endpoint (#15250)
This PR adds the `renovate[bot]` user to the `GET /contributor` endpoint
so that it passes the CLA check.

I patched this temporarily by adding a case into the `zed.dev` endpoint
the fronts this one, but I think long-term it will be better for collab
to be the source of truth.

Release Notes:

- N/A
2024-07-25 22:52:59 -04:00
renovate[bot]
70c22cbdd6 Update Rust crate indoc to v2 (#15247)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [indoc](https://togithub.com/dtolnay/indoc) | workspace.dependencies |
major | `1` -> `2` |

---

### Release Notes

<details>
<summary>dtolnay/indoc (indoc)</summary>

### [`v2.0.5`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.5)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/2.0.4...2.0.5)

- Documentation improvements
([#&#8203;62](https://togithub.com/dtolnay/indoc/issues/62), thanks
[@&#8203;ilyagr](https://togithub.com/ilyagr))

### [`v2.0.4`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.4)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/2.0.3...2.0.4)

- Fix handling of \r\n ending on first line
([#&#8203;61](https://togithub.com/dtolnay/indoc/issues/61), thanks
[@&#8203;PizzasBear](https://togithub.com/PizzasBear))

### [`v2.0.3`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.3)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/2.0.2...2.0.3)

-   Documentation improvements

### [`v2.0.2`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.2)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/2.0.1...2.0.2)

-   Add `no-alloc` category to crates.io metadata

### [`v2.0.1`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.1)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/2.0.0...2.0.1)

-   Set html_root_url attribute

### [`v2.0.0`](https://togithub.com/dtolnay/indoc/releases/tag/2.0.0)

[Compare
Source](https://togithub.com/dtolnay/indoc/compare/1.0.9...2.0.0)

- Change handling of final newline at zero levels of indentation
([#&#8203;55](https://togithub.com/dtolnay/indoc/issues/55))
- Add [`concatdoc!`](https://docs.rs/indoc/2/indoc/macro.concatdoc.html)
macro ([#&#8203;56](https://togithub.com/dtolnay/indoc/issues/56))
-   Raise oldest supported rustc to 1.56

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 21:59:17 -04:00
Marshall Bowers
9621005851 Organize workspace Cargo.toml (#15244)
This PR does a bit of organization of the workspace `Cargo.toml`.

Release Notes:

- N/A
2024-07-25 21:52:53 -04:00
Marshall Bowers
05003ed4c5 Hoist strum to workspace level (#15243)
This PR hoists `strum` up to a workspace dependency.

Release Notes:

- N/A
2024-07-25 21:30:48 -04:00
renovate[bot]
2c610c0e57 Update Rust crate ctor to v0.2.8 (#15242)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ctor](https://togithub.com/mmastrac/rust-ctor) |
workspace.dependencies | patch | `0.2.6` -> `0.2.8` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 21:26:51 -04:00
Marshall Bowers
479ffbbd51 ui: Make Label respect the ui_font_weight setting (#15241)
This PR makes the `Label` component respect the `ui_font_weight`
setting, by default.

An explicit font weight can still be set via the `weight` method, which
will override the `ui_font_weight` for that `Label`.

<img width="1566" alt="Screenshot 2024-07-25 at 8 55 16 PM"
src="https://github.com/user-attachments/assets/2751e29c-c76e-4685-8564-604b3b77f603">

Release Notes:

- Updated UI labels to respect the `ui_font_weight` setting
([#15234](https://github.com/zed-industries/zed/issues/15234)).
2024-07-25 21:08:28 -04:00
Marshall Bowers
fe23504eba uiua: Upgrade zed_extension_api to v0.0.6 (#15240)
This PR upgrades the Uiua extension to use v0.0.6 of the
`zed_extension_api`.

Release Notes:

- N/A
2024-07-25 20:43:15 -04:00
Marshall Bowers
95d82f88de ui: Make custom rows in ContextMenus use a normal cursor (#15239)
This PR makes custom rows in `ContextMenu`s use a regular cursor instead
of a pointer.

Even though custom rows were marked as not selectable, we would still
pass a click handler to them, causing the `ListItem` to show a pointer
cursor.

Release Notes:

- N/A
2024-07-25 20:16:53 -04:00
Peter Tripp
4000b0a02c Restore linux ctrl-d functionality (#15238)
- Restore `ctrl-d` functionality accidentally removed
- Remove duplicate `ctrl-d` keymap in `Editor` context (dead)
2024-07-25 20:11:47 -04:00
Marshall Bowers
02c43a5bf2 Add missing workspace lints (#15237)
This PR adds the missing workspace lint configuration for the following
crates that were missing it:

- `google_ai`
- `open_ai`
- `tab_switcher`

Release Notes:

- N/A
2024-07-25 19:52:24 -04:00
Marshall Bowers
f2060ccbe0 xtask: Add command for checking packages conform to certain standards (#15236)
This PR adds a new `xtask` command for checking that packages conform to
certain standards.

Still a work-in-progress, but right now it checks:

- If `[lints] workspace = true` is set
- If packages are using non-workspace dependencies

Release Notes:

- N/A
2024-07-25 19:20:08 -04:00
Kyle Kelley
13693ff80f docs: Embed video directly, copying formatting from blog (#15229)
Quick doc fix for formatting and display. 


![image](https://github.com/user-attachments/assets/5f869516-74d0-417a-bbeb-4b65f1961b12)

Release Notes:

- N/A
2024-07-25 16:05:04 -07:00
Piotr Osiewicz
ec5886a078 rust: Add static items to the outline (#15225)
Fixes #15208
Release Notes:

- Outline panel for Rust files now includes static items.
2024-07-26 00:52:42 +02:00
Kirill Bulatov
10c9e337cf Fix more gutter close button alignment issues (#15233)
Follow-up of https://github.com/zed-industries/zed/pull/15178

* shows proper cursor on hovering a block that's over a git hunk
* show gutter buttons better when git hunks are on the same line
* show deleted hunks' gutter buttons better when git blame info is shown
in the gutter

Release Notes:

- N/A
2024-07-26 01:42:25 +03:00
Marshall Bowers
1da6a12bb4 Upgrade scrypt to v0.11 (#15228)
This PR upgrades `scrypt` to v0.11.

There were some API changes that impacted our usage just in the tests.

Supersedes #15224.

Release Notes:

- N/A
2024-07-25 17:45:24 -04:00
Kyle Kelley
cc1d3f0a35 docs: Update REPL docs with images, cell mode, and kernel debugging (#15226)
Just a few doc tweaks.

Release Notes:

- N/A
2024-07-25 14:26:14 -07:00
renovate[bot]
22118f15e9 Update Rust crate sha2 to v0.10.8 (#15223)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [sha2](https://togithub.com/RustCrypto/hashes) |
workspace.dependencies | patch | `0.10.7` -> `0.10.8` |

---

### Release Notes

<details>
<summary>RustCrypto/hashes (sha2)</summary>

###
[`v0.10.8`](https://togithub.com/RustCrypto/hashes/compare/sha2-v0.10.7...sha2-v0.10.8)

[Compare
Source](https://togithub.com/RustCrypto/hashes/compare/sha2-v0.10.7...sha2-v0.10.8)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 17:21:24 -04:00
Piotr Osiewicz
0d5de88c4b chore: Bump Rust version to 1.80 (#15186)
Release Notes:

- N/A
2024-07-25 22:48:42 +02:00
Marshall Bowers
f291677d40 Upgrade async-tungstenite to v0.23 (#15220)
This PR upgrades `async-tungstenite` to v0.23.

This is so we can get the CVE fix in `tungstenite` v0.20.1.

Now that #15219 is done, upgrading to v0.23 no longer breaks
authentication with collab.

Release Notes:

- N/A
2024-07-25 16:11:01 -04:00
Marshall Bowers
9d736fe80c Upgrade async-tungstenite to v17 and update usage accordingly (#15219)
This PR upgrades `async-tungstenite` to v17.0.3.

We previously attempted upgrading `async-tungstenite` in #15039, but
broke authentication with collab in the process.

Upon further investigation, I determined that the root cause is due to
this change in `tungstenite` v0.17.0:

> Overhaul of the client's request generation process. Now the users are
able to pass the constructed `http::Request` "as is" to
`tungstenite-rs`, letting the library to check the correctness of the
request and specifying their own headers (including its own key if
necessary). No changes for those ones who used the client in a normal
way by connecting using a URL/URI (most common use-case).

We _were_ relying on passing an `http::Request` directly to
`tungstenite`, meaning we did not benefit from the changes to the common
path (of passing a URL/URI).

This meant that—due to changes in `tungstenite`—we were now missing the
`Sec-WebSocket-Key` header that `tungstenite` would otherwise set for
us.

Since we were only passing a custom `http::Request` to set headers, our
approach has been adjusted to construct the initial WebSocket request
using `tungstenite`'s `IntoClientRequest::into_client_request` and then
modifying the request to set our additional desired headers.

Release Notes:

- N/A
2024-07-25 15:53:22 -04:00
张小白
f3ad754396 linux: Fix wrong names reported by all_font_names (#14865)
The names suggested by `buffer_font_family` are reported by
`all_font_names`. Therefore, `all_font_names` should report family names
rather than postscript names.

close #14854 

Release Notes:

- N/A
2024-07-25 11:53:22 -07:00
Piotr Osiewicz
86456ce379 chore: Fix clippy violations from Cargo.toml (#15216)
/cc @maxdeviant 
Release Notes:

- N/A
2024-07-25 20:22:01 +02:00
Marshall Bowers
d755d29577 extension: Upgrade wasmtime to v21 (#15210)
This PR upgrades the version of `wasmtime` and `wasmtime-wasi` in use to
v21.0.1.

We have to skip v20 because Tree-sitter also skipped it.

Here are the changes that had to be made:

### v19 -> v20

After upgrading the `wasmtime` packages to v20, I also had to run `cargo
update -p mach2` to pull in
[v0.4.2](https://github.com/JohnTitor/mach2/releases/tag/0.4.2) to fix
some compile errors.

There were a few minor API changes in `wasmtime-wasi` from
https://github.com/bytecodealliance/wasmtime/pull/8228 that we needed to
account for.

### v20 -> v21

Since there isn't a Tree-sitter version that depends on `wasmtime@v20`,
we're jumping straight to v21.

The published version of Tree-sitter (v0.22.6) still depends on
`wasmtime@v19`, but there was a commit
(7f4a57817d)
later that month that upgrades the `wasmtime` dependency to v21.

We're patching Tree-sitter to that commit so we can get the new
`wasmtime` version.

The main change in v21 is that imports generated by `bindgen!` are no
longer automatically trapped
(https://github.com/bytecodealliance/wasmtime/pull/8310), so we need to
add `trappable_imports: true` to our `bindgen!` calls.

Release Notes:

- N/A
2024-07-25 13:56:40 -04:00
Nathaniel
ab3c9f0678 windows: Allow horizontal scroll with shift + scroll (#14147)
Release Notes:

- Horizontally scroll when holding down the Shift key and using the
scroll wheel


https://github.com/zed-industries/zed/assets/95680272/e6480f9c-0f6a-4f47-b700-a3657a75716f
2024-07-25 10:44:35 -07:00
张小白
201db23b58 windows: Fix titlebar rendering on Windows 10 (#14656)
As we discussed in #14190, we agreed to open a new PR.

Release Notes:

- N/A
2024-07-25 10:43:25 -07:00
张小白
beb8fbdf7f windows: Remove unnecessary Send and Sync implementations (#14659)
After a update to `windows-rs 0.57`, these two implementations are no
longer needed.

Release Notes:

- N/A
2024-07-25 10:42:36 -07:00
张小白
d2501e8886 windows: Bump windows-rs version (#14719)
Release Notes:

- N/A
2024-07-25 10:41:59 -07:00
张小白
82d6ad4616 Make CosmicTextSystem Linux-only (#14728)
Since `WindowsDispatcher` requires a minimum Windows version of Windows
10 Fall Creators Update (10.0.16299), and the `alacritty_terminal`
dependency relies on conPTY, an API introduced in the same version,
additionally, `DirectWriteTextSystem` also relies on Windows 10 Fall
Creators Update (10.0.16299), so it seems reasonable to make
`CosmicTextSystem` Linux-only. And we can use `DirectWriteTextSystem` on
the Windows platform exclusively. I hope this approach makes sense.

Release Notes:

- N/A
2024-07-25 10:40:49 -07:00
张小白
a60b3b9389 windows: Stop beeping (#14872)
Close #14857 

Release Notes:

- N/A
2024-07-25 10:26:36 -07:00
Fernando Tagawa
06863144c6 x11: Add keyboard layout hot plugging (#15059)
Now it is possible to change keyboard layouts with `setxkbmap` without
having to restart zed.
 
Release Notes:

- x11: Support for keyboard layout hot plugging.
2024-07-25 10:25:34 -07:00
Harsh Narayan Jha
b7c6f3e98e linux: Update TryExec value in desktop file (#15149)
Release Notes:

- Fixed ([#15148](https://github.com/zed-industries/zed/issues/15148)).
2024-07-25 10:16:23 -06:00
Thorsten Ball
7146087b44 zed: Mark restored buffers as conflicted if file changed on disk between store & restore (#15207)
Previously, we've only marked restored buffers as dirty. This PR changes
that behavior in case the buffer has been associated with a file and
that file has changed on disk since the last time Zed stored its
contents.

Example timeline:

1. User edits file in Zed, buffer is dirty
2. User quites Zed with `cmd-q`
3. User changes file on disk: `echo foobar >> file.txt` or `git checkout
file.txt`
4. User starts Zed
5. File/buffer are now marked as having a conflict (yellow icon)

Release Notes:

- Unsaved files that are restored when Zed starts are now marked as
having a conflict if they have been changed on disk since the last time
they were stored.

Demo:



https://github.com/user-attachments/assets/6098b485-b325-49b7-b694-fd2fc60cce64
2024-07-25 18:04:47 +02:00
Marshall Bowers
6d3eaa055f renovate: Fix wasmtime package prefix 2024-07-25 11:45:14 -04:00
Marshall Bowers
f31c55a76f zig: Bump to v0.1.5 (#15203)
This PR bumps the Zig extension to v0.1.5.

Changes:

- #15197

Release Notes:

- N/A
2024-07-25 11:36:50 -04:00
Marshall Bowers
97750529fe renovate: Fix selector for wasmtime group (#15202)
This PR fixes the package name selector for the `wasmtime` group.

Release Notes:

- N/A
2024-07-25 11:30:31 -04:00
Uberlicious
cd9dd5ccf7 zig: Add Windows support (#15197)
Release Notes:

- N/A

Currently Windows environments do not have a `shell_env`. This causes
the Zig extension to error when trying to call `worktree.shell_env()`
since extensions api isn't yet on `0.0.7` and thus not using wasm-host
`0.0.7` we need to only call for the shell env only on non-windows
systems. 0.0.7 and onward at the moment return a Result from
`shell_env()`. The binary path is also slightly different on windows.

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-07-25 11:30:02 -04:00
Marshall Bowers
3ce864e69e renovate: Group wasmtime updates (#15199)
This PR updates the Renovate config to group `wasmtime` crates together
(e.g., `wasmtime` and `wasmtime-wasi`).

Release Notes:

- N/A
2024-07-25 11:21:51 -04:00
Marshall Bowers
9eeb564c5c danger: Upgrade danger to v12 (#15194)
This PR upgrades `danger` to v12.

Release Notes:

- N/A
2024-07-25 11:07:04 -04:00
Conrad Irwin
847bd35bd9 vim remap 2 (#15193)
Release Notes:

- N/A
2024-07-25 09:00:53 -06:00
renovate[bot]
b8e5ddf456 Update actions/checkout action to v4 (#15189)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://togithub.com/actions/checkout) | action |
major | `v2` -> `v4` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v4`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v417)

[Compare Source](https://togithub.com/actions/checkout/compare/v3...v4)

- Bump the minor-npm-dependencies group across 1 directory with 4
updates by [@&#8203;dependabot](https://togithub.com/dependabot) in
[https://github.com/actions/checkout/pull/1739](https://togithub.com/actions/checkout/pull/1739)
- Bump actions/checkout from 3 to 4 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[https://github.com/actions/checkout/pull/1697](https://togithub.com/actions/checkout/pull/1697)
- Check out other refs/\* by commit by
[@&#8203;orhantoy](https://togithub.com/orhantoy) in
[https://github.com/actions/checkout/pull/1774](https://togithub.com/actions/checkout/pull/1774)
- Pin actions/checkout's own workflows to a known, good, stable version.
by [@&#8203;jww3](https://togithub.com/jww3) in
[https://github.com/actions/checkout/pull/1776](https://togithub.com/actions/checkout/pull/1776)

###
[`v3`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v360)

[Compare Source](https://togithub.com/actions/checkout/compare/v2...v3)

- [Fix: Mark test scripts with Bash'isms to be run via
Bash](https://togithub.com/actions/checkout/pull/1377)
- [Add option to fetch tags even if fetch-depth >
0](https://togithub.com/actions/checkout/pull/579)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 09:48:15 -04:00
Peter Tripp
6998c03c59 Document git permalinks (GitHub, Gitlab, Bitbucket, SourceHut, Codeberg, etc) (#15113)
- Docs: Added "Copy Permalink to Line" and "Open Permalink to Line"
2024-07-25 09:39:57 -04:00
Antonio Scandurra
8631180e43 Avoid buffering line content to compute indent guides (#15167)
Release Notes:

- Improved performance when computing indent guides for buffers with
extremely long lines.

---------

Co-authored-by: Nathan <nathan@zed.dev>
Co-authored-by: Bennet <bennet@zed.dev>
Co-authored-by: Thorsten <thorsten@zed.dev>
2024-07-25 15:21:50 +02:00
renovate[bot]
cd9a42e8da Pin dependencies (#15188)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[2428392/gh-truncate-string-action](https://togithub.com/2428392/gh-truncate-string-action)
| action | pinDigest | -> `67b1b81` |
| [actions/checkout](https://togithub.com/actions/checkout) | action |
pinDigest | -> `692973e` |
| [actions/checkout](https://togithub.com/actions/checkout) | action |
pinDigest | -> `ee0669b` |
| [actions/setup-node](https://togithub.com/actions/setup-node) | action
| pinDigest | -> `1e60f62` |
| [actions/setup-python](https://togithub.com/actions/setup-python) |
action | pinDigest | -> `39cd149` |
|
[actions/upload-artifact](https://togithub.com/actions/upload-artifact)
| action | pinDigest | -> `0b2256b` |
|
[cloudflare/wrangler-action](https://togithub.com/cloudflare/wrangler-action)
| action | pinDigest | -> `f84a562` |
|
[dcarbone/install-jq-action](https://togithub.com/dcarbone/install-jq-action)
| action | pinDigest | -> `8867ddb` |
|
[peaceiris/actions-mdbook](https://togithub.com/peaceiris/actions-mdbook)
| action | pinDigest | -> `ee69d23` |
| [rui314/setup-mold](https://togithub.com/rui314/setup-mold) | action |
pinDigest | -> `2e332a0` |
|
[softprops/action-gh-release](https://togithub.com/softprops/action-gh-release)
| action | pinDigest | -> `de2c0eb` |
| [swatinem/rust-cache](https://togithub.com/swatinem/rust-cache) |
action | pinDigest | -> `23bce25` |
|
[tsickert/discord-webhook](https://togithub.com/tsickert/discord-webhook)
| action | pinDigest | -> `c840d45` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 09:19:05 -04:00
Marshall Bowers
3246a932ca renovate: Pin GitHub Action versions with SHAs (#15184)
This PR updates the Renovate config to pin all GitHub Action versions to
SHAs.

From the Renovate docs:

> The [GitHub Docs, using third-party
actions](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions)
recommend that you pin third-party GitHub Actions to a full-length
commit SHA.
>
> We recommend pinning all Actions. That's why the
helpers:pinGitHubActionDigests preset pins all GitHub Actions.
>
> For an in-depth explanation why you should pin your Github Actions,
read the [Palo Alto Networks blog post about the GitHub Actions
worm](https://www.paloaltonetworks.com/blog/prisma-cloud/github-actions-worm-dependencies/).

Release Notes:

- N/A
2024-07-25 09:02:48 -04:00
Marshall Bowers
8ba392bba6 purescript: Upgrade zed_extension_api to v0.0.6 (#15181)
This PR upgrades the PureScript extension to use v0.0.6 of the
`zed_extension_api`.

Release Notes:

- N/A
2024-07-25 08:55:16 -04:00
Kirill Bulatov
856a8ef5e8 Layout gutter hunk diff close button (X) better (#15178)
Closes https://github.com/zed-industries/zed/issues/15164

* Deleted hunk
Before:

![before_top](https://github.com/user-attachments/assets/27c72ee5-719f-4787-b222-4f597840936a)

After:

![after_top](https://github.com/user-attachments/assets/58095b21-698d-4778-8412-b680d5253e2c)

* Modified hunk
Before:

![before_down](https://github.com/user-attachments/assets/3fffb73b-7101-493c-b63b-15c3ccaf5362)

After:

![after_down](https://github.com/user-attachments/assets/f07a05ed-1260-4e2a-9388-c9cb93020d78)

* Added hunk
Before:

![before_mid](https://github.com/user-attachments/assets/0dd3f0f9-51e8-449a-bdd7-4c3ba5cd7791)

After:

![after_mid](https://github.com/user-attachments/assets/92f749bd-2d95-4650-8334-1d5c38c6aeb6)

Release Notes:

- N/A
2024-07-25 15:50:57 +03:00
renovate[bot]
6dd9ce1376 Update Rust crate smallvec to v1.13.2 (#15179)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [smallvec](https://togithub.com/servo/rust-smallvec) |
workspace.dependencies | minor | `1.11.1` -> `1.13.2` |

---

### Release Notes

<details>
<summary>servo/rust-smallvec (smallvec)</summary>

###
[`v1.13.2`](https://togithub.com/servo/rust-smallvec/releases/tag/v1.13.2)

[Compare
Source](https://togithub.com/servo/rust-smallvec/compare/v1.13.1...v1.13.2)

#### What's Changed

- Add more tests for UB by
[@&#8203;workingjubilee](https://togithub.com/workingjubilee) in
[https://github.com/servo/rust-smallvec/pull/346](https://togithub.com/servo/rust-smallvec/pull/346)
- Fix UB on out-of-bounds insert() by
[@&#8203;mbrubeck](https://togithub.com/mbrubeck) in
[https://github.com/servo/rust-smallvec/pull/345](https://togithub.com/servo/rust-smallvec/pull/345)

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.13.1...v1.13.2

###
[`v1.13.1`](https://togithub.com/servo/rust-smallvec/releases/tag/v1.13.1)

[Compare
Source](https://togithub.com/servo/rust-smallvec/compare/v1.13.0...v1.13.1)

- Remove the optional `get-size` feature, to avoid a cyclic dependency
([#&#8203;335](https://togithub.com/servo/rust-smallvec/issues/335)).

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.13.0...v1.13.1

###
[`v1.13.0`](https://togithub.com/servo/rust-smallvec/releases/tag/v1.13.0)

[Compare
Source](https://togithub.com/servo/rust-smallvec/compare/v1.12.0...v1.13.0)

#### What's Changed

- Impl get_size::GetSize (behind feature flag) by
[@&#8203;amandasaurus](https://togithub.com/amandasaurus) in
[https://github.com/servo/rust-smallvec/pull/335](https://togithub.com/servo/rust-smallvec/pull/335)

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.12.0...v1.13.0

###
[`v1.12.0`](https://togithub.com/servo/rust-smallvec/releases/tag/v1.12.0)

[Compare
Source](https://togithub.com/servo/rust-smallvec/compare/v1.11.2...v1.12.0)

#### What's Changed

- Add `from_const_with_len_unchecked` by
[@&#8203;Expyron](https://togithub.com/Expyron) in
[https://github.com/servo/rust-smallvec/pull/329](https://togithub.com/servo/rust-smallvec/pull/329)

#### New Contributors

- [@&#8203;Expyron](https://togithub.com/Expyron) made their first
contribution in
[https://github.com/servo/rust-smallvec/pull/329](https://togithub.com/servo/rust-smallvec/pull/329)

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.11.2...v1.12.0

###
[`v1.11.2`](https://togithub.com/servo/rust-smallvec/releases/tag/v1.11.2)

[Compare
Source](https://togithub.com/servo/rust-smallvec/compare/v1.11.1...v1.11.2)

#### What's Changed

- Automated testing improvements by
[@&#8203;waywardmonkeys](https://togithub.com/waywardmonkeys) in
[https://github.com/servo/rust-smallvec/pull/322](https://togithub.com/servo/rust-smallvec/pull/322)
and
[https://github.com/servo/rust-smallvec/pull/326](https://togithub.com/servo/rust-smallvec/pull/326)
- fix: don't special-case `doc` for `feature = "const_generics"` by
[@&#8203;mkroening](https://togithub.com/mkroening) in
[https://github.com/servo/rust-smallvec/pull/328](https://togithub.com/servo/rust-smallvec/pull/328)
- Code cleanup by [@&#8203;emilio](https://togithub.com/emilio) in
[https://github.com/servo/rust-smallvec/pull/316](https://togithub.com/servo/rust-smallvec/pull/316)
and [@&#8203;waywardmonkeys](https://togithub.com/waywardmonkeys) in
[https://github.com/servo/rust-smallvec/pull/323](https://togithub.com/servo/rust-smallvec/pull/323)
- Minor tweaks to doc formatting. by
[@&#8203;waywardmonkeys](https://togithub.com/waywardmonkeys) in
[https://github.com/servo/rust-smallvec/pull/318](https://togithub.com/servo/rust-smallvec/pull/318)

#### New Contributors

- [@&#8203;mkroening](https://togithub.com/mkroening) made their first
contribution in
[https://github.com/servo/rust-smallvec/pull/328](https://togithub.com/servo/rust-smallvec/pull/328)

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.11.1...v1.11.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 08:48:56 -04:00
Marshall Bowers
fbbea7ab01 prisma: Upgrade zed_extension_api to v0.0.6 (#15180)
This PR upgrades the Prisma extension to use v0.0.6 of the
`zed_extension_api`.

Release Notes:

- N/A
2024-07-25 08:46:17 -04:00
Marshall Bowers
aded3dfb05 emmet: Upgrade zed_extension_api to v0.0.6 (#15177)
This PR upgrades the Emmet extension to use v0.0.6 of the
`zed_extension_api`.

Release Notes:

- N/A
2024-07-25 08:34:45 -04:00
Marshall Bowers
3053f98652 csharp: Upgrade zed_extension_api to v0.0.6 (#15175)
This PR upgrades the C# extension to use v0.0.6 of the
`zed_extension_api`.

Release Notes:

- N/A
2024-07-25 08:26:04 -04:00
Peter Tripp
ebd407deb6 Fix broken link in initial settings (#15119)
Fixes #15114
2024-07-25 08:25:27 -04:00
Marshall Bowers
5e44f5fa44 terraform: Bump to v0.0.4 (#15174)
This PR bumps the Terraform extension to v0.0.4.

Changes:

- #10937
- #15171

Release Notes:

- N/A
2024-07-25 08:22:28 -04:00
Marshall Bowers
a07122d78f deno: Bump to v0.0.2 (#15173)
This PR bumps the Deno extension to v0.0.2.

Changes:

- #14410

Release Notes:

- N/A
2024-07-25 08:19:43 -04:00
Marshall Bowers
6a079cbdc3 astro: Bump to v0.1.0 (#15172)
This PR bumps the Astro extension to v0.1.0.

Changes:

- #14849
- #15010
- #15011

Release Notes:

- N/A
2024-07-25 08:16:28 -04:00
Marshall Bowers
c7e2d5bd89 terraform: Make downloaded language server binary executable (#15171)
This PR updates the Terraform extension to make the downloaded language
server binary executable.

Resolves #14502.

Release Notes:

- N/A
2024-07-25 08:08:38 -04:00
renovate[bot]
6bff8ecb73 Update Rust crate heed to v0.20.3 (#15169)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [heed](https://togithub.com/Kerollmops/heed) | workspace.dependencies
| patch | `0.20.1` -> `0.20.3` |

---

### Release Notes

<details>
<summary>Kerollmops/heed (heed)</summary>

###
[`v0.20.3`](https://togithub.com/meilisearch/heed/releases/tag/v0.20.3):
🛁

[Compare
Source](https://togithub.com/Kerollmops/heed/compare/v0.20.2...v0.20.3)

<p align="center"><img width="280px"
src="https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon-logo.png"></a></p>
<h1 align="center" >heed</h1>

##### What's Changed
* Update dependencies by
@&#8203;irevoi[https://github.com/meilisearch/heed/pull/265](https://togithub.com/meilisearch/heed/pull/265)ll/265

###
[`v0.20.2`](https://togithub.com/meilisearch/heed/releases/tag/v0.20.2):
🛁

[Compare
Source](https://togithub.com/Kerollmops/heed/compare/v0.20.1...v0.20.2)

<p align="center"><img width="280px"
src="https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon-logo.png"></a></p>
<h1 align="center" >heed</h1>

##### What's Changed
* Introduce the `longer-keys` feature which sets `-DMDB_MAXKEYSIZE=0` by
@&#8203;tpund[https://github.com/meilisearch/heed/pull/263](https://togithub.com/meilisearch/heed/pull/263)ll/263
* Bump the internal LMDB version to v0.9.33 by
@&#8203;Kerollmo[https://github.com/meilisearch/heed/pull/264](https://togithub.com/meilisearch/heed/pull/264)ll/264

##### New Contributors
* @&#8203;tpunder made their first
contributi[https://github.com/meilisearch/heed/pull/263](https://togithub.com/meilisearch/heed/pull/263)ll/263

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 07:55:15 -04:00
Thorsten Ball
e2113e4895 repl: Add ability to evaluate Markdown code blocks (#15100)
This adds the ability to evaluate TypeScript and Python code blocks in
Markdown files.

cc @rgbkrk 

Demo:


https://github.com/user-attachments/assets/55352de5-68f3-4aef-920a-78ca205651ba



Release Notes:

- N/A

---------

Co-authored-by: Nathan <nathan@zed.dev>
Co-authored-by: Antonio <antonio@zed.dev>
2024-07-25 12:11:19 +02:00
renovate[bot]
b56e4ff2af Update Rust crate any_vec to 0.14 (#15147)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [any_vec](https://togithub.com/tower120/any_vec) |
workspace.dependencies | minor | `0.13` -> `0.14` |

---

### Release Notes

<details>
<summary>tower120/any_vec (any_vec)</summary>

###
[`v0.14.0`](https://togithub.com/tower120/any_vec/blob/HEAD/CHANGELOG.md#0140)

[Compare
Source](https://togithub.com/tower120/any_vec/compare/v0.13.0...v0.14.0)

##### Added

-   Now library `no_std` friendly.

##### Removed

- Helpers `any_value::move_out`, `any_value::move_out_w_size` removed as
redundant.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 12:38:09 +03:00
Marshall Bowers
88f68101d4 renovate: Separate major versions into multiple PRs (#15146)
This PR updates the Renovate config to split major versions changes into
multiple PRs.

This way we only have to deal with one set of breaking changes at a time
instead of jumping across multiple major versions.

Release Notes:

- N/A
2024-07-24 23:48:53 -04:00
renovate[bot]
d852a32ef1 Update Rust crate async-broadcast to v0.7.1 (#15142)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [async-broadcast](https://togithub.com/smol-rs/async-broadcast) |
dependencies | patch | `0.7.0` -> `0.7.1` |

---

### Release Notes

<details>
<summary>smol-rs/async-broadcast (async-broadcast)</summary>

###
[`v0.7.1`](https://togithub.com/smol-rs/async-broadcast/blob/HEAD/CHANGELOG.md#Version-071)

[Compare
Source](https://togithub.com/smol-rs/async-broadcast/compare/0.7.0...v0.7.1)

- Add a `poll_recv()` method to the `Receiver` type. This allows for
`Receiver`
to be used in `poll`-based contexts.
([#&#8203;56](https://togithub.com/smol-rs/async-broadcast/issues/56))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 23:34:49 -04:00
renovate[bot]
b53c3b84e2 Update Rust crate async-compat to v0.2.4 (#15143)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [async-compat](https://togithub.com/smol-rs/async-compat) |
dependencies | patch | `0.2.1` -> `0.2.4` |

---

### Release Notes

<details>
<summary>smol-rs/async-compat (async-compat)</summary>

###
[`v0.2.4`](https://togithub.com/smol-rs/async-compat/blob/HEAD/CHANGELOG.md#Version-024)

[Compare
Source](https://togithub.com/smol-rs/async-compat/compare/v0.2.3...v0.2.4)

- Derive `Clone` for `Compat`.
([#&#8203;27](https://togithub.com/smol-rs/async-compat/issues/27))
- Rather than spawning our own `tokio` runtime all of the time, reuse an
existing runtime if possible.
([#&#8203;30](https://togithub.com/smol-rs/async-compat/issues/30))

###
[`v0.2.3`](https://togithub.com/smol-rs/async-compat/blob/HEAD/CHANGELOG.md#Version-023)

[Compare
Source](https://togithub.com/smol-rs/async-compat/compare/v0.2.2...v0.2.3)

- Enter the `tokio` context while dropping wrapped `tokio` types.
([#&#8203;22](https://togithub.com/smol-rs/async-compat/issues/22))

###
[`v0.2.2`](https://togithub.com/smol-rs/async-compat/blob/HEAD/CHANGELOG.md#Version-022)

[Compare
Source](https://togithub.com/smol-rs/async-compat/compare/v0.2.1...v0.2.2)

- Add `smol-rs` logo to the docs.
([#&#8203;19](https://togithub.com/smol-rs/async-compat/issues/19))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 23:33:02 -04:00
renovate[bot]
3d6b07d78c Update Rust crate derive_more to v0.99.18 (#15144)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [derive_more](https://togithub.com/JelteF/derive_more) |
workspace.dependencies | patch | `0.99.17` -> `0.99.18` |

---

### Release Notes

<details>
<summary>JelteF/derive_more (derive_more)</summary>

###
[`v0.99.18`](https://togithub.com/JelteF/derive_more/compare/v0.99.17...v0.99.18)

[Compare
Source](https://togithub.com/JelteF/derive_more/compare/v0.99.17...v0.99.18)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 23:31:40 -04:00
Marshall Bowers
4c0d0ad4f4 renovate: Add release notes to PR footer (#15145)
This PR updates the Renovate config to place the "Release Notes" section
in the PR body footer.

Also removed the `cla-signed` label, because the CLA bot just removes
it.

Release Notes:

- N/A
2024-07-24 23:18:33 -04:00
renovate[bot]
55575ca830 Update Rust crate aho-corasick to v1.1.3 (#15137)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [aho-corasick](https://togithub.com/BurntSushi/aho-corasick) |
workspace.dependencies | patch | `1.1.1` -> `1.1.3` |

---

### Release Notes

<details>
<summary>BurntSushi/aho-corasick (aho-corasick)</summary>

###
[`v1.1.3`](https://togithub.com/BurntSushi/aho-corasick/compare/1.1.2...1.1.3)

[Compare
Source](https://togithub.com/BurntSushi/aho-corasick/compare/1.1.2...1.1.3)

###
[`v1.1.2`](https://togithub.com/BurntSushi/aho-corasick/compare/1.1.1...1.1.2)

[Compare
Source](https://togithub.com/BurntSushi/aho-corasick/compare/1.1.1...1.1.2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job
log](https://developer.mend.io/github/zed-industries/zed).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJjbGEtc2lnbmVkIl19-->

Release Notes:

- N/A

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 23:01:55 -04:00
Marshall Bowers
ea44af4a85 Upgrade anyhow to v1.0.86 (#15140)
This PR upgrades `anyhow` to v1.0.86.

Release Notes:

- N/A
2024-07-24 22:54:02 -04:00
Marshall Bowers
5865c5e80f Update Renovate config (#15141)
This PR applies some further updates to the Renovate config.

We add the https://github.com/zed-industries/zed/labels/cla-signed label
to the PRs so that check passes.

Also seeing if we can add a "Release Notes" sections to Renovate PRs.

Release Notes:

- N/A
2024-07-24 22:51:51 -04:00
renovate[bot]
51f8013616 Configure Renovate (#15132)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

Welcome to [Renovate](https://togithub.com/renovatebot/renovate)! This
is an onboarding PR to help you understand and configure settings before
regular Pull Requests begin.

🚦 To activate Renovate, merge this Pull Request. To disable Renovate,
simply close this Pull Request unmerged.



---
### Detected Package Files

 * `Cargo.toml` (cargo)
 * `crates/activity_indicator/Cargo.toml` (cargo)
 * `crates/anthropic/Cargo.toml` (cargo)
 * `crates/assets/Cargo.toml` (cargo)
 * `crates/assistant/Cargo.toml` (cargo)
 * `crates/assistant_slash_command/Cargo.toml` (cargo)
 * `crates/assistant_tooling/Cargo.toml` (cargo)
 * `crates/audio/Cargo.toml` (cargo)
 * `crates/auto_update/Cargo.toml` (cargo)
 * `crates/breadcrumbs/Cargo.toml` (cargo)
 * `crates/call/Cargo.toml` (cargo)
 * `crates/channel/Cargo.toml` (cargo)
 * `crates/cli/Cargo.toml` (cargo)
 * `crates/client/Cargo.toml` (cargo)
 * `crates/clock/Cargo.toml` (cargo)
 * `crates/collab/Cargo.toml` (cargo)
 * `crates/collab_ui/Cargo.toml` (cargo)
 * `crates/collections/Cargo.toml` (cargo)
 * `crates/command_palette/Cargo.toml` (cargo)
 * `crates/command_palette_hooks/Cargo.toml` (cargo)
 * `crates/completion/Cargo.toml` (cargo)
 * `crates/copilot/Cargo.toml` (cargo)
 * `crates/db/Cargo.toml` (cargo)
 * `crates/dev_server_projects/Cargo.toml` (cargo)
 * `crates/diagnostics/Cargo.toml` (cargo)
 * `crates/editor/Cargo.toml` (cargo)
 * `crates/extension/Cargo.toml` (cargo)
 * `crates/extension_api/Cargo.toml` (cargo)
 * `crates/extension_cli/Cargo.toml` (cargo)
 * `crates/extensions_ui/Cargo.toml` (cargo)
 * `crates/feature_flags/Cargo.toml` (cargo)
 * `crates/feedback/Cargo.toml` (cargo)
 * `crates/file_finder/Cargo.toml` (cargo)
 * `crates/file_icons/Cargo.toml` (cargo)
 * `crates/fs/Cargo.toml` (cargo)
 * `crates/fsevent/Cargo.toml` (cargo)
 * `crates/fuzzy/Cargo.toml` (cargo)
 * `crates/git/Cargo.toml` (cargo)
 * `crates/git_hosting_providers/Cargo.toml` (cargo)
 * `crates/go_to_line/Cargo.toml` (cargo)
 * `crates/google_ai/Cargo.toml` (cargo)
 * `crates/gpui/Cargo.toml` (cargo)
 * `crates/gpui_macros/Cargo.toml` (cargo)
 * `crates/headless/Cargo.toml` (cargo)
 * `crates/html_to_markdown/Cargo.toml` (cargo)
 * `crates/http_client/Cargo.toml` (cargo)
 * `crates/image_viewer/Cargo.toml` (cargo)
 * `crates/indexed_docs/Cargo.toml` (cargo)
 * `crates/inline_completion_button/Cargo.toml` (cargo)
 * `crates/install_cli/Cargo.toml` (cargo)
 * `crates/journal/Cargo.toml` (cargo)
 * `crates/language/Cargo.toml` (cargo)
 * `crates/language_model/Cargo.toml` (cargo)
 * `crates/language_selector/Cargo.toml` (cargo)
 * `crates/language_tools/Cargo.toml` (cargo)
 * `crates/languages/Cargo.toml` (cargo)
 * `crates/live_kit_client/Cargo.toml` (cargo)
 * `crates/live_kit_server/Cargo.toml` (cargo)
 * `crates/lsp/Cargo.toml` (cargo)
 * `crates/markdown/Cargo.toml` (cargo)
 * `crates/markdown_preview/Cargo.toml` (cargo)
 * `crates/media/Cargo.toml` (cargo)
 * `crates/menu/Cargo.toml` (cargo)
 * `crates/multi_buffer/Cargo.toml` (cargo)
 * `crates/node_runtime/Cargo.toml` (cargo)
 * `crates/notifications/Cargo.toml` (cargo)
 * `crates/ollama/Cargo.toml` (cargo)
 * `crates/open_ai/Cargo.toml` (cargo)
 * `crates/outline/Cargo.toml` (cargo)
 * `crates/outline_panel/Cargo.toml` (cargo)
 * `crates/paths/Cargo.toml` (cargo)
 * `crates/picker/Cargo.toml` (cargo)
 * `crates/prettier/Cargo.toml` (cargo)
 * `crates/project/Cargo.toml` (cargo)
 * `crates/project_panel/Cargo.toml` (cargo)
 * `crates/project_symbols/Cargo.toml` (cargo)
 * `crates/proto/Cargo.toml` (cargo)
 * `crates/quick_action_bar/Cargo.toml` (cargo)
 * `crates/recent_projects/Cargo.toml` (cargo)
 * `crates/refineable/Cargo.toml` (cargo)
 * `crates/refineable/derive_refineable/Cargo.toml` (cargo)
 * `crates/release_channel/Cargo.toml` (cargo)
 * `crates/remote/Cargo.toml` (cargo)
 * `crates/remote_server/Cargo.toml` (cargo)
 * `crates/repl/Cargo.toml` (cargo)
 * `crates/rich_text/Cargo.toml` (cargo)
 * `crates/rope/Cargo.toml` (cargo)
 * `crates/rpc/Cargo.toml` (cargo)
 * `crates/search/Cargo.toml` (cargo)
 * `crates/semantic_index/Cargo.toml` (cargo)
 * `crates/semantic_version/Cargo.toml` (cargo)
 * `crates/session/Cargo.toml` (cargo)
 * `crates/settings/Cargo.toml` (cargo)
 * `crates/settings_ui/Cargo.toml` (cargo)
 * `crates/snippet/Cargo.toml` (cargo)
 * `crates/snippet_provider/Cargo.toml` (cargo)
 * `crates/sqlez/Cargo.toml` (cargo)
 * `crates/sqlez_macros/Cargo.toml` (cargo)
 * `crates/story/Cargo.toml` (cargo)
 * `crates/storybook/Cargo.toml` (cargo)
 * `crates/sum_tree/Cargo.toml` (cargo)
 * `crates/supermaven/Cargo.toml` (cargo)
 * `crates/supermaven_api/Cargo.toml` (cargo)
 * `crates/tab_switcher/Cargo.toml` (cargo)
 * `crates/task/Cargo.toml` (cargo)
 * `crates/tasks_ui/Cargo.toml` (cargo)
 * `crates/telemetry_events/Cargo.toml` (cargo)
 * `crates/terminal/Cargo.toml` (cargo)
 * `crates/terminal_view/Cargo.toml` (cargo)
 * `crates/text/Cargo.toml` (cargo)
 * `crates/theme/Cargo.toml` (cargo)
 * `crates/theme_importer/Cargo.toml` (cargo)
 * `crates/theme_selector/Cargo.toml` (cargo)
 * `crates/time_format/Cargo.toml` (cargo)
 * `crates/title_bar/Cargo.toml` (cargo)
 * `crates/ui/Cargo.toml` (cargo)
 * `crates/ui_input/Cargo.toml` (cargo)
 * `crates/util/Cargo.toml` (cargo)
 * `crates/vcs_menu/Cargo.toml` (cargo)
 * `crates/vim/Cargo.toml` (cargo)
 * `crates/welcome/Cargo.toml` (cargo)
 * `crates/workspace/Cargo.toml` (cargo)
 * `crates/worktree/Cargo.toml` (cargo)
 * `crates/zed/Cargo.toml` (cargo)
 * `crates/zed_actions/Cargo.toml` (cargo)
 * `extensions/astro/Cargo.toml` (cargo)
 * `extensions/clojure/Cargo.toml` (cargo)
 * `extensions/csharp/Cargo.toml` (cargo)
 * `extensions/dart/Cargo.toml` (cargo)
 * `extensions/deno/Cargo.toml` (cargo)
 * `extensions/elixir/Cargo.toml` (cargo)
 * `extensions/elm/Cargo.toml` (cargo)
 * `extensions/emmet/Cargo.toml` (cargo)
 * `extensions/erlang/Cargo.toml` (cargo)
 * `extensions/gleam/Cargo.toml` (cargo)
 * `extensions/glsl/Cargo.toml` (cargo)
 * `extensions/haskell/Cargo.toml` (cargo)
 * `extensions/html/Cargo.toml` (cargo)
 * `extensions/lua/Cargo.toml` (cargo)
 * `extensions/ocaml/Cargo.toml` (cargo)
 * `extensions/php/Cargo.toml` (cargo)
 * `extensions/prisma/Cargo.toml` (cargo)
 * `extensions/purescript/Cargo.toml` (cargo)
 * `extensions/ruby/Cargo.toml` (cargo)
 * `extensions/ruff/Cargo.toml` (cargo)
 * `extensions/snippets/Cargo.toml` (cargo)
 * `extensions/svelte/Cargo.toml` (cargo)
 * `extensions/terraform/Cargo.toml` (cargo)
 * `extensions/test-extension/Cargo.toml` (cargo)
 * `extensions/toml/Cargo.toml` (cargo)
 * `extensions/uiua/Cargo.toml` (cargo)
 * `extensions/vue/Cargo.toml` (cargo)
 * `extensions/zig/Cargo.toml` (cargo)
 * `tooling/xtask/Cargo.toml` (cargo)
 * `compose.yml` (docker-compose)
 * `Dockerfile` (dockerfile)
 * `.github/actions/run_tests/action.yml` (github-actions)
 * `.github/workflows/bump_patch_version.yml` (github-actions)
 * `.github/workflows/ci.yml` (github-actions)
 * `.github/workflows/danger.yml` (github-actions)
 * `.github/workflows/deploy_cloudflare.yml` (github-actions)
 * `.github/workflows/deploy_collab.yml` (github-actions)
 * `.github/workflows/publish_extension_cli.yml` (github-actions)
 * `.github/workflows/randomized_tests.yml` (github-actions)
 * `.github/workflows/release_actions.yml` (github-actions)
 * `.github/workflows/release_nightly.yml` (github-actions)
* `.github/workflows/update_all_top_ranking_issues.yml` (github-actions)
* `.github/workflows/update_weekly_top_ranking_issues.yml`
(github-actions)
 * `script/danger/package.json` (npm)
 * `script/update_top_ranking_issues/pyproject.toml` (pep621)
* `script/update_top_ranking_issues/requirements.txt` (pip_requirements)
 * `script/update_top_ranking_issues/pyproject.toml` (poetry)
 * `crates/live_kit_client/LiveKitBridge/Package.swift` (swift)

### Configuration Summary

Based on the default config's presets, Renovate will:

  - Start dependency updates only once this onboarding PR is merged
  - Show all Merge Confidence badges for pull requests.
  - Enable Renovate Dependency Dashboard creation.
- Use semantic commit type `fix` for dependencies and `chore` for all
others if semantic commits are in use.
- Ignore `node_modules`, `bower_components`, `vendor` and various
test/tests directories.
  - Group known monorepo packages together.
  - Use curated list of recommended non-monorepo package groupings.
  - Apply crowd-sourced package replacement rules.
  - Apply crowd-sourced workarounds for known problems with packages.
  - Disable semantic prefixes for commit messages and PR titles.
  - Run Renovate on following schedule: after 3pm on Wednesday

🔡 Do you want to change how Renovate upgrades your dependencies? Add
your custom config to `renovate.json` in this branch. Renovate will
update the Pull Request description the next time it runs.

---

### What to Expect

With your current configuration, Renovate will create 144 Pull Requests:

<details>
<summary>Update Python to v3.12.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/python-3.x`
  - Merge into: `main`
- Upgrade [python](https://togithub.com/containerbase/python-prebuild)
to `3.12.4`


</details>

<details>
<summary>Update Rust crate aho-corasick to v1.1.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/aho-corasick-1.x-lockfile`
  - Merge into: `main`
- Upgrade [aho-corasick](https://togithub.com/BurntSushi/aho-corasick)
to `1.1.3`


</details>

<details>
<summary>Update Rust crate anyhow to v1.0.86</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/anyhow-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [anyhow](https://togithub.com/dtolnay/anyhow) to `1.0.86`


</details>

<details>
<summary>Update Rust crate async-broadcast to v0.7.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-broadcast-0.x-lockfile`
  - Merge into: `main`
- Upgrade
[async-broadcast](https://togithub.com/smol-rs/async-broadcast) to
`0.7.1`


</details>

<details>
<summary>Update Rust crate async-compat to v0.2.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-compat-0.x-lockfile`
  - Merge into: `main`
- Upgrade [async-compat](https://togithub.com/smol-rs/async-compat) to
`0.2.4`


</details>

<details>
<summary>Update Rust crate async-compression to v0.4.12</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-compression-0.x-lockfile`
  - Merge into: `main`
- Upgrade
[async-compression](https://togithub.com/Nullus157/async-compression) to
`0.4.12`


</details>

<details>
<summary>Update Rust crate async-task to v4.7.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-task-4.x-lockfile`
  - Merge into: `main`
- Upgrade [async-task](https://togithub.com/smol-rs/async-task) to
`4.7.1`


</details>

<details>
<summary>Update Rust crate async-trait to v0.1.81</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-trait-0.x-lockfile`
  - Merge into: `main`
- Upgrade [async-trait](https://togithub.com/dtolnay/async-trait) to
`0.1.81`


</details>

<details>
<summary>Update Rust crate backtrace to v0.3.73</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/backtrace-0.x-lockfile`
  - Merge into: `main`
- Upgrade [backtrace](https://togithub.com/rust-lang/backtrace-rs) to
`0.3.73`


</details>

<details>
<summary>Update Rust crate cargo_toml to v0.20.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/cargo_toml-0.x-lockfile`
  - Merge into: `main`
- Upgrade [cargo_toml](https://gitlab.com/lib.rs/cargo_toml) to `0.20.4`


</details>

<details>
<summary>Update Rust crate core-graphics to v0.23.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/core-graphics-0.x-lockfile`
  - Merge into: `main`
- Upgrade [core-graphics](https://togithub.com/servo/core-foundation-rs)
to `0.23.2`


</details>

<details>
<summary>Update Rust crate ctor to v0.2.8</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/ctor-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [ctor](https://togithub.com/mmastrac/rust-ctor) to `0.2.8`


</details>

<details>
<summary>Update Rust crate derive_more to v0.99.18</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/derive_more-0.x-lockfile`
  - Merge into: `main`
- Upgrade [derive_more](https://togithub.com/JelteF/derive_more) to
`0.99.18`


</details>

<details>
<summary>Update Rust crate embed-resource to v2.4.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/embed-resource-2.x-lockfile`
  - Merge into: `main`
- Upgrade
[embed-resource](https://togithub.com/nabijaczleweli/rust-embed-resource)
to `2.4.3`


</details>

<details>
<summary>Update Rust crate emojis to v0.6.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/emojis-0.x-lockfile`
  - Merge into: `main`
- Upgrade [emojis](https://togithub.com/rossmacarthur/emojis) to `0.6.3`


</details>

<details>
<summary>Update Rust crate etagere to v0.2.13</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/etagere-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [etagere](https://togithub.com/nical/etagere) to `0.2.13`


</details>

<details>
<summary>Update Rust crate futures to v0.3.30</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rust-futures-monorepo`
  - Merge into: `main`
- Upgrade [futures](https://togithub.com/rust-lang/futures-rs) to
`0.3.30`


</details>

<details>
<summary>Update Rust crate heed to v0.20.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/heed-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [heed](https://togithub.com/Kerollmops/heed) to `0.20.3`


</details>

<details>
<summary>Update Rust crate image to v0.25.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/image-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [image](https://togithub.com/image-rs/image) to `0.25.2`


</details>

<details>
<summary>Update Rust crate ipc-channel to v0.18.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/ipc-channel-0.x-lockfile`
  - Merge into: `main`
- Upgrade [ipc-channel](https://togithub.com/servo/ipc-channel) to
`0.18.2`


</details>

<details>
<summary>Update Rust crate libc to v0.2.155</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/libc-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [libc](https://togithub.com/rust-lang/libc) to `0.2.155`


</details>

<details>
<summary>Update Rust crate linkme to v0.3.27</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/linkme-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [linkme](https://togithub.com/dtolnay/linkme) to `0.3.27`


</details>

<details>
<summary>Update Rust crate log to v0.4.22</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/log-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [log](https://togithub.com/rust-lang/log) to `0.4.22`


</details>

<details>
<summary>Update Rust crate mimalloc to v0.1.43</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/mimalloc-0.x-lockfile`
  - Merge into: `main`
- Upgrade [mimalloc](https://togithub.com/purpleprotocol/mimalloc_rust)
to `0.1.43`


</details>

<details>
<summary>Update Rust crate oo7 to v0.3.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/oo7-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [oo7](https://togithub.com/bilelmoussaoui/oo7) to `0.3.3`


</details>

<details>
<summary>Update Rust crate ordered-float to v2.10.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/ordered-float-2.x-lockfile`
  - Merge into: `main`
- Upgrade [ordered-float](https://togithub.com/reem/rust-ordered-float)
to `2.10.1`


</details>

<details>
<summary>Update Rust crate palette to v0.7.6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/palette-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [palette](https://togithub.com/Ogeon/palette) to `0.7.6`


</details>

<details>
<summary>Update Rust crate parking_lot to v0.12.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/parking_lot-0.x-lockfile`
  - Merge into: `main`
- Upgrade [parking_lot](https://togithub.com/Amanieu/parking_lot) to
`0.12.3`


</details>

<details>
<summary>Update Rust crate proc-macro2 to v1.0.86</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/proc-macro2-1.x-lockfile`
  - Merge into: `main`
- Upgrade [proc-macro2](https://togithub.com/dtolnay/proc-macro2) to
`1.0.86`


</details>

<details>
<summary>Update Rust crate prometheus to v0.13.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/prometheus-0.x-lockfile`
  - Merge into: `main`
- Upgrade [prometheus](https://togithub.com/tikv/rust-prometheus) to
`0.13.4`


</details>

<details>
<summary>Update Rust crate quote to v1.0.36</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/quote-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [quote](https://togithub.com/dtolnay/quote) to `1.0.36`


</details>

<details>
<summary>Update Rust crate raw-window-handle to v0.6.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/raw-window-handle-0.x-lockfile`
  - Merge into: `main`
- Upgrade
[raw-window-handle](https://togithub.com/rust-windowing/raw-window-handle)
to `0.6.2`


</details>

<details>
<summary>Update Rust crate rustc-demangle to v0.1.24</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rustc-demangle-0.x-lockfile`
  - Merge into: `main`
- Upgrade
[rustc-demangle](https://togithub.com/rust-lang/rustc-demangle) to
`0.1.24`


</details>

<details>
<summary>Update Rust crate schemars to v0.8.21</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/schemars-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [schemars](https://togithub.com/GREsau/schemars) to `0.8.21`


</details>

<details>
<summary>Update Rust crate sea-orm to v0.12.15</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/sea-orm-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [sea-orm](https://togithub.com/SeaQL/sea-orm) to `0.12.15`


</details>

<details>
<summary>Update Rust crate semver to v1.0.23</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/semver-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [semver](https://togithub.com/dtolnay/semver) to `1.0.23`


</details>

<details>
<summary>Update Rust crate serde_json to v1.0.120</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/serde_json-1.x-lockfile`
  - Merge into: `main`
- Upgrade [serde_json](https://togithub.com/serde-rs/json) to `1.0.120`


</details>

<details>
<summary>Update Rust crate serde_repr to v0.1.19</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/serde_repr-0.x-lockfile`
  - Merge into: `main`
- Upgrade [serde_repr](https://togithub.com/dtolnay/serde-repr) to
`0.1.19`


</details>

<details>
<summary>Update Rust crate sha2 to v0.10.8</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/sha2-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [sha2](https://togithub.com/RustCrypto/hashes) to `0.10.8`


</details>

<details>
<summary>Update Rust crate slotmap to v1.0.7</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/slotmap-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [slotmap](https://togithub.com/orlp/slotmap) to `1.0.7`


</details>

<details>
<summary>Update Rust crate sqlformat to v0.2.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/sqlformat-0.x-lockfile`
  - Merge into: `main`
- Upgrade [sqlformat](https://togithub.com/shssoichiro/sqlformat-rs) to
`0.2.4`


</details>

<details>
<summary>Update Rust crate sysinfo to v0.30.13</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/sysinfo-0.x-lockfile`
  - Merge into: `main`
- Upgrade [sysinfo](https://togithub.com/GuillaumeGomez/sysinfo) to
`0.30.13`


</details>

<details>
<summary>Update Rust crate thiserror to v1.0.63</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/thiserror-1.x-lockfile`
  - Merge into: `main`
- Upgrade [thiserror](https://togithub.com/dtolnay/thiserror) to
`1.0.63`


</details>

<details>
<summary>Update Rust crate thread_local to v1.1.8</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/thread_local-1.x-lockfile`
  - Merge into: `main`
- Upgrade [thread_local](https://togithub.com/Amanieu/thread_local-rs)
to `1.1.8`


</details>

<details>
<summary>Update Rust crate toml to v0.8.15</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/toml-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [toml](https://togithub.com/toml-rs/toml) to `0.8.15`


</details>

<details>
<summary>Update Rust crate url to v2.5.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/url-2.x-lockfile`
  - Merge into: `main`
  - Upgrade [url](https://togithub.com/servo/rust-url) to `2.5.2`


</details>

<details>
<summary>Update Rust crate wayland-backend to v0.3.6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wayland-backend-0.x-lockfile`
  - Merge into: `main`
- Upgrade [wayland-backend](https://togithub.com/smithay/wayland-rs) to
`0.3.6`


</details>

<details>
<summary>Update Rust crate wayland-client to v0.31.5</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wayland-client-0.x-lockfile`
  - Merge into: `main`
- Upgrade [wayland-client](https://togithub.com/smithay/wayland-rs) to
`0.31.5`


</details>

<details>
<summary>Update Rust crate wayland-cursor to v0.31.5</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wayland-cursor-0.x-lockfile`
  - Merge into: `main`
- Upgrade [wayland-cursor](https://togithub.com/smithay/wayland-rs) to
`0.31.5`


</details>

<details>
<summary>Update Rust crate which to v6.0.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/which-6.x-lockfile`
  - Merge into: `main`
  - Upgrade [which](https://togithub.com/harryfei/which-rs) to `6.0.1`


</details>

<details>
<summary>Update Rust crate x11rb to v0.13.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/x11rb-0.x-lockfile`
  - Merge into: `main`
  - Upgrade [x11rb](https://togithub.com/psychon/x11rb) to `0.13.1`


</details>

<details>
<summary>Update Rust crate zed_extension_api to 0.0.6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/zed_extension_api-0.x`
  - Merge into: `main`
- Upgrade [zed_extension_api](https://togithub.com/zed-industries/zed)
to `0.0.6`


</details>

<details>
<summary>Update serde monorepo to v1.0.204</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/serde-monorepo`
  - Merge into: `main`
  - Upgrade [serde](https://togithub.com/serde-rs/serde) to `1.0.204`
- Upgrade [serde_derive](https://togithub.com/serde-rs/serde) to
`1.0.204`


</details>

<details>
<summary>Update 2428392/gh-truncate-string-action action to
v1.4.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/2428392-gh-truncate-string-action-1.x`
  - Merge into: `main`
- Upgrade
[2428392/gh-truncate-string-action](https://togithub.com/2428392/gh-truncate-string-action)
to `v1.4.0`


</details>

<details>
<summary>Update Rust crate alacritty_terminal to 0.24</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/alacritty_terminal-0.x`
  - Merge into: `main`
- Upgrade [alacritty_terminal](https://togithub.com/alacritty/alacritty)
to `0.24`


</details>

<details>
<summary>Update Rust crate any_vec to 0.14</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/any_vec-0.x`
  - Merge into: `main`
  - Upgrade [any_vec](https://togithub.com/tower120/any_vec) to `0.14`


</details>

<details>
<summary>Update Rust crate async-recursion to v1.1.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-recursion-1.x-lockfile`
  - Merge into: `main`
- Upgrade [async-recursion](https://togithub.com/dcchut/async-recursion)
to `1.1.1`


</details>

<details>
<summary>Update Rust crate async-tungstenite to 0.27</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-tungstenite-0.x`
  - Merge into: `main`
- Upgrade
[async-tungstenite](https://togithub.com/sdroege/async-tungstenite) to
`0.27`


</details>

<details>
<summary>Update Rust crate axum to 0.7</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/axum-0.x`
  - Merge into: `main`
  - Upgrade [axum](https://togithub.com/tokio-rs/axum) to `0.7`


</details>

<details>
<summary>Update Rust crate axum-extra to 0.9</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/axum-extra-0.x`
  - Merge into: `main`
  - Upgrade [axum-extra](https://togithub.com/tokio-rs/axum) to `0.9`


</details>

<details>
<summary>Update Rust crate base64 to 0.22</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/base64-0.x`
  - Merge into: `main`
- Upgrade [base64](https://togithub.com/marshallpierce/rust-base64) to
`0.22`


</details>

<details>
<summary>Update Rust crate bindgen to 0.69.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/bindgen-0.x`
  - Merge into: `main`
- Upgrade [bindgen](https://togithub.com/rust-lang/rust-bindgen) to
`0.69.0`


</details>

<details>
<summary>Update Rust crate bytemuck to v1.16.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/bytemuck-1.x-lockfile`
  - Merge into: `main`
- Upgrade [bytemuck](https://togithub.com/Lokathor/bytemuck) to `1.16.1`


</details>

<details>
<summary>Update Rust crate calloop to 0.14.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/calloop-0.x`
  - Merge into: `main`
  - Upgrade [calloop](https://togithub.com/Smithay/calloop) to `0.14.0`


</details>

<details>
<summary>Update Rust crate cap-std to v3.2.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/cap-std-3.x-lockfile`
  - Merge into: `main`
- Upgrade [cap-std](https://togithub.com/bytecodealliance/cap-std) to
`3.2.0`


</details>

<details>
<summary>Update Rust crate clap to v4.5.10</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/clap-4.x-lockfile`
  - Merge into: `main`
  - Upgrade [clap](https://togithub.com/clap-rs/clap) to `4.5.10`


</details>

<details>
<summary>Update Rust crate clickhouse to 0.12.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/clickhouse-0.x`
  - Merge into: `main`
- Upgrade [clickhouse](https://togithub.com/loyd/clickhouse.rs) to
`0.12.0`


</details>

<details>
<summary>Update Rust crate env_logger to 0.11</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/env_logger-0.x`
  - Merge into: `main`
- Upgrade [env_logger](https://togithub.com/rust-cli/env_logger) to
`0.11`


</details>

<details>
<summary>Update Rust crate fork to 0.2.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/fork-0.x`
  - Merge into: `main`
  - Upgrade [fork](https://togithub.com/immortal/fork) to `0.2.0`


</details>

<details>
<summary>Update Rust crate http to v1.1.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/http-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [http](https://togithub.com/hyperium/http) to `1.1.0`


</details>

<details>
<summary>Update Rust crate itertools to v0.13.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/itertools-0.x`
  - Merge into: `main`
- Upgrade [itertools](https://togithub.com/rust-itertools/itertools) to
`0.13`
- Upgrade [itertools](https://togithub.com/rust-itertools/itertools) to
`0.13.0`


</details>

<details>
<summary>Update Rust crate lazy_static to v1.5.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/lazy_static-1.x-lockfile`
  - Merge into: `main`
- Upgrade
[lazy_static](https://togithub.com/rust-lang-nursery/lazy-static.rs) to
`1.5.0`


</details>

<details>
<summary>Update Rust crate libsqlite3-sys to 0.30</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/libsqlite3-sys-0.x`
  - Merge into: `main`
- Upgrade [libsqlite3-sys](https://togithub.com/rusqlite/rusqlite) to
`0.30`


</details>

<details>
<summary>Update Rust crate nix to 0.29</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/nix-0.x`
  - Merge into: `main`
  - Upgrade [nix](https://togithub.com/nix-rust/nix) to `0.29`


</details>

<details>
<summary>Update Rust crate pulldown-cmark to 0.11.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/pulldown-cmark-0.x`
  - Merge into: `main`
- Upgrade
[pulldown-cmark](https://togithub.com/raphlinus/pulldown-cmark) to
`0.11.0`


</details>

<details>
<summary>Update Rust crate rayon to v1.10.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rayon-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [rayon](https://togithub.com/rayon-rs/rayon) to `1.10.0`


</details>

<details>
<summary>Update Rust crate reqwest to 0.12</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/reqwest-0.x`
  - Merge into: `main`
- Upgrade [reqwest](https://togithub.com/seanmonstar/reqwest) to `0.12`


</details>

<details>
<summary>Update Rust crate resvg to 0.42.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/resvg-0.x`
  - Merge into: `main`
  - Upgrade [resvg](https://togithub.com/RazrFalcon/resvg) to `0.42.0`


</details>

<details>
<summary>Update Rust crate rodio to 0.19.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rodio-0.x`
  - Merge into: `main`
  - Upgrade [rodio](https://togithub.com/RustAudio/rodio) to `0.19.0`


</details>

<details>
<summary>Update Rust crate runtimelib to 0.13</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/runtimelib-0.x`
  - Merge into: `main`
  - Upgrade runtimelib to `0.13`


</details>

<details>
<summary>Update Rust crate rusqlite to 0.32.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rusqlite-0.x`
  - Merge into: `main`
- Upgrade [rusqlite](https://togithub.com/rusqlite/rusqlite) to `0.32.0`


</details>

<details>
<summary>Update Rust crate rust-embed to v8.5.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rust-embed-8.x-lockfile`
  - Merge into: `main`
- Upgrade [rust-embed](https://togithub.com/pyros2097/rust-embed) to
`8.5.0`


</details>

<details>
<summary>Update Rust crate scrypt to 0.11</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/scrypt-0.x`
  - Merge into: `main`
- Upgrade [scrypt](https://togithub.com/RustCrypto/password-hashes) to
`0.11`


</details>

<details>
<summary>Update Rust crate serde_json_lenient to 0.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/serde_json_lenient-0.x`
  - Merge into: `main`
- Upgrade
[serde_json_lenient](https://togithub.com/google/serde_json_lenient) to
`0.2`


</details>

<details>
<summary>Update Rust crate smallvec to v1.13.2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/smallvec-1.x-lockfile`
  - Merge into: `main`
- Upgrade [smallvec](https://togithub.com/servo/rust-smallvec) to
`1.13.2`


</details>

<details>
<summary>Update Rust crate sqlx to 0.8</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/sqlx-0.x`
  - Merge into: `main`
  - Upgrade [sqlx](https://togithub.com/launchbadge/sqlx) to `0.8`


</details>

<details>
<summary>Update Rust crate strum to 0.26.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/strum-monorepo`
  - Merge into: `main`
  - Upgrade [strum](https://togithub.com/Peternator7/strum) to `0.26.0`


</details>

<details>
<summary>Update Rust crate subtle to v2.6.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/subtle-2.x-lockfile`
  - Merge into: `main`
- Upgrade [subtle](https://togithub.com/dalek-cryptography/subtle) to
`2.6.1`


</details>

<details>
<summary>Update Rust crate taffy to 0.5.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/taffy-0.x`
  - Merge into: `main`
  - Upgrade [taffy](https://togithub.com/DioxusLabs/taffy) to `0.5.0`


</details>

<details>
<summary>Update Rust crate tempfile to v3.10.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tempfile-3.x-lockfile`
  - Merge into: `main`
- Upgrade [tempfile](https://togithub.com/Stebalien/tempfile) to
`3.10.1`


</details>

<details>
<summary>Update Rust crate tiny_http to 0.12</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tiny_http-0.x`
  - Merge into: `main`
- Upgrade [tiny_http](https://togithub.com/tiny-http/tiny-http) to
`0.12`


</details>

<details>
<summary>Update Rust crate tokio to v1.39.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tokio-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [tokio](https://togithub.com/tokio-rs/tokio) to `1.39.1`


</details>

<details>
<summary>Update Rust crate tower-http to 0.5.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tower-http-0.x`
  - Merge into: `main`
- Upgrade [tower-http](https://togithub.com/tower-rs/tower-http) to
`0.5.0`


</details>

<details>
<summary>Update Rust crate tree-sitter-embedded-template to
0.21.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tree-sitter-embedded-template-0.x`
  - Merge into: `main`
- Upgrade
[tree-sitter-embedded-template](https://togithub.com/tree-sitter/tree-sitter-embedded-template)
to `0.21.0`


</details>

<details>
<summary>Update Rust crate unicode-segmentation to v1.11.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/unicode-segmentation-1.x-lockfile`
  - Merge into: `main`
- Upgrade
[unicode-segmentation](https://togithub.com/unicode-rs/unicode-segmentation)
to `1.11.0`


</details>

<details>
<summary>Update Rust crate unindent to 0.2.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/unindent-0.x`
  - Merge into: `main`
  - Upgrade [unindent](https://togithub.com/dtolnay/indoc) to `0.2.0`


</details>

<details>
<summary>Update Rust crate usvg to 0.42.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/usvg-0.x`
  - Merge into: `main`
  - Upgrade [usvg](https://togithub.com/RazrFalcon/resvg) to `0.42.0`


</details>

<details>
<summary>Update Rust crate uuid to v1.10.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/uuid-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [uuid](https://togithub.com/uuid-rs/uuid) to `1.10.0`


</details>

<details>
<summary>Update Rust crate waker-fn to v1.2.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/waker-fn-1.x-lockfile`
  - Merge into: `main`
  - Upgrade [waker-fn](https://togithub.com/smol-rs/waker-fn) to `1.2.0`


</details>

<details>
<summary>Update Rust crate wasm-encoder to 0.214</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wasm-encoder-0.x`
  - Merge into: `main`
- Upgrade
[wasm-encoder](https://togithub.com/bytecodealliance/wasm-tools) to
`0.214`


</details>

<details>
<summary>Update Rust crate wasmparser to 0.214</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wasmparser-0.x`
  - Merge into: `main`
- Upgrade [wasmparser](https://togithub.com/bytecodealliance/wasm-tools)
to `0.214`


</details>

<details>
<summary>Update Rust crate wayland-protocols to 0.32.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wayland-protocols-0.x`
  - Merge into: `main`
- Upgrade [wayland-protocols](https://togithub.com/smithay/wayland-rs)
to `0.32.0`


</details>

<details>
<summary>Update Rust crate wayland-protocols-plasma to 0.3.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wayland-protocols-plasma-0.x`
  - Merge into: `main`
- Upgrade
[wayland-protocols-plasma](https://togithub.com/smithay/wayland-rs) to
`0.3.0`


</details>

<details>
<summary>Update Rust crate windows to 0.58</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/windows-0.x`
  - Merge into: `main`
- Upgrade [windows](https://togithub.com/microsoft/windows-rs) to `0.58`


</details>

<details>
<summary>Update Rust crate windows-core to 0.58</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/windows-core-0.x`
  - Merge into: `main`
- Upgrade [windows-core](https://togithub.com/microsoft/windows-rs) to
`0.58`


</details>

<details>
<summary>Update Rust crate wit-bindgen to 0.28</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wit-bindgen-0.x`
  - Merge into: `main`
- Upgrade [wit-bindgen](https://togithub.com/bytecodealliance/wasi-rs)
to `0.28`


</details>

<details>
<summary>Update Rust crate wit-component to 0.214</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wit-component-0.x`
  - Merge into: `main`
- Upgrade
[wit-component](https://togithub.com/bytecodealliance/wasm-tools) to
`0.214`


</details>

<details>
<summary>Update Rust crate zstd to 0.13</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/zstd-0.x`
  - Merge into: `main`
  - Upgrade [zstd](https://togithub.com/gyscos/zstd-rs) to `0.13`


</details>

<details>
<summary>Update aws-sdk-rust monorepo</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/aws-sdk-rust-monorepo`
  - Merge into: `main`
- Upgrade [aws-config](https://togithub.com/smithy-lang/smithy-rs) to
`1.5.4`
- Upgrade [aws-sdk-s3](https://togithub.com/awslabs/aws-sdk-rust) to
`1.42.0`


</details>

<details>
<summary>Update dependency PyGithub to v1.59.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/pygithub-1.x`
  - Merge into: `main`
- Upgrade [PyGithub](https://togithub.com/pygithub/pygithub) to `1.59.1`


</details>

<details>
<summary>Update dependency livekit/client-sdk-swift to v1.1.6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/livekit-client-sdk-swift-1.x`
  - Merge into: `main`
- Upgrade
[livekit/client-sdk-swift](https://togithub.com/livekit/client-sdk-swift)
to `1.1.6`


</details>

<details>
<summary>Update dependency mypy to v1.11.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/mypy-1.x`
  - Merge into: `main`
  - Upgrade [mypy](https://togithub.com/python/mypy) to `1.11.0`
  - Upgrade [mypy](https://togithub.com/python/mypy) to `==1.11.0`


</details>

<details>
<summary>Update dependency pytz to v2022.7.1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/pytz-2022.x`
  - Merge into: `main`
  - Upgrade pytz to `2022.7.1`
  - Upgrade pytz to `==2022.7.1`


</details>

<details>
<summary>Update dependency ruff to v0.5.4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/ruff-0.x`
  - Merge into: `main`
  - Upgrade [ruff](https://togithub.com/astral-sh/ruff) to `==0.5.4`


</details>

<details>
<summary>Update dependency typer to v0.12.3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/typer-0.x`
  - Merge into: `main`
  - Upgrade [typer](https://togithub.com/tiangolo/typer) to `0.12.3`
  - Upgrade [typer](https://togithub.com/tiangolo/typer) to `==0.12.3`


</details>

<details>
<summary>Update dependency types-pytz to v2023.4.0.20240130</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/types-pytz-2023.x`
  - Merge into: `main`
- Upgrade [types-pytz](https://togithub.com/python/typeshed) to
`2023.4.0.20240130`
- Upgrade [types-pytz](https://togithub.com/python/typeshed) to
`==2023.4.0.20240130`


</details>

<details>
<summary>Update docker/dockerfile Docker tag to v1.9</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/docker-dockerfile-1.x`
  - Merge into: `main`
  - Upgrade docker/dockerfile to `1.9`


</details>

<details>
<summary>Update tokio-prost monorepo to 0.13</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tokio-prost-monorepo`
  - Merge into: `main`
  - Upgrade [prost](https://togithub.com/tokio-rs/prost) to `0.13`
  - Upgrade [prost-build](https://togithub.com/tokio-rs/prost) to `0.13`
  - Upgrade [prost-types](https://togithub.com/tokio-rs/prost) to `0.13`


</details>

<details>
<summary>Update tsickert/discord-webhook action to v5.5.0</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tsickert-discord-webhook-5.x`
  - Merge into: `main`
- Upgrade
[tsickert/discord-webhook](https://togithub.com/tsickert/discord-webhook)
to `v5.5.0`


</details>

<details>
<summary>Update Rust crate async-fs to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-fs-2.x`
  - Merge into: `main`
  - Upgrade [async-fs](https://togithub.com/smol-rs/async-fs) to `2.0`


</details>

<details>
<summary>Update Rust crate async-recursion to v1</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/async-recursion-1.x`
  - Merge into: `main`
- Upgrade [async-recursion](https://togithub.com/dcchut/async-recursion)
to `1.0`


</details>

<details>
<summary>Update Rust crate dashmap to v6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/dashmap-6.x`
  - Merge into: `main`
  - Upgrade [dashmap](https://togithub.com/xacrimon/dashmap) to `6.0`
  - Upgrade [dashmap](https://togithub.com/xacrimon/dashmap) to `6.0.0`


</details>

<details>
<summary>Update Rust crate dirs to v5</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/dirs-5.x`
  - Merge into: `main`
  - Upgrade [dirs](https://togithub.com/soc/dirs-rs) to `5.0`


</details>

<details>
<summary>Update Rust crate fsevent-sys to v4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/fsevent-sys-4.x`
  - Merge into: `main`
- Upgrade [fsevent-sys](https://togithub.com/octplane/fsevent-rust) to
`4.0.0`


</details>

<details>
<summary>Update Rust crate futures-lite to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/futures-lite-2.x`
  - Merge into: `main`
- Upgrade [futures-lite](https://togithub.com/smol-rs/futures-lite) to
`2.0`


</details>

<details>
<summary>Update Rust crate indexmap to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/indexmap-2.x`
  - Merge into: `main`
- Upgrade [indexmap](https://togithub.com/indexmap-rs/indexmap) to
`2.0.0`


</details>

<details>
<summary>Update Rust crate indoc to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/indoc-2.x`
  - Merge into: `main`
  - Upgrade [indoc](https://togithub.com/dtolnay/indoc) to `2`


</details>

<details>
<summary>Update Rust crate ordered-float to v4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/ordered-float-4.x`
  - Merge into: `main`
- Upgrade [ordered-float](https://togithub.com/reem/rust-ordered-float)
to `4.0.0`


</details>

<details>
<summary>Update Rust crate rustc-hash to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/rustc-hash-2.x`
  - Merge into: `main`
- Upgrade [rustc-hash](https://togithub.com/rust-lang/rustc-hash) to
`2.0`


</details>

<details>
<summary>Update Rust crate shellexpand to v3</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/shellexpand-3.x`
  - Merge into: `main`
- Upgrade [shellexpand](https://gitlab.com/ijackson/rust-shellexpand) to
`3.0.0`


</details>

<details>
<summary>Update Rust crate similar to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/similar-2.x`
  - Merge into: `main`
  - Upgrade [similar](https://togithub.com/mitsuhiko/similar) to `2.0`


</details>

<details>
<summary>Update Rust crate smol to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/smol-2.x`
  - Merge into: `main`
  - Upgrade [smol](https://togithub.com/smol-rs/smol) to `2.0`


</details>

<details>
<summary>Update Rust crate syn to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/syn-2.x`
  - Merge into: `main`
  - Upgrade [syn](https://togithub.com/dtolnay/syn) to `2.0`
  - Upgrade [syn](https://togithub.com/dtolnay/syn) to `2.0.0`


</details>

<details>
<summary>Update Rust crate wasmtime to v23</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wasmtime-23.x`
  - Merge into: `main`
- Upgrade [wasmtime](https://togithub.com/bytecodealliance/wasmtime) to
`23.0.0`


</details>

<details>
<summary>Update Rust crate wasmtime-wasi to v23</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/wasmtime-wasi-23.x`
  - Merge into: `main`
- Upgrade
[wasmtime-wasi](https://togithub.com/bytecodealliance/wasmtime) to
`23.0.0`


</details>

<details>
<summary>Update actions/checkout action to v4</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/actions-checkout-4.x`
  - Merge into: `main`
- Upgrade [actions/checkout](https://togithub.com/actions/checkout) to
`v4`


</details>

<details>
<summary>Update dependency PyGithub to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/pygithub-2.x`
  - Merge into: `main`
- Upgrade [PyGithub](https://togithub.com/pygithub/pygithub) to `2.3.0`


</details>

<details>
<summary>Update dependency danger to v12</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/danger-12.x`
  - Merge into: `main`
  - Upgrade [danger](https://togithub.com/danger/danger-js) to `12.3.3`


</details>

<details>
<summary>Update dependency livekit/client-sdk-swift to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/livekit-client-sdk-swift-2.x`
  - Merge into: `main`
- Upgrade
[livekit/client-sdk-swift](https://togithub.com/livekit/client-sdk-swift)
to `2.0.12`


</details>

<details>
<summary>Update dependency pytz to v2024</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/pytz-2024.x`
  - Merge into: `main`
  - Upgrade pytz to `2024.1`
  - Upgrade pytz to `==2024.1`


</details>

<details>
<summary>Update dependency types-pytz to v2024</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/types-pytz-2024.x`
  - Merge into: `main`
- Upgrade [types-pytz](https://togithub.com/python/typeshed) to
`2024.1.0.20240417`
- Upgrade [types-pytz](https://togithub.com/python/typeshed) to
`==2024.1.0.20240417`


</details>

<details>
<summary>Update postgres Docker tag to v16</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/postgres-16.x`
  - Merge into: `main`
  - Upgrade postgres to `16`


</details>

<details>
<summary>Update softprops/action-gh-release action to v2</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/softprops-action-gh-release-2.x`
  - Merge into: `main`
- Upgrade
[softprops/action-gh-release](https://togithub.com/softprops/action-gh-release)
to `v2`


</details>

<details>
<summary>Update tsickert/discord-webhook action to v6</summary>

  - Schedule: ["after 3pm on Wednesday"]
  - Branch name: `renovate/tsickert-discord-webhook-6.x`
  - Merge into: `main`
- Upgrade
[tsickert/discord-webhook](https://togithub.com/tsickert/discord-webhook)
to `v6.0.0`


</details>



🚸 Branch creation will be limited to maximum 2 per hour, so it doesn't
swamp any CI resources or overwhelm the project. See docs for
`prhourlylimit` for details.


---

 Got questions? Check out Renovate's
[Docs](https://docs.renovatebot.com/), particularly the Getting Started
section.
If you need any further assistance then you can also [request help
here](https://togithub.com/renovatebot/renovate/discussions).


---

This PR was generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View the
[repository job
log](https://developer.mend.io/github/zed-industries/zed).


<!--renovate-config-hash:1752dbf5c31d5751ca59e575a43754358e807680713ab4daa60a32ec782882a0-->

Release Notes:

- N/A

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-07-24 22:32:58 -04:00
pantheraleo-7
b9570218b6 Remove !jupyter context for cmd-enter (ctrl-enter for linux) key binding (#15133)
Since zed has done away with `cmd-enter` binding for `repl::Run`
[#15026](https://github.com/zed-industries/zed/pull/15026), I think this
is no longer needed.

Release Notes:

- N/A
2024-07-24 19:02:24 -07:00
Marshall Bowers
fb4d77c008 Pin a specific version of typos in CI (#15128)
This PR makes it so we pin a specific version of `typos` in CI, rather
than just relying on whatever is already installed or what the latest
version is.

Release Notes:

- N/A
2024-07-24 19:03:07 -04:00
Max Brunsfeld
b14bb6bda4 Make git blame for SSH remote projects (#15106)
This also refactors the BufferStore + WorktreeStore interfaces to make
them cleaner, more fully encapsulating the RPC aspects of their
functionality.

Release Notes:

- N/A
2024-07-24 15:50:29 -07:00
Marshall Bowers
8501ae6a19 Make context and dropdown menus scrollable (#15127)
This PR makes context and dropdown menus scrollable, so that they don't
become totally unusable when they overflow the window.

Release Notes:

- N/A
2024-07-24 18:43:01 -04:00
Piotr Osiewicz
4e88a08ed4 chore: Some more dependency bumps (#15125)
Release Notes:

- N/A
2024-07-25 00:36:50 +02:00
Marshall Bowers
659f34bf21 settings_ui: Add UI and buffer font family controls (#15124)
This PR adds settings controls for changing the UI and buffer font
families.

Release Notes:

- N/A
2024-07-24 18:01:35 -04:00
Fernando Tagawa
001376fd6d cpp: Improve syntax highlighting (#13922)
* Added some missing operators, delimeters and keywords
* Highlight destructor, and operator overload as `@function`
* Moved `(field_identifier)` to the top, as it was highlighting methods
as `@property`

There are still some problems with something like `n1::n2::foo(...)`,
`foo` is not properly highlighted as a function

Release Notes:

- Improved C++ syntax highlighting
2024-07-25 00:55:21 +03:00
Marshall Bowers
298ca5ff1b Prefer .map for conditionals with else conditions (#15118)
This PR updates instances where we were using `.when_else` and
`.when_else_some` to use `.map` with a conditional inside.

This allows us to avoid reinventing Rust's syntax for conditionals and
(IMO) makes the code easier to read.

Release Notes:

- N/A
2024-07-24 17:09:07 -04:00
Kirill Bulatov
596ee58be8 Bump tree-sitter and related core language parser libraries (#14986)
Closes https://github.com/zed-industries/zed/issues/4565

To fix issues with code blocks' parsing in Markdown, a
tree-sitter-markdown library update is needed.
But `tree_sitter::language` is used in many places within core Zed,
which forced more library updates.

Release Notes:

- Updated tree-sitter parsers for core languages

---------

Co-authored-by: Max Brunsfeld <max@zed.dev>
Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
2024-07-24 23:38:21 +03:00
Kirill Bulatov
fd4a4127eb Use proper names for sorting path entries (#15116)
Closes https://github.com/zed-industries/zed/issues/12470

Release Notes:

- Fixed project panel not showing properly file entries for directories
with dots in their names
([#12470](https://github.com/zed-industries/zed/issues/12470))
2024-07-24 23:36:13 +03:00
Marshall Bowers
0297a42735 Use US English spelling of "behavior" and "customize" (#15117)
This PR fixes some instances that weren't using US English spellings of
"behavior" and "customize".

Release Notes:

- N/A
2024-07-24 16:36:01 -04:00
Vitaly Slobodin
9c9a0bd24f lsp: Check if "Goto Definition" supported before request (#15111)
This is related to #15023 where we have the running Rubocop LSP that
provides diagnostics and formatting capabilities. Rubocop LSP sends its
capabilities
back to Zed without support for "textDocument/definition" request, Zed
actually does not check that and sends a request to Rubocop that results
in the server error "Unsupported method: textDocument/definition".

The fix here is related to
https://github.com/zed-industries/zed/pull/14666

Release Notes:

- N/A
2024-07-24 23:28:23 +03:00
Marshall Bowers
740c444089 settings_ui: Add theme settings controls (#15115)
This PR adds settings controls for the theme settings.

Release Notes:

- N/A
2024-07-24 16:25:52 -04:00
Piotr Osiewicz
325e6b9fef editor: Improve performance of buffer/project search (#15109)
Fixes #15102
Release Notes:

- Improved performance of project and buffer search when there are many
matches.
2024-07-24 21:04:07 +02:00
Danilo Leal
65c63defcc Ensure quick action bar icon buttons are a square (#15092)
As the title says! Also decreased a bit the gap between them so that's
consistent with other similar icon button stacks. I wish they could be
bigger buttons but the icons would need to be refined further for that,
as each has been drawn with a different dimension/bounding-box. Maybe in
the near future :)

---

Release Notes:

- N/A
2024-07-24 15:40:55 -03:00
Marshall Bowers
274e56b086 settings_ui: Add UI and buffer font weight controls (#15104)
This PR adds settings controls for the UI and buffer font weight
settings.

It also does some work around grouping the settings into related
sections.

Release Notes:

- N/A
2024-07-24 14:09:13 -04:00
Tom Anderson
7fb906d774 vim: Prevent overflowing integer when pushing count digit (#15079)
Minor bug where the command count overflows when enough digits are
entered. This swaps out simple multiplication/addition for their checked
counter parts, falling back to the previous value in case of overflow.

Release Notes:

- N/A
2024-07-24 11:54:59 -06:00
Conrad Irwin
d107d22c2d Fix cmd-alt-g b for git blame (#15103)
Broken by #14942 as the matching Pane binding for toggle regex now takes
precedence. cmd-alt-x still works for that.

Release Notes:

- N/A
2024-07-24 11:44:39 -06:00
Kyle Kelley
23dac9cfce docs: Show how to use the percent format to denote cells for the Zed REPL (#15099)
Release Notes:

- N/A
2024-07-24 10:31:25 -07:00
Joseph T Lyons
777ddefa73 Fix contributor-scraping code 2024-07-24 12:34:42 -04:00
Joseph T Lyons
77a2f2490e v0.147.x dev 2024-07-24 12:08:26 -04:00
297 changed files with 7272 additions and 5232 deletions

View File

@@ -12,3 +12,7 @@ rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.aarch64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
# This cfg will reduce the size of `windows::core::Error` from 16 bytes to 4 bytes
[target.'cfg(target_os = "windows")']
rustflags = ["--cfg", "windows_slim_errors"]

View File

@@ -10,7 +10,7 @@ runs:
cargo install cargo-nextest
- name: Install Node
uses: actions/setup-node@v4
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
with:
node-version: "18"

View File

@@ -19,7 +19,7 @@ jobs:
- test
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
ref: ${{ github.event.inputs.branch }}
ssh-key: ${{ secrets.ZED_BOT_DEPLOY_KEY }}

View File

@@ -30,7 +30,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
fetch-depth: 0
@@ -90,7 +90,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -117,7 +117,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -137,17 +137,18 @@ jobs:
runs-on: hosted-windows-1
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
- name: Cache dependencies
uses: swatinem/rust-cache@v2
uses: swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: cargo clippy
run: ./script/clippy
# Windows can't run shell scripts, so we need to use `cargo xtask`.
run: cargo xtask clippy
- name: Build Zed
run: cargo build -p zed
@@ -170,12 +171,12 @@ jobs:
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps:
- name: Install Node
uses: actions/setup-node@v4
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
with:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
# We need to fetch more than one commit so that `script/draft-release-notes`
# is able to diff between the current and previous tag.
@@ -230,26 +231,26 @@ jobs:
mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
- name: Upload app bundle (universal) to workflow run if main branch or specific label
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
path: target/release/Zed.dmg
- name: Upload app bundle (aarch64) to workflow run if main branch or specific label
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
- name: Upload app bundle (x86_64) to workflow run if main branch or specific label
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
- uses: softprops/action-gh-release@v1
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
name: Upload app bundle to release
if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
with:
@@ -280,7 +281,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -318,14 +319,14 @@ jobs:
run: script/bundle-linux
- name: Upload Linux bundle to workflow run if main branch or specific label
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
path: target/release/zed-*.tar.gz
- name: Upload app bundle to release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with:
draft: true
prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
@@ -347,11 +348,11 @@ jobs:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
- name: "Setup jq"
uses: dcarbone/install-jq-action@v2
uses: dcarbone/install-jq-action@8867ddb4788346d7c22b72ea2e2ffe4d514c7bcb # v2
- name: Set up Clang
run: |
@@ -359,7 +360,7 @@ jobs:
sudo apt-get install -y llvm-10 clang-10 build-essential cmake pkg-config libasound2-dev libfontconfig-dev libwayland-dev libxkbcommon-x11-dev libssl-dev libsqlite3-dev libzstd-dev libvulkan1 libgit2-dev
echo "/usr/lib/llvm-10/bin" >> $GITHUB_PATH
- uses: rui314/setup-mold@v1
- uses: rui314/setup-mold@2e332a0b602c2fc65d2d3995941b1b29a5f554a0 # v1
with:
mold-version: 2.32.0
@@ -402,14 +403,14 @@ jobs:
run: script/bundle-linux
- name: Upload Linux bundle to workflow run if main branch or specific label
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
path: target/release/zed-*.tar.gz
- name: Upload app bundle to release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
with:
draft: true

View File

@@ -14,14 +14,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: pnpm/action-setup@v3
with:
version: 9
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
with:
node-version: "20"
cache: "pnpm"

View File

@@ -12,12 +12,12 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v2
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2
with:
mdbook-version: "0.4.37"
@@ -28,28 +28,28 @@ jobs:
mdbook build ./docs --dest-dir=../target/deploy/docs/
- name: Deploy Docs
uses: cloudflare/wrangler-action@v3
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy target/deploy --project-name=docs
- name: Deploy Install
uses: cloudflare/wrangler-action@v3
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh
- name: Deploy Docs Workers
uses: cloudflare/wrangler-action@v3
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy .cloudflare/docs-proxy/src/worker.js
- name: Deploy Install Workers
uses: cloudflare/wrangler-action@v3
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

View File

@@ -18,7 +18,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
fetch-depth: 0
@@ -37,7 +37,7 @@ jobs:
needs: style
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
fetch-depth: 0
@@ -71,7 +71,7 @@ jobs:
run: doctl registry login
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false

View File

@@ -16,12 +16,12 @@ jobs:
- ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
- name: Cache dependencies
uses: swatinem/rust-cache@v2
uses: swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}

View File

@@ -23,12 +23,12 @@ jobs:
- randomized-tests
steps:
- name: Install Node
uses: actions/setup-node@v4
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
with:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false

View File

@@ -16,7 +16,7 @@ jobs:
fi
echo "::set-output name=URL::$URL"
- name: Get content
uses: 2428392/gh-truncate-string-action@v1.3.0
uses: 2428392/gh-truncate-string-action@67b1b814955634208b103cff064be3cb1c7a19be # v1.3.0
id: get-content
with:
stringToTruncate: |
@@ -26,7 +26,7 @@ jobs:
maxLength: 2000
truncationSymbol: "..."
- name: Discord Webhook Action
uses: tsickert/discord-webhook@v5.3.0
uses: tsickert/discord-webhook@c840d45a03a323fbc3f7507ac7769dbd91bfb164 # v5.3.0
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
content: ${{ steps.get-content.outputs.string }}

View File

@@ -23,7 +23,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
fetch-depth: 0
@@ -44,7 +44,7 @@ jobs:
needs: style
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -69,12 +69,12 @@ jobs:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Install Node
uses: actions/setup-node@v4
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
with:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -108,7 +108,7 @@ jobs:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
@@ -141,12 +141,12 @@ jobs:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
clean: false
- name: "Setup jq"
uses: dcarbone/install-jq-action@v2
uses: dcarbone/install-jq-action@8867ddb4788346d7c22b72ea2e2ffe4d514c7bcb # v2
- name: Set up Clang
run: |
@@ -154,7 +154,7 @@ jobs:
sudo apt-get install -y llvm-10 clang-10 build-essential cmake pkg-config libasound2-dev libfontconfig-dev libwayland-dev libxkbcommon-x11-dev libssl-dev libsqlite3-dev libzstd-dev libvulkan1 libgit2-dev
echo "/usr/lib/llvm-10/bin" >> $GITHUB_PATH
- uses: rui314/setup-mold@v1
- uses: rui314/setup-mold@2e332a0b602c2fc65d2d3995941b1b29a5f554a0 # v1
with:
mold-version: 2.32.0

View File

@@ -8,8 +8,8 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5
with:
python-version: "3.11"
architecture: "x64"

View File

@@ -8,8 +8,8 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5
with:
python-version: "3.11"
architecture: "x64"

1282
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
[workspace]
resolver = "2"
members = [
"crates/activity_indicator",
"crates/anthropic",
"crates/assets",
"crates/assistant",
"crates/assistant_slash_command",
"crates/assistant_tooling",
"crates/audio",
"crates/auto_update",
"crates/breadcrumbs",
@@ -125,6 +125,10 @@ members = [
"crates/zed",
"crates/zed_actions",
#
# Extensions
#
"extensions/astro",
"extensions/clojure",
"extensions/csharp",
@@ -154,20 +158,25 @@ members = [
"extensions/vue",
"extensions/zig",
#
# Tooling
#
"tooling/xtask",
]
default-members = ["crates/zed"]
resolver = "2"
[workspace.dependencies]
#
# Workspace member crates
#
activity_indicator = { path = "crates/activity_indicator" }
aho-corasick = "1.1"
ai = { path = "crates/ai" }
anthropic = { path = "crates/anthropic" }
assets = { path = "crates/assets" }
assistant = { path = "crates/assistant" }
assistant_slash_command = { path = "crates/assistant_slash_command" }
assistant_tooling = { path = "crates/assistant_tooling" }
audio = { path = "crates/audio" }
auto_update = { path = "crates/auto_update" }
breadcrumbs = { path = "crates/breadcrumbs" }
@@ -240,6 +249,7 @@ project_symbols = { path = "crates/project_symbols" }
proto = { path = "crates/proto" }
quick_action_bar = { path = "crates/quick_action_bar" }
recent_projects = { path = "crates/recent_projects" }
refineable = { path = "crates/refineable" }
release_channel = { path = "crates/release_channel" }
remote = { path = "crates/remote" }
remote_server = { path = "crates/remote_server" }
@@ -285,39 +295,44 @@ worktree = { path = "crates/worktree" }
zed = { path = "crates/zed" }
zed_actions = { path = "crates/zed_actions" }
#
# External crates
#
aho-corasick = "1.1"
alacritty_terminal = "0.23"
any_vec = "0.13"
anyhow = "1.0.57"
any_vec = "0.14"
anyhow = "1.0.86"
ashpd = "0.9.1"
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
async-dispatcher = { version = "0.1" }
async-dispatcher = "0.1"
async-fs = "1.6"
async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553" }
async-recursion = "1.0.0"
async-tar = "0.4.2"
async-trait = "0.1"
async-tungstenite = { version = "0.16" }
async-tungstenite = "0.23"
async-watch = "0.3.1"
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
base64 = "0.13"
base64 = "0.22"
bitflags = "2.6.0"
blade-graphics = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" }
blade-macros = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" }
blade-util = { git = "https://github.com/zed-industries/blade", rev = "7e497c534d5d4a30c18d9eb182cf39eaf0aaa25e" }
cap-std = "3.0"
cargo_metadata = "0.18"
cargo_toml = "0.20"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.4", features = ["derive"] }
clickhouse = { version = "0.11.6" }
clickhouse = "0.11.6"
cocoa = "0.25"
core-foundation = { version = "0.9.3" }
core-foundation = "0.9.3"
core-foundation-sys = "0.8.6"
ctor = "0.2.6"
dashmap = "5.5.3"
dashmap = "6.0"
derive_more = "0.99.17"
dirs = "4.0"
emojis = "0.6.1"
env_logger = "0.10"
env_logger = "0.11"
exec = "0.3.1"
fork = "0.1.23"
futures = "0.3"
@@ -331,12 +346,13 @@ html5ever = "0.27.0"
ignore = "0.4.22"
image = "0.25.1"
indexmap = { version = "1.6.2", features = ["serde"] }
indoc = "1"
indoc = "2"
# We explicitly disable http2 support in isahc.
isahc = { version = "1.7.2", default-features = false, features = [
"text-decoding",
] }
itertools = "0.11.0"
jsonwebtoken = "9.3"
lazy_static = "1.4.0"
libc = "0.2"
linkify = "0.10.0"
@@ -358,14 +374,14 @@ prost-build = "0.9"
prost-types = "0.9"
pulldown-cmark = { version = "0.10.0", default-features = false }
rand = "0.8.5"
refineable = { path = "./crates/refineable" }
regex = "1.5"
repair_json = "0.1.0"
rsa = "0.9.6"
runtimelib = { version = "0.14", default-features = false, features = [
runtimelib = { version = "0.12", default-features = false, features = [
"async-dispatcher-runtime",
] }
rusqlite = { version = "0.29.0", features = ["blob", "array", "modern_sqlite"] }
rustc-demangle = "0.1.23"
rust-embed = { version = "8.4", features = ["include-exclude"] }
schemars = {version = "0.8", features = ["impl_json_schema"]}
semver = "1.0"
@@ -387,6 +403,7 @@ smallvec = { version = "1.6", features = ["union"] }
smol = "1.2"
strum = { version = "0.25.0", features = ["derive"] }
subtle = "2.5.0"
sys-locale = "0.3.1"
sysinfo = "0.30.7"
tempfile = "3.9.0"
thiserror = "1.0.29"
@@ -402,29 +419,28 @@ tiny_http = "0.8"
toml = "0.8"
tokio = { version = "1", features = ["full"] }
tower-http = "0.4.4"
tree-sitter = { version = "0.20", features = ["wasm"] }
tree-sitter-bash = "0.20.5"
tree-sitter-c = "0.20.1"
tree-sitter-cpp = "0.20.5"
tree-sitter-css = "0.20"
tree-sitter-elixir = "0.1.1"
tree-sitter = { version = "0.22", features = ["wasm"] }
tree-sitter-bash = "0.21"
tree-sitter-c = "0.21"
tree-sitter-cpp = "0.22"
tree-sitter-css = "0.21"
tree-sitter-elixir = "0.2"
tree-sitter-embedded-template = "0.20.0"
tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "b82ab803d887002a0af11f6ce63d72884580bf33" }
tree-sitter-gomod = "1.0.1"
tree-sitter-gowork = { git = "https://github.com/d1y/tree-sitter-go-work" }
rustc-demangle = "0.1.23"
tree-sitter-heex = { git = "https://github.com/phoenixframework/tree-sitter-heex", rev = "2e1348c3cf2c9323e87c2744796cf3f3868aa82a" }
tree-sitter-html = "0.19.0"
tree-sitter-jsdoc = { git = "https://github.com/tree-sitter/tree-sitter-jsdoc", rev = "6a6cf9e7341af32d8e2b2e24a37fbfebefc3dc55" }
tree-sitter-json = "0.20.2"
tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" }
tree-sitter-proto = { git = "https://github.com/rewinfrey/tree-sitter-proto", rev = "36d54f288aee112f13a67b550ad32634d0c2cb52" }
tree-sitter-python = "0.20.2"
tree-sitter-regex = "0.20.0"
tree-sitter-ruby = "0.20.0"
tree-sitter-rust = "0.20.3"
tree-sitter-typescript = "0.20.5"
tree-sitter-yaml = "0.0.1"
tree-sitter-go = "0.21"
tree-sitter-go-mod = { git = "https://github.com/SomeoneToIgnore/tree-sitter-go-mod", rev = "8c1f54f12bb4c846336b634bc817645d6f35d641", package = "tree-sitter-gomod" }
tree-sitter-gowork = { git = "https://github.com/d1y/tree-sitter-go-work", rev = "dcbabff454703c3a4bc98a23cf8778d4be46fd22" }
tree-sitter-heex = { git = "https://github.com/phoenixframework/tree-sitter-heex", rev = "6dd0303acf7138dd2b9b432a229e16539581c701" }
tree-sitter-html = "0.20"
tree-sitter-jsdoc = "0.21"
tree-sitter-json = "0.21"
tree-sitter-md = { git = "https://github.com/zed-industries/tree-sitter-markdown", rev = "e3855e37f8f2c71aa7513c18a9c95fb7461b1b10" }
protols-tree-sitter-proto = "0.2"
tree-sitter-python = "0.21"
tree-sitter-regex = "0.21"
tree-sitter-ruby = "0.21"
tree-sitter-rust = "0.21"
tree-sitter-typescript = "0.21"
tree-sitter-yaml = "0.6"
unindent = "0.1.7"
unicase = "2.6"
unicode-segmentation = "1.10"
@@ -432,20 +448,19 @@ url = "2.2"
uuid = { version = "1.1.2", features = ["v4", "v5", "serde"] }
wasmparser = "0.201"
wasm-encoder = "0.201"
wasmtime = { version = "19.0.2", default-features = false, features = [
wasmtime = { version = "21.0.1", default-features = false, features = [
"async",
"demangle",
"runtime",
"cranelift",
"component-model",
] }
wasmtime-wasi = "19.0.2"
wasmtime-wasi = "21.0.1"
which = "6.0.0"
wit-component = "0.201"
sys-locale = "0.3.1"
[workspace.dependencies.windows]
version = "0.57"
version = "0.58"
features = [
"implement",
"Foundation_Numerics",
@@ -465,7 +480,6 @@ features = [
"Win32_Security",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",
"Win32_System_LibraryLoader",
"Win32_System_Com",
"Win32_System_Com_StructuredStorage",
"Win32_System_DataExchange",
@@ -485,7 +499,8 @@ features = [
]
[patch.crates-io]
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "7b4894ba2ae81b988846676f54c0988d4027ef4f" }
# Patch Tree-sitter for updated wasmtime.
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "7f4a57817d58a2f134fe863674acad6bbf007228" }
[profile.dev]
split-debuginfo = "unpacked"
@@ -538,13 +553,6 @@ single_range_in_vec_init = "allow"
style = { level = "allow", priority = -1 }
# Individual rules that have violations in the codebase:
almost_complete_range = "allow"
arc_with_non_send_sync = "allow"
borrowed_box = "allow"
let_underscore_future = "allow"
map_entry = "allow"
non_canonical_partial_ord_impl = "allow"
reversed_empty_ranges = "allow"
type_complexity = "allow"
[workspace.metadata.cargo-machete]

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.2
FROM rust:1.79-bookworm as builder
FROM rust:1.80-bookworm as builder
WORKDIR app
COPY . .

1
assets/icons/eye.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-eye"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>

After

Width:  |  Height:  |  Size: 358 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-code"><path d="M10 12.5 8 15l2 2.5"/><path d="m14 12.5 2 2.5-2 2.5"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/></svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-text"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>

After

Width:  |  Height:  |  Size: 384 B

View File

@@ -0,0 +1,6 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 4H8" stroke="black" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 10L11 10" stroke="black" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="4" cy="10" r="1.875" stroke="black" stroke-width="1.75"/>
<circle cx="10" cy="4" r="1.875" stroke="black" stroke-width="1.75"/>
</svg>

After

Width:  |  Height:  |  Size: 450 B

View File

@@ -105,6 +105,7 @@
"bindings": {
"enter": "editor::Newline",
"shift-enter": "editor::Newline",
"ctrl-enter": "editor::NewlineAbove",
"ctrl-shift-enter": "editor::NewlineBelow",
"alt-z": "editor::ToggleSoftWrap",
"ctrl-f": "buffer_search::Deploy",
@@ -115,12 +116,6 @@
"ctrl-alt-e": "editor::SelectEnclosingSymbol"
}
},
{
"context": "Editor && mode == full && !jupyter",
"bindings": {
"ctrl-enter": "editor::NewlineAbove"
}
},
{
"context": "Editor && mode == full && inline_completion",
"bindings": {
@@ -249,6 +244,13 @@
"ctrl-alt-shift-x": "search::ToggleRegex"
}
},
{
"context": "Terminal",
"bindings": {
"ctrl-w": ["terminal::SendKeystroke", "ctrl-w"],
"ctrl-e": ["terminal::SendKeystroke", "ctrl-e"]
}
},
// Bindings from VS Code
{
"context": "Editor",
@@ -458,16 +460,12 @@
{
"bindings": {
"ctrl-alt-shift-f": "workspace::FollowNextCollaborator",
// TODO: Move this to a dock open action
"ctrl-shift-c": "collab_panel::ToggleFocus",
"ctrl-alt-i": "zed::DebugElements",
"ctrl-:": "editor::ToggleInlayHints"
}
},
{
"context": "!Terminal",
"bindings": {
"ctrl-shift-c": "collab_panel::ToggleFocus"
}
},
{
"context": "Editor && mode == full",
"bindings": {
@@ -601,14 +599,12 @@
"context": "Terminal",
"bindings": {
"ctrl-alt-space": "terminal::ShowCharacterPalette",
"ctrl-shift-c": "terminal::Copy",
"shift-ctrl-c": "terminal::Copy",
"ctrl-insert": "terminal::Copy",
// "ctrl-a": "editor::SelectAll", // conflicts with readline
"ctrl-shift-v": "terminal::Paste",
"ctrl-a": "editor::SelectAll",
"shift-ctrl-v": "terminal::Paste",
"shift-insert": "terminal::Paste",
"ctrl-enter": "assistant::InlineAssist",
"ctrl-w": ["terminal::SendKeystroke", "ctrl-w"],
"ctrl-e": ["terminal::SendKeystroke", "ctrl-e"],
"up": ["terminal::SendKeystroke", "up"],
"pageup": ["terminal::SendKeystroke", "pageup"],
"down": ["terminal::SendKeystroke", "down"],

View File

@@ -135,6 +135,7 @@
"bindings": {
"enter": "editor::Newline",
"shift-enter": "editor::Newline",
"cmd-enter": "editor::NewlineBelow",
"cmd-shift-enter": "editor::NewlineAbove",
"alt-z": "editor::ToggleSoftWrap",
"cmd-f": "buffer_search::Deploy",
@@ -146,12 +147,6 @@
"cmd-alt-e": "editor::SelectEnclosingSymbol"
}
},
{
"context": "Editor && mode == full && !jupyter",
"bindings": {
"cmd-enter": "editor::NewlineBelow"
}
},
{
"context": "Editor && mode == full && inline_completion",
"bindings": {
@@ -298,7 +293,6 @@
"alt-cmd-c": "search::ToggleCaseSensitive",
"alt-cmd-w": "search::ToggleWholeWord",
"alt-cmd-f": "project_search::ToggleFilters",
"alt-cmd-g": "search::ToggleRegex",
"alt-cmd-x": "search::ToggleRegex"
}
},

View File

@@ -26,6 +26,9 @@
},
// The name of a font to use for rendering text in the editor
"buffer_font_family": "Zed Plex Mono",
// Set the buffer text's font fallbacks, this will be merged with
// the platform's default fallbacks.
"buffer_font_fallbacks": [],
// The OpenType features to enable for text in the editor.
"buffer_font_features": {
// Disable ligatures:
@@ -47,8 +50,11 @@
// },
"buffer_line_height": "comfortable",
// The name of a font to use for rendering text in the UI
// (On macOS) You can set this to ".SystemUIFont" to use the system font
// You can set this to ".SystemUIFont" to use the system font
"ui_font_family": "Zed Plex Sans",
// Set the UI's font fallbacks, this will be merged with the platform's
// default font fallbacks.
"ui_font_fallbacks": [],
// The OpenType features to enable for text in the UI
"ui_font_features": {
// Disable ligatures:
@@ -312,7 +318,7 @@
"auto_reveal_entries": true,
// Whether to fold directories automatically and show compact folders
// (e.g. "a/b/c" ) when a directory has only one subdirectory inside.
"auto_fold_dirs": false,
"auto_fold_dirs": true,
/// Scrollbar-related settings
"scrollbar": {
/// When to show the scrollbar in the project panel.
@@ -675,6 +681,10 @@
// Set the terminal's font family. If this option is not included,
// the terminal will default to matching the buffer's font family.
// "font_family": "Zed Plex Mono",
// Set the terminal's font fallbacks. If this option is not included,
// the terminal will default to matching the buffer's font fallbacks.
// This will be merged with the platform's default font fallbacks
// "font_fallbacks": ["FiraCode Nerd Fonts"],
// Sets the maximum number of lines in the terminal's scrollback buffer.
// Default: 10_000, maximum: 100_000 (all bigger values set will be treated as 100_000), 0 disables the scrolling.
// Existing terminals will not pick up this change until they are recreated.
@@ -965,5 +975,21 @@
// {
// "W": "workspace::Save"
// }
"command_aliases": {}
"command_aliases": {},
// ssh_connections is an array of ssh connections.
// By default this setting is null, which disables the direct ssh connection support.
// You can configure these from `project: Open Remote` in the command palette.
// Zed's ssh support will pull configuration from your ~/.ssh too.
// Examples:
// [
// {
// "host": "example-box",
// "projects": [
// {
// "paths": ["/home/user/code/zed"]
// }
// ]
// }
// ]
"ssh_connections": null
}

View File

@@ -1,5 +1,5 @@
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://zed.dev/docs/configuring-zed#folder-specific-settings
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{}

View File

@@ -100,21 +100,13 @@ impl From<Role> for String {
#[derive(Debug, Serialize)]
pub struct Request {
#[serde(serialize_with = "serialize_request_model")]
pub model: Model,
pub model: String,
pub messages: Vec<RequestMessage>,
pub stream: bool,
pub system: String,
pub max_tokens: u32,
}
fn serialize_request_model<S>(model: &Model, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&model.id())
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct RequestMessage {
pub role: Role,

View File

@@ -38,7 +38,7 @@ Considering these aspects will ensure our conversation view design is optimized
@nate> 2 feels like it isn't important at the moment, we can explore that later. Let's start with 4, which I think will lead us to discussion 3 and 5.
#zed share your thoughts on the points we need to consider to design a layout and visualization for a conversation view between you (#zed) and multuple peoople, or between multiple people and multiple bots (you and other bots).
#zed share your thoughts on the points we need to consider to design a layout and visualization for a conversation view between you (#zed) and multiple people, or between multiple people and multiple bots (you and other bots).
@nathan> Agreed. I'm interested in threading I think more than anything. Or 4 yeah. I think we need to scope the threading conversation. Also, asking #zed to propose the solution... not sure it will be that effective but it's worth a try...

View File

@@ -532,7 +532,21 @@ impl EditOperation {
.path_candidates
.iter()
.find(|item| item.string == symbol)
.context("symbol not found")?;
.with_context(|| {
format!(
"symbol {:?} not found in path {:?}.\ncandidates: {:?}.\nparse status: {:?}. text:\n{}",
symbol,
path,
outline
.path_candidates
.iter()
.map(|candidate| &candidate.string)
.collect::<Vec<_>>(),
*parse_status.borrow(),
buffer.read_with(&cx, |buffer, _| buffer.text()).unwrap_or_else(|_| "error".to_string())
)
})?;
buffer.update(&mut cx, |buffer, _| {
let outline_item = &outline.items[candidate.id];
let symbol_range = outline_item.range.to_point(buffer);
@@ -1123,16 +1137,17 @@ impl Context {
.timer(Duration::from_millis(200))
.await;
let token_count = cx
.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})?
.await?;
if let Some(token_count) = cx.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})? {
let token_count = token_count.await?;
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify()
})?;
}
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify()
})?;
anyhow::Ok(())
}
.log_err()

View File

@@ -1420,27 +1420,34 @@ impl Render for PromptEditor {
.w(gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0))
.justify_center()
.gap_2()
.child(ModelSelector::new(
self.fs.clone(),
IconButton::new("context", IconName::Settings)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.tooltip(move |cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelCompletionProvider::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
cx,
)
}),
))
.child(
ModelSelector::new(
self.fs.clone(),
IconButton::new("context", IconName::SlidersAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.tooltip(move |cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelCompletionProvider::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
cx,
)
}),
)
.with_info_text(
"Inline edits use context\n\
from the currently selected\n\
assistant panel tab.",
),
)
.children(
if let CodegenStatus::Error(error) = &self.codegen.read(cx).status {
let error_message = SharedString::from(error.to_string());
@@ -1628,15 +1635,18 @@ impl PromptEditor {
})?
.await?;
let token_count = cx
.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})?
.await?;
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify();
})
if let Some(token_count) = cx.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})? {
let token_count = token_count.await?;
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify();
})
} else {
Ok(())
}
})
}
@@ -1825,6 +1835,7 @@ impl PromptEditor {
},
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(1.3),

View File

@@ -2,6 +2,7 @@ use std::sync::Arc;
use crate::{assistant_settings::AssistantSettings, LanguageModelCompletionProvider};
use fs::Fs;
use gpui::SharedString;
use language_model::LanguageModelRegistry;
use settings::update_settings_file;
use ui::{prelude::*, ContextMenu, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
@@ -11,6 +12,7 @@ pub struct ModelSelector<T: PopoverTrigger> {
handle: Option<PopoverMenuHandle<ContextMenu>>,
fs: Arc<dyn Fs>,
trigger: T,
info_text: Option<SharedString>,
}
impl<T: PopoverTrigger> ModelSelector<T> {
@@ -19,6 +21,7 @@ impl<T: PopoverTrigger> ModelSelector<T> {
handle: None,
fs,
trigger,
info_text: None,
}
}
@@ -26,6 +29,11 @@ impl<T: PopoverTrigger> ModelSelector<T> {
self.handle = Some(handle);
self
}
pub fn with_info_text(mut self, text: impl Into<SharedString>) -> Self {
self.info_text = Some(text.into());
self
}
}
impl<T: PopoverTrigger> RenderOnce for ModelSelector<T> {
@@ -35,8 +43,20 @@ impl<T: PopoverTrigger> RenderOnce for ModelSelector<T> {
menu = menu.with_handle(handle);
}
let info_text = self.info_text.clone();
menu.menu(move |cx| {
ContextMenu::build(cx, |mut menu, cx| {
if let Some(info_text) = info_text.clone() {
menu = menu
.custom_row(move |_cx| {
Label::new(info_text.clone())
.color(Color::Muted)
.into_any_element()
})
.separator();
}
for (index, provider) in LanguageModelRegistry::global(cx)
.read(cx)
.providers()

View File

@@ -734,26 +734,29 @@ impl PromptLibrary {
const DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
cx.background_executor().timer(DEBOUNCE_TIMEOUT).await;
let token_count = cx
.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(
LanguageModelRequest {
messages: vec![LanguageModelRequestMessage {
role: Role::System,
content: body.to_string(),
}],
stop: Vec::new(),
temperature: 1.,
},
cx,
)
})?
.await?;
this.update(&mut cx, |this, cx| {
let prompt_editor = this.prompt_editors.get_mut(&prompt_id).unwrap();
prompt_editor.token_count = Some(token_count);
cx.notify();
})
if let Some(token_count) = cx.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(
LanguageModelRequest {
messages: vec![LanguageModelRequestMessage {
role: Role::System,
content: body.to_string(),
}],
stop: Vec::new(),
temperature: 1.,
},
cx,
)
})? {
let token_count = token_count.await?;
this.update(&mut cx, |this, cx| {
let prompt_editor = this.prompt_editors.get_mut(&prompt_id).unwrap();
prompt_editor.token_count = Some(token_count);
cx.notify();
})
} else {
Ok(())
}
}
.log_err()
});

View File

@@ -33,7 +33,7 @@ impl DiagnosticsSlashCommand {
if query.is_empty() {
let workspace = workspace.read(cx);
let entries = workspace.recent_navigation_history(Some(10), cx);
let path_prefix: Arc<str> = "".into();
let path_prefix: Arc<str> = Arc::default();
Task::ready(
entries
.into_iter()

View File

@@ -219,7 +219,7 @@ impl SlashCommand for DocsSlashCommand {
if index {
// We don't need to hold onto this task, as the `IndexedDocsStore` will hold it
// until it completes.
let _ = store.clone().index(package.as_str().into());
drop(store.clone().index(package.as_str().into()));
}
let items = store.search(package).await;

View File

@@ -29,7 +29,7 @@ impl FileSlashCommand {
let workspace = workspace.read(cx);
let project = workspace.project().read(cx);
let entries = workspace.recent_navigation_history(Some(10), cx);
let path_prefix: Arc<str> = "".into();
let path_prefix: Arc<str> = Arc::default();
Task::ready(
entries
.into_iter()

View File

@@ -707,15 +707,18 @@ impl PromptEditor {
inline_assistant.request_for_inline_assist(assist_id, cx)
})??;
let token_count = cx
.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})?
.await?;
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify();
})
if let Some(token_count) = cx.update(|cx| {
LanguageModelCompletionProvider::read_global(cx).count_tokens(request, cx)
})? {
let token_count = token_count.await?;
this.update(&mut cx, |this, cx| {
this.token_count = Some(token_count);
cx.notify();
})
} else {
Ok(())
}
})
}
@@ -906,6 +909,7 @@ impl PromptEditor {
},
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(1.3),
@@ -943,7 +947,7 @@ impl TerminalTransaction {
}
pub fn push(&mut self, hunk: String, cx: &mut AppContext) {
// Ensure that the assistant cannot accidently execute commands that are streamed into the terminal
// Ensure that the assistant cannot accidentally execute commands that are streamed into the terminal
let input = hunk.replace(CARRIAGE_RETURN, " ");
self.terminal
.update(cx, |terminal, _| terminal.input(input));

View File

@@ -1,33 +0,0 @@
[package]
name = "assistant_tooling"
version = "0.1.0"
edition = "2021"
publish = false
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/assistant_tooling.rs"
[dependencies]
anyhow.workspace = true
collections.workspace = true
futures.workspace = true
gpui.workspace = true
log.workspace = true
project.workspace = true
repair_json.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
sum_tree.workspace = true
ui.workspace = true
util.workspace = true
[dev-dependencies]
gpui = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
unindent.workspace = true

View File

@@ -1 +0,0 @@
../../LICENSE-GPL

View File

@@ -1,85 +0,0 @@
# Assistant Tooling
Bringing Language Model tool calling to GPUI.
This unlocks:
- **Structured Extraction** of model responses
- **Validation** of model inputs
- **Execution** of chosen tools
## Overview
Language Models can produce structured outputs that are perfect for calling functions. The most famous of these is OpenAI's tool calling. When making a chat completion you can pass a list of tools available to the model. The model will choose `0..n` tools to help them complete a user's task. It's up to _you_ to create the tools that the model can call.
> **User**: "Hey I need help with implementing a collapsible panel in GPUI"
>
> **Assistant**: "Sure, I can help with that. Let me see what I can find."
>
> `tool_calls: ["name": "query_codebase", arguments: "{ 'query': 'GPUI collapsible panel' }"]`
>
> `result: "['crates/gpui/src/panel.rs:12: impl Panel { ... }', 'crates/gpui/src/panel.rs:20: impl Panel { ... }']"`
>
> **Assistant**: "Here are some excerpts from the GPUI codebase that might help you."
This library is designed to facilitate this interaction mode by allowing you to go from `struct` to `tool` with two simple traits, `LanguageModelTool` and `ToolView`.
## Using the Tool Registry
```rust
let mut tool_registry = ToolRegistry::new();
tool_registry
.register(WeatherTool { api_client },
})
.unwrap(); // You can only register one tool per name
let completion = cx.update(|cx| {
CompletionProvider::get(cx).complete(
model_name,
messages,
Vec::new(),
1.0,
// The definitions get passed directly to OpenAI when you want
// the model to be able to call your tool
tool_registry.definitions(),
)
});
let mut stream = completion?.await?;
let mut message = AssistantMessage::new();
while let Some(delta) = stream.next().await {
// As messages stream in, you'll get both assistant content
if let Some(content) = &delta.content {
message
.body
.update(cx, |message, cx| message.append(&content, cx));
}
// And tool calls!
for tool_call_delta in delta.tool_calls {
let index = tool_call_delta.index as usize;
if index >= message.tool_calls.len() {
message.tool_calls.resize_with(index + 1, Default::default);
}
let tool_call = &mut message.tool_calls[index];
// Build up an ID
if let Some(id) = &tool_call_delta.id {
tool_call.id.push_str(id);
}
tool_registry.update_tool_call(
tool_call,
tool_call_delta.name.as_deref(),
tool_call_delta.arguments.as_deref(),
cx,
);
}
}
```
Once the stream of tokens is complete, you can exexute the tool call by calling `tool_registry.execute_tool_call(tool_call, cx)`, which returns a `Task<Result<()>>`.
As the tokens stream in and tool calls are executed, your `ToolView` will get updates. Render each tool call by passing that `tool_call` in to `tool_registry.render_tool_call(tool_call, cx)`. The final message for the model can be pulled by calling `self.tool_registry.content_for_tool_call( tool_call, &mut project_context, cx, )`.

View File

@@ -1,13 +0,0 @@
mod attachment_registry;
mod project_context;
mod tool_registry;
pub use attachment_registry::{
AttachmentOutput, AttachmentRegistry, LanguageModelAttachment, SavedUserAttachment,
UserAttachment,
};
pub use project_context::ProjectContext;
pub use tool_registry::{
LanguageModelTool, SavedToolFunctionCall, ToolFunctionCall, ToolFunctionDefinition,
ToolRegistry, ToolView,
};

View File

@@ -1,234 +0,0 @@
use crate::ProjectContext;
use anyhow::{anyhow, Result};
use collections::HashMap;
use futures::future::join_all;
use gpui::{AnyView, Render, Task, View, WindowContext};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::value::RawValue;
use std::{
any::TypeId,
sync::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc,
},
};
use util::ResultExt as _;
pub struct AttachmentRegistry {
registered_attachments: HashMap<TypeId, RegisteredAttachment>,
}
pub trait AttachmentOutput {
fn generate(&self, project: &mut ProjectContext, cx: &mut WindowContext) -> String;
}
pub trait LanguageModelAttachment {
type Output: DeserializeOwned + Serialize + 'static;
type View: Render + AttachmentOutput;
fn name(&self) -> Arc<str>;
fn run(&self, cx: &mut WindowContext) -> Task<Result<Self::Output>>;
fn view(&self, output: Result<Self::Output>, cx: &mut WindowContext) -> View<Self::View>;
}
/// A collected attachment from running an attachment tool
pub struct UserAttachment {
pub view: AnyView,
name: Arc<str>,
serialized_output: Result<Box<RawValue>, String>,
generate_fn: fn(AnyView, &mut ProjectContext, cx: &mut WindowContext) -> String,
}
#[derive(Serialize, Deserialize)]
pub struct SavedUserAttachment {
name: Arc<str>,
serialized_output: Result<Box<RawValue>, String>,
}
/// Internal representation of an attachment tool to allow us to treat them dynamically
struct RegisteredAttachment {
name: Arc<str>,
enabled: AtomicBool,
call: Box<dyn Fn(&mut WindowContext) -> Task<Result<UserAttachment>>>,
deserialize: Box<dyn Fn(&SavedUserAttachment, &mut WindowContext) -> Result<UserAttachment>>,
}
impl AttachmentRegistry {
pub fn new() -> Self {
Self {
registered_attachments: HashMap::default(),
}
}
pub fn register<A: LanguageModelAttachment + 'static>(&mut self, attachment: A) {
let attachment = Arc::new(attachment);
let call = Box::new({
let attachment = attachment.clone();
move |cx: &mut WindowContext| {
let result = attachment.run(cx);
let attachment = attachment.clone();
cx.spawn(move |mut cx| async move {
let result: Result<A::Output> = result.await;
let serialized_output =
result
.as_ref()
.map_err(ToString::to_string)
.and_then(|output| {
Ok(RawValue::from_string(
serde_json::to_string(output).map_err(|e| e.to_string())?,
)
.unwrap())
});
let view = cx.update(|cx| attachment.view(result, cx))?;
Ok(UserAttachment {
name: attachment.name(),
view: view.into(),
generate_fn: generate::<A>,
serialized_output,
})
})
}
});
let deserialize = Box::new({
let attachment = attachment.clone();
move |saved_attachment: &SavedUserAttachment, cx: &mut WindowContext| {
let serialized_output = saved_attachment.serialized_output.clone();
let output = match &serialized_output {
Ok(serialized_output) => {
Ok(serde_json::from_str::<A::Output>(serialized_output.get())?)
}
Err(error) => Err(anyhow!("{error}")),
};
let view = attachment.view(output, cx).into();
Ok(UserAttachment {
name: saved_attachment.name.clone(),
view,
serialized_output,
generate_fn: generate::<A>,
})
}
});
self.registered_attachments.insert(
TypeId::of::<A>(),
RegisteredAttachment {
name: attachment.name(),
call,
deserialize,
enabled: AtomicBool::new(true),
},
);
return;
fn generate<T: LanguageModelAttachment>(
view: AnyView,
project: &mut ProjectContext,
cx: &mut WindowContext,
) -> String {
view.downcast::<T::View>()
.unwrap()
.update(cx, |view, cx| T::View::generate(view, project, cx))
}
}
pub fn set_attachment_tool_enabled<A: LanguageModelAttachment + 'static>(
&self,
is_enabled: bool,
) {
if let Some(attachment) = self.registered_attachments.get(&TypeId::of::<A>()) {
attachment.enabled.store(is_enabled, SeqCst);
}
}
pub fn is_attachment_tool_enabled<A: LanguageModelAttachment + 'static>(&self) -> bool {
if let Some(attachment) = self.registered_attachments.get(&TypeId::of::<A>()) {
attachment.enabled.load(SeqCst)
} else {
false
}
}
pub fn call<A: LanguageModelAttachment + 'static>(
&self,
cx: &mut WindowContext,
) -> Task<Result<UserAttachment>> {
let Some(attachment) = self.registered_attachments.get(&TypeId::of::<A>()) else {
return Task::ready(Err(anyhow!("no attachment tool")));
};
(attachment.call)(cx)
}
pub fn call_all_attachment_tools(
self: Arc<Self>,
cx: &mut WindowContext<'_>,
) -> Task<Result<Vec<UserAttachment>>> {
let this = self.clone();
cx.spawn(|mut cx| async move {
let attachment_tasks = cx.update(|cx| {
let mut tasks = Vec::new();
for attachment in this
.registered_attachments
.values()
.filter(|attachment| attachment.enabled.load(SeqCst))
{
tasks.push((attachment.call)(cx))
}
tasks
})?;
let attachments = join_all(attachment_tasks.into_iter()).await;
Ok(attachments
.into_iter()
.filter_map(|attachment| attachment.log_err())
.collect())
})
}
pub fn serialize_user_attachment(
&self,
user_attachment: &UserAttachment,
) -> SavedUserAttachment {
SavedUserAttachment {
name: user_attachment.name.clone(),
serialized_output: user_attachment.serialized_output.clone(),
}
}
pub fn deserialize_user_attachment(
&self,
saved_user_attachment: SavedUserAttachment,
cx: &mut WindowContext,
) -> Result<UserAttachment> {
if let Some(registered_attachment) = self
.registered_attachments
.values()
.find(|attachment| attachment.name == saved_user_attachment.name)
{
(registered_attachment.deserialize)(&saved_user_attachment, cx)
} else {
Err(anyhow!(
"no attachment tool for name {}",
saved_user_attachment.name
))
}
}
}
impl UserAttachment {
pub fn generate(&self, output: &mut ProjectContext, cx: &mut WindowContext) -> Option<String> {
let result = (self.generate_fn)(self.view.clone(), output, cx);
if result.is_empty() {
None
} else {
Some(result)
}
}
}

View File

@@ -1,296 +0,0 @@
use anyhow::{anyhow, Result};
use gpui::{AppContext, Model, Task, WeakModel};
use project::{Fs, Project, ProjectPath, Worktree};
use std::{cmp::Ordering, fmt::Write as _, ops::Range, sync::Arc};
use sum_tree::TreeMap;
pub struct ProjectContext {
files: TreeMap<ProjectPath, PathState>,
project: WeakModel<Project>,
fs: Arc<dyn Fs>,
}
#[derive(Debug, Clone)]
enum PathState {
PathOnly,
EntireFile,
Excerpts { ranges: Vec<Range<usize>> },
}
impl ProjectContext {
pub fn new(project: WeakModel<Project>, fs: Arc<dyn Fs>) -> Self {
Self {
files: TreeMap::default(),
fs,
project,
}
}
pub fn add_path(&mut self, project_path: ProjectPath) {
if self.files.get(&project_path).is_none() {
self.files.insert(project_path, PathState::PathOnly);
}
}
pub fn add_excerpts(&mut self, project_path: ProjectPath, new_ranges: &[Range<usize>]) {
let previous_state = self
.files
.get(&project_path)
.unwrap_or(&PathState::PathOnly);
let mut ranges = match previous_state {
PathState::EntireFile => return,
PathState::PathOnly => Vec::new(),
PathState::Excerpts { ranges } => ranges.to_vec(),
};
for new_range in new_ranges {
let ix = ranges.binary_search_by(|probe| {
if probe.end < new_range.start {
Ordering::Less
} else if probe.start > new_range.end {
Ordering::Greater
} else {
Ordering::Equal
}
});
match ix {
Ok(mut ix) => {
let existing = &mut ranges[ix];
existing.start = existing.start.min(new_range.start);
existing.end = existing.end.max(new_range.end);
while ix + 1 < ranges.len() && ranges[ix + 1].start <= ranges[ix].end {
ranges[ix].end = ranges[ix].end.max(ranges[ix + 1].end);
ranges.remove(ix + 1);
}
while ix > 0 && ranges[ix - 1].end >= ranges[ix].start {
ranges[ix].start = ranges[ix].start.min(ranges[ix - 1].start);
ranges.remove(ix - 1);
ix -= 1;
}
}
Err(ix) => {
ranges.insert(ix, new_range.clone());
}
}
}
self.files
.insert(project_path, PathState::Excerpts { ranges });
}
pub fn add_file(&mut self, project_path: ProjectPath) {
self.files.insert(project_path, PathState::EntireFile);
}
pub fn generate_system_message(&self, cx: &mut AppContext) -> Task<Result<String>> {
let project = self
.project
.upgrade()
.ok_or_else(|| anyhow!("project dropped"));
let files = self.files.clone();
let fs = self.fs.clone();
cx.spawn(|cx| async move {
let project = project?;
let mut result = "project structure:\n".to_string();
let mut last_worktree: Option<Model<Worktree>> = None;
for (project_path, path_state) in files.iter() {
if let Some(worktree) = &last_worktree {
if worktree.read_with(&cx, |tree, _| tree.id())? != project_path.worktree_id {
last_worktree = None;
}
}
let worktree;
if let Some(last_worktree) = &last_worktree {
worktree = last_worktree.clone();
} else if let Some(tree) = project.read_with(&cx, |project, cx| {
project.worktree_for_id(project_path.worktree_id, cx)
})? {
worktree = tree;
last_worktree = Some(worktree.clone());
let worktree_name =
worktree.read_with(&cx, |tree, _cx| tree.root_name().to_string())?;
writeln!(&mut result, "# {}", worktree_name).unwrap();
} else {
continue;
}
let worktree_abs_path = worktree.read_with(&cx, |tree, _cx| tree.abs_path())?;
let path = &project_path.path;
writeln!(&mut result, "## {}", path.display()).unwrap();
match path_state {
PathState::PathOnly => {}
PathState::EntireFile => {
let text = fs.load(&worktree_abs_path.join(&path)).await?;
writeln!(&mut result, "~~~\n{text}\n~~~").unwrap();
}
PathState::Excerpts { ranges } => {
let text = fs.load(&worktree_abs_path.join(&path)).await?;
writeln!(&mut result, "~~~").unwrap();
// Assumption: ranges are in order, not overlapping
let mut prev_range_end = 0;
for range in ranges {
if range.start > prev_range_end {
writeln!(&mut result, "...").unwrap();
prev_range_end = range.end;
}
let mut start = range.start;
let mut end = range.end.min(text.len());
while !text.is_char_boundary(start) {
start += 1;
}
while !text.is_char_boundary(end) {
end -= 1;
}
result.push_str(&text[start..end]);
if !result.ends_with('\n') {
result.push('\n');
}
}
if prev_range_end < text.len() {
writeln!(&mut result, "...").unwrap();
}
writeln!(&mut result, "~~~").unwrap();
}
}
}
Ok(result)
})
}
}
#[cfg(test)]
mod tests {
use std::path::Path;
use super::*;
use gpui::TestAppContext;
use project::FakeFs;
use serde_json::json;
use settings::SettingsStore;
use unindent::Unindent as _;
#[gpui::test]
async fn test_system_message_generation(cx: &mut TestAppContext) {
init_test(cx);
let file_3_contents = r#"
fn test1() {}
fn test2() {}
fn test3() {}
"#
.unindent();
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/code",
json!({
"root1": {
"lib": {
"file1.rs": "mod example;",
"file2.rs": "",
},
"test": {
"file3.rs": file_3_contents,
}
},
"root2": {
"src": {
"main.rs": ""
}
}
}),
)
.await;
let project = Project::test(
fs.clone(),
["/code/root1".as_ref(), "/code/root2".as_ref()],
cx,
)
.await;
let worktree_ids = project.read_with(cx, |project, cx| {
project
.worktrees(cx)
.map(|worktree| worktree.read(cx).id())
.collect::<Vec<_>>()
});
let mut ax = ProjectContext::new(project.downgrade(), fs);
ax.add_file(ProjectPath {
worktree_id: worktree_ids[0],
path: Path::new("lib/file1.rs").into(),
});
let message = cx
.update(|cx| ax.generate_system_message(cx))
.await
.unwrap();
assert_eq!(
r#"
project structure:
# root1
## lib/file1.rs
~~~
mod example;
~~~
"#
.unindent(),
message
);
ax.add_excerpts(
ProjectPath {
worktree_id: worktree_ids[0],
path: Path::new("test/file3.rs").into(),
},
&[
file_3_contents.find("fn test2").unwrap()
..file_3_contents.find("fn test3").unwrap(),
],
);
let message = cx
.update(|cx| ax.generate_system_message(cx))
.await
.unwrap();
assert_eq!(
r#"
project structure:
# root1
## lib/file1.rs
~~~
mod example;
~~~
## test/file3.rs
~~~
...
fn test2() {}
...
~~~
"#
.unindent(),
message
);
}
fn init_test(cx: &mut TestAppContext) {
cx.update(|cx| {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
Project::init_settings(cx);
});
}
}

View File

@@ -1,526 +0,0 @@
use crate::ProjectContext;
use anyhow::{anyhow, Result};
use gpui::{AnyElement, AnyView, IntoElement, Render, Task, View, WindowContext};
use repair_json::repair;
use schemars::{schema::RootSchema, schema_for, JsonSchema};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::value::RawValue;
use std::{
any::TypeId,
collections::HashMap,
fmt::Display,
mem,
sync::atomic::{AtomicBool, Ordering::SeqCst},
};
use ui::ViewContext;
pub struct ToolRegistry {
registered_tools: HashMap<String, RegisteredTool>,
}
#[derive(Default)]
pub struct ToolFunctionCall {
pub id: String,
pub name: String,
pub arguments: String,
state: ToolFunctionCallState,
}
#[derive(Default)]
enum ToolFunctionCallState {
#[default]
Initializing,
NoSuchTool,
KnownTool(Box<dyn InternalToolView>),
ExecutedTool(Box<dyn InternalToolView>),
}
trait InternalToolView {
fn view(&self) -> AnyView;
fn generate(&self, project: &mut ProjectContext, cx: &mut WindowContext) -> String;
fn try_set_input(&self, input: &str, cx: &mut WindowContext);
fn execute(&self, cx: &mut WindowContext) -> Task<Result<()>>;
fn serialize_output(&self, cx: &mut WindowContext) -> Result<Box<RawValue>>;
fn deserialize_output(&self, raw_value: &RawValue, cx: &mut WindowContext) -> Result<()>;
}
#[derive(Default, Serialize, Deserialize)]
pub struct SavedToolFunctionCall {
id: String,
name: String,
arguments: String,
state: SavedToolFunctionCallState,
}
#[derive(Default, Serialize, Deserialize)]
enum SavedToolFunctionCallState {
#[default]
Initializing,
NoSuchTool,
KnownTool,
ExecutedTool(Box<RawValue>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct ToolFunctionDefinition {
pub name: String,
pub description: String,
pub parameters: RootSchema,
}
pub trait LanguageModelTool {
type View: ToolView;
/// Returns the name of the tool.
///
/// This name is exposed to the language model to allow the model to pick
/// which tools to use. As this name is used to identify the tool within a
/// tool registry, it should be unique.
fn name(&self) -> String;
/// Returns the description of the tool.
///
/// This can be used to _prompt_ the model as to what the tool does.
fn description(&self) -> String;
/// Returns the OpenAI Function definition for the tool, for direct use with OpenAI's API.
fn definition(&self) -> ToolFunctionDefinition {
let root_schema = schema_for!(<Self::View as ToolView>::Input);
ToolFunctionDefinition {
name: self.name(),
description: self.description(),
parameters: root_schema,
}
}
/// A view of the output of running the tool, for displaying to the user.
fn view(&self, cx: &mut WindowContext) -> View<Self::View>;
}
pub trait ToolView: Render {
/// The input type that will be passed in to `execute` when the tool is called
/// by the language model.
type Input: DeserializeOwned + JsonSchema;
/// The output returned by executing the tool.
type SerializedState: DeserializeOwned + Serialize;
fn generate(&self, project: &mut ProjectContext, cx: &mut ViewContext<Self>) -> String;
fn set_input(&mut self, input: Self::Input, cx: &mut ViewContext<Self>);
fn execute(&mut self, cx: &mut ViewContext<Self>) -> Task<Result<()>>;
fn serialize(&self, cx: &mut ViewContext<Self>) -> Self::SerializedState;
fn deserialize(
&mut self,
output: Self::SerializedState,
cx: &mut ViewContext<Self>,
) -> Result<()>;
}
struct RegisteredTool {
enabled: AtomicBool,
type_id: TypeId,
build_view: Box<dyn Fn(&mut WindowContext) -> Box<dyn InternalToolView>>,
definition: ToolFunctionDefinition,
}
impl ToolRegistry {
pub fn new() -> Self {
Self {
registered_tools: HashMap::new(),
}
}
pub fn set_tool_enabled<T: 'static + LanguageModelTool>(&self, is_enabled: bool) {
for tool in self.registered_tools.values() {
if tool.type_id == TypeId::of::<T>() {
tool.enabled.store(is_enabled, SeqCst);
return;
}
}
}
pub fn is_tool_enabled<T: 'static + LanguageModelTool>(&self) -> bool {
for tool in self.registered_tools.values() {
if tool.type_id == TypeId::of::<T>() {
return tool.enabled.load(SeqCst);
}
}
false
}
pub fn definitions(&self) -> Vec<ToolFunctionDefinition> {
self.registered_tools
.values()
.filter(|tool| tool.enabled.load(SeqCst))
.map(|tool| tool.definition.clone())
.collect()
}
pub fn update_tool_call(
&self,
call: &mut ToolFunctionCall,
name: Option<&str>,
arguments: Option<&str>,
cx: &mut WindowContext,
) {
if let Some(name) = name {
call.name.push_str(name);
}
if let Some(arguments) = arguments {
if call.arguments.is_empty() {
if let Some(tool) = self.registered_tools.get(&call.name) {
let view = (tool.build_view)(cx);
call.state = ToolFunctionCallState::KnownTool(view);
} else {
call.state = ToolFunctionCallState::NoSuchTool;
}
}
call.arguments.push_str(arguments);
if let ToolFunctionCallState::KnownTool(view) = &call.state {
if let Ok(repaired_arguments) = repair(call.arguments.clone()) {
view.try_set_input(&repaired_arguments, cx)
}
}
}
}
pub fn execute_tool_call(
&self,
tool_call: &mut ToolFunctionCall,
cx: &mut WindowContext,
) -> Option<Task<Result<()>>> {
if let ToolFunctionCallState::KnownTool(view) = mem::take(&mut tool_call.state) {
let task = view.execute(cx);
tool_call.state = ToolFunctionCallState::ExecutedTool(view);
Some(task)
} else {
None
}
}
pub fn render_tool_call(
&self,
tool_call: &ToolFunctionCall,
_cx: &mut WindowContext,
) -> Option<AnyElement> {
match &tool_call.state {
ToolFunctionCallState::NoSuchTool => {
Some(ui::Label::new("No such tool").into_any_element())
}
ToolFunctionCallState::Initializing => None,
ToolFunctionCallState::KnownTool(view) | ToolFunctionCallState::ExecutedTool(view) => {
Some(view.view().into_any_element())
}
}
}
pub fn content_for_tool_call(
&self,
tool_call: &ToolFunctionCall,
project_context: &mut ProjectContext,
cx: &mut WindowContext,
) -> String {
match &tool_call.state {
ToolFunctionCallState::Initializing => String::new(),
ToolFunctionCallState::NoSuchTool => {
format!("No such tool: {}", tool_call.name)
}
ToolFunctionCallState::KnownTool(view) | ToolFunctionCallState::ExecutedTool(view) => {
view.generate(project_context, cx)
}
}
}
pub fn serialize_tool_call(
&self,
call: &ToolFunctionCall,
cx: &mut WindowContext,
) -> Result<SavedToolFunctionCall> {
Ok(SavedToolFunctionCall {
id: call.id.clone(),
name: call.name.clone(),
arguments: call.arguments.clone(),
state: match &call.state {
ToolFunctionCallState::Initializing => SavedToolFunctionCallState::Initializing,
ToolFunctionCallState::NoSuchTool => SavedToolFunctionCallState::NoSuchTool,
ToolFunctionCallState::KnownTool(_) => SavedToolFunctionCallState::KnownTool,
ToolFunctionCallState::ExecutedTool(view) => {
SavedToolFunctionCallState::ExecutedTool(view.serialize_output(cx)?)
}
},
})
}
pub fn deserialize_tool_call(
&self,
call: &SavedToolFunctionCall,
cx: &mut WindowContext,
) -> Result<ToolFunctionCall> {
let Some(tool) = self.registered_tools.get(&call.name) else {
return Err(anyhow!("no such tool {}", call.name));
};
Ok(ToolFunctionCall {
id: call.id.clone(),
name: call.name.clone(),
arguments: call.arguments.clone(),
state: match &call.state {
SavedToolFunctionCallState::Initializing => ToolFunctionCallState::Initializing,
SavedToolFunctionCallState::NoSuchTool => ToolFunctionCallState::NoSuchTool,
SavedToolFunctionCallState::KnownTool => {
log::error!("Deserialized tool that had not executed");
let view = (tool.build_view)(cx);
view.try_set_input(&call.arguments, cx);
ToolFunctionCallState::KnownTool(view)
}
SavedToolFunctionCallState::ExecutedTool(output) => {
let view = (tool.build_view)(cx);
view.try_set_input(&call.arguments, cx);
view.deserialize_output(output, cx)?;
ToolFunctionCallState::ExecutedTool(view)
}
},
})
}
pub fn register<T: 'static + LanguageModelTool>(&mut self, tool: T) -> Result<()> {
let name = tool.name();
let registered_tool = RegisteredTool {
type_id: TypeId::of::<T>(),
definition: tool.definition(),
enabled: AtomicBool::new(true),
build_view: Box::new(move |cx: &mut WindowContext| Box::new(tool.view(cx))),
};
let previous = self.registered_tools.insert(name.clone(), registered_tool);
if previous.is_some() {
return Err(anyhow!("already registered a tool with name {}", name));
}
return Ok(());
}
}
impl<T: ToolView> InternalToolView for View<T> {
fn view(&self) -> AnyView {
self.clone().into()
}
fn generate(&self, project: &mut ProjectContext, cx: &mut WindowContext) -> String {
self.update(cx, |view, cx| view.generate(project, cx))
}
fn try_set_input(&self, input: &str, cx: &mut WindowContext) {
if let Ok(input) = serde_json::from_str::<T::Input>(input) {
self.update(cx, |view, cx| {
view.set_input(input, cx);
cx.notify();
});
}
}
fn execute(&self, cx: &mut WindowContext) -> Task<Result<()>> {
self.update(cx, |view, cx| view.execute(cx))
}
fn serialize_output(&self, cx: &mut WindowContext) -> Result<Box<RawValue>> {
let output = self.update(cx, |view, cx| view.serialize(cx));
Ok(RawValue::from_string(serde_json::to_string(&output)?)?)
}
fn deserialize_output(&self, output: &RawValue, cx: &mut WindowContext) -> Result<()> {
let state = serde_json::from_str::<T::SerializedState>(output.get())?;
self.update(cx, |view, cx| view.deserialize(state, cx))?;
Ok(())
}
}
impl Display for ToolFunctionDefinition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let schema = serde_json::to_string(&self.parameters).ok();
let schema = schema.unwrap_or("None".to_string());
write!(f, "Name: {}:\n", self.name)?;
write!(f, "Description: {}\n", self.description)?;
write!(f, "Parameters: {}", schema)
}
}
#[cfg(test)]
mod test {
use super::*;
use gpui::{div, prelude::*, Render, TestAppContext};
use gpui::{EmptyView, View};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::json;
#[derive(Deserialize, Serialize, JsonSchema)]
struct WeatherQuery {
location: String,
unit: String,
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
struct WeatherResult {
location: String,
temperature: f64,
unit: String,
}
struct WeatherView {
input: Option<WeatherQuery>,
result: Option<WeatherResult>,
// Fake API call
current_weather: WeatherResult,
}
#[derive(Clone, Serialize)]
struct WeatherTool {
current_weather: WeatherResult,
}
impl WeatherView {
fn new(current_weather: WeatherResult) -> Self {
Self {
input: None,
result: None,
current_weather,
}
}
}
impl Render for WeatherView {
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
match self.result {
Some(ref result) => div()
.child(format!("temperature: {}", result.temperature))
.into_any_element(),
None => div().child("Calculating weather...").into_any_element(),
}
}
}
impl ToolView for WeatherView {
type Input = WeatherQuery;
type SerializedState = WeatherResult;
fn generate(&self, _output: &mut ProjectContext, _cx: &mut ViewContext<Self>) -> String {
serde_json::to_string(&self.result).unwrap()
}
fn set_input(&mut self, input: Self::Input, cx: &mut ViewContext<Self>) {
self.input = Some(input);
cx.notify();
}
fn execute(&mut self, _cx: &mut ViewContext<Self>) -> Task<Result<()>> {
let input = self.input.as_ref().unwrap();
let _location = input.location.clone();
let _unit = input.unit.clone();
let weather = self.current_weather.clone();
self.result = Some(weather);
Task::ready(Ok(()))
}
fn serialize(&self, _cx: &mut ViewContext<Self>) -> Self::SerializedState {
self.current_weather.clone()
}
fn deserialize(
&mut self,
output: Self::SerializedState,
_cx: &mut ViewContext<Self>,
) -> Result<()> {
self.current_weather = output;
Ok(())
}
}
impl LanguageModelTool for WeatherTool {
type View = WeatherView;
fn name(&self) -> String {
"get_current_weather".to_string()
}
fn description(&self) -> String {
"Fetches the current weather for a given location.".to_string()
}
fn view(&self, cx: &mut WindowContext) -> View<Self::View> {
cx.new_view(|_cx| WeatherView::new(self.current_weather.clone()))
}
}
#[gpui::test]
async fn test_openai_weather_example(cx: &mut TestAppContext) {
let (_, cx) = cx.add_window_view(|_cx| EmptyView);
let mut registry = ToolRegistry::new();
registry
.register(WeatherTool {
current_weather: WeatherResult {
location: "San Francisco".to_string(),
temperature: 21.0,
unit: "Celsius".to_string(),
},
})
.unwrap();
let definitions = registry.definitions();
assert_eq!(
definitions,
[ToolFunctionDefinition {
name: "get_current_weather".to_string(),
description: "Fetches the current weather for a given location.".to_string(),
parameters: serde_json::from_value(json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "WeatherQuery",
"type": "object",
"properties": {
"location": {
"type": "string"
},
"unit": {
"type": "string"
}
},
"required": ["location", "unit"]
}))
.unwrap(),
}]
);
let mut call = ToolFunctionCall {
id: "the-id".to_string(),
name: "get_cur".to_string(),
..Default::default()
};
let task = cx.update(|cx| {
registry.update_tool_call(
&mut call,
Some("rent_weather"),
Some(r#"{"location": "San Francisco","#),
cx,
);
registry.update_tool_call(&mut call, None, Some(r#" "unit": "Celsius"}"#), cx);
registry.execute_tool_call(&mut call, cx).unwrap()
});
task.await.unwrap();
match &call.state {
ToolFunctionCallState::ExecutedTool(_view) => {}
_ => panic!(),
}
}
}

View File

@@ -55,8 +55,6 @@ struct UpdateRequestBody {
installation_id: Option<Arc<str>>,
release_channel: Option<&'static str>,
telemetry: bool,
is_staff: Option<bool>,
destination: &'static str,
}
#[derive(Clone, PartialEq, Eq)]
@@ -577,27 +575,18 @@ async fn download_remote_server_binary(
cx: &AsyncAppContext,
) -> Result<()> {
let mut target_file = File::create(&target_path).await?;
let (installation_id, release_channel, telemetry_enabled, is_staff) = cx.update(|cx| {
let telemetry = Client::global(cx).telemetry().clone();
let is_staff = telemetry.is_staff();
let installation_id = telemetry.installation_id();
let (installation_id, release_channel, telemetry) = cx.update(|cx| {
let installation_id = Client::global(cx).telemetry().installation_id();
let release_channel =
ReleaseChannel::try_global(cx).map(|release_channel| release_channel.display_name());
let telemetry_enabled = TelemetrySettings::get_global(cx).metrics;
let telemetry = TelemetrySettings::get_global(cx).metrics;
(
installation_id,
release_channel,
telemetry_enabled,
is_staff,
)
(installation_id, release_channel, telemetry)
})?;
let request_body = AsyncBody::from(serde_json::to_string(&UpdateRequestBody {
installation_id,
release_channel,
telemetry: telemetry_enabled,
is_staff,
destination: "remote",
telemetry,
})?);
let mut response = client.get(&release.url, request_body, true).await?;
@@ -613,28 +602,19 @@ async fn download_release(
) -> Result<()> {
let mut target_file = File::create(&target_path).await?;
let (installation_id, release_channel, telemetry_enabled, is_staff) = cx.update(|cx| {
let telemetry = Client::global(cx).telemetry().clone();
let is_staff = telemetry.is_staff();
let installation_id = telemetry.installation_id();
let (installation_id, release_channel, telemetry) = cx.update(|cx| {
let installation_id = Client::global(cx).telemetry().installation_id();
let release_channel =
ReleaseChannel::try_global(cx).map(|release_channel| release_channel.display_name());
let telemetry_enabled = TelemetrySettings::get_global(cx).metrics;
let telemetry = TelemetrySettings::get_global(cx).metrics;
(
installation_id,
release_channel,
telemetry_enabled,
is_staff,
)
(installation_id, release_channel, telemetry)
})?;
let request_body = AsyncBody::from(serde_json::to_string(&UpdateRequestBody {
installation_id,
release_channel,
telemetry: telemetry_enabled,
is_staff,
destination: "local",
telemetry,
})?);
let mut response = client.get(&release.url, request_body, true).await?;

View File

@@ -493,7 +493,7 @@ impl Room {
// we leave the room and return an error.
if let Some(this) = this.upgrade() {
log::info!("reconnection failed, leaving room");
let _ = this.update(&mut cx, |this, cx| this.leave(cx))?;
let _ = this.update(&mut cx, |this, cx| this.leave(cx))?.await?;
}
Err(anyhow!(
"can't reconnect to room: client failed to re-establish connection"
@@ -942,7 +942,7 @@ impl Room {
this.pending_room_update.take();
if this.should_leave() {
log::info!("room is empty, leaving");
let _ = this.leave(cx);
let _ = this.leave(cx).detach();
}
this.user_store.update(cx, |user_store, cx| {

View File

@@ -7,8 +7,9 @@ pub mod user;
use anyhow::{anyhow, Context as _, Result};
use async_recursion::async_recursion;
use async_tungstenite::tungstenite::{
client::IntoClientRequest,
error::Error as WebsocketError,
http::{Request, StatusCode},
http::{HeaderValue, Request, StatusCode},
};
use clock::SystemClock;
use collections::HashMap;
@@ -235,6 +236,8 @@ pub enum EstablishConnectionError {
#[error("{0}")]
Http(#[from] http_client::Error),
#[error("{0}")]
InvalidHeaderValue(#[from] async_tungstenite::tungstenite::http::header::InvalidHeaderValue),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
Websocket(#[from] async_tungstenite::tungstenite::http::Error),
@@ -1159,19 +1162,24 @@ impl Client {
.ok()
.unwrap_or_default();
let request = Request::builder()
.header("Authorization", credentials.authorization_header())
.header("x-zed-protocol-version", rpc::PROTOCOL_VERSION)
.header("x-zed-app-version", app_version)
.header(
"x-zed-release-channel",
release_channel.map(|r| r.dev_name()).unwrap_or("unknown"),
);
let http = self.http.clone();
let credentials = credentials.clone();
let rpc_url = self.rpc_url(http, release_channel);
cx.background_executor().spawn(async move {
use HttpOrHttps::*;
#[derive(Debug)]
enum HttpOrHttps {
Http,
Https,
}
let mut rpc_url = rpc_url.await?;
let url_scheme = match rpc_url.scheme() {
"https" => Https,
"http" => Http,
_ => Err(anyhow!("invalid rpc url: {}", rpc_url))?,
};
let rpc_host = rpc_url
.host_str()
.zip(rpc_url.port_or_known_default())
@@ -1180,10 +1188,37 @@ impl Client {
log::info!("connected to rpc endpoint {}", rpc_url);
match rpc_url.scheme() {
"https" => {
rpc_url.set_scheme("wss").unwrap();
let request = request.uri(rpc_url.as_str()).body(())?;
rpc_url
.set_scheme(match url_scheme {
Https => "wss",
Http => "ws",
})
.unwrap();
// We call `into_client_request` to let `tungstenite` construct the WebSocket request
// for us from the RPC URL.
//
// Among other things, it will generate and set a `Sec-WebSocket-Key` header for us.
let mut request = rpc_url.into_client_request()?;
// We then modify the request to add our desired headers.
let request_headers = request.headers_mut();
request_headers.insert(
"Authorization",
HeaderValue::from_str(&credentials.authorization_header())?,
);
request_headers.insert(
"x-zed-protocol-version",
HeaderValue::from_str(&rpc::PROTOCOL_VERSION.to_string())?,
);
request_headers.insert("x-zed-app-version", HeaderValue::from_str(&app_version)?);
request_headers.insert(
"x-zed-release-channel",
HeaderValue::from_str(&release_channel.map(|r| r.dev_name()).unwrap_or("unknown"))?,
);
match url_scheme {
Https => {
let (stream, _) =
async_tungstenite::async_std::client_async_tls(request, stream).await?;
Ok(Connection::new(
@@ -1192,9 +1227,7 @@ impl Client {
.sink_map_err(|error| anyhow!(error)),
))
}
"http" => {
rpc_url.set_scheme("ws").unwrap();
let request = request.uri(rpc_url.as_str()).body(())?;
Http => {
let (stream, _) = async_tungstenite::client_async(request, stream).await?;
Ok(Connection::new(
stream
@@ -1202,7 +1235,6 @@ impl Client {
.sink_map_err(|error| anyhow!(error)),
))
}
_ => Err(anyhow!("invalid rpc url: {}", rpc_url))?,
}
})
}
@@ -1410,7 +1442,7 @@ impl Client {
self.peer.send(self.connection_id()?, message)
}
fn send_dynamic(&self, envelope: proto::Envelope) -> Result<()> {
pub fn send_dynamic(&self, envelope: proto::Envelope) -> Result<()> {
let connection_id = self.connection_id()?;
self.peer.send_dynamic(connection_id, envelope)
}

View File

@@ -30,7 +30,7 @@ chrono.workspace = true
clock.workspace = true
clickhouse.workspace = true
collections.workspace = true
dashmap = "5.4"
dashmap.workspace = true
envy = "0.4.2"
futures.workspace = true
google_ai.workspace = true
@@ -47,7 +47,7 @@ prost.workspace = true
rand.workspace = true
reqwest = { version = "0.11", features = ["json"] }
rpc.workspace = true
scrypt = "0.7"
scrypt = "0.11"
sea-orm = { version = "0.12.x", features = ["sqlx-postgres", "postgres-array", "runtime-tokio-rustls", "with-uuid"] }
semantic_version.workspace = true
semver.workspace = true

View File

@@ -1,6 +1,5 @@
use anyhow::{anyhow, Context as _, Result};
use anyhow::{anyhow, Result};
use rpc::proto;
use util::ResultExt as _;
pub fn language_model_request_to_open_ai(
request: proto::CompleteWithLanguageModel,
@@ -21,25 +20,7 @@ pub fn language_model_request_to_open_ai(
proto::LanguageModelRole::LanguageModelAssistant => {
open_ai::RequestMessage::Assistant {
content: Some(message.content),
tool_calls: message
.tool_calls
.into_iter()
.filter_map(|call| {
Some(open_ai::ToolCall {
id: call.id,
content: match call.variant? {
proto::tool_call::Variant::Function(f) => {
open_ai::ToolCallContent::Function {
function: open_ai::FunctionContent {
name: f.name,
arguments: f.arguments,
},
}
}
},
})
})
.collect(),
tool_calls: Vec::new(),
}
}
proto::LanguageModelRole::LanguageModelSystem => {
@@ -47,12 +28,6 @@ pub fn language_model_request_to_open_ai(
content: message.content,
}
}
proto::LanguageModelRole::LanguageModelTool => open_ai::RequestMessage::Tool {
tool_call_id: message
.tool_call_id
.ok_or_else(|| anyhow!("tool message is missing tool call id"))?,
content: message.content,
},
};
Ok(openai_message)
@@ -61,32 +36,8 @@ pub fn language_model_request_to_open_ai(
stream: true,
stop: request.stop,
temperature: request.temperature,
tools: request
.tools
.into_iter()
.filter_map(|tool| {
Some(match tool.variant? {
proto::chat_completion_tool::Variant::Function(f) => {
open_ai::ToolDefinition::Function {
function: open_ai::FunctionDefinition {
name: f.name,
description: f.description,
parameters: if let Some(params) = &f.parameters {
Some(
serde_json::from_str(params)
.context("failed to deserialize tool parameters")
.log_err()?,
)
} else {
None
},
},
}
}
})
})
.collect(),
tool_choice: request.tool_choice,
tool_choice: None,
tools: Vec::new(),
})
}
@@ -118,9 +69,6 @@ pub fn language_model_request_message_to_google_ai(
proto::LanguageModelRole::LanguageModelUser => google_ai::Role::User,
proto::LanguageModelRole::LanguageModelAssistant => google_ai::Role::Model,
proto::LanguageModelRole::LanguageModelSystem => google_ai::Role::User,
proto::LanguageModelRole::LanguageModelTool => {
Err(anyhow!("we don't handle tool calls with google ai yet"))?
}
},
})
}

View File

@@ -1,3 +1,4 @@
pub mod contributors;
pub mod events;
pub mod extensions;
pub mod ips_file;
@@ -5,13 +6,13 @@ pub mod slack;
use crate::{
auth,
db::{ContributorSelector, User, UserId},
db::{User, UserId},
rpc, AppState, Error, Result,
};
use anyhow::anyhow;
use axum::{
body::Body,
extract::{self, Path, Query},
extract::{Path, Query},
http::{self, Request, StatusCode},
middleware::{self, Next},
response::IntoResponse,
@@ -19,7 +20,6 @@ use axum::{
Extension, Json, Router,
};
use axum_extra::response::ErasedJson;
use chrono::SecondsFormat;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tower::ServiceBuilder;
@@ -31,8 +31,7 @@ pub fn routes(rpc_server: Option<Arc<rpc::Server>>, state: Arc<AppState>) -> Rou
.route("/user", get(get_authenticated_user))
.route("/users/:id/access_tokens", post(create_access_token))
.route("/rpc_server_snapshot", get(get_rpc_server_snapshot))
.route("/contributors", get(get_contributors).post(add_contributor))
.route("/contributor", get(check_is_contributor))
.merge(contributors::router())
.layer(
ServiceBuilder::new()
.layer(Extension(state))
@@ -126,66 +125,6 @@ async fn get_rpc_server_snapshot(
Ok(ErasedJson::pretty(rpc_server.snapshot().await))
}
async fn get_contributors(Extension(app): Extension<Arc<AppState>>) -> Result<Json<Vec<String>>> {
Ok(Json(app.db.get_contributors().await?))
}
#[derive(Debug, Deserialize)]
struct CheckIsContributorParams {
github_user_id: Option<i32>,
github_login: Option<String>,
}
impl CheckIsContributorParams {
fn as_contributor_selector(self) -> Result<ContributorSelector> {
if let Some(github_user_id) = self.github_user_id {
return Ok(ContributorSelector::GitHubUserId { github_user_id });
}
if let Some(github_login) = self.github_login {
return Ok(ContributorSelector::GitHubLogin { github_login });
}
Err(anyhow!(
"must be one of `github_user_id` or `github_login`."
))?
}
}
#[derive(Debug, Serialize)]
struct CheckIsContributorResponse {
signed_at: Option<String>,
}
async fn check_is_contributor(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<CheckIsContributorParams>,
) -> Result<Json<CheckIsContributorResponse>> {
let params = params.as_contributor_selector()?;
Ok(Json(CheckIsContributorResponse {
signed_at: app
.db
.get_contributor_sign_timestamp(&params)
.await?
.map(|ts| ts.and_utc().to_rfc3339_opts(SecondsFormat::Millis, true)),
}))
}
async fn add_contributor(
Extension(app): Extension<Arc<AppState>>,
extract::Json(params): extract::Json<AuthenticatedUserParams>,
) -> Result<()> {
let initial_channel_id = app.config.auto_join_channel_id;
app.db
.add_contributor(
&params.github_login,
params.github_user_id,
params.github_email.as_deref(),
initial_channel_id,
)
.await
}
#[derive(Deserialize)]
struct CreateAccessTokenQueryParams {
public_key: String,

View File

@@ -0,0 +1,121 @@
use std::sync::{Arc, OnceLock};
use anyhow::anyhow;
use axum::{
extract::{self, Query},
routing::get,
Extension, Json, Router,
};
use chrono::{NaiveDateTime, SecondsFormat};
use serde::{Deserialize, Serialize};
use crate::api::AuthenticatedUserParams;
use crate::db::ContributorSelector;
use crate::{AppState, Result};
pub fn router() -> Router {
Router::new()
.route("/contributors", get(get_contributors).post(add_contributor))
.route("/contributor", get(check_is_contributor))
}
async fn get_contributors(Extension(app): Extension<Arc<AppState>>) -> Result<Json<Vec<String>>> {
Ok(Json(app.db.get_contributors().await?))
}
#[derive(Debug, Deserialize)]
struct CheckIsContributorParams {
github_user_id: Option<i32>,
github_login: Option<String>,
}
impl CheckIsContributorParams {
fn as_contributor_selector(self) -> Result<ContributorSelector> {
if let Some(github_user_id) = self.github_user_id {
return Ok(ContributorSelector::GitHubUserId { github_user_id });
}
if let Some(github_login) = self.github_login {
return Ok(ContributorSelector::GitHubLogin { github_login });
}
Err(anyhow!(
"must be one of `github_user_id` or `github_login`."
))?
}
}
#[derive(Debug, Serialize)]
struct CheckIsContributorResponse {
signed_at: Option<String>,
}
async fn check_is_contributor(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<CheckIsContributorParams>,
) -> Result<Json<CheckIsContributorResponse>> {
let params = params.as_contributor_selector()?;
if RenovateBot::is_renovate_bot(&params) {
return Ok(Json(CheckIsContributorResponse {
signed_at: Some(
RenovateBot::created_at()
.and_utc()
.to_rfc3339_opts(SecondsFormat::Millis, true),
),
}));
}
Ok(Json(CheckIsContributorResponse {
signed_at: app
.db
.get_contributor_sign_timestamp(&params)
.await?
.map(|ts| ts.and_utc().to_rfc3339_opts(SecondsFormat::Millis, true)),
}))
}
/// The Renovate bot GitHub user (`renovate[bot]`).
///
/// https://api.github.com/users/renovate[bot]
struct RenovateBot;
impl RenovateBot {
const LOGIN: &'static str = "renovate[bot]";
const USER_ID: i32 = 29139614;
/// Returns the `created_at` timestamp for the Renovate bot user.
fn created_at() -> &'static NaiveDateTime {
static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
CREATED_AT.get_or_init(|| {
chrono::DateTime::parse_from_rfc3339("2017-06-02T07:04:12Z")
.expect("failed to parse 'created_at' for 'renovate[bot]'")
.naive_utc()
})
}
/// Returns whether the given contributor selector corresponds to the Renovate bot user.
fn is_renovate_bot(contributor: &ContributorSelector) -> bool {
match contributor {
ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
ContributorSelector::GitHubUserId { github_user_id } => {
github_user_id == &Self::USER_ID
}
}
}
}
async fn add_contributor(
Extension(app): Extension<Arc<AppState>>,
extract::Json(params): extract::Json<AuthenticatedUserParams>,
) -> Result<()> {
let initial_channel_id = app.config.auto_join_channel_id;
app.db
.add_contributor(
&params.github_login,
params.github_user_id,
params.github_email.as_deref(),
initial_channel_id,
)
.await
}

View File

@@ -9,6 +9,7 @@ use axum::{
middleware::Next,
response::IntoResponse,
};
use base64::prelude::*;
use prometheus::{exponential_buckets, register_histogram, Histogram};
pub use rpc::auth::random_token;
use scrypt::{
@@ -155,10 +156,7 @@ pub async fn create_access_token(
/// protection.
pub fn hash_access_token(token: &str) -> String {
let digest = sha2::Sha256::digest(token);
format!(
"$sha256${}",
base64::encode_config(digest, base64::URL_SAFE)
)
format!("$sha256${}", BASE64_URL_SAFE.encode(digest))
}
/// Encrypts the given access token with the given public key to avoid leaking it on the way
@@ -402,15 +400,16 @@ mod test {
fn previous_hash_access_token(token: &str) -> Result<String> {
// Avoid slow hashing in debug mode.
let params = if cfg!(debug_assertions) {
scrypt::Params::new(1, 1, 1).unwrap()
scrypt::Params::new(1, 1, 1, scrypt::Params::RECOMMENDED_LEN).unwrap()
} else {
scrypt::Params::new(14, 8, 1).unwrap()
scrypt::Params::new(14, 8, 1, scrypt::Params::RECOMMENDED_LEN).unwrap()
};
Ok(Scrypt
.hash_password(
.hash_password_customized(
token.as_bytes(),
None,
None,
params,
&SaltString::generate(thread_rng()),
)

View File

@@ -153,7 +153,7 @@ async fn main() -> Result<()> {
let signal = async move {
// todo(windows):
// `ctrl_close` does not work well, because tokio's signal handler always returns soon,
// but system termiates the application soon after returning CTRL+CLOSE handler.
// but system terminates the application soon after returning CTRL+CLOSE handler.
// So we should implement blocking handler to treat CTRL+CLOSE signal.
let mut ctrl_break = tokio::signal::windows::ctrl_break()
.expect("failed to listen for interrupt signal");

View File

@@ -12,7 +12,7 @@ use crate::{
executor::Executor,
AppState, Error, RateLimit, RateLimiter, Result,
};
use anyhow::{anyhow, Context as _};
use anyhow::{anyhow, bail, Context as _};
use async_tungstenite::tungstenite::{
protocol::CloseFrame as TungsteniteCloseFrame, Message as TungsteniteMessage,
};
@@ -1392,7 +1392,7 @@ pub async fn handle_websocket_request(
let socket = socket
.map_ok(to_tungstenite_message)
.err_into()
.with(|message| async move { Ok(to_axum_message(message)) });
.with(|message| async move { to_axum_message(message) });
let connection = Connection::new(Box::pin(socket));
async move {
server
@@ -4597,37 +4597,19 @@ async fn complete_with_open_ai(
.map(|choice| proto::LanguageModelChoiceDelta {
index: choice.index,
delta: Some(proto::LanguageModelResponseMessage {
role: choice.delta.role.map(|role| match role {
open_ai::Role::User => LanguageModelRole::LanguageModelUser,
open_ai::Role::Assistant => LanguageModelRole::LanguageModelAssistant,
open_ai::Role::System => LanguageModelRole::LanguageModelSystem,
open_ai::Role::Tool => LanguageModelRole::LanguageModelTool,
} as i32),
role: choice.delta.role.and_then(|role| match role {
open_ai::Role::User => {
Some(LanguageModelRole::LanguageModelUser as i32)
}
open_ai::Role::Assistant => {
Some(LanguageModelRole::LanguageModelAssistant as i32)
}
open_ai::Role::System => {
Some(LanguageModelRole::LanguageModelSystem as i32)
}
_ => None,
}),
content: choice.delta.content,
tool_calls: choice
.delta
.tool_calls
.unwrap_or_default()
.into_iter()
.map(|delta| proto::ToolCallDelta {
index: delta.index as u32,
id: delta.id,
variant: match delta.function {
Some(function) => {
let name = function.name;
let arguments = function.arguments;
Some(proto::tool_call_delta::Variant::Function(
proto::tool_call_delta::FunctionCallDelta {
name,
arguments,
},
))
}
None => None,
},
})
.collect(),
}),
finish_reason: choice.finish_reason,
})
@@ -4679,8 +4661,6 @@ async fn complete_with_google_ai(
})
.collect(),
),
// Tool calls are not supported for Google
tool_calls: Vec::new(),
}),
finish_reason: candidate.finish_reason.map(|reason| reason.to_string()),
})
@@ -4697,8 +4677,6 @@ async fn complete_with_anthropic(
session: UserSession,
api_key: Arc<str>,
) -> Result<()> {
let model = anthropic::Model::from_id(&request.model)?;
let mut system_message = String::new();
let messages = request
.messages
@@ -4723,8 +4701,6 @@ async fn complete_with_anthropic(
None
}
// We don't yet support tool calls for Anthropic
LanguageModelRole::LanguageModelTool => None,
}
})
.collect();
@@ -4734,7 +4710,7 @@ async fn complete_with_anthropic(
anthropic::ANTHROPIC_API_URL,
&api_key,
anthropic::Request {
model,
model: request.model,
messages,
stream: true,
system: system_message,
@@ -4769,7 +4745,6 @@ async fn complete_with_anthropic(
delta: Some(proto::LanguageModelResponseMessage {
role: Some(current_role as i32),
content: Some(text),
tool_calls: Vec::new(),
}),
finish_reason: None,
}],
@@ -4786,7 +4761,6 @@ async fn complete_with_anthropic(
delta: Some(proto::LanguageModelResponseMessage {
role: Some(current_role as i32),
content: Some(text),
tool_calls: Vec::new(),
}),
finish_reason: None,
}],
@@ -5154,8 +5128,8 @@ async fn get_private_user_info(
Ok(())
}
fn to_axum_message(message: TungsteniteMessage) -> AxumMessage {
match message {
fn to_axum_message(message: TungsteniteMessage) -> anyhow::Result<AxumMessage> {
let message = match message {
TungsteniteMessage::Text(payload) => AxumMessage::Text(payload),
TungsteniteMessage::Binary(payload) => AxumMessage::Binary(payload),
TungsteniteMessage::Ping(payload) => AxumMessage::Ping(payload),
@@ -5164,7 +5138,20 @@ fn to_axum_message(message: TungsteniteMessage) -> AxumMessage {
code: frame.code.into(),
reason: frame.reason,
})),
}
// We should never receive a frame while reading the message, according
// to the `tungstenite` maintainers:
//
// > It cannot occur when you read messages from the WebSocket, but it
// > can be used when you want to send the raw frames (e.g. you want to
// > send the frames to the WebSocket without composing the full message first).
// >
// > — https://github.com/snapview/tungstenite-rs/issues/268
TungsteniteMessage::Frame(_) => {
bail!("received an unexpected frame while reading the message")
}
};
Ok(message)
}
fn to_tungstenite_message(message: AxumMessage) -> TungsteniteMessage {

View File

@@ -1,3 +1,4 @@
#![allow(clippy::reversed_empty_ranges)]
use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
use call::{ActiveCall, ParticipantLocation};
use client::ChannelId;

View File

@@ -78,7 +78,7 @@ pretty_assertions.workspace = true
project = { workspace = true, features = ["test-support"] }
rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
tree-sitter-markdown.workspace = true
tree-sitter-md.workspace = true
util = { workspace = true, features = ["test-support"] }
http_client = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }

View File

@@ -533,6 +533,7 @@ impl Render for MessageEditor {
},
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: TextSize::Small.rems(cx).into(),
font_weight: settings.ui_font.weight,
font_style: FontStyle::Normal,

View File

@@ -2190,6 +2190,7 @@ impl CollabPanel {
},
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
font_style: FontStyle::Normal,

View File

@@ -1,5 +1,5 @@
use anyhow::{anyhow, Result};
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
use futures::{future::BoxFuture, stream::BoxStream, StreamExt};
use gpui::{AppContext, Global, Model, ModelContext, Task};
use language_model::{
LanguageModel, LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry,
@@ -27,7 +27,7 @@ pub struct LanguageModelCompletionProvider {
const MAX_CONCURRENT_COMPLETION_REQUESTS: usize = 4;
pub struct LanguageModelCompletionResponse {
pub inner: BoxStream<'static, Result<String>>,
inner: BoxStream<'static, Result<String>>,
_lock: SemaphoreGuardArc,
}
@@ -143,11 +143,11 @@ impl LanguageModelCompletionProvider {
&self,
request: LanguageModelRequest,
cx: &AppContext,
) -> BoxFuture<'static, Result<usize>> {
) -> Option<BoxFuture<'static, Result<usize>>> {
if let Some(model) = self.active_model() {
model.count_tokens(request, cx)
Some(model.count_tokens(request, cx))
} else {
std::future::ready(Err(anyhow!("No active model set"))).boxed()
None
}
}

View File

@@ -691,7 +691,7 @@ impl Copilot {
{
match event {
language::Event::Edited => {
let _ = registered_buffer.report_changes(&buffer, cx);
drop(registered_buffer.report_changes(&buffer, cx));
}
language::Event::Saved => {
server

View File

@@ -333,7 +333,7 @@ mod tests {
three
"});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one.|<>
@@ -341,7 +341,7 @@ mod tests {
three
"},
vec!["completion_a", "completion_b"],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -375,7 +375,7 @@ mod tests {
three
"});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one.|<>
@@ -383,7 +383,7 @@ mod tests {
three
"},
vec![],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -408,7 +408,7 @@ mod tests {
three
"});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one.|<>
@@ -416,7 +416,7 @@ mod tests {
three
"},
vec!["completion_a", "completion_b"],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -590,7 +590,7 @@ mod tests {
three
"});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one.|<>
@@ -598,7 +598,7 @@ mod tests {
three
"},
vec![],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -632,7 +632,7 @@ mod tests {
three
"});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one.|<>
@@ -640,7 +640,7 @@ mod tests {
three
"},
vec![],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -889,7 +889,7 @@ mod tests {
three
"});
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one
@@ -897,7 +897,7 @@ mod tests {
three
"},
vec!["completion_a", "completion_b"],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -917,7 +917,7 @@ mod tests {
});
cx.simulate_keystroke("o");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one
@@ -925,7 +925,7 @@ mod tests {
three
"},
vec!["completion_a_2", "completion_b_2"],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {
@@ -944,7 +944,7 @@ mod tests {
});
cx.simulate_keystroke(".");
let _ = handle_completion_request(
drop(handle_completion_request(
&mut cx,
indoc! {"
one
@@ -952,7 +952,7 @@ mod tests {
three
"},
vec!["something_else()"],
);
));
handle_copilot_completion_request(
&copilot_lsp,
vec![crate::request::Completion {

View File

@@ -1320,9 +1320,8 @@ fn render_same_line_diagnostics(
let editor_handle = editor_handle.clone();
let parent = h_flex()
.items_start()
.child(v_flex().size_full().when_some_else(
toggle_expand_label,
|parent, label| {
.child(v_flex().size_full().map(|parent| {
if let Some(label) = toggle_expand_label {
parent.child(Button::new(cx.block_id, label).on_click({
let diagnostics = Arc::clone(&diagnostics);
move |_, cx| {
@@ -1353,16 +1352,15 @@ fn render_same_line_diagnostics(
});
}
}))
},
|parent| {
} else {
parent.child(
h_flex()
.size(IconSize::default().rems())
.invisible()
.flex_none(),
)
},
));
}
}));
let max_message_rows = if expanded {
None
} else {

View File

@@ -109,6 +109,7 @@ pub struct DisplayMap {
crease_map: CreaseMap,
fold_placeholder: FoldPlaceholder,
pub clip_at_line_ends: bool,
pub(crate) masked: bool,
}
impl DisplayMap {
@@ -156,6 +157,7 @@ impl DisplayMap {
text_highlights: Default::default(),
inlay_highlights: Default::default(),
clip_at_line_ends: false,
masked: false,
}
}
@@ -182,6 +184,7 @@ impl DisplayMap {
text_highlights: self.text_highlights.clone(),
inlay_highlights: self.inlay_highlights.clone(),
clip_at_line_ends: self.clip_at_line_ends,
masked: self.masked,
fold_placeholder: self.fold_placeholder.clone(),
}
}
@@ -499,6 +502,7 @@ pub struct DisplaySnapshot {
text_highlights: TextHighlights,
inlay_highlights: InlayHighlights,
clip_at_line_ends: bool,
masked: bool,
pub(crate) fold_placeholder: FoldPlaceholder,
}
@@ -561,7 +565,7 @@ impl DisplaySnapshot {
}
}
// used by line_mode selections and tries to match vim behaviour
// used by line_mode selections and tries to match vim behavior
pub fn expand_to_line(&self, range: Range<Point>) -> Range<Point> {
let new_start = if range.start.row == 0 {
MultiBufferPoint::new(0, 0)
@@ -650,6 +654,7 @@ impl DisplaySnapshot {
.chunks(
display_row.0..self.max_point().row().next_row().0,
false,
self.masked,
Highlights::default(),
)
.map(|h| h.text)
@@ -657,9 +662,9 @@ impl DisplaySnapshot {
/// Returns text chunks starting at the end of the given display row in reverse until the start of the file
pub fn reverse_text_chunks(&self, display_row: DisplayRow) -> impl Iterator<Item = &str> {
(0..=display_row.0).rev().flat_map(|row| {
(0..=display_row.0).rev().flat_map(move |row| {
self.block_snapshot
.chunks(row..row + 1, false, Highlights::default())
.chunks(row..row + 1, false, self.masked, Highlights::default())
.map(|h| h.text)
.collect::<Vec<_>>()
.into_iter()
@@ -676,6 +681,7 @@ impl DisplaySnapshot {
self.block_snapshot.chunks(
display_rows.start.0..display_rows.end.0,
language_aware,
self.masked,
Highlights {
text_highlights: Some(&self.text_highlights),
inlay_highlights: Some(&self.inlay_highlights),

View File

@@ -23,6 +23,7 @@ use text::Edit;
use ui::ElementId;
const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize];
const BULLETS: &str = "********************************************************************************************************************************";
/// Tracks custom blocks such as diagnostics that should be displayed within buffer.
///
@@ -285,6 +286,7 @@ pub struct BlockChunks<'a> {
input_chunk: Chunk<'a>,
output_row: u32,
max_output_row: u32,
masked: bool,
}
#[derive(Clone)]
@@ -893,6 +895,7 @@ impl BlockSnapshot {
self.chunks(
0..self.transforms.summary().output_rows,
false,
false,
Highlights::default(),
)
.map(|chunk| chunk.text)
@@ -903,6 +906,7 @@ impl BlockSnapshot {
&'a self,
rows: Range<u32>,
language_aware: bool,
masked: bool,
highlights: Highlights<'a>,
) -> BlockChunks<'a> {
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
@@ -941,6 +945,7 @@ impl BlockSnapshot {
transforms: cursor,
output_row: rows.start,
max_output_row,
masked,
}
}
@@ -1229,12 +1234,20 @@ impl<'a> Iterator for BlockChunks<'a> {
let (prefix_rows, prefix_bytes) =
offset_for_row(self.input_chunk.text, transform_end - self.output_row);
self.output_row += prefix_rows;
let (prefix, suffix) = self.input_chunk.text.split_at(prefix_bytes);
let (mut prefix, suffix) = self.input_chunk.text.split_at(prefix_bytes);
self.input_chunk.text = suffix;
if self.output_row == transform_end {
self.transforms.next(&());
}
if self.masked {
// Not great for multibyte text because to keep cursor math correct we
// need to have the same number of bytes in the input as output.
let chars = prefix.chars().count();
let bullet_len = chars;
prefix = &BULLETS[..bullet_len];
}
Some(Chunk {
text: prefix,
..self.input_chunk.clone()
@@ -2048,6 +2061,7 @@ mod tests {
.chunks(
start_row as u32..blocks_snapshot.max_point().row + 1,
false,
false,
Highlights::default(),
)
.map(|chunk| chunk.text)

View File

@@ -11,13 +11,14 @@
//!
//! All other submodules and structs are mostly concerned with holding editor data about the way it displays current buffer region(s).
//!
//! If you're looking to improve Vim mode, you should check out Vim crate that wraps Editor and overrides its behaviour.
//! If you're looking to improve Vim mode, you should check out Vim crate that wraps Editor and overrides its behavior.
pub mod actions;
mod blame_entry_tooltip;
mod blink_manager;
mod debounced_delay;
pub mod display_map;
mod editor_settings;
mod editor_settings_controls;
mod element;
mod git;
mod highlight_matching_bracket;
@@ -57,6 +58,7 @@ use debounced_delay::DebouncedDelay;
use display_map::*;
pub use display_map::{DisplayPoint, FoldPlaceholder};
pub use editor_settings::{CurrentLineHighlight, EditorSettings};
pub use editor_settings_controls::*;
use element::LineWithInvisibles;
pub use element::{
CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
@@ -406,6 +408,7 @@ impl EditorActionId {
type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
#[derive(Default)]
struct ScrollbarMarkerState {
scrollbar_size: Size<Pixels>,
dirty: bool,
@@ -419,17 +422,6 @@ impl ScrollbarMarkerState {
}
}
impl Default for ScrollbarMarkerState {
fn default() -> Self {
Self {
scrollbar_size: Size::default(),
dirty: false,
markers: Arc::from([]),
pending_refresh: None,
}
}
}
#[derive(Clone, Debug)]
struct RunnableTasks {
templates: Vec<(TaskSourceKind, TaskTemplate)>,
@@ -488,7 +480,6 @@ pub struct Editor {
mode: EditorMode,
show_breadcrumbs: bool,
show_gutter: bool,
redact_all: bool,
show_line_numbers: Option<bool>,
show_git_diff_gutter: Option<bool>,
show_code_actions: Option<bool>,
@@ -592,7 +583,7 @@ pub struct EditorSnapshot {
const GIT_BLAME_GUTTER_WIDTH_CHARS: f32 = 53.;
#[derive(Debug, Clone, Copy)]
#[derive(Default, Debug, Clone, Copy)]
pub struct GutterDimensions {
pub left_padding: Pixels,
pub right_padding: Pixels,
@@ -615,18 +606,6 @@ impl GutterDimensions {
}
}
impl Default for GutterDimensions {
fn default() -> Self {
Self {
left_padding: Pixels::ZERO,
right_padding: Pixels::ZERO,
width: Pixels::ZERO,
margin: Pixels::ZERO,
git_blame_entries_width: None,
}
}
}
#[derive(Debug)]
pub struct RemoteSelection {
pub replica_id: ReplicaId,
@@ -1823,7 +1802,6 @@ impl Editor {
show_code_actions: None,
show_runnables: None,
show_wrap_guides: None,
redact_all: false,
show_indent_guides,
placeholder_text: None,
highlight_order: 0,
@@ -5165,7 +5143,7 @@ impl Editor {
}))
}
fn render_close_hunk_diff_button(
fn close_hunk_diff_button(
&self,
hunk: HoveredHunk,
row: DisplayRow,
@@ -5740,7 +5718,7 @@ impl Editor {
self.transact(cx, |this, cx| {
this.buffer.update(cx, |buffer, cx| {
let empty_str: Arc<str> = "".into();
let empty_str: Arc<str> = Arc::default();
buffer.edit(
deletion_ranges
.into_iter()
@@ -5806,7 +5784,7 @@ impl Editor {
self.transact(cx, |this, cx| {
let buffer = this.buffer.update(cx, |buffer, cx| {
let empty_str: Arc<str> = "".into();
let empty_str: Arc<str> = Arc::default();
buffer.edit(
edit_ranges
.into_iter()
@@ -8107,7 +8085,7 @@ impl Editor {
let mut selection_edit_ranges = Vec::new();
let mut last_toggled_row = None;
let snapshot = this.buffer.read(cx).read(cx);
let empty_str: Arc<str> = "".into();
let empty_str: Arc<str> = Arc::default();
let mut suffixes_inserted = Vec::new();
fn comment_prefix_range(
@@ -10440,9 +10418,11 @@ impl Editor {
cx.notify();
}
pub fn set_redact_all(&mut self, redact_all: bool, cx: &mut ViewContext<Self>) {
self.redact_all = redact_all;
cx.notify();
pub fn set_masked(&mut self, masked: bool, cx: &mut ViewContext<Self>) {
if self.display_map.read(cx).masked != masked {
self.display_map.update(cx, |map, _| map.masked = masked);
}
cx.notify()
}
pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut ViewContext<Self>) {
@@ -10857,17 +10837,6 @@ impl Editor {
color_fetcher: fn(&ThemeColors) -> Hsla,
cx: &mut ViewContext<Self>,
) {
let snapshot = self.snapshot(cx);
// this is to try and catch a panic sooner
for range in ranges {
snapshot
.buffer_snapshot
.summary_for_anchor::<usize>(&range.start);
snapshot
.buffer_snapshot
.summary_for_anchor::<usize>(&range.end);
}
self.background_highlights
.insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
self.scrollbar_marker_state.dirty = true;
@@ -11139,10 +11108,6 @@ impl Editor {
display_snapshot: &DisplaySnapshot,
cx: &WindowContext,
) -> Vec<Range<DisplayPoint>> {
if self.redact_all {
return vec![DisplayPoint::zero()..display_snapshot.max_point()];
}
display_snapshot
.buffer_snapshot
.redacted_ranges(search_range, |file| {
@@ -11824,8 +11789,24 @@ impl Editor {
editor_snapshot: &EditorSnapshot,
cx: &mut ViewContext<Self>,
) -> Option<gpui::Point<Pixels>> {
let text_layout_details = self.text_layout_details(cx);
let line_height = text_layout_details
.editor_style
.text
.line_height_in_pixels(cx.rem_size());
let source_point = source.to_display_point(editor_snapshot);
self.display_to_pixel_point(source_point, editor_snapshot, cx)
let first_visible_line = text_layout_details
.scroll_anchor
.anchor
.to_display_point(editor_snapshot);
if first_visible_line > source_point {
return None;
}
let source_x = editor_snapshot.x_for_display_point(source_point, &text_layout_details);
let source_y = line_height
* ((source_point.row() - first_visible_line.row()).0 as f32
- text_layout_details.scroll_anchor.offset.y);
Some(gpui::Point::new(source_x, source_y))
}
pub fn display_to_pixel_point(
@@ -11836,18 +11817,22 @@ impl Editor {
) -> Option<gpui::Point<Pixels>> {
let line_height = self.style()?.text.line_height_in_pixels(cx.rem_size());
let text_layout_details = self.text_layout_details(cx);
let scroll_top = text_layout_details
let first_visible_line = text_layout_details
.scroll_anchor
.scroll_position(editor_snapshot)
.y;
if source.row().as_f32() < scroll_top.floor() {
.anchor
.to_display_point(editor_snapshot);
if first_visible_line > source {
return None;
}
let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
let source_y = line_height * (source.row().as_f32() - scroll_top);
let source_y = line_height * (source.row() - first_visible_line.row()).0 as f32;
Some(gpui::Point::new(source_x, source_y))
}
fn gutter_bounds(&self) -> Option<Bounds<Pixels>> {
let bounds = self.last_bounds?;
Some(element::gutter_bounds(bounds, self.gutter_dimensions))
}
}
fn hunks_for_selections(
@@ -12234,7 +12219,7 @@ impl EditorSnapshot {
self.scroll_anchor.scroll_position(&self.display_snapshot)
}
pub fn gutter_dimensions(
fn gutter_dimensions(
&self,
font_id: FontId,
font_size: Pixels,
@@ -12445,6 +12430,7 @@ impl Render for Editor {
color: cx.theme().colors().editor_foreground,
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(settings.buffer_line_height.value()),
@@ -12454,6 +12440,7 @@ impl Render for Editor {
color: cx.theme().colors().editor_foreground,
font_family: settings.buffer_font.family.clone(),
font_features: settings.buffer_font.features.clone(),
font_fallbacks: settings.buffer_font.fallbacks.clone(),
font_size: settings.buffer_font_size(cx).into(),
font_weight: settings.buffer_font.weight,
line_height: relative(settings.buffer_line_height.value()),

View File

@@ -305,7 +305,7 @@ pub struct ScrollbarContent {
}
/// Gutter related settings
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
pub struct GutterContent {
/// Whether to show line numbers in the gutter.
///

View File

@@ -0,0 +1,427 @@
use std::sync::Arc;
use gpui::{AppContext, FontFeatures, FontWeight};
use project::project_settings::{InlineBlameSettings, ProjectSettings};
use settings::{EditableSettingControl, Settings};
use theme::{FontFamilyCache, ThemeSettings};
use ui::{
prelude::*, CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer,
SettingsGroup,
};
use crate::EditorSettings;
#[derive(IntoElement)]
pub struct EditorSettingsControls {}
impl EditorSettingsControls {
pub fn new() -> Self {
Self {}
}
}
impl RenderOnce for EditorSettingsControls {
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
SettingsContainer::new()
.child(
SettingsGroup::new("Font")
.child(
h_flex()
.gap_2()
.justify_between()
.child(BufferFontFamilyControl)
.child(BufferFontWeightControl),
)
.child(BufferFontSizeControl)
.child(BufferFontLigaturesControl),
)
.child(SettingsGroup::new("Editor").child(InlineGitBlameControl))
.child(
SettingsGroup::new("Gutter").child(
h_flex()
.gap_2()
.justify_between()
.child(LineNumbersControl)
.child(RelativeLineNumbersControl),
),
)
}
}
#[derive(IntoElement)]
struct BufferFontFamilyControl;
impl EditableSettingControl for BufferFontFamilyControl {
type Value = SharedString;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"Buffer Font Family".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font.family.clone()
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.buffer_font_family = Some(value.to_string());
}
}
impl RenderOnce for BufferFontFamilyControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
.gap_2()
.child(Icon::new(IconName::Font))
.child(DropdownMenu::new(
"buffer-font-family",
value.clone(),
ContextMenu::build(cx, |mut menu, cx| {
let font_family_cache = FontFamilyCache::global(cx);
for font_name in font_family_cache.list_font_families(cx) {
menu = menu.custom_entry(
{
let font_name = font_name.clone();
move |_cx| Label::new(font_name.clone()).into_any_element()
},
{
let font_name = font_name.clone();
move |cx| {
Self::write(font_name.clone(), cx);
}
},
)
}
menu
}),
))
}
}
#[derive(IntoElement)]
struct BufferFontSizeControl;
impl EditableSettingControl for BufferFontSizeControl {
type Value = Pixels;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"Buffer Font Size".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font_size
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.buffer_font_size = Some(value.into());
}
}
impl RenderOnce for BufferFontSizeControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
.gap_2()
.child(Icon::new(IconName::FontSize))
.child(NumericStepper::new(
value.to_string(),
move |_, cx| {
Self::write(value - px(1.), cx);
},
move |_, cx| {
Self::write(value + px(1.), cx);
},
))
}
}
#[derive(IntoElement)]
struct BufferFontWeightControl;
impl EditableSettingControl for BufferFontWeightControl {
type Value = FontWeight;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"Buffer Font Weight".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font.weight
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.buffer_font_weight = Some(value.0);
}
}
impl RenderOnce for BufferFontWeightControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
.gap_2()
.child(Icon::new(IconName::FontWeight))
.child(DropdownMenu::new(
"buffer-font-weight",
value.0.to_string(),
ContextMenu::build(cx, |mut menu, _cx| {
for weight in FontWeight::ALL {
menu = menu.custom_entry(
move |_cx| Label::new(weight.0.to_string()).into_any_element(),
{
move |cx| {
Self::write(weight, cx);
}
},
)
}
menu
}),
))
}
}
#[derive(IntoElement)]
struct BufferFontLigaturesControl;
impl EditableSettingControl for BufferFontLigaturesControl {
type Value = bool;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"Buffer Font Ligatures".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings
.buffer_font
.features
.is_calt_enabled()
.unwrap_or(true)
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
let value = if value { 1 } else { 0 };
let mut features = settings
.buffer_font_features
.as_ref()
.map(|features| {
features
.tag_value_list()
.into_iter()
.cloned()
.collect::<Vec<_>>()
})
.unwrap_or_default();
if let Some(calt_index) = features.iter().position(|(tag, _)| tag == "calt") {
features[calt_index].1 = value;
} else {
features.push(("calt".into(), value));
}
settings.buffer_font_features = Some(FontFeatures(Arc::new(features)));
}
}
impl RenderOnce for BufferFontLigaturesControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"buffer-font-ligatures",
Label::new(self.name()),
value.into(),
|selection, cx| {
Self::write(
match selection {
Selection::Selected => true,
Selection::Unselected | Selection::Indeterminate => false,
},
cx,
);
},
)
}
}
#[derive(IntoElement)]
struct InlineGitBlameControl;
impl EditableSettingControl for InlineGitBlameControl {
type Value = bool;
type Settings = ProjectSettings;
fn name(&self) -> SharedString {
"Inline Git Blame".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ProjectSettings::get_global(cx);
settings.git.inline_blame_enabled()
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
if let Some(inline_blame) = settings.git.inline_blame.as_mut() {
inline_blame.enabled = value;
} else {
settings.git.inline_blame = Some(InlineBlameSettings {
enabled: false,
..Default::default()
});
}
}
}
impl RenderOnce for InlineGitBlameControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"inline-git-blame",
Label::new(self.name()),
value.into(),
|selection, cx| {
Self::write(
match selection {
Selection::Selected => true,
Selection::Unselected | Selection::Indeterminate => false,
},
cx,
);
},
)
}
}
#[derive(IntoElement)]
struct LineNumbersControl;
impl EditableSettingControl for LineNumbersControl {
type Value = bool;
type Settings = EditorSettings;
fn name(&self) -> SharedString {
"Line Numbers".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = EditorSettings::get_global(cx);
settings.gutter.line_numbers
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
if let Some(gutter) = settings.gutter.as_mut() {
gutter.line_numbers = Some(value);
} else {
settings.gutter = Some(crate::editor_settings::GutterContent {
line_numbers: Some(value),
..Default::default()
});
}
}
}
impl RenderOnce for LineNumbersControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
CheckboxWithLabel::new(
"line-numbers",
Label::new(self.name()),
value.into(),
|selection, cx| {
Self::write(
match selection {
Selection::Selected => true,
Selection::Unselected | Selection::Indeterminate => false,
},
cx,
);
},
)
}
}
#[derive(IntoElement)]
struct RelativeLineNumbersControl;
impl EditableSettingControl for RelativeLineNumbersControl {
type Value = bool;
type Settings = EditorSettings;
fn name(&self) -> SharedString {
"Relative Line Numbers".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = EditorSettings::get_global(cx);
settings.relative_line_numbers
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.relative_line_numbers = Some(value);
}
}
impl RenderOnce for RelativeLineNumbersControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
DropdownMenu::new(
"relative-line-numbers",
if value { "Relative" } else { "Ascending" },
ContextMenu::build(cx, |menu, _cx| {
menu.custom_entry(
|_cx| Label::new("Ascending").into_any_element(),
move |cx| Self::write(false, cx),
)
.custom_entry(
|_cx| Label::new("Relative").into_any_element(),
move |cx| Self::write(true, cx),
)
}),
)
}
}

View File

@@ -4716,12 +4716,13 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
editor
.condition::<crate::EditorEvent>(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
.await;
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(DisplayRow(0), 25)..DisplayPoint::new(DisplayRow(0), 25),
@@ -4731,94 +4732,126 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
});
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
&[
DisplayPoint::new(DisplayRow(0), 23)..DisplayPoint::new(DisplayRow(0), 27),
DisplayPoint::new(DisplayRow(2), 35)..DisplayPoint::new(DisplayRow(2), 7),
DisplayPoint::new(DisplayRow(3), 15)..DisplayPoint::new(DisplayRow(3), 21),
]
);
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::{mod3, «mod4ˇ»};
_ = view.update(cx, |view, cx| {
fn fn_1«ˇ(param1: bool, param2: &str)» {
let var1 = "«textˇ»";
}
"#},
cx,
);
});
editor.update(cx, |view, cx| {
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::«{mod3, mod4}ˇ»;
«ˇfn fn_1(param1: bool, param2: &str) {
let var1 = "text";
"#},
cx,
);
});
editor.update(cx, |view, cx| {
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 16)..DisplayPoint::new(DisplayRow(0), 28),
DisplayPoint::new(DisplayRow(4), 1)..DisplayPoint::new(DisplayRow(2), 0),
]
);
_ = view.update(cx, |view, cx| {
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(0), 0)]
);
// Trying to expand the selected syntax node one more time has no effect.
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(0), 0)]
);
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 16)..DisplayPoint::new(DisplayRow(0), 28),
DisplayPoint::new(DisplayRow(4), 1)..DisplayPoint::new(DisplayRow(2), 0),
]
);
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::«{mod3, mod4}ˇ»;
_ = view.update(cx, |view, cx| {
view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
«ˇfn fn_1(param1: bool, param2: &str) {
let var1 = "text";
"#},
cx,
);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 23)..DisplayPoint::new(DisplayRow(0), 27),
DisplayPoint::new(DisplayRow(2), 35)..DisplayPoint::new(DisplayRow(2), 7),
DisplayPoint::new(DisplayRow(3), 15)..DisplayPoint::new(DisplayRow(3), 21),
]
);
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 25)..DisplayPoint::new(DisplayRow(0), 25),
DisplayPoint::new(DisplayRow(2), 24)..DisplayPoint::new(DisplayRow(2), 12),
DisplayPoint::new(DisplayRow(3), 18)..DisplayPoint::new(DisplayRow(3), 18),
]
);
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::{mod3, «mod4ˇ»};
fn fn_1«ˇ(param1: bool, param2: &str)» {
let var1 = "«textˇ»";
}
"#},
cx,
);
});
editor.update(cx, |view, cx| {
view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
});
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::{mod3, mo«ˇ»d4};
fn fn_1(para«ˇm1: bool, pa»ram2: &str) {
let var1 = "te«ˇ»xt";
}
"#},
cx,
);
});
// Trying to shrink the selected syntax node one more time has no effect.
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 25)..DisplayPoint::new(DisplayRow(0), 25),
DisplayPoint::new(DisplayRow(2), 24)..DisplayPoint::new(DisplayRow(2), 12),
DisplayPoint::new(DisplayRow(3), 18)..DisplayPoint::new(DisplayRow(3), 18),
]
);
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::{mod3, mo«ˇ»d4};
fn fn_1(para«ˇm1: bool, pa»ram2: &str) {
let var1 = "te«ˇ»xt";
}
"#},
cx,
);
});
// Ensure that we keep expanding the selection if the larger selection starts or ends within
// a fold.
_ = view.update(cx, |view, cx| {
editor.update(cx, |view, cx| {
view.fold_ranges(
vec![
(
@@ -4835,14 +4868,19 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
);
view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
});
assert_eq!(
view.update(cx, |view, cx| view.selections.display_ranges(cx)),
&[
DisplayPoint::new(DisplayRow(0), 16)..DisplayPoint::new(DisplayRow(0), 28),
DisplayPoint::new(DisplayRow(2), 35)..DisplayPoint::new(DisplayRow(2), 7),
DisplayPoint::new(DisplayRow(3), 4)..DisplayPoint::new(DisplayRow(3), 23),
]
);
editor.update(cx, |editor, cx| {
assert_text_with_selections(
editor,
indoc! {r#"
use mod1::mod2::«{mod3, mod4}ˇ»;
fn fn_1«ˇ(param1: bool, param2: &str)» {
«let var1 = "text";ˇ»
}
"#},
cx,
);
});
}
#[gpui::test]
@@ -8173,11 +8211,13 @@ async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) {
);
cx.executor().run_until_parked();
cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
// TODO this is how it actually worked in Zed Stable, which is not very ergonomic.
// Uncommenting and commenting from this position brings in even more wrong artifacts.
cx.assert_editor_state(
&r#"
<!-- ˇ<script> -->
// ˇvar x = new Y();
<!-- ˇ</script> -->
// ˇ</script>
"#
.unindent(),
);
@@ -10065,7 +10105,7 @@ struct Row8;
struct Row9;
struct Row10;"#};
// Deletion hunks trigger with carets on ajacent rows, so carets and selections have to stay farther to avoid the revert
// Deletion hunks trigger with carets on adjacent rows, so carets and selections have to stay farther to avoid the revert
assert_hunk_revert(
indoc! {r#"struct Row;
struct Row2;

View File

@@ -59,6 +59,7 @@ use std::{
fmt::{self, Write},
iter, mem,
ops::{Deref, Range},
rc::Rc,
sync::Arc,
};
use sum_tree::Bias;
@@ -1248,7 +1249,7 @@ impl EditorElement {
// Folds contained in a hunk are ignored apart from shrinking visual size
// If a fold contains any hunks then that fold line is marked as modified
fn layout_git_gutters(
fn layout_gutter_git_hunks(
&self,
line_height: Pixels,
gutter_hitbox: &Hitbox,
@@ -1553,12 +1554,14 @@ impl EditorElement {
(offset_y, length)
}
#[allow(clippy::too_many_arguments)]
fn layout_run_indicators(
&self,
line_height: Pixels,
scroll_pixel_position: gpui::Point<Pixels>,
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
snapshot: &EditorSnapshot,
cx: &mut WindowContext,
) -> Vec<AnyElement> {
@@ -1602,6 +1605,7 @@ impl EditorElement {
gutter_dimensions,
scroll_pixel_position,
gutter_hitbox,
rows_with_hunk_bounds,
cx,
);
Some(button)
@@ -1610,6 +1614,7 @@ impl EditorElement {
})
}
#[allow(clippy::too_many_arguments)]
fn layout_code_actions_indicator(
&self,
line_height: Pixels,
@@ -1617,6 +1622,7 @@ impl EditorElement {
scroll_pixel_position: gpui::Point<Pixels>,
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
cx: &mut WindowContext,
) -> Option<AnyElement> {
let mut active = false;
@@ -1640,6 +1646,7 @@ impl EditorElement {
gutter_dimensions,
scroll_pixel_position,
gutter_hitbox,
rows_with_hunk_bounds,
cx,
);
@@ -1963,6 +1970,7 @@ impl EditorElement {
max_width: text_hitbox.size.width.max(*scroll_width),
editor_style: &self.style,
}))
.cursor(CursorStyle::Arrow)
.on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
.into_any_element()
}
@@ -3170,7 +3178,7 @@ impl EditorElement {
});
}
fn diff_hunk_bounds(
pub(super) fn diff_hunk_bounds(
snapshot: &EditorSnapshot,
line_height: Pixels,
gutter_bounds: Bounds<Pixels>,
@@ -4040,20 +4048,22 @@ impl EditorElement {
self.column_pixels(digit_count, cx)
}
#[allow(clippy::too_many_arguments)]
fn layout_hunk_diff_close_indicators(
&self,
expanded_hunks_by_rows: HashMap<DisplayRow, ExpandedHunk>,
line_height: Pixels,
scroll_pixel_position: gpui::Point<Pixels>,
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
expanded_hunks_by_rows: HashMap<DisplayRow, ExpandedHunk>,
cx: &mut WindowContext,
) -> Vec<AnyElement> {
self.editor.update(cx, |editor, cx| {
expanded_hunks_by_rows
.into_iter()
.map(|(display_row, hunk)| {
let button = editor.render_close_hunk_diff_button(
let button = editor.close_hunk_diff_button(
HoveredHunk {
multi_buffer_range: hunk.hunk_range,
status: hunk.status,
@@ -4070,6 +4080,7 @@ impl EditorElement {
gutter_dimensions,
scroll_pixel_position,
gutter_hitbox,
rows_with_hunk_bounds,
cx,
)
})
@@ -4078,6 +4089,7 @@ impl EditorElement {
}
}
#[allow(clippy::too_many_arguments)]
fn prepaint_gutter_button(
button: IconButton,
row: DisplayRow,
@@ -4085,6 +4097,7 @@ fn prepaint_gutter_button(
gutter_dimensions: &GutterDimensions,
scroll_pixel_position: gpui::Point<Pixels>,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
cx: &mut WindowContext<'_>,
) -> AnyElement {
let mut button = button.into_any_element();
@@ -4094,14 +4107,16 @@ fn prepaint_gutter_button(
);
let indicator_size = button.layout_as_root(available_space, cx);
let blame_width = gutter_dimensions
.git_blame_entries_width
.unwrap_or(Pixels::ZERO);
let blame_width = gutter_dimensions.git_blame_entries_width;
let gutter_width = rows_with_hunk_bounds
.get(&row)
.map(|bounds| bounds.size.width);
let left_offset = blame_width.max(gutter_width).unwrap_or_default();
let mut x = blame_width;
let mut x = left_offset;
let available_width = gutter_dimensions.margin + gutter_dimensions.left_padding
- indicator_size.width
- blame_width;
- left_offset;
x += available_width / 2.;
let mut y = row.as_f32() * line_height - scroll_pixel_position.y;
@@ -4949,13 +4964,8 @@ impl Element for EditorElement {
.collect::<SmallVec<[_; 2]>>();
let hitbox = cx.insert_hitbox(bounds, false);
let gutter_hitbox = cx.insert_hitbox(
Bounds {
origin: bounds.origin,
size: size(gutter_dimensions.width, bounds.size.height),
},
false,
);
let gutter_hitbox =
cx.insert_hitbox(gutter_bounds(bounds, gutter_dimensions), false);
let text_hitbox = cx.insert_hitbox(
Bounds {
origin: gutter_hitbox.upper_right(),
@@ -5078,7 +5088,7 @@ impl Element for EditorElement {
self.layout_crease_trailers(buffer_rows.iter().copied(), &snapshot, cx)
});
let display_hunks = self.layout_git_gutters(
let display_hunks = self.layout_gutter_git_hunks(
line_height,
&gutter_hitbox,
start_row..end_row,
@@ -5305,6 +5315,27 @@ impl Element for EditorElement {
.collect::<HashMap<_, _>>()
});
let rows_with_hunk_bounds = display_hunks
.iter()
.filter_map(|(hunk, hitbox)| Some((hunk, hitbox.as_ref()?.bounds)))
.fold(
HashMap::default(),
|mut rows_with_hunk_bounds, (hunk, bounds)| {
match hunk {
DisplayDiffHunk::Folded { display_row } => {
rows_with_hunk_bounds.insert(*display_row, bounds);
}
DisplayDiffHunk::Unfolded {
display_row_range, ..
} => {
for display_row in display_row_range.iter_rows() {
rows_with_hunk_bounds.insert(display_row, bounds);
}
}
}
rows_with_hunk_bounds
},
);
let mut _context_menu_visible = false;
let mut code_actions_indicator = None;
if let Some(newest_selection_head) = newest_selection_head {
@@ -5353,6 +5384,7 @@ impl Element for EditorElement {
scroll_pixel_position,
&gutter_dimensions,
&gutter_hitbox,
&rows_with_hunk_bounds,
cx,
);
}
@@ -5368,6 +5400,7 @@ impl Element for EditorElement {
scroll_pixel_position,
&gutter_dimensions,
&gutter_hitbox,
&rows_with_hunk_bounds,
&snapshot,
cx,
)
@@ -5376,11 +5409,12 @@ impl Element for EditorElement {
};
let close_indicators = self.layout_hunk_diff_close_indicators(
expanded_add_hunks_by_rows,
line_height,
scroll_pixel_position,
&gutter_dimensions,
&gutter_hitbox,
&rows_with_hunk_bounds,
expanded_add_hunks_by_rows,
cx,
);
@@ -5460,7 +5494,7 @@ impl Element for EditorElement {
EditorLayout {
mode: snapshot.mode,
position_map: Arc::new(PositionMap {
position_map: Rc::new(PositionMap {
size: bounds.size,
scroll_pixel_position,
scroll_max,
@@ -5591,6 +5625,16 @@ impl Element for EditorElement {
}
}
pub(super) fn gutter_bounds(
editor_bounds: Bounds<Pixels>,
gutter_dimensions: GutterDimensions,
) -> Bounds<Pixels> {
Bounds {
origin: editor_bounds.origin,
size: size(gutter_dimensions.width, editor_bounds.size.height),
}
}
impl IntoElement for EditorElement {
type Element = Self;
@@ -5600,7 +5644,7 @@ impl IntoElement for EditorElement {
}
pub struct EditorLayout {
position_map: Arc<PositionMap>,
position_map: Rc<PositionMap>,
hitbox: Hitbox,
text_hitbox: Hitbox,
gutter_hitbox: Hitbox,

View File

@@ -786,6 +786,7 @@ mod tests {
let mut cx = EditorLspTestContext::new_rust(
lsp::ServerCapabilities {
hover_provider: Some(lsp::HoverProviderCapability::Simple(true)),
definition_provider: Some(lsp::OneOf::Left(true)),
..Default::default()
},
cx,

View File

@@ -5,7 +5,7 @@ use std::{
use collections::{hash_map, HashMap, HashSet};
use git::diff::{DiffHunk, DiffHunkStatus};
use gpui::{Action, AppContext, Hsla, Model, MouseButton, Subscription, Task, View};
use gpui::{Action, AppContext, CursorStyle, Hsla, Model, MouseButton, Subscription, Task, View};
use language::Buffer;
use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptRange, MultiBuffer, MultiBufferRow, MultiBufferSnapshot, ToPoint,
@@ -13,8 +13,8 @@ use multi_buffer::{
use settings::SettingsStore;
use text::{BufferId, Point};
use ui::{
h_flex, v_flex, ActiveTheme, Context as _, ContextMenu, InteractiveElement, IntoElement,
ParentElement, Pixels, Styled, ViewContext, VisualContext,
div, h_flex, rems, v_flex, ActiveTheme, Context as _, ContextMenu, InteractiveElement,
IntoElement, ParentElement, Pixels, Styled, ViewContext, VisualContext,
};
use util::{debug_panic, RangeExt};
@@ -24,8 +24,8 @@ use crate::{
hunk_status, hunks_for_selections,
mouse_context_menu::MouseContextMenu,
BlockDisposition, BlockProperties, BlockStyle, CustomBlockId, DiffRowHighlight, Editor,
EditorSnapshot, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks, ToDisplayPoint,
ToggleHunkDiff,
EditorElement, EditorSnapshot, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks,
ToDisplayPoint, ToggleHunkDiff,
};
#[derive(Debug, Clone)]
@@ -430,7 +430,6 @@ impl Editor {
let (editor_height, editor_with_deleted_text) =
editor_with_deleted_text(diff_base_buffer, deleted_hunk_color, hunk, cx);
let editor = cx.view().clone();
let editor_model = cx.model().clone();
let hunk = hunk.clone();
let mut new_block_ids = self.insert_blocks(
Some(BlockProperties {
@@ -439,37 +438,87 @@ impl Editor {
style: BlockStyle::Flex,
disposition: BlockDisposition::Above,
render: Box::new(move |cx| {
let close_button = editor.update(cx.context, |editor, cx| {
let editor_snapshot = editor.snapshot(cx);
let hunk_start_row = hunk
.multi_buffer_range
.start
.to_display_point(&editor_snapshot)
.row();
editor.render_close_hunk_diff_button(hunk.clone(), hunk_start_row, cx)
});
let gutter_dimensions = editor_model.read(cx).gutter_dimensions;
let Some(gutter_bounds) = editor.read(cx).gutter_bounds() else {
return div().into_any_element();
};
let (gutter_dimensions, hunk_bounds, close_button) =
editor.update(cx.context, |editor, cx| {
let editor_snapshot = editor.snapshot(cx);
let hunk_display_range = hunk
.multi_buffer_range
.clone()
.to_display_points(&editor_snapshot);
let gutter_dimensions = editor.gutter_dimensions;
let hunk_bounds = EditorElement::diff_hunk_bounds(
&editor_snapshot,
cx.line_height(),
gutter_bounds,
&DisplayDiffHunk::Unfolded {
diff_base_byte_range: hunk.diff_base_byte_range.clone(),
multi_buffer_range: hunk.multi_buffer_range.clone(),
display_row_range: hunk_display_range.start.row()
..hunk_display_range.end.row(),
status: hunk.status,
},
);
let close_button = editor.close_hunk_diff_button(
hunk.clone(),
hunk_display_range.start.row(),
cx,
);
(gutter_dimensions, hunk_bounds, close_button)
});
let click_editor = editor.clone();
let clicked_hunk = hunk.clone();
h_flex()
.id("gutter with editor")
.bg(deleted_hunk_color)
.size_full()
.child(
v_flex()
h_flex()
.id("gutter")
.max_w(gutter_dimensions.full_width())
.min_w(gutter_dimensions.full_width())
.size_full()
.on_mouse_down(MouseButton::Left, {
let click_hunk = hunk.clone();
move |e, cx| {
let modifiers = e.modifiers;
if modifiers.control || modifiers.platform {
click_editor.update(cx, |editor, cx| {
editor.toggle_hovered_hunk(&click_hunk, cx);
});
}
}
})
.child(close_button),
.child(
h_flex()
.id("gutter hunk")
.pl(gutter_dimensions.margin
+ gutter_dimensions
.git_blame_entries_width
.unwrap_or_default())
.max_w(hunk_bounds.size.width)
.min_w(hunk_bounds.size.width)
.size_full()
.cursor(CursorStyle::PointingHand)
.on_mouse_down(MouseButton::Left, {
let click_hunk = hunk.clone();
move |e, cx| {
let modifiers = e.modifiers;
if modifiers.control || modifiers.platform {
click_editor.update(cx, |editor, cx| {
editor.toggle_hovered_hunk(&click_hunk, cx);
});
} else {
click_editor.update(cx, |editor, cx| {
editor.open_hunk_context_menu(
clicked_hunk.clone(),
e.position,
cx,
);
});
}
}
}),
)
.child(
v_flex()
.size_full()
.pt(rems(0.25))
.justify_start()
.child(close_button),
),
)
.child(editor_with_deleted_text.clone())
.into_any_element()

View File

@@ -1,7 +1,9 @@
use crate::{
editor_settings::SeedQuerySetting, persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll,
Editor, EditorEvent, EditorSettings, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot,
NavigationData, SearchWithinRange, ToPoint as _,
editor_settings::SeedQuerySetting,
persistence::{SerializedEditor, DB},
scroll::ScrollAnchor,
Anchor, Autoscroll, Editor, EditorEvent, EditorSettings, ExcerptId, ExcerptRange, MultiBuffer,
MultiBufferSnapshot, NavigationData, SearchWithinRange, ToPoint as _,
};
use anyhow::{anyhow, Context as _, Result};
use collections::HashSet;
@@ -914,18 +916,23 @@ impl SerializableItem for Editor {
item_id: ItemId,
cx: &mut ViewContext<Pane>,
) -> Task<Result<View<Self>>> {
let path_content_language = match DB
.get_path_and_contents(item_id, workspace_id)
let serialized_editor = match DB
.get_serialized_editor(item_id, workspace_id)
.context("Failed to query editor state")
{
Ok(Some((path, content, language))) => {
Ok(Some(serialized_editor)) => {
if ProjectSettings::get_global(cx)
.session
.restore_unsaved_buffers
{
(path, content, language)
serialized_editor
} else {
(path, None, None)
SerializedEditor {
path: serialized_editor.path,
contents: None,
language: None,
mtime: None,
}
}
}
Ok(None) => {
@@ -936,34 +943,48 @@ impl SerializableItem for Editor {
}
};
match path_content_language {
(None, Some(content), language_name) => cx.spawn(|_, mut cx| async move {
let language = if let Some(language_name) = language_name {
let language_registry =
project.update(&mut cx, |project, _| project.languages().clone())?;
let buffer_task = match serialized_editor {
SerializedEditor {
path: None,
contents: Some(contents),
language,
..
} => cx.spawn(|_, mut cx| {
let project = project.clone();
async move {
let language = if let Some(language_name) = language {
let language_registry =
project.update(&mut cx, |project, _| project.languages().clone())?;
Some(language_registry.language_for_name(&language_name).await?)
} else {
None
};
// We don't fail here, because we'd rather not set the language if the name changed
// than fail to restore the buffer.
language_registry
.language_for_name(&language_name)
.await
.ok()
} else {
None
};
// First create the empty buffer
let buffer = project.update(&mut cx, |project, cx| {
project.create_local_buffer("", language, cx)
})?;
// First create the empty buffer
let buffer = project.update(&mut cx, |project, cx| {
project.create_local_buffer("", language, cx)
})?;
// Then set the text so that the dirty bit is set correctly
buffer.update(&mut cx, |buffer, cx| {
buffer.set_text(content, cx);
})?;
// Then set the text so that the dirty bit is set correctly
buffer.update(&mut cx, |buffer, cx| {
buffer.set_text(contents, cx);
})?;
cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project), cx);
editor.read_scroll_position_from_db(item_id, workspace_id, cx);
editor
})
anyhow::Ok(buffer)
}
}),
(Some(path), contents, _) => {
SerializedEditor {
path: Some(path),
contents,
mtime,
..
} => {
let project_item = project.update(cx, |project, cx| {
let (worktree, path) = project
.find_worktree(&path, cx)
@@ -978,7 +999,7 @@ impl SerializableItem for Editor {
project_item
.map(|project_item| {
cx.spawn(|pane, mut cx| async move {
cx.spawn(|_, mut cx| async move {
let (_, project_item) = project_item.await?;
let buffer = project_item.downcast::<Buffer>().map_err(|_| {
anyhow!("Project item at stored path was not a buffer")
@@ -988,27 +1009,43 @@ impl SerializableItem for Editor {
// disk and then overwrite the content.
// But for now, it keeps the implementation of the content serialization
// simple, because we don't have to persist all of the metadata that we get
// by loading the file (git diff base, mtime, ...).
// by loading the file (git diff base, ...).
if let Some(buffer_text) = contents {
buffer.update(&mut cx, |buffer, cx| {
// If we did restore an mtime, we want to store it on the buffer
// so that the next edit will mark the buffer as dirty/conflicted.
if mtime.is_some() {
buffer.did_reload(
buffer.version(),
buffer.line_ending(),
mtime,
cx,
);
}
buffer.set_text(buffer_text, cx);
})?;
}
pane.update(&mut cx, |_, cx| {
cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project), cx);
editor.read_scroll_position_from_db(item_id, workspace_id, cx);
editor
})
})
Ok(buffer)
})
})
.unwrap_or_else(|error| Task::ready(Err(error)))
}
_ => Task::ready(Err(anyhow!("No path or contents found for buffer"))),
}
_ => return Task::ready(Err(anyhow!("No path or contents found for buffer"))),
};
cx.spawn(|pane, mut cx| async move {
let buffer = buffer_task.await?;
pane.update(&mut cx, |_, cx| {
cx.new_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project), cx);
editor.read_scroll_position_from_db(item_id, workspace_id, cx);
editor
})
})
})
}
fn serialize(
@@ -1036,36 +1073,33 @@ impl SerializableItem for Editor {
let buffer = self.buffer().read(cx).as_singleton()?;
let is_dirty = buffer.read(cx).is_dirty();
let path = buffer
.read(cx)
.file()
.and_then(|file| file.as_local())
.map(|file| file.abs_path(cx));
let local_file = buffer.read(cx).file().and_then(|file| file.as_local());
let path = local_file.map(|file| file.abs_path(cx));
let mtime = buffer.read(cx).saved_mtime();
let snapshot = buffer.read(cx).snapshot();
Some(cx.spawn(|_this, cx| async move {
cx.background_executor()
.spawn(async move {
if let Some(path) = path {
DB.save_path(item_id, workspace_id, path.clone())
.await
.context("failed to save path of buffer")?
}
let (contents, language) = if serialize_dirty_buffers && is_dirty {
let contents = snapshot.text();
let language = snapshot.language().map(|lang| lang.name().to_string());
(Some(contents), language)
} else {
(None, None)
};
if serialize_dirty_buffers {
let (contents, language) = if is_dirty {
let contents = snapshot.text();
let language = snapshot.language().map(|lang| lang.name().to_string());
(Some(contents), language)
} else {
(None, None)
};
let editor = SerializedEditor {
path,
contents,
language,
mtime,
};
DB.save_contents(item_id, workspace_id, contents, language)
.await?;
}
anyhow::Ok(())
DB.save_serialized_editor(item_id, workspace_id, editor)
.await
.context("failed to save serialized editor")
})
.await
.context("failed to save contents of buffer")?;
@@ -1474,10 +1508,16 @@ fn path_for_file<'a>(
#[cfg(test)]
mod tests {
use crate::editor_tests::init_test;
use super::*;
use gpui::AppContext;
use language::TestFile;
use std::path::Path;
use gpui::{AppContext, VisualTestContext};
use language::{LanguageMatcher, TestFile};
use project::FakeFs;
use std::{
path::{Path, PathBuf},
time::SystemTime,
};
#[gpui::test]
fn test_path_for_file(cx: &mut AppContext) {
@@ -1487,4 +1527,183 @@ mod tests {
};
assert_eq!(path_for_file(&file, 0, false, cx), None);
}
async fn deserialize_editor(
item_id: ItemId,
workspace_id: WorkspaceId,
workspace: View<Workspace>,
project: Model<Project>,
cx: &mut VisualTestContext,
) -> View<Editor> {
workspace
.update(cx, |workspace, cx| {
let pane = workspace.active_pane();
pane.update(cx, |_, cx| {
Editor::deserialize(
project.clone(),
workspace.weak_handle(),
workspace_id,
item_id,
cx,
)
})
})
.await
.unwrap()
}
fn rust_language() -> Arc<language::Language> {
Arc::new(language::Language::new(
language::LanguageConfig {
name: "Rust".into(),
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
))
}
#[gpui::test]
async fn test_deserialize(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
let now = SystemTime::now();
let fs = FakeFs::new(cx.executor());
fs.set_next_mtime(now);
fs.insert_file("/file.rs", Default::default()).await;
// Test case 1: Deserialize with path and contents
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
let item_id = 1234 as ItemId;
let serialized_editor = SerializedEditor {
path: Some(PathBuf::from("/file.rs")),
contents: Some("fn main() {}".to_string()),
language: Some("Rust".to_string()),
mtime: Some(now),
};
DB.save_serialized_editor(item_id, workspace_id, serialized_editor.clone())
.await
.unwrap();
let deserialized =
deserialize_editor(item_id, workspace_id, workspace, project, cx).await;
deserialized.update(cx, |editor, cx| {
assert_eq!(editor.text(cx), "fn main() {}");
assert!(editor.is_dirty(cx));
assert!(!editor.has_conflict(cx));
let buffer = editor.buffer().read(cx).as_singleton().unwrap().read(cx);
assert!(buffer.file().is_some());
});
}
// Test case 2: Deserialize with only path
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
let item_id = 5678 as ItemId;
let serialized_editor = SerializedEditor {
path: Some(PathBuf::from("/file.rs")),
contents: None,
language: None,
mtime: None,
};
DB.save_serialized_editor(item_id, workspace_id, serialized_editor)
.await
.unwrap();
let deserialized =
deserialize_editor(item_id, workspace_id, workspace, project, cx).await;
deserialized.update(cx, |editor, cx| {
assert_eq!(editor.text(cx), ""); // The file should be empty as per our initial setup
assert!(!editor.is_dirty(cx));
assert!(!editor.has_conflict(cx));
let buffer = editor.buffer().read(cx).as_singleton().unwrap().read(cx);
assert!(buffer.file().is_some());
});
}
// Test case 3: Deserialize with no path (untitled buffer, with content and language)
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
// Add Rust to the language, so that we can restore the language of the buffer
project.update(cx, |project, _| project.languages().add(rust_language()));
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
let item_id = 9012 as ItemId;
let serialized_editor = SerializedEditor {
path: None,
contents: Some("hello".to_string()),
language: Some("Rust".to_string()),
mtime: None,
};
DB.save_serialized_editor(item_id, workspace_id, serialized_editor)
.await
.unwrap();
let deserialized =
deserialize_editor(item_id, workspace_id, workspace, project, cx).await;
deserialized.update(cx, |editor, cx| {
assert_eq!(editor.text(cx), "hello");
assert!(editor.is_dirty(cx)); // The editor should be dirty for an untitled buffer
let buffer = editor.buffer().read(cx).as_singleton().unwrap().read(cx);
assert_eq!(
buffer.language().map(|lang| lang.name()).as_deref(),
Some("Rust")
); // Language should be set to Rust
assert!(buffer.file().is_none()); // The buffer should not have an associated file
});
}
// Test case 4: Deserialize with path, content, and old mtime
{
let project = Project::test(fs.clone(), ["/file.rs".as_ref()], cx).await;
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
let item_id = 9345 as ItemId;
let old_mtime = now
.checked_sub(std::time::Duration::from_secs(60 * 60 * 24))
.unwrap();
let serialized_editor = SerializedEditor {
path: Some(PathBuf::from("/file.rs")),
contents: Some("fn main() {}".to_string()),
language: Some("Rust".to_string()),
mtime: Some(old_mtime),
};
DB.save_serialized_editor(item_id, workspace_id, serialized_editor)
.await
.unwrap();
let deserialized =
deserialize_editor(item_id, workspace_id, workspace, project, cx).await;
deserialized.update(cx, |editor, cx| {
assert_eq!(editor.text(cx), "fn main() {}");
assert!(editor.has_conflict(cx)); // The editor should have a conflict
});
}
}
}

View File

@@ -10,7 +10,6 @@ use gpui::prelude::FluentBuilder;
use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext};
use workspace::OpenInTerminal;
#[derive(Debug)]
pub enum MenuPosition {
/// When the editor is scrolled, the context menu stays on the exact
/// same position on the screen, never disappearing.
@@ -30,15 +29,6 @@ pub struct MouseContextMenu {
_subscription: Subscription,
}
impl std::fmt::Debug for MouseContextMenu {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MouseContextMenu")
.field("position", &self.position)
.field("context_menu", &self.context_menu)
.finish()
}
}
impl MouseContextMenu {
pub(crate) fn pinned_to_editor(
editor: &mut Editor,

View File

@@ -1,12 +1,80 @@
use anyhow::Result;
use db::sqlez::bindable::{Bind, Column, StaticColumnCount};
use db::sqlez::statement::Statement;
use std::path::PathBuf;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use db::sqlez_macros::sql;
use db::{define_connection, query};
use workspace::{ItemId, WorkspaceDb, WorkspaceId};
#[derive(Clone, Debug, PartialEq, Default)]
pub(crate) struct SerializedEditor {
pub(crate) path: Option<PathBuf>,
pub(crate) contents: Option<String>,
pub(crate) language: Option<String>,
pub(crate) mtime: Option<SystemTime>,
}
impl StaticColumnCount for SerializedEditor {
fn column_count() -> usize {
5
}
}
impl Bind for SerializedEditor {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let start_index = statement.bind(&self.path, start_index)?;
let start_index = statement.bind(&self.contents, start_index)?;
let start_index = statement.bind(&self.language, start_index)?;
let mtime = self.mtime.and_then(|mtime| {
mtime
.duration_since(UNIX_EPOCH)
.ok()
.map(|duration| (duration.as_secs() as i64, duration.subsec_nanos() as i32))
});
let start_index = match mtime {
Some((seconds, nanos)) => {
let start_index = statement.bind(&seconds, start_index)?;
statement.bind(&nanos, start_index)?
}
None => {
let start_index = statement.bind::<Option<i64>>(&None, start_index)?;
statement.bind::<Option<i32>>(&None, start_index)?
}
};
Ok(start_index)
}
}
impl Column for SerializedEditor {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (path, start_index): (Option<PathBuf>, i32) = Column::column(statement, start_index)?;
let (contents, start_index): (Option<String>, i32) =
Column::column(statement, start_index)?;
let (language, start_index): (Option<String>, i32) =
Column::column(statement, start_index)?;
let (mtime_seconds, start_index): (Option<i64>, i32) =
Column::column(statement, start_index)?;
let (mtime_nanos, start_index): (Option<i32>, i32) =
Column::column(statement, start_index)?;
let mtime = mtime_seconds
.zip(mtime_nanos)
.map(|(seconds, nanos)| UNIX_EPOCH + Duration::new(seconds as u64, nanos as u32));
let editor = Self {
path,
contents,
language,
mtime,
};
Ok((editor, start_index))
}
}
define_connection!(
// Current schema shape using pseudo-rust syntax:
// editors(
@@ -18,6 +86,8 @@ define_connection!(
// scroll_horizontal_offset: f32,
// content: Option<String>,
// language: Option<String>,
// mtime_seconds: Option<i64>,
// mtime_nanos: Option<i32>,
// )
pub static ref DB: EditorDb<WorkspaceDb> =
&[sql! (
@@ -61,41 +131,36 @@ define_connection!(
DROP TABLE editors;
ALTER TABLE new_editors_tmp RENAME TO editors;
)];
),
sql! (
ALTER TABLE editors ADD COLUMN mtime_seconds INTEGER DEFAULT NULL;
ALTER TABLE editors ADD COLUMN mtime_nanos INTEGER DEFAULT NULL;
),
];
);
impl EditorDb {
query! {
pub fn get_path_and_contents(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<(Option<PathBuf>, Option<String>, Option<String>)>> {
SELECT path, contents, language FROM editors
pub fn get_serialized_editor(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<SerializedEditor>> {
SELECT path, contents, language, mtime_seconds, mtime_nanos FROM editors
WHERE item_id = ? AND workspace_id = ?
}
}
query! {
pub async fn save_path(item_id: ItemId, workspace_id: WorkspaceId, path: PathBuf) -> Result<()> {
pub async fn save_serialized_editor(item_id: ItemId, workspace_id: WorkspaceId, serialized_editor: SerializedEditor) -> Result<()> {
INSERT INTO editors
(item_id, workspace_id, path)
(item_id, workspace_id, path, contents, language, mtime_seconds, mtime_nanos)
VALUES
(?1, ?2, ?3)
(?1, ?2, ?3, ?4, ?5, ?6, ?7)
ON CONFLICT DO UPDATE SET
item_id = ?1,
workspace_id = ?2,
path = ?3
}
}
query! {
pub async fn save_contents(item_id: ItemId, workspace: WorkspaceId, contents: Option<String>, language: Option<String>) -> Result<()> {
INSERT INTO editors
(item_id, workspace_id, contents, language)
VALUES
(?1, ?2, ?3, ?4)
ON CONFLICT DO UPDATE SET
item_id = ?1,
workspace_id = ?2,
contents = ?3,
language = ?4
path = ?3,
contents = ?4,
language = ?5,
mtime_seconds = ?6,
mtime_nanos = ?7
}
}
@@ -158,41 +223,79 @@ mod tests {
use gpui;
#[gpui::test]
async fn test_saving_content() {
env_logger::try_init().ok();
async fn test_save_and_get_serialized_editor() {
let workspace_id = workspace::WORKSPACE_DB.next_id().await.unwrap();
// Sanity check: make sure there is no row in the `editors` table
assert_eq!(DB.get_path_and_contents(1234, workspace_id).unwrap(), None);
let serialized_editor = SerializedEditor {
path: Some(PathBuf::from("testing.txt")),
contents: None,
language: None,
mtime: None,
};
// Save content/language
DB.save_contents(
1234,
workspace_id,
Some("testing".into()),
Some("Go".into()),
)
.await
.unwrap();
// Check that it can be read from DB
let path_and_contents = DB.get_path_and_contents(1234, workspace_id).unwrap();
let (path, contents, language) = path_and_contents.unwrap();
assert!(path.is_none());
assert_eq!(contents, Some("testing".to_owned()));
assert_eq!(language, Some("Go".to_owned()));
// Update it with NULL
DB.save_contents(1234, workspace_id, None, None)
DB.save_serialized_editor(1234, workspace_id, serialized_editor.clone())
.await
.unwrap();
// Check that it worked
let path_and_contents = DB.get_path_and_contents(1234, workspace_id).unwrap();
let (path, contents, language) = path_and_contents.unwrap();
assert!(path.is_none());
assert!(contents.is_none());
assert!(language.is_none());
let have = DB
.get_serialized_editor(1234, workspace_id)
.unwrap()
.unwrap();
assert_eq!(have, serialized_editor);
// Now update contents and language
let serialized_editor = SerializedEditor {
path: Some(PathBuf::from("testing.txt")),
contents: Some("Test".to_owned()),
language: Some("Go".to_owned()),
mtime: None,
};
DB.save_serialized_editor(1234, workspace_id, serialized_editor.clone())
.await
.unwrap();
let have = DB
.get_serialized_editor(1234, workspace_id)
.unwrap()
.unwrap();
assert_eq!(have, serialized_editor);
// Now set all the fields to NULL
let serialized_editor = SerializedEditor {
path: None,
contents: None,
language: None,
mtime: None,
};
DB.save_serialized_editor(1234, workspace_id, serialized_editor.clone())
.await
.unwrap();
let have = DB
.get_serialized_editor(1234, workspace_id)
.unwrap()
.unwrap();
assert_eq!(have, serialized_editor);
// Storing and retrieving mtime
let now = SystemTime::now();
let serialized_editor = SerializedEditor {
path: None,
contents: None,
language: None,
mtime: Some(now),
};
DB.save_serialized_editor(1234, workspace_id, serialized_editor.clone())
.await
.unwrap();
let have = DB
.get_serialized_editor(1234, workspace_id)
.unwrap()
.unwrap();
assert_eq!(have, serialized_editor);
}
}

View File

@@ -44,7 +44,7 @@ impl SelectionsCollection {
buffer,
next_selection_id: 1,
line_mode: false,
disjoint: Arc::from([]),
disjoint: Arc::default(),
pending: Some(PendingSelection {
selection: Selection {
id: 0,
@@ -398,7 +398,7 @@ impl<'a> MutableSelectionsCollection<'a> {
}
pub fn clear_disjoint(&mut self) {
self.collection.disjoint = Arc::from([]);
self.collection.disjoint = Arc::default();
}
pub fn delete(&mut self, selection_id: usize) {

View File

@@ -3,7 +3,7 @@ use crate::Editor;
use gpui::{Task as AsyncTask, WindowContext};
use project::Location;
use task::{TaskContext, TaskVariables, VariableName};
use text::{Point, ToOffset, ToPoint};
use text::{ToOffset, ToPoint};
use workspace::Workspace;
fn task_context_with_editor(
@@ -14,11 +14,7 @@ fn task_context_with_editor(
return AsyncTask::ready(None);
};
let (selection, buffer, editor_snapshot) = {
let mut selection = editor.selections.newest::<Point>(cx);
if editor.selections.line_mode {
selection.start = Point::new(selection.start.row, 0);
selection.end = Point::new(selection.end.row + 1, 0);
}
let selection = editor.selections.newest_adjusted(cx);
let Some((buffer, _, _)) = editor
.buffer()
.read(cx)

View File

@@ -27,6 +27,7 @@ pub fn marked_display_snapshot(
let font = Font {
family: "Zed Plex Mono".into(),
features: FontFeatures::default(),
fallbacks: None,
weight: FontWeight::default(),
style: FontStyle::default(),
};
@@ -62,6 +63,7 @@ pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContex
editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
}
#[track_caller]
pub fn assert_text_with_selections(
editor: &mut Editor,
marked_text: &str,

View File

@@ -327,7 +327,7 @@ impl EditorTestContext {
.background_highlights
.get(&TypeId::of::<Tag>())
.map(|h| h.1.clone())
.unwrap_or_else(|| Arc::from([]))
.unwrap_or_else(|| Arc::default())
.into_iter()
.map(|range| range.to_offset(&snapshot.buffer_snapshot))
.collect()

View File

@@ -21,7 +21,6 @@ assistant_slash_command.workspace = true
async-compression.workspace = true
async-tar.workspace = true
async-trait.workspace = true
cap-std.workspace = true
client.workspace = true
collections.workspace = true
fs.workspace = true

View File

@@ -363,6 +363,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
},
);
#[allow(clippy::let_underscore_future)]
let _ = store.update(cx, |store, cx| store.reload(None, cx));
cx.executor().advance_clock(RELOAD_DEBOUNCE_DURATION);

View File

@@ -159,29 +159,25 @@ impl WasmHost {
}
async fn build_wasi_ctx(&self, manifest: &Arc<ExtensionManifest>) -> Result<wasi::WasiCtx> {
use cap_std::{ambient_authority, fs::Dir};
let extension_work_dir = self.work_dir.join(manifest.id.as_ref());
self.fs
.create_dir(&extension_work_dir)
.await
.context("failed to create extension work dir")?;
let work_dir_preopen = Dir::open_ambient_dir(&extension_work_dir, ambient_authority())
.context("failed to preopen extension work directory")?;
let current_dir_preopen = work_dir_preopen
.try_clone()
.context("failed to preopen extension current directory")?;
let extension_work_dir = extension_work_dir.to_string_lossy();
let perms = wasi::FilePerms::all();
let file_perms = wasi::FilePerms::all();
let dir_perms = wasi::DirPerms::all();
Ok(wasi::WasiCtxBuilder::new()
.inherit_stdio()
.preopened_dir(current_dir_preopen, dir_perms, perms, ".")
.preopened_dir(work_dir_preopen, dir_perms, perms, &extension_work_dir)
.env("PWD", &extension_work_dir)
.preopened_dir(&extension_work_dir, ".", dir_perms, file_perms)?
.preopened_dir(
&extension_work_dir,
&extension_work_dir.to_string_lossy(),
dir_perms,
file_perms,
)?
.env("PWD", &extension_work_dir.to_string_lossy())
.env("RUST_BACKTRACE", "full")
.build())
}

View File

@@ -29,7 +29,7 @@ pub fn new_linker(
f: impl Fn(&mut Linker<WasmState>, fn(&mut WasmState) -> &mut WasmState) -> Result<()>,
) -> Linker<WasmState> {
let mut linker = Linker::new(&wasm_engine());
wasmtime_wasi::command::add_to_linker(&mut linker).unwrap();
wasmtime_wasi::add_to_linker_async(&mut linker).unwrap();
f(&mut linker, wasi_view).unwrap();
linker
}

View File

@@ -12,6 +12,7 @@ pub const MIN_VERSION: SemanticVersion = SemanticVersion::new(0, 0, 1);
wasmtime::component::bindgen!({
async: true,
trappable_imports: true,
path: "../extension_api/wit/since_v0.0.1",
with: {
"worktree": ExtensionWorktree,

View File

@@ -11,6 +11,7 @@ pub const MIN_VERSION: SemanticVersion = SemanticVersion::new(0, 0, 4);
wasmtime::component::bindgen!({
async: true,
trappable_imports: true,
path: "../extension_api/wit/since_v0.0.4",
with: {
"worktree": ExtensionWorktree,

View File

@@ -12,6 +12,7 @@ pub const MAX_VERSION: SemanticVersion = SemanticVersion::new(0, 0, 6);
wasmtime::component::bindgen!({
async: true,
trappable_imports: true,
path: "../extension_api/wit/since_v0.0.6",
with: {
"worktree": ExtensionWorktree,

View File

@@ -26,6 +26,7 @@ pub const MAX_VERSION: SemanticVersion = SemanticVersion::new(0, 0, 7);
wasmtime::component::bindgen!({
async: true,
trappable_imports: true,
path: "../extension_api/wit/since_v0.0.7",
with: {
"worktree": ExtensionWorktree,

View File

@@ -134,6 +134,7 @@ impl ExtensionFilter {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
enum Feature {
Git,
OpenIn,
Vim,
LanguageBash,
LanguageC,
@@ -150,6 +151,19 @@ fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
KEYWORDS_BY_FEATURE.get_or_init(|| {
BTreeMap::from_iter([
(Feature::Git, vec!["git"]),
(
Feature::OpenIn,
vec![
"github",
"gitlab",
"bitbucket",
"codeberg",
"sourcehut",
"permalink",
"link",
"open in",
],
),
(Feature::Vim, vec!["vim"]),
(Feature::LanguageBash, vec!["sh", "bash"]),
(Feature::LanguageC, vec!["c", "clang"]),
@@ -802,6 +816,7 @@ impl ExtensionsPage {
},
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(1.3),
@@ -957,6 +972,11 @@ impl ExtensionsPage {
"Zed comes with basic Git support. More Git features are coming in the future.",
)
.docs_url("https://zed.dev/docs/git"),
Feature::OpenIn => FeatureUpsell::new(
telemetry,
"Zed supports linking to a source line on GitHub and others.",
)
.docs_url("https://zed.dev/docs/git#git-integrations"),
Feature::Vim => FeatureUpsell::new(telemetry, "Vim support is built-in to Zed!")
.docs_url("https://zed.dev/docs/vim")
.child(CheckboxWithLabel::new(

View File

@@ -998,7 +998,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("b0.5")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1006,7 +1006,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("c1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1014,7 +1014,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("a1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1022,7 +1022,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("a0.5")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1030,7 +1030,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("b1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
];
@@ -1044,7 +1044,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("a1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1052,7 +1052,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("b1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1060,7 +1060,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("c1.0")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1068,7 +1068,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("a0.5")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
ProjectPanelOrdMatch(PathMatch {
@@ -1076,7 +1076,7 @@ mod tests {
positions: Vec::new(),
worktree_id: 0,
path: Arc::from(Path::new("b0.5")),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: 0,
}),
]

View File

@@ -821,6 +821,11 @@ impl FakeFs {
})
}
pub fn set_next_mtime(&self, next_mtime: SystemTime) {
let mut state = self.state.lock();
state.next_mtime = next_mtime;
}
pub async fn insert_file(&self, path: impl AsRef<Path>, content: Vec<u8>) {
self.write_file_internal(path, content).unwrap()
}

View File

@@ -404,7 +404,12 @@ mod tests {
#[test]
fn test_match_multibyte_path_entries() {
let paths = vec!["aαbβ/cγ", "αβγδ/bcde", "c1⃣2⃣3⃣/d4⃣5⃣6⃣/e7⃣8⃣9⃣/f", "/d/🆒/h"];
let paths = vec![
"aαbβ/cγ",
"αβγδ/bcde",
"c1⃣2⃣3⃣/d4⃣5⃣6⃣/e7⃣8⃣9⃣/f",
"/d/🆒/h",
];
assert_eq!("1".len(), 7);
assert_eq!(
match_single_path_query("bcd", false, &paths),

View File

@@ -120,7 +120,7 @@ pub fn match_fixed_path_set(
worktree_id,
positions: Vec::new(),
path: Arc::from(candidate.path),
path_prefix: Arc::from(""),
path_prefix: Arc::default(),
distance_to_relative_ancestor: usize::MAX,
},
);

View File

@@ -5,6 +5,9 @@ edition = "2021"
publish = false
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/google_ai.rs"

View File

@@ -73,7 +73,7 @@ thiserror.workspace = true
time.workspace = true
util.workspace = true
uuid.workspace = true
waker-fn = "1.1.0"
waker-fn = "1.2.0"
[dev-dependencies]
backtrace = "0.3"
@@ -93,6 +93,7 @@ cbindgen = { version = "0.26.0", default-features = false }
block = "0.1"
cocoa.workspace = true
core-foundation.workspace = true
core-foundation-sys = "0.8"
core-graphics = "0.23"
core-text = "20.1"
foreign-types = "0.5"
@@ -150,7 +151,7 @@ x11-clipboard = "0.9.2"
[target.'cfg(windows)'.dependencies]
windows.workspace = true
windows-core = "0.57"
windows-core = "0.58"
[[example]]
name = "hello_world"

View File

@@ -0,0 +1,50 @@
use gpui::{
div, img, prelude::*, App, AppContext, ImageSource, Render, ViewContext, WindowOptions,
};
use std::path::PathBuf;
struct GifViewer {
gif_path: PathBuf,
}
impl GifViewer {
fn new(gif_path: PathBuf) -> Self {
Self { gif_path }
}
}
impl Render for GifViewer {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div().size_full().child(
img(ImageSource::File(self.gif_path.clone().into()))
.size_full()
.object_fit(gpui::ObjectFit::Contain)
.id("gif"),
)
}
}
fn main() {
env_logger::init();
App::new().run(|cx: &mut AppContext| {
let cwd = std::env::current_dir().expect("Failed to get current working directory");
let gif_path = cwd.join("crates/gpui/examples/image/black-cat-typing.gif");
if !gif_path.exists() {
eprintln!("Image file not found at {:?}", gif_path);
eprintln!("Make sure you're running this example from the root of the gpui crate");
cx.quit();
return;
}
cx.open_window(
WindowOptions {
focus: true,
..Default::default()
},
|cx| cx.new_view(|_cx| GifViewer::new(gif_path)),
)
.unwrap();
cx.activate(true);
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

View File

@@ -1,6 +1,7 @@
use crate::{size, DevicePixels, Result, SharedString, Size};
use smallvec::SmallVec;
use image::RgbaImage;
use image::{Delay, Frame};
use std::{
borrow::Cow,
fmt,
@@ -34,43 +35,54 @@ pub struct ImageId(usize);
#[derive(PartialEq, Eq, Hash, Clone)]
pub(crate) struct RenderImageParams {
pub(crate) image_id: ImageId,
pub(crate) frame_index: usize,
}
/// A cached and processed image.
pub struct ImageData {
/// The ID associated with this image
pub id: ImageId,
data: RgbaImage,
data: SmallVec<[Frame; 1]>,
}
impl ImageData {
/// Create a new image from the given data.
pub fn new(data: RgbaImage) -> Self {
pub fn new(data: impl Into<SmallVec<[Frame; 1]>>) -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
Self {
id: ImageId(NEXT_ID.fetch_add(1, SeqCst)),
data,
data: data.into(),
}
}
/// Convert this image into a byte slice.
pub fn as_bytes(&self) -> &[u8] {
&self.data
pub fn as_bytes(&self, frame_index: usize) -> &[u8] {
&self.data[frame_index].buffer()
}
/// Get the size of this image, in pixels
pub fn size(&self) -> Size<DevicePixels> {
let (width, height) = self.data.dimensions();
/// Get the size of this image, in pixels.
pub fn size(&self, frame_index: usize) -> Size<DevicePixels> {
let (width, height) = self.data[frame_index].buffer().dimensions();
size(width.into(), height.into())
}
/// Get the delay of this frame from the previous
pub fn delay(&self, frame_index: usize) -> Delay {
self.data[frame_index].delay()
}
/// Get the number of frames for this image.
pub fn frame_count(&self) -> usize {
self.data.len()
}
}
impl fmt::Debug for ImageData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ImageData")
.field("id", &self.id)
.field("size", &self.data.dimensions())
.field("size", &self.size(0))
.finish()
}
}

View File

@@ -323,14 +323,14 @@ impl Interactivity {
pub fn on_boxed_action(
&mut self,
action: &dyn Action,
listener: impl Fn(&Box<dyn Action>, &mut WindowContext) + 'static,
listener: impl Fn(&dyn Action, &mut WindowContext) + 'static,
) {
let action = action.boxed_clone();
self.action_listeners.push((
(*action).type_id(),
Box::new(move |_, phase, cx| {
if phase == DispatchPhase::Bubble {
(listener)(&action, cx)
(listener)(&*action, cx)
}
}),
));
@@ -757,7 +757,7 @@ pub trait InteractiveElement: Sized {
fn on_boxed_action(
mut self,
action: &dyn Action,
listener: impl Fn(&Box<dyn Action>, &mut WindowContext) + 'static,
listener: impl Fn(&dyn Action, &mut WindowContext) + 'static,
) -> Self {
self.interactivity().on_boxed_action(action, listener);
self

View File

@@ -1,7 +1,3 @@
use std::fs;
use std::path::PathBuf;
use std::sync::Arc;
use crate::{
point, px, size, AbsoluteLength, Asset, Bounds, DefiniteLength, DevicePixels, Element,
ElementId, GlobalElementId, Hitbox, ImageData, InteractiveElement, Interactivity, IntoElement,
@@ -9,11 +5,20 @@ use crate::{
WindowContext,
};
use futures::{AsyncReadExt, Future};
use image::{ImageBuffer, ImageError};
use http_client;
use image::{
codecs::gif::GifDecoder, AnimationDecoder, Frame, ImageBuffer, ImageError, ImageFormat,
};
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
use http_client;
use smallvec::SmallVec;
use std::{
fs,
io::Cursor,
path::PathBuf,
sync::Arc,
time::{Duration, Instant},
};
use thiserror::Error;
use util::ResultExt;
@@ -230,8 +235,14 @@ impl Img {
}
}
/// The image state between frames
struct ImgState {
frame_index: usize,
last_frame_time: Option<Instant>,
}
impl Element for Img {
type RequestLayoutState = ();
type RequestLayoutState = usize;
type PrepaintState = Option<Hitbox>;
fn id(&self) -> Option<ElementId> {
@@ -243,29 +254,65 @@ impl Element for Img {
global_id: Option<&GlobalElementId>,
cx: &mut WindowContext,
) -> (LayoutId, Self::RequestLayoutState) {
let layout_id = self
.interactivity
.request_layout(global_id, cx, |mut style, cx| {
if let Some(data) = self.source.data(cx) {
let image_size = data.size();
match (style.size.width, style.size.height) {
(Length::Auto, Length::Auto) => {
style.size = Size {
width: Length::Definite(DefiniteLength::Absolute(
AbsoluteLength::Pixels(px(image_size.width.0 as f32)),
)),
height: Length::Definite(DefiniteLength::Absolute(
AbsoluteLength::Pixels(px(image_size.height.0 as f32)),
)),
cx.with_optional_element_state(global_id, |state, cx| {
let mut state = state.map(|state| {
state.unwrap_or(ImgState {
frame_index: 0,
last_frame_time: None,
})
});
let frame_index = state.as_ref().map(|state| state.frame_index).unwrap_or(0);
let layout_id = self
.interactivity
.request_layout(global_id, cx, |mut style, cx| {
if let Some(data) = self.source.data(cx) {
if let Some(state) = &mut state {
let frame_count = data.frame_count();
if frame_count > 1 {
let current_time = Instant::now();
if let Some(last_frame_time) = state.last_frame_time {
let elapsed = current_time - last_frame_time;
let frame_duration =
Duration::from(data.delay(state.frame_index));
if elapsed >= frame_duration {
state.frame_index = (state.frame_index + 1) % frame_count;
state.last_frame_time =
Some(current_time - (elapsed - frame_duration));
}
} else {
state.last_frame_time = Some(current_time);
}
}
}
_ => {}
}
}
cx.request_layout(style, [])
});
(layout_id, ())
let image_size = data.size(frame_index);
match (style.size.width, style.size.height) {
(Length::Auto, Length::Auto) => {
style.size = Size {
width: Length::Definite(DefiniteLength::Absolute(
AbsoluteLength::Pixels(px(image_size.width.0 as f32)),
)),
height: Length::Definite(DefiniteLength::Absolute(
AbsoluteLength::Pixels(px(image_size.height.0 as f32)),
)),
}
}
_ => {}
}
if global_id.is_some() && data.frame_count() > 1 {
cx.request_animation_frame();
}
}
cx.request_layout(style, [])
});
((layout_id, frame_index), state)
})
}
fn prepaint(
@@ -283,7 +330,7 @@ impl Element for Img {
&mut self,
global_id: Option<&GlobalElementId>,
bounds: Bounds<Pixels>,
_: &mut Self::RequestLayoutState,
frame_index: &mut Self::RequestLayoutState,
hitbox: &mut Self::PrepaintState,
cx: &mut WindowContext,
) {
@@ -293,9 +340,15 @@ impl Element for Img {
let corner_radii = style.corner_radii.to_pixels(bounds.size, cx.rem_size());
if let Some(data) = source.data(cx) {
let new_bounds = self.object_fit.get_bounds(bounds, data.size());
cx.paint_image(new_bounds, corner_radii, data.clone(), self.grayscale)
.log_err();
let new_bounds = self.object_fit.get_bounds(bounds, data.size(*frame_index));
cx.paint_image(
new_bounds,
corner_radii,
data.clone(),
*frame_index,
self.grayscale,
)
.log_err();
}
match source {
@@ -385,12 +438,34 @@ impl Asset for Image {
};
let data = if let Ok(format) = image::guess_format(&bytes) {
let mut data = image::load_from_memory_with_format(&bytes, format)?.into_rgba8();
let data = match format {
ImageFormat::Gif => {
let decoder = GifDecoder::new(Cursor::new(&bytes))?;
let mut frames = SmallVec::new();
// Convert from RGBA to BGRA.
for pixel in data.chunks_exact_mut(4) {
pixel.swap(0, 2);
}
for frame in decoder.into_frames() {
let mut frame = frame?;
// Convert from RGBA to BGRA.
for pixel in frame.buffer_mut().chunks_exact_mut(4) {
pixel.swap(0, 2);
}
frames.push(frame);
}
frames
}
_ => {
let mut data =
image::load_from_memory_with_format(&bytes, format)?.into_rgba8();
// Convert from RGBA to BGRA.
for pixel in data.chunks_exact_mut(4) {
pixel.swap(0, 2);
}
SmallVec::from_elem(Frame::new(data), 1)
}
};
ImageData::new(data)
} else {
@@ -400,7 +475,7 @@ impl Asset for Image {
let buffer =
ImageBuffer::from_raw(pixmap.width(), pixmap.height(), pixmap.take()).unwrap();
ImageData::new(buffer)
ImageData::new(SmallVec::from_elem(Frame::new(buffer), 1))
};
Ok(Arc::new(data))

View File

@@ -180,7 +180,7 @@ impl Transformation {
}
fn into_matrix(self, center: Point<Pixels>, scale_factor: f32) -> TransformationMatrix {
//Note: if you read this as a sequence of matrix mulitplications, start from the bottom
//Note: if you read this as a sequence of matrix multiplications, start from the bottom
TransformationMatrix::unit()
.translate(center.scale(scale_factor) + self.translate.scale(scale_factor))
.rotate(self.rotate)

View File

@@ -940,6 +940,15 @@ where
pub fn half_perimeter(&self) -> T {
self.size.width.clone() + self.size.height.clone()
}
/// centered_at creates a new bounds centered at the given point.
pub fn centered_at(center: Point<T>, size: Size<T>) -> Self {
let origin = Point {
x: center.x - size.width.half(),
y: center.y - size.height.half(),
};
Self::new(origin, size)
}
}
impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T>> Bounds<T> {

View File

@@ -4,9 +4,6 @@
mod app_menu;
mod keystroke;
#[cfg(not(target_os = "macos"))]
mod cosmic_text;
#[cfg(target_os = "linux")]
mod linux;
@@ -51,8 +48,6 @@ use uuid::Uuid;
pub use app_menu::*;
pub use keystroke::*;
#[cfg(not(target_os = "macos"))]
pub(crate) use cosmic_text::*;
#[cfg(target_os = "linux")]
pub(crate) use linux::*;
#[cfg(target_os = "macos")]
@@ -105,7 +100,6 @@ pub fn guess_compositor() -> &'static str {
}
}
// todo("windows")
#[cfg(target_os = "windows")]
pub(crate) fn current_platform(_headless: bool) -> Rc<dyn Platform> {
Rc::new(WindowsPlatform::new())
@@ -413,8 +407,6 @@ pub(crate) trait PlatformTextSystem: Send + Sync {
raster_bounds: Bounds<DevicePixels>,
) -> Result<(Size<DevicePixels>, Vec<u8>)>;
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout;
#[cfg(target_os = "windows")]
fn destroy(&self);
}
#[derive(PartialEq, Eq, Hash, Clone)]
@@ -714,7 +706,6 @@ pub(crate) struct WindowParams {
pub display_id: Option<DisplayId>,
#[cfg_attr(target_os = "linux", allow(dead_code))]
pub window_min_size: Option<Size<Pixels>>,
}

View File

@@ -1,3 +0,0 @@
mod text_system;
pub(crate) use text_system::*;

View File

@@ -237,14 +237,15 @@ pub struct Modifiers {
}
impl Modifiers {
/// Returns true if any modifier key is pressed
/// Returns whether any modifier key is pressed.
pub fn modified(&self) -> bool {
self.control || self.alt || self.shift || self.platform || self.function
}
/// Whether the semantically 'secondary' modifier key is pressed
/// On macos, this is the command key
/// On windows and linux, this is the control key
/// Whether the semantically 'secondary' modifier key is pressed.
///
/// On macOS, this is the command key.
/// On Linux and Windows, this is the control key.
pub fn secondary(&self) -> bool {
#[cfg(target_os = "macos")]
{
@@ -257,7 +258,7 @@ impl Modifiers {
}
}
/// How many modifier keys are pressed
/// Returns how many modifier keys are pressed.
pub fn number_of_modifiers(&self) -> u8 {
self.control as u8
+ self.alt as u8
@@ -266,12 +267,12 @@ impl Modifiers {
+ self.function as u8
}
/// helper method for Modifiers with no modifiers
/// Returns [`Modifiers`] with no modifiers.
pub fn none() -> Modifiers {
Default::default()
}
/// helper method for Modifiers with just the command key
/// Returns [`Modifiers`] with just the command key.
pub fn command() -> Modifiers {
Modifiers {
platform: true,
@@ -279,7 +280,7 @@ impl Modifiers {
}
}
/// A helper method for Modifiers with just the secondary key pressed
/// A Returns [`Modifiers`] with just the secondary key pressed.
pub fn secondary_key() -> Modifiers {
#[cfg(target_os = "macos")]
{
@@ -298,7 +299,7 @@ impl Modifiers {
}
}
/// helper method for Modifiers with just the windows key
/// Returns [`Modifiers`] with just the windows key.
pub fn windows() -> Modifiers {
Modifiers {
platform: true,
@@ -306,7 +307,7 @@ impl Modifiers {
}
}
/// helper method for Modifiers with just the super key
/// Returns [`Modifiers`] with just the super key.
pub fn super_key() -> Modifiers {
Modifiers {
platform: true,
@@ -314,7 +315,7 @@ impl Modifiers {
}
}
/// helper method for Modifiers with just control
/// Returns [`Modifiers`] with just control.
pub fn control() -> Modifiers {
Modifiers {
control: true,
@@ -322,7 +323,15 @@ impl Modifiers {
}
}
/// helper method for Modifiers with just shift
/// Returns [`Modifiers`] with just control.
pub fn alt() -> Modifiers {
Modifiers {
alt: true,
..Default::default()
}
}
/// Returns [`Modifiers`] with just shift.
pub fn shift() -> Modifiers {
Modifiers {
shift: true,
@@ -330,7 +339,7 @@ impl Modifiers {
}
}
/// helper method for Modifiers with command + shift
/// Returns [`Modifiers`] with command + shift.
pub fn command_shift() -> Modifiers {
Modifiers {
shift: true,
@@ -339,7 +348,7 @@ impl Modifiers {
}
}
/// helper method for Modifiers with command + shift
/// Returns [`Modifiers`] with command + shift.
pub fn control_shift() -> Modifiers {
Modifiers {
shift: true,
@@ -348,7 +357,7 @@ impl Modifiers {
}
}
/// Checks if this Modifiers is a subset of another Modifiers
/// Checks if this [`Modifiers`] is a subset of another [`Modifiers`].
pub fn is_subset_of(&self, other: &Modifiers) -> bool {
(other.control || !self.control)
&& (other.alt || !self.alt)

Some files were not shown because too many files have changed in this diff Show More