Compare commits

...

366 Commits

Author SHA1 Message Date
Michael Sloan
5d11fc5bc4 Update edit predictions documentation 2025-02-13 04:47:19 -07:00
Conrad Irwin
d57f5937d4 Git panel: Right click menu (#24787)
Release Notes:

- N/A
2025-02-12 22:26:34 -07:00
Joseph T. Lyons
fc7bf7bcb9 Bump Zed to v0.175 (#24785)
Release Notes:

-N/A
2025-02-12 23:14:45 -05:00
tidely
5d634245a2 remote_server: Remove unnecessary Box, prevent time-of-check time-of-use bug (#24730)
The MultiWrite struct is defined in the function scope and is allowed to
have a concrete type, which means we can throw away the extra Box.
PathBuf::exists is known to be prone to invalid usage. It doesn't take
into account permissions errors and just returns false, additionally it
introduces a time-of-check time-of-use bug. While extremely unlikely,
why not fix it anyway.

Release Notes:

- remove unnecessary Box
- prevent time-of-check time-of-use bug
2025-02-12 20:55:22 -07:00
Conrad Irwin
21a1541a70 Branch/co-authors in commit (#24768)
- **branch selector in commit box**
- **TEMP**
- **Add co-authors toggle button**

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
2025-02-12 20:53:52 -07:00
Max Brunsfeld
71867096c8 Migrate edit_prediction_provider setting before updating its value to 'zed' during onboarding (#24781)
This fixes a bug where we'd update your settings to an invalid state if
you were using the old `inline_completion_provider` setting, then
onboarded to Zeta, then migrated your settings.

Release Notes:

- N/A

Co-authored-by: Michael Sloan <mgsloan@gmail.com>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
2025-02-13 02:35:25 +00:00
Danilo Leal
3d68dba696 edit predictions: Iterate on onboarding modal copywriting (#24779)
Release Notes:

- N/A

---------

Co-authored-by: Nathan Sobo <1789+nathansobo@users.noreply.github.com>
2025-02-13 02:07:20 +00:00
renovate[bot]
f0cd71e43c Update cloudflare/wrangler-action digest to 392082e (#24753)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cloudflare/wrangler-action](https://redirect.github.com/cloudflare/wrangler-action)
| action | digest | `7a5f8bb` -> `392082e` |

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 20:01:42 -05:00
Michael Sloan
a13c2baa7f Improve error message for AcceptEditPredictions - add docs link (#24772)
The docs have not been updated yet, this is anticipating their presence
soon.


![image](https://github.com/user-attachments/assets/bbcf56f2-6d5b-460b-8ed0-36bef3b4f12f)

Release Notes:

- N/A
2025-02-12 17:46:53 -07:00
Michal Vrbata
7ba1492f0a file_icons: Add separate icon key for Bicep files (#24757)
This PR adds support for bicep file icon:

Release Notes:

- Icon themes: Added the ability to change the file icon for Bicep
(`.bicep`) files.
2025-02-13 00:36:27 +00:00
Danilo Leal
0a681225b6 edit predictions: Enable blog post link behind a feature flag (#24720)
This PR updates the blog post link in the onboarding modal to be behind
the `predict-edits-launch` feature flag instead of a staff flag.

This will allow us to enable the blog post link once we're live.

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-12 23:59:06 +00:00
Marshall Bowers
277fb54632 zeta: Respect x-zed-minimum-required-version header (#24771)
This PR makes it so Zeta respects the `x-zed-minimum-required-version`
header sent back from the server.

If the current Zed version is strictly less than the indicated minimum
required version, we show an error indicating that an update is required
in order to continue using Zeta:

<img width="472" alt="Screenshot 2025-02-12 at 6 15 44 PM"
src="https://github.com/user-attachments/assets/51b85dff-23a0-464c-ae4b-5b8f46b5915c"
/>

Release Notes:

- N/A
2025-02-12 23:58:38 +00:00
renovate[bot]
0e42a69490 Update dependency danger to v12.3.4 (#24770)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [danger](https://redirect.github.com/danger/danger-js) | [`12.3.3` ->
`12.3.4`](https://renovatebot.com/diffs/npm/danger/12.3.3/12.3.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/danger/12.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/danger/12.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/danger/12.3.3/12.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/danger/12.3.3/12.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>danger/danger-js (danger)</summary>

###
[`v12.3.4`](https://redirect.github.com/danger/danger-js/blob/HEAD/CHANGELOG.md#1234)

[Compare
Source](https://redirect.github.com/danger/danger-js/compare/12.3.3...12.3.4)

- Ensure that [babel ignores](https://babeljs.io/docs/options#ignore) do
not cause the transpiler to fall over, by supporting the
`null` return from `loadOptions` which occurs when a file is ignored.
-   Allow absolute paths for a Dangerfile

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 23:26:07 +00:00
Mikayla Maki
b014afa938 Add an undo button to the git panel (#24593)
Also prep infrastructure for pushing a commit

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
Co-authored-by: Nate Butler <iamnbutler@gmail.com>
2025-02-12 15:57:08 -07:00
Ben Kunkle
df8adc8b11 Fix linux zeta modifiers display (#24764)
Improves rendering of Zeta keybind shortcuts on Linux

Before:

![image](https://github.com/user-attachments/assets/9b6a61f7-dade-480f-a864-acdcede05957)

After: (with muting modifier changes merged)

![image](https://github.com/user-attachments/assets/dd616d29-ac2e-4c8b-bf9b-5d74f8e4f1c4)


Release Notes:

- N/A

---------

Co-authored-by: Michael <michael@zed.dev>
Co-authored-by: Agus <agus@zed.dev>
2025-02-12 14:46:42 -08:00
smit
522b8d662c editor: Fix autoscroll flickering regression (#24758)
This PR fixes autoscroll flickering issue caused by recent
[#24735](https://github.com/zed-industries/zed/pull/24735) which fixes
soft wrap scroll issues. No release notes, as this was few hours ago.

Adding vertical scrollbar width to viewport width, so that autoscroll
function don't try to that much pixels extra.

Release Notes:

- N/A
2025-02-13 03:42:22 +05:30
smit
5dc3c237eb workspace: Do not reuse window for sub directory (only for root directory and sub files) (#24560)
Closes #10232

Context:

We have three ways to open files or dirs in Zed: `zed`, `zed --new`, and
`zed --add`. `--new` forces the project to open in a new window, while
`--add` forces it to open in an existing window (even if the dir isn’t a
subdir of an existing project or the file isn’t part of it).

Using just `zed` tries to open it in an existing window based on similar
logic of `--add`, but if no related project is found the dir, opens in a
new window.

Problem:

Right now, subdirs that are part of an existing project open in the
existing window when using `zed`. By default, subdirs should open in a
new window instead. If someone wants to open it in the existing window,
they can explicitly use `--add`. After this PR, only root dir and files
will focus on existing window, when `zed ` is used.

Fix:

For the `zed` case, we’ve filtered out subdirs in the logic that assigns
them to an existing window.

Release Notes:

- Fixed an issue where subdirectories of an already opened project, when
opened via the terminal, would open in the existing project instead of a
new window.
2025-02-13 03:37:39 +05:30
Agus Zubiaga
c771ca49e1 Fix <1px gap between diff popover and accept keybindingg (#24756)
Release Notes:

- N/A

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: rtfeldman <oss@rtfeldman.com>
Co-authored-by: mgsloan <mgsloan@gmail.com>
2025-02-12 20:59:11 +00:00
Cole Miller
ab4a6f1c79 Open git panel when deploying project diff via action (#24751)
Release Notes:

- N/A
2025-02-12 15:37:17 -05:00
Max Brunsfeld
316b97d6e3 Position prediction popover adjacent to edit if possible (#24750)
Also, place accept key binding indicator on right edge of popover to
avoid obscuring content above.

Release Notes:

- N/A

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: rtfeldman <oss@rtfeldman.com>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
2025-02-12 12:11:49 -08:00
Cole Miller
eea6b526dc Implement staging and unstaging hunks (#24606)
- [x] Staging hunks
- [x] Unstaging hunks
- [x] Write a randomized test
- [x] Get test passing
- [x] Fix existing bug in diff_base_byte_range computation
- [x] Remote project support
- [ ] ~~Improve performance of
buffer_range_to_unchanged_diff_base_range~~
- [ ] ~~Bug: project diff editor scrolls to top when staging/unstaging
hunk~~ existing issue
- [ ] ~~UI~~ deferred
- [x] Tricky cases
  - [x] Correctly handle acting on multiple hunks for a single file
- [x] Remove path from index when unstaging the last staged hunk, if
it's absent from HEAD, or staging the only hunk, if it's deleted in the
working copy

Release Notes:

- Add `ToggleStagedSelectedDiffHunks` action for staging and unstaging
individual diff hunks
2025-02-12 19:46:42 +00:00
Finn Evers
ea8da43c6b ui: Fix keybind sizing for non-default UI font sizes (#24708)
Closes #24597 

This fixes the regression from
00971fbe41
which removed the `text_ui(cx)` - call from the keybinding render. The
removal caused improperly scaled font rendering as shown in the images
below.

This PR reintroduces this behaviour for all cases where `size` is not
set.

| | `main` | With this patch | Parent of
00971fbe41
| --- | ---- | ---- | --- |
| Small font size (10px) | <img width="204" alt="cur_small"
src="https://github.com/user-attachments/assets/2bb1615a-c346-4da5-855c-01894744ee74"
/> | <img width="205" alt="pr_small"
src="https://github.com/user-attachments/assets/26ab70f0-d6ca-439b-aaea-4d6ded4f8f11"
/> | <img width="203" alt="prev_small"
src="https://github.com/user-attachments/assets/92a04008-8408-4a98-83a2-59fdd6e5708a"
/> |
| Large font size | <img width="369" alt="cur_big"
src="https://github.com/user-attachments/assets/8400c205-19b6-479c-a3d1-df12ed4e84da"
/> | <img width="398" alt="pr_big"
src="https://github.com/user-attachments/assets/01f495aa-0be1-4169-ae09-4292b0e638ff"
/> | <img width="389" alt="prev_big"
src="https://github.com/user-attachments/assets/e041a8ea-a958-4a3b-8fef-0f7fe5079c34"
/> |


Release Notes:

- Fixed keybind hints being improperly scaled for custom ui font sizes
2025-02-12 14:17:00 -05:00
smit
cc97f4131b editor: Fix horizontal scroll when soft wrap is active (#24735)
Closes #22252

This PR fixes the bug introduced in
https://github.com/zed-industries/zed/pull/19495 by:

Problem:

The vertical scrollbar is currently rendered absolutely on top of the
editor. When calculating soft wrap, the editor uses its width to decide
how many words fit on a line. This causes words to overlap with the
vertical scrollbar because it doesn't account for the scrollbar's width.
To fix the overlap, extra overflow is added to the scrollbar, which
solves the issue but creates unnecessary scrolling in soft wrap mode.

Fix:

The editor width is adjusted to account for the scrollbar's width. This
makes sure the correct number of words fit on a line and prevents
overlapping with the scrollbar in soft wrap mode.

Since the scrollbar width is now accounted for in the editor's width,
there's no need to add extra overflow, unless there’s no soft wrap. In
that case, when text overflows the editor’s width, we still need to add
extra overscroll to match the scrollbar width. Without this, long lines
will overlap with the scrollbar.

Release Notes:

- Fixed issue where horizontal scrollbar would scroll few characters
width when soft wrap is active.
2025-02-12 22:52:22 +05:30
Piotr Osiewicz
ba7d2ba8c7 project: Activate buffer_diff/test-support in test-support (#24739)
Closes #ISSUE

Release Notes:

- N/A
2025-02-12 16:51:47 +00:00
Agus Zubiaga
553cc2cca5 edit predictions: Do not require modifier if in leading space but just accepted a prediction (#24733)
This makes the tab tab tab experience smoother

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: as-cii <as-cii@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Ben <ben@zed.dev>
2025-02-12 16:30:58 +00:00
Marshall Bowers
3f95d79fc5 inline_completion_button: Put "Eager Preview Mode" menu entry behind a feature flag (#24734)
This PR puts the "Eager Preview Mode" menu entry behind a feature flag
rather than a staff flag.

Currently it defaults to `false` for staff so that it doesn't leak into
any marketing/launch materials.

Folks who want to see it can opt-in to the flag explicitly, for now.

Release Notes:

- N/A
2025-02-12 16:23:23 +00:00
Agus Zubiaga
51092c4e31 Polish edit predictions (#24732)
Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: as-cii <as-cii@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-02-12 15:56:31 +00:00
Antonio Scandurra
2b7d3726b4 Replace rustls-native-certs with rustls-platform-verifier (#24656)
closes https://github.com/zed-industries/zed/issues/19620.

I am not 100% sure on how to test this though. @elithrar: would you mind
giving this branch a shot and seeing if it works for you? I kicked off
bundling for this pull request and you should be able to download a DMG
from the CI artifacts as soon as it's done building.

Release Notes:

- Fixed a bug that caused OS-level CA certificate bundles to not be
respected.

---------

Co-authored-by: Bennet <bennet@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
2025-02-12 07:32:17 -08:00
Sanjeev Shrestha
1ce6e8d0e3 file_icons: Use separate keys for C#, Cue, GitLab YAML, Luau, and Solidity (#24711)
This PR updates the file icon mappings such that:

- C# (`.cs`) files map to the `csharp` key
- Cue (`.cue`) files map to the `cue` key
- GitLab YAML (`gitlab-ci.yml`) files map to the `gitlab` key
- Luau (`.luau`) files map to the `luau` key
- Solidity (`.sol`) files map to the `solidity` key

Release Notes:

- Icon themes: Added the ability to change the file icon for C# (`.cs`)
files.
- Icon themes: Added the ability to change the file icon for Cue
(`.cue`) files.
- Icon themes: Added the ability to change the file icon for GitLab YAML
(`gitlab-ci.yml`) files.
- Icon themes: Added the ability to change the file icon for Luau
(`.luau`) files.
- Icon themes: Added the ability to change the file icon for Solidity
(`.sol`) files.

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-12 14:25:01 +00:00
Michael Sloan
eb389a5132 edit predictions: Update migration banner text and rename chore (#24713)
Rationale for the changes:

* `requires migration` -> `uses some deprecated settings` changed
because really it isn't required by this version of Zed, and I believe
we hope to offer support for deprecated settings and their migration for
a long time.

* Rename of `migration` -> `updated` is because to me, "updated" feels
lighter and more accurate. To me migration has connotations of moving to
a whole new format.

Formatting changes are due to shortening the line causing cargo fmt to
go from not formatting the code to doing so.

Release Notes:

- N/A

---------

Co-authored-by: smit <0xtimsb@gmail.com>
2025-02-12 19:28:29 +05:30
Adrien Tiburce
e148815e04 docs: Fix modal_max_width naming (#24719)
## Fixes `modal_max_width` doc.

The settings `modal_max_width` was `max_modal_width` in the doc.
2025-02-12 13:15:25 +00:00
Michael Sloan
fc86e7cd51 Fix modifier key logic for edit predictions preview with completions (#24709)
Release Notes:

- N/A
2025-02-12 03:26:51 +00:00
Danilo Leal
754560876b edit predictions: Refine the settings migration banner (#24706)
Just a slight design touch-up on the settings migration banner.

Release Notes:

- N/A
2025-02-12 00:13:38 -03:00
smit
65934ae181 migrator: In-memory migration and improved UX (#24621)
This PR adds:

- Support for deprecated keymap and settings (In-memory migration)
- Migration prompt only shown in `settings.json` / `keymap.json`.

Release Notes:

- The migration banner will only appear in `settings.json` and
`keymap.json` if you have deprecated settings or keybindings, allowing
you to migrate them to work with the new version on Zed.
2025-02-12 06:47:08 +05:30
Michael Sloan
498bb518ff Require alt-tab for AcceptEditPrediction when tab inserting whitespace is desired (#24705)
Moves tab whitespace insertion logic out of `AcceptEditPrediction`
handler.

`edit_prediction_requires_modifier` context will now be true when on a
line with leading whitespace, so that `alt-tab` is used to accept
predictions in this case. This way leading indentation can be typed when
edit predictions are visible

Release Notes:

- N/A

Co-authored-by: Ben <ben@zed.dev>
Co-authored-by: Joao <joao@zed.dev>
2025-02-12 01:14:09 +00:00
Danilo Leal
2e7a89c5e3 edit predictions: Improve copywriting (#24689) 2025-02-11 21:43:48 -03:00
Conrad Irwin
f5fd3d98ad Fix project diff focus (#24691)
Release Notes:

- N/A
2025-02-11 16:40:40 -08:00
Max Brunsfeld
9a9fdce253 Fixes for accept edit popovers (#24703)
Follow-up to #24700

Release Notes:

- N/A

---------

Co-authored-by: danilo-leal <daniloleal09@gmail.com>
Co-authored-by: agu-z <hi@aguz.me>
2025-02-11 16:32:15 -08:00
Marshall Bowers
cc931a8fcc theme: Add support for setting light/dark icon themes (#24702)
This PR adds support for configuring both a light and dark icon theme in
`settings.json`.

In addition to accepting just an icon theme name, the `icon_theme` field
now also accepts an object in the following form:

```jsonc
{
  "icon_theme": {
    "mode": "system",
    "light": "Zed (Default)",
    "dark": "Zed (Default)"
  }
}
```

Both `light` and `dark` are required, and indicate which icon theme
should be used when the system is in light mode and dark mode,
respectively.

The `mode` field is optional and indicates which icon theme should be
used:
- `"system"` - Use the icon theme that corresponds to the system's
appearance.
- `"light"` - Use the icon theme indicated by the `light` field.
- `"dark"` - Use the icon theme indicated by the `dark` field.

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

Release Notes:

- Added support for configuring both a light and dark icon theme and
switching between them based on system preference.
2025-02-11 23:45:37 +00:00
Max Brunsfeld
148547ecd1 Rework edit prediction preview mode (#24700)
Don't animate the cursor when previewing jumps.
Instead, display the jump popover with a line that resembles a cursor,
indicating the jump destination. If the jump destination is outside of
the view port, there is an extra step in which `tab` scrolls the
viewport to reveal the jump destination.

Release Notes:

- N/A

---------

Co-authored-by: danilo-leal <daniloleal09@gmail.com>
Co-authored-by: agu-z <hi@aguz.me>
2025-02-11 23:14:12 +00:00
Mikayla Maki
5293f5724c Add a script that sets up a trusted MITM proxy (#24698)
In an effort to squash bugs like:
https://github.com/zed-industries/zed/issues/19620, and improve
confidence on PRs like:
https://github.com/zed-industries/zed/pull/24656, I created this little
test script using `mitmproxy` to simulate the situation.

Unfortunately, I don't see any issues with our current usage of the
local certificate store using this script. But I'd like to have it as a
base to build off of.

Release Notes:

- N/A
2025-02-11 22:43:35 +00:00
Kirill Bulatov
73b32a20e2 Fix editor::GoToDiagnostics cycle (#24697)
Re-lands https://github.com/zed-industries/zed/pull/24446 with a more
appropriate fix


https://github.com/user-attachments/assets/45f665f0-473a-49bd-b013-b9d1bdb902bd

After activating 2nd diagnostics group, `find_map` code for next
diagnostics did not skip the previous group for the same place.

This time, instead of fiddling with the diagnostics group comparison,
the code splits the diagnostics by search place, looks up the active
group (if any) in both split parts, and selects the entries after the
group elements.

Release Notes:

- Fixed `editor::GoToDiagnostics` action stuck when multiple diagnostics
groups belong to the same place
2025-02-11 22:41:23 +00:00
Marshall Bowers
7da913c801 collab: Update user email and name when signing in (#24694)
This PR updates the `GET /user` endpoint to update the user's email and
name from the provided GitHub profile information on sign-in.

Currently, these fields were only set when the user was first created.

Release Notes:

- N/A
2025-02-11 22:02:11 +00:00
Marshall Bowers
a2592a3a37 Clean up edit predictions settings (#24692)
This PR does some clean up for the edit predictions settings:

- Removed `editor.show_edit_predictions_in_menu`
- Renamed `edit_predictions.inline_preview` to `edit_predictions.mode`

Release Notes:

- N/A

---------

Co-authored-by: Agus Zubiaga <agus@zed.dev>
2025-02-11 21:33:31 +00:00
Kirill Bulatov
636253d2dc Prefer names over github logins when filling co-authors (#24693)
Follow-up of https://github.com/zed-industries/zed/pull/24575

Release Notes:

- N/A
2025-02-11 21:32:03 +00:00
Marshall Bowers
e851abd2ec migrator: Do some cleanup (#24687)
This PR does some clean up of the `migrator` crate:

- Remove `.unwrap`s
- Don't suppress `rustfmt`

Release Notes:

- N/A
2025-02-11 20:46:21 +00:00
Joseph T. Lyons
b3814ce4e3 Fix "Project Diff Opened" event name (#24686)
Release Notes:

- N/A
2025-02-11 20:43:58 +00:00
Nate Butler
2d71733490 ui: Update Label component (#24653)
- Standardize style methods
- Convert label story to a component preview
- update component preview styles  

Release Notes:

- N/A
2025-02-11 20:16:59 +00:00
Marshall Bowers
aab3e0495d inline_completion_button: Add menu option to toggle "Eager Preview"s for edit predictions (#24685)
This PR adds a menu option to the edit prediction menu to toggle the
"Eager Preview" behavior:

<img width="252" alt="Screenshot 2025-02-11 at 2 44 52 PM"
src="https://github.com/user-attachments/assets/232e879b-3c11-4edd-a549-f284e2bca391"
/>

Release Notes:

- N/A
2025-02-11 20:02:52 +00:00
Michael Sloan
12163c9b45 Add Editor && to accept edit contexts in vim keymap (#24684)
Without this, these default vim bindings were taking precedence over
user keybindings

Release Notes:

- N/A
2025-02-11 19:42:43 +00:00
Mikayla Maki
477cec0ef1 Add more view tracking (#24683)
This should fix a panic in `Window::current_view()`

Release Notes:

- N/A
2025-02-11 19:18:54 +00:00
5brian
0a146793ea vim: Prevent around word operations from selecting indentation (#24635)
Closes https://github.com/zed-industries/zed/issues/15323

Changes:
Added check for first word on line

Tested `v/c/d/y aw`. Matches standard neovim.

|initial|old|new|
|---|---|---|

|![image](https://github.com/user-attachments/assets/725b74e6-3aa0-40dc-9fd2-4d2b593e9926)|![image](https://github.com/user-attachments/assets/eeebd267-b4c6-4ea6-bb9a-fb913614754c)|![image](https://github.com/user-attachments/assets/fb695e54-b4c2-44a6-a588-909c1fd415e0)



Release Notes:

- vim: Prevent around word operations from selecting indentation
2025-02-11 11:35:59 -07:00
Peter Tripp
7378ab9ba5 Correctly handle [[ autoclosing in Markdown (#24662) 2025-02-11 13:06:45 -05:00
Cole Miller
759ea0ec48 Touch up stale hunks fix (#24669)
Release Notes:

- N/A

Co-authored-by: Max <max@zed.dev>
2025-02-11 17:47:41 +00:00
João Marcos
7c00eec08b edit predictions: Fix popover hint not scrolling horizontally (#24602)
Release Notes:

- N/A
2025-02-11 17:29:00 +00:00
Marshall Bowers
eaab7da2d8 zeta: Add ability to change predict edits URL via environment variable (#24668)
This PR adds the ability to change the predict edits URL using the
`ZED_PREDICT_EDITS_URL` environment variable.

This allows for easily pointing Zed to a development version of the
Cloudflare Worker.

Release Notes:

- N/A
2025-02-11 17:28:13 +00:00
Agus Zubiaga
14d9788ba3 edit predictions: Don't animate cursor when jumping in eager mode without LSP completions (#24664)
We should only do this in "holding modifier" mode OR when there's a
language server completions menu.

Release Notes:

- N/A
2025-02-11 16:47:34 +00:00
Cameron Radmore
b395beaf93 file_icons: Add Stylelint file icon associations (#24605)
This PR adds file associations for stylelint files.

This is how it looks like in Zed (the icon doesn't exist):
![default javascript file icon is shown for
stylelint.config.js](https://github.com/user-attachments/assets/a873d7fc-1b8a-4a9c-8e92-1be56d5b01b1)

In a dev version of an icon theme it looks like this (icon sourced from:
https://github.com/vscode-icons/vscode-icons/blob/master/icons/file_type_stylelint.svg
):
![stylelint file icon is shown for
stylelint.config.js](https://github.com/user-attachments/assets/ddbb068d-7986-43de-94f8-9c844cb6b96f)

Release Notes:

- Icon themes: Added Stylelint file icon associations.

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-11 16:42:54 +00:00
Cole Miller
6e7416eb00 Fix stale hunks after commit (#24663)
Fixes a regression introduced in #24475.

Release Notes:

- N/A
2025-02-11 11:39:57 -05:00
smit
bbea3a2184 editor: Fix crash caused by editor::SelectPrevious (#24660)
Closes #24345

Release Notes:

- Fixed a crash caused by calling `editor::SelectPrevious` twice in a
row.

Co-authored-by: conrad <conrad@zed.dev>
2025-02-11 22:07:44 +05:30
Twilight
7950368bc2 file_icons: Add missing React file icon associations (#24659)
The `.mjsx`, `.cjsx`, `.mtsx`, and `.ctsx` file extensions are also
designed to contain JSX code.

Release Notes:

- Added file icon associations for more React files (`.mjsx`, `.cjsx`,
`.mtsx`, `.ctsx`).
2025-02-11 16:23:53 +00:00
ANKDDEV
7fe6943d89 Add command to copy current file name (#22174)
Closes #21967

Add actions `CopyFileName` and `CopyFileNameWithoutExtension` to be used in the command palette.

Release Notes:

- Added commands `editor: copy file name` and `editor: copy file name without extensions`.
2025-02-11 12:42:23 -03:00
Bennet Bo Fenner
8fa85c41a1 edit prediction: Try to fix panic in Buffer::preview_edits (#24654)
We've seen a few crashes in `SyntaxSnapshot::reparse_with_ranges` during
`Buffer::preview_edits`, where an offset conversion fails because it is
out of range.
We are not sure how exactly this is happening. 
Our theory is that the syntax snapshot is using an outdated state when
edits happen in the meantime (while interpolating). This is an attempt
to see if it helps with the panics, hopefully we can revisit this when
we have a better understanding of the issue.


Co-Authored-by: Antonio <antonio@zed.dev>

Release Notes:

- N/A

Co-authored-by: Antonio <antonio@zed.dev>
2025-02-11 16:35:09 +01:00
Marshall Bowers
7b45901d96 gpui: Update asset paths for more examples (#24646)
This PR updates the asset paths used in more GPUI examples such that
they work when run from the repository root or from within
`crates/gpui`.

Release Notes:

- N/A
2025-02-11 14:37:55 +00:00
Agus Zubiaga
22e2b8e832 edit predictions: Preview jumps by animating cursor to target (#24604)
https://github.com/user-attachments/assets/977d08fb-a2b1-4826-9d95-8f35c6cb9f13




Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: Smit <smit@zed.dev>
Co-authored-by: Max <max@zed.dev>
2025-02-11 11:19:51 -03:00
Marshall Bowers
5778e1e6f0 theme: Fix Svelte file icon (#24650)
This PR fixes the file icon used for Svelte files in the default icon
theme, as I used the wrong icon name in #24644.

Release Notes:

- N/A
2025-02-11 14:09:03 +00:00
Marshall Bowers
c61f2dff47 file_icons: Use a separate icon key for Markdown files (#24648)
This PR updates the file icon mappings such that Markdown (`.md`,
`.markdown`) files map to the `markdown` key.

Release Notes:

- Icon themes: Added the ability to change the file icon for Markdown
(`.md`, `.markdown`) files.
2025-02-11 13:58:53 +00:00
Marshall Bowers
04d65cb3cd gpui: Make image example work regardless of how it is run (#24645)
This PR updates the GPUI `image` example such that it works when run in
the following ways:

- `cargo run -p gpui --example image` from the repository root
- `cargo run --example image` from within `crates/gpui`

Release Notes:

- N/A
2025-02-11 13:34:38 +00:00
Marshall Bowers
6a40a400bd file_icons: Use a separate icon key for Svelte files (#24644)
This PR updates the file icon mappings such that Svelte (`.svelte`)
files map to the `svelte` key.

Release Notes:

- Icon themes: Added the ability to change the file icon for Svelte
(`.svelte`) files.
2025-02-11 13:22:23 +00:00
smit
c8c4ec21f3 docs: Fix vim Subword and Push example snippet (#24641)
All other vim examples are objects in Keymap file, where these two
examples are stated as Keymap file itself.

PR fixes this confusion.  

Release Notes:

- N/A
2025-02-11 18:10:16 +05:30
Piotr Osiewicz
64ae5093af chore: Remove settings dependency on migrator (#24642)
Closes #ISSUE

Release Notes:

- N/A
2025-02-11 13:34:33 +01:00
zfx
7f4957cf20 Remove non-existent icon IndicatorX (#24636)
There is no file indicator_x.svg in the assets directory.

09:49:05 [ERROR] could not find asset at path "icons/indicator_x.svg"

![image](https://github.com/user-attachments/assets/e9cc5ae3-4eb3-4e1e-b012-43ac7297c0a7)

Release Notes:

- N/A
2025-02-11 11:32:38 +00:00
Bennet Bo Fenner
8c349057e5 edit prediction: Fix zeta: Rate completions action not working when using keybinding (#24569)
Release Notes:

- N/A
2025-02-11 12:14:42 +01:00
Michael Sloan
a1d4bd94c9 Make alt-l the default linux/windows binding for AcceptEditPrediction (#24630)
Release Notes:

- N/A
2025-02-11 08:34:32 +00:00
Michael Sloan
9e178f128d Revert "Make ctrl-l the default vim binding for AcceptEditPrediction (#24599) (#24614)
Didn't realize that the base keymap binds this to `editor::SelectLine`.

This reverts commit c5fe5f1139.

Release Notes:

- N/A
2025-02-11 07:14:16 +00:00
5brian
236f51cddd vim: Update vi{ (#24601)
Small fix: Following up on
https://github.com/zed-industries/zed/pull/24518 where i missed `vi{`.

Matching neovim(tree-sitter), `vi{` should not have the newline selected
(Now `vi{d`/`vi{c` can match `di{`/`ci{`).

Also moved the cursor to the start.

|prev|new|neovim|
|---|---|---|

|![image](https://github.com/user-attachments/assets/0311fbe5-df2e-4feb-977d-de33a3af7fdc)|![image](https://github.com/user-attachments/assets/a940c6ba-268b-4401-8c43-38ca17848542)|![image](https://github.com/user-attachments/assets/dab2c47d-660c-4ae3-bf79-635265222cc1)|

Release Notes:

- N/A
2025-02-10 22:26:26 -07:00
Max Bucknell
37785a54d5 vim: :set support (#24209)
Closes #21147 

Release Notes:

- vim: First version of `:set` with support for `[no]wrap`,
`[no]number`, `[no]relativenumber`

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-02-11 04:55:40 +00:00
Peter Tripp
2e7bb11b7d docs: Improve StyLua Lua formatter suggested settings (#24144) 2025-02-10 22:12:01 -05:00
Peter Tripp
cf9661a56b Improve extension extraction documentation (#24590)
- Add .gitignore
- Update extension.toml URL
- Script cleanup of Cargo.toml workspace lines
2025-02-10 22:11:23 -05:00
Michael Sloan
c5fe5f1139 Make ctrl-l the default vim binding for AcceptEditPrediction (#24599)
Release Notes:

- N/A
2025-02-11 03:03:53 +00:00
Cole Miller
8f75fe25e5 Add staged status information to diff hunks (#24475)
Release Notes:

- Render unstaged hunks in the project diff editor with a slashed
background

---------

Co-authored-by: maxbrunsfeld <max@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2025-02-10 21:43:25 -05:00
Michael Sloan
a9de9e3cb4 Remove alt-tab / alt-enter binds in vim keymap, as they are in base (#24598)
Was unnecessary to include these in #24596 as they will be available
from the base keymap.

Release Notes:

- N/A

Co-authored-by: Conrad <conrad@zed.dev>
2025-02-11 02:41:09 +00:00
Michael Sloan
4c881b6a12 Use editor::AcceptEditPrediction in vim keymap (#24596)
* Overrides the action handler to switch to insert mode after jumps.

* Returns `vim::Tab` to its behavior from before #24418

Release Notes:

- N/A

Co-authored-by: Conrad <conrad@zed.dev>
2025-02-10 19:20:13 -07:00
Danilo Leal
c89ad65782 edit predictions: Show user if current project is open source (#24587)
Release Notes:

- N/A

---------

Co-authored-by: João Marcos <marcospb19@hotmail.com>
2025-02-10 22:28:56 -03:00
Michael Sloan
3d9f70946c Use last keybind (highest precedence) for AcceptEditPrediction display (#24595)
Fix of PR #24582

Release Notes:

- N/A
2025-02-11 01:12:46 +00:00
Michael Sloan
7fe331f83d Remove old keymap comments about AcceptEditPrediction modifier changes (#24592)
This was fixed in #24442

Release Notes:

- N/A
2025-02-10 17:58:08 -07:00
张小白
c1f162abc6 collab: Fix project sharing between Windows and Unix (#23680)
Closes #14258

Windows user(host) sharing a project to a guest(using macOS), and host
follows guest:


https://github.com/user-attachments/assets/ba306b6b-23f7-48b1-8ba8-fdc5992d8f00

macOS user(host) sharing a project to a guest(using Windows), and host
follows guest:



https://github.com/user-attachments/assets/c5ee5e78-870d-49e5-907d-8565977a01ae

macOS user edits files in a windows project through collab:



https://github.com/user-attachments/assets/581057cf-e7df-4e56-a0ce-ced74339906a





Release Notes:

- N/A
2025-02-10 16:12:01 -08:00
Max Brunsfeld
929c5e76b4 Fix some visual bugs w/ edit predictions (#24591)
* correct the size of key binding icons
* avoid spurious modifier in 'jump to edit' popover when already
previewing
* fix height of the edit preview popover

Release Notes:

- N/A

Co-authored-by: agu-z <hi@aguz.me>
2025-02-10 23:49:08 +00:00
Ben Kunkle
dab9c41799 Fix formatters not running in order (#24584)
Previously, if multiple formatters were specified for the same language,
they would be run in parallel on the state of the file, and then all
edits would be applied. This lead to incorrect output with many unwanted
artifacts.
This PR refactors the formatting code to clean it up, and ensure results
from previous formatters are passed in to subsequent formatters.

Closes #15544

Release Notes:

- Fixed an issue where when running multiple formatters they would be
ran in parallel rather than sequentially, leading to unwanted artifacts
and incorrect output.

---------

Co-authored-by: Conrad <conrad@zed.dev>
2025-02-10 16:18:14 -06:00
Agus Zubiaga
1f288f7327 edit predictions: Fix predictions bar disappearing while loading (#24582)
Release Notes:

- N/A

---------

Co-authored-by: Max <max@zed.dev>
2025-02-10 21:49:46 +00:00
Peter Tripp
89e051d650 Update extension extraction documentation (2025-02-10) (#24585)
Include lessons learned from PHP Extension extraction.
2025-02-10 21:13:26 +00:00
Peter Tripp
62bb3398ed Migate PHP Extension to zed-extensions/php (#24583)
PHP Extension has been extracted to it's own repository available here:
- https://github.com/zed-extensions/php
2025-02-10 16:07:38 -05:00
Agus Zubiaga
0af048a7cf edit predictions: Cache settings across renders (#24581)
We were reading edit prediction settings too often, causing frames to be
dropped. We'll now cache them and update them from
`update_visible_inline_completion`.

Release Notes:

- N/A
2025-02-10 20:57:25 +00:00
Conrad Irwin
973cb916f3 Fix fill-co-authors, and collaborator cursors (#24575)
Co-authored-by: mikayla-maki <mikayla.c.maki@gmail.com>

Release Notes:

- N/A

Co-authored-by: mikayla-maki <mikayla.c.maki@gmail.com>
2025-02-10 13:57:07 -07:00
Michael Sloan
63c0150cc2 Fix handling of holding modifier to show edit prediction (#24580)
Meant to include this in #24442

Release Notes:

- N/A
2025-02-10 13:39:03 -07:00
Michael Sloan
78a5cf0257 Fix display of bindings for editor::AcceptInlineCompletion + add validation + use modifiers from keymap (#24442)
Release Notes:

- N/A
2025-02-10 13:01:42 -07:00
Michael Sloan
43afa68dab Make migration notification not display if some bug causes no changes (#24578)
When working on #24442, I did a project wide replacement of
`AcceptInlineCompletion` with `AcceptEditPrediction`, as I was updating
the branch to mmain and that rename had happened. This also replaced it
in the migrator, causing the migration notification to always pop up on
keymap changes.

Checking if the migration actually changes the text makes it behave
better if this variety of bug happens in the future.

Release Notes:

- N/A
2025-02-10 13:01:10 -07:00
Finn Evers
0fd2203665 context_menu: Use when instead of if-block (#24566)
See
https://github.com/zed-industries/zed/pull/24562#issuecomment-2648343416
. Should have just added that to my original comment btw - sorry!

CC @danilo-leal 

Release Notes:

- N/A
2025-02-10 16:47:09 -03:00
Liam Murphy
72e1947025 Update tree-sitter to 0.24 (#24492)
I didn't update it to 0.25 because its Wasm support seems to be
partially broken due to
https://github.com/tree-sitter/tree-sitter/pull/3938: it didn't
introduce a check that the Wasm module's ABI is new enough to include
supertype info while parsing it, and so in the case where it isn't it
ends up interpreting random bytes as the number of supertypes, causing
out-of-bounds memory accesses.

Closes #24489

Release Notes:

- Fixed a rare crash during syntax highlighting
2025-02-10 10:52:27 -08:00
Max Brunsfeld
d9909c691d Fix panic when outline items have no name (#24574)
Closes #23787

Release Notes:

- Fixed a crash when searching the outline view in certain Ruby files.
2025-02-10 18:50:26 +00:00
Kirill Bulatov
4f7200527c Revert "Fix editor::GoToDiagnostics cycle (#24446)" (#24568)
This reverts commit 4f65cfa93d.

Release Notes:

- N/A
2025-02-10 17:13:12 +00:00
Nate Butler
de8d4d00ce git_ui: Update git panel commit editor, start on quick commit
- Fixes commit editor issues & updates style
- Starts on quick commit (not hooked up to anything)
- Updates some panel styles
- Adds SwitchWithLabel
- 
Release Notes:

- N/A
2025-02-10 15:52:09 +00:00
5brian
69d415c8d0 vim: Multiline operation improvements (#24518)
Closes #15711

Discussed changes to match neovim in
https://github.com/zed-industries/zed/pull/24481#issuecomment-2644504695
-- `vi{` matches neovim with treesitter instead of vanilla neovim.
Change and delete matches standard neovim.

Not sure if this is the best way to do it, implemented post processing
to change and delete objects.
I think another way would be adjust the range to trim the trailing
newline char on change and delete operations, instead of having to add
it back.

||Before|After|
|---|---|---|

|initial|![image](https://github.com/user-attachments/assets/0bab37b7-c0ac-4992-a365-b7ec304a6800)||
| `vi{` |
![image](https://github.com/user-attachments/assets/4c802fcd-fa7e-45ba-b7d4-3283ed538e10)
|
![image](https://github.com/user-attachments/assets/4394bb6e-418b-4463-9737-f9bdfc6d31c2)
|
| `ci{` |
![image](https://github.com/user-attachments/assets/b5eabb58-4a93-4c98-80b6-f34a6525b1fb)
|
![image](https://github.com/user-attachments/assets/79af57e4-260c-4432-af66-eba5285d97a0)
|
| `di{` |
![image](https://github.com/user-attachments/assets/190a70e7-71fd-47fe-9d6c-2082f2034d0f)
|
![image](https://github.com/user-attachments/assets/775b86a9-68c1-4397-a44b-c645a772de63)
|

Release Notes:

- vim: Improved multi-line operations
2025-02-10 08:45:06 -07:00
Danilo Leal
d292b7c96d context menu: Use invisible() to hide the check icon (#24562)
Follow up to: https://github.com/zed-industries/zed/pull/24549

Release Notes:

- N/A
2025-02-10 12:16:33 -03:00
Piotr Osiewicz
ca4378cbaa ui: Use cursor: pointer for Toggles (#24563)
Closes #ISSUE

Release Notes:

- N/A
2025-02-10 15:10:35 +00:00
Finn Evers
d42322ab06 php: Update brackets.scm (#24558)
Closes #24550 
Adds some missing brackets to the PHP language extension.
2025-02-10 09:42:16 -05:00
Danilo Leal
3f0288e52a docs: Add a light border to h2s (#24554)
I was finding hard to navigate the "Configuring Zed" page with just
white space creating a boundary between the different chunks of content.
I think a slight border below the h2 heading helps a lot with that!

Release Notes:

- N/A
2025-02-10 09:43:51 -03:00
Danilo Leal
d15a61a1aa context menu: Adjust toggleable entry label alignment (#24549)
Previously, we were passing an `IconSize` that had a default size. Given
the check icon is small by default, when the entry is not toggled, that
caused a slight misalignment between the toggled and not-toggled items.
I'm passing now the same icon element but inside an opacity 0 div. Open
to other suggestions if this feels clunky.

| Before | After |
|--------|--------|
| <img width="946" alt="Screenshot 2025-02-10 at 7 58 28 AM"
src="https://github.com/user-attachments/assets/4d2b3f12-72c5-4c8d-acaf-c16230250560"
/> | <img width="943" alt="Screenshot 2025-02-10 at 7 58 37 AM"
src="https://github.com/user-attachments/assets/2df64752-7273-4bdc-9f6b-5153ed52c889"
/> |

Release Notes:

- N/A
2025-02-10 08:19:58 -03:00
Danilo Leal
e72f7b4e22 edit predictions: Put back status bar button tooltips (#24548)
These were wrongly removed in
https://github.com/zed-industries/zed/pull/24540; putting them back.

cc @SomeoneToIgnore 

Release Notes:

- N/A
2025-02-10 08:19:46 -03:00
Libon
d0c4c664b0 Brighten yellow and black terminal colors in One themes (#24420)
Closes https://github.com/zed-industries/zed/issues/24419

I made some fine adjustments to the color of the theme with reference
to' Window Terminal' to make it look good. If there is anything
inappropriate in this revision, please also point it out. :)


![window-terminal-one-light](https://github.com/user-attachments/assets/86c4002f-a5a7-4ab1-81de-e6ed0529fe06)

![window-terminal-one-dark](https://github.com/user-attachments/assets/c57095d7-0131-4978-ae6d-7105639110b5)

Release Notes:
- N/A
2025-02-10 11:03:47 +00:00
CharlesChen0823
994bea0003 workspace: Fix pane focus transfer when closing another pane (#23175)
Closes #23123 

Only close current active_pane should move focus to other pane.

Release Notes:

- N/A
2025-02-10 11:54:06 +02:00
Kirill Bulatov
6f7f0f30e2 Fix hover tooltips appearing after related element is pressed (#24540)
Closes https://github.com/zed-industries/zed/issues/23894

Reworks all trigger declarations from
`.trigger(element.tooltip(tooltip))` into
`.trigger_with_tooltip(element, tooltip)` , with new API disallowing
simultaneous trigger and tooltip display.

All existing `.trigger(` calls were replaced, except 2 not applicable
(in dock.rs and pane.rs), 15 left as ones without tooltips, and 2
unchanged places in `inline_completion_button.rs`, where


0f7bb2e9fd/crates/inline_completion_button/src/inline_completion_button.rs (L311-L319)

`with_animation` does not allow us to simply use the same approach.

Release Notes:

- Fixed hover tooltips appearing after related element is pressed

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-02-10 00:16:12 +00:00
Michael Sloan
1a133ab9d8 Settings/keymap backup path next to files + update notification messages (#24517)
Before:


![image](https://github.com/user-attachments/assets/5b7d8677-b0db-4a66-ac30-e4751ba4182d)

After:


![image](https://github.com/user-attachments/assets/94743bc2-2902-43a3-8d6e-e0e0e6e469ec)

Release Notes:

- N/A
2025-02-09 16:51:37 -07:00
Kirill Bulatov
cf74d653bd Fix outline panel issues in a multi-worktree set-up (#24538)
Closes https://github.com/zed-industries/zed/issues/22993

Properly calculates depth and maintains worktree order, when displaying
multiple worktrees in the outline panel.

Release Notes:

- Fixed outline panel issues in a multi-worktree set-up
2025-02-09 21:29:29 +00:00
Nate Butler
8f1ff189cc component: Add component and component_preview crates to power UI components (#24456)
This PR formalizes design components with the Component and
ComponentPreview traits.

You can open the preview UI with `workspace: open component preview`.

Component previews no longer need to return `Self` allowing for more
complex previews, and previews of components like `ui::Tooltip` that
supplement other components rather than are rendered by default.

`cargo-machete` incorrectly identifies `linkme` as an unused dep on
crates that have components deriving `IntoComponent`, so you may need to
add this to that crate's `Cargo.toml`:

```toml
# cargo-machete doesn't understand that linkme is used in the component macro
[package.metadata.cargo-machete]
ignored = ["linkme"]
```

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-09 13:25:03 -05:00
Agus Zubiaga
56cfc60875 ui: Add buffer_font method to labels (#24479)
Now you don't need to wrap the `Label` in a `div` anymore 

Release Notes:

- N/A

Co-authored-by: Danilo <danilo@zed.dev>
2025-02-09 15:23:39 -03:00
Kirill Bulatov
6ee447ee58 Move focus into editor for outline_panel::Open action on outlines and search results (#24535)
Follow-up of
https://github.com/zed-industries/zed/discussions/19782#discussioncomment-12055976

Release Notes:

- Fixed outline panel not focusing editor when outlines and search
results were opened with `outline_panel::Open`
2025-02-09 17:27:41 +00:00
Marshall Bowers
f42177a912 ci: Pin Prettier to a specific version for docs formatting (#24531)
This PR pins Prettier to a specific version when we run the docs
formatting check.

This should prevent drift when new Prettier versions are released that
may impact the formatting.

Release Notes:

- N/A
2025-02-09 16:46:33 +00:00
Marshall Bowers
072d2b061a ui: Remove ToolStrip component (#24529)
This PR removes the `ToolStrip` component.

Pulling this change out of
https://github.com/zed-industries/zed/pull/24456.

Release Notes:

- N/A
2025-02-09 16:07:40 +00:00
Caleb!
065fdcb86b language_tools: Add background color to syntax tree view (#24524)
Closes #22830 

@jansol, please take a look. I don't know if this is correct as I
couldn't really tell the difference. I just added the active theme's
background color to the main container of the tree view.

<img width="1309" alt="Screenshot 2025-02-09 at 10 29 15 AM"
src="https://github.com/user-attachments/assets/dadf9333-0074-4bfa-bb06-ed4c4f275200"
/>
 
Release Notes:

- Added an explicit background color to the syntax tree view.

cc: @iamnbutler

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-09 15:54:14 +00:00
Henrikh Kantuni
e84d77e879 Fix typo in elm.md (#24519)
Removes duplicate mention of `elm`.
2025-02-09 11:43:09 +02:00
smit
f1693e6129 project_panel: Fix worktree root rename (#24487)
Closes #7923

This PR fixes root worktree renaming by:  

1. Handling the case where `new_path` is the new root name instead of a
relative path from the root.
2. [#20313](https://github.com/zed-industries/zed/pull/20313) added
functionality to watch for root worktree renames made externally, e.g.,
via Finder. This PR avoids relying on that watcher because, when
renaming explicitly from Zed, we can eagerly perform the necessary work
(of course after fs rename) instead of waiting for the watcher to detect
the rename. This prevents UI glitches during renaming root.

Todo:

- [x] Fix wrong abs paths when root is renamed
- [x] Fix explicit scan entry func to handle renamed root dir
- [x] Tests
- [x] Test on Linux
- [x] Tested with single and multipe worktrees
- [x] Tested when single file is root file

Release Notes:

- Fixed an issue where worktree root name couldn't be renamed in project
panel.
2025-02-09 14:16:27 +05:30
Affan Shahid
4207b194e3 docs: Fix typo in the Icon Themes page (#24516)
Release Notes:

- N/A
2025-02-08 18:35:43 -05:00
Marshall Bowers
fe6d180a1a Sort Prettier files in file_types.json (#24505)
This PR sorts the Prettier files added in #24496.

Release Notes:

- N/A
2025-02-08 16:11:31 +00:00
João Marcos
0294b19694 Track caller on <usize as ToOffset>::to_offset (#24503)
To get useful logs when reporting bugs involving offsets out of range

Release Notes:

- N/A
2025-02-08 15:29:29 +00:00
Kirill Bulatov
b1055878c7 Improve outline panel initial update (#24500)
Closes https://github.com/zed-industries/zed/issues/24128

* removed unnecessary debounces when updating the panel data
* removed all "loading"-related messages to snow nothing when initial
data is loaded, thus reducing flickering

Release Notes:

- Improved outline panel initial update
2025-02-08 12:33:47 +00:00
Sanjeev Shrestha
3582fc4636 File icons add icon association for Prettier config (#24496)
This PR adds icon association for more Prettier's config files.

Here is the list:

```
.prettierrc.cjs
.prettierrc.js
.prettierrc.json5
.prettierrc.mjs
.prettierrc.toml
.prettierrc.yaml
.prettierrc.yml
prettier.config.cjs
prettier.config.js
prettier.config.mjs
```

Release Notes:

- Added icon support for additional Prettier config file types.
2025-02-08 17:03:01 +05:30
Mikayla Maki
ca4e8043d4 Add branch to git panel (#24485)
This PR adds the branch selector to the git panel and fixes a few bugs
in the repository selector.

Release Notes:

- N/A

---------

Co-authored-by: ConradIrwin <conrad.irwin@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
2025-02-08 03:27:58 +00:00
roycrippen4
d9183c7669 vim: Escape to normal mode when visual surround operation pending (#24484)
Closes #24382

Release Notes:
Added a default keymap that returns the user to `normal` mode after
pressing escape during a pending `visual-surround` operation.

- N/A

---------

Co-authored-by: roy.crippen4 <roy.crippen4@archarithms.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-02-07 20:23:10 -07:00
5brian
7bddb390ca vim: Preserve trailing whitespace in inner text object selections (#24481)
Closes #24438

Changes: Adjusted loop to only trim whitespace between last newline and
closing marker, when using inner objects like `y/d/c i b`

| Start   | Fixed `vib`   | Previous `vib`   |
| ---------- | ---------- | ---------- |
|
![image](https://github.com/user-attachments/assets/3d64dd7d-ed3d-4a85-9f98-f2f83799a738)
|
![image](https://github.com/user-attachments/assets/841beb59-31b1-475e-93f0-f4deaf18939c)
|
![image](https://github.com/user-attachments/assets/736d4c6f-20e1-4563-9471-1e8195455df4)
|



Release Notes:

- vim: Preserve trailing whitespace in inner text object selections

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-02-08 02:50:34 +00:00
Michael Sloan
146b9c232c Sort and dedupe .gitignore files (#24491)
Release Notes:

- N/A
2025-02-08 02:17:17 +00:00
Michael Sloan
be26acccca Cargo.lock update (#24486)
Release Notes:

- N/A
2025-02-08 00:18:20 +00:00
Beniamin Zagan
4be89ea60f title_bar: Add menu item to deploy icon theme selector (#24482)
Added the icons option in the title bar between Themes and Extension.

| Before | After |
|
---------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------
|
| <img width="215" alt="Screenshot 2025-02-07 at 5 18 10 PM"
src="https://github.com/user-attachments/assets/ff8bf5ce-c176-4d8c-8b0e-bb1cc65ec1d8"
/> | <img width="206" alt="Screenshot 2025-02-07 at 5 18 01 PM"
src="https://github.com/user-attachments/assets/c47a302e-98af-4530-a908-097b8306f2f0"
/> |

Release Notes:

- Added an option to open the icon theme selector from the user menu.

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-07 22:33:00 +00:00
Marshall Bowers
e17e838c07 Include prediction ID on edit prediction accepted/discarded events (#24480)
This PR updates the edit predictions to include the prediction ID
returned from the server on the resulting telemetry events indicating
whether the prediction was accepted or discarded.

The `prediction_id` on the events can then be correlated with the
`request_id` on the server-side prediction events.

Release Notes:

- N/A
2025-02-07 22:06:37 +00:00
Marshall Bowers
ed5656813c inline_completion: Add missing punctuation (#24477)
This PR adds some missing punctuation.

Release Notes:

- N/A
2025-02-07 21:03:37 +00:00
Danilo Leal
c4bcff1e87 edit predictions: Add binding to the prediction toggle (#24468)
This PR primary goal is to add a keybinding to the (ephemeral)
prediction toggle. In doing that, we also standardized the keybinding to
open the status bar menu with it.

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
2025-02-07 18:01:39 -03:00
Danilo Leal
07f1b612cf edit predictions: Fix translucent "jump to edit" background color (#24473)
This PR uses a pretty cool GPUI method called `blend` to make this
callout's background color not translucent.

| Before | Header |
|--------|--------|
| <img width="732" alt="Screenshot 2025-02-07 at 4 58 16 PM"
src="https://github.com/user-attachments/assets/2a5df61b-dfa0-4edc-bffa-a605a2aa491a"
/> | <img width="732" alt="Screenshot 2025-02-07 at 4 56 48 PM"
src="https://github.com/user-attachments/assets/5dee9fca-6239-4ae0-80f5-dcc6abf0e779"
/> |

Release Notes:

- N/A
2025-02-07 17:58:20 -03:00
Marshall Bowers
9e5bc81f1c zeta: Promote line comment to doc comment (#24476)
This PR promotes a line comment for the `tos_accepted` field to a doc
comment.

Release Notes:

- N/A
2025-02-07 20:57:42 +00:00
Conrad Irwin
7148092e12 Fix adding new git repos to a project (#24471)
Release Notes:

- N/A
2025-02-07 20:08:09 +00:00
Jason Lee
ead5a836a1 gpui: Add data table example (#24373)
Release Notes:

- N/A

As https://github.com/zed-industries/zed/discussions/24260 I mentioned
issue.

Make a complex data table example to test the text rendering
performance.

This example also can be an example to show how to build a large data
table.

```bash
cargo run -p gpui --example data_table
```

<img width="2004" alt="image"
src="https://github.com/user-attachments/assets/653771e5-ef08-4d76-97b9-90ea4b78be59"
/>

----

I will try to do some test. 

For example: With a threshold for the hold number of caches in
`FrameCache`, and only when the threshold is greater than a certain
number, some caches are released, or when a certain time has passed. I
am not sure if this is feasible.

This example is added to help us to test.
2025-02-07 11:54:34 -08:00
Conrad Irwin
3be8066415 Newlines in commit editor (#24465)
Release Notes:

- N/A
2025-02-07 12:31:12 -07:00
Antonio Scandurra
f6e396837c Re-introduce syntax-based context and use new model (#24469)
Release Notes:

- N/A

---------

Co-authored-by: Marshall <marshall@zed.dev>
2025-02-07 19:19:57 +00:00
Agus Zubiaga
fd7fa87939 edit predictions: Restore red dot in status buttons when pending ToS (#24408)
In one of the recent changes to the edit predictions status bar menu, we
lost the red dot that is displayed when the user has Zed as the provider
but hasn't accepted terms of service. Note: All the checks were still in
place, just the visual indicator was missing.

![CleanShot 2025-02-06 at 20 22
21@2x](https://github.com/user-attachments/assets/da8f25dd-5ed2-4bf9-8453-10b80f00bf63)


Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-02-07 15:42:27 -03:00
Danilo Leal
a7a14e59bf edit predictions: Clarify disabled_globs documentation (#24460)
This PR clarifies how the `disabled_globs` work.

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
2025-02-07 19:35:55 +01:00
Marshall Bowers
8ff8dbdb2b assistant_context_editor: Fix patch block not rendering due to window reborrow (#24461)
This PR fixes an issue where the Assistant patch block was not being
rendered when using "Suggest Edits".

The issue was that the `BlockContext` already has a borrow of the
`Window`, so we can't use `update_in` to reborrow the window.

The fix is to reuse the existing `&mut Window` reference from the
`BlockContext` so we don't need to `update_in`.

Closes #24169.

Release Notes:

- Assistant: Fixed an issue where the patch block was not being rendered
when using "Suggest Edits".

---------

Co-authored-by: Max <max@zed.dev>
2025-02-07 18:03:19 +00:00
smit
44c6a54f95 pane: Improve close active item to better handle pinned tabs (#23488)
Closes #22247

- [x] Do not close pinned tab on keyboard shortcuts like `ctrl+w` or
`alt+f4`
- [x] Close pinned tab on context menu action, menu bar action, or vim
bang
- [x] While closing pinned tab via shortcut (where it won't close),
instead activate any other non-pinned tab in same pane
- [x] Else, if any other pane contains non-pinned tab, activate that
- [x] Tests

Co-authored-by: uncenter <47499684+uncenter@users.noreply.github.com>

Release Notes:

- Pinned tab now stay open when using close shortcuts, auto focuses to
any other non-pinned tab instead.
2025-02-07 22:54:57 +05:30
Bennet Bo Fenner
f0565b4e2e edit prediction: Do not show icon as disabled when there is no buffer open (#24458)
Release Notes:

- N/A
2025-02-07 17:02:14 +00:00
Conrad Irwin
a6e15dda4b Make it a bit clearer when people are running dev builds (#24457)
Release Notes:

- Include an indicator in About/CopySystemSpecs when running in debug mode
2025-02-07 09:57:37 -07:00
Finn Evers
144487bf1a theme: Implement icon theme reloading (#24449)
Closes #24353 

This PR implements icon theme reload to ensure file icons are properly
updated whenever an icon theme extension is upgraded or uninstalled.

Currently, on both upgrade and uninstall of an icon theme extension the
file icons from the previously installed version will stay visibile and
will not be updated as shown in the linked issue. With this change, file
icons will properly be updated on extension upgrade or reinstall.

The code is primarily a copy for reloading the current color theme
adapted to work for icon themes. Happy for any feedback!


Release Notes:

- Fixed file icons not being properly updated upon icon theme upgrade or
uninstall.
2025-02-07 11:30:53 -05:00
Wilhelm Klopp
2d57e43e34 docs: Emphasize that Rust must be installed via rustup (#24447)
Just tried installing a dev extension and kept getting "error: failed to install dev extension".

Turns out this was because I had rust installed via homebrew and not rust. Once I switched to rustup, it worked perfectly fine.

Release Notes:

- N/A
2025-02-07 11:29:45 -05:00
Peter Tripp
c484374b2f Make OpenKeyContextView open to the right (#24452)
Match the behavior of OpenSyntaxTreeView logs and OpenLanguageServerLogs

Release Notes:

- Make `debug::OpenSyntaxTreeView` automatically open in split to the
right
2025-02-07 11:20:27 -05:00
IaVashik
8114d17cba google_ai: Add support for Gemini 2.0 models (#24448)
Add support for the newly released Gemini 2.0 models from Google announced this new family of models earlier this week (2025-02-05).

Release Notes:

- Added support for Google's new Gemini 2.0 models.
2025-02-07 11:18:18 -05:00
Sanjeev Shrestha
c7cd5b019b file_icons: Use separate icon key for JSON files (#24432)
This PR updates the file icon mappings for JSON (`.json`) file map to
the`json` key. Also, updates `.json` icon from `storage` to `code`.

This allows for the JSON file icons to be replaced in icon themes.

Release Notes:

- Icon themes: Added the ability to change the file icon for JSON
(`.json`) files.

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-07 16:14:26 +00:00
Marshall Bowers
07929229ae migrator: Sort dependencies in Cargo.toml (#24455)
This PR sorts the dependencies in the `Cargo.toml` for the `migrator`
crate.

Release Notes:

- N/A
2025-02-07 16:10:07 +00:00
smit
00c2a30059 Migrate keymap and settings + edit predictions rename (#23834)
- [x] snake case keymap properties
- [x] flatten actions
- [x] keymap migration + notfication
- [x] settings migration + notification
- [x] inline completions -> edit predictions 

### future: 
- keymap notification doesn't show up on start up, only on keymap save.
this is existing bug in zed, will be addressed in seperate PR.

Release Notes:

- Added a notification for deprecated settings and keymaps, allowing you
to migrate them with a single click. A backup of your existing keymap
and settings will be created in your home directory.
- Modified some keymap actions and settings for consistency.

---------

Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2025-02-07 21:17:07 +05:30
Ben Kunkle
a1544f47ad Fix incorrect assumption about Path.extension() (#24443)
Release Notes:

- N/A
2025-02-07 09:37:07 -06:00
Kirill Bulatov
4f65cfa93d Fix editor::GoToDiagnostics cycle (#24446)
https://github.com/user-attachments/assets/45f665f0-473a-49bd-b013-b9d1bdb902bd


After activating 2nd diagnostics group, `find_map` code for next
diagnostics did not skip the previous group for the same place.

Release Notes:

- Fixed `editor::GoToDiagnostics` action stuck when multiple diagnostics
groups belong to the same place
2025-02-07 16:49:13 +02:00
Piotr Osiewicz
b6b06cf6d8 lsp: Send DidOpen notifications when changing selections in multi buffer (#22958)
Fixes #22773

Release Notes:

- Fixed an edge case with multibuffers that could break language
features within them.
2025-02-07 12:33:35 +01:00
Michael Sloan
f700268029 Improve vim interactions with edit predictions (#24418)
* When an edit prediction is present in non-insertion modes, hide it but
show `tab Jump to edit`.
* Removes discarding of edit predictions when going from insert mode to
normal mode, instead just hide them in non-insertion modes.
* Removes zeta-specific showing of predictions in normal mode. This
behavior was only happening in special cases anyway - where the discard
of completions wasn't happening due to some other thing taking
precedence in `dismiss_menus_and_popups`.

Release Notes:

- N/A

---------

Co-authored-by: Conrad <conrad@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
2025-02-07 03:53:38 -07:00
Michael Sloan
92c21a2814 Fix undismissed app notifications appearing on new workspaces (#24437)
Bug in #23817

Release Notes:

- N/A
2025-02-07 10:29:05 +00:00
Conrad Irwin
1f9d02607b Fixes to commit button in Git Panel (#24425)
Git Panel updates:

* Fixes commit/commit all button to work (and be disabled correctly in
merge conflict status)
* Updates keyboard shortcuts and sets focus on the button (enter now
does the same as click; tab cycles between editor and change list)


Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-02-07 00:21:28 -07:00
smit
6534e0bafd linux: Fix crash when NoKeymap event is received on Wayland (#24379)
Closes #24139

For weird reasons, Sway on few linux distoros sends `NoKeymap` event when
switching windows. Zed crashes due to assertion on this event to be `XkbV1`.

To fix this, we ignore `NoKeymap` event instead crashing Zed.

Release Notes:

- Fixed a crash in Wayland-based compositors like Sway when switching windows via the keyboard.
2025-02-07 12:31:46 +05:30
Cole Miller
5ffacb9ca5 Revert "Move git status updates to a background thread (#24307)" (#24415)
This reverts commit 980ce5fbf2.

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-02-07 04:46:43 +00:00
Michael Sloan
864c1ff00c Use commondir from libgit2 instead of walking fs (#22028)
Release Notes:

- N/A
2025-02-07 04:38:09 +00:00
Michael Sloan
35ef269233 Fix build of remote_server when not in git repo (#24424)
Followup to #24258

Release Notes:

- N/A
2025-02-07 04:35:22 +00:00
Cole Miller
d97adfc540 Fix pairs of almost-adjacent hunks toggling together (#24355)
Release Notes:

- Fixed a bug where toggling a diff hunk that immediately precedes
another hunk would act on both hunks
2025-02-07 04:18:59 +00:00
Michael Sloan
a42e040660 Remove use of use_key_equivalents from linux keymap as it does nothing (#24422)
`use_key_equivalents` does nothing on linux, as key equivalents are only
supported on mac. While it could be sensible to anticipate support,
right now it is only used in these few spots, so removing it.

Release Notes:

- N/A
2025-02-07 03:46:15 +00:00
Conrad Irwin
8646d37c0c vim: Replace with Register (#24326)
Closes #18813

Release Notes:

- vim: Add `gr` for [replace with
register](https://github.com/vim-scripts/ReplaceWithRegister)
2025-02-06 20:24:41 -07:00
Anthony Eid
d83c316e6d Fix Project Panel select_next_git_entry action (#24217)
## Context

I noticed that the project panel `select_next_git_entry` wasn't behaving
correctly. Turns out it was searching in reverse, which caused the
action to select itself or the last entry.

This PR corrects the behavior and adds a unit test that should stop
regressions.

Note: Since select next/prev git entry uses the same function as select
next/prev diagnostic, the test partially works for that as well.

Release Notes:

- Fix bug where `select_next_git_entry` project panel action would only
select a previous entry or the currently selected entry.

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2025-02-07 03:04:02 +00:00
Jason Lee
c5913899d9 gpui: Fix text-align with nowrap mode (#24116)
Release Notes:

- N/A


------

- Continue #24090 to fix text align for when used `whitespace_nowrap`.
- Fix wrapped line length calculation.

And add example

```
cargo run -p gpui --example text_layout
```

<img width="760" alt="image"
src="https://github.com/user-attachments/assets/a087c300-0e0e-4a80-98c6-90161a9b0905"
/>

---------

Co-authored-by: Owen Law <owenlaw222@gmail.com>
2025-02-06 18:51:00 -08:00
Stanislav Alekseev
e689c8c01b markdown: Use parsed text (#24388)
Fixes #15463

Release Notes:

- Fixed display of symbols such as `&nbsp;` in hover popovers
2025-02-06 18:37:50 -08:00
Marshall Bowers
888a2df3f0 Sort Cargo.tomls (#24417)
This PR sorts the dependencies in a number of `Cargo.toml` files.

Release Notes:

- N/A
2025-02-07 02:14:57 +00:00
Caleb!
d6d0d7d3e4 Add image dimension and file size information (#21675)
Closes https://github.com/zed-industries/zed/issues/21281

@jansol, kindly take a look when you're free.


![image](https://github.com/user-attachments/assets/da9a54fa-6284-4012-a243-7e355a5290d3)

Release Notes:

- Added dimensions and file size information for images.

---------

Co-authored-by: tims <0xtimsb@gmail.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-07 00:56:34 +00:00
Ben Kunkle
a1ed1a00b3 Fix issue with Vim test instead of cheating (#24411)
Appears this test was failing, and someone edited the expected test
output instead of fixing it. Well no longer!

Release Notes:

- N/A

Co-authored-by: Conrad <conrad@zed.dev>
2025-02-06 18:43:30 -06:00
Cole Miller
a190f42ccc Fix double-lease panic in Repository::activate (#24414)
Release Notes:

- N/A

Co-authored-by: maxbrunsfeld <max@zed.dev>
2025-02-07 00:33:41 +00:00
Cole Miller
59bba2a98c Assign base text language earlier to fix missing highlighting in deletion hunks (#24413)
Release Notes:

- Fixed deletion diff hunks not being syntax highlighted in some cases

Co-authored-by: Max <max@zed.dev>
2025-02-06 16:14:47 -08:00
Peter Tripp
5315d38cf4 Update extension extraction docs (#24079)
- Fixed a regex for finding tags.
- Templatize the instructions with `$LANGNAME` to prevent manual errors
from failing to edit commands (this bit me)
- Ran formatting through Prettier
2025-02-06 19:01:32 -05:00
Ben Kunkle
337b9e62d2 Fix vim full line operations failing when no trailing newline (#24409)
Closes #24270

Release Notes:

- Fixed an issue where doing line-wise operations in vim mode on the
last line of a file with no trailing newline would not work properly
2025-02-06 17:57:24 -06:00
Cole Miller
73c487c222 Introduce diff crate to unite BufferDiff and BufferChangeSet (#24392)
This is a refactoring PR that does three things:

- First, it introduces a new `diff` crate that holds the previous
contents of the `git::diff` module, plus the `BufferChangeSet` type
formerly of `project::buffer_store`. The new crate is necessary since
simply moving `BufferChangeSet` into `git::diff` results in a dependency
cycle due to the use of `language::Buffer` to represent the diff base in
`BufferChangeSet`.
- Second, it renames the two main types in the new diff crate:
`BufferDiff` becomes `BufferDiffSnapshot`, and `BufferChangeSet` becomes
`BufferDiff`. This reflects that the relationship between these two
types (immutable cheaply-cloneable "value" type + stateful "resource
type" with subscriptions) mirrors existing pairs like
`Buffer`/`BufferSnapshot`. References to "change sets" throughout the
codebase are updated to refer to "diffs" instead.
- Finally, it moves the base_text field of the new BufferDiff type to
BufferDiffSnapshot.

Release Notes:

- N/A

---------

Co-authored-by: maxbrunsfeld <max@zed.dev>
2025-02-06 18:52:32 -05:00
Finn Evers
ffcad71bfa file_icons: Resolve icon properly for exact file name match (#24396)
Follow-up to #24391 

The current approach has two issues:
- For the described case of `eslint.config.js`, for which a mapping
exists in `suffixes`, this would get mapped from `eslint.config.js` to
`eslint`. However, for `eslint`, there is no mapping within `suffixes`,
thus currently `get_icon_from_suffix` would return `None` and a wrong
item would be returned at a later step.
- Paths passed to this method are relative to the worktree root, thus
e.g. `eslint.config.js` files in subdirectories would still be assigned
the wrong icon.

---

Behaviour on `main`:
<img width="281" alt="main"
src="https://github.com/user-attachments/assets/19b5e5f8-e413-4ac9-a0a1-2c72f810aa86"
/>

Behaviour with this change:
<img width="299" alt="pr"
src="https://github.com/user-attachments/assets/eec70cbd-df39-49b4-8b07-d22afa949781"
/>

CC @probably-neb 

Release Notes:

- N/A
2025-02-06 17:14:39 -06:00
Marshall Bowers
3ab48b31a1 image_viewer: Fix cargo test errors (#24404)
This PR fixes the errors when running `cargo test` in the `image_viewer`
crate.

Release Notes:

- N/A
2025-02-06 22:38:35 +00:00
Nate Butler
00971fbe41 Introduce KeybindingHint (#24397)
- Implements scaling for `ui::Keybinding` and it's component parts
- Adds the `ui::KeybindingHint` component for creating keybinding hints
easily:

![CleanShot 2025-02-04 at 16 59
38@2x](https://github.com/user-attachments/assets/d781e401-8875-4edc-a4b0-5f8750777d86)

Release Notes:

- N/A
2025-02-06 21:45:03 +00:00
Ben Kunkle
9c132fece5 Fix #24314 - File icons missing for hidden files (#24391)
- **fix ignoring ignored files when matching icons**
- **remove poorly named and confusing method
`PathExt.icon_stem_or_suffix` and refactor
`PathExt.extension_or_hidden_file_name` to actually do what it says it
does**

Closes #24314

Release Notes:

- Fixed an issue where hidden files would have the default icon instead
of the correct one
- Fixed an issue where files with specific icons (such as
`eslint.config.js`) would not have the their specific icon without a
leading `.` (`.eslint.config.js`)
2025-02-06 14:26:42 -06:00
Danilo Leal
ad46c5b567 edit prediction: Improve the onboarding modal (#24386) 2025-02-06 19:58:53 +00:00
Danilo Leal
c28c767b40 edit prediction: Wordsmith status bar menu docs aside (#24390)
Refining writing in the status bar menu docs aside.

Release Notes:

- N/A

---------

Co-authored-by: Nathan Sobo <1789+nathansobo@users.noreply.github.com>
2025-02-06 19:49:13 +00:00
Agus Zubiaga
e1bb9570df edit predictions: Reset onboarding action (#24387)
https://github.com/user-attachments/assets/bb597b93-a616-4f8a-8608-013b8202799c


Release Notes:

- N/A
2025-02-06 19:07:27 +00:00
Marshall Bowers
09967ac3d0 zeta: Send up diagnostics with prediction requests (#24384)
This PR makes it so we send up the diagnostic groups as additional data
with the edit prediction request.

We're not yet making use of them, but we are recording them so we can
use them later (e.g., to train the model).

Release Notes:

- N/A

---------

Co-authored-by: Nathan <nathan@zed.dev>
2025-02-06 18:07:26 +00:00
Agus Zubiaga
13089d7ec6 edit predictions: Polish up ⌥ preview experience (#24380)
- Do not accept with just `tab` in `when_holding_modifer` mode
- Fix fake cursor for jumps when destination row is outside viewport
- Use current preview state for deciding whether to show modifiers in
popovers
- Stay in preview state if ⌥ isn't released after accepting a jump

Release Notes:

- N/A
2025-02-06 16:13:21 +00:00
0x2CA
c24f22cd14 vim: Fix Around Subword not including whitespace (#24356)
Closes #24271

Release Notes:

- Fixed Around Subword No Include Whitespace
2025-02-06 08:54:04 -07:00
Marshall Bowers
8fc5d227a4 copilot: Sort dev dependencies in Cargo.toml (#24378)
This PR sorts the dev dependencies in `copilot`'s `Cargo.toml`.

Release Notes:

- N/A
2025-02-06 15:19:03 +00:00
Cole Miller
01bcbf3b0d Fix missing diff hunks in single-file worktrees (#24377)
Release Notes:

- Fixed diff hunks not appearing when opening a single file within a
larger repository
2025-02-06 10:13:56 -05:00
Danilo Leal
592642fbfc edit predictions: Tweak status bar menu copywriting (#24376)
Just fine-tuning words on items of the status bar menu.

Release Notes:

- N/A
2025-02-06 11:28:25 -03:00
Danilo Leal
35886e38e5 edit prediction: Add minor UI tweaks to the preview bar (#24174)
Just little nudges of spacing, alignment, and treatment for overflowing
content.

Release Notes:

- N/A
2025-02-06 11:00:09 -03:00
Agus Zubiaga
8ed8b4d2ec edit predictions: Preview while holding modifier mode (#24316)
This PR adds a new `inline_completions.inline_preview` config which can
be set to `auto` (current behavior) or to `when_holding_modifier`.
When set to the latter, instead of showing edit prediction previews
inline in the buffer, we'll show it in a popover (even when there's no
LSP completion) so your isn't constantly moving as completions arrive.


https://github.com/user-attachments/assets/3615d151-3633-4ee4-98b9-66ee0aa735b8

Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>
2025-02-06 09:58:19 -03:00
Kirill Bulatov
b4d8b1be3f Preserve Wrangler logs during docs deployment CI runs (#24371)
Adds a log collection step to debug errors like
https://github.com/zed-industries/zed/actions/runs/13175284280/job/36773129216#step:8:29

During testing though, the CI had passed, so 500 seems to be unrelated
to Zed changes:
https://github.com/zed-industries/zed/actions/runs/13175800537/job/36774702686

Release Notes:

- N/A
2025-02-06 10:12:22 +00:00
Kirill Bulatov
d459cd517e Alter Windows CI disk limits (#24368)
An attempt to fix
https://github.com/zed-industries/zed/actions/runs/13174780143/job/36771552892

Release Notes:

- N/A
2025-02-06 09:53:25 +00:00
Michael Sloan
69e6910c9c Add build SHA to panic reports and zed --version (on nightly/dev) (#24258)
Release Notes:

- N/A
2025-02-06 02:09:24 -07:00
Jason Lee
f08b1d78ec Revert "Revert recent anti-aliasing improvements (#24289)" and fix selection top right corner radius issue (#24342)
Release Notes:

- N/A

----

To fix #24289 mention issue and revert PathBuilder and MSAA.

I'm sorry about of this, in #22808 I was forgotten this bit of detail.


![image](https://github.com/user-attachments/assets/112afda2-088c-41d0-83bd-808f6cd2f9d5)

So, add `move_to` here, we can fix the selection top right corner radius
issue.

## After change

<img width="1383" alt="image"
src="https://github.com/user-attachments/assets/28ea103c-d652-41d6-bbe0-7fd042d81e77"
/>
2025-02-06 11:03:23 +02:00
Michael Sloan
1f2205d75c Wrap AnyView.cached_style in an Rc to make the struct much smaller (#24363)
Byte size before was 672, now is 56. The `cached` method is only used in
two places, so this was a lot of extra bytes being shuffled around for
every `AnyView` not using this.

Release Notes:

- N/A
2025-02-06 08:37:46 +00:00
renovate[bot]
53fcd7cc92 Update Rust crate clap to v4.5.28 (#24311)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.23` -> `4.5.28` |

---

### Release Notes

<details>
<summary>clap-rs/clap (clap)</summary>

###
[`v4.5.28`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4528---2025-02-03)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.27...v4.5.28)

##### Features

- *(derive)* Unstable support for full markdown syntax for doc comments,
enabled with `unstable-markdown`

###
[`v4.5.27`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4527---2025-01-20)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.26...v4.5.27)

##### Documentation

-   Iterate on tutorials and reference based on feedback

###
[`v4.5.26`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4526---2025-01-09)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.25...v4.5.26)

##### Fixes

-   *(error)* Reduce binary size with the `suggestions` feature

###
[`v4.5.25`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4525---2025-01-09)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.24...v4.5.25)

##### Fixes

-   *(help)* Reduce binary size

###
[`v4.5.24`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4524---2025-01-07)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.23...v4.5.24)

##### Fixes

- *(parser)* Correctly handle defaults with `ignore_errors(true)` and
when a suggestion is provided for an unknown argument

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:31:37 +02:00
renovate[bot]
88ff44f2e8 Update Rust crate rustc-hash to v2.1.1 (#24317)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [rustc-hash](https://redirect.github.com/rust-lang/rustc-hash) |
workspace.dependencies | patch | `2.1.0` -> `2.1.1` |

---

### Release Notes

<details>
<summary>rust-lang/rustc-hash (rustc-hash)</summary>

###
[`v2.1.1`](https://redirect.github.com/rust-lang/rustc-hash/blob/HEAD/CHANGELOG.md#211)

[Compare
Source](https://redirect.github.com/rust-lang/rustc-hash/compare/v2.1.0...v2.1.1)

-   Change the internal algorithm to better accomodate large hashmaps.
This mitigates a [regression with 2.0 in
rustc](https://redirect.github.com/rust-lang/rust/issues/135477).
See [PR#55](https://redirect.github.com/rust-lang/rustc-hash/pull/55)
for more details on the change (this PR was not merged).
This problem might be improved with changes to hashbrown in the future.

#### 2.1.0

-   Implement `Clone` for `FxRandomState`
-   Implement `Clone` for `FxSeededState`
-   Use SPDX license expression in license field

#### 2.0.0

-   Replace hash with faster and better finalized hash.
    This replaces the previous "fxhash" algorithm originating in Firefox
with a custom hasher designed and implemented by Orson Peters
([`@orlp`](https://redirect.github.com/orlp)).
It was measured to have slightly better performance for rustc, has
better theoretical properties
    and also includes a significantly better string hasher.
-   Fix `no_std` builds

#### 1.2.0 (**YANKED**)

**Note: This version has been yanked due to issues with the `no_std`
feature!**

-   Add a `FxBuildHasher` unit struct
-   Improve documentation
-   Add seed API for supplying custom seeds other than 0
- Add `FxRandomState` based on `rand` (behind the `rand` feature) for
random seeds
-   Make many functions `const fn`
-   Implement `Clone` for `FxHasher` struct

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:30:51 +02:00
renovate[bot]
b96f62f4c9 Update Rust crate derive_more to v0.99.19 (#24312)
This PR contains the following updates:

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

---

### Release Notes

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

###
[`v0.99.19`](https://redirect.github.com/JelteF/derive_more/blob/HEAD/CHANGELOG.md#09919---2025-02-03)

[Compare
Source](https://redirect.github.com/JelteF/derive_more/compare/v0.99.18...v0.99.19)

-   Add crate metadata for the Rust Playground.

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:30:15 +02:00
renovate[bot]
b1b2e812b1 Update Rust crate toml to v0.8.20 (#24318)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [toml](https://redirect.github.com/toml-rs/toml) |
workspace.dependencies | patch | `0.8.19` -> `0.8.20` |

---

### Release Notes

<details>
<summary>toml-rs/toml (toml)</summary>

###
[`v0.8.20`](https://redirect.github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20)

[Compare
Source](https://redirect.github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:26:48 +02:00
James Roberts
00b1964940 auto_update_ui: Show update notification across workspaces (#23458)
When Zed reopens after an auto-update is installed, a notification was
previously displayed in the first window opened. If there were multiple
windows open, the notification could be hidden because Zed reopens the
last session's window stack in order from back to front. Now, the
notification is opened in every workspace, and dismissing the
notification in any workspace will dismisses it everywhere.

Closes #23236

Release Notes:

- Improved notification after Zed is updated to be visible in all
workspaces.

---------

Co-authored-by: Michael Sloan <michael@zed.dev>
2025-02-06 08:05:41 +00:00
renovate[bot]
a6f83c283c Update Rust crate bytes to v1.10.0 (#24335)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bytes](https://redirect.github.com/tokio-rs/bytes) |
workspace.dependencies | minor | `1.9.0` -> `1.10.0` |

---

### Release Notes

<details>
<summary>tokio-rs/bytes (bytes)</summary>

###
[`v1.10.0`](https://redirect.github.com/tokio-rs/bytes/blob/HEAD/CHANGELOG.md#1100-February-3rd-2025)

[Compare
Source](https://redirect.github.com/tokio-rs/bytes/compare/v1.9.0...v1.10.0)

##### Added

- Add feature to support platforms without atomic CAS
([#&#8203;467](https://redirect.github.com/tokio-rs/bytes/issues/467))
- `try_get_*` methods for `Buf` trait
([#&#8203;753](https://redirect.github.com/tokio-rs/bytes/issues/753))
- Implement `Buf::chunks_vectored` for `Take`
([#&#8203;617](https://redirect.github.com/tokio-rs/bytes/issues/617))
- Implement `Buf::chunks_vectored` for `VecDeque<u8>`
([#&#8203;708](https://redirect.github.com/tokio-rs/bytes/issues/708))

##### Fixed

- Remove incorrect guarantee for `chunks_vectored`
([#&#8203;754](https://redirect.github.com/tokio-rs/bytes/issues/754))
- Ensure that tests pass under `panic=abort`
([#&#8203;749](https://redirect.github.com/tokio-rs/bytes/issues/749))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:02:36 +02:00
renovate[bot]
97cda3f410 Update aws-sdk-rust monorepo (#24334)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [aws-config](https://redirect.github.com/smithy-lang/smithy-rs) |
dependencies | patch | `1.5.15` -> `1.5.16` |
| [aws-sdk-kinesis](https://redirect.github.com/awslabs/aws-sdk-rust) |
dependencies | minor | `1.59.0` -> `1.60.0` |
| [aws-sdk-s3](https://redirect.github.com/awslabs/aws-sdk-rust) |
dependencies | minor | `1.72.0` -> `1.73.0` |

---

### 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://redirect.github.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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:02:14 +02:00
renovate[bot]
7cbcca2881 Update Rust crate wayland-cursor to v0.31.8 (#24328)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [wayland-cursor](https://redirect.github.com/smithay/wayland-rs) |
dependencies | patch | `0.31.7` -> `0.31.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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 10:01:56 +02:00
Michael Sloan
10792ee0ad First check if menu visible in layout_gutter_menu (#24259)
Also uses an expect instead of unwrap for result of
`render_context_menu`

Release Notes:

- N/A
2025-02-06 06:46:23 +00:00
João Marcos
c61f12dd22 Zeta: Skip opening files redundantly if a license was found (#24357)
Release Notes:

- N/A
2025-02-06 06:07:05 +00:00
João Marcos
1cdfbe2d5f License detection: also check LICENSE.txt and LICENCE.txt (#24351)
and move the list of files to `crates/zeta/src/license_detection.rs`
for better visibility.

Release Notes:

- N/A
2025-02-06 04:04:35 +00:00
João Marcos
fa0261e3ad Add more info to CONTRIBUTING.md (#24348)
mention the crates:
- `cli`
- `zed`

and add a section for packaging Zed, which links to our website docs

Release Notes:

- N/A
2025-02-06 03:58:21 +00:00
João Marcos
5931af810e Update Cargo.lock according to changes on #24347 (#24350)
Release Notes:

- N/A
2025-02-06 03:54:39 +00:00
Ben Kunkle
8b3d315e40 Fix #24081 - lsp diagnostic code type conversion (#24347)
- **store `buffer::Diagnostic`as NumberOrString instead of assuming
String**
- **update zed-industries/lsp-types rev**

Closes #24081

Release Notes:

- Fixed an issue where language server diagnostic codes would be converted to strings leading to errors with some language servers
2025-02-05 21:23:46 -06:00
Mikayla Maki
10b6bc2508 Fix broken merge (#24341)
Release Notes:

- N/A
2025-02-06 02:21:42 +00:00
Amr Bashir
4270f89956 gpui: Implement HasWindowHandle on Window (#24327)
Implement `raw_window_handle::HasWindowHandle` for `gpui::Window`

This opens a lot of possibility of using gpui with platform specific
APIs.

Edit: With this exposed, we can use crates like `window-vibrancy`,
`muda` (menus crate) or even use `wry` (a webview renderer) to create a
child `WebView` inside the gpui window.

Release Notes:

- N/A
2025-02-06 01:55:17 +00:00
Conrad Irwin
0a70627f00 Split conflicts into their own section (#24324)
Co-Authored-By: Mikayla <mikayla@zed.dev>

Release Notes:

- N/A
2025-02-05 18:34:14 -07:00
Conrad Irwin
5d1c56829a Add staged checkboxes to multibuffer headers (#24308)
Co-authored-by: Mikayla <mikayla@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
2025-02-05 18:32:07 -07:00
Marshall Bowers
0671be215f gpui: Render SVGs at 2x size when rendered in an img (#24332)
This PR adjusts the rendering of SVGs when used with the `img` element
such that they are rendered at 2x their displayed size.

This results in much crisper icons for icons loaded by icon themes:

<img width="1136" alt="Screenshot 2025-02-05 at 7 39 48 PM"
src="https://github.com/user-attachments/assets/47d1fcee-c54d-4717-8fca-9b9d2bc8da9a"
/>

<img width="1136" alt="Screenshot 2025-02-05 at 7 40 01 PM"
src="https://github.com/user-attachments/assets/3061157c-8c88-41c1-a5dc-83ef9cd341cb"
/>

Release Notes:

- Improved the resolution of icons rendered by icon themes.
2025-02-06 01:05:43 +00:00
renovate[bot]
3374514f82 Update Rust crate zed_llm_client to v0.1.2 (#24329)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [zed_llm_client](https://crates.io/crates/zed_llm_client) |
workspace.dependencies | patch | `0.1.1` -> `0.1.2` |

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 00:26:24 +00:00
Marshall Bowers
4e5b11a0a7 extensions_ui: Add general structure for filtering extensions by what they provide (#24325)
This PR adds the general structure for filtering the extensions list by
what the extensions provide.

Currently flagged for Zed staff until we get some design direction on
how best to present the filter.

Release Notes:

- N/A
2025-02-06 00:09:37 +00:00
Marshall Bowers
d81a4ec7ec file_icons: Use a separate icon key for HTML files (#24323)
This PR updates the file icon mappings such that HTML (`.html` and
`.htm`) files map to the `html` key.

This allows for the HTML file icons to be replaced in icon themes.

Release Notes:

- Icon themes: Added the ability to change the file icon for HTML
(`.html`, `.htm`) files.
2025-02-05 18:35:27 -05:00
Kirill Bulatov
980ce5fbf2 Move git status updates to a background thread (#24307)
Part of https://github.com/zed-industries/zed/issues/24099
Part of https://github.com/zed-industries/zed/issues/23025

Git status checks & updates are still slow for such repos, but those are
now not blocking FS entry population and rescans.

Release Notes:

- Improved project panel's speed in large projects
2025-02-05 23:14:26 +00:00
Michael Sloan
1dbca5d9a0 Mostly fix hover tooltips not respecting occlusion (#24319)
Regression in #22644

Unfortunately not a full fix, In the case where a tooltip gets displayed
and then gets occluded after display, it will stick around until the
mouse exits the hover bounds.

Release Notes:

- N/A

Co-authored-by: Ben <ben@zed.dev>
2025-02-05 23:08:56 +00:00
Marshall Bowers
e1919b4121 collab: Add the ability to filter extensions by what they provide (#24315)
This PR adds the ability to filter extension results from the extension
API by the features that they provide.

For instance, to filter down just to extensions that provide icon
themes:

```
https://api.zed.dev/extensions?provides=icon-themes
```

Release Notes:

- N/A
2025-02-05 22:12:18 +00:00
Patrick Detlefsen
c0dd7e8367 open_ai: Include o3-mini in Model::from_id (#24261) 2025-02-05 16:45:38 -05:00
Marshall Bowers
b7244af093 extensions_ui: Show extension features on cards (#24310)
This PR updates the extensions list to display the features that an
extension provides.

<img width="1309" alt="Screenshot 2025-02-05 at 4 12 07 PM"
src="https://github.com/user-attachments/assets/ff0c61cd-b7fe-49c3-9fc8-a0ab6b0511a6"
/>

Note that this will only show up for extensions that have this data
(which will be extensions published/updated on or after now).

Here's the view with some mocked data:

<img width="1309" alt="Screenshot 2025-02-05 at 4 01 56 PM"
src="https://github.com/user-attachments/assets/d6d6a818-d6ac-4162-9309-95472b17833a"
/>

Release Notes:

- N/A
2025-02-05 21:31:52 +00:00
Max Brunsfeld
ca01a8b9cb Fix two issues with diff highlights (#24309)
* fix syntax highlighting of deleted text when buffer language changes
* do not highlight entire untracked files as created, except in the
project diff view

Release Notes:

- N/A

Co-authored-by: ConradIrwin <conrad.irwin@gmail.com>
Co-authored-by: cole-miller <m@cole-miller.net>
2025-02-05 21:29:39 +00:00
Conrad Irwin
9114ca973c Revert "Revert "Upgrade to rustls v0.23.22" (#24197)" (#24210)
try to reland rustls without breaking linux arm builders

See: 
- #24197
- #24138

Release Notes:

- N/A
2025-02-05 14:24:21 -07:00
renovate[bot]
e506efa9bf Update Rust crate async-trait to v0.1.86 (#24305)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [async-trait](https://redirect.github.com/dtolnay/async-trait) |
workspace.dependencies | patch | `0.1.85` -> `0.1.86` |

---

### Release Notes

<details>
<summary>dtolnay/async-trait (async-trait)</summary>

###
[`v0.1.86`](https://redirect.github.com/dtolnay/async-trait/releases/tag/0.1.86)

[Compare
Source](https://redirect.github.com/dtolnay/async-trait/compare/0.1.85...0.1.86)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 15:53:25 -05:00
renovate[bot]
f0239c0a89 Update actions/setup-node digest to 1d0ff46 (#24304)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | digest | `39370e3` -> `1d0ff46` |

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 15:48:47 -05:00
Max Brunsfeld
b710945949 Fix replication of head text when head matches index (#24306)
Release Notes:

- N/A

---------

Co-authored-by: cole-miller <m@cole-miller.net>
2025-02-05 20:37:32 +00:00
Marshall Bowers
59738f88c2 collab: Store features provided by extensions in the database (#24303)
This PR adds new columns to the `extension_versions` table to record
which features an extension provides.

These `provides_*` columns are populated from the `provides` field on
the extension manifest.

We'll be able to leverage this data in the future for showing what an
extension provides in the extensions UI, as well as allowing to filter
by extensions that provide a certain feature.

Release Notes:

- N/A
2025-02-05 19:50:24 +00:00
Marshall Bowers
2f5abe2b5a panel: Remove unneeded lib.name field in Cargo.toml (#24301)
This PR removes the `name` field from under `lib` in the `Cargo.toml`
file for the `panel` crate, as it isn't necessary.

Also removed it from `script/new-crate`.

Release Notes:

- N/A
2025-02-05 19:30:06 +00:00
Conrad Irwin
44a7614a74 Fix panic when editing diff (#24298)
Release Notes:

- N/A
2025-02-05 12:14:02 -07:00
Conrad Irwin
9369b72475 Delete old project diff code (#24299)
Closes #ISSUE

Co-Authored-By: Mikayla <mikayla@zed.dev>

Release Notes:

- N/A
2025-02-05 12:13:54 -07:00
Conrad Irwin
971a91ced7 Commit All Mode (#24293)
- **Base diffs on uncommitted changes**
- **Show added files in project diff view**
- **Fix git panel optimism**
- **boop**
- **Co-Authored-By: Cole <cole@zed.dev>**
- **Fix commit (all) buttons state**
- **WIP**
- **WIP: commit all mode**

Closes #ISSUE

Release Notes:

- N/A
2025-02-05 12:13:32 -07:00
Nate Butler
6d81ad1e0b git_ui: Start unifying panel style with other panels (#24296)
- Adds the `panel` crate for defining UI shared between panels, like
common button and header designs, etc
- Starts to update the git ui to be more consistent with other panels

Release Notes:

- N/A
2025-02-05 13:54:14 -05:00
Conrad Irwin
70b1e0eec0 Fix expand buttons adjacent to folded hunks (#24297)
Release Notes:

- Fix expand buttons adjacent to folded hunks
2025-02-05 11:48:33 -07:00
Cole Miller
ffe503d77c Fix spurious addition hunks in files with no git repo (#24288)
Release Notes:

- N/A
2025-02-05 13:41:08 -05:00
Marshall Bowers
5a25751521 extension_cli: Include the list of what an extension provides in the generated manifest (#24295)
This PR updates the Zed extension CLI with support for populating the
`provides` field in the generated extension manifest.

This field will contain the set of features that the extension provides.

For example:

```
"provides": ["themes", "icon-themes"]
```

Release Notes:

- N/A
2025-02-05 18:17:19 +00:00
Kirill Bulatov
aaf432fcd2 Revert recent anti-aliasing improvements (#24289)
This reverts commit 31fa414422.
This reverts commit b9e0aae49f.

`lyon` commit revert:

![image](https://github.com/user-attachments/assets/0243f61c-0713-416d-b8db-47372e04abaa)

`MSAA` commit revert:

![image](https://github.com/user-attachments/assets/b1a4a9fe-0192-47ef-be6f-52e03c025724)

cc @huacnlee , @\as-cii had decided to revert this PR due to a selection
right corner rendering bug.
Not sure what to propose for a fix from my side

Release Notes:

- N/A
2025-02-05 17:17:26 +00:00
Bennet Bo Fenner
e1a6d9a485 edit prediction: Improve UX around disabled_globs and show_inline_completions (#24207)
Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-02-05 17:09:19 +00:00
Danilo Leal
37db1dcd48 Revise the MessageNotification component (#24287)
This PR makes adding icons to the primary and secondary actions, in the
`MessageNotification` component, optional. Also took the opportunity to
remove a probably unnecessary "third action" from it; streamlining the
component API (we had added that for a design that we're not using
anymore). I did keep the "more info" possibility, which may be useful in
the future, though.

Release Notes:

- N/A
2025-02-05 13:39:27 -03:00
Danilo Leal
17a7495332 edit prediction: Fix license detection error logging + check for different spellings (#24281)
Follow-up to https://github.com/zed-industries/zed/pull/24278

This PR ensures we're checking if there's a license-type file in both US
& UK English spelling, and fixes the error logging again, treating for
when the worktree contains just a single file or multiple.

Release Notes:

- N/A

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
2025-02-05 13:15:41 -03:00
Cole Miller
6b29616c95 Fix the worktree's repository_for_path (#24279)
Go back to a less optimized implementation for now since the custom
cursor target seems to have some bugs.

Release Notes:

- Fixed missing git blame and status output in some projects with
multiple git repositories
2025-02-05 10:37:51 -05:00
Kirill Bulatov
868e3f75b2 Rework shared commit editors (#24274)
Rework of https://github.com/zed-industries/zed/pull/24130
Uses
1033c0b57e
`COMMIT_EDITMSG` language-related definitions (thanks @d1y )

Instead of using real `.git/COMMIT_EDITMSG` file, create a buffer
without FS representation, stored in the `Repository` and shared the
regular way via the `BufferStore`.
Adds a knowledge of what `Git Commit` language is, and uses it in the
buffers which are rendered in the git panel.


Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad@zed.dev>
Co-authored-by: d1y <chenhonzhou@gmail.com>
Co-authored-by: Smit <smit@zed.dev>
2025-02-05 15:36:24 +00:00
Danilo Leal
da4bad3a55 edit prediction: Don't log an error if license file isn't found (#24278)
Logging an error in this case isn't super necessary.

Release Notes:

- N/A

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
2025-02-05 12:28:44 -03:00
Agus Zubiaga
630d0add19 edit predictions: Onboarding funnel telemetry (#24237)
Release Notes:

- N/A
2025-02-05 15:26:11 +00:00
Marshall Bowers
0a89d1a479 languages: Sort dependencies in Cargo.toml (#24277)
This PR sorts the dependency lists in the `Cargo.toml` for the
`languages` crate.

Release Notes:

- N/A
2025-02-05 15:07:53 +00:00
Peter Tripp
992125bec2 Revert "copilot: Correct o3-mini context length" (#24275)
Reverts zed-industries/zed#24152
See comment: https://github.com/zed-industries/zed/pull/24152#issuecomment-2636808170
Manually confirmed >20k generates error.
2025-02-05 15:03:45 +00:00
张小白
74c4dbd237 windows: Fix tests on Windows (#22616)
Release Notes:

- N/A

---------

Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
2025-02-05 14:30:09 +00:00
Agus Zubiaga
c252b5db16 Accept edit predictions with alt-tab in addition to tab (#24272)
When you have an edit prediction available, you can now also accept it
with `alt-tab` (or `alt-enter` on Linux) even if you don't have an LSP
completions menu open. This is meant to lower the mental load when going
from one mode to another.

Release Notes:

- N/A
2025-02-05 11:06:12 -03:00
Agus Zubiaga
f5e8048fcb edit prediction: Allow enabling OSS data collection with no project open (#24265)
This was an leftover from when we were persisting a per-project setting.

Release Notes:

- N/A
2025-02-05 10:39:20 -03:00
Piotr Osiewicz
88b5f069fb lsp: Add support for default rename behavior in prepareRename request (#24246)
Fixes #24184

Release Notes:

- Fixed renaming not working with some language servers (e.g. hls)
2025-02-05 13:27:57 +01:00
Michael Sloan
fef567bb49 Remove extra space in zed --version string for non-stable (#24254)
Release Notes:

- N/A
2025-02-05 07:25:03 +00:00
Cole Miller
5a955e208c Fix panic when deleting an empty line after a deleted hunk (#24255)
Release Notes:

- Fix a panic when deleting text after a deletion hunk
2025-02-05 07:23:02 +00:00
Conrad Irwin
0963401a8d Git improvements (#24238)
- **Base diffs on uncommitted changes**
- **Show added files in project diff view**
- **Fix git panel optimism**

Release Notes:

- Git: update diffs to be relative to HEAD instead of the index; to pave
the way for showing which hunks are staged

---------

Co-authored-by: Cole <cole@zed.dev>
2025-02-05 06:09:41 +00:00
João Marcos
22b7042b9e Avoid suggesting 'find' key for linux shortcuts (#24252)
this key isn't present in most keyboards, and so, other key combinations
should be preferred over this one

Release Notes:

- N/A
2025-02-05 05:52:25 +00:00
Cole Miller
7c1132ed88 Refactor change sets to store index text in only one place (#24245)
This is a pure refactor that somewhat reduces the amount of code needed
when handling diff base changes. There's also a small performance gain
from reparsing the staged text and computing a new diff in parallel when
we weren't previously.

Release Notes:

- N/A

Co-authored-by: Max <max@zed.dev>
2025-02-04 17:11:01 -08:00
Marshall Bowers
f366b97899 collab: Use billing_customers.has_overdue_invoices to gate subscription access (#24240)
This PR updates the check that prevents subscribing with overdue
subscriptions to use the `billing_customers.has_overdue_invoices` field
instead.

This will allow us to set the value of `has_overdue_invoices` to `false`
when the invoices have been paid.

Release Notes:

- N/A
2025-02-04 18:38:00 -05:00
Marshall Bowers
aa3da35e8e collab: Add has_overdue_invoices to billing_customers (#24239)
This PR adds a new `has_overdue_invoices` field to the
`billing_customers` table.

This will be used to statefully track whether a customer has overdue
invoices, and also to reset it when the invoices are paid.

We will set this field to `true` when a subscription is canceled with
the reason `payment_failed`.

Release Notes:

- N/A
2025-02-04 18:12:35 -05:00
Agus Zubiaga
b13498a5dd edit prediction: Fix jump cursor position when scrolled (#24230)
We were looking up line layouts without subtracting start row so we
would get the wrong one when scrolled

Release Notes:

- N/A
2025-02-04 21:47:34 +00:00
Marshall Bowers
b02baea9d2 zeta: Use DTOs from zed_llm_client crate (#24229)
This PR updates the `zeta` crate to use the predictive edit DTOs defined
in the `zed_llm_client` crate.

This way we aren't duplicating their definitions (and risk them going
out of sync).

Release Notes:

- N/A
2025-02-04 21:39:15 +00:00
Marshall Bowers
d6a2a0b04a zeta: Rename data_collection_permission back to can_collect_data (#24225)
This PR renames some bindings from `data_collection_permission` back to
`can_collect_data`, as the latter name is clearer on account of being a
modal verb.

Release Notes:

- N/A
2025-02-04 21:02:26 +00:00
Agus Zubiaga
58db66ef44 edit prediction: Do not render jump cursor until line layout is ready (#24226)
This is pretty rare but I found a case where `line_layouts` didn't have
the requested line yet, so we now skip rendering the cursor for that
period and avoid panicking.

Release Notes:

- N/A
2025-02-04 17:58:25 -03:00
Max Brunsfeld
6f0f9d631e Allow running cancel-language-server-work action w/o editor focused (#24215)
Release Notes:

- Added the ability to run the `cancel language server work` action
while a panel (like the terminal panel) is focused
2025-02-04 20:49:08 +00:00
Cole Miller
5704b50fb1 git: Compute and synchronize diffs from HEAD (#23626)
This PR builds on #21258 to make it possible to use HEAD as a diff base.
The buffer store is extended to support holding multiple change sets,
and collab gains support for synchronizing the committed text of files
when any collaborator requires it.

Not implemented in this PR:

- Exposing the diff from HEAD to the user
- Decorating the diff from HEAD with information about which hunks are
staged

`test_random_multibuffer` now fails first at `SEED=13277`, similar to
the previous high-water mark, but with various bugs in the multibuffer
logic now shaken out.

Release Notes:

- N/A

---------

Co-authored-by: Max <max@zed.dev>
Co-authored-by: Ben <ben@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
2025-02-04 15:29:10 -05:00
Cole Miller
871f98bc4d Bump openssl to fix vulnerability (#24223)
See: https://github.com/advisories/GHSA-rpmj-rpgj-qmpm

Release Notes:

- N/A
2025-02-04 20:26:06 +00:00
Mikayla Maki
69bb0a0597 Fix slow focus transitions to the terminal panel (#24172)
This long standing bug was caused by `Pane`'s focus_in handler bouncing
the focus to another handle.
Because focus resolution happens _after_ a frame has been rendered, the
only way to deal with this case is to schedule another frame to be
redrawn. However, we where suppressing all window refreshes that occur
during a focus transfer, causing this focus change to be completely
missed. However, changing this behavior can lead to infinite notify
loops, due to drawing a frame causing another to be rendered.

This PR fixes this problem narrowly by adding an `on_next_frame()`
callback in the pane's focus handle, so that the focus changes take
effect almost immediately. But only for this case, where we know it
doesn't cause infinite notify loops.

TODO:
- [x] Fix the infinite notify loop bug or determine a third way to fix
this lag

Release Notes:

- Fixed a bug where shifting focus to the terminal panel could be slow
2025-02-04 20:23:20 +00:00
Mikayla Maki
cfe0932c0a Implement character index for point (#23989)
Fixes #22939
Fixes #23970
Supersedes https://github.com/zed-industries/zed/pull/23469

Release Notes:

- Fixed a bug where Zed could crash with certain input sources on macOS

---------

Co-authored-by: Louis Brunner <louis.brunner.fr@gmail.com>
Co-authored-by: ben <ben@zed.dev>
2025-02-04 20:15:43 +00:00
Henry Chu
7da60995cc Enable CSS, JSON, Python, and Tailwind to lookup LSP installed in PATH (#22037)
Co-authored-by: Peter Tripp <peter@zed.dev>
2025-02-04 14:50:49 -05:00
Peter Tripp
ee422dea6e Bump Zed to v0.174 (#24221) 2025-02-04 14:38:37 -05:00
Michael Sloan
f8c436fe7f Fix prediction preview binding: Alt + Preview -> Alt Preview (#24220)
Release Notes:

- N/A
2025-02-04 19:32:30 +00:00
Michael Sloan
b5d4b17f60 Fix showing "enter Accept" for prediction with LSP menu open (#24218)
Release Notes:

- N/A
2025-02-04 19:15:14 +00:00
Kirill Bulatov
3e68f7fde4 Revert "Skip COMMIT_EDITMSG contents when opening the file (#24146)" (#24216) 2025-02-04 21:05:10 +02:00
Mikayla Maki
e768eb0a34 Replace Window::parent_view_id() with Window::current_view() (#24212)
Chatted with @as-cii about limitations in the `Window::parent_view_id()`
API (see:
662153dcfd)
and realized that I shouldn't be using the dispatch tree's data
structures as they are layout dependent. I've introduced a new stack to
`Window`, `rendered_entity_stack`, that tracks exactly which view's
elements are being drawn. As such, I've also been able to remove the
`Option<>` around the previous API.

Release Notes:

- N/A
2025-02-04 18:50:21 +00:00
Richard Feldman
667396c44b Use the term "edit prediction" over "inline completion" (#24211)
Note that this does *not* involve any breaking code changes.

cc @0xtimsb - I didn't change any settings or anything here. That can
happen separately!

Release Notes:

- N/A
2025-02-04 10:33:01 -08:00
Antonio Scandurra
c64b26110c Revert "edit prediction: Try to expand context to parent treesitter region" (#24214)
Reverts zed-industries/zed#24186
2025-02-04 18:32:17 +00:00
Anthony Eid
8c7096f7a6 Rename model based variable names to entity (#24198)
## Context
While looking through the client crate, I noticed that some of the old
functions and variables were still using gpui::model name that was
deprecated during the gpui3 transition. This PR renames those instances
of model to entity to be more inline with gpui3.

In addition, I also renamed `model` to `entity` in cases found by the
below search terms given by @someone13574

- model = cx.
- model: Entity
- model: &Entity
- OpenedModelHandle
- model.update
- model.upgrade
- model = .*\.root (regex)
- parent_model
- model = cx.new
- cx.spawn(move |model

Release Notes:

- N/A
2025-02-04 10:24:35 -08:00
Max Brunsfeld
27d1c689cf Avoid subtraction overflow when excerpt primary is outside of excerpt… (#24213)
This fixes a "subtract with overflow" error that could happen in debug
mode when viewing the project diagnostics.

From git bisecting, I think that this behavior was introduced by
https://github.com/zed-industries/zed/pull/21942. It seems like it's
possible in some cases for the excerpt-expansion heuristic to cause the
excerpt's `context` range to start *after* the excerpt's `primary`
range. We should probably revisit that heuristic at some point, but it
also seems reasonable to handle that situation at this layer, rather
than overflowing.

Release Notes:

- N/A
2025-02-04 18:24:05 +00:00
Mikayla Maki
4ab4e87266 Fix a bug in GPUI, where AsyncApp::update wouldn't kick off a flush effects loop (#24208)
Release Notes:

- N/A
2025-02-04 10:00:11 -08:00
Agus Zubiaga
4f98157e64 edit predictions: Make Zed bar at least as wide as menu (#24206)
Release Notes:

- N/A

---------

Co-authored-by: Ben <ben@zed.dev>
2025-02-04 17:45:45 +00:00
Agus Zubiaga
9b031d747f edit prediction: Use thin cursor for jump preview and gradients instead of ellipsis (#24202)
https://github.com/user-attachments/assets/06e14893-c285-4cea-927c-75e82a378b15

Release Notes:

- N/A

---------

Co-authored-by: Ben <ben@zed.dev>
2025-02-04 14:25:18 -03:00
Antonio Scandurra
aea36f0eff Prevent requesting more than 3 edit predictions per second (#24203)
Release Notes:

- N/A

Co-authored-by: Marshall <marshall@zed.dev>
2025-02-04 18:07:24 +01:00
Bennet Bo Fenner
cae712e740 edit prediction: Try to expand context to parent treesitter region (#24186)
Also send the `speculated_output` (which is just the editable region) to
the llm backend

Closes #ISSUE

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2025-02-04 18:03:26 +01:00
张小白
bce9a9a6f4 windows: Use setup-dev-driver.ps1 to create dev driver (#24196)
Closes #ISSUE

Release Notes:

- N/A
2025-02-05 00:10:24 +08:00
Peter Tripp
c50cb90d6f Revert "Upgrade to rustls v0.23.22" (#24197)
Reverts zed-industries/zed#24138

Nightly build failed, I believe because of this.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189


![image](https://github.com/user-attachments/assets/8121dfb7-4ae7-4efb-8625-f07967640620)

CC: @ConradIrwin 

Release Notes:

- N/A
2025-02-04 10:20:07 -05:00
Nate Butler
a0269aba77 theme_selector: Add a button to open the extension store (#24195)
Adds a button to the theme selector to help people find more themes in
the extension store.

![CleanShot 2025-02-04 at 09 00
20@2x](https://github.com/user-attachments/assets/fd430ff5-b0e3-4be0-ac4a-eeaf0093089b)

Release Notes:

- Added a way to access the extension store from the theme selector to
make it easier to find new themes.
2025-02-04 14:13:24 +00:00
Angelk90
88b485f5cc Update license year (#24191) 2025-02-04 09:02:59 -05:00
Jacob Chapel
28536498c9 copilot: Correct o3-mini context length (#24152)
It should be 200k (with 100k output). I can't find anything that puts it
at 20k and the changeover in
2f82374926
only changed the name from o1-mini to o3-mini

References:
*
https://docs.github.com/en/copilot/using-github-copilot/asking-github-copilot-questions-in-github#ai-models-for-copilot-chat
* https://github.com/marketplace/models/azure-openai/o3-mini
* https://platform.openai.com/docs/models#o3-mini

Release Notes:

- Corrected Github Copilot o3-mini context length

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-04 09:01:36 -05:00
Bennet Bo Fenner
cc2ebb96a6 Revert "inline completion: Respect disabled_globs when manually requesting completions (#24121)" (#24189)
This reverts commit eb820ab800.
The previous PR broke manual completions. Turns out there is more
confusing behavior then i realized, will follow up with another PR soon.

Closes #ISSUE

Release Notes:

- N/A
2025-02-04 13:02:45 +00:00
Mikayla Maki
d400bdea76 Add example compilation to CI (#24182)
Stop https://github.com/zed-industries/zed/pull/24165 from happening

Release Notes:

- N/A
2025-02-04 09:48:54 +00:00
Mikayla Maki
71f2cbe798 Git Panel: separate new and changed (#24181)
Release Notes:

- N/A

---------

Co-authored-by: conrad <conrad@zed.dev>
Co-authored-by: nate <nate@zed.dev>
2025-02-04 09:15:09 +00:00
Kirill Bulatov
6659aea13b Disallow multiple quit confirmations (#24180)
Closes https://github.com/zed-industries/zed/issues/10192 , again.

Release Notes:

- Fixed multiple save modals appearing when app is being closed multiple
times
2025-02-04 09:09:46 +00:00
Danilo Leal
386cfacb25 zeta: Fix data collection display on the status bar menu (#24177)
Follow-up to: https://github.com/zed-industries/zed/pull/24031

This PR adds a new function that allows the UI also to display the state
of the data collection. Previously, we only showed that if the project
adhered to the `is_open_source` condition. Now, we show it for all
projects.

Release Notes:

- N/A
2025-02-04 08:05:28 +00:00
Danilo Leal
e5c3273486 status_bar: Only show divider for left dock (#24178)
Follow up to https://github.com/zed-industries/zed/pull/24114

Just fixing the UI so that the divider only shows for the
left-positioned items.

Release Notes:

- N/A
2025-02-04 08:02:29 +00:00
Michael Sloan
556b0eb4f1 Show larger jump target preview + add ellipsii to indicate truncation (#24179)
Release Notes:

- N/A
2025-02-04 08:00:48 +00:00
Agus Zubiaga
93f8ccaaee zeta: Revised data-collection onboarding experience (#24031)
Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: João Marcos <marcospb19@hotmail.com>
2025-02-04 04:06:09 -03:00
Michael Sloan
29e559d60c Fix display of + between modifiers on linux and windows (#24173)
Regressions in #24024:

* `+` was no longer included between modifiers and key
* Multi-character keys like "control" were displayed all lowercase,
whereas before they were all uppercase like "CONTROL". Now they are
capitalized, so "Control".
* Brings back icon for tab key.

Release Notes:

- N/A
2025-02-04 07:03:35 +00:00
Conrad Irwin
9a22ef2fd5 Don't save deleted files (#24171)
We now treat new files that have no content as not-dirty. This fixes the
git diff view when deleted files are present.

It also fixes a long-standing bug where `zed RAEDME` and then closing
the tab would prompt for "unsaved changes" when there were none.

Release Notes:

- Fixed a bug where closing an empty, named, file would warn about
unsaved content.
2025-02-03 23:31:34 -07:00
Michael Sloan
66e0898425 Fix corner case where edit prediction preview and docs aside overlap (#24170)
+ add docs and simplify logic around popover order

Release Notes:

- N/A
2025-02-04 06:05:36 +00:00
Conrad Irwin
cf4539ec79 Handle empty diff excerpts (#24168)
Release Notes:

- Fix display, revert and undo of deleted hunks when the file is empty.
2025-02-03 22:55:11 -07:00
Nathan Sobo
8bce896395 Invalidate GPUI views regardless of draw phase (#24164)
We think this could fix issues around view invalidation during focus
handling.

I want to run CI on this and see.

cc @mikayla-maki @maxbrunsfeld 

Release Notes:

- N/A
2025-02-03 21:44:07 -08:00
Kirill Bulatov
ea66a54cf8 Skip COMMIT_EDITMSG contents when opening the file (#24146) 2025-02-04 07:23:14 +02:00
Conrad Irwin
225f0c4d12 Fix input example (#24165)
Release Notes:

- N/A
2025-02-03 22:09:45 -07:00
Ben Kunkle
daf09fa532 Fix issue where changing the case of a vim object would be clipped at the end of the line (#24163)
Co-authored-by: Conrad Irwin <conrad@zed.dev>

Closes #24124

Release Notes:

- Fixed an issue in vim mode where changing the case of an object at the
end of the line would not change the case of the last character in the
object

Co-authored-by: Conrad Irwin <conrad@zed.dev>
2025-02-04 03:40:45 +00:00
Ben Kunkle
8742c18107 Allow auto-indenting with syntax errors when using regex-based indent matches to improve bash auto-indent behavior (#24160)
- Fixes auto-indent issues around `elif` caused by auto-indent being prevented due to syntax errors generated before `elif` clause completed

Release Notes:

- Fixed an issue where inserting an elif before an else in bash would
not properly auto-indent

---------

Co-authored-by: Conrad Irwin <conrad@zed.dev>
2025-02-03 21:34:37 -06:00
Conrad Irwin
66d0cdfd91 vim: Add ctrl-w a (#24162)
Closes #ISSUE

Release Notes:

- vim: Add `ctrl-w a` to close all items in the current pane
2025-02-04 03:26:37 +00:00
Conrad Irwin
e17f307189 vim: Load keymap after base keymap (#24161)
Closes #22562

Release Notes:

- vim: Load vim keymap after a user-configured keymap
2025-02-04 03:25:20 +00:00
Saurabh
3d3ac2c470 vim: Fix ctrl-w ctrl-q and ctrl-w ctrl-c to close active pane instead of all panes (#24018)
According to vim `ctrl-w ctrl-q` should close the active tab or pane
similar to :q


![Screenshot_20250131_163139](https://github.com/user-attachments/assets/c6a0d3a0-8dcf-4152-b2bf-835472d4f870)

Release Notes:

- vim: fix `ctrl-w ctrl-q` to close active pane instead of all panes
2025-02-03 20:10:03 -07:00
Piotr Osiewicz
0919f10037 chore: Remove moot file from #23901 (#24159)
Closes #ISSUE

Release Notes:

- N/A
2025-02-04 01:34:10 +00:00
Piotr Osiewicz
2442c49048 ci: Use ReFS for our Windows CI (#23901)
Based on uv's CI setup.

Closes #ISSUE

Release Notes:

- N/A
2025-02-04 00:49:31 +00:00
Agus Zubiaga
4c29e1ff07 zeta: Improve UX for simultaneous LSP and prediction completions (#24024)
Release Notes:

- N/A

---------

Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: Richard <richard@zed.dev>
2025-02-03 21:47:11 -03:00
Ben Kunkle
b6e680ea3d Support bash autoindenting (#24156)
Creates an indents.scm file for bash and adds regexes for
`{increase,decrease}_indent_pattern` in
`crates/languages/src/bash/config.toml`
so that autoindent works as expected in bash

Note that this PR does not attempt to handle all cases where indenting
might be desired in bash. I am aiming to support ~80% of what people
want while avoiding the more gnarly/edge cases like indented blocks in
case statements and indenting for associative arrays.
This is done with the explicit hope that someone (possibly from the
community) more familiar with and passionate about bash can come through
at a later date and handle those cases

Closes #23628

Release Notes:

- Add basic support for autoindent functionality in bash/shell files
2025-02-04 00:37:52 +00:00
Marshall Bowers
dfd11c3d3b docs: Add docs for icon theme extensions (#24155)
This PR adds docs for icon themes.

Release Notes:

- N/A
2025-02-04 00:23:33 +00:00
Michael Sloan
28b80455f9 Fix missing modifier changed events on Linux X11 (#24154)
Release Notes:

- Fixed some modifier changed events not being present on Linux X11.
This affected things like the project search palette, where holding ctrl
would not cause the split options to appear.
2025-02-04 00:12:24 +00:00
Max Brunsfeld
13b7be12bd themes: Make background colors partly transparent by default (#24151)
Certain themes define the `created` and `deleted` status colors, but not
`created_background` and `deleted_background`. Previously, Zed would use
`created` and `deleted` colors, and apply a hard-coded opacity change,
but *not* use `created_background` and `deleted_background`, but that
behavior was inadvertently changed in
https://github.com/zed-industries/zed/pull/22994.

This PR restores the old behavior as a fallback. If a theme defines a
status color, but not the corresponding background color, we'll use a
75% transparent version of the foreground color as a fallback.

Release Notes:

- Fixed an issue in certain themes where diffs would render with the
wrong red and green colors for deletions and insertions.
2025-02-03 22:38:14 +00:00
Marshall Bowers
e2d6d4bcb2 docs: Update link to Scheme extension (#24148)
This PR updates the link to the Scheme extension in the docs, as it was
moved to a separate repo in #24078.

Release Notes:

- N/A
2025-02-03 22:01:16 +00:00
Kirill Bulatov
1ec91a8738 Clip points when searching for @ in the Assistant 2 panel (#24147)
Release Notes:

- N/A
2025-02-03 21:42:13 +00:00
Joseph T. Lyons
11e095b56a Fix editor edited event property field name (#24145)
Release Notes:

- N/A
2025-02-03 21:28:14 +00:00
Conrad Irwin
45708d2680 Project Diff 2 (#23891)
This adds a new version of the project diff editor to go alongside the
new git panel.

The basics seem to be working, but still todo:

* [ ] Fix untracked files
* [ ] Fix deleted files
* [ ] Show commit message editor at top
* [x] Handle empty state
* [x] Fix panic where locator sometimes seeks to wrong excerpt

Release Notes:

- N/A
2025-02-03 13:18:50 -07:00
Conrad Irwin
27a413a5e3 linux: Remove openssl dependency (#24141)
Release Notes:

- linux: Move from using openssl for collaboration to rustls/ring
2025-02-03 13:01:44 -07:00
Peter Tripp
a47a7fb6a9 Reformat Zed Terms of Use with Prettier (no changes) (#24143)
No-op white-space only change.
Converts two spaces after periods to one space.
Enables using Prettier going forward.
2025-02-03 14:57:55 -05:00
Conrad Irwin
4f63423d56 Upgrade to rustls v0.23.22 (#24138)
This will help us debug a panic we're seeing in their internals.

In order to make this work, I've temporarily forked async-tls with:
https://github.com/async-rs/async-tls/pull/59/files

Closes #ISSUE

Release Notes:

- N/A
2025-02-03 12:31:42 -07:00
Joseph T. Lyons
a8741dc310 Migrate more events to telemetry::event! macro (#24102)
I believe this takes care of the remaining events running through the
old flow that requires transformation at the collab server level. I
think all events are now going through `telemetry::event!()`.

For anyone curious where the new telemetry names are coming from, you
can check the `for_snowflake` function within
`crates/collab/src/api/events.rs`, to see how collab is currently
transforming the events going through the old flow.

Release Notes:

- N/A
2025-02-03 16:38:45 +00:00
Kirill Bulatov
a864168c27 Enable collaborating editing of the commit message input inside the git panel (#24130)
https://github.com/user-attachments/assets/200b88b8-249a-4841-97cd-fda8365efd00

Now all users in the collab/ssh session can edit the commit input
collaboratively, observing each others' changes live.

A real `.git/COMMIT_EDITMSG` file is opened, which automatically enables
its syntax highlight, but its original context is never used or saved on
disk — this way we avoid stale commit messages from previous commits
that git places there.

A caveat: previous version put some effort into preserving unfinished
commit messages on repo swtiches, but this version would not do that
— instead, it will be blank on startup, and use whatever
`.git/COMMIT_EDITMSG` contents on repo switch

Release Notes:

- N/A

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-02-03 18:11:13 +02:00
Piotr Osiewicz
6b48a6e690 workspace: Respect minimized state when deserializing workspaces (#24127)
Fixes a regression from #24015 pointed out in #24093

Closes #24093

Release Notes:

- N/A
2025-02-03 12:35:16 +00:00
Christian Borup
f45d58f01a Add support for Go fuzz tests (#24107)
Add support for go fuzz tests.

Closes #23809

Release Notes:

- N/A

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2025-02-03 11:33:58 +01:00
Bennet Bo Fenner
8edcaec1bf inline completion: Merge disabled_globs setting with default values (#24122)
This ensures that the following files are always ignored:

```
"**/.env*"
"**/*.pem"
"**/*.key"
"**/*.cert"
"**/*.crt"
"**/secrets.yml"
```

Release Notes:

- N/A
2025-02-03 09:37:46 +00:00
Bennet Bo Fenner
eb820ab800 inline completion: Respect disabled_globs when manually requesting completions (#24121)
When requesting completions manually with `editor: Show inline
completion`, we did not check if completions are actually disabled for
the current file (`inline_completions > disabled_globs`)

Release Notes:

- Fixed an issue where the `inline_completions > disabled_globs` setting
would not be respected when manually requesting a completion (`editor:
Show inline completion`)
2025-02-03 08:54:24 +00:00
João Marcos
08c834ced0 cli: Instruct in --help how to run to see all logs (#24112)
Release Notes:

- N/A
2025-02-03 04:46:49 -03:00
Michael Sloan
52aed4849a Use prettier to fix formatting in docs/src/languages/lua.md + fix typo (#24118)
Release Notes:

- N/A
2025-02-03 04:58:33 +00:00
Kevin Sweet
f14ef40a13 Conditionally render divider between button groups in the status bar (#24114)
In the left hand status bar, there are two groups of buttons. There was
a border between the two hardcoded on the first button of the second
group, however, if all buttons in the first group are hidden, the border
doesn't need to be rendered.

(Not handled in this PR) A potentially better approach would be to
change StatusBar's definition from `left_items` and `right_items` to
`left_groups` and `right_groups`, and render dividers between each group
of items. That seemed like a bigger refactor than I wanted to handle for
now, but is an option for the future.

If you use these settings on `main`, the border will show, but with
nothing to the left of it.

```json
{
  "collaboration_panel": {
    "button": false
  },
  "outline_panel": {
    "button": false
  },
  "project_panel": {
    "button": false,
  },
}
```

Screenshots:

Before:
<img width="117" alt="Screenshot 2025-02-02 at 6 19 24 PM"
src="https://github.com/user-attachments/assets/b3401b47-6172-4392-9277-31aa1affaf7a"
/>
<img width="134" alt="Screenshot 2025-02-02 at 6 20 12 PM"
src="https://github.com/user-attachments/assets/1e8caee6-1da8-47f6-8499-9a93b6d8fa27"
/>

After:
<img width="125" alt="Screenshot 2025-02-02 at 6 19 58 PM"
src="https://github.com/user-attachments/assets/9b9f421c-660b-41cb-80e0-acb774c66054"
/>
<img width="132" alt="Screenshot 2025-02-02 at 6 20 20 PM"
src="https://github.com/user-attachments/assets/87e0e475-084b-44df-b820-573c68728c1a"
/>

Release Notes:

- Conditionally render divider in status bar

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2025-02-03 04:13:40 +00:00
Billy
1d3e9b22b0 docs: Update completion keybindings and fix typos (#24113)
Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2025-02-03 04:06:07 +00:00
Michael Sloan
1301c41cea Add direnv .envrc to .gitignore (#24115)
Release Notes:

- N/A
2025-02-03 02:22:07 +00:00
Peter Tripp
1dd2bbe2ba docs: Add lua-language-server formatter example (#24105) 2025-02-02 20:15:50 +00:00
Piotr Osiewicz
4885ace107 workspace: Prevent clicks from falling through on some notifications (#24104)
Closes #ISSUE

Release Notes:

- N/A
2025-02-02 19:39:13 +00:00
Michael Sloan
691de6b4b3 Add #[track_caller] to gpui foreground executor spawn methods (#24103)
Use of this location info was added in #21758 to help with diagnosing
remote_server panics on drop of tasks on a different thread.

Release Notes:

- N/A
2025-02-02 19:20:17 +00:00
Peter Tripp
422d57e8a2 docs: Add Lua formatters section (stylua) (#24101) 2025-02-02 18:56:44 +00:00
someone13574
aa42e206b3 gpui: Add text alignment (#24090)
Adds a text property for controlling left, center, or right text
alignment.

#8792 should stay open since this doesn't add support for `justify`
(which would require a much bigger change since this can just alter the
origin of each line, but justify requires changing spacing, whereas
justify requires changes to each platform's shaping code).

Release Notes:

- N/A
2025-02-02 09:15:12 -08:00
someone13574
4a65315f3b gpui: Switch from linkme to inventory for action registration (#24087)
This switches how actions are registered in GPUI from
[dtolnay/linkme](https://github.com/dtolnay/linkme) to
[dtolany/inventory](https://github.com/dtolnay/inventory), fixing the
linking error seen in #15902, which also occurs on nightly toolchains.
I'm not sure if that issue should be closed or not given the other
problems on Chimera though.

This also fixes zed-industries/create-gpui-app#10

Release Notes:

- N/A
2025-02-02 09:13:46 -08:00
Kirill Bulatov
f4f51c198c Remove /workflow command as not existing anymore #2 (#24097)
Follow-up of https://github.com/zed-industries/zed/pull/24095

Release Notes:

- N/A
2025-02-02 15:20:01 +00:00
Kirill Bulatov
f7d2b5300c Remove /workflow command as not existing anymore (#24095)
Based on
https://github.com/zed-industries/zed/issues/16913#issuecomment-2629424808
Follow-up of https://github.com/zed-industries/zed/pull/19900

Release Notes:

- N/A
2025-02-02 15:05:57 +00:00
Peter Tripp
2f82374926 Switch GitHub Copilot Chat from o1-mini to o3-mini (#24080)
Co-authored-by: SkywardSyntax <87048477+SkywardSyntax@users.noreply.github.com>
2025-02-01 12:49:24 -05:00
Roshan Padaki
af461f8165 assistant: Use GPT 4 tokenizer for o3-mini (#24068)
Sorry to dump an unsolicited PR for a hot feature! I'm sure someone else
was taking a look at this.

I noticed that token counting was disabled and I was getting error logs
of the form `[2025-01-31T22:59:01-05:00 ERROR assistant_context_editor]
No tokenizer found for model o3-mini` when using the new model. To fix
the issue, this PR registers the `gpt-4` tokenizer for this model.

Release Notes:

- openai: Fixed Assistant token counts for `o3-mini` models
2025-02-01 12:08:44 -05:00
Peter Tripp
f6824e3eaa Move scheme extension to zed-extensions/scheme (#24078)
New home: https://github.com/zed-extensions/scheme

- See also: https://github.com/zed-industries/extensions/pull/1981
2025-02-01 11:50:20 -05:00
João Marcos
5bd7eaa173 Solve 50+ cargo doc warnings (#24071)
Release Notes:

- N/A
2025-02-01 06:19:29 +00:00
João Marcos
39d45bcbc1 Update docs for running collab locally (again) (#24069)
Release Notes:

- N/A
2025-02-01 04:57:44 +00:00
AidanV
d0152f9eb4 vim: Add keybindings for resizing docks (#23874)
Closes #23334

This does not follow the exact way that windows are resized in vim.
Normally the command is `ctrl-w >` however this PR uses just `ctrl->`.
This is because I could not find a good way to read in a count like `10
ctrl-w ctrl->`. This is not really a problem since `ctrl->` can be held
down, which, in my opinion, speeds up resizing. I think this is a good
compromise since it improves usability; however, I am concerned that
this is not intuitive. I am looking forward to feedback.

Release Notes:

- Added the following commands 
  - vim::ResizeLeftDock
  - vim::ResizeRightDock
  - vim::ResizeBottomDock
- Added keybinds
  - `ctrl->` for widening left dock
  - `ctrl-<` for narrowing left dock
2025-01-31 21:50:16 -07:00
Conrad Irwin
a3c7dc3321 vim: Add textobject e for entire file (#24039)
Co-Authored-By: Thomas Heartman <zed@thomasheartman.com>

Release Notes:

- vim: Add `e` for entire file object. `yae` to copy entire file

Co-authored-by: Thomas Heartman <zed@thomasheartman.com>
2025-01-31 21:38:19 -07:00
Nate Butler
66e2028313 git_ui: More git panel refinement (#24065)
- Removes flakey keybindings from buttons
- Moves git panel entries to use a standard ListItem
- Show a repo selector in the panel when more than one repo is present
- Remove temporary repo selector from title bar

Release Notes:

- N/A
2025-02-01 03:32:41 +00:00
Marshall Bowers
52a3013d73 editor: Push em width calculations down into EditorSnapshot::gutter_dimensions (#24062)
This PR removes the `em_width` and `em_advance` parameters to
`EditorSnapshot::gutter_dimensions` in favor of computing the values
inside of it.

In practice all of the callers were passing in the same values, and
there isn't a circumstance where we would want to pass in different
values.

`gutter_dimensions` has also been modified to return
`Option<GutterDimensions>` instead of `GutterDimensions` so that we can
remove some `.unwrap`s when interacting with the text system.

Release Notes:

- N/A
2025-02-01 00:10:42 +00:00
Michael Sloan
17872260e6 Add language::BufferSnapshot::highlighted_text_for_range (#24060)
In support of work on

https://github.com/zed-industries/zed/tree/new-ui-for-edit-prediction-with-lsp-completions,
where we want to be able to extract a range of the buffer as
`HighlightedText`.

Release Notes:

- N/A
2025-01-31 23:36:24 +00:00
Kirill Bulatov
9a6b9e3124 Use different commit author for collab project clients (#24058)
Follow-up of https://github.com/zed-industries/zed/pull/23869

* Retrieves user + email for collab project clients and use these when
such users commit

Same as in https://github.com/zed-industries/zed/pull/23329, "is it the
right user name and e-mail" and "how to override these" questions apply.

* If this data is unavailable, forbid committing to the remote client

* Forbid running related actions in git panel, if committing/writing is
not permitted


Release Notes:

- N/A
2025-01-31 23:25:58 +00:00
Michael Sloan
93c7b54caa Renames: HighlightedText->HighlightedMatch + HighlightedEdits->HighlightedText (#24057)
In support of work on
https://github.com/zed-industries/zed/tree/new-ui-for-edit-prediction-with-lsp-completions,
where we want to be able to extract a range of the buffer as
`HighlightedText`.

Release Notes:

- N/A
2025-01-31 23:15:46 +00:00
Marshall Bowers
4d9659adc4 feature_flags: Add FeatureFlagAppExt::wait_for_flag_or_timeout (#24055)
This PR adds a new `wait_for_flag_or_timeout` method to the
`FeatureFlagAppExt` trait.

This encapsulates the somewhat gnarly code for using `wait_for_flag`
with a timeout.

A side benefit of this is that the tasks waiting on the feature flags
run in parallel, so in the case where the feature flags do not resolve
we don't end up having to wait on consecutive timeouts. This should help
a bit with https://github.com/zed-industries/zed/issues/23922.

Release Notes:

- N/A
2025-01-31 22:35:23 +00:00
Peter Tripp
3af37ddf6d lmstudio: Support missing quantization in model metadata (#24054)
- Closes https://github.com/zed-industries/zed/issues/23764

Certain models do not include `quantization` parameter from lm studio rest API.
2025-01-31 22:28:11 +00:00
Peter Tripp
df16ef209c chore: Fix default.json formatting (#24053)
Forgot to run default.json through prettier in #24051. Oops.
2025-01-31 22:20:51 +00:00
Marshall Bowers
1e96663e20 assistant_context_editor: Don't block ContextStore initialization on reloading contexts (#24052)
This PR changes the `ContextStore` constructor to not block on reloading
the contexts before we finish initializing it.

I noticed that the Assistant panel was taking a long time to show up in
the status bar, and upon further investigation uncovered that with a
large number of contexts (I have ~320) it takes a long time to load them
all.

Release Notes:

- N/A
2025-01-31 17:08:33 -05:00
Peter Tripp
de3702bedc Improve inline_completions.disabled_globs in default.json (#24051)
Make sure that inline completions (Copilot, etc) are disabled for more secret globs (matches `private_files`)
2025-01-31 16:57:54 -05:00
Peter Tripp
d04800c329 Add OpenAI o3-mini support (#24044)
Release Notes:

- Add support for OpenAI o3-mini
2025-01-31 15:48:55 -05:00
Kirill Bulatov
e42b6e6905 Do less git metadata rescans on FS events (#24034)
A preparation for collaborative commit message editing.

Before, almost any `.git`-contained file FS update, except
`.git/fsmonitor--daemon/cookies/**` caused git metadata rescan.
This included `index.lock` that was created after any git operation,
e.g. `git status`, which was unnecessary.
Collaborative editing aims to share `.git/COMMIT_EDITMSG` between
multiple users, so there are potentially multiple users editing the file
and causing excessive events.

The change makes worktree to ignore .git/COMMIT_EDITMSG`,
`.git/index.lock` and `.git/fsmonitor--daemon/**` paths and adjusts the
logic to be more extensible: there's much more files Zed can ignore and
still have its git metadata up to date.

Release Notes:

- N/A
2025-01-31 20:17:57 +00:00
someone13574
0c94bdc8e4 gpui: Update docs to reflect removal of View, ViewContext, WindowContext (#24008)
This PR updates function signatures, docstrings, and gpui's other
documentation to reflect it's new state following the merge of `Model`
and `View` into `Entity` as well as the removal of `WindowContext`.

Release Notes:

- N/A
2025-01-31 11:40:42 -08:00
Ben Kunkle
027fe1b4b5 Ensure pane where search buttons are clicked is focused before dispatching action (#24037)
Closes #23906

Note: Changes the focused pane when search UI is interacted with on an
unfocused pane rather than leaving the focused pane unchanged as
focusing on click is more likely to be the expected behavior

Release Notes:

- Fixes an issue with search actions so that they now execute on the
clicked pane rather than the focused pane when using search UI in
multiple panes
2025-01-31 13:03:11 -06:00
Marshall Bowers
990bdde5e8 gpui: Add helper methods for em width and em advance (#24036)
This PR adds two helpers methods to the `TextSystem`:

- `em_width`
- `em_advance`

These methods return the width and advance width for an `em`,
respectively.

We were using these definitions in a number of different spots, and by
unifying them we better canonicalize that an `em` is based on the `m`
character.

Release Notes:

- N/A
2025-01-31 17:47:44 +00:00
Marshall Bowers
af6548c745 docs: Remove lingering docs for default_dock_anchor (#24029)
This PR removes some lingering docs leftover after `default_dock_anchor`
was removed.

These were missed in https://github.com/zed-industries/zed/pull/18210.

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

Release Notes:

- N/A
2025-01-31 14:34:13 +00:00
552 changed files with 28689 additions and 15465 deletions

View File

@@ -0,0 +1,26 @@
name: "Run tests on Windows"
description: "Runs the tests on Windows"
inputs:
working-directory:
description: "The working directory"
required: true
default: "."
runs:
using: "composite"
steps:
- name: Install Rust
shell: pwsh
working-directory: ${{ inputs.working-directory }}
run: cargo install cargo-nextest --locked
- name: Install Node
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
with:
node-version: "18"
- name: Run tests
shell: pwsh
working-directory: ${{ inputs.working-directory }}
run: cargo nextest run --workspace --no-fail-fast

View File

@@ -135,6 +135,7 @@ jobs:
cargo check -p gpui --features "macos-blade"
cargo check -p workspace
cargo build -p remote_server
cargo check -p gpui --examples
script/check-rust-livekit-macos
# Since the macOS runners are stateful, so we need to remove the config file to prevent potential bug.
@@ -181,6 +182,7 @@ jobs:
run: |
cargo build -p zed
cargo check -p workspace
cargo check -p gpui --examples
# Even the Linux runner is not stateful, in theory there is no need to do this cleanup.
# But, to avoid potential issues in the future if we choose to use a stateful Linux runner and forget to add code
@@ -226,7 +228,6 @@ jobs:
if: always()
run: rm -rf ./../.cargo
# todo(windows): Actually run the tests
windows_tests:
timeout-minutes: 60
name: (Windows) Run Clippy and tests
@@ -236,33 +237,55 @@ jobs:
# more info here:- https://github.com/rust-lang/cargo/issues/13020
- name: Enable longer pathnames for git
run: git config --system core.longpaths true
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
clean: false
- name: Create Dev Drive using ReFS
run: ./script/setup-dev-driver.ps1
# actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
- name: Copy Git Repo to Dev Drive
run: |
Copy-Item -Path "${{ github.workspace }}" -Destination "${{ env.ZED_WORKSPACE }}" -Recurse
- name: Cache dependencies
uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
workspaces: ${{ env.ZED_WORKSPACE }}
cache-provider: "github"
- name: Configure CI
run: |
mkdir -p ./../.cargo
cp ./.cargo/ci-config.toml ./../.cargo/config.toml
mkdir -p ${{ env.CARGO_HOME }} -ErrorAction Ignore
cp ./.cargo/ci-config.toml ${{ env.CARGO_HOME }}/config.toml
- name: cargo clippy
working-directory: ${{ env.ZED_WORKSPACE }}
# Windows can't run shell scripts, so we need to use `cargo xtask`.
run: cargo xtask clippy
- name: Run tests
uses: ./.github/actions/run_tests_windows
with:
working-directory: ${{ env.ZED_WORKSPACE }}
- name: Build Zed
working-directory: ${{ env.ZED_WORKSPACE }}
run: cargo build
- name: Check dev drive space
working-directory: ${{ env.ZED_WORKSPACE }}
# `setup-dev-driver.ps1` creates a 100GB drive, with CI taking up ~45GB of the drive.
run: ./script/exit-ci-if-dev-drive-is-full.ps1 95
# Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
- name: Clean CI config file
if: always()
run: Remove-Item -Path "./../.cargo" -Recurse -Force
run: Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml" -Force
bundle-mac:
timeout-minutes: 120

View File

@@ -37,29 +37,36 @@ jobs:
mdbook build ./docs --dest-dir=../target/deploy/docs/
- name: Deploy Docs
uses: cloudflare/wrangler-action@7a5f8bbdfeedcde38e6777a50fe685f89259d4ca # v3
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # 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@7a5f8bbdfeedcde38e6777a50fe685f89259d4ca # v3
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # 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@7a5f8bbdfeedcde38e6777a50fe685f89259d4ca # v3
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # 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@7a5f8bbdfeedcde38e6777a50fe685f89259d4ca # v3
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy .cloudflare/docs-proxy/src/worker.js
- name: Preserve Wrangler logs
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
if: always()
with:
name: wrangler_logs
path: /home/runner/.config/.wrangler/logs/

View File

@@ -24,11 +24,13 @@ jobs:
- name: Prettier Check on /docs
working-directory: ./docs
run: |
pnpm dlx prettier . --check || {
pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
echo "To fix, run from the root of the zed repo:"
echo " cd docs && pnpm dlx prettier . --write && cd .."
echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
false
}
env:
PRETTIER_VERSION: 3.5.0
- name: Check for Typos with Typos-CLI
uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6

46
.gitignore vendored
View File

@@ -1,35 +1,35 @@
/.direnv
.envrc
.idea
**/target
**/*.db
**/cargo-target
/zed.xcworkspace
.DS_Store
/plugins/bin
/script/node_modules
/crates/theme/schemas/theme.json
/crates/collab/seed.json
/crates/zed/resources/flatpak/flatpak-cargo-sources.json
/dev.zed.Zed*.json
/assets/*licenses.*
**/target
**/venv
.build
*.wasm
Packages
*.xcodeproj
xcuserdata/
DerivedData/
.DS_Store
.blob_store
.build
.envrc
.flatpak-builder
.idea
.netrc
.pytest_cache
.swiftpm
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
.swiftpm
**/*.db
.pytest_cache
.venv
.blob_store
.vscode
.wrangler
.flatpak-builder
/.direnv
/assets/*licenses.*
/crates/collab/seed.json
/crates/theme/schemas/theme.json
/crates/zed/resources/flatpak/flatpak-cargo-sources.json
/dev.zed.Zed*.json
/plugins/bin
/script/node_modules
/zed.xcworkspace
DerivedData/
Packages
xcuserdata/
# Don't commit any secrets to the repo.
.env.secret.toml

View File

@@ -52,3 +52,9 @@ Zed is made up of several smaller crates - let's go over those you're most likel
- [`rpc`](/crates/rpc) defines messages to be exchanged with collaboration server.
- [`theme`](/crates/theme) defines the theme system and provides a default theme.
- [`ui`](/crates/ui) is a collection of UI components and common patterns used throughout Zed.
- [`cli`](/crates/cli) is the CLI crate which invokes the Zed binary.
- [`zed`](/crates/zed) is where all things come together, and the `main` entry point for Zed.
## Packaging Zed
Check our [notes for packaging Zed](https://zed.dev/docs/development/linux#notes-for-packaging-zed).

936
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,12 +26,15 @@ members = [
"crates/collections",
"crates/command_palette",
"crates/command_palette_hooks",
"crates/component",
"crates/component_preview",
"crates/context_server",
"crates/context_server_settings",
"crates/copilot",
"crates/db",
"crates/deepseek",
"crates/diagnostics",
"crates/buffer_diff",
"crates/docs_preprocessor",
"crates/editor",
"crates/evals",
@@ -80,6 +83,7 @@ members = [
"crates/markdown_preview",
"crates/media",
"crates/menu",
"crates/migrator",
"crates/multi_buffer",
"crates/node_runtime",
"crates/notifications",
@@ -87,6 +91,7 @@ members = [
"crates/open_ai",
"crates/outline",
"crates/outline_panel",
"crates/panel",
"crates/paths",
"crates/picker",
"crates/prettier",
@@ -103,7 +108,6 @@ members = [
"crates/remote_server",
"crates/repl",
"crates/reqwest_client",
"crates/reqwest_client",
"crates/rich_text",
"crates/rope",
"crates/rpc",
@@ -144,7 +148,7 @@ members = [
"crates/ui_input",
"crates/ui_macros",
"crates/util",
"crates/vcs_menu",
"crates/util_macros",
"crates/vim",
"crates/vim_mode_setting",
"crates/welcome",
@@ -152,7 +156,6 @@ members = [
"crates/worktree",
"crates/zed",
"crates/zed_actions",
"crates/zed_predict_onboarding",
"crates/zeta",
#
@@ -168,7 +171,6 @@ members = [
"extensions/haskell",
"extensions/html",
"extensions/lua",
"extensions/php",
"extensions/perplexity",
"extensions/proto",
"extensions/purescript",
@@ -225,12 +227,15 @@ collab_ui = { path = "crates/collab_ui" }
collections = { path = "crates/collections" }
command_palette = { path = "crates/command_palette" }
command_palette_hooks = { path = "crates/command_palette_hooks" }
component = { path = "crates/component" }
component_preview = { path = "crates/component_preview" }
context_server = { path = "crates/context_server" }
context_server_settings = { path = "crates/context_server_settings" }
copilot = { path = "crates/copilot" }
db = { path = "crates/db" }
deepseek = { path = "crates/deepseek" }
diagnostics = { path = "crates/diagnostics" }
buffer_diff = { path = "crates/buffer_diff" }
editor = { path = "crates/editor" }
extension = { path = "crates/extension" }
extension_host = { path = "crates/extension_host" }
@@ -243,8 +248,8 @@ fs = { path = "crates/fs" }
fsevent = { path = "crates/fsevent" }
fuzzy = { path = "crates/fuzzy" }
git = { path = "crates/git" }
git_ui = { path = "crates/git_ui" }
git_hosting_providers = { path = "crates/git_hosting_providers" }
git_ui = { path = "crates/git_ui" }
go_to_line = { path = "crates/go_to_line" }
google_ai = { path = "crates/google_ai" }
gpui = { path = "crates/gpui", default-features = false, features = [
@@ -277,6 +282,7 @@ markdown = { path = "crates/markdown" }
markdown_preview = { path = "crates/markdown_preview" }
media = { path = "crates/media" }
menu = { path = "crates/menu" }
migrator = { path = "crates/migrator" }
multi_buffer = { path = "crates/multi_buffer" }
node_runtime = { path = "crates/node_runtime" }
notifications = { path = "crates/notifications" }
@@ -285,6 +291,7 @@ open_ai = { path = "crates/open_ai" }
outline = { path = "crates/outline" }
outline_panel = { path = "crates/outline_panel" }
paths = { path = "crates/paths" }
panel = { path = "crates/panel" }
picker = { path = "crates/picker" }
plugin = { path = "crates/plugin" }
plugin_macros = { path = "crates/plugin_macros" }
@@ -340,7 +347,7 @@ ui = { path = "crates/ui" }
ui_input = { path = "crates/ui_input" }
ui_macros = { path = "crates/ui_macros" }
util = { path = "crates/util" }
vcs_menu = { path = "crates/vcs_menu" }
util_macros = { path = "crates/util_macros" }
vim = { path = "crates/vim" }
vim_mode_setting = { path = "crates/vim_mode_setting" }
welcome = { path = "crates/welcome" }
@@ -348,7 +355,6 @@ workspace = { path = "crates/workspace" }
worktree = { path = "crates/worktree" }
zed = { path = "crates/zed" }
zed_actions = { path = "crates/zed_actions" }
zed_predict_onboarding = { path = "crates/zed_predict_onboarding" }
zeta = { path = "crates/zeta" }
#
@@ -361,7 +367,7 @@ alacritty_terminal = { git = "https://github.com/alacritty/alacritty.git", rev =
any_vec = "0.14"
anyhow = "1.0.86"
arrayvec = { version = "0.7.4", features = ["serde"] }
ashpd = { version = "0.10", default-features = false, features = ["async-std"]}
ashpd = { version = "0.10", default-features = false, features = ["async-std"] }
async-compat = "0.2.1"
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
async-dispatcher = "0.1"
@@ -416,6 +422,7 @@ ignore = "0.4.22"
image = "0.25.1"
indexmap = { version = "2.7.0", features = ["serde"] }
indoc = "2"
inventory = "0.3.19"
itertools = "0.14.0"
jsonwebtoken = "9.3"
jupyter-protocol = { version = "0.6.0" }
@@ -423,7 +430,12 @@ jupyter-websocket-client = { version = "0.9.0" }
libc = "0.2"
libsqlite3-sys = { version = "0.30.1", features = ["bundled"] }
linkify = "0.10.0"
livekit = { git = "https://github.com/zed-industries/livekit-rust-sdks", rev="060964da10574cd9bf06463a53bf6e0769c5c45e", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
linkme = "0.3.31"
livekit = { git = "https://github.com/zed-industries/livekit-rust-sdks", rev = "811ceae29fabee455f110c56cd66b3f49a7e5003", features = [
"dispatcher",
"services-dispatcher",
"rustls-tls-native-roots",
], default-features = false }
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
markup5ever_rcdom = "0.3.0"
nanoid = "0.4"
@@ -443,11 +455,13 @@ pet-poetry = { git = "https://github.com/microsoft/python-environment-tools.git"
pet-reporter = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "1abe5cec5ebfbe97ca71746a4cfc7fe89bddf8e0" }
postage = { version = "0.5", features = ["futures-traits"] }
pretty_assertions = { version = "1.3.0", features = ["unstable"] }
proc-macro2 = "1.0.93"
profiling = "1"
prost = "0.9"
prost-build = "0.9"
prost-types = "0.9"
pulldown-cmark = { version = "0.12.0", default-features = false }
quote = "1.0.9"
rand = "0.8.5"
rayon = "1.8"
regex = "1.5"
@@ -467,8 +481,8 @@ runtimelib = { version = "0.25.0", default-features = false, features = [
rustc-demangle = "0.1.23"
rust-embed = { version = "8.4", features = ["include-exclude"] }
rustc-hash = "2.1.0"
rustls = "0.21.12"
rustls-native-certs = "0.8.0"
rustls = { version = "0.23.22" }
rustls-platform-verifier = "0.5.0"
schemars = { version = "0.8", features = ["impl_json_schema", "indexmap2"] }
semver = "1.0"
serde = { version = "1.0", features = ["derive", "rc"] }
@@ -488,9 +502,11 @@ simplelog = "0.12.2"
smallvec = { version = "1.6", features = ["union"] }
smol = "2.0"
sqlformat = "0.2"
streaming-iterator = "0.1"
strsim = "0.11"
strum = { version = "0.26.0", features = ["derive"] }
subtle = "2.5.0"
syn = { version = "1.0.72", features = ["full", "extra-traits"] }
sys-locale = "0.3.1"
sysinfo = "0.31.0"
take-until = "0.2.0"
@@ -508,13 +524,14 @@ tiny_http = "0.8"
toml = "0.8"
tokio = { version = "1" }
tower-http = "0.4.4"
tree-sitter = { version = "0.23", features = ["wasm"] }
tree-sitter = { version = "0.24", features = ["wasm"] }
tree-sitter-bash = "0.23"
tree-sitter-c = "0.23"
tree-sitter-cpp = "0.23"
tree-sitter-css = "0.23"
tree-sitter-elixir = "0.3"
tree-sitter-embedded-template = "0.23.0"
tree-sitter-gitcommit = {git = "https://github.com/zed-industries/tree-sitter-git-commit", rev = "88309716a69dd13ab83443721ba6e0b491d37ee9"}
tree-sitter-go = "0.23"
tree-sitter-go-mod = { git = "https://github.com/camdencheek/tree-sitter-go-mod", rev = "6efb59652d30e0e9cd5f3b3a669afd6f1a926d3c", package = "tree-sitter-gomod" }
tree-sitter-gowork = { git = "https://github.com/zed-industries/tree-sitter-go-work", rev = "acb0617bf7f4fda02c6217676cc64acb89536dc7" }
@@ -536,18 +553,19 @@ unicode-segmentation = "1.10"
unicode-script = "0.5.7"
url = "2.2"
uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] }
wasmparser = "0.215"
wasm-encoder = "0.215"
wasmtime = { version = "24", default-features = false, features = [
wasmparser = "0.217"
wasm-encoder = "0.217"
wasmtime = { version = "25", default-features = false, features = [
"async",
"demangle",
"runtime",
"cranelift",
"component-model",
] }
wasmtime-wasi = "24"
wasmtime-wasi = "25"
which = "6.0.0"
wit-component = "0.201"
zed_llm_client = "0.4"
zstd = "0.11"
metal = "0.31"
@@ -608,6 +626,7 @@ features = [
# TODO livekit https://github.com/RustAudio/cpal/pull/891
[patch.crates-io]
cpal = { git = "https://github.com/zed-industries/cpal", rev = "fd8bc2fd39f1f5fdee5a0690656caff9a26d9d50" }
real-async-tls = { git = "https://github.com/zed-industries/async-tls", rev = "1e759a4b5e370f87dc15e40756ac4f8815b61d9d", package = "async-tls"}
[profile.dev]
split-debuginfo = "unpacked"
@@ -661,7 +680,6 @@ telemetry_events = { codegen-units = 1 }
theme_selector = { codegen-units = 1 }
time_format = { codegen-units = 1 }
ui_input = { codegen-units = 1 }
vcs_menu = { codegen-units = 1 }
zed_actions = { codegen-units = 1 }
[profile.release]

View File

@@ -1,4 +1,4 @@
Copyright 2022 - 2024 Zed Industries, Inc.
Copyright 2022 - 2025 Zed Industries, Inc.

View File

@@ -1,4 +1,4 @@
Copyright 2022 - 2024 Zed Industries, Inc.
Copyright 2022 - 2025 Zed Industries, Inc.
Licensed under the Apache License, Version 2.0 (the "License");

1
assets/icons/circle.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="7.25" cy="7.25" r="3" fill="currentColor"></circle></svg>

After

Width:  |  Height:  |  Size: 165 B

View File

@@ -18,18 +18,23 @@
"bash_logout": "terminal",
"bash_profile": "terminal",
"bashrc": "terminal",
"bicep": "bicep",
"bmp": "image",
"c": "c",
"c++": "cpp",
"cc": "cpp",
"cjs": "javascript",
"cjsx": "react",
"coffee": "coffeescript",
"conf": "settings",
"cpp": "cpp",
"cs": "csharp",
"css": "css",
"csv": "storage",
"cxx": "cpp",
"cts": "typescript",
"ctsx": "react",
"cue": "cue",
"dart": "dart",
"dat": "storage",
"db": "storage",
@@ -64,6 +69,7 @@
"gitattributes": "vcs",
"gitignore": "vcs",
"gitkeep": "vcs",
"gitlab-ci.yml": "gitlab",
"gitmodules": "vcs",
"TAG_EDITMSG": "vcs",
"MERGE_MSG": "vcs",
@@ -86,8 +92,8 @@
"hpp": "cpp",
"hrl": "erlang",
"hs": "haskell",
"htm": "template",
"html": "template",
"htm": "html",
"html": "html",
"hxx": "cpp",
"ib": "storage",
"ico": "image",
@@ -101,7 +107,7 @@
"jpeg": "image",
"jpg": "image",
"js": "javascript",
"json": "storage",
"json": "json",
"jsonc": "storage",
"jsx": "react",
"jxl": "image",
@@ -111,16 +117,18 @@
"lockb": "bun",
"log": "log",
"lua": "lua",
"luau": "luau",
"m4a": "audio",
"m4v": "video",
"markdown": "document",
"md": "document",
"markdown": "markdown",
"md": "markdown",
"mdb": "storage",
"mdf": "storage",
"mdx": "document",
"metadata": "code",
"metal": "metal",
"mjs": "javascript",
"mjsx": "react",
"mka": "audio",
"mkv": "video",
"ml": "ocaml",
@@ -130,6 +138,7 @@
"mp3": "audio",
"mp4": "video",
"mts": "typescript",
"mtsx": "react",
"myd": "storage",
"myi": "storage",
"nim": "nim",
@@ -150,8 +159,19 @@
"postcss": "css",
"ppt": "document",
"pptx": "document",
"prettier.config.cjs": "prettier",
"prettier.config.js": "prettier",
"prettier.config.mjs": "prettier",
"prettierignore": "prettier",
"prettierrc": "prettier",
"prettierrc.cjs": "prettier",
"prettierrc.js": "prettier",
"prettierrc.json": "prettier",
"prettierrc.json5": "prettier",
"prettierrc.mjs": "prettier",
"prettierrc.toml": "prettier",
"prettierrc.yaml": "prettier",
"prettierrc.yml": "prettier",
"prisma": "prisma",
"profile": "terminal",
"ps1": "terminal",
@@ -173,9 +193,21 @@
"scss": "sass",
"sdf": "storage",
"sh": "terminal",
"sol": "solidity",
"sql": "storage",
"sqlite": "storage",
"svelte": "template",
"stylelint.config.cjs": "stylelint",
"stylelint.config.js": "stylelint",
"stylelint.config.mjs": "stylelint",
"stylelintignore": "stylelint",
"stylelintrc": "stylelint",
"stylelintrc.cjs": "stylelint",
"stylelintrc.js": "stylelint",
"stylelintrc.json": "stylelint",
"stylelintrc.mjs": "stylelint",
"stylelintrc.yaml": "stylelint",
"stylelintrc.yml": "stylelint",
"svelte": "svelte",
"svg": "image",
"swift": "swift",
"tcl": "tcl",

View File

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 5C5 3.89543 5.89543 3 7 3H9C10.1046 3 11 3.89543 11 5V6H5V5Z" stroke="black" stroke-width="1.5"/>
<path d="M8 9V11" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<circle cx="8" cy="9" r="1" fill="black"/>
<rect x="3.75" y="5.75" width="8.5" height="7.5" rx="1.25" stroke="black" stroke-width="1.5" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 452 B

View File

@@ -1,6 +1,6 @@
<svg width="420" height="128" xmlns="http://www.w3.org/2000/svg">
<svg width="550" height="128" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="tilePattern" width="22" height="22" patternUnits="userSpaceOnUse">
<pattern id="tilePattern" width="23" height="23" patternUnits="userSpaceOnUse">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 5L14 8L12 11" stroke="black" stroke-width="1.5"/>
<path d="M10 6.5L11 8L10 9.5" stroke="black" stroke-width="1.5"/>

Before

Width:  |  Height:  |  Size: 971 B

After

Width:  |  Height:  |  Size: 971 B

View File

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M6.75 9.31247L8.25 10.5576V11.75H1.75V10.0803L4.49751 7.44273L5.65909 8.40693L3.73923 10.25H6.75V9.31247ZM8.25 5.85739V4.25H6.31358L8.25 5.85739ZM1.75 5.16209V7.1H3.25V6.4072L1.75 5.16209Z" fill="black"/>
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M10.9624 9.40853L11.9014 8L10.6241 6.08397L9.37598 6.91603L10.0986 8L9.80184 8.44518L10.9624 9.40853Z" fill="black"/>
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M12.8936 11.0116L14.9014 8L12.6241 4.58397L11.376 5.41603L13.0986 8L11.7331 10.0483L12.8936 11.0116Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1225 13.809C14.0341 13.9146 13.877 13.9289 13.7711 13.8409L1.19311 3.40021C1.08659 3.31178 1.07221 3.15362 1.16104 3.04743L1.87752 2.19101C1.96588 2.0854 2.123 2.07112 2.22895 2.15906L14.8069 12.5998C14.9134 12.6882 14.9278 12.8464 14.839 12.9526L14.1225 13.809Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 9.33333L14.5 9.66667L12.5 11L10.5 9.66667L10 9.33333" stroke="black" stroke-width="1.5"/>
<path d="M12.5 11V4.5" stroke="black" stroke-width="1.5"/>
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 375 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 6.66667L10.5 6.33333L12.5 5L14.5 6.33333L15 6.66667" stroke="black" stroke-width="1.5"/>
<path d="M12.5 11V5" stroke="black" stroke-width="1.5"/>
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 372 B

View File

@@ -31,8 +31,8 @@
"ctrl-,": "zed::OpenSettings",
"ctrl-q": "zed::Quit",
"f11": "zed::ToggleFullScreen",
"ctrl-alt-z": "zeta::RateCompletions",
"ctrl-shift-i": "inline_completion::ToggleMenu"
"ctrl-alt-z": "edit_prediction::RateCompletions",
"ctrl-shift-i": "edit_prediction::ToggleMenu"
}
},
{
@@ -122,7 +122,8 @@
"ctrl-i": "editor::ShowSignatureHelp",
"alt-g b": "editor::ToggleGitBlame",
"menu": "editor::OpenContextMenu",
"shift-f10": "editor::OpenContextMenu"
"shift-f10": "editor::OpenContextMenu",
"ctrl-shift-e": "editor::ToggleEditPrediction"
}
},
{
@@ -145,17 +146,17 @@
}
},
{
"context": "Editor && mode == full && inline_completion",
"context": "Editor && mode == full && edit_prediction",
"bindings": {
"alt-]": "editor::NextInlineCompletion",
"alt-[": "editor::PreviousInlineCompletion",
"alt-right": "editor::AcceptPartialInlineCompletion"
"alt-]": "editor::NextEditPrediction",
"alt-[": "editor::PreviousEditPrediction",
"alt-right": "editor::AcceptPartialEditPrediction"
}
},
{
"context": "Editor && !inline_completion",
"context": "Editor && !edit_prediction",
"bindings": {
"alt-\\": "editor::ShowInlineCompletion"
"alt-\\": "editor::ShowEditPrediction"
}
},
{
@@ -203,8 +204,8 @@
"enter": "search::SelectNextMatch",
"shift-enter": "search::SelectPrevMatch",
"alt-enter": "search::SelectAllMatches",
"ctrl-f": "search::FocusSearch",
"find": "search::FocusSearch",
"ctrl-f": "search::FocusSearch",
"ctrl-h": "search::ToggleReplace",
"ctrl-l": "search::ToggleSelection"
}
@@ -274,8 +275,8 @@
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-shift-pageup": "pane::SwapItemLeft",
"ctrl-shift-pagedown": "pane::SwapItemRight",
"ctrl-f4": "pane::CloseActiveItem",
"ctrl-w": "pane::CloseActiveItem",
"ctrl-f4": ["pane::CloseActiveItem", { "close_pinned": false }],
"ctrl-w": ["pane::CloseActiveItem", { "close_pinned": false }],
"alt-ctrl-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
"alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes",
"ctrl-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
@@ -290,15 +291,15 @@
"f3": "search::SelectNextMatch",
"ctrl-alt-shift-g": "search::SelectPrevMatch",
"shift-f3": "search::SelectPrevMatch",
"ctrl-shift-f": "project_search::ToggleFocus",
"shift-find": "project_search::ToggleFocus",
"ctrl-shift-f": "project_search::ToggleFocus",
"ctrl-alt-shift-h": "search::ToggleReplace",
"ctrl-alt-shift-l": "search::ToggleSelection",
"alt-enter": "search::SelectAllMatches",
"alt-c": "search::ToggleCaseSensitive",
"alt-w": "search::ToggleWholeWord",
"alt-ctrl-f": "project_search::ToggleFilters",
"alt-find": "project_search::ToggleFilters",
"alt-ctrl-f": "project_search::ToggleFilters",
"ctrl-alt-shift-r": "search::ToggleRegex",
"ctrl-alt-shift-x": "search::ToggleRegex",
"alt-r": "search::ToggleRegex",
@@ -348,15 +349,15 @@
"ctrl-k ctrl-l": "editor::ToggleFold",
"ctrl-k ctrl-[": "editor::FoldRecursive",
"ctrl-k ctrl-]": "editor::UnfoldRecursive",
"ctrl-k ctrl-1": ["editor::FoldAtLevel", { "level": 1 }],
"ctrl-k ctrl-2": ["editor::FoldAtLevel", { "level": 2 }],
"ctrl-k ctrl-3": ["editor::FoldAtLevel", { "level": 3 }],
"ctrl-k ctrl-4": ["editor::FoldAtLevel", { "level": 4 }],
"ctrl-k ctrl-5": ["editor::FoldAtLevel", { "level": 5 }],
"ctrl-k ctrl-6": ["editor::FoldAtLevel", { "level": 6 }],
"ctrl-k ctrl-7": ["editor::FoldAtLevel", { "level": 7 }],
"ctrl-k ctrl-8": ["editor::FoldAtLevel", { "level": 8 }],
"ctrl-k ctrl-9": ["editor::FoldAtLevel", { "level": 9 }],
"ctrl-k ctrl-1": ["editor::FoldAtLevel", 1],
"ctrl-k ctrl-2": ["editor::FoldAtLevel", 2],
"ctrl-k ctrl-3": ["editor::FoldAtLevel", 3],
"ctrl-k ctrl-4": ["editor::FoldAtLevel", 4],
"ctrl-k ctrl-5": ["editor::FoldAtLevel", 5],
"ctrl-k ctrl-6": ["editor::FoldAtLevel", 6],
"ctrl-k ctrl-7": ["editor::FoldAtLevel", 7],
"ctrl-k ctrl-8": ["editor::FoldAtLevel", 8],
"ctrl-k ctrl-9": ["editor::FoldAtLevel", 9],
"ctrl-k ctrl-0": "editor::FoldAll",
"ctrl-k ctrl-j": "editor::UnfoldAll",
"ctrl-space": "editor::ShowCompletions",
@@ -432,14 +433,14 @@
"ctrl-alt-s": "workspace::SaveAll",
"ctrl-k m": "language_selector::Toggle",
"escape": "workspace::Unfollow",
"ctrl-k ctrl-left": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-k ctrl-right": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-k ctrl-up": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-k ctrl-down": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-k ctrl-left": "workspace::ActivatePaneLeft",
"ctrl-k ctrl-right": "workspace::ActivatePaneRight",
"ctrl-k ctrl-up": "workspace::ActivatePaneUp",
"ctrl-k ctrl-down": "workspace::ActivatePaneDown",
"ctrl-k shift-left": "workspace::SwapPaneLeft",
"ctrl-k shift-right": "workspace::SwapPaneRight",
"ctrl-k shift-up": "workspace::SwapPaneUp",
"ctrl-k shift-down": "workspace::SwapPaneDown",
"ctrl-shift-x": "zed::Extensions",
"ctrl-shift-r": "task::Rerun",
"ctrl-alt-r": "task::Rerun",
@@ -453,8 +454,8 @@
{
"context": "ApplicationMenu",
"bindings": {
"left": ["app_menu::NavigateApplicationMenuInDirection", "Left"],
"right": ["app_menu::NavigateApplicationMenuInDirection", "Right"]
"left": "app_menu::ActivateMenuLeft",
"right": "app_menu::ActivateMenuRight"
}
},
// Bindings from Sublime Text
@@ -496,17 +497,27 @@
},
{
"context": "Editor && showing_completions",
"use_key_equivalents": true,
"bindings": {
"enter": "editor::ConfirmCompletion",
"tab": "editor::ComposeCompletion"
}
},
// Bindings for accepting edit predictions
//
// alt-l is provided as an alternative to tab/alt-tab. and will be displayed in the UI. This is
// because alt-tab may not be available, as it is often used for window switching.
{
"context": "Editor && inline_completion && !showing_completions",
"use_key_equivalents": true,
"context": "Editor && edit_prediction",
"bindings": {
"tab": "editor::AcceptInlineCompletion"
"alt-tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction"
}
},
{
"context": "Editor && edit_prediction && !edit_prediction_requires_modifier",
"bindings": {
"tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction"
}
},
{
@@ -530,8 +541,7 @@
{
"bindings": {
"ctrl-alt-shift-f": "workspace::FollowNextCollaborator",
"ctrl-alt-i": "zed::DebugElements",
"ctrl-:": "editor::ToggleInlayHints"
"ctrl-alt-i": "zed::DebugElements"
}
},
{
@@ -549,7 +559,8 @@
"ctrl-shift-e": "pane::RevealInProjectPanel",
"ctrl-f8": "editor::GoToHunk",
"ctrl-shift-f8": "editor::GoToPrevHunk",
"ctrl-enter": "assistant::InlineAssist"
"ctrl-enter": "assistant::InlineAssist",
"ctrl-:": "editor::ToggleInlayHints"
}
},
{
@@ -595,14 +606,12 @@
},
{
"context": "MessageEditor > Editor",
"use_key_equivalents": true,
"bindings": {
"enter": "assistant2::Chat"
}
},
{
"context": "ContextStrip",
"use_key_equivalents": true,
"bindings": {
"up": "assistant2::FocusUp",
"right": "assistant2::FocusRight",
@@ -680,8 +689,8 @@
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": false }],
"alt-ctrl-r": "project_panel::RevealInFileManager",
"ctrl-shift-enter": "project_panel::OpenWithSystem",
"ctrl-shift-f": "project_panel::NewSearchInDirectory",
"shift-find": "project_panel::NewSearchInDirectory",
"ctrl-shift-f": "project_panel::NewSearchInDirectory",
"shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev",
"escape": "menu::Cancel"
@@ -695,30 +704,32 @@
},
{
"context": "GitPanel && !CommitEditor",
"use_key_equivalents": true,
"bindings": {
"escape": "git_panel::Close"
}
},
{
"context": "GitPanel && ChangesList",
"use_key_equivalents": true,
"bindings": {
"up": "menu::SelectPrev",
"down": "menu::SelectNext",
"enter": "menu::Confirm",
"space": "git::ToggleStaged",
"ctrl-space": "git::StageAll",
"ctrl-shift-space": "git::UnstageAll"
"ctrl-shift-space": "git::UnstageAll",
"tab": "git_panel::FocusEditor",
"shift-tab": "git_panel::FocusEditor",
"escape": "git_panel::ToggleFocus"
}
},
{
"context": "GitPanel && CommitEditor > Editor",
"use_key_equivalents": true,
"context": "GitPanel > Editor",
"bindings": {
"escape": "git_panel::FocusChanges",
"ctrl-enter": "git::CommitChanges",
"ctrl-shift-enter": "git::CommitAllChanges"
"ctrl-enter": "git::Commit",
"tab": "git_panel::FocusChanges",
"shift-tab": "git_panel::FocusChanges",
"alt-up": "git_panel::FocusChanges"
}
},
{
@@ -826,7 +837,6 @@
},
{
"context": "ZedPredictModal",
"use_key_equivalents": true,
"bindings": {
"escape": "menu::Cancel"
}

View File

@@ -39,8 +39,8 @@
"cmd-m": "zed::Minimize",
"fn-f": "zed::ToggleFullScreen",
"ctrl-cmd-f": "zed::ToggleFullScreen",
"ctrl-shift-z": "zeta::RateCompletions",
"ctrl-shift-i": "inline_completion::ToggleMenu"
"ctrl-cmd-z": "edit_prediction::RateCompletions",
"ctrl-cmd-i": "edit_prediction::ToggleMenu"
}
},
{
@@ -132,7 +132,8 @@
"cmd-alt-g b": "editor::ToggleGitBlame",
"cmd-i": "editor::ShowSignatureHelp",
"ctrl-f12": "editor::GoToDeclaration",
"alt-ctrl-f12": "editor::GoToDeclarationSplit"
"alt-ctrl-f12": "editor::GoToDeclarationSplit",
"ctrl-cmd-e": "editor::ToggleEditPrediction"
}
},
{
@@ -155,19 +156,19 @@
}
},
{
"context": "Editor && mode == full && inline_completion",
"context": "Editor && mode == full && edit_prediction",
"use_key_equivalents": true,
"bindings": {
"alt-tab": "editor::NextInlineCompletion",
"alt-shift-tab": "editor::PreviousInlineCompletion",
"ctrl-cmd-right": "editor::AcceptPartialInlineCompletion"
"alt-tab": "editor::NextEditPrediction",
"alt-shift-tab": "editor::PreviousEditPrediction",
"ctrl-cmd-right": "editor::AcceptPartialEditPrediction"
}
},
{
"context": "Editor && !inline_completion",
"context": "Editor && !edit_prediction",
"use_key_equivalents": true,
"bindings": {
"alt-tab": "editor::ShowInlineCompletion"
"alt-tab": "editor::ShowEditPrediction"
}
},
{
@@ -349,7 +350,7 @@
"cmd-}": "pane::ActivateNextItem",
"ctrl-shift-pageup": "pane::SwapItemLeft",
"ctrl-shift-pagedown": "pane::SwapItemRight",
"cmd-w": "pane::CloseActiveItem",
"cmd-w": ["pane::CloseActiveItem", { "close_pinned": false }],
"alt-cmd-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
"ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes",
"cmd-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
@@ -413,15 +414,15 @@
"cmd-k cmd-l": "editor::ToggleFold",
"cmd-k cmd-[": "editor::FoldRecursive",
"cmd-k cmd-]": "editor::UnfoldRecursive",
"cmd-k cmd-1": ["editor::FoldAtLevel", { "level": 1 }],
"cmd-k cmd-2": ["editor::FoldAtLevel", { "level": 2 }],
"cmd-k cmd-3": ["editor::FoldAtLevel", { "level": 3 }],
"cmd-k cmd-4": ["editor::FoldAtLevel", { "level": 4 }],
"cmd-k cmd-5": ["editor::FoldAtLevel", { "level": 5 }],
"cmd-k cmd-6": ["editor::FoldAtLevel", { "level": 6 }],
"cmd-k cmd-7": ["editor::FoldAtLevel", { "level": 7 }],
"cmd-k cmd-8": ["editor::FoldAtLevel", { "level": 8 }],
"cmd-k cmd-9": ["editor::FoldAtLevel", { "level": 9 }],
"cmd-k cmd-1": ["editor::FoldAtLevel", 1],
"cmd-k cmd-2": ["editor::FoldAtLevel", 2],
"cmd-k cmd-3": ["editor::FoldAtLevel", 3],
"cmd-k cmd-4": ["editor::FoldAtLevel", 4],
"cmd-k cmd-5": ["editor::FoldAtLevel", 5],
"cmd-k cmd-6": ["editor::FoldAtLevel", 6],
"cmd-k cmd-7": ["editor::FoldAtLevel", 7],
"cmd-k cmd-8": ["editor::FoldAtLevel", 8],
"cmd-k cmd-9": ["editor::FoldAtLevel", 9],
"cmd-k cmd-0": "editor::FoldAll",
"cmd-k cmd-j": "editor::UnfoldAll",
// Using `ctrl-space` in Zed requires disabling the macOS global shortcut.
@@ -509,14 +510,14 @@
"cmd-alt-s": "workspace::SaveAll",
"cmd-k m": "language_selector::Toggle",
"escape": "workspace::Unfollow",
"cmd-k cmd-left": ["workspace::ActivatePaneInDirection", "Left"],
"cmd-k cmd-right": ["workspace::ActivatePaneInDirection", "Right"],
"cmd-k cmd-up": ["workspace::ActivatePaneInDirection", "Up"],
"cmd-k cmd-down": ["workspace::ActivatePaneInDirection", "Down"],
"cmd-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
"cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
"cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
"cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
"cmd-k cmd-left": "workspace::ActivatePaneLeft",
"cmd-k cmd-right": "workspace::ActivatePaneRight",
"cmd-k cmd-up": "workspace::ActivatePaneUp",
"cmd-k cmd-down": "workspace::ActivatePaneDown",
"cmd-k shift-left": "workspace::SwapPaneLeft",
"cmd-k shift-right": "workspace::SwapPaneRight",
"cmd-k shift-up": "workspace::SwapPaneUp",
"cmd-k shift-down": "workspace::SwapPaneDown",
"cmd-shift-x": "zed::Extensions"
}
},
@@ -580,10 +581,16 @@
}
},
{
"context": "Editor && inline_completion && !showing_completions",
"context": "Editor && edit_prediction",
"bindings": {
"alt-tab": "editor::AcceptEditPrediction"
}
},
{
"context": "Editor && edit_prediction && !edit_prediction_requires_modifier",
"use_key_equivalents": true,
"bindings": {
"tab": "editor::AcceptInlineCompletion"
"tab": "editor::AcceptEditPrediction"
}
},
{
@@ -612,8 +619,7 @@
"ctrl-alt-cmd-f": "workspace::FollowNextCollaborator",
// TODO: Move this to a dock open action
"cmd-shift-c": "collab_panel::ToggleFocus",
"cmd-alt-i": "zed::DebugElements",
"ctrl-:": "editor::ToggleInlayHints"
"cmd-alt-i": "zed::DebugElements"
}
},
{
@@ -626,7 +632,8 @@
"cmd-shift-e": "pane::RevealInProjectPanel",
"cmd-f8": "editor::GoToHunk",
"cmd-shift-f8": "editor::GoToPrevHunk",
"ctrl-enter": "assistant::InlineAssist"
"ctrl-enter": "assistant::InlineAssist",
"ctrl-:": "editor::ToggleInlayHints"
}
},
{
@@ -708,13 +715,6 @@
"space": "project_panel::Open"
}
},
{
"context": "GitPanel && !CommitEditor",
"use_key_equivalents": true,
"bindings": {
"escape": "git_panel::Close"
}
},
{
"context": "GitPanel && ChangesList",
"use_key_equivalents": true,
@@ -727,17 +727,21 @@
"space": "git::ToggleStaged",
"cmd-shift-space": "git::StageAll",
"ctrl-shift-space": "git::UnstageAll",
"alt-down": "git_panel::FocusEditor"
"alt-down": "git_panel::FocusEditor",
"tab": "git_panel::FocusEditor",
"shift-tab": "git_panel::FocusEditor",
"escape": "git_panel::ToggleFocus"
}
},
{
"context": "GitPanel && CommitEditor > Editor",
"context": "GitPanel > Editor",
"use_key_equivalents": true,
"bindings": {
"alt-up": "git_panel::FocusChanges",
"escape": "git_panel::FocusChanges",
"cmd-enter": "git::CommitChanges",
"cmd-alt-enter": "git::CommitAllChanges"
"enter": "editor::Newline",
"cmd-enter": "git::Commit",
"tab": "git_panel::FocusChanges",
"shift-tab": "git_panel::FocusChanges",
"alt-up": "git_panel::FocusChanges"
}
},
{

View File

@@ -2,8 +2,8 @@
{
"context": "VimControl && !menu",
"bindings": {
"i": ["vim::PushOperator", { "Object": { "around": false } }],
"a": ["vim::PushOperator", { "Object": { "around": true } }],
"i": ["vim::PushObject", { "around": false }],
"a": ["vim::PushObject", { "around": true }],
"left": "vim::Left",
"h": "vim::Left",
"backspace": "vim::Backspace",
@@ -54,10 +54,10 @@
// "b": "vim::PreviousSubwordStart",
// "e": "vim::NextSubwordEnd",
// "g e": "vim::PreviousSubwordEnd",
"shift-w": ["vim::NextWordStart", { "ignorePunctuation": true }],
"shift-e": ["vim::NextWordEnd", { "ignorePunctuation": true }],
"shift-b": ["vim::PreviousWordStart", { "ignorePunctuation": true }],
"g shift-e": ["vim::PreviousWordEnd", { "ignorePunctuation": true }],
"shift-w": ["vim::NextWordStart", { "ignore_punctuation": true }],
"shift-e": ["vim::NextWordEnd", { "ignore_punctuation": true }],
"shift-b": ["vim::PreviousWordStart", { "ignore_punctuation": true }],
"g shift-e": ["vim::PreviousWordEnd", { "ignore_punctuation": true }],
"/": "vim::Search",
"g /": "pane::DeploySearch",
"?": ["vim::Search", { "backwards": true }],
@@ -70,20 +70,20 @@
"[ {": ["vim::UnmatchedBackward", { "char": "{" }],
"] )": ["vim::UnmatchedForward", { "char": ")" }],
"[ (": ["vim::UnmatchedBackward", { "char": "(" }],
"f": ["vim::PushOperator", { "FindForward": { "before": false } }],
"t": ["vim::PushOperator", { "FindForward": { "before": true } }],
"shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }],
"shift-t": ["vim::PushOperator", { "FindBackward": { "after": true } }],
"m": ["vim::PushOperator", "Mark"],
"'": ["vim::PushOperator", { "Jump": { "line": true } }],
"`": ["vim::PushOperator", { "Jump": { "line": false } }],
"f": ["vim::PushFindForward", { "before": false }],
"t": ["vim::PushFindForward", { "before": true }],
"shift-f": ["vim::PushFindBackward", { "after": false }],
"shift-t": ["vim::PushFindBackward", { "after": true }],
"m": "vim::PushMark",
"'": ["vim::PushJump", { "line": true }],
"`": ["vim::PushJump", { "line": false }],
";": "vim::RepeatFind",
",": "vim::RepeatFindReversed",
"ctrl-o": "pane::GoBack",
"ctrl-i": "pane::GoForward",
"ctrl-]": "editor::GoToDefinition",
"escape": ["vim::SwitchMode", "Normal"],
"ctrl-[": ["vim::SwitchMode", "Normal"],
"escape": "vim::SwitchToNormalMode",
"ctrl-[": "vim::SwitchToNormalMode",
"v": "vim::ToggleVisual",
"shift-v": "vim::ToggleVisualLine",
"ctrl-g": "vim::ShowLocation",
@@ -102,6 +102,7 @@
"ctrl-e": "vim::LineDown",
"ctrl-y": "vim::LineUp",
// "g" commands
"g r": "vim::PushReplaceWithRegister",
"g g": "vim::StartOfDocument",
"g h": "editor::Hover",
"g t": "pane::ActivateNextItem",
@@ -124,17 +125,17 @@
"g .": "editor::ToggleCodeActions", // zed specific
"g shift-a": "editor::FindAllReferences", // zed specific
"g space": "editor::OpenExcerpts", // zed specific
"g *": ["vim::MoveToNext", { "partialWord": true }],
"g #": ["vim::MoveToPrev", { "partialWord": true }],
"g j": ["vim::Down", { "displayLines": true }],
"g down": ["vim::Down", { "displayLines": true }],
"g k": ["vim::Up", { "displayLines": true }],
"g up": ["vim::Up", { "displayLines": true }],
"g $": ["vim::EndOfLine", { "displayLines": true }],
"g end": ["vim::EndOfLine", { "displayLines": true }],
"g 0": ["vim::StartOfLine", { "displayLines": true }],
"g home": ["vim::StartOfLine", { "displayLines": true }],
"g ^": ["vim::FirstNonWhitespace", { "displayLines": true }],
"g *": ["vim::MoveToNext", { "partial_word": true }],
"g #": ["vim::MoveToPrev", { "partial_word": true }],
"g j": ["vim::Down", { "display_lines": true }],
"g down": ["vim::Down", { "display_lines": true }],
"g k": ["vim::Up", { "display_lines": true }],
"g up": ["vim::Up", { "display_lines": true }],
"g $": ["vim::EndOfLine", { "display_lines": true }],
"g end": ["vim::EndOfLine", { "display_lines": true }],
"g 0": ["vim::StartOfLine", { "display_lines": true }],
"g home": ["vim::StartOfLine", { "display_lines": true }],
"g ^": ["vim::FirstNonWhitespace", { "display_lines": true }],
"g v": "vim::RestoreVisualSelection",
"g ]": "editor::GoToDiagnostic",
"g [": "editor::GoToPrevDiagnostic",
@@ -146,7 +147,7 @@
"shift-l": "vim::WindowBottom",
"q": "vim::ToggleRecord",
"shift-q": "vim::ReplayLastRecording",
"@": ["vim::PushOperator", "ReplayRegister"],
"@": "vim::PushReplayRegister",
// z commands
"z enter": ["workspace::SendKeystrokes", "z t ^"],
"z -": ["workspace::SendKeystrokes", "z b ^"],
@@ -165,8 +166,8 @@
"z f": "editor::FoldSelectedRanges",
"z shift-m": "editor::FoldAll",
"z shift-r": "editor::UnfoldAll",
"shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }],
"shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }],
"shift-z shift-q": ["pane::CloseActiveItem", { "save_intent": "skip" }],
"shift-z shift-z": ["pane::CloseActiveItem", { "save_intent": "save_all" }],
// Count support
"1": ["vim::Number", 1],
"2": ["vim::Number", 2],
@@ -193,13 +194,13 @@
"escape": "editor::Cancel",
":": "command_palette::Toggle",
".": "vim::Repeat",
"c": ["vim::PushOperator", "Change"],
"c": "vim::PushChange",
"shift-c": "vim::ChangeToEndOfLine",
"d": ["vim::PushOperator", "Delete"],
"d": "vim::PushDelete",
"shift-d": "vim::DeleteToEndOfLine",
"shift-j": "vim::JoinLines",
"g shift-j": "vim::JoinLinesNoWhitespace",
"y": ["vim::PushOperator", "Yank"],
"y": "vim::PushYank",
"shift-y": "vim::YankLine",
"i": "vim::InsertBefore",
"shift-i": "vim::InsertFirstNonWhitespace",
@@ -216,19 +217,19 @@
"shift-p": ["vim::Paste", { "before": true }],
"u": "vim::Undo",
"ctrl-r": "vim::Redo",
"r": ["vim::PushOperator", "Replace"],
"r": "vim::PushReplace",
"s": "vim::Substitute",
"shift-s": "vim::SubstituteLine",
">": ["vim::PushOperator", "Indent"],
"<": ["vim::PushOperator", "Outdent"],
"=": ["vim::PushOperator", "AutoIndent"],
"!": ["vim::PushOperator", "ShellCommand"],
"g u": ["vim::PushOperator", "Lowercase"],
"g shift-u": ["vim::PushOperator", "Uppercase"],
"g ~": ["vim::PushOperator", "OppositeCase"],
"\"": ["vim::PushOperator", "Register"],
"g w": ["vim::PushOperator", "Rewrap"],
"g q": ["vim::PushOperator", "Rewrap"],
">": "vim::PushIndent",
"<": "vim::PushOutdent",
"=": "vim::PushAutoIndent",
"!": "vim::PushShellCommand",
"g u": "vim::PushLowercase",
"g shift-u": "vim::PushUppercase",
"g ~": "vim::PushOppositeCase",
"\"": "vim::PushRegister",
"g w": "vim::PushRewrap",
"g q": "vim::PushRewrap",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem",
"insert": "vim::InsertBefore",
@@ -239,7 +240,7 @@
"[ d": "editor::GoToPrevDiagnostic",
"] c": "editor::GoToHunk",
"[ c": "editor::GoToPrevHunk",
"g c": ["vim::PushOperator", "ToggleComments"]
"g c": "vim::PushToggleComments"
}
},
{
@@ -264,14 +265,14 @@
"y": "vim::VisualYank",
"shift-y": "vim::VisualYankLine",
"p": "vim::Paste",
"shift-p": ["vim::Paste", { "preserveClipboard": true }],
"shift-p": ["vim::Paste", { "preserve_clipboard": true }],
"c": "vim::Substitute",
"s": "vim::Substitute",
"shift-r": "vim::SubstituteLine",
"shift-s": "vim::SubstituteLine",
"~": "vim::ChangeCase",
"*": ["vim::MoveToNext", { "partialWord": true }],
"#": ["vim::MoveToPrev", { "partialWord": true }],
"*": ["vim::MoveToNext", { "partial_word": true }],
"#": ["vim::MoveToPrev", { "partial_word": true }],
"ctrl-a": "vim::Increment",
"ctrl-x": "vim::Decrement",
"g ctrl-a": ["vim::Increment", { "step": true }],
@@ -282,19 +283,19 @@
"g shift-a": "vim::VisualInsertEndOfLine",
"shift-j": "vim::JoinLines",
"g shift-j": "vim::JoinLinesNoWhitespace",
"r": ["vim::PushOperator", "Replace"],
"ctrl-c": ["vim::SwitchMode", "Normal"],
"ctrl-[": ["vim::SwitchMode", "Normal"],
"escape": ["vim::SwitchMode", "Normal"],
"r": "vim::PushReplace",
"ctrl-c": "vim::SwitchToNormalMode",
"ctrl-[": "vim::SwitchToNormalMode",
"escape": "vim::SwitchToNormalMode",
">": "vim::Indent",
"<": "vim::Outdent",
"=": "vim::AutoIndent",
"!": "vim::ShellCommand",
"i": ["vim::PushOperator", { "Object": { "around": false } }],
"a": ["vim::PushOperator", { "Object": { "around": true } }],
"i": ["vim::PushObject", { "around": false }],
"a": ["vim::PushObject", { "around": true }],
"g c": "vim::ToggleComments",
"g q": "vim::Rewrap",
"\"": ["vim::PushOperator", "Register"],
"\"": "vim::PushRegister",
// tree-sitter related commands
"[ x": "editor::SelectLargerSyntaxNode",
"] x": "editor::SelectSmallerSyntaxNode"
@@ -309,19 +310,19 @@
"ctrl-x": null,
"ctrl-x ctrl-o": "editor::ShowCompletions",
"ctrl-x ctrl-a": "assistant::InlineAssist", // zed specific
"ctrl-x ctrl-c": "editor::ShowInlineCompletion", // zed specific
"ctrl-x ctrl-c": "editor::ShowEditPrediction", // zed specific
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
"ctrl-x ctrl-z": "editor::Cancel",
"ctrl-w": "editor::DeleteToPreviousWordStart",
"ctrl-u": "editor::DeleteToBeginningOfLine",
"ctrl-t": "vim::Indent",
"ctrl-d": "vim::Outdent",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-k": ["vim::PushDigraph", {}],
"ctrl-v": ["vim::PushLiteral", {}],
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-r": ["vim::PushOperator", "Register"],
"ctrl-q": ["vim::PushLiteral", {}],
"ctrl-shift-q": ["vim::PushLiteral", {}],
"ctrl-r": "vim::PushRegister",
"insert": "vim::ToggleReplace",
"ctrl-o": "vim::TemporaryNormal"
}
@@ -356,11 +357,11 @@
"ctrl-c": "vim::NormalBefore",
"ctrl-[": "vim::NormalBefore",
"escape": "vim::NormalBefore",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-k": ["vim::PushDigraph", {}],
"ctrl-v": ["vim::PushLiteral", {}],
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-q": ["vim::PushLiteral", {}],
"ctrl-shift-q": ["vim::PushLiteral", {}],
"backspace": "vim::UndoReplace",
"tab": "vim::Tab",
"enter": "vim::Enter",
@@ -375,9 +376,15 @@
"ctrl-c": "vim::ClearOperators",
"ctrl-[": "vim::ClearOperators",
"escape": "vim::ClearOperators",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-q": ["vim::PushOperator", { "Literal": {} }]
"ctrl-k": ["vim::PushDigraph", {}],
"ctrl-v": ["vim::PushLiteral", {}],
"ctrl-q": ["vim::PushLiteral", {}]
}
},
{
"context": "Editor && vim_mode == waiting && (vim_operator == ys || vim_operator == cs)",
"bindings": {
"escape": "vim::SwitchToNormalMode"
}
},
{
@@ -393,10 +400,10 @@
"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
"bindings": {
"w": "vim::Word",
"shift-w": ["vim::Word", { "ignorePunctuation": true }],
"shift-w": ["vim::Word", { "ignore_punctuation": true }],
// Subword TextObject
// "w": "vim::Subword",
// "shift-w": ["vim::Subword", { "ignorePunctuation": true }],
// "shift-w": ["vim::Subword", { "ignore_punctuation": true }],
"t": "vim::Tag",
"s": "vim::Sentence",
"p": "vim::Paragraph",
@@ -419,9 +426,10 @@
">": "vim::AngleBrackets",
"a": "vim::Argument",
"i": "vim::IndentObj",
"shift-i": ["vim::IndentObj", { "includeBelow": true }],
"shift-i": ["vim::IndentObj", { "include_below": true }],
"f": "vim::Method",
"c": "vim::Class"
"c": "vim::Class",
"e": "vim::EntireFile"
}
},
{
@@ -429,14 +437,14 @@
"bindings": {
"c": "vim::CurrentLine",
"d": "editor::Rename", // zed specific
"s": ["vim::PushOperator", { "ChangeSurrounds": {} }]
"s": ["vim::PushChangeSurrounds", {}]
}
},
{
"context": "vim_operator == d",
"bindings": {
"d": "vim::CurrentLine",
"s": ["vim::PushOperator", "DeleteSurrounds"],
"s": "vim::PushDeleteSurrounds",
"o": "editor::ToggleSelectedDiffHunks", // "d o"
"p": "editor::RevertSelectedHunks" // "d p"
}
@@ -475,7 +483,7 @@
"context": "vim_operator == y",
"bindings": {
"y": "vim::CurrentLine",
"s": ["vim::PushOperator", { "AddSurrounds": {} }]
"s": ["vim::PushAddSurrounds", {}]
}
},
{
@@ -565,34 +573,34 @@
}
},
{
"context": "ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView",
"context": "GitPanel || ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView",
"bindings": {
// window related commands (ctrl-w X)
"ctrl-w": null,
"ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w >": ["vim::ResizePane", "Widen"],
"ctrl-w <": ["vim::ResizePane", "Narrow"],
"ctrl-w -": ["vim::ResizePane", "Shorten"],
"ctrl-w +": ["vim::ResizePane", "Lengthen"],
"ctrl-w left": "workspace::ActivatePaneLeft",
"ctrl-w right": "workspace::ActivatePaneRight",
"ctrl-w up": "workspace::ActivatePaneUp",
"ctrl-w down": "workspace::ActivatePaneDown",
"ctrl-w ctrl-h": "workspace::ActivatePaneLeft",
"ctrl-w ctrl-l": "workspace::ActivatePaneRight",
"ctrl-w ctrl-k": "workspace::ActivatePaneUp",
"ctrl-w ctrl-j": "workspace::ActivatePaneDown",
"ctrl-w h": "workspace::ActivatePaneLeft",
"ctrl-w l": "workspace::ActivatePaneRight",
"ctrl-w k": "workspace::ActivatePaneUp",
"ctrl-w j": "workspace::ActivatePaneDown",
"ctrl-w shift-left": "workspace::SwapPaneLeft",
"ctrl-w shift-right": "workspace::SwapPaneRight",
"ctrl-w shift-up": "workspace::SwapPaneUp",
"ctrl-w shift-down": "workspace::SwapPaneDown",
"ctrl-w shift-h": "workspace::SwapPaneLeft",
"ctrl-w shift-l": "workspace::SwapPaneRight",
"ctrl-w shift-k": "workspace::SwapPaneUp",
"ctrl-w shift-j": "workspace::SwapPaneDown",
"ctrl-w >": "vim::ResizePaneRight",
"ctrl-w <": "vim::ResizePaneLeft",
"ctrl-w -": "vim::ResizePaneDown",
"ctrl-w +": "vim::ResizePaneUp",
"ctrl-w _": "vim::MaximizePane",
"ctrl-w =": "vim::ResetPaneSizes",
"ctrl-w g t": "pane::ActivateNextItem",
@@ -610,10 +618,12 @@
"ctrl-w shift-s": "pane::SplitHorizontal",
"ctrl-w ctrl-s": "pane::SplitHorizontal",
"ctrl-w s": "pane::SplitHorizontal",
"ctrl-w ctrl-c": "pane::CloseAllItems",
"ctrl-w c": "pane::CloseAllItems",
"ctrl-w ctrl-q": "pane::CloseAllItems",
"ctrl-w q": "pane::CloseAllItems",
"ctrl-w ctrl-c": "pane::CloseActiveItem",
"ctrl-w c": "pane::CloseActiveItem",
"ctrl-w ctrl-q": "pane::CloseActiveItem",
"ctrl-w q": "pane::CloseActiveItem",
"ctrl-w ctrl-a": "pane::CloseAllItems",
"ctrl-w a": "pane::CloseAllItems",
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w ctrl-n": "workspace::NewFileSplitHorizontal",
@@ -621,7 +631,7 @@
}
},
{
"context": "EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
"context": "ChangesList || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
"bindings": {
":": "command_palette::Toggle",
"g /": "pane::DeploySearch"
@@ -684,5 +694,22 @@
"shift-x": "git::StageAll",
"shift-u": "git::UnstageAll"
}
},
{
"context": "Editor && edit_prediction && !edit_prediction_requires_modifier",
"bindings": {
// This is identical to the binding in the base keymap, but the vim bindings above to
// "vim::Tab" shadow it, so it needs to be bound again.
"tab": "editor::AcceptEditPrediction"
}
},
{
"context": "os != macos && Editor && edit_prediction",
"bindings": {
// alt-l is provided as an alternative to tab/alt-tab. and will be displayed in the UI. This
// is because alt-tab may not be available, as it is often used for window switching on Linux
// and Windows.
"alt-l": "editor::AcceptEditPrediction"
}
}
]

View File

@@ -24,8 +24,8 @@
"base_keymap": "VSCode",
// Features that can be globally enabled or disabled
"features": {
// Which inline completion provider to use.
"inline_completion_provider": "copilot"
// Which edit prediction provider to use.
"edit_prediction_provider": "copilot"
},
// The name of a font to use for rendering text in the editor
"buffer_font_family": "Zed Plex Mono",
@@ -93,6 +93,13 @@
// workspace when the centered layout is used.
"right_padding": 0.2
},
// All settings related to the image viewer.
"image_viewer": {
// The unit for image file sizes.
// By default we're setting it to binary.
// The second option is decimal.
"unit": "binary"
},
// The key to use for adding multiple cursors
// Currently "alt" or "cmd_or_ctrl" (also aliased as
// "cmd" and "ctrl") are supported.
@@ -161,9 +168,6 @@
/// Whether to show the signature help after completion or a bracket pair inserted.
/// If `auto_signature_help` is enabled, this setting will be treated as enabled also.
"show_signature_help_after_edits": false,
/// Whether to show the inline completions next to the completions provided by a language server.
/// Only has an effect if inline completion provider supports it.
"show_inline_completions_in_menu": true,
// Whether to show wrap guides (vertical rulers) in the editor.
// Setting this to true will show a guide at the 'preferred_line_length' value
// if 'soft_wrap' is set to 'preferred_line_length', and will show any
@@ -196,12 +200,12 @@
// Otherwise(when `true`), the closing characters are always skipped over and auto-removed
// no matter how they were inserted.
"always_treat_brackets_as_autoclosed": false,
// Controls whether inline completions are shown immediately (true)
// or manually by triggering `editor::ShowInlineCompletion` (false).
"show_inline_completions": true,
// Controls whether inline completions are shown in a given language scope.
// Controls whether edit predictions are shown immediately (true)
// or manually by triggering `editor::ShowEditPrediction` (false).
"show_edit_predictions": true,
// Controls whether edit predictions are shown in a given language scope.
// Example: ["string", "comment"]
"inline_completions_disabled_in": [],
"edit_predictions_disabled_in": [],
// Whether to show tabs and spaces in the editor.
// This setting can take four values:
//
@@ -648,15 +652,15 @@
// There are 5 possible width values:
//
// 1. Small: This value is essentially a fixed width.
// "modal_width": "small"
// "modal_max_width": "small"
// 2. Medium:
// "modal_width": "medium"
// "modal_max_width": "medium"
// 3. Large:
// "modal_width": "large"
// "modal_max_width": "large"
// 4. Extra Large:
// "modal_width": "xlarge"
// "modal_max_width": "xlarge"
// 5. Fullscreen: This value removes any horizontal padding, as it consumes the whole viewport width.
// "modal_width": "full"
// "modal_max_width": "full"
//
// Default: small
"modal_max_width": "small"
@@ -774,9 +778,25 @@
// 2. Load direnv configuration through the shell hook, works for POSIX shells and fish.
// "load_direnv": "shell_hook"
"load_direnv": "direct",
"inline_completions": {
// A list of globs representing files that inline completions should be disabled for.
"disabled_globs": [".env"]
"edit_predictions": {
// A list of globs representing files that edit predictions should be disabled for.
// There's a sensible default list of globs already included.
// Any addition to this list will be merged with the default list.
"disabled_globs": [
"**/.env*",
"**/*.pem",
"**/*.key",
"**/*.cert",
"**/*.crt",
"**/secrets.yml"
],
// When to show edit predictions previews in buffer.
// This setting takes two possible values:
// 1. Display inline when there are no language server completions available.
// "mode": "eager_preview"
// 2. Display inline when holding modifier key (alt by default).
// "mode": "auto"
"mode": "eager_preview"
},
// Settings specific to journaling
"journal": {

View File

@@ -81,7 +81,7 @@
"terminal.ansi.bright_green": "#4d6140ff",
"terminal.ansi.dim_green": "#d1e0bfff",
"terminal.ansi.yellow": "#dec184ff",
"terminal.ansi.bright_yellow": "#786441ff",
"terminal.ansi.bright_yellow": "#e5c07bff",
"terminal.ansi.dim_yellow": "#f1dfc1ff",
"terminal.ansi.blue": "#74ade8ff",
"terminal.ansi.bright_blue": "#385378ff",
@@ -457,7 +457,7 @@
"terminal.ansi.bright_green": "#b2cfa9ff",
"terminal.ansi.dim_green": "#354d2eff",
"terminal.ansi.yellow": "#dec184ff",
"terminal.ansi.bright_yellow": "#f1dfc1ff",
"terminal.ansi.bright_yellow": "#826221ff",
"terminal.ansi.dim_yellow": "#786441ff",
"terminal.ansi.blue": "#5c78e2ff",
"terminal.ansi.bright_blue": "#b5baf2ff",

View File

@@ -250,7 +250,7 @@ pub async fn stream_completion(
.map(|output| output.0)
}
/// https://docs.anthropic.com/en/api/rate-limits#response-headers
/// <https://docs.anthropic.com/en/api/rate-limits#response-headers>
#[derive(Debug)]
pub struct RateLimitInfo {
pub requests_limit: usize,
@@ -626,7 +626,7 @@ pub struct ApiError {
}
/// An Anthropic API error code.
/// https://docs.anthropic.com/en/api/errors#http-errors
/// <https://docs.anthropic.com/en/api/errors#http-errors>
#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumString)]
#[strum(serialize_all = "snake_case")]
pub enum ApiErrorCode {

View File

@@ -3,7 +3,7 @@ use std::sync::LazyLock;
/// Returns whether the given country code is supported by Anthropic.
///
/// https://www.anthropic.com/supported-countries
/// <https://www.anthropic.com/supported-countries>
pub fn is_supported_country(country_code: &str) -> bool {
SUPPORTED_COUNTRIES.contains(&country_code)
}

View File

@@ -250,10 +250,10 @@ impl AssistantPanel {
)
.child(
PopoverMenu::new("assistant-panel-popover-menu")
.trigger(
.trigger_with_tooltip(
IconButton::new("menu", IconName::EllipsisVertical)
.icon_size(IconSize::Small)
.tooltip(Tooltip::text("Toggle Assistant Menu")),
.icon_size(IconSize::Small),
Tooltip::text("Toggle Assistant Menu"),
)
.menu(move |window, cx| {
let zoom_label = if _pane.read(cx).is_zoomed() {

View File

@@ -1255,7 +1255,7 @@ impl InlineAssistant {
editor.scroll_manager.set_forbid_vertical_scroll(true);
editor.set_show_scrollbars(false, cx);
editor.set_read_only(true);
editor.set_show_inline_completions(Some(false), window, cx);
editor.set_show_edit_predictions(Some(false), window, cx);
editor.highlight_rows::<DeletedLines>(
Anchor::min()..Anchor::max(),
cx.theme().status().deleted_background,
@@ -1595,22 +1595,22 @@ impl Render for PromptEditor {
IconButton::new("context", IconName::SettingsAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.tooltip(move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelRegistry::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
window,
cx,
)
}),
.icon_color(Color::Muted),
move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelRegistry::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
window,
cx,
)
},
))
.map(|el| {
let CodegenStatus::Error(error) = self.codegen.read(cx).status(cx) else {

View File

@@ -646,22 +646,22 @@ impl Render for PromptEditor {
IconButton::new("context", IconName::SettingsAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.tooltip(move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelRegistry::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
window,
cx,
)
}),
.icon_color(Color::Muted),
move |window, cx| {
Tooltip::with_meta(
format!(
"Using {}",
LanguageModelRegistry::read_global(cx)
.active_model()
.map(|model| model.name().0)
.unwrap_or_else(|| "No model selected".into()),
),
None,
"Change Model",
window,
cx,
)
},
))
.children(
if let CodegenStatus::Error(error) = &self.codegen.read(cx).status {

View File

@@ -74,16 +74,16 @@ impl Render for AssistantModelSelector {
.color(Color::Muted)
.size(IconSize::XSmall),
),
),
move |window, cx| {
Tooltip::for_action_in(
"Change Model",
&ToggleModelSelector,
&focus_handle,
window,
cx,
)
.tooltip(move |window, cx| {
Tooltip::for_action_in(
"Change Model",
&ToggleModelSelector,
&focus_handle,
window,
cx,
)
}),
},
)
.with_handle(self.menu_handle.clone())
}

View File

@@ -442,7 +442,7 @@ impl AssistantPanel {
fn handle_assistant_configuration_event(
&mut self,
_model: &Entity<AssistantConfiguration>,
_entity: &Entity<AssistantConfiguration>,
event: &AssistantConfigurationEvent,
window: &mut Window,
cx: &mut Context<Self>,
@@ -660,11 +660,11 @@ impl AssistantPanel {
.gap(DynamicSpacing::Base02.rems(cx))
.child(
PopoverMenu::new("assistant-toolbar-new-popover-menu")
.trigger(
.trigger_with_tooltip(
IconButton::new("new", IconName::Plus)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.tooltip(Tooltip::text("New…")),
.style(ButtonStyle::Subtle),
Tooltip::text("New…"),
)
.anchor(Corner::TopRight)
.with_handle(self.new_item_context_menu_handle.clone())
@@ -677,11 +677,11 @@ impl AssistantPanel {
)
.child(
PopoverMenu::new("assistant-toolbar-history-popover-menu")
.trigger(
.trigger_with_tooltip(
IconButton::new("open-history", IconName::HistoryRerun)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.tooltip(Tooltip::text("History…")),
.style(ButtonStyle::Subtle),
Tooltip::text("History…"),
)
.anchor(Corner::TopRight)
.with_handle(self.open_history_context_menu_handle.clone())

View File

@@ -79,8 +79,8 @@ impl ContextStore {
project.open_buffer(project_path.clone(), cx)
})?;
let buffer_model = open_buffer_task.await?;
let buffer_id = this.update(&mut cx, |_, cx| buffer_model.read(cx).remote_id())?;
let buffer_entity = open_buffer_task.await?;
let buffer_id = this.update(&mut cx, |_, cx| buffer_entity.read(cx).remote_id())?;
let already_included = this.update(&mut cx, |this, _cx| {
match this.will_include_buffer(buffer_id, &project_path.path) {
@@ -98,10 +98,10 @@ impl ContextStore {
}
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
let buffer = buffer_model.read(cx);
let buffer = buffer_entity.read(cx);
collect_buffer_info_and_text(
project_path.path.clone(),
buffer_model,
buffer_entity,
buffer,
cx.to_async(),
)
@@ -119,18 +119,18 @@ impl ContextStore {
pub fn add_file_from_buffer(
&mut self,
buffer_model: Entity<Buffer>,
buffer_entity: Entity<Buffer>,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
cx.spawn(|this, mut cx| async move {
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
let buffer = buffer_model.read(cx);
let buffer = buffer_entity.read(cx);
let Some(file) = buffer.file() else {
return Err(anyhow!("Buffer has no path."));
};
Ok(collect_buffer_info_and_text(
file.path().clone(),
buffer_model,
buffer_entity,
buffer,
cx.to_async(),
))
@@ -207,11 +207,11 @@ impl ContextStore {
let mut buffer_infos = Vec::new();
let mut text_tasks = Vec::new();
this.update(&mut cx, |_, cx| {
for (path, buffer_model) in files.into_iter().zip(buffers) {
let buffer_model = buffer_model?;
let buffer = buffer_model.read(cx);
for (path, buffer_entity) in files.into_iter().zip(buffers) {
let buffer_entity = buffer_entity?;
let buffer = buffer_entity.read(cx);
let (buffer_info, text_task) =
collect_buffer_info_and_text(path, buffer_model, buffer, cx.to_async());
collect_buffer_info_and_text(path, buffer_entity, buffer, cx.to_async());
buffer_infos.push(buffer_info);
text_tasks.push(text_task);
}
@@ -429,7 +429,7 @@ pub enum FileInclusion {
// ContextBuffer without text.
struct BufferInfo {
buffer_model: Entity<Buffer>,
buffer_entity: Entity<Buffer>,
id: BufferId,
version: clock::Global,
}
@@ -437,7 +437,7 @@ struct BufferInfo {
fn make_context_buffer(info: BufferInfo, text: SharedString) -> ContextBuffer {
ContextBuffer {
id: info.id,
buffer: info.buffer_model,
buffer: info.buffer_entity,
version: info.version,
text,
}
@@ -445,13 +445,13 @@ fn make_context_buffer(info: BufferInfo, text: SharedString) -> ContextBuffer {
fn collect_buffer_info_and_text(
path: Arc<Path>,
buffer_model: Entity<Buffer>,
buffer_entity: Entity<Buffer>,
buffer: &Buffer,
cx: AsyncApp,
) -> (BufferInfo, Task<SharedString>) {
let buffer_info = BufferInfo {
id: buffer.remote_id(),
buffer_model,
buffer_entity,
version: buffer.version(),
};
// Important to collect version at the same time as content so that staleness logic is correct.

View File

@@ -92,8 +92,8 @@ impl ContextStrip {
let active_item = workspace.read(cx).active_item(cx)?;
let editor = active_item.to_any().downcast::<Editor>().ok()?.read(cx);
let active_buffer_model = editor.buffer().read(cx).as_singleton()?;
let active_buffer = active_buffer_model.read(cx);
let active_buffer_entity = editor.buffer().read(cx).as_singleton()?;
let active_buffer = active_buffer_entity.read(cx);
let path = active_buffer.file()?.path();
@@ -115,7 +115,7 @@ impl ContextStrip {
Some(SuggestedContext::File {
name,
buffer: active_buffer_model.downgrade(),
buffer: active_buffer_entity.downgrade(),
icon_path,
})
}
@@ -393,9 +393,9 @@ impl Render for ContextStrip {
.on_action(cx.listener(Self::remove_focused_context))
.on_action(cx.listener(Self::accept_suggested_context))
.on_children_prepainted({
let model = cx.entity().downgrade();
let entity = cx.entity().downgrade();
move |children_bounds, _window, cx| {
model
entity
.update(cx, |this, _| {
this.children_bounds = Some(children_bounds);
})
@@ -411,22 +411,22 @@ impl Render for ContextStrip {
Some(context_picker.clone())
})
.trigger(
.trigger_with_tooltip(
IconButton::new("add-context", IconName::Plus)
.icon_size(IconSize::Small)
.style(ui::ButtonStyle::Filled)
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Add Context",
&ToggleContextPicker,
&focus_handle,
window,
cx,
)
}
}),
.style(ui::ButtonStyle::Filled),
{
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Add Context",
&ToggleContextPicker,
&focus_handle,
window,
cx,
)
}
},
)
.attach(gpui::Corner::TopLeft)
.anchor(gpui::Corner::BottomLeft)

View File

@@ -1345,7 +1345,7 @@ impl InlineAssistant {
editor.scroll_manager.set_forbid_vertical_scroll(true);
editor.set_show_scrollbars(false, cx);
editor.set_read_only(true);
editor.set_show_inline_completions(Some(false), window, cx);
editor.set_show_edit_predictions(Some(false), window, cx);
editor.highlight_rows::<DeletedLines>(
Anchor::min()..Anchor::max(),
cx.theme().status().deleted_background,

View File

@@ -12,6 +12,7 @@ use language_model_selector::LanguageModelSelector;
use rope::Point;
use settings::Settings;
use std::time::Duration;
use text::Bias;
use theme::ThemeSettings;
use ui::{
prelude::*, ButtonLike, KeyBinding, PopoverMenu, PopoverMenuHandle, Switch, TintColor, Tooltip,
@@ -239,7 +240,10 @@ impl MessageEditor {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let newest_cursor = editor.selections.newest::<Point>(cx).head();
if newest_cursor.column > 0 {
let behind_cursor = Point::new(newest_cursor.row, newest_cursor.column - 1);
let behind_cursor = snapshot.clip_point(
Point::new(newest_cursor.row, newest_cursor.column - 1),
Bias::Left,
);
let char_behind_cursor = snapshot.chars_at(behind_cursor).next();
if char_behind_cursor == Some('@') {
self.inline_context_picker_menu_handle.show(window, cx);

View File

@@ -459,7 +459,7 @@ impl ContextEditor {
window: &mut Window,
cx: &mut Context<Self>,
) {
if self.editor.read(cx).has_active_completions_menu() {
if self.editor.read(cx).has_visible_completions_menu() {
return;
}
@@ -832,12 +832,13 @@ impl ContextEditor {
let render_block: RenderBlock = Arc::new({
let this = this.clone();
let patch_range = range.clone();
move |cx: &mut BlockContext<'_, '_>| {
move |cx: &mut BlockContext| {
let max_width = cx.max_width;
let gutter_width = cx.gutter_dimensions.full_width();
let block_id = cx.block_id;
let selected = cx.selected;
this.update_in(cx, |this, window, cx| {
let window = &mut cx.window;
this.update(cx.app, |this, cx| {
this.render_patch_block(
patch_range.clone(),
max_width,
@@ -2358,8 +2359,8 @@ impl ContextEditor {
.icon(IconName::Plus)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.tooltip(Tooltip::text("Type / to insert via keyboard")),
.icon_position(IconPosition::Start),
Tooltip::text("Type / to insert via keyboard"),
)
}
@@ -3322,10 +3323,10 @@ impl Render for ContextEditorToolbarItem {
.color(Color::Muted)
.size(IconSize::XSmall),
),
)
.tooltip(move |window, cx| {
Tooltip::for_action("Change Model", &ToggleModelSelector, window, cx)
}),
),
move |window, cx| {
Tooltip::for_action("Change Model", &ToggleModelSelector, window, cx)
},
)
.with_handle(self.language_model_selector_menu_handle.clone()),
)

View File

@@ -31,11 +31,11 @@ use std::{
use util::{ResultExt, TryFutureExt};
pub(crate) fn init(client: &AnyProtoClient) {
client.add_model_message_handler(ContextStore::handle_advertise_contexts);
client.add_model_request_handler(ContextStore::handle_open_context);
client.add_model_request_handler(ContextStore::handle_create_context);
client.add_model_message_handler(ContextStore::handle_update_context);
client.add_model_request_handler(ContextStore::handle_synchronize_contexts);
client.add_entity_message_handler(ContextStore::handle_advertise_contexts);
client.add_entity_request_handler(ContextStore::handle_open_context);
client.add_entity_request_handler(ContextStore::handle_create_context);
client.add_entity_message_handler(ContextStore::handle_update_context);
client.add_entity_request_handler(ContextStore::handle_synchronize_contexts);
}
#[derive(Clone)]
@@ -144,11 +144,9 @@ impl ContextStore {
this.handle_project_changed(project.clone(), cx);
this.synchronize_contexts(cx);
this.register_context_server_handlers(cx);
this.reload(cx).detach_and_log_err(cx);
this
})?;
this.update(&mut cx, |this, cx| this.reload(cx))?
.await
.log_err();
Ok(this)
})
@@ -312,7 +310,7 @@ impl ContextStore {
.client
.subscribe_to_entity(remote_id)
.log_err()
.map(|subscription| subscription.set_model(&cx.entity(), &mut cx.to_async()));
.map(|subscription| subscription.set_entity(&cx.entity(), &mut cx.to_async()));
self.advertise_contexts(cx);
} else {
self.client_subscription = None;

View File

@@ -5,7 +5,7 @@ use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWor
use editor::{CompletionProvider, Editor};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{App, Context, Entity, Task, WeakEntity, Window};
use language::{Anchor, Buffer, Documentation, LanguageServerId, ToPoint};
use language::{Anchor, Buffer, CompletionDocumentation, LanguageServerId, ToPoint};
use parking_lot::Mutex;
use project::CompletionIntent;
use rope::Point;
@@ -120,7 +120,9 @@ impl SlashCommandCompletionProvider {
});
Some(project::Completion {
old_range: name_range.clone(),
documentation: Some(Documentation::SingleLine(command.description())),
documentation: Some(CompletionDocumentation::SingleLine(
command.description(),
)),
new_text,
label: command.label(cx),
server_id: LanguageServerId(0),

View File

@@ -1,17 +1,22 @@
use std::sync::Arc;
use assistant_slash_command::SlashCommandWorkingSet;
use gpui::{AnyElement, DismissEvent, SharedString, Task, WeakEntity};
use gpui::{AnyElement, AnyView, DismissEvent, SharedString, Task, WeakEntity};
use picker::{Picker, PickerDelegate, PickerEditorPosition};
use ui::{prelude::*, ListItem, ListItemSpacing, PopoverMenu, PopoverTrigger, Tooltip};
use crate::context_editor::ContextEditor;
#[derive(IntoElement)]
pub(super) struct SlashCommandSelector<T: PopoverTrigger> {
pub(super) struct SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
working_set: Arc<SlashCommandWorkingSet>,
active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
tooltip: TT,
}
#[derive(Clone)]
@@ -48,16 +53,22 @@ pub(crate) struct SlashCommandDelegate {
selected_index: usize,
}
impl<T: PopoverTrigger> SlashCommandSelector<T> {
impl<T, TT> SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
pub(crate) fn new(
working_set: Arc<SlashCommandWorkingSet>,
active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
tooltip: TT,
) -> Self {
SlashCommandSelector {
working_set,
active_context_editor,
trigger,
tooltip,
}
}
}
@@ -241,7 +252,11 @@ impl PickerDelegate for SlashCommandDelegate {
}
}
impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
impl<T, TT> RenderOnce for SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let all_models = self
.working_set
@@ -322,7 +337,7 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
.ok();
PopoverMenu::new("model-switcher")
.menu(move |_window, _cx| Some(picker_view.clone()))
.trigger(self.trigger)
.trigger_with_tooltip(self.trigger, self.tooltip)
.attach(gpui::Corner::TopLeft)
.anchor(gpui::Corner::BottomLeft)
.offset(gpui::Point {

View File

@@ -434,7 +434,7 @@ pub struct LegacyAssistantSettingsContent {
pub default_open_ai_model: Option<OpenAiModel>,
/// OpenAI API base URL to use when creating new chats.
///
/// Default: https://api.openai.com/v1
/// Default: <https://api.openai.com/v1>
pub openai_api_url: Option<String>,
}

View File

@@ -323,7 +323,14 @@ fn collect_files(
)))?;
directory_stack.push(entry.path.clone());
} else {
let entry_name = format!("{}/{}", prefix_paths, &filename);
// todo(windows)
// Potential bug: this assumes that the path separator is always `\` on Windows
let entry_name = format!(
"{}{}{}",
prefix_paths,
std::path::MAIN_SEPARATOR_STR,
&filename
);
events_tx.unbounded_send(Ok(SlashCommandEvent::StartSection {
icon: IconName::Folder,
label: entry_name.clone().into(),
@@ -455,6 +462,7 @@ mod custom_path_matcher {
use std::{fmt::Debug as _, path::Path};
use globset::{Glob, GlobSet, GlobSetBuilder};
use util::paths::SanitizedPath;
#[derive(Clone, Debug, Default)]
pub struct PathMatcher {
@@ -481,7 +489,7 @@ mod custom_path_matcher {
pub fn new(globs: &[String]) -> Result<Self, globset::Error> {
let globs = globs
.into_iter()
.map(|glob| Glob::new(&glob))
.map(|glob| Glob::new(&SanitizedPath::from(glob).to_glob_string()))
.collect::<Result<Vec<_>, _>>()?;
let sources = globs.iter().map(|glob| glob.glob().to_owned()).collect();
let sources_with_trailing_slash = globs
@@ -507,7 +515,9 @@ mod custom_path_matcher {
.zip(self.sources_with_trailing_slash.iter())
.any(|(source, with_slash)| {
let as_bytes = other_path.as_os_str().as_encoded_bytes();
let with_slash = if source.ends_with("/") {
// todo(windows)
// Potential bug: this assumes that the path separator is always `\` on Windows
let with_slash = if source.ends_with(std::path::MAIN_SEPARATOR_STR) {
source.as_bytes()
} else {
with_slash.as_bytes()
@@ -569,6 +579,7 @@ mod test {
use serde_json::json;
use settings::SettingsStore;
use smol::stream::StreamExt;
use util::{path, separator};
use super::collect_files;
@@ -592,7 +603,7 @@ mod test {
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
path!("/root"),
json!({
"dir": {
"subdir": {
@@ -607,7 +618,7 @@ mod test {
)
.await;
let project = Project::test(fs, ["/root".as_ref()], cx).await;
let project = Project::test(fs, [path!("/root").as_ref()], cx).await;
let result_1 =
cx.update(|cx| collect_files(project.clone(), &["root/dir".to_string()], cx));
@@ -615,7 +626,7 @@ mod test {
.await
.unwrap();
assert!(result_1.text.starts_with("root/dir"));
assert!(result_1.text.starts_with(separator!("root/dir")));
// 4 files + 2 directories
assert_eq!(result_1.sections.len(), 6);
@@ -631,7 +642,7 @@ mod test {
cx.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx).boxed());
let result = SlashCommandOutput::from_event_stream(result).await.unwrap();
assert!(result.text.starts_with("root/dir"));
assert!(result.text.starts_with(separator!("root/dir")));
// 5 files + 2 directories
assert_eq!(result.sections.len(), 7);
@@ -645,7 +656,7 @@ mod test {
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/zed",
path!("/zed"),
json!({
"assets": {
"dir1": {
@@ -670,7 +681,7 @@ mod test {
)
.await;
let project = Project::test(fs, ["/zed".as_ref()], cx).await;
let project = Project::test(fs, [path!("/zed").as_ref()], cx).await;
let result =
cx.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx));
@@ -679,27 +690,36 @@ mod test {
.unwrap();
// Sanity check
assert!(result.text.starts_with("zed/assets/themes\n"));
assert!(result.text.starts_with(separator!("zed/assets/themes\n")));
assert_eq!(result.sections.len(), 7);
// Ensure that full file paths are included in the real output
assert!(result.text.contains("zed/assets/themes/andromeda/LICENSE"));
assert!(result.text.contains("zed/assets/themes/ayu/LICENSE"));
assert!(result.text.contains("zed/assets/themes/summercamp/LICENSE"));
assert!(result
.text
.contains(separator!("zed/assets/themes/andromeda/LICENSE")));
assert!(result
.text
.contains(separator!("zed/assets/themes/ayu/LICENSE")));
assert!(result
.text
.contains(separator!("zed/assets/themes/summercamp/LICENSE")));
assert_eq!(result.sections[5].label, "summercamp");
// Ensure that things are in descending order, with properly relativized paths
assert_eq!(
result.sections[0].label,
"zed/assets/themes/andromeda/LICENSE"
separator!("zed/assets/themes/andromeda/LICENSE")
);
assert_eq!(result.sections[1].label, "andromeda");
assert_eq!(result.sections[2].label, "zed/assets/themes/ayu/LICENSE");
assert_eq!(
result.sections[2].label,
separator!("zed/assets/themes/ayu/LICENSE")
);
assert_eq!(result.sections[3].label, "ayu");
assert_eq!(
result.sections[4].label,
"zed/assets/themes/summercamp/LICENSE"
separator!("zed/assets/themes/summercamp/LICENSE")
);
// Ensure that the project lasts until after the last await
@@ -712,7 +732,7 @@ mod test {
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/zed",
path!("/zed"),
json!({
"assets": {
"themes": {
@@ -732,7 +752,7 @@ mod test {
)
.await;
let project = Project::test(fs, ["/zed".as_ref()], cx).await;
let project = Project::test(fs, [path!("/zed").as_ref()], cx).await;
let result =
cx.update(|cx| collect_files(project.clone(), &["zed/assets/themes".to_string()], cx));
@@ -740,26 +760,29 @@ mod test {
.await
.unwrap();
assert!(result.text.starts_with("zed/assets/themes\n"));
assert_eq!(result.sections[0].label, "zed/assets/themes/LICENSE");
assert!(result.text.starts_with(separator!("zed/assets/themes\n")));
assert_eq!(
result.sections[0].label,
separator!("zed/assets/themes/LICENSE")
);
assert_eq!(
result.sections[1].label,
"zed/assets/themes/summercamp/LICENSE"
separator!("zed/assets/themes/summercamp/LICENSE")
);
assert_eq!(
result.sections[2].label,
"zed/assets/themes/summercamp/subdir/LICENSE"
separator!("zed/assets/themes/summercamp/subdir/LICENSE")
);
assert_eq!(
result.sections[3].label,
"zed/assets/themes/summercamp/subdir/subsubdir/LICENSE"
separator!("zed/assets/themes/summercamp/subdir/subsubdir/LICENSE")
);
assert_eq!(result.sections[4].label, "subsubdir");
assert_eq!(result.sections[5].label, "subdir");
assert_eq!(result.sections[6].label, "summercamp");
assert_eq!(result.sections[7].label, "zed/assets/themes");
assert_eq!(result.sections[7].label, separator!("zed/assets/themes"));
assert_eq!(result.text, "zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n");
assert_eq!(result.text, separator!("zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"));
// Ensure that the project lasts until after the last await
drop(project);

View File

@@ -9,7 +9,7 @@ use release_channel::{AppVersion, ReleaseChannel};
use serde::Deserialize;
use smol::io::AsyncReadExt;
use util::ResultExt as _;
use workspace::notifications::NotificationId;
use workspace::notifications::{show_app_notification, NotificationId};
use workspace::Workspace;
use crate::update_notification::UpdateNotification;
@@ -17,6 +17,7 @@ use crate::update_notification::UpdateNotification;
actions!(auto_update, [ViewReleaseNotesLocally]);
pub fn init(cx: &mut App) {
notify_if_app_was_updated(cx);
cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
workspace.register_action(|workspace, _: &ViewReleaseNotesLocally, window, cx| {
view_release_notes_locally(workspace, window, cx);
@@ -124,31 +125,35 @@ fn view_release_notes_locally(
.detach();
}
pub fn notify_of_any_new_update(window: &mut Window, cx: &mut Context<Workspace>) -> Option<()> {
let updater = AutoUpdater::get(cx)?;
/// Shows a notification across all workspaces if an update was previously automatically installed
/// and this notification had not yet been shown.
pub fn notify_if_app_was_updated(cx: &mut App) {
let Some(updater) = AutoUpdater::get(cx) else {
return;
};
let version = updater.read(cx).current_version();
let should_show_notification = updater.read(cx).should_show_update_notification(cx);
cx.spawn_in(window, |workspace, mut cx| async move {
cx.spawn(|cx| async move {
let should_show_notification = should_show_notification.await?;
if should_show_notification {
workspace.update(&mut cx, |workspace, cx| {
let workspace_handle = workspace.weak_handle();
workspace.show_notification(
cx.update(|cx| {
show_app_notification(
NotificationId::unique::<UpdateNotification>(),
cx,
|cx| cx.new(|_| UpdateNotification::new(version, workspace_handle)),
move |cx| {
let workspace_handle = cx.entity().downgrade();
cx.new(|_| UpdateNotification::new(version, workspace_handle))
},
);
updater.update(cx, |updater, cx| {
updater
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
});
})
})?;
}
anyhow::Ok(())
})
.detach();
None
}

View File

@@ -0,0 +1,37 @@
[package]
name = "buffer_diff"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/buffer_diff.rs"
[features]
test-support = []
[dependencies]
anyhow.workspace = true
futures.workspace = true
git2.workspace = true
gpui.workspace = true
language.workspace = true
log.workspace = true
rope.workspace = true
sum_tree.workspace = true
text.workspace = true
util.workspace = true
[dev-dependencies]
ctor.workspace = true
env_logger.workspace = true
gpui = { workspace = true, features = ["test-support"] }
pretty_assertions.workspace = true
rand.workspace = true
serde_json.workspace = true
text = { workspace = true, features = ["test-support"] }
unindent.workspace = true

File diff suppressed because it is too large Load Diff

View File

@@ -532,6 +532,10 @@ impl Room {
&self.local_participant
}
pub fn local_participant_user(&self, cx: &App) -> Option<Arc<User>> {
self.user_store.read(cx).current_user()
}
pub fn remote_participants(&self) -> &BTreeMap<u64, RemoteParticipant> {
&self.remote_participants
}

View File

@@ -588,6 +588,10 @@ impl Room {
&self.local_participant
}
pub fn local_participant_user(&self, cx: &App) -> Option<Arc<User>> {
self.user_store.read(cx).current_user()
}
pub fn remote_participants(&self) -> &BTreeMap<u64, RemoteParticipant> {
&self.remote_participants
}

View File

@@ -15,8 +15,8 @@ use util::ResultExt;
pub const ACKNOWLEDGE_DEBOUNCE_INTERVAL: Duration = Duration::from_millis(250);
pub(crate) fn init(client: &AnyProtoClient) {
client.add_model_message_handler(ChannelBuffer::handle_update_channel_buffer);
client.add_model_message_handler(ChannelBuffer::handle_update_channel_buffer_collaborators);
client.add_entity_message_handler(ChannelBuffer::handle_update_channel_buffer);
client.add_entity_message_handler(ChannelBuffer::handle_update_channel_buffer_collaborators);
}
pub struct ChannelBuffer {
@@ -81,7 +81,7 @@ impl ChannelBuffer {
collaborators: Default::default(),
acknowledge_task: None,
channel_id: channel.id,
subscription: Some(subscription.set_model(&cx.entity(), &mut cx.to_async())),
subscription: Some(subscription.set_entity(&cx.entity(), &mut cx.to_async())),
user_store,
channel_store,
};

View File

@@ -95,9 +95,9 @@ pub enum ChannelChatEvent {
impl EventEmitter<ChannelChatEvent> for ChannelChat {}
pub fn init(client: &AnyProtoClient) {
client.add_model_message_handler(ChannelChat::handle_message_sent);
client.add_model_message_handler(ChannelChat::handle_message_removed);
client.add_model_message_handler(ChannelChat::handle_message_updated);
client.add_entity_message_handler(ChannelChat::handle_message_sent);
client.add_entity_message_handler(ChannelChat::handle_message_removed);
client.add_entity_message_handler(ChannelChat::handle_message_updated);
}
impl ChannelChat {
@@ -132,7 +132,7 @@ impl ChannelChat {
last_acknowledged_id: None,
rng: StdRng::from_entropy(),
first_loaded_message_id: None,
_subscription: subscription.set_model(&cx.entity(), &mut cx.to_async()),
_subscription: subscription.set_entity(&cx.entity(), &mut cx.to_async()),
}
})?;
Self::handle_loaded_messages(

View File

@@ -39,8 +39,8 @@ pub struct ChannelStore {
channel_states: HashMap<ChannelId, ChannelState>,
outgoing_invites: HashSet<(ChannelId, UserId)>,
update_channels_tx: mpsc::UnboundedSender<proto::UpdateChannels>,
opened_buffers: HashMap<ChannelId, OpenedModelHandle<ChannelBuffer>>,
opened_chats: HashMap<ChannelId, OpenedModelHandle<ChannelChat>>,
opened_buffers: HashMap<ChannelId, OpenEntityHandle<ChannelBuffer>>,
opened_chats: HashMap<ChannelId, OpenEntityHandle<ChannelChat>>,
client: Arc<Client>,
did_subscribe: bool,
user_store: Entity<UserStore>,
@@ -142,7 +142,7 @@ pub enum ChannelEvent {
impl EventEmitter<ChannelEvent> for ChannelStore {}
enum OpenedModelHandle<E> {
enum OpenEntityHandle<E> {
Open(WeakEntity<E>),
Loading(Shared<Task<Result<Entity<E>, Arc<anyhow::Error>>>>),
}
@@ -292,7 +292,7 @@ impl ChannelStore {
pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &App) -> bool {
if let Some(buffer) = self.opened_buffers.get(&channel_id) {
if let OpenedModelHandle::Open(buffer) = buffer {
if let OpenEntityHandle::Open(buffer) = buffer {
return buffer.upgrade().is_some();
}
}
@@ -453,7 +453,7 @@ impl ChannelStore {
fn open_channel_resource<T, F, Fut>(
&mut self,
channel_id: ChannelId,
get_map: fn(&mut Self) -> &mut HashMap<ChannelId, OpenedModelHandle<T>>,
get_map: fn(&mut Self) -> &mut HashMap<ChannelId, OpenEntityHandle<T>>,
load: F,
cx: &mut Context<Self>,
) -> Task<Result<Entity<T>>>
@@ -465,15 +465,15 @@ impl ChannelStore {
let task = loop {
match get_map(self).entry(channel_id) {
hash_map::Entry::Occupied(e) => match e.get() {
OpenedModelHandle::Open(model) => {
if let Some(model) = model.upgrade() {
break Task::ready(Ok(model)).shared();
OpenEntityHandle::Open(entity) => {
if let Some(entity) = entity.upgrade() {
break Task::ready(Ok(entity)).shared();
} else {
get_map(self).remove(&channel_id);
continue;
}
}
OpenedModelHandle::Loading(task) => {
OpenEntityHandle::Loading(task) => {
break task.clone();
}
},
@@ -490,7 +490,7 @@ impl ChannelStore {
})
.shared();
e.insert(OpenedModelHandle::Loading(task.clone()));
e.insert(OpenEntityHandle::Loading(task.clone()));
cx.spawn({
let task = task.clone();
move |this, mut cx| async move {
@@ -499,7 +499,7 @@ impl ChannelStore {
Ok(model) => {
get_map(this).insert(
channel_id,
OpenedModelHandle::Open(model.downgrade()),
OpenEntityHandle::Open(model.downgrade()),
);
}
Err(_) => {
@@ -900,7 +900,7 @@ impl ChannelStore {
self.disconnect_channel_buffers_task.take();
for chat in self.opened_chats.values() {
if let OpenedModelHandle::Open(chat) = chat {
if let OpenEntityHandle::Open(chat) = chat {
if let Some(chat) = chat.upgrade() {
chat.update(cx, |chat, cx| {
chat.rejoin(cx);
@@ -911,7 +911,7 @@ impl ChannelStore {
let mut buffer_versions = Vec::new();
for buffer in self.opened_buffers.values() {
if let OpenedModelHandle::Open(buffer) = buffer {
if let OpenEntityHandle::Open(buffer) = buffer {
if let Some(buffer) = buffer.upgrade() {
let channel_buffer = buffer.read(cx);
let buffer = channel_buffer.buffer().read(cx);
@@ -937,7 +937,7 @@ impl ChannelStore {
this.update(&mut cx, |this, cx| {
this.opened_buffers.retain(|_, buffer| match buffer {
OpenedModelHandle::Open(channel_buffer) => {
OpenEntityHandle::Open(channel_buffer) => {
let Some(channel_buffer) = channel_buffer.upgrade() else {
return false;
};
@@ -998,7 +998,7 @@ impl ChannelStore {
false
})
}
OpenedModelHandle::Loading(_) => true,
OpenEntityHandle::Loading(_) => true,
});
})
.ok();
@@ -1018,7 +1018,7 @@ impl ChannelStore {
if let Some(this) = this.upgrade() {
this.update(&mut cx, |this, cx| {
for (_, buffer) in this.opened_buffers.drain() {
if let OpenedModelHandle::Open(buffer) = buffer {
if let OpenEntityHandle::Open(buffer) = buffer {
if let Some(buffer) = buffer.upgrade() {
buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
}
@@ -1082,7 +1082,7 @@ impl ChannelStore {
{
continue;
}
if let Some(OpenedModelHandle::Open(buffer)) =
if let Some(OpenEntityHandle::Open(buffer)) =
self.opened_buffers.remove(&channel_id)
{
if let Some(buffer) = buffer.upgrade() {
@@ -1098,7 +1098,7 @@ impl ChannelStore {
let channel_changed = index.insert(channel);
if channel_changed {
if let Some(OpenedModelHandle::Open(buffer)) = self.opened_buffers.get(&id) {
if let Some(OpenEntityHandle::Open(buffer)) = self.opened_buffers.get(&id) {
if let Some(buffer) = buffer.upgrade() {
buffer.update(cx, ChannelBuffer::channel_changed);
}

View File

@@ -1,3 +1,5 @@
use std::process::Command;
fn main() {
if std::env::var("ZED_UPDATE_EXPLANATION").is_ok() {
println!(r#"cargo:rustc-cfg=feature="no-bundled-uninstall""#);
@@ -8,4 +10,18 @@ fn main() {
// Weakly link ScreenCaptureKit to ensure can be used on macOS 10.15+.
println!("cargo:rustc-link-arg=-Wl,-weak_framework,ScreenCaptureKit");
}
// Populate git sha environment variable if git is available
println!("cargo:rerun-if-changed=../../.git/logs/HEAD");
if let Some(output) = Command::new("git")
.args(["rev-parse", "HEAD"])
.output()
.ok()
.filter(|output| output.status.success())
{
let git_sha = String::from_utf8_lossy(&output.stdout);
let git_sha = git_sha.trim();
println!("cargo:rustc-env=ZED_COMMIT_SHA={git_sha}");
}
}

View File

@@ -33,7 +33,19 @@ trait InstalledApp {
#[command(
name = "zed",
disable_version_flag = true,
after_help = "To read from stdin, append '-' (e.g. 'ps axf | zed -')"
before_help = "The Zed CLI binary.
This CLI is a separate binary that invokes Zed.
Examples:
`zed`
Simply opens Zed
`zed --foreground`
Runs in foreground (shows all logs)
`zed path-to-your-project`
Open your project in Zed
`zed -n path-to-file `
Open file/folder in a new window",
after_help = "To read from stdin, append '-', e.g. 'ps axf | zed -'"
)]
struct Args {
/// Wait for all of the given paths to be opened/closed before exiting.
@@ -45,10 +57,9 @@ struct Args {
/// Create a new workspace
#[arg(short, long, overrides_with = "add")]
new: bool,
/// A sequence of space-separated paths that you want to open.
/// The paths to open in Zed (space-separated).
///
/// Use `path:line:row` syntax to open a file at a specific location.
/// Non-existing paths and directories will ignore `:line:row` suffix.
/// Use `path:line:column` syntax to open a file at the given line and column.
paths_with_position: Vec<String>,
/// Print Zed's version and the app path.
#[arg(short, long)]
@@ -328,13 +339,17 @@ mod linux {
impl InstalledApp for App {
fn zed_version_string(&self) -> String {
format!(
"Zed {}{} {}",
"Zed {}{}{} {}",
if *RELEASE_CHANNEL == "stable" {
"".to_string()
} else {
format!(" {} ", *RELEASE_CHANNEL)
format!("{} ", *RELEASE_CHANNEL)
},
option_env!("RELEASE_VERSION").unwrap_or_default(),
match option_env!("ZED_COMMIT_SHA") {
Some(commit_sha) => format!(" {commit_sha} "),
None => "".to_string(),
},
self.0.display(),
)
}

View File

@@ -33,8 +33,6 @@ postage.workspace = true
rand.workspace = true
release_channel.workspace = true
rpc = { workspace = true, features = ["gpui"] }
rustls-native-certs.workspace = true
rustls.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true

View File

@@ -379,7 +379,7 @@ pub struct PendingEntitySubscription<T: 'static> {
}
impl<T: 'static> PendingEntitySubscription<T> {
pub fn set_model(mut self, model: &Entity<T>, cx: &AsyncApp) -> Subscription {
pub fn set_entity(mut self, entity: &Entity<T>, cx: &AsyncApp) -> Subscription {
self.consumed = true;
let mut handlers = self.client.handler_set.lock();
let id = (TypeId::of::<T>(), self.remote_id);
@@ -392,7 +392,7 @@ impl<T: 'static> PendingEntitySubscription<T> {
handlers.entities_by_type_and_remote_id.insert(
id,
EntityMessageSubscriber::Entity {
handle: model.downgrade().into(),
handle: entity.downgrade().into(),
},
);
drop(handlers);
@@ -686,8 +686,8 @@ impl Client {
H: 'static + Sync + Fn(Entity<E>, TypedEnvelope<M>, AsyncApp) -> F + Send + Sync,
F: 'static + Future<Output = Result<()>>,
{
self.add_message_handler_impl(entity, move |model, message, _, cx| {
handler(model, message, cx)
self.add_message_handler_impl(entity, move |entity, message, _, cx| {
handler(entity, message, cx)
})
}
@@ -709,7 +709,7 @@ impl Client {
let message_type_id = TypeId::of::<M>();
let mut state = self.handler_set.lock();
state
.models_by_message_type
.entities_by_message_type
.insert(message_type_id, entity.into());
let prev_handler = state.message_handlers.insert(
@@ -738,7 +738,7 @@ impl Client {
pub fn add_request_handler<M, E, H, F>(
self: &Arc<Self>,
model: WeakEntity<E>,
entity: WeakEntity<E>,
handler: H,
) -> Subscription
where
@@ -747,7 +747,7 @@ impl Client {
H: 'static + Sync + Fn(Entity<E>, TypedEnvelope<M>, AsyncApp) -> F + Send + Sync,
F: 'static + Future<Output = Result<M::Response>>,
{
self.add_message_handler_impl(model, move |handle, envelope, this, cx| {
self.add_message_handler_impl(entity, move |handle, envelope, this, cx| {
Self::respond_to_request(envelope.receipt(), handler(handle, envelope, cx), this)
})
}
@@ -1124,31 +1124,11 @@ impl Client {
match url_scheme {
Https => {
let client_config = {
let mut root_store = rustls::RootCertStore::empty();
let root_certs = rustls_native_certs::load_native_certs();
for error in root_certs.errors {
log::warn!("error loading native certs: {:?}", error);
}
root_store.add_parsable_certificates(
&root_certs
.certs
.into_iter()
.map(|cert| cert.as_ref().to_owned())
.collect::<Vec<_>>(),
);
rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth()
};
let (stream, _) =
async_tungstenite::async_tls::client_async_tls_with_connector(
request,
stream,
Some(client_config.into()),
Some(http_client::tls_config().into()),
)
.await?;
Ok(Connection::new(
@@ -1948,9 +1928,9 @@ mod tests {
let (done_tx1, done_rx1) = smol::channel::unbounded();
let (done_tx2, done_rx2) = smol::channel::unbounded();
AnyProtoClient::from(client.clone()).add_model_message_handler(
move |model: Entity<TestModel>, _: TypedEnvelope<proto::JoinProject>, mut cx| {
match model.update(&mut cx, |model, _| model.id).unwrap() {
AnyProtoClient::from(client.clone()).add_entity_message_handler(
move |entity: Entity<TestEntity>, _: TypedEnvelope<proto::JoinProject>, mut cx| {
match entity.update(&mut cx, |entity, _| entity.id).unwrap() {
1 => done_tx1.try_send(()).unwrap(),
2 => done_tx2.try_send(()).unwrap(),
_ => unreachable!(),
@@ -1958,15 +1938,15 @@ mod tests {
async { Ok(()) }
},
);
let model1 = cx.new(|_| TestModel {
let entity1 = cx.new(|_| TestEntity {
id: 1,
subscription: None,
});
let model2 = cx.new(|_| TestModel {
let entity2 = cx.new(|_| TestEntity {
id: 2,
subscription: None,
});
let model3 = cx.new(|_| TestModel {
let entity3 = cx.new(|_| TestEntity {
id: 3,
subscription: None,
});
@@ -1974,17 +1954,17 @@ mod tests {
let _subscription1 = client
.subscribe_to_entity(1)
.unwrap()
.set_model(&model1, &mut cx.to_async());
.set_entity(&entity1, &mut cx.to_async());
let _subscription2 = client
.subscribe_to_entity(2)
.unwrap()
.set_model(&model2, &mut cx.to_async());
.set_entity(&entity2, &mut cx.to_async());
// Ensure dropping a subscription for the same entity type still allows receiving of
// messages for other entity IDs of the same type.
let subscription3 = client
.subscribe_to_entity(3)
.unwrap()
.set_model(&model3, &mut cx.to_async());
.set_entity(&entity3, &mut cx.to_async());
drop(subscription3);
server.send(proto::JoinProject { project_id: 1 });
@@ -2006,11 +1986,11 @@ mod tests {
});
let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.new(|_| TestModel::default());
let entity = cx.new(|_| TestEntity::default());
let (done_tx1, _done_rx1) = smol::channel::unbounded();
let (done_tx2, done_rx2) = smol::channel::unbounded();
let subscription1 = client.add_message_handler(
model.downgrade(),
entity.downgrade(),
move |_, _: TypedEnvelope<proto::Ping>, _| {
done_tx1.try_send(()).unwrap();
async { Ok(()) }
@@ -2018,7 +1998,7 @@ mod tests {
);
drop(subscription1);
let _subscription2 = client.add_message_handler(
model.downgrade(),
entity.downgrade(),
move |_, _: TypedEnvelope<proto::Ping>, _| {
done_tx2.try_send(()).unwrap();
async { Ok(()) }
@@ -2041,27 +2021,27 @@ mod tests {
});
let server = FakeServer::for_client(user_id, &client, cx).await;
let model = cx.new(|_| TestModel::default());
let entity = cx.new(|_| TestEntity::default());
let (done_tx, done_rx) = smol::channel::unbounded();
let subscription = client.add_message_handler(
model.clone().downgrade(),
move |model: Entity<TestModel>, _: TypedEnvelope<proto::Ping>, mut cx| {
model
.update(&mut cx, |model, _| model.subscription.take())
entity.clone().downgrade(),
move |entity: Entity<TestEntity>, _: TypedEnvelope<proto::Ping>, mut cx| {
entity
.update(&mut cx, |entity, _| entity.subscription.take())
.unwrap();
done_tx.try_send(()).unwrap();
async { Ok(()) }
},
);
model.update(cx, |model, _| {
model.subscription = Some(subscription);
entity.update(cx, |entity, _| {
entity.subscription = Some(subscription);
});
server.send(proto::Ping {});
done_rx.recv().await.unwrap();
}
#[derive(Default)]
struct TestModel {
struct TestEntity {
id: usize,
subscription: Option<Subscription>,
}

View File

@@ -3,7 +3,6 @@ mod event_coalescer;
use crate::TelemetrySettings;
use anyhow::Result;
use clock::SystemClock;
use collections::{HashMap, HashSet};
use futures::channel::mpsc;
use futures::{Future, StreamExt};
use gpui::{App, BackgroundExecutor, Task};
@@ -12,14 +11,13 @@ use parking_lot::Mutex;
use release_channel::ReleaseChannel;
use settings::{Settings, SettingsStore};
use sha2::{Digest, Sha256};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;
use std::sync::LazyLock;
use std::time::Instant;
use std::{env, mem, path::PathBuf, sync::Arc, time::Duration};
use telemetry_events::{
AppEvent, AssistantEvent, AssistantPhase, EditEvent, Event, EventRequestBody, EventWrapper,
};
use telemetry_events::{AssistantEvent, AssistantPhase, Event, EventRequestBody, EventWrapper};
use util::{ResultExt, TryFutureExt};
use worktree::{UpdatedEntriesSet, WorktreeId};
@@ -285,7 +283,7 @@ impl Telemetry {
// TestAppContext ends up calling this function on shutdown and it panics when trying to find the TelemetrySettings
#[cfg(not(any(test, feature = "test-support")))]
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
self.report_app_event("close".to_string());
telemetry::event!("App Closed");
// TODO: close final edit period and make sure it's sent
Task::ready(())
}
@@ -355,30 +353,23 @@ impl Telemetry {
);
}
pub fn report_app_event(self: &Arc<Self>, operation: String) -> Event {
let event = Event::App(AppEvent { operation });
self.report_event(event.clone());
event
}
pub fn log_edit_event(self: &Arc<Self>, environment: &'static str, is_via_ssh: bool) {
let mut state = self.state.lock();
let period_data = state.event_coalescer.log_event(environment);
drop(state);
if let Some((start, end, environment)) = period_data {
let event = Event::Edit(EditEvent {
duration: end
.saturating_duration_since(start)
.min(Duration::from_secs(60 * 60 * 24))
.as_millis() as i64,
environment: environment.to_string(),
is_via_ssh,
});
let duration = end
.saturating_duration_since(start)
.min(Duration::from_secs(60 * 60 * 24))
.as_millis() as i64;
self.report_event(event);
telemetry::event!(
"Editor Edited",
duration = duration,
environment = environment.to_string(),
is_via_ssh = is_via_ssh
);
}
}
@@ -422,9 +413,8 @@ impl Telemetry {
.collect()
};
// Done on purpose to avoid calling `self.state.lock()` multiple times
for project_type_name in project_type_names {
self.report_app_event(format!("open {} project", project_type_name));
telemetry::event!("Project Opened", project_type = project_type_name);
}
}
@@ -590,6 +580,7 @@ mod tests {
use clock::FakeSystemClock;
use gpui::TestAppContext;
use http_client::FakeHttpClient;
use telemetry_events::FlexibleEvent;
#[gpui::test]
fn test_telemetry_flush_on_max_queue_size(cx: &mut TestAppContext) {
@@ -609,15 +600,17 @@ mod tests {
assert!(is_empty_state(&telemetry));
let first_date_time = clock.utc_now();
let operation = "test".to_string();
let event_properties = HashMap::from_iter([(
"test_key".to_string(),
serde_json::Value::String("test_value".to_string()),
)]);
let event = telemetry.report_app_event(operation.clone());
assert_eq!(
event,
Event::App(AppEvent {
operation: operation.clone(),
})
);
let event = FlexibleEvent {
event_type: "test".to_string(),
event_properties,
};
telemetry.report_event(Event::Flexible(event.clone()));
assert_eq!(telemetry.state.lock().events_queue.len(), 1);
assert!(telemetry.state.lock().flush_events_task.is_some());
assert_eq!(
@@ -627,13 +620,7 @@ mod tests {
clock.advance(Duration::from_millis(100));
let event = telemetry.report_app_event(operation.clone());
assert_eq!(
event,
Event::App(AppEvent {
operation: operation.clone(),
})
);
telemetry.report_event(Event::Flexible(event.clone()));
assert_eq!(telemetry.state.lock().events_queue.len(), 2);
assert!(telemetry.state.lock().flush_events_task.is_some());
assert_eq!(
@@ -643,13 +630,7 @@ mod tests {
clock.advance(Duration::from_millis(100));
let event = telemetry.report_app_event(operation.clone());
assert_eq!(
event,
Event::App(AppEvent {
operation: operation.clone(),
})
);
telemetry.report_event(Event::Flexible(event.clone()));
assert_eq!(telemetry.state.lock().events_queue.len(), 3);
assert!(telemetry.state.lock().flush_events_task.is_some());
assert_eq!(
@@ -660,14 +641,7 @@ mod tests {
clock.advance(Duration::from_millis(100));
// Adding a 4th event should cause a flush
let event = telemetry.report_app_event(operation.clone());
assert_eq!(
event,
Event::App(AppEvent {
operation: operation.clone(),
})
);
telemetry.report_event(Event::Flexible(event));
assert!(is_empty_state(&telemetry));
});
}
@@ -690,17 +664,19 @@ mod tests {
telemetry.start(system_id, installation_id, session_id, cx);
assert!(is_empty_state(&telemetry));
let first_date_time = clock.utc_now();
let operation = "test".to_string();
let event = telemetry.report_app_event(operation.clone());
assert_eq!(
event,
Event::App(AppEvent {
operation: operation.clone(),
})
);
let event_properties = HashMap::from_iter([(
"test_key".to_string(),
serde_json::Value::String("test_value".to_string()),
)]);
let event = FlexibleEvent {
event_type: "test".to_string(),
event_properties,
};
telemetry.report_event(Event::Flexible(event));
assert_eq!(telemetry.state.lock().events_queue.len(), 1);
assert!(telemetry.state.lock().flush_events_task.is_some());
assert_eq!(

View File

@@ -201,9 +201,8 @@ impl UserStore {
cx.update(|cx| {
if let Some(info) = info {
let disable_staff = std::env::var("ZED_DISABLE_STAFF")
.map_or(false, |v| !v.is_empty() && v != "0");
let staff = info.staff && !disable_staff;
let staff =
info.staff && !*feature_flags::ZED_DISABLE_STAFF;
cx.update_flags(staff, info.flags);
client.telemetry.set_authenticated_user_info(
Some(info.metrics_id.clone()),

View File

@@ -33,6 +33,7 @@ clock.workspace = true
collections.workspace = true
dashmap.workspace = true
derive_more.workspace = true
buffer_diff.workspace = true
envy = "0.4.2"
futures.workspace = true
google_ai.workspace = true
@@ -130,7 +131,7 @@ worktree = { workspace = true, features = ["test-support"] }
livekit_client_macos = { workspace = true, features = ["test-support"] }
[target.'cfg(not(target_os = "macos"))'.dev-dependencies]
livekit_client = {workspace = true, features = ["test-support"] }
livekit_client = { workspace = true, features = ["test-support"] }
[package.metadata.cargo-machete]
ignored = ["async-stripe"]

View File

@@ -100,6 +100,8 @@ CREATE TABLE "worktree_repositories" (
"branch" VARCHAR,
"scan_id" INTEGER NOT NULL,
"is_deleted" BOOL NOT NULL,
"current_merge_conflicts" VARCHAR,
"branch_summary" VARCHAR,
PRIMARY KEY(project_id, worktree_id, work_directory_id),
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE,
FOREIGN KEY(project_id, worktree_id, work_directory_id) REFERENCES worktree_entries (project_id, worktree_id, id) ON DELETE CASCADE
@@ -401,6 +403,15 @@ CREATE TABLE extension_versions (
schema_version INTEGER NOT NULL DEFAULT 0,
wasm_api_version TEXT,
download_count INTEGER NOT NULL DEFAULT 0,
provides_themes BOOLEAN NOT NULL DEFAULT FALSE,
provides_icon_themes BOOLEAN NOT NULL DEFAULT FALSE,
provides_languages BOOLEAN NOT NULL DEFAULT FALSE,
provides_grammars BOOLEAN NOT NULL DEFAULT FALSE,
provides_language_servers BOOLEAN NOT NULL DEFAULT FALSE,
provides_context_servers BOOLEAN NOT NULL DEFAULT FALSE,
provides_slash_commands BOOLEAN NOT NULL DEFAULT FALSE,
provides_indexed_docs_providers BOOLEAN NOT NULL DEFAULT FALSE,
provides_snippets BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (extension_id, version)
);
@@ -430,6 +441,7 @@ CREATE TABLE IF NOT EXISTS billing_customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL REFERENCES users(id),
has_overdue_invoices BOOLEAN NOT NULL DEFAULT FALSE,
stripe_customer_id TEXT NOT NULL
);

View File

@@ -0,0 +1,2 @@
alter table billing_customers
add column has_overdue_invoices bool not null default false;

View File

@@ -0,0 +1,10 @@
alter table extension_versions
add column provides_themes bool not null default false,
add column provides_icon_themes bool not null default false,
add column provides_languages bool not null default false,
add column provides_grammars bool not null default false,
add column provides_language_servers bool not null default false,
add column provides_context_servers bool not null default false,
add column provides_slash_commands bool not null default false,
add column provides_indexed_docs_providers bool not null default false,
add column provides_snippets bool not null default false;

View File

@@ -0,0 +1,2 @@
ALTER TABLE worktree_repositories
ADD COLUMN current_merge_conflicts VARCHAR NULL;

View File

@@ -0,0 +1,2 @@
ALTER TABLE worktree_repositories
ADD COLUMN worktree_repositories VARCHAR NULL;

View File

@@ -0,0 +1 @@
ALTER TABLE worktree_repositories ADD COLUMN branch_summary TEXT NULL;

View File

@@ -249,29 +249,31 @@ async fn create_billing_subscription(
));
}
if app.db.has_overdue_billing_subscriptions(user.id).await? {
return Err(Error::http(
StatusCode::PAYMENT_REQUIRED,
"user has overdue billing subscriptions".into(),
));
let existing_billing_customer = app.db.get_billing_customer_by_user_id(user.id).await?;
if let Some(existing_billing_customer) = &existing_billing_customer {
if existing_billing_customer.has_overdue_invoices {
return Err(Error::http(
StatusCode::PAYMENT_REQUIRED,
"user has overdue invoices".into(),
));
}
}
let customer_id =
if let Some(existing_customer) = app.db.get_billing_customer_by_user_id(user.id).await? {
CustomerId::from_str(&existing_customer.stripe_customer_id)
.context("failed to parse customer ID")?
} else {
let customer = Customer::create(
&stripe_client,
CreateCustomer {
email: user.email_address.as_deref(),
..Default::default()
},
)
.await?;
let customer_id = if let Some(existing_customer) = existing_billing_customer {
CustomerId::from_str(&existing_customer.stripe_customer_id)
.context("failed to parse customer ID")?
} else {
let customer = Customer::create(
&stripe_client,
CreateCustomer {
email: user.email_address.as_deref(),
..Default::default()
},
)
.await?;
customer.id
};
customer.id
};
let default_model = llm_db.model(rpc::LanguageModelProvider::Anthropic, "claude-3-5-sonnet")?;
let stripe_model = stripe_billing.register_model(default_model).await?;
@@ -666,6 +668,27 @@ async fn handle_customer_subscription_event(
.await?
.ok_or_else(|| anyhow!("billing customer not found"))?;
let was_canceled_due_to_payment_failure = subscription.status == SubscriptionStatus::Canceled
&& subscription
.cancellation_details
.as_ref()
.and_then(|details| details.reason)
.map_or(false, |reason| {
reason == CancellationDetailsReason::PaymentFailed
});
if was_canceled_due_to_payment_failure {
app.db
.update_billing_customer(
billing_customer.id,
&UpdateBillingCustomerParams {
has_overdue_invoices: ActiveValue::set(true),
..Default::default()
},
)
.await?;
}
if let Some(existing_subscription) = app
.db
.get_billing_subscription_by_stripe_subscription_id(&subscription.id)

View File

@@ -495,6 +495,10 @@ fn for_snowflake(
body.events.into_iter().flat_map(move |event| {
let timestamp =
first_event_at + Duration::milliseconds(event.milliseconds_since_first_event);
// We will need to double check, but I believe all of the events that
// are being transformed here are now migrated over to use the
// telemetry::event! macro, as of this commit so this code can go away
// when we feel enough users have upgraded past this point.
let (event_type, mut event_properties) = match &event.event {
Event::Editor(e) => (
match e.operation.as_str() {
@@ -506,7 +510,7 @@ fn for_snowflake(
),
Event::InlineCompletion(e) => (
format!(
"Inline Completion {}",
"Edit Prediction {}",
if e.suggestion_accepted {
"Accepted"
} else {
@@ -516,7 +520,7 @@ fn for_snowflake(
serde_json::to_value(e).unwrap(),
),
Event::InlineCompletionRating(e) => (
"Inline Completion Rated".to_string(),
"Edit Prediction Rated".to_string(),
serde_json::to_value(e).unwrap(),
),
Event::Call(e) => {

View File

@@ -9,10 +9,11 @@ use axum::{
routing::get,
Extension, Json, Router,
};
use collections::HashMap;
use rpc::{ExtensionApiManifest, GetExtensionsResponse};
use collections::{BTreeSet, HashMap};
use rpc::{ExtensionApiManifest, ExtensionProvides, GetExtensionsResponse};
use semantic_version::SemanticVersion;
use serde::Deserialize;
use std::str::FromStr;
use std::{sync::Arc, time::Duration};
use time::PrimitiveDateTime;
use util::{maybe, ResultExt};
@@ -35,6 +36,14 @@ pub fn router() -> Router {
#[derive(Debug, Deserialize)]
struct GetExtensionsParams {
filter: Option<String>,
/// A comma-delimited list of features that the extension must provide.
///
/// For example:
/// - `themes`
/// - `themes,icon-themes`
/// - `languages,language-servers`
#[serde(default)]
provides: Option<String>,
#[serde(default)]
max_schema_version: i32,
}
@@ -43,9 +52,22 @@ async fn get_extensions(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<GetExtensionsParams>,
) -> Result<Json<GetExtensionsResponse>> {
let provides_filter = params.provides.map(|provides| {
provides
.split(',')
.map(|value| value.trim())
.filter_map(|value| ExtensionProvides::from_str(value).ok())
.collect::<BTreeSet<_>>()
});
let mut extensions = app
.db
.get_extensions(params.filter.as_deref(), params.max_schema_version, 500)
.get_extensions(
params.filter.as_deref(),
provides_filter.as_ref(),
params.max_schema_version,
500,
)
.await?;
if let Some(filter) = params.filter.as_deref() {
@@ -391,6 +413,7 @@ async fn fetch_extension_manifest(
repository: manifest.repository,
schema_version: manifest.schema_version.unwrap_or(0),
wasm_api_version: manifest.wasm_api_version,
provides: manifest.provides,
published_at,
})
}

View File

@@ -6,10 +6,11 @@ pub mod tests;
use crate::{executor::Executor, Error, Result};
use anyhow::anyhow;
use collections::{BTreeMap, HashMap, HashSet};
use collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use dashmap::DashMap;
use futures::StreamExt;
use rand::{prelude::StdRng, Rng, SeedableRng};
use rpc::ExtensionProvides;
use rpc::{
proto::{self},
ConnectionId, ExtensionMetadata,
@@ -781,6 +782,7 @@ pub struct NewExtensionVersion {
pub repository: String,
pub schema_version: i32,
pub wasm_api_version: Option<String>,
pub provides: BTreeSet<ExtensionProvides>,
pub published_at: PrimitiveDateTime,
}

View File

@@ -10,6 +10,7 @@ pub struct CreateBillingCustomerParams {
pub struct UpdateBillingCustomerParams {
pub user_id: ActiveValue<UserId>,
pub stripe_customer_id: ActiveValue<String>,
pub has_overdue_invoices: ActiveValue<bool>,
}
impl Database {
@@ -43,6 +44,7 @@ impl Database {
id: ActiveValue::set(id),
user_id: params.user_id.clone(),
stripe_customer_id: params.stripe_customer_id.clone(),
has_overdue_invoices: params.has_overdue_invoices.clone(),
..Default::default()
})
.exec(&*tx)

View File

@@ -170,40 +170,4 @@ impl Database {
})
.await
}
/// Returns whether the user has any overdue billing subscriptions.
pub async fn has_overdue_billing_subscriptions(&self, user_id: UserId) -> Result<bool> {
Ok(self.count_overdue_billing_subscriptions(user_id).await? > 0)
}
/// Returns the count of the overdue billing subscriptions for the user with the specified ID.
///
/// This includes subscriptions:
/// - Whose status is `past_due`
/// - Whose status is `canceled` and the cancellation reason is `payment_failed`
pub async fn count_overdue_billing_subscriptions(&self, user_id: UserId) -> Result<usize> {
self.transaction(|tx| async move {
let past_due = billing_subscription::Column::StripeSubscriptionStatus
.eq(StripeSubscriptionStatus::PastDue);
let payment_failed = billing_subscription::Column::StripeSubscriptionStatus
.eq(StripeSubscriptionStatus::Canceled)
.and(
billing_subscription::Column::StripeCancellationReason
.eq(StripeCancellationReason::PaymentFailed),
);
let count = billing_subscription::Entity::find()
.inner_join(billing_customer::Entity)
.filter(
billing_customer::Column::UserId
.eq(user_id)
.and(past_due.or(payment_failed)),
)
.count(&*tx)
.await?;
Ok(count as usize)
})
.await
}
}

View File

@@ -10,6 +10,7 @@ impl Database {
pub async fn get_extensions(
&self,
filter: Option<&str>,
provides_filter: Option<&BTreeSet<ExtensionProvides>>,
max_schema_version: i32,
limit: usize,
) -> Result<Vec<ExtensionMetadata>> {
@@ -26,6 +27,10 @@ impl Database {
condition = condition.add(Expr::cust_with_expr("name ILIKE $1", fuzzy_name_filter));
}
if let Some(provides_filter) = provides_filter {
condition = apply_provides_filter(condition, provides_filter);
}
self.get_extensions_where(condition, Some(limit as u64), &tx)
.await
})
@@ -282,6 +287,39 @@ impl Database {
description: ActiveValue::Set(version.description.clone()),
schema_version: ActiveValue::Set(version.schema_version),
wasm_api_version: ActiveValue::Set(version.wasm_api_version.clone()),
provides_themes: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Themes),
),
provides_icon_themes: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::IconThemes),
),
provides_languages: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Languages),
),
provides_grammars: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Grammars),
),
provides_language_servers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::LanguageServers),
),
provides_context_servers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::ContextServers),
),
provides_slash_commands: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::SlashCommands),
),
provides_indexed_docs_providers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::IndexedDocsProviders),
),
provides_snippets: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Snippets),
),
download_count: ActiveValue::NotSet,
}
}))
@@ -352,10 +390,55 @@ impl Database {
}
}
fn apply_provides_filter(
mut condition: Condition,
provides_filter: &BTreeSet<ExtensionProvides>,
) -> Condition {
if provides_filter.contains(&ExtensionProvides::Themes) {
condition = condition.add(extension_version::Column::ProvidesThemes.eq(true));
}
if provides_filter.contains(&ExtensionProvides::IconThemes) {
condition = condition.add(extension_version::Column::ProvidesIconThemes.eq(true));
}
if provides_filter.contains(&ExtensionProvides::Languages) {
condition = condition.add(extension_version::Column::ProvidesLanguages.eq(true));
}
if provides_filter.contains(&ExtensionProvides::Grammars) {
condition = condition.add(extension_version::Column::ProvidesGrammars.eq(true));
}
if provides_filter.contains(&ExtensionProvides::LanguageServers) {
condition = condition.add(extension_version::Column::ProvidesLanguageServers.eq(true));
}
if provides_filter.contains(&ExtensionProvides::ContextServers) {
condition = condition.add(extension_version::Column::ProvidesContextServers.eq(true));
}
if provides_filter.contains(&ExtensionProvides::SlashCommands) {
condition = condition.add(extension_version::Column::ProvidesSlashCommands.eq(true));
}
if provides_filter.contains(&ExtensionProvides::IndexedDocsProviders) {
condition = condition.add(extension_version::Column::ProvidesIndexedDocsProviders.eq(true));
}
if provides_filter.contains(&ExtensionProvides::Snippets) {
condition = condition.add(extension_version::Column::ProvidesSnippets.eq(true));
}
condition
}
fn metadata_from_extension_and_version(
extension: extension::Model,
version: extension_version::Model,
) -> ExtensionMetadata {
let provides = version.provides();
ExtensionMetadata {
id: extension.external_id.into(),
manifest: rpc::ExtensionApiManifest {
@@ -370,6 +453,7 @@ fn metadata_from_extension_and_version(
repository: version.repository,
schema_version: Some(version.schema_version),
wasm_api_version: version.wasm_api_version,
provides,
},
published_at: convert_time_to_chrono(version.published_at),

View File

@@ -326,13 +326,26 @@ impl Database {
if !update.updated_repositories.is_empty() {
worktree_repository::Entity::insert_many(update.updated_repositories.iter().map(
|repository| worktree_repository::ActiveModel {
project_id: ActiveValue::set(project_id),
worktree_id: ActiveValue::set(worktree_id),
work_directory_id: ActiveValue::set(repository.work_directory_id as i64),
scan_id: ActiveValue::set(update.scan_id as i64),
branch: ActiveValue::set(repository.branch.clone()),
is_deleted: ActiveValue::set(false),
|repository| {
worktree_repository::ActiveModel {
project_id: ActiveValue::set(project_id),
worktree_id: ActiveValue::set(worktree_id),
work_directory_id: ActiveValue::set(
repository.work_directory_id as i64,
),
scan_id: ActiveValue::set(update.scan_id as i64),
branch: ActiveValue::set(repository.branch.clone()),
is_deleted: ActiveValue::set(false),
branch_summary: ActiveValue::Set(
repository
.branch_summary
.as_ref()
.map(|summary| serde_json::to_string(summary).unwrap()),
),
current_merge_conflicts: ActiveValue::Set(Some(
serde_json::to_string(&repository.current_merge_conflicts).unwrap(),
)),
}
},
))
.on_conflict(
@@ -344,6 +357,8 @@ impl Database {
.update_columns([
worktree_repository::Column::ScanId,
worktree_repository::Column::Branch,
worktree_repository::Column::BranchSummary,
worktree_repository::Column::CurrentMergeConflicts,
])
.to_owned(),
)
@@ -769,6 +784,20 @@ impl Database {
updated_statuses.push(db_status_to_proto(status_entry)?);
}
let current_merge_conflicts = db_repository_entry
.current_merge_conflicts
.as_ref()
.map(|conflicts| serde_json::from_str(&conflicts))
.transpose()?
.unwrap_or_default();
let branch_summary = db_repository_entry
.branch_summary
.as_ref()
.map(|branch_summary| serde_json::from_str(&branch_summary))
.transpose()?
.unwrap_or_default();
worktree.repository_entries.insert(
db_repository_entry.work_directory_id as u64,
proto::RepositoryEntry {
@@ -776,6 +805,8 @@ impl Database {
branch: db_repository_entry.branch,
updated_statuses,
removed_statuses: Vec::new(),
current_merge_conflicts,
branch_summary,
},
);
}

View File

@@ -736,11 +736,27 @@ impl Database {
}
}
let current_merge_conflicts = db_repository
.current_merge_conflicts
.as_ref()
.map(|conflicts| serde_json::from_str(&conflicts))
.transpose()?
.unwrap_or_default();
let branch_summary = db_repository
.branch_summary
.as_ref()
.map(|branch_summary| serde_json::from_str(&branch_summary))
.transpose()?
.unwrap_or_default();
worktree.updated_repositories.push(proto::RepositoryEntry {
work_directory_id: db_repository.work_directory_id as u64,
branch: db_repository.branch,
updated_statuses,
removed_statuses,
current_merge_conflicts,
branch_summary,
});
}
}

View File

@@ -133,26 +133,23 @@ impl Database {
initial_channel_id: Option<ChannelId>,
tx: &DatabaseTransaction,
) -> Result<User> {
if let Some(user_by_github_user_id) = user::Entity::find()
.filter(user::Column::GithubUserId.eq(github_user_id))
.one(tx)
if let Some(existing_user) = self
.get_user_by_github_user_id_or_github_login(github_user_id, github_login, tx)
.await?
{
let mut user_by_github_user_id = user_by_github_user_id.into_active_model();
user_by_github_user_id.github_login = ActiveValue::set(github_login.into());
user_by_github_user_id.github_user_created_at =
ActiveValue::set(Some(github_user_created_at));
Ok(user_by_github_user_id.update(tx).await?)
} else if let Some(user_by_github_login) = user::Entity::find()
.filter(user::Column::GithubLogin.eq(github_login))
.one(tx)
.await?
{
let mut user_by_github_login = user_by_github_login.into_active_model();
user_by_github_login.github_user_id = ActiveValue::set(github_user_id);
user_by_github_login.github_user_created_at =
ActiveValue::set(Some(github_user_created_at));
Ok(user_by_github_login.update(tx).await?)
let mut existing_user = existing_user.into_active_model();
existing_user.github_login = ActiveValue::set(github_login.into());
existing_user.github_user_created_at = ActiveValue::set(Some(github_user_created_at));
if let Some(github_email) = github_email {
existing_user.email_address = ActiveValue::set(Some(github_email.into()));
}
if let Some(github_name) = github_name {
existing_user.name = ActiveValue::set(Some(github_name.into()));
}
Ok(existing_user.update(tx).await?)
} else {
let user = user::Entity::insert(user::ActiveModel {
email_address: ActiveValue::set(github_email.map(|email| email.into())),
@@ -183,6 +180,34 @@ impl Database {
}
}
/// Tries to retrieve a user, first by their GitHub user ID, and then by their GitHub login.
///
/// Returns `None` if a user is not found with this GitHub user ID or GitHub login.
pub async fn get_user_by_github_user_id_or_github_login(
&self,
github_user_id: i32,
github_login: &str,
tx: &DatabaseTransaction,
) -> Result<Option<User>> {
if let Some(user_by_github_user_id) = user::Entity::find()
.filter(user::Column::GithubUserId.eq(github_user_id))
.one(tx)
.await?
{
return Ok(Some(user_by_github_user_id));
}
if let Some(user_by_github_login) = user::Entity::find()
.filter(user::Column::GithubLogin.eq(github_login))
.one(tx)
.await?
{
return Ok(Some(user_by_github_login));
}
Ok(None)
}
/// get_all_users returns the next page of users. To get more call again with
/// the same limit and the page incremented by 1.
pub async fn get_all_users(&self, page: u32, limit: u32) -> Result<Vec<User>> {

View File

@@ -9,6 +9,7 @@ pub struct Model {
pub id: BillingCustomerId,
pub user_id: UserId,
pub stripe_customer_id: String,
pub has_overdue_invoices: bool,
pub created_at: DateTime,
}

View File

@@ -1,4 +1,6 @@
use crate::db::ExtensionId;
use collections::BTreeSet;
use rpc::ExtensionProvides;
use sea_orm::entity::prelude::*;
use time::PrimitiveDateTime;
@@ -16,6 +18,58 @@ pub struct Model {
pub schema_version: i32,
pub wasm_api_version: Option<String>,
pub download_count: i64,
pub provides_themes: bool,
pub provides_icon_themes: bool,
pub provides_languages: bool,
pub provides_grammars: bool,
pub provides_language_servers: bool,
pub provides_context_servers: bool,
pub provides_slash_commands: bool,
pub provides_indexed_docs_providers: bool,
pub provides_snippets: bool,
}
impl Model {
pub fn provides(&self) -> BTreeSet<ExtensionProvides> {
let mut provides = BTreeSet::default();
if self.provides_themes {
provides.insert(ExtensionProvides::Themes);
}
if self.provides_icon_themes {
provides.insert(ExtensionProvides::IconThemes);
}
if self.provides_languages {
provides.insert(ExtensionProvides::Languages);
}
if self.provides_grammars {
provides.insert(ExtensionProvides::Grammars);
}
if self.provides_language_servers {
provides.insert(ExtensionProvides::LanguageServers);
}
if self.provides_context_servers {
provides.insert(ExtensionProvides::ContextServers);
}
if self.provides_slash_commands {
provides.insert(ExtensionProvides::SlashCommands);
}
if self.provides_indexed_docs_providers {
provides.insert(ExtensionProvides::IndexedDocsProviders);
}
if self.provides_snippets {
provides.insert(ExtensionProvides::Snippets);
}
provides
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View File

@@ -13,6 +13,10 @@ pub struct Model {
pub scan_id: i64,
pub branch: Option<String>,
pub is_deleted: bool,
// JSON array typed string
pub current_merge_conflicts: Option<String>,
// A JSON object representing the current Branch values
pub branch_summary: Option<String>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use crate::db::billing_subscription::{StripeCancellationReason, StripeSubscriptionStatus};
use crate::db::billing_subscription::StripeSubscriptionStatus;
use crate::db::tests::new_test_user;
use crate::db::{CreateBillingCustomerParams, CreateBillingSubscriptionParams};
use crate::test_both_dbs;
@@ -88,113 +88,3 @@ async fn test_get_active_billing_subscriptions(db: &Arc<Database>) {
assert_eq!(subscription_count, 0);
}
}
test_both_dbs!(
test_count_overdue_billing_subscriptions,
test_count_overdue_billing_subscriptions_postgres,
test_count_overdue_billing_subscriptions_sqlite
);
async fn test_count_overdue_billing_subscriptions(db: &Arc<Database>) {
// A user with no subscription has no overdue billing subscriptions.
{
let user_id = new_test_user(db, "no-subscription-user@example.com").await;
let subscription_count = db
.count_overdue_billing_subscriptions(user_id)
.await
.unwrap();
assert_eq!(subscription_count, 0);
}
// A user with a past-due subscription has an overdue billing subscription.
{
let user_id = new_test_user(db, "past-due-user@example.com").await;
let customer = db
.create_billing_customer(&CreateBillingCustomerParams {
user_id,
stripe_customer_id: "cus_past_due_user".into(),
})
.await
.unwrap();
assert_eq!(customer.stripe_customer_id, "cus_past_due_user".to_string());
db.create_billing_subscription(&CreateBillingSubscriptionParams {
billing_customer_id: customer.id,
stripe_subscription_id: "sub_past_due_user".into(),
stripe_subscription_status: StripeSubscriptionStatus::PastDue,
stripe_cancellation_reason: None,
})
.await
.unwrap();
let subscription_count = db
.count_overdue_billing_subscriptions(user_id)
.await
.unwrap();
assert_eq!(subscription_count, 1);
}
// A user with a canceled subscription with a reason of `payment_failed` has an overdue billing subscription.
{
let user_id =
new_test_user(db, "canceled-subscription-payment-failed-user@example.com").await;
let customer = db
.create_billing_customer(&CreateBillingCustomerParams {
user_id,
stripe_customer_id: "cus_canceled_subscription_payment_failed_user".into(),
})
.await
.unwrap();
assert_eq!(
customer.stripe_customer_id,
"cus_canceled_subscription_payment_failed_user".to_string()
);
db.create_billing_subscription(&CreateBillingSubscriptionParams {
billing_customer_id: customer.id,
stripe_subscription_id: "sub_canceled_subscription_payment_failed_user".into(),
stripe_subscription_status: StripeSubscriptionStatus::Canceled,
stripe_cancellation_reason: Some(StripeCancellationReason::PaymentFailed),
})
.await
.unwrap();
let subscription_count = db
.count_overdue_billing_subscriptions(user_id)
.await
.unwrap();
assert_eq!(subscription_count, 1);
}
// A user with a canceled subscription with a reason of `cancellation_requested` has no overdue billing subscriptions.
{
let user_id = new_test_user(db, "canceled-subscription-user@example.com").await;
let customer = db
.create_billing_customer(&CreateBillingCustomerParams {
user_id,
stripe_customer_id: "cus_canceled_subscription_user".into(),
})
.await
.unwrap();
assert_eq!(
customer.stripe_customer_id,
"cus_canceled_subscription_user".to_string()
);
db.create_billing_subscription(&CreateBillingSubscriptionParams {
billing_customer_id: customer.id,
stripe_subscription_id: "sub_canceled_subscription_user".into(),
stripe_subscription_status: StripeSubscriptionStatus::Canceled,
stripe_cancellation_reason: Some(StripeCancellationReason::CancellationRequested),
})
.await
.unwrap();
let subscription_count = db
.count_overdue_billing_subscriptions(user_id)
.await
.unwrap();
assert_eq!(subscription_count, 0);
}
}

View File

@@ -1,10 +1,14 @@
use std::collections::BTreeSet;
use std::sync::Arc;
use rpc::ExtensionProvides;
use super::Database;
use crate::db::ExtensionVersionConstraints;
use crate::{
db::{queries::extensions::convert_time_to_chrono, ExtensionMetadata, NewExtensionVersion},
test_both_dbs,
};
use std::sync::Arc;
test_both_dbs!(
test_extensions,
@@ -16,7 +20,7 @@ async fn test_extensions(db: &Arc<Database>) {
let versions = db.get_known_extension_versions().await.unwrap();
assert!(versions.is_empty());
let extensions = db.get_extensions(None, 1, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 1, 5).await.unwrap();
assert!(extensions.is_empty());
let t0 = time::OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
@@ -37,6 +41,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
},
NewExtensionVersion {
@@ -47,6 +52,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
},
],
@@ -61,6 +67,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@@ -83,7 +90,7 @@ async fn test_extensions(db: &Arc<Database>) {
);
// The latest version of each extension is returned.
let extensions = db.get_extensions(None, 1, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 1, 5).await.unwrap();
assert_eq!(
extensions,
&[
@@ -97,6 +104,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: Some(1),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 0,
@@ -111,6 +119,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: Some(0),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 0
@@ -119,7 +128,7 @@ async fn test_extensions(db: &Arc<Database>) {
);
// Extensions with too new of a schema version are excluded.
let extensions = db.get_extensions(None, 0, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 0, 5).await.unwrap();
assert_eq!(
extensions,
&[ExtensionMetadata {
@@ -132,6 +141,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: Some(0),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 0
@@ -158,7 +168,7 @@ async fn test_extensions(db: &Arc<Database>) {
.unwrap());
// Extensions are returned in descending order of total downloads.
let extensions = db.get_extensions(None, 1, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 1, 5).await.unwrap();
assert_eq!(
extensions,
&[
@@ -172,6 +182,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: Some(0),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 7
@@ -186,6 +197,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: Some(1),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 5,
@@ -207,6 +219,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@@ -220,6 +233,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@@ -244,7 +258,7 @@ async fn test_extensions(db: &Arc<Database>) {
.collect()
);
let extensions = db.get_extensions(None, 1, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 1, 5).await.unwrap();
assert_eq!(
extensions,
&[
@@ -258,6 +272,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: Some(0),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 7
@@ -272,6 +287,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: Some(1),
wasm_api_version: None,
provides: BTreeSet::default(),
},
published_at: t0_chrono,
download_count: 5,
@@ -290,7 +306,7 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
let versions = db.get_known_extension_versions().await.unwrap();
assert!(versions.is_empty());
let extensions = db.get_extensions(None, 1, 5).await.unwrap();
let extensions = db.get_extensions(None, None, 1, 5).await.unwrap();
assert!(extensions.is_empty());
let t0 = time::OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
@@ -311,6 +327,10 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
]),
published_at: t0,
},
NewExtensionVersion {
@@ -321,6 +341,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
published_at: t0,
},
NewExtensionVersion {
@@ -331,6 +356,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.5".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
published_at: t0,
},
],
@@ -345,6 +375,7 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@@ -378,6 +409,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: Some(1),
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
},
published_at: t0_chrono,
download_count: 0,

View File

@@ -309,7 +309,8 @@ impl Server {
.add_request_handler(forward_read_only_project_request::<proto::ResolveInlayHint>)
.add_request_handler(forward_read_only_project_request::<proto::OpenBufferByPath>)
.add_request_handler(forward_read_only_project_request::<proto::GitBranches>)
.add_request_handler(forward_read_only_project_request::<proto::GetStagedText>)
.add_request_handler(forward_read_only_project_request::<proto::OpenUnstagedDiff>)
.add_request_handler(forward_read_only_project_request::<proto::OpenUncommittedDiff>)
.add_request_handler(
forward_mutating_project_request::<proto::RegisterBufferWithLanguageServers>,
)
@@ -348,7 +349,7 @@ impl Server {
.add_message_handler(broadcast_project_message_from_host::<proto::UpdateBufferFile>)
.add_message_handler(broadcast_project_message_from_host::<proto::BufferReloaded>)
.add_message_handler(broadcast_project_message_from_host::<proto::BufferSaved>)
.add_message_handler(broadcast_project_message_from_host::<proto::UpdateDiffBase>)
.add_message_handler(broadcast_project_message_from_host::<proto::UpdateDiffBases>)
.add_request_handler(get_users)
.add_request_handler(fuzzy_search_users)
.add_request_handler(request_contact)
@@ -394,6 +395,10 @@ impl Server {
.add_request_handler(forward_mutating_project_request::<proto::Stage>)
.add_request_handler(forward_mutating_project_request::<proto::Unstage>)
.add_request_handler(forward_mutating_project_request::<proto::Commit>)
.add_request_handler(forward_read_only_project_request::<proto::GitShow>)
.add_request_handler(forward_read_only_project_request::<proto::GitReset>)
.add_request_handler(forward_mutating_project_request::<proto::SetIndexText>)
.add_request_handler(forward_mutating_project_request::<proto::OpenCommitMessageBuffer>)
.add_message_handler(broadcast_project_message_from_host::<proto::AdvertiseContexts>)
.add_message_handler(update_context)
.add_request_handler({

View File

@@ -342,7 +342,7 @@ async fn test_multiple_handles_to_channel_buffer(
future::try_join3(channel_buffer_1, channel_buffer_2, channel_buffer_3)
.await
.unwrap();
let channel_buffer_model_id = channel_buffer.entity_id();
let channel_buffer_entity_id = channel_buffer.entity_id();
assert_eq!(channel_buffer, channel_buffer_2);
assert_eq!(channel_buffer, channel_buffer_3);
@@ -366,7 +366,7 @@ async fn test_multiple_handles_to_channel_buffer(
.update(cx_a, |store, cx| store.open_channel_buffer(channel_id, cx))
.await
.unwrap();
assert_ne!(channel_buffer.entity_id(), channel_buffer_model_id);
assert_ne!(channel_buffer.entity_id(), channel_buffer_entity_id);
channel_buffer.update(cx_a, |buffer, cx| {
buffer.buffer().update(cx, |buffer, _| {
assert_eq!(buffer.text(), "hello");

View File

@@ -1991,10 +1991,9 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
.collect(),
remote_url: Some("git@github.com:zed-industries/zed.git".to_string()),
};
client_a.fs().set_blame_for_repo(
Path::new("/my-repo/.git"),
vec![(Path::new("file.txt"), blame)],
);
client_a
.fs()
.set_blame_for_repo(Path::new("/my-repo/.git"), vec![("file.txt".into(), blame)]);
let (project_a, worktree_id) = client_a.build_local_project("/my-repo", cx_a).await;
let project_id = active_call_a

View File

@@ -8,6 +8,7 @@ use crate::{
use anyhow::{anyhow, Result};
use assistant_context_editor::ContextStore;
use assistant_slash_command::SlashCommandWorkingSet;
use buffer_diff::{assert_hunks, DiffHunkSecondaryStatus, DiffHunkStatus};
use call::{room, ActiveCall, ParticipantLocation, Room};
use client::{User, RECEIVE_TIMEOUT};
use collections::{HashMap, HashSet};
@@ -2558,13 +2559,27 @@ async fn test_git_diff_base_change(
let project_remote = client_b.join_remote_project(project_id, cx_b).await;
let diff_base = "
let staged_text = "
one
three
"
.unindent();
let new_diff_base = "
let committed_text = "
one
TWO
three
"
.unindent();
let new_committed_text = "
one
TWO_HUNDRED
three
"
.unindent();
let new_staged_text = "
one
two
"
@@ -2572,7 +2587,11 @@ async fn test_git_diff_base_change(
client_a.fs().set_index_for_repo(
Path::new("/dir/.git"),
&[(Path::new("a.txt"), diff_base.clone())],
&[("a.txt".into(), staged_text.clone())],
);
client_a.fs().set_head_for_repo(
Path::new("/dir/.git"),
&[("a.txt".into(), committed_text.clone())],
);
// Create the buffer
@@ -2580,26 +2599,26 @@ async fn test_git_diff_base_change(
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
let change_set_local_a = project_local
let local_unstaged_diff_a = project_local
.update(cx_a, |p, cx| {
p.open_unstaged_changes(buffer_local_a.clone(), cx)
p.open_unstaged_diff(buffer_local_a.clone(), cx)
})
.await
.unwrap();
// Wait for it to catch up to the new diff
executor.run_until_parked();
change_set_local_a.read_with(cx_a, |change_set, cx| {
local_unstaged_diff_a.read_with(cx_a, |diff, cx| {
let buffer = buffer_local_a.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(diff_base.as_str())
diff.base_text_string().as_deref(),
Some(staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff_base,
&[(1..2, "", "two\n")],
&diff.base_text_string().unwrap(),
&[(1..2, "", "two\n", DiffHunkStatus::added())],
);
});
@@ -2608,73 +2627,123 @@ async fn test_git_diff_base_change(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
let change_set_remote_a = project_remote
let remote_unstaged_diff_a = project_remote
.update(cx_b, |p, cx| {
p.open_unstaged_changes(buffer_remote_a.clone(), cx)
p.open_unstaged_diff(buffer_remote_a.clone(), cx)
})
.await
.unwrap();
// Wait remote buffer to catch up to the new diff
executor.run_until_parked();
change_set_remote_a.read_with(cx_b, |change_set, cx| {
remote_unstaged_diff_a.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_a.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(diff_base.as_str())
diff.base_text_string().as_deref(),
Some(staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff_base,
&[(1..2, "", "two\n")],
&diff.base_text_string().unwrap(),
&[(1..2, "", "two\n", DiffHunkStatus::added())],
);
});
// Update the staged text of the open buffer
// Open uncommitted changes on the guest, without opening them on the host first
let remote_uncommitted_diff_a = project_remote
.update(cx_b, |p, cx| {
p.open_uncommitted_diff(buffer_remote_a.clone(), cx)
})
.await
.unwrap();
executor.run_until_parked();
remote_uncommitted_diff_a.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_a.read(cx);
assert_eq!(
diff.base_text_string().as_deref(),
Some(committed_text.as_str())
);
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff.base_text_string().unwrap(),
&[(
1..2,
"TWO\n",
"two\n",
DiffHunkStatus::Modified(DiffHunkSecondaryStatus::HasSecondaryHunk),
)],
);
});
// Update the index text of the open buffer
client_a.fs().set_index_for_repo(
Path::new("/dir/.git"),
&[(Path::new("a.txt"), new_diff_base.clone())],
&[("a.txt".into(), new_staged_text.clone())],
);
client_a.fs().set_head_for_repo(
Path::new("/dir/.git"),
&[("a.txt".into(), new_committed_text.clone())],
);
// Wait for buffer_local_a to receive it
executor.run_until_parked();
change_set_local_a.read_with(cx_a, |change_set, cx| {
local_unstaged_diff_a.read_with(cx_a, |diff, cx| {
let buffer = buffer_local_a.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(new_diff_base.as_str())
diff.base_text_string().as_deref(),
Some(new_staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&new_diff_base,
&[(2..3, "", "three\n")],
&diff.base_text_string().unwrap(),
&[(2..3, "", "three\n", DiffHunkStatus::added())],
);
});
change_set_remote_a.read_with(cx_b, |change_set, cx| {
remote_unstaged_diff_a.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_a.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(new_diff_base.as_str())
diff.base_text_string().as_deref(),
Some(new_staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&new_diff_base,
&[(2..3, "", "three\n")],
&diff.base_text_string().unwrap(),
&[(2..3, "", "three\n", DiffHunkStatus::added())],
);
});
remote_uncommitted_diff_a.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_a.read(cx);
assert_eq!(
diff.base_text_string().as_deref(),
Some(new_committed_text.as_str())
);
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff.base_text_string().unwrap(),
&[(
1..2,
"TWO_HUNDRED\n",
"two\n",
DiffHunkStatus::Modified(DiffHunkSecondaryStatus::OverlapsWithSecondaryHunk),
)],
);
});
// Nested git dir
let diff_base = "
let staged_text = "
one
three
"
.unindent();
let new_diff_base = "
let new_staged_text = "
one
two
"
@@ -2682,7 +2751,7 @@ async fn test_git_diff_base_change(
client_a.fs().set_index_for_repo(
Path::new("/dir/sub/.git"),
&[(Path::new("b.txt"), diff_base.clone())],
&[("b.txt".into(), staged_text.clone())],
);
// Create the buffer
@@ -2690,26 +2759,26 @@ async fn test_git_diff_base_change(
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "sub/b.txt"), cx))
.await
.unwrap();
let change_set_local_b = project_local
let local_unstaged_diff_b = project_local
.update(cx_a, |p, cx| {
p.open_unstaged_changes(buffer_local_b.clone(), cx)
p.open_unstaged_diff(buffer_local_b.clone(), cx)
})
.await
.unwrap();
// Wait for it to catch up to the new diff
executor.run_until_parked();
change_set_local_b.read_with(cx_a, |change_set, cx| {
local_unstaged_diff_b.read_with(cx_a, |diff, cx| {
let buffer = buffer_local_b.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(diff_base.as_str())
diff.base_text_string().as_deref(),
Some(staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff_base,
&[(1..2, "", "two\n")],
&diff.base_text_string().unwrap(),
&[(1..2, "", "two\n", DiffHunkStatus::added())],
);
});
@@ -2718,61 +2787,61 @@ async fn test_git_diff_base_change(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "sub/b.txt"), cx))
.await
.unwrap();
let change_set_remote_b = project_remote
let remote_unstaged_diff_b = project_remote
.update(cx_b, |p, cx| {
p.open_unstaged_changes(buffer_remote_b.clone(), cx)
p.open_unstaged_diff(buffer_remote_b.clone(), cx)
})
.await
.unwrap();
executor.run_until_parked();
change_set_remote_b.read_with(cx_b, |change_set, cx| {
remote_unstaged_diff_b.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_b.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(diff_base.as_str())
diff.base_text_string().as_deref(),
Some(staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&diff_base,
&[(1..2, "", "two\n")],
&staged_text,
&[(1..2, "", "two\n", DiffHunkStatus::added())],
);
});
// Update the staged text
// Updatet the staged text
client_a.fs().set_index_for_repo(
Path::new("/dir/sub/.git"),
&[(Path::new("b.txt"), new_diff_base.clone())],
&[("b.txt".into(), new_staged_text.clone())],
);
// Wait for buffer_local_b to receive it
executor.run_until_parked();
change_set_local_b.read_with(cx_a, |change_set, cx| {
local_unstaged_diff_b.read_with(cx_a, |diff, cx| {
let buffer = buffer_local_b.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(new_diff_base.as_str())
diff.base_text_string().as_deref(),
Some(new_staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&new_diff_base,
&[(2..3, "", "three\n")],
&new_staged_text,
&[(2..3, "", "three\n", DiffHunkStatus::added())],
);
});
change_set_remote_b.read_with(cx_b, |change_set, cx| {
remote_unstaged_diff_b.read_with(cx_b, |diff, cx| {
let buffer = buffer_remote_b.read(cx);
assert_eq!(
change_set.base_text_string().as_deref(),
Some(new_diff_base.as_str())
diff.base_text_string().as_deref(),
Some(new_staged_text.as_str())
);
git::diff::assert_hunks(
change_set.diff_to_buffer.hunks_in_row_range(0..4, buffer),
assert_hunks(
diff.hunks_in_row_range(0..4, buffer, cx),
buffer,
&new_diff_base,
&[(2..3, "", "three\n")],
&new_staged_text,
&[(2..3, "", "three\n", DiffHunkStatus::added())],
);
});
}
@@ -2826,7 +2895,10 @@ async fn test_git_branch_name(
assert_eq!(worktrees.len(), 1);
let worktree = worktrees[0].clone();
let root_entry = worktree.read(cx).snapshot().root_git_entry().unwrap();
assert_eq!(root_entry.branch(), branch_name.map(Into::into));
assert_eq!(
root_entry.branch().map(|branch| branch.name.to_string()),
branch_name
);
}
// Smoke test branch reading
@@ -6714,7 +6786,7 @@ async fn test_remote_git_branches(
})
});
assert_eq!(host_branch.as_ref(), branches[2]);
assert_eq!(host_branch.name, branches[2]);
// Also try creating a new branch
cx_b.update(|cx| {
@@ -6735,5 +6807,5 @@ async fn test_remote_git_branches(
})
});
assert_eq!(host_branch.as_ref(), "totally-new-branch");
assert_eq!(host_branch.name, "totally-new-branch");
}

View File

@@ -953,8 +953,8 @@ impl RandomizedTest for ProjectCollaborationTest {
let dot_git_dir = repo_path.join(".git");
let contents = contents
.iter()
.map(|(path, contents)| (path.as_path(), contents.clone()))
.into_iter()
.map(|(path, contents)| (path.into(), contents))
.collect::<Vec<_>>();
if client.fs().metadata(&dot_git_dir).await?.is_none() {
client.fs().create_dir(&dot_git_dir).await?;
@@ -1339,7 +1339,7 @@ impl RandomizedTest for ProjectCollaborationTest {
project
.buffer_store()
.read(cx)
.get_unstaged_changes(host_buffer.read(cx).remote_id())
.get_unstaged_diff(host_buffer.read(cx).remote_id(), cx)
.unwrap()
.read(cx)
.base_text_string()
@@ -1348,7 +1348,7 @@ impl RandomizedTest for ProjectCollaborationTest {
project
.buffer_store()
.read(cx)
.get_unstaged_changes(guest_buffer.read(cx).remote_id())
.get_unstaged_diff(guest_buffer.read(cx).remote_id(), cx)
.unwrap()
.read(cx)
.base_text_string()

View File

@@ -314,7 +314,7 @@ async fn test_ssh_collaboration_git_branches(
})
});
assert_eq!(server_branch.as_ref(), branches[2]);
assert_eq!(server_branch.name, branches[2]);
// Also try creating a new branch
cx_b.update(|cx| {
@@ -337,7 +337,7 @@ async fn test_ssh_collaboration_git_branches(
})
});
assert_eq!(server_branch.as_ref(), "totally-new-branch");
assert_eq!(server_branch.name, "totally-new-branch");
}
#[gpui::test]

View File

@@ -849,10 +849,10 @@ impl TestClient {
) -> (Entity<Workspace>, &'a mut VisualTestContext) {
let window = cx.update(|cx| cx.active_window().unwrap().downcast::<Workspace>().unwrap());
let model = window.root(cx).unwrap();
let entity = window.root(cx).unwrap();
let cx = VisualTestContext::from_window(*window.deref(), cx).as_mut();
// it might be nice to try and cleanup these at the end of each test.
(model, cx)
(entity, cx)
}
}
@@ -861,9 +861,9 @@ pub fn open_channel_notes(
cx: &mut VisualTestContext,
) -> Task<anyhow::Result<Entity<ChannelView>>> {
let window = cx.update(|_, cx| cx.active_window().unwrap().downcast::<Workspace>().unwrap());
let model = window.root(cx).unwrap();
let entity = window.root(cx).unwrap();
cx.update(|window, cx| ChannelView::open(channel_id, None, model.clone(), window, cx))
cx.update(|window, cx| ChannelView::open(channel_id, None, entity.clone(), window, cx))
}
impl Drop for TestClient {

View File

@@ -461,7 +461,7 @@ impl Item for ChannelView {
.child(
Label::new(channel_name)
.color(params.text_color())
.italic(params.preview),
.when(params.preview, |this| this.italic()),
)
.when_some(status, |element, status| {
element.child(

View File

@@ -97,14 +97,14 @@ impl ChatPanel {
});
cx.new(|cx| {
let model = cx.entity().downgrade();
let entity = cx.entity().downgrade();
let message_list = ListState::new(
0,
gpui::ListAlignment::Bottom,
px(1000.),
move |ix, window, cx| {
if let Some(model) = model.upgrade() {
model.update(cx, |this: &mut Self, cx| {
if let Some(entity) = entity.upgrade() {
entity.update(cx, |this: &mut Self, cx| {
this.render_message(ix, window, cx).into_any_element()
})
} else {

View File

@@ -239,14 +239,14 @@ impl CollabPanel {
)
.detach();
let model = cx.entity().downgrade();
let entity = cx.entity().downgrade();
let list_state = ListState::new(
0,
gpui::ListAlignment::Top,
px(1000.),
move |ix, window, cx| {
if let Some(model) = model.upgrade() {
model.update(cx, |this, cx| this.render_list_entry(ix, window, cx))
if let Some(entity) = entity.upgrade() {
entity.update(cx, |this, cx| this.render_list_entry(ix, window, cx))
} else {
div().into_any()
}

View File

@@ -110,13 +110,13 @@ impl NotificationPanel {
})
.detach();
let model = cx.entity().downgrade();
let entity = cx.entity().downgrade();
let notification_list =
ListState::new(0, ListAlignment::Top, px(1000.), move |ix, window, cx| {
model
entity
.upgrade()
.and_then(|model| {
model.update(cx, |this, cx| this.render_notification(ix, window, cx))
.and_then(|entity| {
entity.update(cx, |this, cx| this.render_notification(ix, window, cx))
})
.unwrap_or_else(|| div().into_any())
});
@@ -323,9 +323,9 @@ impl NotificationPanel {
.justify_end()
.child(Button::new("decline", "Decline").on_click({
let notification = notification.clone();
let model = cx.entity().clone();
let entity = cx.entity().clone();
move |_, _, cx| {
model.update(cx, |this, cx| {
entity.update(cx, |this, cx| {
this.respond_to_notification(
notification.clone(),
false,
@@ -336,9 +336,9 @@ impl NotificationPanel {
}))
.child(Button::new("accept", "Accept").on_click({
let notification = notification.clone();
let model = cx.entity().clone();
let entity = cx.entity().clone();
move |_, _, cx| {
model.update(cx, |this, cx| {
entity.update(cx, |this, cx| {
this.respond_to_notification(
notification.clone(),
true,

View File

@@ -198,26 +198,29 @@ impl CommandPaletteDelegate {
) {
self.updating_matches.take();
let mut intercept_result = CommandPaletteInterceptor::try_global(cx)
.and_then(|interceptor| interceptor.intercept(&query, cx));
let mut intercept_results = CommandPaletteInterceptor::try_global(cx)
.map(|interceptor| interceptor.intercept(&query, cx))
.unwrap_or_default();
if parse_zed_link(&query, cx).is_some() {
intercept_result = Some(CommandInterceptResult {
intercept_results = vec![CommandInterceptResult {
action: OpenZedUrl { url: query.clone() }.boxed_clone(),
string: query.clone(),
positions: vec![],
})
}]
}
if let Some(CommandInterceptResult {
let mut new_matches = Vec::new();
for CommandInterceptResult {
action,
string,
positions,
}) = intercept_result
} in intercept_results
{
if let Some(idx) = matches
.iter()
.position(|m| commands[m.candidate_id].action.type_id() == action.type_id())
.position(|m| commands[m.candidate_id].action.partial_eq(&*action))
{
matches.remove(idx);
}
@@ -225,18 +228,16 @@ impl CommandPaletteDelegate {
name: string.clone(),
action,
});
matches.insert(
0,
StringMatch {
candidate_id: commands.len() - 1,
string,
positions,
score: 0.0,
},
)
new_matches.push(StringMatch {
candidate_id: commands.len() - 1,
string,
positions,
score: 0.0,
})
}
new_matches.append(&mut matches);
self.commands = commands;
self.matches = matches;
self.matches = new_matches;
if self.matches.is_empty() {
self.selected_ix = 0;
} else {

View File

@@ -108,7 +108,7 @@ pub struct CommandInterceptResult {
/// An interceptor for the command palette.
#[derive(Default)]
pub struct CommandPaletteInterceptor(
Option<Box<dyn Fn(&str, &App) -> Option<CommandInterceptResult>>>,
Option<Box<dyn Fn(&str, &App) -> Vec<CommandInterceptResult>>>,
);
#[derive(Default)]
@@ -132,10 +132,12 @@ impl CommandPaletteInterceptor {
}
/// Intercepts the given query from the command palette.
pub fn intercept(&self, query: &str, cx: &App) -> Option<CommandInterceptResult> {
let handler = self.0.as_ref()?;
(handler)(query, cx)
pub fn intercept(&self, query: &str, cx: &App) -> Vec<CommandInterceptResult> {
if let Some(handler) = self.0.as_ref() {
(handler)(query, cx)
} else {
Vec::new()
}
}
/// Clears the global interceptor.
@@ -146,7 +148,7 @@ impl CommandPaletteInterceptor {
/// Sets the global interceptor.
///
/// This will override the previous interceptor, if it exists.
pub fn set(&mut self, handler: Box<dyn Fn(&str, &App) -> Option<CommandInterceptResult>>) {
pub fn set(&mut self, handler: Box<dyn Fn(&str, &App) -> Vec<CommandInterceptResult>>) {
self.0 = Some(handler);
}
}

View File

@@ -0,0 +1,23 @@
[package]
name = "component"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/component.rs"
[dependencies]
collections.workspace = true
gpui.workspace = true
linkme.workspace = true
once_cell = "1.20.3"
parking_lot.workspace = true
theme.workspace = true
[features]
default = []

View File

@@ -0,0 +1,327 @@
use std::ops::{Deref, DerefMut};
use collections::HashMap;
use gpui::{div, prelude::*, px, AnyElement, App, IntoElement, RenderOnce, SharedString, Window};
use linkme::distributed_slice;
use once_cell::sync::Lazy;
use parking_lot::RwLock;
use theme::ActiveTheme;
pub trait Component {
fn scope() -> Option<&'static str>;
fn name() -> &'static str {
std::any::type_name::<Self>()
}
fn description() -> Option<&'static str> {
None
}
}
pub trait ComponentPreview: Component {
fn preview(_window: &mut Window, _cx: &App) -> AnyElement;
}
#[distributed_slice]
pub static __ALL_COMPONENTS: [fn()] = [..];
#[distributed_slice]
pub static __ALL_PREVIEWS: [fn()] = [..];
pub static COMPONENT_DATA: Lazy<RwLock<ComponentRegistry>> =
Lazy::new(|| RwLock::new(ComponentRegistry::new()));
pub struct ComponentRegistry {
components: Vec<(Option<&'static str>, &'static str, Option<&'static str>)>,
previews: HashMap<&'static str, fn(&mut Window, &App) -> AnyElement>,
}
impl ComponentRegistry {
fn new() -> Self {
ComponentRegistry {
components: Vec::new(),
previews: HashMap::default(),
}
}
}
pub fn init() {
let component_fns: Vec<_> = __ALL_COMPONENTS.iter().cloned().collect();
let preview_fns: Vec<_> = __ALL_PREVIEWS.iter().cloned().collect();
for f in component_fns {
f();
}
for f in preview_fns {
f();
}
}
pub fn register_component<T: Component>() {
let component_data = (T::scope(), T::name(), T::description());
COMPONENT_DATA.write().components.push(component_data);
}
pub fn register_preview<T: ComponentPreview>() {
let preview_data = (T::name(), T::preview as fn(&mut Window, &App) -> AnyElement);
COMPONENT_DATA
.write()
.previews
.insert(preview_data.0, preview_data.1);
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ComponentId(pub &'static str);
#[derive(Clone)]
pub struct ComponentMetadata {
name: SharedString,
scope: Option<SharedString>,
description: Option<SharedString>,
preview: Option<fn(&mut Window, &App) -> AnyElement>,
}
impl ComponentMetadata {
pub fn name(&self) -> SharedString {
self.name.clone()
}
pub fn scope(&self) -> Option<SharedString> {
self.scope.clone()
}
pub fn description(&self) -> Option<SharedString> {
self.description.clone()
}
pub fn preview(&self) -> Option<fn(&mut Window, &App) -> AnyElement> {
self.preview
}
}
pub struct AllComponents(pub HashMap<ComponentId, ComponentMetadata>);
impl AllComponents {
pub fn new() -> Self {
AllComponents(HashMap::default())
}
/// Returns all components with previews
pub fn all_previews(&self) -> Vec<&ComponentMetadata> {
self.0.values().filter(|c| c.preview.is_some()).collect()
}
/// Returns all components with previews sorted by name
pub fn all_previews_sorted(&self) -> Vec<ComponentMetadata> {
let mut previews: Vec<ComponentMetadata> =
self.all_previews().into_iter().cloned().collect();
previews.sort_by_key(|a| a.name());
previews
}
/// Returns all components
pub fn all(&self) -> Vec<&ComponentMetadata> {
self.0.values().collect()
}
/// Returns all components sorted by name
pub fn all_sorted(&self) -> Vec<ComponentMetadata> {
let mut components: Vec<ComponentMetadata> = self.all().into_iter().cloned().collect();
components.sort_by_key(|a| a.name());
components
}
}
impl Deref for AllComponents {
type Target = HashMap<ComponentId, ComponentMetadata>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for AllComponents {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub fn components() -> AllComponents {
let data = COMPONENT_DATA.read();
let mut all_components = AllComponents::new();
for &(scope, name, description) in &data.components {
let scope = scope.map(Into::into);
let preview = data.previews.get(name).cloned();
all_components.insert(
ComponentId(name),
ComponentMetadata {
name: name.into(),
scope,
description: description.map(Into::into),
preview,
},
);
}
all_components
}
/// Which side of the preview to show labels on
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExampleLabelSide {
/// Left side
Left,
/// Right side
Right,
#[default]
/// Top side
Top,
/// Bottom side
Bottom,
}
/// A single example of a component.
#[derive(IntoElement)]
pub struct ComponentExample {
variant_name: SharedString,
element: AnyElement,
label_side: ExampleLabelSide,
grow: bool,
}
impl RenderOnce for ComponentExample {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let base = div().flex();
let base = match self.label_side {
ExampleLabelSide::Right => base.flex_row(),
ExampleLabelSide::Left => base.flex_row_reverse(),
ExampleLabelSide::Bottom => base.flex_col(),
ExampleLabelSide::Top => base.flex_col_reverse(),
};
base.gap_1()
.p_2()
.text_sm()
.text_color(cx.theme().colors().text)
.when(self.grow, |this| this.flex_1())
.child(self.element)
.child(self.variant_name)
.into_any_element()
}
}
impl ComponentExample {
/// Create a new example with the given variant name and example value.
pub fn new(variant_name: impl Into<SharedString>, element: AnyElement) -> Self {
Self {
variant_name: variant_name.into(),
element,
label_side: ExampleLabelSide::default(),
grow: false,
}
}
/// Set the example to grow to fill the available horizontal space.
pub fn grow(mut self) -> Self {
self.grow = true;
self
}
}
/// A group of component examples.
#[derive(IntoElement)]
pub struct ComponentExampleGroup {
pub title: Option<SharedString>,
pub examples: Vec<ComponentExample>,
pub grow: bool,
}
impl RenderOnce for ComponentExampleGroup {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.flex_col()
.text_sm()
.text_color(cx.theme().colors().text_muted)
.when(self.grow, |this| this.w_full().flex_1())
.when_some(self.title, |this, title| {
this.gap_4().pb_5().child(
div()
.flex()
.items_center()
.gap_3()
.child(div().h_px().w_4().bg(cx.theme().colors().border_variant))
.child(
div()
.flex_none()
.text_size(px(10.))
.child(title.to_uppercase()),
)
.child(
div()
.h_px()
.w_full()
.flex_1()
.bg(cx.theme().colors().border),
),
)
})
.child(
div()
.flex()
.items_start()
.w_full()
.gap_8()
.children(self.examples)
.into_any_element(),
)
.into_any_element()
}
}
impl ComponentExampleGroup {
/// Create a new group of examples with the given title.
pub fn new(examples: Vec<ComponentExample>) -> Self {
Self {
title: None,
examples,
grow: false,
}
}
/// Create a new group of examples with the given title.
pub fn with_title(title: impl Into<SharedString>, examples: Vec<ComponentExample>) -> Self {
Self {
title: Some(title.into()),
examples,
grow: false,
}
}
/// Set the group to grow to fill the available horizontal space.
pub fn grow(mut self) -> Self {
self.grow = true;
self
}
}
/// Create a single example
pub fn single_example(
variant_name: impl Into<SharedString>,
example: AnyElement,
) -> ComponentExample {
ComponentExample::new(variant_name, example)
}
/// Create a group of examples without a title
pub fn example_group(examples: Vec<ComponentExample>) -> ComponentExampleGroup {
ComponentExampleGroup::new(examples)
}
/// Create a group of examples with a title
pub fn example_group_with_title(
title: impl Into<SharedString>,
examples: Vec<ComponentExample>,
) -> ComponentExampleGroup {
ComponentExampleGroup::with_title(title, examples)
}

View File

@@ -1,5 +1,5 @@
[package]
name = "vcs_menu"
name = "component_preview"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
@@ -8,14 +8,14 @@ license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/component_preview.rs"
[features]
default = []
[dependencies]
anyhow.workspace = true
fuzzy.workspace = true
git.workspace = true
component.workspace = true
gpui.workspace = true
picker.workspace = true
project.workspace = true
ui.workspace = true
util.workspace = true
workspace.workspace = true
zed_actions.workspace = true

View File

@@ -0,0 +1 @@
../../LICENSE-GPL

View File

@@ -0,0 +1,190 @@
//! # Component Preview
//!
//! A view for exploring Zed components.
use component::{components, ComponentMetadata};
use gpui::{prelude::*, App, EventEmitter, FocusHandle, Focusable, Window};
use ui::prelude::*;
use workspace::{item::ItemEvent, Item, Workspace, WorkspaceId};
pub fn init(cx: &mut App) {
cx.observe_new(|workspace: &mut Workspace, _, _cx| {
workspace.register_action(
|workspace, _: &workspace::OpenComponentPreview, window, cx| {
let component_preview = cx.new(ComponentPreview::new);
workspace.add_item_to_active_pane(
Box::new(component_preview),
None,
true,
window,
cx,
)
},
);
})
.detach();
}
struct ComponentPreview {
focus_handle: FocusHandle,
}
impl ComponentPreview {
pub fn new(cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
}
}
fn render_sidebar(&self, _window: &Window, _cx: &Context<Self>) -> impl IntoElement {
let components = components().all_sorted();
let sorted_components = components.clone();
v_flex()
.max_w_48()
.gap_px()
.p_1()
.children(
sorted_components
.into_iter()
.map(|component| self.render_sidebar_entry(&component, _cx)),
)
.child(
Label::new("These will be clickable once the layout is moved to a gpui::List.")
.color(Color::Muted)
.size(LabelSize::XSmall)
.italic(),
)
}
fn render_sidebar_entry(
&self,
component: &ComponentMetadata,
_cx: &Context<Self>,
) -> impl IntoElement {
h_flex()
.w_40()
.px_1p5()
.py_0p5()
.text_sm()
.child(component.name().clone())
}
fn render_preview(
&self,
component: &ComponentMetadata,
window: &mut Window,
cx: &Context<Self>,
) -> impl IntoElement {
let name = component.name();
let scope = component.scope();
let description = component.description();
v_flex()
.border_b_1()
.border_color(cx.theme().colors().border)
.w_full()
.gap_3()
.py_6()
.child(
v_flex()
.gap_1()
.child(
h_flex()
.gap_1()
.text_2xl()
.child(div().child(name))
.when_some(scope, |this, scope| {
this.child(div().opacity(0.5).child(format!("({})", scope)))
}),
)
.when_some(description, |this, description| {
this.child(
div()
.text_ui_sm(cx)
.text_color(cx.theme().colors().text_muted)
.max_w(px(600.0))
.child(description),
)
}),
)
.when_some(component.preview(), |this, preview| {
this.child(preview(window, cx))
})
.into_any_element()
}
fn render_previews(&self, window: &mut Window, cx: &Context<Self>) -> impl IntoElement {
v_flex()
.id("component-previews")
.size_full()
.overflow_y_scroll()
.p_4()
.gap_4()
.children(
components()
.all_previews_sorted()
.iter()
.map(|component| self.render_preview(component, window, cx)),
)
}
}
impl Render for ComponentPreview {
fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
h_flex()
.id("component-preview")
.key_context("ComponentPreview")
.items_start()
.overflow_hidden()
.size_full()
.max_h_full()
.track_focus(&self.focus_handle)
.px_2()
.bg(cx.theme().colors().editor_background)
.child(self.render_sidebar(window, cx))
.child(self.render_previews(window, cx))
}
}
impl EventEmitter<ItemEvent> for ComponentPreview {}
impl Focusable for ComponentPreview {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Item for ComponentPreview {
type Event = ItemEvent;
fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Component Preview".into())
}
fn telemetry_event_text(&self) -> Option<&'static str> {
None
}
fn show_toolbar(&self) -> bool {
false
}
fn clone_on_split(
&self,
_workspace_id: Option<WorkspaceId>,
_window: &mut Window,
cx: &mut Context<Self>,
) -> Option<gpui::Entity<Self>>
where
Self: Sized,
{
Some(cx.new(Self::new))
}
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
f(*event)
}
}

View File

@@ -59,20 +59,20 @@ workspace.workspace = true
async-std = { version = "1.12.0", features = ["unstable"] }
[dev-dependencies]
indoc.workspace = true
serde_json.workspace = true
clock = { workspace = true, features = ["test-support"] }
client = { workspace = true, features = ["test-support"] }
clock = { workspace = true, features = ["test-support"] }
collections = { workspace = true, features = ["test-support"] }
editor = { workspace = true, features = ["test-support"] }
fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
http_client = { workspace = true, features = ["test-support"] }
indoc.workspace = true
language = { workspace = true, features = ["test-support"] }
lsp = { workspace = true, features = ["test-support"] }
node_runtime = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
rpc = { workspace = true, features = ["test-support"] }
serde_json.workspace = true
settings = { workspace = true, features = ["test-support"] }
theme = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }

View File

@@ -17,7 +17,7 @@ use gpui::{
use http_client::github::get_release_by_tag_name;
use http_client::HttpClient;
use language::{
language_settings::{all_language_settings, language_settings, InlineCompletionProvider},
language_settings::{all_language_settings, language_settings, EditPredictionProvider},
point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16,
ToPointUtf16,
};
@@ -368,8 +368,8 @@ impl Copilot {
let server_id = self.server_id;
let http = self.http.clone();
let node_runtime = self.node_runtime.clone();
if all_language_settings(None, cx).inline_completions.provider
== InlineCompletionProvider::Copilot
if all_language_settings(None, cx).edit_predictions.provider
== EditPredictionProvider::Copilot
{
if matches!(self.server, CopilotServer::Disabled) {
let start_task = cx
@@ -1061,6 +1061,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
mod tests {
use super::*;
use gpui::TestAppContext;
use util::path;
#[gpui::test(iterations = 10)]
async fn test_buffer_management(cx: &mut TestAppContext) {
@@ -1123,7 +1124,7 @@ mod tests {
buffer_1.update(cx, |buffer, cx| {
buffer.file_updated(
Arc::new(File {
abs_path: "/root/child/buffer-1".into(),
abs_path: path!("/root/child/buffer-1").into(),
path: Path::new("child/buffer-1").into(),
}),
cx,
@@ -1136,7 +1137,7 @@ mod tests {
text_document: lsp::TextDocumentIdentifier::new(buffer_1_uri),
}
);
let buffer_1_uri = lsp::Url::from_file_path("/root/child/buffer-1").unwrap();
let buffer_1_uri = lsp::Url::from_file_path(path!("/root/child/buffer-1")).unwrap();
assert_eq!(
lsp.receive_notification::<lsp::notification::DidOpenTextDocument>()
.await,

View File

@@ -36,8 +36,8 @@ pub enum Model {
Gpt3_5Turbo,
#[serde(alias = "o1", rename = "o1")]
O1,
#[serde(alias = "o1-mini", rename = "o1-mini")]
O1Mini,
#[serde(alias = "o1-mini", rename = "o3-mini")]
O3Mini,
#[serde(alias = "claude-3-5-sonnet", rename = "claude-3.5-sonnet")]
Claude3_5Sonnet,
}
@@ -46,7 +46,7 @@ impl Model {
pub fn uses_streaming(&self) -> bool {
match self {
Self::Gpt4o | Self::Gpt4 | Self::Gpt3_5Turbo | Self::Claude3_5Sonnet => true,
Self::O1Mini | Self::O1 => false,
Self::O3Mini | Self::O1 => false,
}
}
@@ -56,7 +56,7 @@ impl Model {
"gpt-4" => Ok(Self::Gpt4),
"gpt-3.5-turbo" => Ok(Self::Gpt3_5Turbo),
"o1" => Ok(Self::O1),
"o1-mini" => Ok(Self::O1Mini),
"o3-mini" => Ok(Self::O3Mini),
"claude-3-5-sonnet" => Ok(Self::Claude3_5Sonnet),
_ => Err(anyhow!("Invalid model id: {}", id)),
}
@@ -67,7 +67,7 @@ impl Model {
Self::Gpt3_5Turbo => "gpt-3.5-turbo",
Self::Gpt4 => "gpt-4",
Self::Gpt4o => "gpt-4o",
Self::O1Mini => "o1-mini",
Self::O3Mini => "o3-mini",
Self::O1 => "o1",
Self::Claude3_5Sonnet => "claude-3-5-sonnet",
}
@@ -78,7 +78,7 @@ impl Model {
Self::Gpt3_5Turbo => "GPT-3.5",
Self::Gpt4 => "GPT-4",
Self::Gpt4o => "GPT-4o",
Self::O1Mini => "o1-mini",
Self::O3Mini => "o3-mini",
Self::O1 => "o1",
Self::Claude3_5Sonnet => "Claude 3.5 Sonnet",
}
@@ -89,7 +89,7 @@ impl Model {
Self::Gpt4o => 64000,
Self::Gpt4 => 32768,
Self::Gpt3_5Turbo => 12288,
Self::O1Mini => 20000,
Self::O3Mini => 20000,
Self::O1 => 20000,
Self::Claude3_5Sonnet => 200_000,
}

View File

@@ -1,11 +1,9 @@
use crate::{Completion, Copilot};
use anyhow::Result;
use gpui::{App, Context, Entity, EntityId, Task};
use inline_completion::{Direction, InlineCompletion, InlineCompletionProvider};
use language::{
language_settings::{all_language_settings, AllLanguageSettings},
Buffer, OffsetRangeExt, ToOffset,
};
use inline_completion::{Direction, EditPredictionProvider, InlineCompletion};
use language::{language_settings::AllLanguageSettings, Buffer, OffsetRangeExt, ToOffset};
use project::Project;
use settings::Settings;
use std::{path::Path, time::Duration};
@@ -50,7 +48,7 @@ impl CopilotCompletionProvider {
}
}
impl InlineCompletionProvider for CopilotCompletionProvider {
impl EditPredictionProvider for CopilotCompletionProvider {
fn name() -> &'static str {
"copilot"
}
@@ -63,33 +61,22 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
false
}
fn show_completions_in_normal_mode() -> bool {
false
}
fn is_refreshing(&self) -> bool {
self.pending_refresh.is_some()
}
fn is_enabled(
&self,
buffer: &Entity<Buffer>,
cursor_position: language::Anchor,
_buffer: &Entity<Buffer>,
_cursor_position: language::Anchor,
cx: &App,
) -> bool {
if !self.copilot.read(cx).status().is_authorized() {
return false;
}
let buffer = buffer.read(cx);
let file = buffer.file();
let language = buffer.language_at(cursor_position);
let settings = all_language_settings(file, cx);
settings.inline_completions_enabled(language.as_ref(), file.map(|f| f.path().as_ref()), cx)
self.copilot.read(cx).status().is_authorized()
}
fn refresh(
&mut self,
_project: Option<Entity<Project>>,
buffer: Entity<Buffer>,
cursor_position: language::Anchor,
debounce: bool,
@@ -205,7 +192,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
fn discard(&mut self, cx: &mut Context<Self>) {
let settings = AllLanguageSettings::get_global(cx);
let copilot_enabled = settings.inline_completions_enabled(None, None, cx);
let copilot_enabled = settings.show_inline_completions(None, cx);
if !copilot_enabled {
return;
@@ -255,6 +242,7 @@ impl InlineCompletionProvider for CopilotCompletionProvider {
} else {
let position = cursor_position.bias_right(buffer);
Some(InlineCompletion {
id: None,
edits: vec![(position..position, completion_text.into())],
edit_preview: None,
})
@@ -290,7 +278,10 @@ mod tests {
use serde_json::json;
use settings::SettingsStore;
use std::future::Future;
use util::test::{marked_text_ranges_by, TextRangeMarker};
use util::{
path,
test::{marked_text_ranges_by, TextRangeMarker},
};
#[gpui::test(iterations = 10)]
async fn test_copilot(executor: BackgroundExecutor, cx: &mut TestAppContext) {
@@ -311,7 +302,7 @@ mod tests {
.await;
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
cx.update_editor(|editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -341,7 +332,6 @@ mod tests {
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
cx.update_editor(|editor, window, cx| {
assert!(editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(!editor.has_active_inline_completion());
// Since we have both, the copilot suggestion is not shown inline
assert_eq!(editor.text(cx), "one.\ntwo\nthree\n");
@@ -394,12 +384,11 @@ mod tests {
assert_eq!(editor.text(cx), "one.\ntwo\nthree\n");
});
// Ensure existing inline completion is interpolated when inserting again.
// Ensure existing edit prediction is interpolated when inserting again.
cx.simulate_keystroke("c");
executor.run_until_parked();
cx.update_editor(|editor, _, cx| {
assert!(!editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
@@ -419,7 +408,6 @@ mod tests {
cx.update_editor(|editor, window, cx| {
assert!(!editor.context_menu_visible());
assert!(editor.has_active_inline_completion());
assert!(!editor.context_menu_contains_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
@@ -449,8 +437,8 @@ mod tests {
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
// AcceptInlineCompletion when there is an active suggestion inserts it.
editor.accept_inline_completion(&Default::default(), window, cx);
// AcceptEditPrediction when there is an active suggestion inserts it.
editor.accept_edit_prediction(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
assert_eq!(editor.text(cx), "one.copilot2\ntwo\nthree\n");
@@ -495,7 +483,7 @@ mod tests {
);
cx.update_editor(|editor, window, cx| {
editor.next_inline_completion(&Default::default(), window, cx)
editor.next_edit_prediction(&Default::default(), window, cx)
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
cx.update_editor(|editor, window, cx| {
@@ -509,8 +497,8 @@ mod tests {
assert_eq!(editor.text(cx), "fn foo() {\n \n}");
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
// Using AcceptInlineCompletion again accepts the suggestion.
editor.accept_inline_completion(&Default::default(), window, cx);
// Using AcceptEditPrediction again accepts the suggestion.
editor.accept_edit_prediction(&Default::default(), window, cx);
assert!(!editor.has_active_inline_completion());
assert_eq!(editor.text(cx), "fn foo() {\n let x = 4;\n}");
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
@@ -539,7 +527,7 @@ mod tests {
.await;
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
cx.update_editor(|editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
});
// Setup the editor with a completion request.
@@ -663,7 +651,7 @@ mod tests {
.await;
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
cx.update_editor(|editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -682,7 +670,7 @@ mod tests {
vec![],
);
cx.update_editor(|editor, window, cx| {
editor.next_inline_completion(&Default::default(), window, cx)
editor.next_edit_prediction(&Default::default(), window, cx)
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
cx.update_editor(|editor, window, cx| {
@@ -753,7 +741,7 @@ mod tests {
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
editor
.update(cx, |editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
})
.unwrap();
@@ -771,7 +759,7 @@ mod tests {
editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
});
editor.next_inline_completion(&Default::default(), window, cx);
editor.next_edit_prediction(&Default::default(), window, cx);
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
_ = editor.update(cx, |editor, _, cx| {
@@ -847,7 +835,7 @@ mod tests {
.await;
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
cx.update_editor(|editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
});
cx.set_state(indoc! {"
@@ -875,7 +863,7 @@ mod tests {
vec![],
);
cx.update_editor(|editor, window, cx| {
editor.next_inline_completion(&Default::default(), window, cx)
editor.next_edit_prediction(&Default::default(), window, cx)
});
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
cx.update_editor(|editor, _, cx| {
@@ -934,7 +922,6 @@ mod tests {
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
cx.update_editor(|editor, _, cx| {
assert!(editor.context_menu_visible());
assert!(!editor.context_menu_contains_inline_completion());
assert!(!editor.has_active_inline_completion(),);
assert_eq!(editor.text(cx), "one\ntwo.\nthree\n");
});
@@ -944,7 +931,7 @@ mod tests {
async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut TestAppContext) {
init_test(cx, |settings| {
settings
.inline_completions
.edit_predictions
.get_or_insert(Default::default())
.disabled_globs = Some(vec![".env*".to_string()]);
});
@@ -953,24 +940,24 @@ mod tests {
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/test",
path!("/test"),
json!({
".env": "SECRET=something\n",
"README.md": "hello\nworld\nhow\nare\nyou\ntoday"
}),
)
.await;
let project = Project::test(fs, ["/test".as_ref()], cx).await;
let project = Project::test(fs, [path!("/test").as_ref()], cx).await;
let private_buffer = project
.update(cx, |project, cx| {
project.open_local_buffer("/test/.env", cx)
project.open_local_buffer(path!("/test/.env"), cx)
})
.await
.unwrap();
let public_buffer = project
.update(cx, |project, cx| {
project.open_local_buffer("/test/README.md", cx)
project.open_local_buffer(path!("/test/README.md"), cx)
})
.await
.unwrap();
@@ -1006,7 +993,7 @@ mod tests {
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
editor
.update(cx, |editor, window, cx| {
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
})
.unwrap();

View File

@@ -750,7 +750,7 @@ impl Item for ProjectDiagnosticsEditor {
}
fn telemetry_event_text(&self) -> Option<&'static str> {
Some("project diagnostics")
Some("Project Diagnostics Opened")
}
fn for_each_project_item(
@@ -933,7 +933,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
.when_some(diagnostic.code.as_ref(), |stack, code| {
stack.child(
div()
.child(SharedString::from(format!("({code})")))
.child(SharedString::from(format!("({code:?})")))
.text_color(color.text_muted),
)
}),

Some files were not shown because too many files have changed in this diff Show More