Compare commits

...

1662 Commits

Author SHA1 Message Date
Antonio Scandurra
707bd7c156 zed 0.91.3 2023-06-16 17:27:42 +02:00
Antonio Scandurra
656f68dc69 Activate screen-sharing when leader activates a panel (#2614)
Fixes
https://linear.app/zed-industries/issue/Z-1875/screen-sharing-tab-is-not-activated-when-leader-is-on-a-panel

Release Notes:

- Fixed a bug that caused followers to not see the leader's screen when
they activated a panel.
2023-06-16 17:26:33 +02:00
Max Brunsfeld
186334bb12 zed 0.91.2 2023-06-15 15:34:43 -07:00
Max Brunsfeld
b1324ebe1f Fix failure to upload panics when multiple panics happen at the same time (#2616)
When multiple panics occur at the same time (usually because one thread
panics, and another thread joins it), multiple panic JSON objects can
get written to the same panic file. The resulting file won't be valid
JSON.

This PR addresses that problem via two changes:
* Format panic files as single-line JSON objects
* When a panic file  isn't valid JSON, try taking the first line

In the future, we could try combining all of the backtraces, but for
now, I just want to avoid a problem of not reporting a panic at all.

Release Notes:

- Fixed a problem with Zed's internal crash reporting.
2023-06-15 15:34:09 -07:00
Max Brunsfeld
e9aec1d67a Don't rely on debug symbols for panic reporting (#2615)
This fixes a regression introduced in
https://github.com/zed-industries/zed/pull/2560, where panic reports did
not include backtraces. The problem was that in that PR, I assumed we
could retrieve file paths for symbols in our backtraces. But actually,
that functionality only works when the app is built locally, and a
`.dSYM` file can be magically found by the OS. We don't ship those dSYM
files with Zed, so panic symbols do not have file paths available.

Panic backtraces will still be more useful and less noisy than before
though: we will strip out frames for which we don't have symbol names,
and remove leading panic-handling stack frames from the backtraces.

Release Notes:

- N/A
2023-06-15 15:34:01 -07:00
Mikayla Maki
32ed547c2c zed 0.91.1 2023-06-14 18:10:16 -07:00
Mikayla Maki
39915f7c96 Add entitlements file to bundle step (#2611)
This completes the bundle changes that will be needed to access voice,
as well as adds permissions for accessing other MacOS services, the
camera, and the necessary permissions for plugins. This was developed by
combining the entitlements of iTerm and VSCode, cross-referenced with
the entitlements of Firefox. 

Release Notes:

- Fixed a bug in enabling authorization for macOS services (preview
only)
2023-06-14 18:09:15 -07:00
Joseph Lyons
2c2cea1c92 v0.91.x preview 2023-06-14 13:27:18 -04:00
Mikayla Maki
75b1f60126 Add UsageDescriptions to Info.plist (#2609)
This updates our dependency on cargo-bundle to point at a fork I've
created that adjusts the latest version's behavior to work for our use
case. This PR also updates the Zed Info.plist to include the following
keys:

- NSSystemAdministrationUsageDescription
- NSAppleEventsUsageDescription
- NSBluetoothAlwaysUsageDescription
- NSCalendarsUsageDescription
- NSCameraUsageDescription
- NSContactsUsageDescription
- NSLocationAlwaysUsageDescription
- NSLocationUsageDescription
- NSLocationWhenInUseUsageDescription
- NSMicrophoneUsageDescription
- NSSpeechRecognitionUsageDescription
- NSRemindersUsageDescription

Release Notes:

- Bug fix: Allow applications run via the Zed terminal to request
authorization for macOS services (e.g. microphone and camera)
2023-06-14 10:04:54 -07:00
Antonio Scandurra
2b8b954c3e Overhaul assistant panel (#2610)
Closes
https://linear.app/zed-industries/issue/Z-2368/use-a-different-icon-for-the-assistant-panel
Closes
https://linear.app/zed-industries/issue/Z-2363/ship-the-assistant-only-on-preview
Closes
https://linear.app/zed-industries/issue/Z-2331/scrolling-makes-it-hard-to-read
Closes
https://linear.app/zed-industries/issue/Z-2306/allow-undo-and-collaboration-in-assistant

This pull request is a significant overhaul of the assistant panel,
which now uses a simple `Buffer` as opposed to a `MultiBuffer` to show
messages. Specifically, we track the start of each message with an
anchor located right after the newline (or `Anchor::MIN` for the first
message). When the anchor becomes invalid (that is, the newline is
deleted), we merge the message with the preceding ones. Crucially,
messages don't actually get deleted so that, if the newline anchor
becomes valid again (such as when undoing/redoing), we can restore the
messages as well.

As part of this overhaul, we are also improving the scrolling behavior
to maintain the viewport stable only when editing or moving the cursor,
but otherwise leave the scroll position unchanged when manually
scrolling up or down.

Note that with these changes, we are limiting access to the assistant to
users on preview (and dev), as we want to polish the behavior a little
more before shipping to the general public. Users on stable will still
be able to see the default settings/keybindings of the assistant, but I
think that's okay, as they won't be able to do anything with them.

Release Notes:

- Added support for undo/redo in the assistant (preview-only)
- Improved the scrolling behavior of the assistant when it was
generating responses. Now Zed will keep the viewport stable only when
editing or moving the cursor, but otherwise leave the scroll position
unchanged when manually scrolling up or down (preview-only)
- Changed the icon of the assistant panel (preview-only)

**Note for @JosephTLyons: given that we're feature flagging this, let's
make sure things on stable look reasonable and work correctly. Things to
look out for: ensure a stock installation works, changing the settings
on stable works, changing the keybinding on stable works.**
2023-06-14 14:09:09 +02:00
Antonio Scandurra
4efe62b3e5 Use robot icon for assistant to prevent confusion with conversations 2023-06-14 12:14:43 +02:00
Antonio Scandurra
049c987310 Avoid loading the assistant panel on stable 2023-06-14 12:08:49 +02:00
Antonio Scandurra
56b0bf8601 Save cursor scroll position when the editor is auto-scrolled 2023-06-14 12:00:27 +02:00
Antonio Scandurra
1aa1774688 Avoid auto-scrolling the editor when inserting/removing headers 2023-06-14 10:49:23 +02:00
Antonio Scandurra
f8b9417406 Keep cursor stable as autocompletions are being streamed 2023-06-14 10:41:18 +02:00
Antonio Scandurra
75ad76bfb2 💄 2023-06-14 09:47:30 +02:00
Antonio Scandurra
7dab17e233 Re-enable copy support in the assistant 2023-06-14 09:40:43 +02:00
Antonio Scandurra
27c83ca3f7 Remove unnecessary set_render_excerpt_header method 2023-06-14 09:38:49 +02:00
Antonio Scandurra
9b7617403d Parse buffer as Markdown 2023-06-14 09:31:41 +02:00
Antonio Scandurra
ea5d677ef8 Merge remote-tracking branch 'origin/main' into assistant-buffer 2023-06-14 09:16:45 +02:00
Mikayla Maki
adc8337ad4 Restore misconfigured Cargo.toml 2023-06-13 18:08:33 -07:00
Mikayla Maki
8ad7eb7598 Switch to using new version of cargo bundle with more capabilities 2023-06-13 18:01:51 -07:00
Kevin Hovsäter
b365e48ff0 Toggle comments for empty single line selections (#2594) 2023-06-13 20:15:11 +02:00
Max Brunsfeld
77367bf2e4 Move worktree tests into their own file (#2608)
The worktree has a lot of tests. Let's reduce their indentation, and
make it easier to navigate to them. We deserve it.

Just doing this in its own PR, to minimize conflicts.

Release Notes:

- N/A
2023-06-13 10:50:49 -07:00
Max Brunsfeld
5b6d1a27ff Flatten worktree tests module structure 2023-06-13 10:31:29 -07:00
Max Brunsfeld
c17dbab6f1 Move worktree tests to their own file 2023-06-13 10:22:14 -07:00
Piotr Osiewicz
b272db9e21 editor: Add language setting for comment continuations (#2605)
Per @JosephTLyons request I've added a language setting for comment
continuations.

Release Notes:

- Added a language setting for comment continuations.
2023-06-13 18:59:46 +02:00
Max Brunsfeld
aedef7bc58 Remove panic when programatically updating an invalid setting (#2607)
Fixes
https://linear.app/zed-industries/issue/Z-2170/thread-main-panicked-at-could-not-deserialize-setting-type-welcomebase
Fixes
https://linear.app/zed-industries/issue/Z-2228/thread-main-panicked-at-could-not-deserialize-setting-type
2023-06-13 09:50:54 -07:00
Max Brunsfeld
1cd11bfe66 Remove panic when programatically updating an invalid setting 2023-06-13 09:43:57 -07:00
Antonio Scandurra
0db0a1ccef Skip merged messages when inserting new ones
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-06-13 16:06:50 +02:00
Antonio Scandurra
6e5de2fbbb Update blocks when cycling the message role
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-06-13 16:00:13 +02:00
Antonio Scandurra
00cede63a8 Show message headers again
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-06-13 15:55:52 +02:00
Antonio Scandurra
2842fc2b1d Merge messages whose header has been invalidated 2023-06-13 15:16:04 +02:00
Antonio Scandurra
2ae8b558b9 Get back to a compiling state with Buffer backing the assistant 2023-06-13 13:43:06 +02:00
Joseph T. Lyons
5e68dc5c92 Fix comments in settings files (#2604)
I accidentally added the information about folder-specific settings to
the user settings default file - just fixing that.

Release Notes:

- N/A
2023-06-13 04:06:53 -04:00
Joseph Lyons
5821bc4161 Fix comments in settings files 2023-06-13 04:03:51 -04:00
Max Brunsfeld
d8a2e176e6 Add support for HEEx templates in Elixir, fix a bug in handling nested language injections (#2603)
Closes https://linear.app/zed-industries/issue/Z-2211/heex-support

Release Notes:

- Added support for Elixir HEEx templates.
- Fixed a bug that caused incorrect syntax highlighting in ERB templates
([#1619](https://github.com/zed-industries/community/issues/1619)).
2023-06-12 17:49:07 -07:00
Max Brunsfeld
df76ab98cf Add Heex language 2023-06-12 17:32:20 -07:00
Max Brunsfeld
01bd5c30fc Fix syntax map bug with combined injections inside of other injections 2023-06-12 17:32:20 -07:00
Max Brunsfeld
ac1882b99b Move SyntaxMap tests to their own file 2023-06-12 16:24:17 -07:00
Max Brunsfeld
04e43899c0 Change action namespace to 'debug' for LSP log and syntax tree view 2023-06-12 15:54:36 -07:00
Max Brunsfeld
8542911eec Add a syntax tree view, for developing and debugging language support (#2601)
This PR adds a syntax tree view, which lets you view the syntax tree of
any layer in the active editor's `SyntaxMap`.

This view uses some new APIs that I added to Tree-sitter, which allow us
to efficiently render the syntax tree using a `UniformList`. Tree-sitter
PR: https://github.com/tree-sitter/tree-sitter/pull/2316

![Screen Shot 2023-06-12 at 3 33 36
PM](https://github.com/zed-industries/zed/assets/326587/2a27ee7b-bf29-4b3b-bfa8-fb47f97a2785)

Release Notes:

- Added a *syntax tree view* that shows Zed's internal syntax tree(s)
for the active editor. You can open it running the `debug: open syntax
tree view` command from the command palette.
2023-06-12 15:50:39 -07:00
Max Brunsfeld
018466171b Include field names in the syntax tree 2023-06-12 15:32:16 -07:00
Max Brunsfeld
594b9def20 Upgrade Tree-sitter 2023-06-12 15:31:59 -07:00
Max Brunsfeld
b4f3a88b38 Close the menu when selecting a different layer in the syntax tree view 2023-06-12 15:14:57 -07:00
Max Brunsfeld
56b749788f Improve the look of the syntax tree view UI 2023-06-12 15:14:57 -07:00
Max Brunsfeld
e969e3b028 Sync selection between syntax tree view and editor 2023-06-12 15:14:57 -07:00
Max Brunsfeld
086cfe57c5 Start work on a syntax tree view 2023-06-12 15:14:56 -07:00
Piotr Osiewicz
3d02f7ce5f Move plugins to feature-gate (#2599)
This PR:
- Reduces our dependency count for a release build by 20%
- Reduces our release compile time by about 30s (out of ~5 minutes)
2023-06-12 21:04:09 +02:00
Antonio Scandurra
7db690b713 WIP 2023-06-12 17:50:13 +02:00
Joseph T. Lyons
db5bb4ec03 Do not rely on user's system time for telemetry events (#2597)
Some user's don't have their system clocks configured right and we are
seeing events 10 years into the future. I'm stripping out the code that
adds time via the client and am adding it in on zed.dev. We will lose a
little accuracy, as the time will be when the batch hits the server, but
I think its negligible (currently, batches send up every 30 seconds, at
the max) and worth it to protect our data from user's who wonkily dont
set care about their system time.

- https://github.com/zed-industries/zed.dev/pull/332

Release Notes:

- N/A
2023-06-09 18:08:11 -04:00
Joseph Lyons
0b3b732310 Do not rely on user's system time for telemetry events 2023-06-09 18:02:20 -04:00
Max Brunsfeld
56a4c2afae Bump tree-sitter-yaml to avoid submodule error during build 2023-06-09 14:58:31 -07:00
Joseph T. Lyons
d8c1ab9c68 Fix formatter comment in default settings (#2593)
Fix comment related to the `formatter` configuration option in Zed's
default settings.

Release Notes:

- N/A
2023-06-09 15:14:04 -04:00
Max Brunsfeld
c1f1ee6b05 collab 0.14.2 2023-06-09 11:50:35 -07:00
Max Brunsfeld
b2bdca4779 Bump protocol version 2023-06-09 11:50:15 -07:00
Max Brunsfeld
097632467d collab 0.14.1 2023-06-09 11:37:47 -07:00
Max Brunsfeld
87efd25d42 Avoid dropping the worktree_repository_statuses table for now 2023-06-09 11:37:39 -07:00
Max Brunsfeld
bb65d75798 Enable rust backtraces on kubernetes 2023-06-09 11:15:21 -07:00
Max Brunsfeld
9cbb63d374 collab 0.14.0 2023-06-09 11:12:45 -07:00
Piotr Osiewicz
5bef2f1778 Z-2303 editor: fix comment extension on the start of line (#2595)
Release Notes:

- Improved comment extension for cases where cursor was placed before
start of comment marker
2023-06-09 20:02:51 +02:00
Max Brunsfeld
fb83ab8e9f Add outline support for Ruby singleton methods (#2592)
This pull request add support for Ruby singleton methods in the document
outline.

**Before**

<img width="1490" alt="outline-before"
src="https://github.com/zed-industries/zed/assets/503025/e90afd4c-bcdd-477b-92cf-fe34cec54980">

**After**

<img width="1493" alt="outline-after"
src="https://github.com/zed-industries/zed/assets/503025/067cc80b-7718-4395-9079-4677a689b9be">

Release Notes:

- Added support for singleton methods in Ruby outline view. Fixed
[#1442](https://github.com/zed-industries/community/issues/1442).
2023-06-09 08:35:34 -07:00
Max Brunsfeld
738b06a778 Update JavaScript outline queries (#2596)
Add support for exported const declarations in the outline view. Did not
include more context (e.g., whether or not the it's exported or not)
because we're not doing that for TypeScript right now. We could do that
in a follow up pull request, addressing both JavaScript and TypeScript
at once.


**Before**

<img width="1186" alt="outline-before"
src="https://github.com/zed-industries/zed/assets/503025/e72b0ed4-52b0-4a7c-af70-b2f4758e3554">

**After**

<img width="1186" alt="outline-after"
src="https://github.com/zed-industries/zed/assets/503025/cd91bc7f-8ce3-485f-9b33-d487ad6c718d">


Release Notes:

- Added support for exported const declarations in the JavaScript
outline view. Fixed
[#1399](https://github.com/zed-industries/community/issues/1399).
2023-06-09 08:34:14 -07:00
Kevin Hovsäter
4213cc013c Update JavaScript outline queries
Add support for exported const declarations in the outline view.
2023-06-09 15:33:27 +02:00
Kevin Hovsäter
6ce3f3bf27 Refactor toggle comment tests 2023-06-09 13:22:04 +02:00
Kevin Hovsäter
a8d43c6d71 Toggle comments for empty single line selections 2023-06-09 10:10:49 +02:00
Kevin Hovsäter
7deddd1149 Fix formatter comment in default settings 2023-06-09 08:08:07 +02:00
Kevin Hovsäter
57ff173e29 Add outline support for Ruby singleton methods 2023-06-09 07:31:09 +02:00
Nate Butler
85b049f250 Build tokens for each theme (#2590)
This PR adds the ability to export tokens for each theme. 

You can export tokens by:

1. `cd styles`
2. `npm run build-tokens`
3. Tokens will be output in the target folder (`styles/target`)

The tokens match the ColorScheme object. In the future we may also
export tokens for our styleTrees.

Release Notes:

- N/A (No public facing changes)

---
TODO:

- [x] Generate Token Studio theme index file
- [x] ColorScheme
    - [x] name:
    - [x] isLight
    - [x] lowest
    - [x] middle
    - [x] highest
    - [x] popoverShadow
    - [x] modalShadow
    - [x] players
    - [x] syntax
2023-06-08 16:40:46 -04:00
Nate Butler
ddcbc774ab $tokens.json => $themes.json 2023-06-08 16:36:15 -04:00
Nate Butler
e4cbc29f98 Update buildTokens to export $metadata.json and $themes.json 2023-06-08 16:19:28 -04:00
Max Brunsfeld
6304897abc Make the LSP log view searchable (#2591)
Also, I noticed errors in the logs of the Elixir LSP that we were
sending `goToTypeDefinition` requests, which that server does not
support. We now respect that server capability.

Release Notes:

- N/A
2023-06-08 13:15:05 -07:00
Nate Butler
3719c206c9 Only export color tokens for syntax 2023-06-08 15:14:59 -04:00
Nate Butler
91e1bb8fd4 WIP syntax tokens 2023-06-08 15:12:11 -04:00
Max Brunsfeld
a7f06f962b Enable type definition capability in fake LSPs in tests 2023-06-08 12:09:37 -07:00
Max Brunsfeld
e0dd9e4185 Make the LSP log view searchable 2023-06-08 11:33:20 -07:00
Max Brunsfeld
11dbbcc9dd Respect LSP goToTypeDefinition server capability 2023-06-08 11:33:09 -07:00
Nate Butler
999b2365a8 Export additional tokens, standardize naming convention 2023-06-08 12:21:51 -04:00
Max Brunsfeld
e3f319467a Enhance LSP log viewer to show server logs in addition to RPC trace (#2586)
In debugging what's going on with the Elixir language server, there was
some interesting content in the server's logs (sent to the app via the
`window/logMessage` LSP endpoint). I decided to invest in making
language server issues easier to debug by exposing these `logMessage`
contents in the app.

Also, improve the UI of the view slightly:

* Select one of the servers by default (instead of "no server selected")
* Make it clearer that the menu is clickable
2023-06-08 09:03:52 -07:00
Max Brunsfeld
908de23b72 Tweak LSP log menu styling 2023-06-08 08:58:57 -07:00
Max Brunsfeld
afaff7f9a9 Merge branch 'main' into lsp-log-messages 2023-06-08 08:49:08 -07:00
Max Brunsfeld
817644eb20 Style new lsp log menu, add a test for it 2023-06-08 08:43:25 -07:00
Nate Butler
e2f46d5448 Build layer tokens for each theme 2023-06-08 11:15:59 -04:00
Nate Butler
16e3e04501 Update TSConfig (#2589)
Based on #2558. Also fixes errors resulting from the stricter options.

Release Notes:

- N/A (No public facing changes)
2023-06-08 01:31:21 -04:00
Nate Butler
1e43fec1c5 Update buildLicenses to only include the theme url if there is one 2023-06-08 01:23:19 -04:00
Nate Butler
e996a66596 Update TSCondif
Based on #2558. Also fixes errors resulting from the stricter options.
2023-06-08 01:15:57 -04:00
Nate Butler
a75e9faa83 Add foundation for exporting tokens from our color schemes (#2588)
We removed our Figma Tokens/Tokens Studio export a while back when we
moved to the theme to ColorSchemes. I'd like to get back to exporting
these so we can be working from up to date themes in Figma, especially
with the large amount of UI design work we'll be doing in the next few
weeks on channels.

This PR adds some basic plumbing to start working through the
theme/colorScheme and export the parts as tokens.

I also discovered that Tokens Studio now publishes their types, so we
can use them directly rather than writing our own:
https://github.com/tokens-studio/types

Pulled those in and started connecting them as well.

Running `npm run build-tokens` will export the tokens for each theme to
`styles/target/tokens`.

Currently only a few element's tokens are exported, will expand this
further as time permits.

Release Notes:

- N/A (No public facing changes)
2023-06-08 00:53:16 -04:00
Nate Butler
c8a9d73ea6 Add foundation for exporting tokens 2023-06-08 00:37:00 -04:00
Nate Butler
d4192fc3e9 Organize misc files into theme, themes and styleTrees (#2587)
We've accumulated a number of miscellaneous folders in the styles
folder. Simplifying these down to `theme`, `themes` and `styleTrees`.

Release Notes:

- N/A (No public facing changes)
2023-06-07 22:47:48 -04:00
Mikayla Maki
8216d26a7a Switch to attaching git statuses to their associated entries (#2571)
This rewrites and simplifies the git status system by attaching the git
status to each individual entry. This also improves the git testing
infrastructure to cover more cases and be more accurate to how file
events actually occur. This also fixes several other bugs in the worktree and the buffer, and stops any randomly generated actions from happening inside a `.git` folder. Hopefully, we can undo this change soon once our randomized testing is more robust.

Release Notes:

- Will require a DB migration

TODO:
- [x] Pass randomized tests
- [x] Get ready for merging
2023-06-07 17:11:43 -07:00
Mikayla Maki
fc1f8c5657 Fixed ci 2023-06-07 16:58:55 -07:00
Mikayla Maki
8ca1a7d43d add scan_complete await 2023-06-07 16:51:54 -07:00
Max Brunsfeld
66f215cd13 Restructure LSP log view to show log messages in addition to RPC trace 2023-06-07 16:51:09 -07:00
Mikayla Maki
9e9d8e3a7b add mroe dbg 2023-06-07 16:50:15 -07:00
Mikayla Maki
9d58c4526d Fix warning 2023-06-07 16:45:36 -07:00
Mikayla Maki
5f143f689f Attempting to debug on ci... 2023-06-07 16:44:13 -07:00
Mikayla Maki
572d40381a Add track caller 2023-06-07 16:39:10 -07:00
Mikayla Maki
2c5e83bf72 Fixed a bug where buffer saved clocks would desynchronize in rare execution paths
co-authored-by: Max <max@zed.dev>
2023-06-07 16:10:45 -07:00
Max Brunsfeld
78f9642ac2 Emit project event when a language server sends a logMessage notification 2023-06-07 14:46:08 -07:00
Mikayla Maki
cd63ec2c7f fmt 2023-06-07 14:20:01 -07:00
Mikayla Maki
03a96d2793 Feature gate import 2023-06-07 14:15:20 -07:00
Mikayla Maki
0ac7a3bc21 fmt 2023-06-07 14:13:57 -07:00
Mikayla Maki
28ba27c9c5 Merge branch 'main' into stream-git-statuses 2023-06-07 14:12:58 -07:00
Mikayla Maki
34e134fafb Fix several randomized test failures with the new git status implementation 2023-06-07 14:10:17 -07:00
Max Brunsfeld
351e4863cd Fix some issues found when testing Elixir-LS (#2583)
Closes
https://linear.app/zed-industries/issue/Z-2209/popovers-dont-always-have-syntax-highlighted-code
Closes
https://linear.app/zed-industries/issue/Z-2206/highlight-syntax-in-hover-docs

* Fix a ton of errors in our logs due to us not recognizing that
`elixir-ls` does not support code actions.
* Syntax-highlight elixir code blocks in hover popovers
2023-06-07 12:21:48 -07:00
Max Brunsfeld
11ab1a8cc6 collab 0.13.1 2023-06-07 10:54:27 -07:00
Max Brunsfeld
be8d268eb9 Bump tree-sitter-yaml submodule to avoid broken child submodule 2023-06-07 10:50:03 -07:00
Max Brunsfeld
72372ddf0e Highlight hover code blocks as LSP's own language by default
The elixir LSP does not include a language name on its elixir code blocks.
2023-06-07 10:01:19 -07:00
Nate Butler
86ec43c908 Update createColorScheme to accept ThemeConfig (#2557)
- Added ThemeConfig
- Updated themes use ThemeConfig
- Refactoring
- Fixed TypeScript errors

Release Notes:
- N/A (No public facing changes)
2023-06-07 12:57:34 -04:00
Nate Butler
29de420b59 Organize misc files into theme, themes and styleTrees 2023-06-07 12:50:37 -04:00
Nate Butler
6269cec4f1 Minor updates 2023-06-07 12:40:49 -04:00
Max Brunsfeld
6067575e38 collab 0.13.0 2023-06-07 09:29:58 -07:00
Max Brunsfeld
f56d642b88 Disable scheduled randomized test workflow for now 2023-06-07 09:20:25 -07:00
Joseph Lyons
8882b22c9c v0.91.x dev 2023-06-07 11:57:41 -04:00
Piotr Osiewicz
e94129446d Z 1618/extend comments (#2585)
Fixes Z-1618. In the current state, this only works for line comments
such as `//` (and whatever's set in `{language}.toml` as a
line_comment).

Release Notes:

- Comments are now extended on new line.
2023-06-07 17:37:02 +02:00
Sergii Onufriienko
b1f009cdce Merge branch 'main' into sergey/z-1768-update-createcolorscheme-to-accept-a-theme-in-the 2023-06-07 16:12:13 +01:00
Sergey Onufrienko
4c405e65a3 feat: use theme index to build licenses 2023-06-07 16:10:16 +01:00
Sergey Onufrienko
0ad76ac92c feat: use theme index to build themes 2023-06-07 16:10:02 +01:00
Sergey Onufrienko
02c1efc60d feat: re-export chroma 2023-06-07 16:09:24 +01:00
Sergey Onufrienko
f5d1f314e0 feat: add themes index 2023-06-07 16:08:58 +01:00
Sergey Onufrienko
d2b8501347 feat: change themes to return ThemeConfig 2023-06-07 16:08:48 +01:00
Antonio Scandurra
d5441ba386 Introduce an Assistant Panel (#2584)
This pull request introduces a new assistant panel to Zed that lets
users interact with OpenAI using their API key:

![CleanShot 2023-06-07 at 09 39
10@2x](https://github.com/zed-industries/zed/assets/482957/ba2a5830-9aeb-4c45-a182-a44d6a72675f)

After setting the key up, it will be saved to the keychain and
automatically loaded the next time the assistant panel is opened. The
key can be reset using `assistant: reset key`.

![CleanShot 2023-06-07 at 09 39
23@2x](https://github.com/zed-industries/zed/assets/482957/a6808bb0-0098-45ae-a2e3-f4d88472e626)

From there, users can type messages in a multi-buffer and hit
`cmd-enter` (`assistant: assist`) to stream assistant responses using
the OpenAI API. Responses can be canceled by hitting `escape`.

![CleanShot 2023-06-07 at 09 40
16@2x](https://github.com/zed-industries/zed/assets/482957/749779da-850e-4ad5-af04-74a3ca39f7ad)

Users can quote a selection from the active editor by hitting `cmd->`
(`assistant: quote selection`), which will embed the selected piece of
text in a Markdown fenced code block. Conversations with the assistant
are ephemeral at the moment, but can be easily copy/pasted:

![CleanShot 2023-06-07 at 09 50
33@2x](https://github.com/zed-industries/zed/assets/482957/b3386c10-4c51-4419-a0e0-517112ef6521)

Release Notes:

- Added a new assistant panel feature that enables interacting with
OpenAI using an API key. This replaces the previous experimental `ai:
assist` command that would work on any buffer. The experience is similar
to the one offered by ChatGPT with the added ability to edit, delete or
enhance previous messages. When hitting `cmd-enter`, the assistant will
start streaming responses from OpenAI. A response stream can be canceled
using `escape`. Moreover, the active editor's selection can be quoted in
the assistant panel using `cmd->`, which will automatically embed the
selected piece of text in a Markdown fenced code block.
2023-06-07 16:05:57 +02:00
Antonio Scandurra
d3e0d38bef Fix assistant panel tests 2023-06-07 15:24:08 +02:00
Antonio Scandurra
d26cc2c897 Maintain scroll bottom when streaming assistant responses 2023-06-07 15:01:50 +02:00
Antonio Scandurra
43500dbf60 Fix zed tests 2023-06-07 10:02:35 +02:00
Antonio Scandurra
0dae8f2dd8 Merge remote-tracking branch 'origin/main' into assistant-2 2023-06-07 09:34:16 +02:00
Antonio Scandurra
a6feaf1300 Allow search assistant editors 2023-06-07 09:24:18 +02:00
Joseph Lyons
c93b6cc599 Tweak comment wording 2023-06-07 00:23:58 -04:00
Max Brunsfeld
e8479f23f9 Improve log message on invalid LSP message from server's stdout 2023-06-06 17:13:59 -07:00
Max Brunsfeld
6f2726524e Remove stray println 2023-06-06 17:13:59 -07:00
Max Brunsfeld
fccbac4887 Handle LSP codeActions capability set to false 2023-06-06 17:13:59 -07:00
Max Brunsfeld
0d90c6d02e Improve syntax highlighting and outline view for Elixir (#2582)
Fixes
https://linear.app/zed-industries/issue/Z-2208/outline-view-doesnt-differentiate-between-overloaded-functions
Fixes
https://linear.app/zed-industries/issue/Z-2205/elixir-syntax-highlighting-not-working-properly-for-doc-attributes-and

This PR improves syntax highlighting and outline view in Elixir. It's
common to overload elixir functions, with many different versions of the
function for different patterns of parameters, so I updated the outline
view to show functions' parameters in Elixir. But if we showed functions
the same way in the *breadcrumbs*, it would take up too much space.

So I added a new capture in languages' `outline` queries called
`@context.extra`, which is included in the outline view, but not in
breadcrumbs.

Release Notes:

- Improved syntax highlighting of doc attributes and special macros in
Elixir
- Updated the outline view in Elixir to display function parameters, to
allow differentiating between function overloads.
2023-06-06 16:34:33 -07:00
Max Brunsfeld
4b9a3c66e6 Show function parameters in elixir outline view
Introduce a new capture in the outline query called 'context.extra', which
causes text to appear in the outline, but not in the breadcrumbs.
2023-06-06 16:27:05 -07:00
Max Brunsfeld
7aeaa84657 Fix the order of some patterns in elixir highlight query 2023-06-06 16:06:16 -07:00
Max Brunsfeld
8dc679e74e Upgrade tree-sitter-elixir 2023-06-06 16:06:16 -07:00
Max Brunsfeld
6737ee1495 Avoid panic when failing to load a language's queries 2023-06-06 16:06:16 -07:00
Piotr Osiewicz
cc63d3d048 chore: add targets to rust-toolchain.toml (#2581) 2023-06-07 00:12:47 +02:00
Max Brunsfeld
a9f865d828 Don't apply the 'literal' color to entire markdown code blocks (#2579)
### Before

![Screen Shot 2023-06-06 at 2 32 46
PM](https://github.com/zed-industries/zed/assets/326587/036f1da3-19c6-4979-adc6-c3133f8d63dc)

### After

![Screen Shot 2023-06-06 at 2 32 08
PM](https://github.com/zed-industries/zed/assets/326587/6d4729db-b76a-4052-847e-fd9de346f194)

Release Notes:

* Improved the syntax highlighting of fenced code blocks in markdown.
2023-06-06 14:54:24 -07:00
Piotr Osiewicz
dfd72770e7 chore: bump MSRV to 1.70, add rust-toolchain (#2580)
This time I've added a `components` section to rust-toolchain.toml file
to explicitly require a rustfmt component. Fingers crossed.
2023-06-06 23:49:34 +02:00
Max Brunsfeld
3fc2e0754b Don't apply the 'literal' color to entire markdown code blocks 2023-06-06 14:34:45 -07:00
Max Brunsfeld
bdd3e77e02 Live-reload tree-sitter queries in development (#2578)
This PR adds live reloading of Tree-sitter queries when running in debug
mode, similar to what we do for the themes. This way, you can change a
highlighting query or an outline query, and immediately see the result
in the app.

Release Notes:

- N/A
2023-06-06 14:30:28 -07:00
Max Brunsfeld
7bfb51ee76 Live-reload tree-sitter queries in development 2023-06-06 14:20:21 -07:00
Piotr Osiewicz
559a58d737 Revert "chore: bump MSRV to 1.70" (#2577)
Reverts zed-industries/zed#2573
2023-06-06 22:21:34 +02:00
Piotr Osiewicz
c1c91dc2e3 chore: bump MSRV to 1.70 (#2573)
Add rust-toolchain.toml

Release Notes:

- N/A
2023-06-06 21:50:27 +02:00
Piotr Osiewicz
572c59eec4 chore: Enable full LTO (#2548)
Per conversation with Antonio, I've suggested enabling full LTO; right
now we use a crate-local ThinLTO, which does not inline function calls
across crates.

| Configuration    | Current main (788f97e) | Thin LTO  | Full LTO  |
|------------------|------------------------|-----------|-----------|
| Size in bytes    | 158806721              | 155868753 | 111115553 |
| % of `main` size | 100%                   | 98.14%    | 69.96%    |
| Size in bytes (no debug info) | 129186657 | 127942929 | 108281345 |
2023-06-06 21:50:08 +02:00
Max Brunsfeld
17560cc5b0 Eliminate assets crate (#2575)
Previously, all static assets were embedded into Zed using a single
`RustEmbed` struct called `Assets`, which was in a crate of its own,
also called `assets`. Many crates depended on this crate. The problem
with this situation was that changing *any* static asset file caused
almost every crate in the codebase to need recompilation (because of
recursive dependencies on `assets`).

Now, most of the assets are embedded only into the top-level `zed`
crate. A few assets (such as settings JSON files and AI prompts) are
needed in lower-level crates such as `settings` and `ai`. For these,
I've created separate `RustEmbed` structs in those specific crates,
which embed those specific sub-folders of `assets`.

The result is that now, when you change a theme file, the only crate
that needs to recompile is `zed`.

Release Notes:

- N/A
2023-06-06 12:00:44 -07:00
Max Brunsfeld
dbbd0558c3 Eliminate assets crate 2023-06-06 11:46:46 -07:00
Joseph Lyons
2003d3dbe4 Update initial_user_settings.json 2023-06-06 14:39:56 -04:00
Antonio Scandurra
7a78e64831 Merge remote-tracking branch 'origin/main' into assistant-2 2023-06-06 19:18:22 +02:00
Antonio Scandurra
16090c35ae Insert reply after assistant message when hitting cmd-enter
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-06-06 19:15:06 +02:00
Antonio Scandurra
ef7ec265c8 Cycle message roles on click
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-06-06 18:45:08 +02:00
Max Brunsfeld
53906fd3da Add an application menu item for creating/opening a project-specific settings file (#2572)
Previously, project-specific settings were not discoverable. This PR
adds a `Zed > Preferences > Local Settings` application menu command
that creates a `.zed/settings.json` at the root of your current
worktree. This command works in both local and remote projects.

Limitations:

* Currently, if you have an empty project open, the command just shows a
notification that there are no folders open.
* The JSON-schema-based autocomplete is the same in local settings files
as in your main settings, even though not all settings can be locally
customized.

Release Notes:

- Added an application menu command - `Zed > Preferences > Local
Settings` for creating a folder-specific settings file.
2023-06-06 09:27:36 -07:00
Antonio Scandurra
ac7178068f Include message headers in copied assistant text
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-06-06 18:18:04 +02:00
Max Brunsfeld
cfcfc3bf6b Show notification when attempting to open local settings in a project w/ no folders 2023-06-06 09:03:57 -07:00
Antonio Scandurra
093ce8a9ac Simplify prompt
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-06-06 17:45:58 +02:00
Nate Butler
7b066df7e6 Tighten up spacing in the project panel (#2574)
Following https://github.com/zed-industries/zed/pull/2559 the project
panel entries become pretty wide again. This PR tries to mitigate that
and just make some general improvements to visual density in the project
panel.

- Reduces padding around items
- Removes top margin
- Slightly reduces the height of each item
- Fixes an issue where ignored files had the wrong color chevron

Release Notes:

- Improved density of the project panel and tidied up some visual
issues.
2023-06-06 11:31:53 -04:00
Piotr Osiewicz
a0e2e5db7d project panel/styles: Align child's chevron with parent path (#2559)
Z-1012

Release notes:
- Adjust indent of files in subdirectories.
2023-06-06 16:55:38 +02:00
Antonio Scandurra
2b1aeb07bc Show error message when requests to OpenAI fail
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-06-06 16:53:56 +02:00
Antonio Scandurra
9c59146026 Set assistant editor's title based on the first question/answer pair
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-06-06 15:59:10 +02:00
Antonio Scandurra
69b8267b6b Show the current model and allow clicking on it to change it 2023-06-06 13:13:44 +02:00
Antonio Scandurra
ada222078c Insert a user reply when hitting cmd-enter in an assistant message 2023-06-06 13:13:41 +02:00
Antonio Scandurra
f4f060667e Add assertion to pinpoint how deletion works across excerpts 2023-06-06 12:36:26 +02:00
Antonio Scandurra
337dda8e3a Only remove excerpts when an edit touches them 2023-06-06 12:27:05 +02:00
Antonio Scandurra
8032324470 Prevent moving across excerpts on Editor::delete 2023-06-06 12:26:53 +02:00
Antonio Scandurra
e46d1549d6 Retain selection's head (as opposed to its end) on insertion
This makes a difference when an edit spans two excerpts and the selection
start won't necessarily be the same as the selection end after the edit.
2023-06-06 10:12:15 +02:00
Nathan Sobo
23836eb251 Not working yet: Remove empty messages unless they contain the cursor
Problem is, I'm trying to trust the excerpt id of the selection head,
but it's a sentinel value and not the actual excerpt id of the message.
I think we probably need to resolve to offsets instead.
2023-06-05 22:58:08 -06:00
Max Brunsfeld
296a0bf510 Populate created local settings file with an empty JSON object and comments 2023-06-05 18:20:02 -07:00
Max Brunsfeld
cb975f1252 Add Zed > Preferences > Local Settings to application menu 2023-06-05 17:45:42 -07:00
Max Brunsfeld
0949ee84d8 🎨 Move OpenSettings action back to the zed crate 2023-06-05 17:43:05 -07:00
Mikayla Maki
a2d58068a7 Improve test generation and implement status propogation
co-authored-by: max <max@zed.dev>
2023-06-05 17:30:12 -07:00
Mikayla Maki
c12bdc894a Silence not found errors 2023-06-05 15:19:59 -07:00
Max Brunsfeld
398b0f303c Apply bounds to all windows when using start-local-collaboration script (#2570)
The `start-local-collaboration` script opens two instances of Zed, each
logged in as a different user, and each one taking up half of the
screen. But previously, when joining a remote project as one of the
collaborators, that newly-opened window would be full screen.

Now, each instance of Zed keeps *all* of its windows on its half of the
screen. This is implemented by respecting the `ZED_WINDOW_{SIZE,BOUNDS}`
env vars, even when joining *remote* projects.

Release Notes:

- N/A
2023-06-05 14:49:39 -07:00
Max Brunsfeld
3d1ba1b363 Apply bounds to all windows when using start-local-collaboration script 2023-06-05 14:36:21 -07:00
Max Brunsfeld
571151173c Fix copilot state corruption when there are multiple buffers with the same remote id in different projects (#2569)
Fixes
https://linear.app/zed-industries/issue/Z-1511/thread-main-panicked-at-assertion-failed-left-==-right-left-local-0-1

Previously, when exchanging messages about buffers with a copilot
language server, we identified buffers using their **remote id**. This
caused problems when there were multiple projects open, where one or
more were remote, because buffers' remote ids are only unique within a
given project.

When you have multiple projects open, and one or more of the projects is
remote, it's pretty easy to have two buffers open with the same remote
id. In my testing, when this happened, copilot would stop working in
both buffers. But I believe that depending on the editing patterns that
occur in the two buffers, it could cause the crash reported in the
Linear issue above.

This PR changes our copilot logic to use buffers' local handle ids for
identifying them. This fixed the problems I was able to reproduce when
using copilot in both remote and local projects.

Release Notes:

- Fixed a crash that would sometimes occur when editing buffers after
having collaborated on a remote project.
2023-06-05 14:33:56 -07:00
Max Brunsfeld
12dd91c89c Use local ids, not remote ids, to identify buffers to copilot 2023-06-05 14:12:19 -07:00
Mikayla Maki
5e4da6433f Add file and line number information to logs (#2568)
This PR adds codegen from rustc to track the file and line number of
calls to `log_err()`. I haven't noticed much longer compile times on my
machine, and looking at the
[implementation](https://rustc-dev-guide.rust-lang.org/backend/implicit-caller-location.html)
it essentially adds an extra argument and secret reference pass.
However, this will show a lot more data in our logs on user machines.
Requesting review from @ForLoveOfCats, who usually knows a bunch about
this kind of thing :)
2023-06-05 13:24:07 -07:00
Mikayla Maki
624467ebca Add file and line number information to logs 2023-06-05 12:53:37 -07:00
Mikayla Maki
9a13a2ba2c WIP: Add status bubbling to project panel 2023-06-05 12:53:04 -07:00
Joseph T. Lyons
7fbafc8030 Remove code sending zed events to mixpanel (#2567)
Release Notes:

- N/A
2023-06-05 15:40:27 -04:00
Joseph Lyons
311074e397 Remove code sending zed events to mixpanel 2023-06-05 15:33:17 -04:00
Mikayla Maki
49c5a3fa86 Add postgres migration 2023-06-05 12:17:21 -07:00
Joseph T. Lyons
2190a27dff Stop sending editor events to mixpanel (#2566)
Release Notes:

- N/A
2023-06-05 15:15:30 -04:00
Joseph Lyons
70c5489c13 Stop sending editor events to mixpanel 2023-06-05 15:09:47 -04:00
Mikayla Maki
4ac5f7b14e Add statuses to test integration 2023-06-05 12:06:23 -07:00
Mikayla Maki
e56fcd69b5 Track git status changes with the changed_paths system 2023-06-05 11:50:23 -07:00
Joseph T. Lyons
4f3165692f Move app version into panic object (#2565)
Final tweaks to clean up how we structure our panic data

Release Notes:

- N/A
2023-06-05 14:40:28 -04:00
Joseph Lyons
917d8949b7 Move app version into panic object 2023-06-05 14:17:48 -04:00
Julia
6b89243902 Update rust-bindgen dev-dependencies (#2563)
I did \*something\* Friday afternoon which changed something about my
system SDK to break the `media` crate's bindings generation. Some of the
types and consts were not being generated despite being able to prove
that they exist in the source, such as when running the header through
the preprocessor myself and feeding that through the generator. Updating
my OS, XCode, command line tools, and reinstalling Rust as well as
working from fresh clones of the repo had no effect.

Updating rust-bindgen resolved the issue and downgrading the version
back to the original version caused the issue to reappear. I'm still not
sure what happened to change the SDK but at this point with being able
to build the project again I'm not going to look a gift horse in the
mouth.

Release Notes:

- N/A
2023-06-05 09:21:07 -04:00
Antonio Scandurra
0ed8bbc818 Query rect_for_text_range on focused view instead of root element (#2564)
This was causing IME input to be drawn in the wrong place when there
were splits or panels in the window.

Release Notes:

- Fixed a bug that was causing IME input to sometimes be rendered in the
wrong position.
2023-06-05 12:11:35 +02:00
Antonio Scandurra
c872f581d1 Query rect_for_text_range on focused view instead of root element
This was causing IME input to be drawn in the wrong place when there
were splits or panels in the window.
2023-06-05 12:00:40 +02:00
Antonio Scandurra
bef6932da7 Avoid accidentally taking the api_key when requesting an assist 2023-06-05 11:25:21 +02:00
Julia
5790d6993e Update rust-bindgen dev-dependencies 2023-06-04 23:34:22 -04:00
Joseph T. Lyons
a89f3ed445 Fix typos (#2562)
Quite literally just ran `typos --write-changes` from
https://crates.io/crates/typos. Its pretty impressive - wonder if we
should run it on CI.

Release Notes:

- N/A
2023-06-02 22:08:45 -04:00
Joseph Lyons
7c60f636d5 Fix typos 2023-06-02 22:02:19 -04:00
Mikayla Maki
ca077408d7 Fix bug where git statuses would not be initialized on startup
move git status queries to be on entry creation

co-authored-by: max <max@zed.dev>
2023-06-02 17:38:39 -07:00
Mikayla Maki
2f97c7a4f1 Remove stale comments
Implement status bubbling query with sum tree traversals

co-authored-by: max <max@zed.dev>
2023-06-02 16:41:01 -07:00
Mikayla Maki
e377459948 Remove stateful bubbling
co-authored-by: max <max@zed.dev>
2023-06-02 15:07:49 -07:00
Mikayla Maki
99a0e11e70 Abandoning stateful bubbling approach
co-authored-by: max <max@zed.dev>
2023-06-02 14:51:40 -07:00
Max Brunsfeld
46d2cbaa4c Improve panic reports (#2560)
* Add an `identifying_backtrace` field that only contains symbols in
*our* own codebase, which can be used for better deduplication.
* In the main backtrace, include file and line numbers for all symbols
in our codebase
* Exclude any stack frames within the panic handling/hooking system
itself, so that the top line of the backtrace is where the panic
originated in our codebase.

This should improve our panic deduplication, and also make panic reports
a bit more readable.

example:

```
{
  "thread": "main",
  "payload": "wtf",
  "location_data": {
    "file": "crates/zed/src/zed.rs",
    "line": 459
  },
  "backtrace": [
    "zed::open_log_file::{{closure}}::{{closure}}::{{closure}}",
    "    crates/zed/src/zed.rs:459",
    "gpui::app::AppContext::spawn_internal::{{closure}}",
    "    crates/gpui/src/app.rs:2073",
    "gpui::executor::any_local_future::{{closure}}",
    "    crates/gpui/src/executor.rs:1026",
    "<core::pin::Pin<P> as core::future::future::Future>::poll",
    "<async_task::runnable::spawn_local::Checked<F> as core::future::future::Future>::poll",
    "async_task::raw::RawTask<F,T,S>::run",
    "async_task::runnable::Runnable::run",
    "<gpui::platform::mac::dispatcher::Dispatcher as gpui::platform::Dispatcher>::run_on_main_thread::trampoline",
    "    crates/gpui/src/platform/mac/dispatcher.rs:40",
    "<() as objc::message::MessageArguments>::invoke",
    "objc::message::platform::send_unverified",
    "objc::message::send_message",
    "<gpui::platform::mac::platform::MacForegroundPlatform as gpui::platform::ForegroundPlatform>::run",
    "    crates/gpui/src/platform/mac/platform.rs:366",
    "gpui::app::App::run",
    "    crates/gpui/src/app.rs:251",
    "Zed::main",
    "    crates/zed/src/main.rs:118",
    "core::ops::function::FnOnce::call_once",
    "std::sys_common::backtrace::__rust_begin_short_backtrace",
    "std::rt::lang_start::{{closure}}",
    "core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once",
    "std::rt::lang_start"
  ],
  "release_channel": "dev",
  "os_name": "macOS",
  "os_version": "12.6.1",
  "architecture": "aarch64",
  "panicked_on": 1685734744050,
  "identifying_backtrace": [
    "zed::open_log_file::{{closure}}::{{closure}}::{{closure}}",
    "gpui::app::AppContext::spawn_internal::{{closure}}",
    "gpui::executor::any_local_future::{{closure}}",
    "<gpui::platform::mac::dispatcher::Dispatcher as gpui::platform::Dispatcher>::run_on_main_thread::trampoline",
    "<gpui::platform::mac::platform::MacForegroundPlatform as gpui::platform::ForegroundPlatform>::run",
    "gpui::app::App::run",
    "Zed::main"
  ]
}
```

Release Notes:

N/A
2023-06-02 13:11:57 -07:00
Max Brunsfeld
33c4c32196 Avoid writing spurious nulls to the settings file when updating it programatically (#2561)
Thanks for catching this @iamnbutler.
2023-06-02 13:11:35 -07:00
Max Brunsfeld
7417835f06 Avoid writing spurious nulls to settings file when updating it programatically 2023-06-02 13:02:17 -07:00
Max Brunsfeld
f6a4706410 Improve panic reports
* Add an 'identifying_backtrace' field that only contains symbols in our
  codebase, which can be used for better deduplication.
* In the main backtrace, include file and line numbers for all symbols
  in our codebase
2023-06-02 12:37:39 -07:00
Joseph T. Lyons
00265c19a0 Add additional panic information to panic events (#2555)
Adds the following to the panic event

release_channel
os_name
os_version
architecture

Merge first: https://github.com/zed-industries/zed.dev/pull/322

Release Notes:

- N/A
2023-06-02 14:30:16 -04:00
Piotr Osiewicz
345fad3e9d editor: add select previous command (#2556)
Added a `select previous` command to complement `select next`.
Release Notes:

- Added "Select previous" editor command, mirroring `Select next`.
Ticket number: Z-366
2023-06-02 17:32:34 +02:00
Antonio Scandurra
f00f16fe37 Show remaining tokens 2023-06-02 17:27:21 +02:00
Sergey Onufrienko
f97999d97f feat: update themes to use ThemeConfig 2023-06-02 14:11:11 +02:00
Sergey Onufrienko
5fbbc1936f fix: typescript errors 2023-06-02 14:10:44 +02:00
Sergey Onufrienko
b38f760fcd feat: add index export 2023-06-02 14:10:19 +02:00
Sergey Onufrienko
d3ed958308 chore: make SyntaxHighlightStyle.color optional 2023-06-02 14:10:02 +02:00
Sergey Onufrienko
6b00db75ad feat: update and refactor colorScheme 2023-06-02 14:08:35 +02:00
Sergey Onufrienko
56ecfaf2f0 feat: add themeConfig types 2023-06-02 14:07:43 +02:00
Antonio Scandurra
3750e64d9f Save OpenAI API key in the keychain 2023-06-02 12:15:25 +02:00
Piotr Osiewicz
571d2f4966 Z-1074/search default label (#2547)
This commit adds a default "Project search" tooltip for empty search
panes. Fixes Linear ticket Z-1074
Release Notes:

- Added default tooltip to empty search panes.
([#1533](https://github.com/zed-industries/community/issues/1533)).
2023-06-02 11:42:40 +02:00
Antonio Scandurra
a81d164ea6 Allow saving the OpenAI API key in the assistant panel 2023-06-02 11:38:02 +02:00
Antonio Scandurra
d0aff65b1c Allow moving the assistant panel to other docks 2023-06-02 10:55:19 +02:00
Antonio Scandurra
55c8c6d3fb Allow adding new contexts 2023-06-02 10:29:22 +02:00
Antonio Scandurra
cf934ab696 Fix compile errors 2023-06-02 10:08:06 +02:00
Antonio Scandurra
20e65a533c Merge remote-tracking branch 'origin/main' into assistant-2 2023-06-02 09:32:11 +02:00
Mikayla Maki
3768851799 WIP: Git statuses 2023-06-01 23:27:49 -07:00
Joseph Lyons
c55aee84d3 Rename field to panicked_on 2023-06-02 01:33:25 -04:00
Joseph Lyons
cc055901e1 Add additional panic information to panic events 2023-06-01 23:34:39 -04:00
Mikayla Maki
5e43dcaab8 WIP: Add stateful status bubbling to worktree 2023-06-01 16:51:34 -07:00
Max Brunsfeld
0bd9d5b1fa Zoom out all panes when opening a dock (#2554)
Fixes
https://linear.app/zed-industries/issue/Z-2051/center-zoom-isnt-unset-when-opening-project-panel

Release Notes:

- Fixed a bug where opening the project panel did not reset the zoom
state of a pane.
2023-06-01 15:26:46 -07:00
Max Brunsfeld
585d13d3db Unzoom all panes when opening a dock 2023-06-01 15:20:15 -07:00
Max Brunsfeld
a55eafa726 Fix ambiguous glob export warnings in rust 1.70 (#2553)
This fixes a warning that is introduced when upgrading to Rust 1.70.

Release Notes:

- N/A
2023-06-01 14:37:36 -07:00
Max Brunsfeld
e67e6e6f70 Fix ambiguous glob export warnings in rust 1.70 2023-06-01 14:07:59 -07:00
Joseph T. Lyons
6d24a8a763 Add panic events (#2552)
Adds a time field to support panic events.  See

https://github.com/zed-industries/zed.dev/pull/321

Release Notes:

- N/A
2023-06-01 16:47:29 -04:00
Joseph Lyons
0065f5715c Add panic events 2023-06-01 16:40:54 -04:00
Mikayla Maki
9d6b3744f7 Redraw the terminal on every wakeup (#2551)
For whatever reason, the optimizations of panes and workspace have
caused the terminal to notify less often then it should. This PR fixes
that oversight.
2023-06-01 10:56:13 -07:00
Mikayla Maki
40c6baf7cb Redraw the terminal on every wakeup
co-authored-by: max <max@zed.dev>
2023-06-01 10:49:31 -07:00
Mikayla Maki
d64dc3960d Make settings store handle no user settings (#2550)
This fixes the crash users have been reporting with the theme selector
2023-06-01 10:25:30 -07:00
Mikayla Maki
2390815d67 Make settings store handle no user settings
co-authored-by: max <max@zed.dev>
2023-06-01 10:09:04 -07:00
Julia
2ffbeca7dd Avoid blocking forever on startup if config files do not exist (#2549)
The files will still get created if the user opens their settings and
saves, otherwise everything will transparently work

Release Notes:

- Fixed an issue where a missing settings file would cause a hang on
startup
([#1590](https://github.com/zed-industries/community/issues/1590)).
2023-06-01 12:13:22 -04:00
Julia
51c82da840 Avoid blocking forever on startup if config files do not exist
The files will still get created if the user opens their settings and
saves, otherwise everything will transparently work

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-06-01 12:04:45 -04:00
Kirill Bulatov
d8ce333cf8 Remove wrong assertion 2023-06-01 16:51:29 +03:00
Piotr Osiewicz
01621972c5 Change "Project search" to "Project Search" 2023-06-01 12:31:37 +02:00
Piotr Osiewicz
e1a6dc9077 search: Add a default tooltip for empty searches
Z-1074
2023-06-01 11:17:33 +02:00
Max Brunsfeld
788f97ec68 Add support for folder-specific settings (#2537)
This PR allows you to customize Zed's settings within a particular
folder by creating a `.zed/settings.json` file within that folder.

Todo

* [x] respect folder-specific settings for local projects
* [x] respect folder-specific settings in remote projects
* [x] pass a path when retrieving editor/language settings
* [x] pass a path when retrieving copilot settings
* [ ] update the `Setting` trait to make it clear which types of
settings are locally overridable

Release Notes:

* Added support for folder-specific settings. You can customize Zed's
settings within a particular folder by creating a `.zed` directory and a
`.zed/settings.json` file within that folder.
2023-05-31 16:27:08 -07:00
Max Brunsfeld
ae7606ce21 collab 0.12.5 2023-05-31 15:38:26 -07:00
Max Brunsfeld
0d281c1b89 🎨 2023-05-31 15:13:01 -07:00
Max Brunsfeld
0dd7694ff5 Make language_settings take a language, not a language name 2023-05-31 15:10:30 -07:00
Max Brunsfeld
03a351fb26 Make language settings accessors take an arc dyn file 2023-05-31 14:57:04 -07:00
Max Brunsfeld
38078b93cc v0.90.x dev 2023-05-31 14:44:48 -07:00
Max Brunsfeld
a2ab7c9eb9 Respect project-specific settings for copilot 2023-05-31 14:42:15 -07:00
Mikayla Maki
6f4fd74f43 Add a dock-keybinding-changed one-time notification (#2546)
This code is intended to be removed at a later date.

Release Notes:

- N/A
2023-05-31 14:28:12 -07:00
Mikayla Maki
bf2016adf5 Remove version check 2023-05-31 14:23:56 -07:00
Mikayla Maki
27ef0e2b52 De-morgans properly 2023-05-31 14:21:38 -07:00
Mikayla Maki
45b42c512d fmt 2023-05-31 14:17:27 -07:00
Mikayla Maki
705e36827c add version check 2023-05-31 14:16:37 -07:00
Mikayla Maki
b875d4ed40 Remove silly panic 2023-05-31 14:10:50 -07:00
Mikayla Maki
ed0b9acb0a Add panic if version is 0.91 2023-05-31 14:06:36 -07:00
Mikayla Maki
ef80b539d1 Fix notification styling, minimize database reads 2023-05-31 13:56:41 -07:00
Max Brunsfeld
62660f2766 Fix more issues with panels and zoom (#2545)
Release Notes:

* Fixed the behavior of panel buttons when their panel is open. Show the
key binding for closing the containing dock (preview only).
* Improved the styling of zoomed panels and panes, giving them a
stronger border, and color the zoom button with an "active" style
(preview only).
* Improved the stability of panels' zoom state. Close their dock instead
of resetting their zoom state when dismissing panels to reveal other
items (preview only).
2023-05-31 13:17:12 -07:00
Max Brunsfeld
193474a346 🎨 2023-05-31 13:07:20 -07:00
Max Brunsfeld
c48fed26bd When revealing items, zoom-out any inactive panes 2023-05-31 13:05:50 -07:00
Mikayla Maki
4717ce1da3 WIP: Move statuses to entries
co-authored-by: julia <julia@zed.dev>
2023-05-31 12:55:31 -07:00
Max Brunsfeld
3f6aa94a5f Use active color for zoom button in a zoomed pane 2023-05-31 12:51:57 -07:00
Max Brunsfeld
893615236d Only include one border edge for zoomed panels 2023-05-31 12:45:55 -07:00
Nate Butler
1f72f9e18b Add un-hooked up zoomIcon styles 2023-05-31 12:45:55 -07:00
Nate Butler
a10933c063 Update pane/panel zoom styling 2023-05-31 12:45:55 -07:00
Max Brunsfeld
ac41564a8f Dismiss zoomed panels by closing their dock, not zooming them out 2023-05-31 12:45:55 -07:00
Mikayla Maki
22e4086658 WIP: Move statuses to be on their associated file entries in worktree
co-authored-by: Julia <julia@zed.dev>
2023-05-31 11:03:11 -07:00
Sergii Onufriienko
c6672dbac2 Update theme license logic (#2541)
Use new theme file structure
```
themes/
  [theme_name]
    [theme_name]-common.ts
    [theme_name]-light.ts
    [theme_name]-dark.ts
    LICENSE
```

Release Notes: 
- N/A
2023-05-31 18:36:13 +01:00
Max Brunsfeld
76927b6d95 Make active panel's button close its dock 2023-05-31 10:29:59 -07:00
Max Brunsfeld
eeba72d775 Bump protocol version 2023-05-31 09:03:45 -07:00
Max Brunsfeld
8f95435548 Replicate project-specific settings when collaborating 2023-05-30 18:08:03 -07:00
Mikayla Maki
c9820fde61 WIP: Add toast when users attempt to use shift-escape for the first time 2023-05-30 17:48:41 -07:00
Mikayla Maki
584e5f7958 Fix usability issues with new panel system. (#2544)
This PR updates the dock key bindings according to the following model:

There are three bits: 
Visible: Opened / closed.
Focus: Panel focused / center focused.
Zoom: Zoomed / Not zoomed.

Each of these variables is 'sticky' in that they won't effect each other
unless they need to. 'Zooming' a panel conceptually merges the visible
and focus bits.

cmd-shift-j/b/r have all been removed.

cmd-j/b/r have been updated to mean 'toggle visibility of a certain
dock', firing them should *always* reveal the panel to you (where you
last left it), or hide it, without moving focus (unless the focused
element is invisible). This means that, when the terminal panel is
zoomed, cmd-j has the same effect as ctrl-`

ctrl-` and cmd-shift-e now toggle a panel's focus, without updating the
zoom state of a panel. Toggling the focus of a zoomed panel causes it to
automatically hide itself, without losing the zoom bit.

When focused or made visible, panels which cannot be zoomed
automatically unzoom everything else so as to preserve user intent of
'show me this panel' and 'everything stays where it is if I don't take
an action'

Release Notes:

- cmd-shift-j/b/r have been removed.  (preview only)
- cmd-j/b/r unconditionally show or hide their associated dock,
respecting zoom settings. (preview only)
- ctrl-` and cmd-shift-e now retain zoom state. (preview only)
- Fixed a bug where terminal dock tab would always be in the active
state (preview only)
- Fixed a bug where terminals would not always open in the terminal
panel
- Changed the look of zoomed panels to fill more of the screen (preview
only)
2023-05-30 16:39:06 -07:00
Mikayla Maki
0122cd61c5 fmt 2023-05-30 16:33:42 -07:00
Mikayla Maki
685e8d7007 Seperate pane and panel styling
co-authored-by: max <max@zed.dev>
2023-05-30 16:23:16 -07:00
Mikayla Maki
9c707eff27 Rework new terminal actions 2023-05-30 16:10:07 -07:00
Mikayla Maki
e80ab5f096 Fix focus bug with new docks
co-authored-by: max <max@zed.dev>
2023-05-30 15:40:30 -07:00
Mikayla Maki
5e4a9abd09 Fix bug in panel button dispatch 2023-05-30 15:17:42 -07:00
Mikayla Maki
5065804388 WIP: iron out bugs in interaction between toggle and toggle focus key bindings
co-authored-by: max <max@zed.dev>
2023-05-30 14:55:49 -07:00
Julia
8f0fc918e9 TextStyle::default() ask system for known existing font family (#2542)
Rather than assuming a specific family exists, try a set of specific
names and if they fail, just grab any old font that the system reports
as existing

Closes
https://linear.app/zed-industries/issue/Z-445/thread-main-panicked-at-called-resultunwrap-on-an-err-value-could-not

Release Notes:

* Fixed crash that could happen if system did not have a specific
fallback font
2023-05-30 16:25:07 -04:00
Mikayla Maki
9c9af5ed94 Remove focus side effects from toggle dock commands
co-authored-by: max <max@zed.dev>
2023-05-30 12:32:00 -07:00
Joseph Lyons
efcf78cbe9 Update pull_request_template.md 2023-05-30 15:15:20 -04:00
Joseph T. Lyons
e9ce85ebc0 Scrape email from feedback editor (#2543)
Add release note lines here:

N/A
2023-05-30 15:13:35 -04:00
Joseph Lyons
501f9ab2c6 Scrape email from feedback editor 2023-05-30 15:06:35 -04:00
Mikayla Maki
1a23fe91b4 WIP: Remove focus side effects from toggle dock commands
co-authored-by: max <max@zed.dev>
2023-05-30 12:00:15 -07:00
Mikayla Maki
84f98f13c4 Seperate open and zoom bits conceptually for new panels
co-authored-by: max <max@zed.dev>
2023-05-30 11:52:14 -07:00
Julia
31516b7863 TextStyle::default() ask system for known existing font family
Rather than assuming a specific family exists, try a set of specific
names and if they fail, just grab any old font that the system reports
as existing

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-30 14:46:27 -04:00
Sergey Onufrienko
51c7078f47 chore: remove license_text 2023-05-30 18:16:50 +02:00
Sergey Onufrienko
4568f80f2e feat: read from LICENSE file 2023-05-30 18:12:31 +02:00
Sergey Onufrienko
14efc18eca refactor: add license file and check it exists 2023-05-30 18:11:54 +02:00
Sergey Onufrienko
05d1dd6b11 refactor: move common to theme folder 2023-05-30 16:53:12 +02:00
Sergey Onufrienko
ac63043c27 chore: move similar themes to one folder 2023-05-30 16:52:28 +02:00
Sergey Onufrienko
0d62e76cd6 refactor: colorSchemes 2023-05-30 15:52:32 +02:00
Antonio Scandurra
69e8a166e4 Start on assistant::QuoteSelection 2023-05-30 15:25:53 +02:00
Antonio Scandurra
dc365472a6 Merge remote-tracking branch 'origin/main' into assistant-2 2023-05-30 15:11:06 +02:00
Antonio Scandurra
1fc9103b61 Remove methods taking &mut Workspace from Pane (#2540)
This pull request simplifies the `Pane` struct by replacing methods like
`Pane::add_item` that would previously take a `&mut Workspace` with
methods that take a `&mut self`. When access to the workspace is needed,
we now either emit an event from the `Pane` or directly move the method
to the `Workspace` struct.
2023-05-30 15:01:35 +02:00
Antonio Scandurra
bd494037bb Call ItemHandle::added_to_pane when an item is added to a pane 2023-05-30 14:46:41 +02:00
Sergey Onufrienko
2269c19169 chore: add LICENSE files 2023-05-30 14:06:19 +02:00
Nathan Sobo
8a851ad7f8 Fix annoying system prompt (#2538)
I was having fun, but it was too much. It makes the assistant too
annoying to be useful.

Release Notes:

Use `N/A` in this section if this item should be skipped in the release
notes.

Add release note lines here:

* Dialed back the system prompt on the assistant.
2023-05-29 22:05:40 -06:00
Nathan Sobo
063613bf4e Fix annoying system prompt
I was having fun, but it was too much. It makes the assistant too annoying to be useful.
2023-05-29 21:47:59 -06:00
Max Brunsfeld
ed0fa2404c Use settings JSON schema when editing local settings files 2023-05-29 14:31:54 -07:00
Max Brunsfeld
89446c7fd4 Start work on respecting project-specific settings 2023-05-29 14:25:49 -07:00
Antonio Scandurra
88eb2b2163 Move history navigation logic to Workspace
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-29 19:47:59 +02:00
Antonio Scandurra
6d3464fd1f Make Pane::add_item a proper Pane method
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-29 19:16:22 +02:00
Antonio Scandurra
890c42a75a Show time in assistant messages 2023-05-29 16:23:16 +02:00
Kirill Bulatov
edf8e276af Improves project search panel shortcut handling (#2536)
* ESC (project_search::ToggleFocus) toggles focus from include/exclude
fields to the editor

* Cmd+Shift+F (workspace::NewSearch) can be triggered from the editor,
and moves focus to the query editor

Release Notes:

* Improved project search panel shortcut handling, allowing more actions
to trigger from panel elements
2023-05-29 17:06:38 +03:00
Kirill Bulatov
d593377e45 Improves project search panel shortcut handling
* ESC (project_search::ToggleFocus) toggles focus from
  include/exclude fields to the editor

* Cmd+Shift+F (workspace::NewSearch) can be triggered from the editor,
and moves focus to the query editor
2023-05-29 16:58:06 +03:00
Antonio Scandurra
52e8bf2928 Show custom header for assistant messages 2023-05-29 15:57:55 +02:00
Sergey Onufrienko
cf75b090d3 feat: organize themes by folders with LICENSE 2023-05-29 15:45:13 +02:00
Kirill Bulatov
986b02e217 Update LSP to the newest version (#2535)
Current `lsp-types:0.91.1` crate lacks inlay hints' definitions. Crate's
changelog is not very descriptive, but it appears that `0.92.1` could be
used:
https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md#v0921-2022-03-21
The latest is crate version is `0.94.0` (2023-02-08), the PR updates Zed
to the latest version.


Notable changes:
* workspace symbols may arrive unresolved if the corresponding client
capability is enabled:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#partialResults
Zed has this capability disabled, forcing all symbols to arrive
synchronously (?).

Resolve capabilities are important for inlay hints too, but I've not
found any code in Zed for that outside tests, so I'd love to learn more
and implement the resolution for workspace symbols separately.

* since LSP `3.17` (current), watch file changes can use relative glob
patterns:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles

That seemed just a straightforward extra `match` to use the same Ruse
`Glob` to handle the relative path one.

Release Notes:

N/A
2023-05-29 12:49:37 +03:00
Antonio Scandurra
404bebab63 Set markdown as the assistant's buffer languages 2023-05-29 11:34:26 +02:00
Kirill Bulatov
fdad1adaf6 Update LSP to the newest version 2023-05-28 21:55:08 +03:00
Max Brunsfeld
e4530471de Make worktree UpdatedEntries events fully describe all changes (#2533)
This PR makes the worktree's change events more useful in a few ways:

* The changes are now described by a cheaply clone-able collection, so
that they can be used in background tasks. Right now, I'm using a simple
Arc slice.
* The `UpdatedEntries` event now captures not only changes due to FS
changes, but also newly-loaded paths that are discovered during the
initial scan.
* The `UpdatedGitRepositories` event now includes repositories whose
work-dir changed but git dir didn't change. A boolean flag is included,
to indicate whether the git content changed.
* The `UpdatedEntries` and `UpdatedGitRepositories` events are now
*used* to compute the worktree's `UpdateWorktree` messages, used to sync
changes to guests. This unifies two closely-related code paths, and
makes the host more efficient when collaborating, because the
`UpdateWorktree` message computation used to require walking the entire
`entries` tree on every FS change.
2023-05-26 15:55:14 -07:00
Max Brunsfeld
1f42bfc1bd Include repositories with workdir changes in worktree UpdatedGitRepsositories event 2023-05-26 15:47:37 -07:00
Max Brunsfeld
2db57b5139 Adjust diagnostic transformation test to not wait for two buffer notifications 2023-05-26 15:47:37 -07:00
Max Brunsfeld
02b95ef320 Derive worktree update messages from existing change events 2023-05-26 15:47:37 -07:00
Kirill Bulatov
9cfe39f1aa Display external paths in history (#2534)
Fixes
https://linear.app/zed-industries/issue/Z-1793/file-finder-external-recent-paths-are-not-rendered-properly

Long paths get trimmed, but same do many of our other elements, such as
type definitions, so I think it's ok for now:

![image](https://github.com/zed-industries/zed/assets/2690773/b8b6588d-6d6b-42db-9085-c741a40b7adb)

Also, we seem to do a lot of odd diagnostics handling on every external
stdlib file opened:

![image](https://github.com/zed-industries/zed/assets/2690773/cd82c54e-7849-46fe-a01c-79bfc5402b7b)
Other external files also emit similar messages, but not that much.
@\mikayla-maki mentioned, that this was happening before, so can be
fixed separately.
The PR adds path printing to these logs.

Release Notes:

* Fixed external files not being displayed properly in the recently
opened list in the file finder panel
2023-05-27 01:27:24 +03:00
Kirill Bulatov
5fda9e934d Shorten full paths with ~ 2023-05-27 01:21:38 +03:00
Kirill Bulatov
3a3c1c5a5b Add a test
co-authored-by: Mikayla <mikayla@zed.dev>
2023-05-27 01:12:22 +03:00
Nathan Sobo
ffbfbe422b WIP: Not sure I actually want to rip this out 2023-05-26 16:11:58 -06:00
Nathan Sobo
3904971bd8 Hide assistant gutter 2023-05-26 15:38:03 -06:00
Nathan Sobo
8f6e67f440 Cancel assists on escape 2023-05-26 14:49:27 -06:00
Max Brunsfeld
6628c4df28 Store worktree changes in a sorted arc slice, not a HashMap
We don't need to look-up change types by an arbitrary key, but we
do need to iterate it. It would also be useful to be able to
cheaply clone the changes, to use them in a background task.
2023-05-26 09:24:15 -07:00
Max Brunsfeld
59bfd40679 Make stricter assertions about change events in random worktree test 2023-05-26 09:24:15 -07:00
Max Brunsfeld
f890eefdef Include paths loaded during initial scan in worktree UpdatedEntries event 2023-05-26 09:24:15 -07:00
Nathan Sobo
80080a43e4 Start on an assistant panel based on multi-buffers
Each message is represented as a multibuffer excerpt to allow for
fluid editing of the conversation transcript.

Co-Authored-By: Antonio Scandurra <antonio@zed.dev>
2023-05-26 10:09:55 -06:00
Kirill Bulatov
cf2bbfc85a Better display labels for external files 2023-05-26 18:18:32 +03:00
Kirill Bulatov
508533ebb7 Track abs paths in history 2023-05-26 17:31:35 +03:00
Kirill Bulatov
2fdc960704 Properly display labels for currently opened external files 2023-05-26 15:44:44 +03:00
Kirill Bulatov
b75c27da6f Simplify selected index handling 2023-05-26 14:15:58 +03:00
Kirill Bulatov
364631a155 Add absolute paths to historic elements 2023-05-26 14:03:44 +03:00
Kirill Bulatov
128c19875d Fix duplicate item creation in project panel (#2532)
Closes
https://linear.app/zed-industries/issue/Z-1760/creating-a-new-file-with-the-same-name-as-an-existing-file-overwrites

Now every rename/creation editor won't do anything if a duplicate name
is submitted.

Release Notes:

* Fixed a bug when created in project panel items with duplicate names
were overwriting the old files
2023-05-26 10:14:50 +03:00
Kirill Bulatov
5501dd741c Fix duplicate item creation in project panel 2023-05-26 02:07:25 +03:00
Julia
7900d2a20a Multibuffer edit perf (#2531)
This took so much longer than I wanted, so glad to finally be rid of
this

Release Notes:
* Improved performance when editing many git-tracked files in a
multi-buffer at the same time
2023-05-25 15:01:05 -04:00
Julia
5e39ba596e Clean up final remaining code paths calling old diff update method 2023-05-25 14:41:09 -04:00
Julia
f40c498491 Fix tests 2023-05-25 14:29:28 -04:00
Julia
8d662edb6c Remove concept of git diff refresh from Item trait 2023-05-25 14:29:28 -04:00
Julia
cede296b04 Project level git diff recalc handling
This avoids an issue where in a many-buffer multi-buffer, each modified
buffer could complete its recalc independently, causing a cascade of
repeated notifies

Now all recalcs started at the same time must complete before
 A: Starting another recalc pass
 B: The master notify occurring

Each buffer can still show its new diff if something else triggers it
to notify earlier, this is desirable and does not have the same negative
effects as the notify cascade as those re-layouts would need to happen
anyway

Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-05-25 14:10:27 -04:00
Max Brunsfeld
54421b11f3 wip 2023-05-25 14:10:27 -04:00
Kirill Bulatov
ae3bdd755e Support OnTypeFormatting LSP request (#2517)
Supports
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_onTypeFormatting

rust-analyzer uses this feature to add matching brackets semantically,
e.g.
before:
![Screenshot 2023-05-23 at 17 46
42](https://github.com/zed-industries/zed/assets/2690773/020e8448-23e6-4a38-8dbb-c9edf18062f7)

after:
![Screenshot 2023-05-23 at 17 46
49](https://github.com/zed-industries/zed/assets/2690773/4d140af3-aca6-451d-ac61-e2a9bb31caea)

`use_on_type_format` settings entry was added, enabled by default, to
disable the new feature.

Release Notes:

* Support `OnTypeFormatting` LSP protocol feature, allowing
rust-analyzer to add matching brackets
2023-05-25 18:35:47 +03:00
Kirill Bulatov
739d5ca373 Have proper undo for both client and host 2023-05-25 18:29:57 +03:00
Antonio Scandurra
24098c561d Prevent bottom dock from becoming too large or too small (#2529)
Fixes
https://linear.app/zed-industries/issue/Z-1834/bottom-dock-can-be-dragged-down-far-enough-such-that-the-tab-bar-is

Release Notes:

- Improved the resize experience for the bottom dock, preventing it from
becoming too large or too small. (preview-only)
2023-05-25 15:44:23 +02:00
Antonio Scandurra
4185a178e7 Prevent bottom dock from becoming too large or too small 2023-05-25 15:29:59 +02:00
Antonio Scandurra
f549ada54f Restore the ability to search terminals in the terminal panel (#2528)
Fixes
https://linear.app/zed-industries/issue/Z-1812/find-in-terminal-panel-is-broken

![CleanShot 2023-05-25 at 15 18
01@2x](https://github.com/zed-industries/zed/assets/482957/ddb33b61-d253-4de1-961f-14b24aaa3e46)

This also removes navigation controls from the terminal panel, given
that terminals don't make use of that feature anyway. When the toolbar
is empty, we'll avoid showing it altogether.

![CleanShot 2023-05-25 at 15 17
26@2x](https://github.com/zed-industries/zed/assets/482957/52419f2c-bca0-494a-a9b3-88e183b4c12f)


Release Notes:

- Fixed a regression that was preventing the terminal panel from being
searched.
2023-05-25 15:28:32 +02:00
Antonio Scandurra
aa8c0475b1 Don't show navigation controls for terminal panel 2023-05-25 15:15:20 +02:00
Kirill Bulatov
e2ff829f98 Use Transaction instead of ProjectTransaction
Co-Authored-By: Antonio Scandurra <antonio@zed.dev>
2023-05-25 16:12:14 +03:00
Antonio Scandurra
414b97adce Add search bar to terminal panel 2023-05-25 14:46:10 +02:00
Antonio Scandurra
dba7ec4a35 Prevent pane from being erroneously zoomed when toggling the outline pane (#2527)
Fixes
https://linear.app/zed-industries/issue/Z-1818/toggling-the-outline-pane-causes-the-pane-to-zoom

Add release note lines here:

- Fixed a bug that could cause panes to be erroneously zoomed when
toggling modals. (preview-only)
2023-05-25 14:10:08 +02:00
Antonio Scandurra
c2f3ac24a4 Prevent zoom from being restored when focusing a modal 2023-05-25 12:11:11 +02:00
Antonio Scandurra
7e1ea8f274 Remove stray dbg! 2023-05-25 12:04:41 +02:00
Kirill Bulatov
aa58d0fd77 Do not send edits over the wire 2023-05-25 12:55:44 +03:00
Kirill Bulatov
f812151840 Add integration tests 2023-05-25 09:45:50 +03:00
Kirill Bulatov
eca6d2b597 Process remote format typing also 2023-05-25 09:45:50 +03:00
Kirill Bulatov
58a56bdda2 Always use server formatting settings 2023-05-25 09:45:50 +03:00
Kirill Bulatov
d1f4b60fa1 Allow to disable the new feature 2023-05-25 09:45:50 +03:00
Kirill Bulatov
b9dabb165e Use formatting options 2023-05-25 09:45:50 +03:00
Kirill Bulatov
3327e8a6dd Support remote sessions 2023-05-25 09:45:50 +03:00
Kirill Bulatov
f6d7b3d2e8 Send and handle OnTypeFormatting LSP request 2023-05-25 09:45:50 +03:00
Nate Butler
793486b2e8 Update Diff Modified Color (#2526)
For some reason the yellow I used for the modified color in light themes
was really light
.
Release Notes:

* Improved the contrast of diff modified color in the editor in light
themes.
2023-05-24 23:50:37 -04:00
Joseph Lyons
3f79b0c7cc Don't hardcode dates into script 2023-05-24 17:39:02 -04:00
Joseph Lyons
cc3186cb4a Add script to print all prs merged between a previous date and now 2023-05-24 16:58:56 -04:00
Nathan Sobo
0b7d095c0a Introduce the ability to talk to GPT-4 within buffers on preview and dev (#2524)
This adds basic ability to interact with OpenAI inside a buffer.

Release Notes:

* If`OPENAI_API_KEY` is defined in your environment, you can now run the
`ai: assist` command to pass the text of your current buffer to GPT-4.
If you're editing a file with a `.zmd` extension, you can also invoke
the model with `cmd-enter.` (preview-only)
2023-05-24 12:00:43 -06:00
Joseph Lyons
37d35db3d7 v0.89.x dev 2023-05-24 13:22:00 -04:00
Nathan Sobo
26051de160 Clean up 2023-05-24 11:08:00 -06:00
Max Brunsfeld
a1a66b8da4 Make toggle dock actions appear in the command palette (#2525)
This makes the `Toggle{Left,Right,Bottom}Dock` actions deserializable
from empty JSON, so that they can be constructed for the command
palette. It also fixes a bug in GPUI's `available_actions` method, in
which we'd include key bindings for actions of the same type but
different values.

Note that, for now, the command palette will perform the *focusing*
version of the actions. I'm not totally sure this is the right behavior,
but it seems more useful to me.

Release Notes:

N/A
2023-05-24 10:07:34 -07:00
Nathan Sobo
747322a02d Merge remote-tracking branch 'origin/main' into zmd 2023-05-24 11:04:07 -06:00
Max Brunsfeld
66b3be8687 Make toggle dock actions appear in the command palette 2023-05-24 09:58:41 -07:00
Nathan Sobo
d495c1b804 Only run AI agent on dev and preview 2023-05-24 10:58:33 -06:00
Antonio Scandurra
35f9996a4f WIP 2023-05-24 18:45:47 +02:00
Nathan Sobo
ba79a8ba94 WIP 2023-05-24 10:26:14 -06:00
Nathan Sobo
50e1e17d09 WIP 2023-05-24 09:53:08 -06:00
Nathan Sobo
051c7566cc WIP 2023-05-24 09:38:37 -06:00
Nathan Sobo
8abaf66602 WIP 2023-05-24 09:21:50 -06:00
Nathan Sobo
6368ade1da WIP 2023-05-24 09:12:16 -06:00
Antonio Scandurra
8832248bb9 Polish panel experience (#2523)
In this pull request we improved key bindings (as described below) and
added tooltips.

Add these release notes to the panels release notes:

- The left, right and bottom dock can be toggled and focused at the same
time respectively via `cmd-b`, `cmd-r` and `cmd-j`. Holding `shift` will
toggle them without changing the focus.
2023-05-24 16:23:24 +02:00
Antonio Scandurra
f67a22828b Show keystroke in panel tooltips
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-24 16:13:58 +02:00
Antonio Scandurra
0cf1632d39 Only focus new terminal if the panel contains focus
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-24 16:04:02 +02:00
Antonio Scandurra
50cfe5eec3 Use cmd-b/cmd-r/cmd-j to toggle left/right/bottom dock and focus when opening
Also, bind the same keys with shift to toggle the dock without focusing.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-24 15:59:06 +02:00
Antonio Scandurra
7534c4e670 Fix opening excerpt when the cursor is at the end of a multi-buffer (#2522)
Fixes
https://linear.app/zed-industries/issue/Z-987/option-enter-doesnt-open-buffer-from-multibuffer-if-on-the-last-line

This was caused by seeking with a right bias, which in the case of the
last excerpt in the buffer would seek past the end of the buffer. This
commit changes the behavior to move the cursor back to the previous
excerpt if we overshoot, to ensure we always land on an excerpt.

Release Notes:

- Fixed a bug that prevented opening excerpts when the cursor was at the
end of a multi-buffer.
2023-05-24 15:08:18 +02:00
Antonio Scandurra
2a8e0824a6 Fix opening excerpt when the cursor is at the end of a multi-buffer
This was caused by seeking with a right bias, which in the case of the
last excerpt in the buffer would seek past the end of the buffer.  This
commit changes the behavior to move the cursor back to the previous excerpt
if we overshoot, to ensure we always land on an excerpt.
2023-05-24 15:02:57 +02:00
Antonio Scandurra
8f49552121 Show maximize/minimize icon for panes and terminal panel (#2521)
Closes
https://linear.app/zed-industries/issue/Z-1790/show-zoomunzoom-icons-for-panes-and-terminal-panel

![CleanShot 2023-05-24 at 11 07
04@2x](https://github.com/zed-industries/zed/assets/482957/b27d002c-6443-440b-88d0-cfa06d902477)
2023-05-24 11:44:39 +02:00
Antonio Scandurra
e5fd953b4f Provide tooltips for pane buttons 2023-05-24 11:18:30 +02:00
Antonio Scandurra
1a353ad25d Show maximize/minimize icon for panes and terminal panel 2023-05-24 11:00:12 +02:00
Antonio Scandurra
9575ffc1e3 Prevent empty panes from being zoomed (#2520)
Closes
https://linear.app/zed-industries/issue/Z-1789/empty-panes-should-not-be-zoomable
2023-05-24 10:51:52 +02:00
Antonio Scandurra
168ff99927 Prevent empty panes from being zoomed 2023-05-24 10:34:56 +02:00
Joseph T. Lyons
e463e3b2e8 Update terminal panel tooltip (#2519)
The actions in Zed now call this the Terminal Panel and the crate is
called that as well, so I think the tooltip should be updated to use
that same name.

Release Notes:

N/A
2023-05-23 22:33:08 -04:00
Joseph Lyons
e6857866d4 Update terminal panel tooltip 2023-05-23 22:23:38 -04:00
Nathan Sobo
637ed79603 WIP 2023-05-23 18:16:49 -06:00
Nathan Sobo
65fc50745b WIP 2023-05-23 18:04:33 -06:00
Nathan Sobo
d934da1905 WIP 2023-05-23 15:25:34 -06:00
Joseph T. Lyons
ba7659fa77 add toggle right and bottom dock actions (#2518)
Release Notes:

N/A
2023-05-23 13:59:45 -04:00
Joseph Lyons
2457c55fe7 add toggle right and bottom dock actions 2023-05-23 13:53:56 -04:00
Joseph T. Lyons
aac83ceea7 Add architecture to clickhouse event request body (#2514)
See title

Release Notes:

N/A
2023-05-23 11:11:17 -04:00
Nathan Sobo
7be41e19f7 WIP 2023-05-23 08:52:21 -06:00
Antonio Scandurra
ad866c5b21 Update LiveKit client SDK to 1.0.12 (#2516)
Fixes
https://linear.app/zed-industries/issue/Z-1756/screen-sharing-is-slow-and-sometimes-doesnt-work-at-all

Release Notes:

* Fixed some cases where screen-sharing would have low bitrate or
completely fail to start.
2023-05-23 16:19:12 +02:00
Antonio Scandurra
774530dd05 Update LiveKit client SDK to 1.0.12
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-05-23 15:32:55 +02:00
Nathan Sobo
073967c80b WIP 2023-05-23 01:56:28 -06:00
Nathan Sobo
5362e7d346 WIP 2023-05-23 01:52:37 -06:00
Nathan Sobo
394e87d17c WIP 2023-05-23 01:23:01 -06:00
Antonio Scandurra
dcc4dd7eb8 Allow multiple docks to be visible at once and only let them contain panels (#2450)
Closes
https://linear.app/zed-industries/issue/Z-1188/allow-docks-to-be-visible-on-left-bottom-right

To prepare the way for the AI assistant, we want to revamp the way docks
and panels work. In this PR, we replace the dock as it currently exists
with 3 independent docks at the left, bottom, and right edge of the
workspace. To replace the "expanded" dock, we will introduce a zoom
feature that works on any pane and some panels. When showing a dock with
an active panel that is zoomed, it will automatically appear zoomed.
This replicates the expanded dock experience. If you unzoom, the panel
will still be visible.

### Panels only

We want to simplify these docks to only allow them to contain *panels*.
By doing this, we don't need to give each dock a tab bar, minimizing
clutter in the workspace. Each panel will remember its size, and the
dock will adjust to that size when the panel is toggled. This will allow
each panel to take up the amount of space that makes sense for its use
case.

There will be 3 kinds of panels:

* Project panel: This currently lives in the left "sidebar", which this
PR renames to the left dock. Users will be able to left click the icon
and switch the project panel to the right dock.
* Terminal panel: This is the primary user of the previous dock. Now all
terminals will live in a terminal panel, which can be docked at the
left, bottom, or right. This dock will contain tabs, but only for
terminals. Terminals will still be able to be dragged into the
workspace, but by default, the first new terminal will live in the
terminal panel which lives in one of the 3 docks.
* Feedback: Instead of opening a pane, let's explore making this a panel
instead.

### Status bar icons

A nice feature of this change is that it simplifies our status bar by
eliminating the dock button. We will only show icons for specific
panels. Panel in the left dock will appear at the left side of the
status bar. Panels in the right dock on the far right, panels in the
bottom will appear on the right, to the immediate left of the buttons
for right panels. Left clicking any panel button will allow it to be
redocked to any valid location for that panel.

### Paving the way for the AI assistant

I'm envisioning the assistant living in the far right panel by default.
So in the stock config, you'll have the project panel on the left,
terminal on the bottom, assistant on the right, and code in the middle.
Let's fucking go!
2023-05-23 09:09:43 +02:00
Antonio Scandurra
19b817e48a Improve styling of bottom and right docks 2023-05-23 09:02:45 +02:00
Antonio Scandurra
208ff2fba7 Merge remote-tracking branch 'origin/main' into panels 2023-05-23 08:24:28 +02:00
Nathan Sobo
0de5a444d3 WIP 2023-05-23 00:22:21 -06:00
Nathan Sobo
234dbc3ca9 WIP 2023-05-23 00:16:44 -06:00
Nathan Sobo
c4d88bc529 WIP 2023-05-22 23:43:02 -06:00
Nathan Sobo
30de64845f WIP 2023-05-22 23:11:27 -06:00
Mikayla Maki
a5b5de5651 Add initial project panel settings (#2515)
This PR adds project panel settings for disabling git status.

Release Notes:

- Adds `project_panel: { git_status: bool }` to the settings, for
controlling whether git status information appears.
2023-05-22 20:43:24 -07:00
Mikayla Maki
a37b1b6a45 Add other setting init 2023-05-22 20:38:30 -07:00
Mikayla Maki
b19a712799 Add init_settings to tests 2023-05-22 20:33:18 -07:00
Mikayla Maki
da96802bf0 fmt 2023-05-22 20:25:27 -07:00
Mikayla Maki
7be8dead07 Add initial project panel settings 2023-05-22 20:23:07 -07:00
Nathan Sobo
7e6cccfa3d WIP: Stream in completions
Drop dependency on tokio introduced by async-openai and do it ourselves.

The approach I'm taking of replacing instead of appending is causing issues. Need to just append.
2023-05-22 20:28:22 -06:00
Joseph Lyons
049b72e3ac Add architecture to clickhouse event request body 2023-05-22 21:45:58 -04:00
Mikayla Maki
54c04a6618 Fix race condition in diff base initializaiton (#2513)
fixes
https://linear.app/zed-industries/issue/Z-1657/diff-markers-in-gutter-do-not-show-up-until-after-first-save

Release Notes:

- Fixes a race condition on buffer initialization that would cause git
diffs to not load.
2023-05-22 18:43:59 -07:00
Mikayla Maki
9307719a4b Add run until parked for test 2023-05-22 18:40:12 -07:00
Mikayla Maki
51d94f532b Load diff base for buffers that are opening but not yet opened when repositories are discovered 2023-05-22 18:26:33 -07:00
Mikayla Maki
fc82489128 Update scrollbar styling 2023-05-22 16:23:36 -07:00
Mikayla Maki
1b5be04f76 Fixed contrast in project panel and scrollbar (#2512)
Redo of https://github.com/zed-industries/zed/pull/2504 

This makes the different git locations individually style-able

Release Notes:

- Improve git contrast (preview only)
2023-05-22 15:59:02 -07:00
Mikayla Maki
e4454f1e7f fmt 2023-05-22 15:53:29 -07:00
Mikayla Maki
5c31c84c90 Fixed contrast in project panel and scrollbar
co-authored-by: nate <nate@zed.dev>
2023-05-22 15:51:31 -07:00
Mikayla Maki
fb2f17e5c9 Revert "Touch up git in project panel and scroll bar styling" (#2511)
Reverts zed-industries/zed#2504, due to accidentally pulling in main
2023-05-22 15:36:15 -07:00
Mikayla Maki
2d1c4a1971 Revert "Touch up git in project panel and scroll bar styling" 2023-05-22 15:31:14 -07:00
Mikayla Maki
dcf4791182 WIP: Touch up git in project panel and scroll bar styling (#2504)
This makes the different git locations individually style-able

Release Notes:

* Improve git contrast (preview only)
2023-05-22 15:11:10 -07:00
Mikayla Maki
9bec74f1d4 fmt 2023-05-22 15:04:51 -07:00
Mikayla Maki
9a47415cb5 Merge branch 'main' into git-project-panel-and-scrollbar-styling 2023-05-22 15:02:28 -07:00
Mikayla Maki
5dfb0e3691 remove border from thumb 2023-05-22 14:56:55 -07:00
Nate Butler
11eb9b17c9 Update project panel & scroll bar git colors 2023-05-22 17:47:52 -04:00
Mikayla Maki
4c9d24da7c Only fire update diff base when the dot repo is scanned (#2510)
This PR fixes a bug in the firing of the UpdatedRepositories event which
caused it to flood collaboration with new messages on every file save.

Release Notes:

* Fixed a bug in repository detection that caused it to fire
over-eagerly (preview only)
2023-05-22 14:11:19 -07:00
Mikayla Maki
96224fa7e8 Only fire update diff base when the dot repo is scanned 2023-05-22 13:57:07 -07:00
Max Brunsfeld
0e332b5f94 Clear old diagnostics when restarting a language server (#2509)
Previously, restarting a language server did not clear out the
diagnostics that were published by that server. Those diagnostics would
stick around forever.

Release Notes:

* Fixed a bug where restarting a language server would sometimes leave
buffers with stale diagnostics associated with that server.
2023-05-22 13:06:32 -07:00
Max Brunsfeld
7689cdf3f9 Clear old diagnostics when restarting a language server 2023-05-22 12:53:22 -07:00
Mikayla Maki
1d07cff765 Adjust scrollbar settings to be expandable (#2507)
Note that this PR cannot be cherrypicked into preview, as it relies on
the new settings infrastructure.

Switches settings from `show_scrollbars: "auto"` to `scrollbar: {show:
"auto", git_diffs: true}`.

fixes
https://linear.app/zed-industries/issue/Z-1650/scroll-bar-feature-settings

Release Notes:

- Changed scrollbar settings from `show_scrollbars: "auto"` to
`scrollbar: {show: "auto", git_diffs: true}`. (preview only)
2023-05-22 12:51:21 -07:00
Mikayla Maki
dcb987ba9d Diagnostics pane was not focusable with the mouse (#2506)
fixes
https://linear.app/zed-industries/issue/Z-1432/cant-cmd-w-an-empty-diagnostics-in-a-split-pane

Release Notes:

* Fixed a bug where the diagnostics pane could not be focused or closed
in certain circumstances.
2023-05-22 12:44:39 -07:00
Mikayla Maki
cfdf9198da Switch back to 2023-05-22 12:16:47 -07:00
Mikayla Maki
687ccd4c6f fmt 2023-05-22 12:13:23 -07:00
Mikayla Maki
366f13bb5c Adjust scrollbar settings to be expandable 2023-05-22 12:12:56 -07:00
Joseph Lyons
49566e5677 Update pull_request_template.md 2023-05-22 15:00:57 -04:00
Joseph Lyons
9c32b774aa Add example of changelog line in PR template 2023-05-22 14:53:07 -04:00
Mikayla Maki
bafc1d922e fmt 2023-05-22 11:46:52 -07:00
Mikayla Maki
e59c8e9d61 Fix diagnostic pane not being closeable 2023-05-22 11:44:23 -07:00
Max Brunsfeld
e129ed2d91 Fix spurious setting error log messages (#2498)
Fixes a bug introduced in
https://github.com/zed-industries/zed/pull/2448, where error messages
would be logged if the user config didn't specify certain fields like
`journal` or `telemetry`.
2023-05-22 11:44:21 -07:00
Joseph Lyons
04355215b2 Indent all release note lines for each PR 2023-05-22 14:44:05 -04:00
Julia
a69144911f Add paragraph based vertical movements (#2502)
Very selfish patch I worked on yesterday, I kept saying I wanted these
and finally decided to just add them. Feedback on the keybindings
welcome

Release Notes:

* Added `MoveToStartOfParagraph` and `MoveToEndOfParagraph` movements
for paragraph based vertical navigation
2023-05-22 14:31:34 -04:00
Mikayla Maki
85266131cf Fix perf problem with scrollbars in large multibuffers (#2505)
Remove scrollbars from multibuffers

Release Notes:

* Removes git scrollbar highlights from multibuffers (preview only)
2023-05-22 11:11:27 -07:00
Mikayla Maki
6f4b6eec5b Diagnostics pane was not focusable with the mouse 2023-05-22 11:10:13 -07:00
Mikayla Maki
6264b24788 fmt 2023-05-22 11:04:36 -07:00
Mikayla Maki
8669dcdc81 Make scrollbar content detection cheaper
Remove scrollbars from multibuffers

co-authored-by: max <max@zed.dev>
2023-05-22 10:55:44 -07:00
Antonio Scandurra
f22067b236 Remove unused imports 2023-05-22 19:38:57 +02:00
Antonio Scandurra
33f6c56b14 Fix more warnings 2023-05-22 19:36:01 +02:00
Antonio Scandurra
6f39d49b18 Fix warnings 2023-05-22 19:33:11 +02:00
Antonio Scandurra
048498e39b Test zooming panels 2023-05-22 19:30:31 +02:00
Mikayla Maki
ef81813d56 Wire in conflict styling 2023-05-22 10:10:47 -07:00
Mikayla Maki
a355b4c135 Add conflict styles to project panel 2023-05-22 10:09:55 -07:00
Mikayla Maki
af73c1af06 Add seperate scrollbar styling 2023-05-22 10:03:02 -07:00
Antonio Scandurra
3ca95678f1 Avoid leaking docks when adding panels 2023-05-22 18:57:14 +02:00
Kirill Bulatov
9e46b17149 Do not refocus project search query on ESC press (#2494)
Closes
https://linear.app/zed-industries/issue/Z-1471/escape-should-not-move-focus-to-project-search

Makes ESC more predictable as a shortcut that cancels/roll backs the
state in project search panel.

Release Notes:

* Fixes ESC making focus to jump in project search panel
2023-05-22 19:56:10 +03:00
Mikayla Maki
2200a22c07 Wire project panel themes into rust 2023-05-22 09:55:59 -07:00
Antonio Scandurra
75a0742c90 Uncomment persistence test 2023-05-22 18:32:28 +02:00
Antonio Scandurra
5b7e852903 Await closing of items in tests 2023-05-22 18:28:30 +02:00
Antonio Scandurra
deaf60005c Fix more tests 2023-05-22 18:21:12 +02:00
Nate Butler
b80cb73745 Add git to project panel in theme, use different values for dark and light 2023-05-22 12:09:54 -04:00
Antonio Scandurra
4aa2858b2b Transfer focus to root view only if previously-focused view was dropped 2023-05-22 18:05:08 +02:00
Max Brunsfeld
21ada545b0 Remove assertions about behavior on invalid settings file 2023-05-22 08:48:37 -07:00
Julia
44903bc193 Add test for paragraph vertical movements 2023-05-22 11:48:07 -04:00
Antonio Scandurra
185a624b99 Fix some project panel tests 2023-05-22 16:18:53 +02:00
Antonio Scandurra
10e947cb5f Persist project and terminal panel sizes 2023-05-22 15:55:44 +02:00
Julia
7190840081 Add paragraph based vertical movements 2023-05-22 09:12:36 -04:00
Antonio Scandurra
146809eef0 Merge branch 'main' into panels 2023-05-22 14:10:17 +02:00
Antonio Scandurra
2098ac2c77 Fix formatting for keymap.json 2023-05-22 10:41:48 +02:00
Joseph Lyons
cb1b64e51b Fix up formatting for get preview channel changes script 2023-05-22 00:02:19 -04:00
Joseph T. Lyons
f2a74017df Fix get preview channel changes script (#2501)
Fixes the text we match on to get PR commits and also prints the release
notes of each PR

Release Notes:

* Skip
2023-05-21 23:47:07 -04:00
Joseph Lyons
c701901c7b Fix get preview channel changes script 2023-05-21 23:40:07 -04:00
Nathan Sobo
d5cf595761 Enable "test-support" feature on editor dependencies for tests (#2499)
Enable the `"test-support"` feature whenever we depend on the `editor`
crate in tests.

If we don't do this, we end up depending on `livekit_client` without
enabling `"test-support"`, and this causes us to link against
`WebRTC.framework` in its build script, which causes a dynamic linker
error when starting the tests.

Fixes
https://linear.app/zed-industries/issue/Z-1646/cant-run-package-tests-for-activity-monitor-and-auto-update

Release Notes:

* No notes
2023-05-20 10:19:59 -06:00
Nathan Sobo
986eafd84e Enable test-support on editor in tests 2023-05-20 09:54:38 -06:00
Nathan Sobo
912fd23006 Parse markdown into an OpenAI chat completion request 2023-05-20 09:43:12 -06:00
Mikayla Maki
35a9b90528 Fix bugs in git implementation (#2495)
fixes
https://linear.app/zed-industries/issue/Z-1593/clean-up-git-integration

- Fixes calculation of git offsets in the scrollbar:

fixes
https://linear.app/zed-industries/issue/Z-1608/fix-scrollbar-diffs-sliding-out-of-sync-with-gutter-diffs-in

fixes
https://linear.app/zed-industries/issue/Z-1629/project-search-panel-has-git-marks-on-the-scrollbar-misaligned

fixes
https://linear.app/zed-industries/issue/Z-1625/soft-wrap-affects-diff-locations-in-scrollbar

- Improves the performance of scrollbar hunks:

fixes
https://linear.app/zed-industries/issue/Z-1640/double-check-performance-of-scrollbar-hunks

- Fixes a long standing bug with how git gutters interact with soft
wraps:

fixes
https://linear.app/zed-industries/issue/Z-1442/make-hunks-grow-to-the-end-of-softwraps-when-ending-on-a-softwrapped

- Allows work directories to be renamed

fixes
https://linear.app/zed-industries/issue/Z-1577/fix-stale-git-repositories-when-directory-is-renamed

Release Notes:

* Fix the offsets of the git diffs in the scrollbar when there are
folds, wraps, or excerpts (preview only)
* Allow the work directory of a repository to be renamed (preview only)
* Extend git gutter to cover the entirety of a wrapped line
(https://github.com/zed-industries/community/issues/937)
2023-05-19 18:15:11 -07:00
Mikayla Maki
bbb68c523c Refactored apart the forward and the backwards iterator for diff hunks 2023-05-19 18:09:47 -07:00
Max Brunsfeld
e32233c826 Fix spurious setting error logs on non-existent setting keys 2023-05-19 17:15:05 -07:00
Mikayla Maki
43e301eeef refine batched anchor conversions
co-authored-by: max <max@zed.dev>
2023-05-19 16:52:57 -07:00
Max Brunsfeld
fb11c3e4bf Remove stray prints 2023-05-19 16:52:30 -07:00
Mikayla Maki
1474429271 fmt 2023-05-19 16:32:07 -07:00
Mikayla Maki
c795c9b844 Rearrange git tests in worktree
Add support for renaming work directories
2023-05-19 16:30:00 -07:00
Mikayla Maki
623a177fe6 Fix bug where git diff hunks would not extend through a soft wrap 2023-05-19 16:23:45 -07:00
Mikayla Maki
560160b100 Batch anchor conversions in git hunk iterator 2023-05-19 16:23:45 -07:00
Mikayla Maki
2a41a32aac Calculate y offsets correctly 2023-05-19 16:23:45 -07:00
Max Brunsfeld
d7d29472c2 Remove expensive-to-clone fields from worktree's LocalSnapshot (#2497)
This fixes performance problems that @nathansobo and I have seen in some
cases, when a large number of files changed on disk. A lot of time was
being spent in `worktree::LocalSnapshot::clone`. I think this may have
been because of needing to clone the `removed_entry_ids` map. This
structure is only really used when *mutating* the `LocalSnapshot` in the
background scanner, so I moved it off of the snapshots.
2023-05-19 16:20:19 -07:00
Mikayla Maki
06a89d9104 Add guards to other pane index removals (#2496)
These should be impossible for users to reach, but why leave it to
chance?

Release Notes:

* N/A
2023-05-19 15:21:00 -07:00
Max Brunsfeld
7ae642b9b8 Avoid storing removed_entry_ids on the LocalSnapshot 2023-05-19 15:16:04 -07:00
Mikayla Maki
c193b0b8fc Add guards to other pane index removals 2023-05-19 15:10:44 -07:00
Max Brunsfeld
32c7157906 🎨 Make worktree repositories more consistent 2023-05-19 15:04:37 -07:00
Max Brunsfeld
6359333749 Don't store next_entry_id on worktree's local snapshot 2023-05-19 13:49:24 -07:00
Kirill Bulatov
065f71d671 Do not refocus project search query on ESC press 2023-05-19 22:06:47 +03:00
Kirill Bulatov
7d1833b759 When the file is deleted via project panel, close it in editors (#2490)
Deals with https://github.com/zed-industries/community/issues/179 by
sending a message about it, to asynchronously apply on all workspaces.

Release Notes:

* Fixes a bug when files, deleted in the project panel were left open in
the editor
2023-05-19 21:51:37 +03:00
Max Brunsfeld
844b8d9e1e Remove unnescessary double lookup in repo for (#2492)
Release Notes:

* Optimize repository queries (preview only)
2023-05-19 11:47:05 -07:00
Kirill Bulatov
2c8fffc4f8 Use better name for the method that closes deleted buffers
co-authored-by: Max <max@zed.dev>
2023-05-19 21:47:00 +03:00
Max Brunsfeld
01a3e49946 Optimize retrieving repos for entries when rendering the project panel (#2493)
This fixes slowness in rendering the project panel due to retrieving the
repository for a given entry.

Release Notes:

* Fixed a lag that would occur when lots of files changed on disk while
the project panel was open (preview only).
2023-05-19 11:46:32 -07:00
Mikayla Maki
9f157bdb67 Remove unescessary methods 2023-05-19 11:30:10 -07:00
Max Brunsfeld
729a93db6b Optimize retrieving repos for entries when rendering the project panel
Co-authored-by: Mikayla <mikayla@zed.dev>
2023-05-19 11:29:02 -07:00
Mikayla Maki
6792788216 Remove unnescessary double lookup 2023-05-19 11:08:58 -07:00
Antonio Scandurra
5a8fb18c20 Show workspace only after initializing it 2023-05-19 19:35:00 +02:00
Antonio Scandurra
5ff49bde31 Serialize and deserialize TerminalPanel 2023-05-19 19:26:32 +02:00
Max Brunsfeld
d480555ec9 Fix performance problems in reporting changed FS paths to language servers (#2491)
Fixes
https://linear.app/zed-industries/issue/Z-1611/main-thread-hangs-while-sending-filesystem-change-events-to-lsp

Release Notes:

* Fixed a lag that would sometime occur when large numbers of files
changed on disk, due to reporting the changed files to language servers.
2023-05-19 09:42:55 -07:00
Max Brunsfeld
847d1e73a3 Replace remaining usages of glob crate with globset 2023-05-19 09:36:46 -07:00
Max Brunsfeld
459cc9c959 Optimize matching of multiple file-watch globs using the globset crate 2023-05-19 09:13:34 -07:00
Kirill Bulatov
583b15badc When the file is deleted via project panel, close it in editors 2023-05-19 18:52:30 +03:00
Antonio Scandurra
e49281699c Add new terminal when the terminal panel is activated, and not on focus 2023-05-19 16:07:47 +02:00
Antonio Scandurra
924ec961ff Toggle project panel when opening new workspace in a dock-agnostic way 2023-05-19 15:27:18 +02:00
Antonio Scandurra
3d6b728364 Activate the correct panel when deserializing workspace 2023-05-19 14:18:11 +02:00
Kirill Bulatov
3984cc6d39 Properly handle WorktreeId 2023-05-19 12:37:36 +03:00
Max Brunsfeld
4bda5c4d69 Optimize LSP watched file reporting in 2 simple ways
* Convert globs to relative paths in advance. This avoids needing to convert
  every changed path to an absolute path before performing glob matching.
* Avoid duplicate reporting for language servers with multiple worktrees.
2023-05-18 17:08:51 -07:00
Max Brunsfeld
34b0d6200f collab 0.12.4 2023-05-18 14:58:57 -07:00
Max Brunsfeld
ffe35d171c Avoid unnecessary code action requests when applying leader updates t… (#2489)
We noticed a huge amount of code actions requests being issued by
followers when applying leader updates. It was caused by a call to
`MultiBuffer::remove_excerpts` with an empty list of excerpts to remove.
This PR fixes that by avoiding emitting spurious events when multibuffer
excerpt manipulation methods are called with empty lists.
2023-05-18 14:52:21 -07:00
Max Brunsfeld
58f704abcb Avoid unnecessary code action requests when applying leader updates to an editor 2023-05-18 14:46:23 -07:00
Mikayla Maki
87e206c451 Fixed an imprecise join in rejoin room (#2488)
This fixed a pre-existing bug in rejoin room that got expanded to
stalling collab with the new git status feature.

Release Notes:

* N/A
2023-05-18 14:42:59 -07:00
Mikayla Maki
99fcf23798 fmt 2023-05-18 14:31:08 -07:00
Mikayla Maki
95a7d69bce Fixed an imprecise join in rejoin room 2023-05-18 14:29:18 -07:00
Max Brunsfeld
2883d6f1ef Improve collab logging (#2487)
This adds some logging to the collab server, to help us identify the
source of the collaboration latency we're seeing in the 0.87 preview
version of zed.
2023-05-18 14:17:17 -07:00
Max Brunsfeld
2a11a89827 collab 0.12.3 2023-05-18 12:27:08 -07:00
Joseph Lyons
55b241a4f6 collab 0.12.2 2023-05-18 12:27:01 -07:00
Max Brunsfeld
c71b59b248 Log how long it takes to handle each RPC message 2023-05-18 12:24:07 -07:00
Kirill Bulatov
923be1892d Maintain recently opened files history (#2467)
Part of https://github.com/zed-industries/community/issues/351 and
https://github.com/zed-industries/community/issues/1125

Adds navigation history to the search file dialogue:


![image](https://github.com/zed-industries/zed/assets/2690773/01a1d3ea-1328-425a-ac95-2ebdbfcc07ab)

The history is only shown on empty query and gets replaced by the query
results after an input.
Currently, history gets lost between the project restarts.

Release Notes:

* Added a recently opened file list to search file dialogue
2023-05-18 22:06:25 +03:00
Kirill Bulatov
2ec994dfcd Add a unit test 2023-05-18 21:53:42 +03:00
Kirill Bulatov
201d513c50 Show navigation history in the file finder modal
co-authored-by: Max <max@zed.dev>
2023-05-18 21:50:38 +03:00
Kirill Bulatov
711d2c6fe7 Maintain recently opened files history 2023-05-18 21:50:38 +03:00
Julia
bd29812391 Avoid panic in get_injections (#2486) 2023-05-18 13:35:10 -04:00
Julia
5ab1ae1521 Avoid panic in get_injections 2023-05-18 12:23:49 -04:00
Max Brunsfeld
83f8981308 Define empty theme for tests regardless of cargo features (#2485)
This fixes some errors that were happening when running a single crate's
tests, if the test did not enable the `test-support` feature in the
`theme` crate.
2023-05-18 09:14:46 -07:00
Max Brunsfeld
71ad7e7612 Define empty theme for tests regardless of cargo features
Co-authored-by: Kirill <kirill@zed.dev>
2023-05-18 09:01:38 -07:00
Antonio Scandurra
f2ad17dbc0 WIP 2023-05-18 15:35:46 +02:00
Kirill Bulatov
263afc75a8 Merge pull request #2484 from zed-industries/kb/unite-dmg-build
Unite dmg build jobs

Follow-up of https://github.com/zed-industries/zed/pull/2472 actually doing the proper thing: allow running dmg builds on PRs if `run-build-dmg` label is attached.
2023-05-18 14:39:41 +03:00
Kirill Bulatov
5ab4eab369 Unite dmg build jobs 2023-05-18 13:49:55 +03:00
Mikayla Maki
89d8bb1425 WIP: Add persistence to new docks 2023-05-17 17:34:20 -07:00
Max Brunsfeld
5c437e2098 Fix crashes when running zed bundled 2023-05-17 16:53:48 -07:00
Max Brunsfeld
a9b107f155 Fix release-mode stub for watch_themes 2023-05-17 16:36:06 -07:00
Max Brunsfeld
d23fc6f135 Merge pull request #2448 from zed-industries/setting-store
Separate the settings struct into a set of dynamically-registered setting types
2023-05-17 16:19:09 -07:00
Max Brunsfeld
a56793c214 Clear buffer font size adjustments when buffer font size setting changes 2023-05-17 16:14:05 -07:00
Max Brunsfeld
823e15d85a Refresh windows when settings file changes 2023-05-17 16:02:21 -07:00
Max Brunsfeld
667f476f7f Remove unused watched_json file 2023-05-17 16:02:08 -07:00
Max Brunsfeld
42eca3048f Move font size adjustment code to the theme crate 2023-05-17 15:56:32 -07:00
Max Brunsfeld
258723566f Rename settings::register_setting -> settings::register 2023-05-17 15:06:11 -07:00
Max Brunsfeld
2d5f03e148 Remove optional path argument when getting settings 2023-05-17 15:05:20 -07:00
Max Brunsfeld
1f0e79ee9d Merge branch 'main' into setting-store 2023-05-17 14:56:35 -07:00
Max Brunsfeld
67a25126d4 Define theme/ui text style settings in theme crate 2023-05-17 14:44:59 -07:00
Mikayla Maki
5ef03992c5 Merge pull request #2483 from zed-industries/add-scrollbar-settings
Add scrollbars setting
2023-05-17 14:44:08 -07:00
Mikayla Maki
f4e99ecde4 Add never option to scrollbar settings 2023-05-17 14:19:35 -07:00
Mikayla Maki
88bc55ddf5 Add a dependency on rustfmt to the CI tests 2023-05-17 14:17:10 -07:00
Mikayla Maki
6cf439e734 fmt 2023-05-17 14:12:04 -07:00
Mikayla Maki
ae3394f4de Add scrollbars setting 2023-05-17 14:09:26 -07:00
Mikayla Maki
1c9a7a7ad8 Merge pull request #2482 from zed-industries/add-hunks-to-scrollbar
Add diff hunks to the scroll bar
2023-05-17 11:51:01 -07:00
Mikayla Maki
aa89632286 Add diff hunks to the scroll bar 2023-05-17 11:40:30 -07:00
Max Brunsfeld
5c729c0e56 Define base keymap setting in welcome crate 2023-05-17 11:23:09 -07:00
Julia
7d11329e80 Merge pull request #2481 from zed-industries/update-font-kit
Update font-kit to resolve panics when loading malformed fonts
2023-05-17 13:57:39 -04:00
Julia
9e5983305b Update font-kit to resolve panics when loading malformed fonts 2023-05-17 13:38:54 -04:00
Max Brunsfeld
89204e85c0 Merge branch 'main' into setting-store 2023-05-17 09:55:24 -07:00
Joseph Lyons
cb0c613da2 v0.88.x dev 2023-05-17 12:39:08 -04:00
Max Brunsfeld
d2ba18eae9 Customize language settings JSON schema in language crate 2023-05-17 09:26:36 -07:00
Antonio Scandurra
4898417617 Drop foreign key constraint from workspaces.dock_pane to panes table
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-05-17 18:21:35 +02:00
Antonio Scandurra
05fb051924 Store whether a panel is zoomed in the panel itself
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-05-17 17:51:11 +02:00
Antonio Scandurra
f097444546 Rebind ctrl-` to toggle terminal panel focus
Also, add `ctrl-~` to create new terminals.

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-05-17 17:35:10 +02:00
Antonio Scandurra
747fbfadeb Notify old/new ancestors of the focused view when they change 2023-05-17 17:12:12 +02:00
Antonio Scandurra
981129ef8e Show a panel/pane as zoomed only if it's the active item in workspace 2023-05-17 15:06:58 +02:00
Max Brunsfeld
6403bb86e1 Define workspace settings in workspace crate 2023-05-16 20:25:18 -07:00
Max Brunsfeld
cbd4771f10 Define project settings in project crate 2023-05-16 17:45:04 -07:00
Max Brunsfeld
65e3713d4d Define editor settings in editor crate 2023-05-16 17:30:29 -07:00
Max Brunsfeld
39618ae32d Define language settings in the language crate 2023-05-16 17:29:53 -07:00
Julia
0a0769d4b9 Merge pull request #2479 from zed-industries/dont-use-svg-text-feature
Disable usvg's text feature flags to include less dependency code
2023-05-16 18:48:12 -04:00
Julia
d61b12a05b Disable usvg's text feature flags to include less dependency code 2023-05-16 18:44:16 -04:00
Joseph T. Lyons
362f56d519 Merge pull request #2478 from zed-industries/Fix-telemetry-bugs
Send editor event when saving a new file
2023-05-16 18:18:07 -04:00
Joseph Lyons
c27859871f Send editor event when saving a new file 2023-05-16 18:16:09 -04:00
Joseph T. Lyons
2e27f26339 Merge pull request #2475 from zed-industries/add-copilot-events
Add events for copilot suggestion accepting and discarding
2023-05-16 17:25:54 -04:00
Joseph Lyons
ffd503951b Don't make events for every rejected suggestion 2023-05-16 17:19:05 -04:00
Kirill Bulatov
55950e52c2 Remove extra dbg! 2023-05-16 22:15:56 +03:00
Kirill Bulatov
685f3de796 Merge pull request #2462 from zed-industries/kb/go-to-line-column-numbers
Support go to file_query:row:column syntax in Find File, Go To Line dialogs and CLI

Deals slightly differently with zed-industries/community#557
Deals with zed-industries/community#1184

    Fixes Go To Line not respecting column number when navigating to a place
    Changes a line-row separator from , to : to show it more uniformly with other tools
    Adjusts file finder dialogue to allow file_query:row:column syntax and opens the buffer at the lines given
    Extends CLI with file_path:row_column syntax and opens these files similarly
2023-05-16 21:24:57 +03:00
Kirill Bulatov
5d4fc99750 Unit test file:row:column parsing 2023-05-16 21:07:48 +03:00
Kirill Bulatov
be7a58b508 Finalize the CLI opening part 2023-05-16 21:07:48 +03:00
Kirill Bulatov
0c6f103899 Return proper items on workspace restoration.
co-authored-by: Mikayla <mikayla@zed.dev>
2023-05-16 21:07:48 +03:00
Kirill Bulatov
106064c734 Do not break Zed & Zed CLI compatibility 2023-05-16 21:07:47 +03:00
Kirill Bulatov
628558aa39 Attempt to open rows and columns from CLI input 2023-05-16 21:07:26 +03:00
Kirill Bulatov
d719352152 Unify path:row:column parsing, use it in CLI 2023-05-16 21:07:26 +03:00
Kirill Bulatov
89fe5c6b09 Test caret selection in file finder
co-authored-by: Max <max@zed.dev>
2023-05-16 21:07:26 +03:00
Kirill Bulatov
477bc8da05 Make Go To Line to respect column numbers 2023-05-16 21:07:26 +03:00
Kirill Bulatov
e5bca9c871 Simplify file-row-column parsing 2023-05-16 21:07:26 +03:00
Kirill Bulatov
e9606982e6 Use ':' instead of ',' to separate files, rows and columns 2023-05-16 21:07:26 +03:00
Kirill Bulatov
0db7f4202a Properly place the caret into the window of the file opened
co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
2023-05-16 21:07:26 +03:00
Kirill Bulatov
54c1e77aff Move the caret to the opened file 2023-05-16 21:07:26 +03:00
Kirill Bulatov
3eea2fb5f8 Parse file find queries with extra data 2023-05-16 21:07:26 +03:00
Kirill Bulatov
9de4a1b70f Merge pull request #2476 from zed-industries/kb/faster-dev-cli
Allow CLI to start Zed from local sources
2023-05-16 21:06:40 +03:00
Joseph Lyons
afe75e8cbd Send copilot events even if file_extension is not known at the time 2023-05-16 14:02:36 -04:00
Joseph Lyons
6976d60bfe Rework code to contain submitting of copilot events within editor 2023-05-16 13:26:05 -04:00
Julia
16cab5d021 Merge pull request #2477 from zed-industries/fixup-some-more-worktree-bugs
Fixup some more worktree bugs
2023-05-16 13:13:22 -04:00
Julia
8b63caa0bd Fix worktree refresh request causing gitignore to not update
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-05-16 13:01:29 -04:00
Julia
f50240181a Avoid removing fake fs entry when rename fails later in the process
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-05-16 13:00:39 -04:00
Antonio Scandurra
f87ae6032e Don't rely on action propagation for zooming in and out
Co-Authored-By: Antonio Scandurra <antonio@zed.dev>
2023-05-16 10:34:50 -06:00
Joseph Lyons
2d4b2e0844 Fix compile error 2023-05-16 11:51:20 -04:00
Kirill Bulatov
903eed964a Allow CLI to start Zed from local sources
Zed now is able to behave as if it's being started from CLI
(`ZED_FORCE_CLI_MODE` env var)

Zed CLI accepts regular binary file path into `-b` parameter (only *.app before),
and tries to start it as Zed editor with `ZED_FORCE_CLI_MODE` env var
and other params needed.
2023-05-16 17:41:32 +03:00
Kirill Bulatov
421db9225a Merge pull request #2470 from zed-industries/kb/fix-project-search-esc
In project search on ESC, reduce multiple carets to one first
2023-05-16 15:16:34 +03:00
Antonio Scandurra
adf361b374 Implement zooming for panes and docks 2023-05-16 11:49:48 +02:00
Joseph Lyons
a7fc07a8cd Init copilot with client instead of http client 2023-05-16 03:12:39 -04:00
Joseph Lyons
f50afefed3 Subscribe to copilot events (WIP) 2023-05-16 00:35:21 -04:00
Joseph Lyons
a6a2f93607 Update telemetry client to accept copilot events 2023-05-16 00:34:58 -04:00
Mikayla Maki
ead9ac6f23 Fix typo 2023-05-15 16:47:46 -07:00
Mikayla Maki
606d5e36e1 Add events for copilot suggestion accepting and discarding 2023-05-15 16:44:09 -07:00
Mikayla Maki
790223f23a Merge pull request #2473 from zed-industries/fix-styling-feedback
Fix git status issues
2023-05-15 16:28:57 -07:00
Mikayla Maki
e4d509adf4 fmt 2023-05-15 16:22:52 -07:00
Mikayla Maki
4d40aa5d6f Restore trickle up git status to folder
co-authored-by: max <max@zed.dev>
2023-05-15 16:22:00 -07:00
Mikayla Maki
f59256f761 Update git repositories to be streamed with their entries
co-authored-by: max <max@zed.dev>
2023-05-15 16:22:00 -07:00
Mikayla Maki
68078853b7 Made status tracking resilient to folder renames
co-authored-by: max <max@zed.dev>
2023-05-15 16:21:58 -07:00
Mikayla Maki
307dd2b83e Update proto names to reflect new status info 2023-05-15 16:20:01 -07:00
Mikayla Maki
1e4ab6cd75 Add index tracking to status 2023-05-15 16:20:01 -07:00
Mikayla Maki
6c26f3d0e4 Fixed formatting 2023-05-15 16:20:01 -07:00
Mikayla Maki
2b18975cdc Change folder styling from a reduce over all child files to a simple 'always modified'
Remove git status from tab titles
2023-05-15 16:20:01 -07:00
Joseph T. Lyons
17f138906e Merge pull request #2474 from zed-industries/update-jetbrains-keymap
Update jetbrains keymap
2023-05-15 14:17:36 -04:00
Joseph Lyons
6a7d718381 Update jetbrains keymap 2023-05-15 14:12:02 -04:00
Julia
cf53b2ca87 Merge pull request #2471 from zed-industries/optimize-update-local-worktree-buffers
Optimize update local worktree buffers
2023-05-15 13:13:09 -04:00
Antonio Scandurra
c03e470fe6 Introduce Panel::can_zoom 2023-05-15 17:10:30 +02:00
Kirill Bulatov
18e0ee44a6 Remove redundant scopes and actions to fix the focus toggle on ESC
co-authored-by: Antonio <antonio@zed.dev>
2023-05-15 13:10:15 +03:00
Kirill Bulatov
93705cbe55 Merge pull request #2472 from zed-industries/kb/zed-main-builds
Build Zed for main and labeled PR commits

Add a job to build Zed images marked with the SHA of the commit it was built from.

The job triggers on every commit to main or every PR with run-build-dmg label and produces an install-ready *.dmg artifact attached to the corresponding CI run.
2023-05-15 11:30:26 +03:00
Kirill Bulatov
5465948f20 Build Zed dmg 2023-05-15 11:26:41 +03:00
Kirill Bulatov
4f36ba3b1e Add a job to build Zed images from current main
The job triggers on every commit to `main` or every PR with
`run-build-dmg` label and produces an install-ready *.dmg artifact attached to the
corresponding CI run.
2023-05-14 22:06:33 +03:00
Julia
fa32adecd5 Fixup more, tests finally pass 2023-05-14 12:06:00 -04:00
Nathan Sobo
ba50b35de6 wip 2023-05-13 14:34:09 -06:00
Mikayla Maki
db87e83bad Merge pull request #2469 from zed-industries/fix-git-init-bug
Fix repository initialization bug
2023-05-13 10:47:55 -07:00
Mikayla Maki
a6a4b846bc fmt 2023-05-13 10:43:16 -07:00
Mikayla Maki
5e2aaf45a0 Fix repository initialization bug 2023-05-13 10:38:24 -07:00
Mikayla Maki
3534665e2b Merge pull request #2468 from zed-industries/touch-up-status
Improve status integration
2023-05-13 09:38:02 -07:00
Mikayla Maki
04041af78b Fixed bug with failing to clear git file status 2023-05-13 02:40:22 -07:00
Mikayla Maki
62c445da57 Match priority of folder highlights to vscode 2023-05-13 02:30:59 -07:00
Mikayla Maki
41bef2e444 Refactor out git status into FileName component
Integrate file name component into the editor's tab content
2023-05-13 02:26:45 -07:00
Nathan Sobo
6c60853842 Don't close panel on event unless active; add tests 2023-05-12 15:44:09 -06:00
Nathan Sobo
bd795d7607 Preserve panel size when re-docking between left and right 2023-05-12 15:15:11 -06:00
Joseph T. Lyons
e1c1100c7b Merge pull request #2466 from zed-industries/update-release-links
Update release links
2023-05-12 14:08:10 -04:00
Joseph Lyons
b70c874a0e Update release links 2023-05-12 14:04:36 -04:00
Mikayla Maki
ad7ed56e6b Delete pull_request_template.md 2023-05-12 10:15:13 -07:00
Mikayla Maki
4663ac8abf Create pull_request_template.md 2023-05-12 10:14:54 -07:00
Mikayla Maki
e71846c653 Create pull_request_template.md 2023-05-12 10:12:47 -07:00
Mikayla Maki
deac8a6ff9 Merge pull request #2465 from zed-industries/stream-branch-first
Send the root branch along with it's entry
2023-05-12 09:45:40 -07:00
Mikayla Maki
60320c6b09 Send the root branch along with it's entry 2023-05-12 09:37:02 -07:00
Mikayla Maki
54e9e7c35b Merge pull request #2464 from zed-industries/remove-between
Add TreeMap::remove_between that can take abstract start and end points
2023-05-12 08:59:56 -07:00
Nathan Sobo
214354b4da Make panels independently resizable 2023-05-12 09:44:14 -06:00
Mikayla Maki
6ef0f70528 Made the map seek target a publicly implementable interface
Integrated remove_range with the existing git code

co-authored-by: Nathan <nathan@zed.dev>
2023-05-12 08:37:32 -07:00
Nathan Sobo
ee3637216e Add TreeMap::remove_between that can take abstract start and end points
This commit introduces a new adaptor trait for SeekTarget that works around
frustrating issues with lifetimes. It wraps the arguments in a newtype wrapper
that lives on the stack to avoid the lifetime getting extended to the caller
of the method.

This allows us to introduce a PathSuccessor object that can be passed as the
end argument of remove_between to remove a whole subtree.
2023-05-12 08:21:01 -07:00
Kirill Bulatov
89352a2bdc Merge pull request #2463 from zed-industries/kb/reapply-modal-accessibility
Reintroduce more accesible modal keybindings
2023-05-12 06:11:04 +03:00
Max Brunsfeld
9ae10a5dd9 Add a better API for updating settings in the SettingsStore in tests 2023-05-11 17:24:58 -07:00
Mikayla Maki
defc9c8591 Merge pull request #2455 from zed-industries/git-status-viewer
Add Git Status to the project panel
2023-05-11 16:13:34 -07:00
Mikayla Maki
5fe8b73f04 compile error 😅 2023-05-11 16:07:41 -07:00
Mikayla Maki
d526fa6f1f fmt 2023-05-11 16:06:56 -07:00
Mikayla Maki
d538994c7f Use more efficient sum tree traversals for removal and improve ergonomics with iter_from
co-authored-by: Nathan <nathan@zed.dev>
2023-05-11 16:06:25 -07:00
Mikayla Maki
72655fc41d fmt 2023-05-11 13:25:57 -07:00
Mikayla Maki
6f87f9c51f Don't scan for statuses in files that are ignored 2023-05-11 13:25:07 -07:00
Mikayla Maki
1bb34e08bb Fix test 2023-05-11 12:03:39 -07:00
Mikayla Maki
dfb6a2f7fc fmt 2023-05-11 12:02:25 -07:00
Mikayla Maki
5b2ee63f80 Added status trickle up 2023-05-11 12:01:42 -07:00
Kirill Bulatov
f12dffa60c Reintroduce more accesible modal keybindings
Brings commit 475fc40923 back
2023-05-11 20:59:10 +03:00
Mikayla Maki
5accf7cf4e Update is_deleted when sending new repositories 2023-05-11 10:21:25 -07:00
Max Brunsfeld
bebb5456c7 Merge pull request #2461 from zed-industries/ci-target-dir-size
During CI, clear the target directory if it gets larger than a maximum size
2023-05-11 09:57:36 -07:00
Max Brunsfeld
3550110e57 ci: clear the target dir if it gets too big 2023-05-11 09:43:13 -07:00
Mikayla Maki
191ac86f09 Remove the CORRECT, overly agressive deletion codepath 2023-05-11 09:24:36 -07:00
Joseph Lyons
0ab94551f4 Revert "More keybindings in macOs modals with buttons"
This reverts commit 1398a12062.
2023-05-11 11:37:34 -04:00
Julia
0f34af50a8 Use path list generated during entry reload of a refresh request 2023-05-10 23:37:02 -04:00
Mikayla Maki
adfbbf21b2 fmt 2023-05-10 20:09:37 -07:00
Mikayla Maki
f5c633e80c Fixed bug in status deletion marking 2023-05-10 19:54:02 -07:00
Mikayla Maki
fca3bb3b93 Add randomized test for git statuses 2023-05-10 19:21:27 -07:00
Mikayla Maki
9800a149a6 Remove some external context from git status test 2023-05-10 17:59:33 -07:00
Mikayla Maki
f55ca7ae3c Fix incorrect import 2023-05-10 17:52:23 -07:00
Mikayla Maki
18becabfa5 Add postgres migration 2023-05-10 17:50:35 -07:00
Max Brunsfeld
bc5b78198a Define terminal settings in terminal crate 2023-05-10 17:43:10 -07:00
Mikayla Maki
c7166fde3b Bump protocol version 2023-05-10 17:38:29 -07:00
Mikayla Maki
65d4c4f6ed Add integration test for git status 2023-05-10 17:37:36 -07:00
Mikayla Maki
e20eaca595 Got basic replication working :) 2023-05-10 17:37:36 -07:00
Mikayla Maki
2b80dfa81d Update protos 2023-05-10 17:37:36 -07:00
Mikayla Maki
00b345fdfe Use sum tree traversal to remove paths 2023-05-10 17:37:36 -07:00
Mikayla Maki
23a19d85b8 Fix bug in status detection when removing a directory 2023-05-10 17:37:36 -07:00
Mikayla Maki
0082d68d4a Revert "Convert git status calculation to use Entry IDs as the key instead of repo relative paths"
This reverts commit 728c6892c924ebeabb086e308ec4b5f56c4fd72a.
2023-05-10 17:37:36 -07:00
Petros Amoiridis
21e1bdc8cd Fix yellow to be yellow 2023-05-10 17:37:36 -07:00
Petros Amoiridis
6b4242cded Use theme.editor.diff for the colors 2023-05-10 17:37:36 -07:00
Mikayla Maki
f935047ff2 Convert git status calculation to use Entry IDs as the key instead of repo relative paths 2023-05-10 17:37:36 -07:00
Mikayla Maki
94a0de4c9f Fix compile errors 2023-05-10 17:37:36 -07:00
Mikayla Maki
a58a33fc93 WIP: integrate status with collab 2023-05-10 17:37:36 -07:00
Mikayla Maki
18cec8d64f Format 2023-05-10 17:37:36 -07:00
Mikayla Maki
e98507d8bf Added git status to the project panel, added worktree test 2023-05-10 17:37:36 -07:00
Mikayla Maki
93f57430da Track live entry status in repository 2023-05-10 17:37:36 -07:00
Mikayla Maki
bd98f78101 Fix compile error 2023-05-10 17:37:36 -07:00
Mikayla Maki
67491632cb WIP: Track live entry status in repository
co-authored-by: petros <petros@zed.dev>
2023-05-10 17:37:36 -07:00
Mikayla Maki
7169f5c760 Add git status to the file system abstraction
co-authored-by: petros <petros@zed.dev>
2023-05-10 17:37:36 -07:00
Max Brunsfeld
cee7edabf9 Ensure the SettingsStore global is added in tests 2023-05-10 16:39:59 -07:00
Joseph Lyons
6385e51957 collab 0.12.1 2023-05-10 18:16:20 -04:00
Joseph Lyons
9405b49957 v0.87.x dev 2023-05-10 16:47:09 -04:00
Max Brunsfeld
68867fe2e1 Define journal settings in journal crate 2023-05-10 12:59:24 -07:00
Max Brunsfeld
aa6ea920e2 Define telemetry settings in the client crate 2023-05-10 12:59:24 -07:00
Max Brunsfeld
9b06be2aa2 Define vim_mode setting in vim crate 2023-05-10 12:59:24 -07:00
Max Brunsfeld
926d7b356d Define auto_update setting in the auto_update crate 2023-05-10 12:59:24 -07:00
Max Brunsfeld
b6b2c5d1d1 Generalize settings JSON schema logic to work w/ arbitrary setting types 2023-05-10 12:59:24 -07:00
Max Brunsfeld
9a6a2d9d27 Start using the SettingsStore in the app 2023-05-10 12:59:24 -07:00
Max Brunsfeld
316f791a77 Add generic update method to SettingsStore 2023-05-10 12:59:24 -07:00
Max Brunsfeld
24e06334d0 Allow registering additional settings after loading global settings 2023-05-10 12:59:24 -07:00
Max Brunsfeld
5de9652a22 Create proof-of-concept SettingStore struct 2023-05-10 12:59:22 -07:00
Nathan Sobo
5549669316 Test moving panels
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-05-10 10:41:03 -06:00
Mikayla Maki
c7fcc031eb Merge pull request #2460 from zed-industries/show-dock-on-activate
Fix bug with terminal button
2023-05-10 09:08:45 -07:00
Nathan Sobo
cc21421ea8 Rename item to panel in various locations 2023-05-10 09:54:20 -06:00
Mikayla Maki
0dce5ba7ae Fix bug with terminal button 2023-05-10 08:15:20 -07:00
Antonio Scandurra
0ccb4a50e6 Create more specific dock position settings associated with each panel 2023-05-10 16:52:10 +02:00
Antonio Scandurra
e507eadb4b Rely on root getting re-focused when panel isn't rendered
This achieves two things:

- When a panel like `TerminalPanel` closes its last tab, the focus
is returned to the root view (the `Workspace`)
- When a panel is moved from a dock to another, it will get rendered
in another spot but the focus will be kept on the panel

This also ensures the focus is not lost when a panel is moved from
a dock to another because that view
2023-05-10 15:43:44 +02:00
Antonio Scandurra
9b9d53fcf8 Focus the root view if the previously-focused view isn't rendered 2023-05-10 15:40:46 +02:00
Antonio Scandurra
cdcb7c8084 Merge branch 'main' into panels 2023-05-10 15:23:37 +02:00
Antonio Scandurra
f28eee88b6 Add context menu to change panel position 2023-05-10 14:05:48 +02:00
Antonio Scandurra
8fa379bbc5 Maintain panel visibility when changing its position 2023-05-10 11:06:37 +02:00
Antonio Scandurra
6e3ce6332a Fix panic when not specifying a project_panel setting 2023-05-10 10:43:42 +02:00
Kirill Bulatov
eec60556ab Highlight include/exclude inputs when errors happen there 2023-05-10 11:11:31 +03:00
Kirill Bulatov
dfdf7e4866 Test the search inclusions/exclusions 2023-05-10 11:11:31 +03:00
Kirill Bulatov
80fc1bc276 Use placeholder in include/exclude editors 2023-05-10 11:11:31 +03:00
Kirill Bulatov
0e31d13a1e Rework tab and escape key handling in search panel
Fixes
https://linear.app/zed-industries/issue/Z-1238/focus-the-results-multibuffer-in-project-search-on-esc

and adds a tab shortcut for project search inputs

co-authored-by: Julia <julia@zed.dev>
2023-05-10 11:11:31 +03:00
Kirill Bulatov
3da55c14a6 Fix arrow layout 2023-05-10 11:11:31 +03:00
Kirill Bulatov
6fb8679184 Trim glob input 2023-05-10 11:11:31 +03:00
Kirill Bulatov
13296d502c Extra rows approach draft
co-authored-by: Max <max@zed.dev>
2023-05-10 11:11:31 +03:00
Kirill Bulatov
b5abac6af6 Draft search include/exclude logic 2023-05-10 11:11:31 +03:00
Kirill Bulatov
915154b047 Add initial include/exclude project search UI 2023-05-10 11:11:31 +03:00
Antonio Scandurra
3115c8381d Merge pull request #2458 from zed-industries/fix-context-menu-click
Always dismiss context menu on click
2023-05-10 09:24:23 +02:00
Antonio Scandurra
1b5e79251c Always dismiss context menu on click 2023-05-10 09:18:13 +02:00
Nathan Sobo
9173916ab8 Remove unused terminal_button module 2023-05-09 20:24:37 -06:00
Nathan Sobo
f554877ff4 Render the bottom dock buttons before the right dock buttons 2023-05-09 17:41:24 -06:00
Nathan Sobo
ba248244ec Allow terminal to be docked left, bottom, or right
Co-Authored-By: Joseph Lyons <joseph@zed.dev>
2023-05-09 17:36:49 -06:00
Nathan Sobo
6a7feb4c4c Allow the project panel to be docked right or left
Co-Authored-By: Joseph Lyons <joseph@zed.dev>
2023-05-09 17:26:54 -06:00
Nathan Sobo
0d78266ddb Replace todo with unimplemented to reduce distractions 2023-05-09 16:41:10 -06:00
Nathan Sobo
6d16d2224d Merge branch 'main' into panels 2023-05-09 16:35:04 -06:00
Nathan Sobo
5e8b7bd06d Replace todo with unimplemented to reduce distractions 2023-05-09 16:31:53 -06:00
Mikayla Maki
26d80eef0a Merge pull request #2456 from zed-industries/fix-dock-pane-focus
Make dock not eagerly steal focus from sub items
2023-05-09 15:59:06 -04:00
Mikayla Maki
0214228689 Fix format 2023-05-09 12:54:53 -07:00
Nathan Sobo
6645323f1b WIP 2023-05-09 13:28:34 -06:00
Mikayla Maki
6dfb48dbd5 Fix center items not being activated when deserialized 2023-05-09 12:27:07 -07:00
Mikayla Maki
8d561d6408 Make dock not eagerly steal focus from sub items 2023-05-09 12:00:09 -07:00
Antonio Scandurra
8f12489937 WIP: Allow panels to be moved
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-09 18:57:25 +02:00
Antonio Scandurra
45df09245b Remove unused code
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-05-09 18:06:59 +02:00
Antonio Scandurra
37d3ed5f5f Focus new item if pane was focused when removing previous active item
Previously, we were relying on the item getting blurred and the workspace
receiving focus, which would in turn focus the active pane. This doesn't
play well with docks because they aren't part of the workspace panes.
2023-05-09 17:38:54 +02:00
Antonio Scandurra
641f5d1107 Ensure ctrl-` works in the terminal panel 2023-05-09 17:38:18 +02:00
Antonio Scandurra
2bc7be9a76 WIP 2023-05-09 17:14:33 +02:00
Antonio Scandurra
48ad3866b7 Randomly mutate worktree in addition to mutating the file-system
This ensures that we test the code path that refreshes entries.

Co-Authored-By: Julia Risley <julia@zed.dev>
2023-05-09 17:01:11 +02:00
Antonio Scandurra
7f27d72b20 Deliver file-system change events in batches in randomized worktree test
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-05-09 16:55:03 +02:00
Julia
5c859da457 Only update changed local worktree buffers
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-05-09 15:13:12 +02:00
Antonio Scandurra
634b699281 Allow customization of Pane tab bar buttons 2023-05-09 15:05:29 +02:00
Antonio Scandurra
ad7f32d7d2 Fix bottom dock resizing 2023-05-09 14:46:15 +02:00
Antonio Scandurra
26fe7a81f3 Prevent splits in the terminal panel 2023-05-09 12:29:16 +02:00
Antonio Scandurra
e6be35c9a5 Show terminal count in panel button 2023-05-09 12:21:35 +02:00
Antonio Scandurra
02066afb0e Don't pass &mut Workspace when closing items in a Pane
This allows closing items via actions even in the `TerminalPanel`
where the `Pane` is not directly owned by a `Workspace`.
2023-05-09 11:45:39 +02:00
Antonio Scandurra
506f978c41 Automatically close terminal dock when the last terminal was closed 2023-05-09 10:18:11 +02:00
Antonio Scandurra
916612caf1 Prevent dragging items that aren't terminals to the terminal panel 2023-05-09 10:18:11 +02:00
Antonio Scandurra
6ddc610fa2 WIP: Start on TerminalPanel 2023-05-09 10:18:11 +02:00
Nathan Sobo
1ddbda5095 Rename DockItem to Panel 2023-05-09 10:18:11 +02:00
Nathan Sobo
03f8c1206a Rename Sidebar to Dock 2023-05-09 10:18:10 +02:00
Nathan Sobo
1919a826f9 Remove dock from workspace 2023-05-09 10:18:10 +02:00
Mikayla Maki
2d7cfb8c7c Merge pull request #2454 from zed-industries/fix-mismatching-panes-when-deserializing-empty-panes
Fully remove panes and update internal data structures
2023-05-08 20:37:06 -04:00
Mikayla Maki
fa049bea6e Refactor and fix format 2023-05-08 17:32:40 -07:00
Mikayla Maki
49335d017a Add manual removal code to remove_panes 2023-05-08 17:25:28 -07:00
Mikayla Maki
9b2d3fcd48 Fully remove panes and update internal data structures 2023-05-08 17:09:29 -07:00
Max Brunsfeld
8fd0c9fb0e collab 0.12.0 2023-05-08 15:54:11 -07:00
Mikayla Maki
1d66f24f23 Merge pull request #2428 from zed-industries/add-branch-name
Add branch name and synchronize repository representations on the worktree.
2023-05-08 17:40:47 -04:00
Mikayla Maki
9366a0dbee Bump protocol version number 2023-05-08 14:34:14 -07:00
Mikayla Maki
f28419cfd1 Fix styling of titlebar highlights 2023-05-08 14:33:59 -07:00
Mikayla Maki
712fb5ad7f Add postgres migration 2023-05-08 14:33:59 -07:00
Mikayla Maki
1a9afd186b Restore randomized integration tests 2023-05-08 14:33:59 -07:00
Mikayla Maki
15d2f19b4a fix format 2023-05-08 14:33:59 -07:00
Mikayla Maki
d2279674a7 Fix panic in tests 2023-05-08 14:33:59 -07:00
Mikayla Maki
62e763d0d3 Removed test modifications, added special case to git initialization for when the repository is inside a .git folder 2023-05-08 14:33:59 -07:00
Mikayla Maki
f9e4464658 Refresh titlebar on project notifications 2023-05-08 14:33:59 -07:00
Mikayla Maki
2c2076bd77 Adjust tests to not create repositories inside repositories 2023-05-08 14:33:59 -07:00
Mikayla Maki
ab952f1b31 Fixed randomized test failures
co-authored-by: Max <max@zed.dev>
2023-05-08 14:33:59 -07:00
Mikayla Maki
d8dac07408 Removed scan ID from repository interfaces
co-authored-by: Max <max@zed.dev>
2023-05-08 14:33:59 -07:00
Mikayla Maki
270147d20c Finished RepositoryEntry refactoring, smoke tests passing
co-authored-by: Max <max@zed.dev>
2023-05-08 14:33:59 -07:00
Mikayla Maki
53569ece03 WIP: Change RepositoryEntry representation to be keyed off of the work directory
Removes branches button scaffolding
2023-05-08 14:33:59 -07:00
Mikayla Maki
b6d6f5c650 WIP: re-arranging the RepositoryEntry representation
Added branches to the randomized test to check the git branch
Added the remaining database integrations in collab

Co-authored-by: Max <max@zed.dev>
Co-authored-by: Petros <petros@zed.dev>
2023-05-08 14:33:59 -07:00
Mikayla Maki
8bde496e74 Add branch name in title UI
co-authored-by: Petros <petros@zed.dev>
2023-05-08 14:33:59 -07:00
Petros Amoiridis
5302c256a4 Rebase main and fix error 2023-05-08 14:33:59 -07:00
Mikayla Maki
8301ee43d6 WIP: Add repository entries to collab and synchronize when rejoining the room
co-authored-by: Max <max@zed.dev>
2023-05-08 14:33:59 -07:00
Mikayla Maki
2fe5bf419b Add proto fields for repository entry maintenance 2023-05-08 14:33:59 -07:00
Mikayla Maki
c6d7ed33c2 Add smoke test for collaboration 2023-05-08 14:33:59 -07:00
Petros Amoiridis
ca4da52e39 Remove unused functions 2023-05-08 14:33:59 -07:00
Petros Amoiridis
e057b0193f Introduce BrancesButton in title bar
Co-Authored-By: Mikayla Maki <mikayla.c.maki@gmail.com>
2023-05-08 14:33:58 -07:00
Petros Amoiridis
797d47a08c Render title root names without branches 2023-05-08 14:33:58 -07:00
Petros Amoiridis
92a222aba8 Introduce a version control branch icon 2023-05-08 14:33:58 -07:00
Mikayla Maki
8f0aa3c6d9 Add branch name into title 2023-05-08 14:33:58 -07:00
Petros Amoiridis
d34ec462f8 Display branch information per worktree root
Co-Authored-By: Mikayla Maki <mikayla.c.maki@gmail.com>
2023-05-08 14:33:58 -07:00
Mikayla Maki
ffd9d4eb59 Fix bug in repo detection 2023-05-08 14:33:58 -07:00
Mikayla Maki
3570810516 Add API for accessing git branch 2023-05-08 14:33:58 -07:00
Mikayla Maki
26afd592c5 Wire in the branch name 2023-05-08 14:33:58 -07:00
Mikayla Maki
5b4e58d1de Fix repo_for and clean up repository_entries 2023-05-08 14:33:58 -07:00
Mikayla Maki
023d665fb3 Fix TreeMap retain 2023-05-08 14:33:58 -07:00
Mikayla Maki
ae890212e3 Restored a lost API and got everything compiling 2023-05-08 14:33:58 -07:00
Mikayla Maki
bcf608e9e9 WIP: Refactor existing git code to use new representation.
co-authored-by: petros <petros@zed.dev>
2023-05-08 14:33:58 -07:00
Mikayla Maki
563f13925f WIP: Convert old git repository vec to new treemap based approach.
co-authored-by: Nathan <nathan@zed.dev>
2023-05-08 14:33:58 -07:00
Mikayla Maki
a58d3d8128 Add a data driven representation of the current git repository state to the worktree snapshots
WIP: Switch git repositories to use SumTrees

Co-authored-by: Nathan <nathan@zed.dev>
2023-05-08 14:33:58 -07:00
Mikayla Maki
bb93447a0d Merge pull request #2453 from zed-industries/fix-click-fallthrough
Fixed clicks falling through the modal terminal
2023-05-08 13:59:57 -04:00
Mikayla Maki
2cf928c85a Fixed clicks falling through the modal terminal
co-authored-by: Antonio <antonio@zed.dev>
2023-05-08 10:54:12 -07:00
Kirill Bulatov
39bddfc7b7 Only allow invisbles in local and leader selections 2023-05-08 19:36:51 +03:00
Kirill Bulatov
98ff18c430 Code review fixes 2023-05-08 19:36:51 +03:00
Kirill Bulatov
e6489e999d Add invisibles wrapping test 2023-05-08 19:36:51 +03:00
Kirill Bulatov
d2b2dc39d9 Do not print invisibles in non-full mode editors 2023-05-08 19:36:51 +03:00
Nate Butler
ab6b3adb2b Add a theme entry for whitespace, use it to style whitespaces
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
Co-Authored-By: Kirill Bulatov <mail4score@gmail.com>
2023-05-08 19:36:51 +03:00
Kirill Bulatov
fb3ef4bcf6 Fix wrapped line detection 2023-05-08 19:36:51 +03:00
Kirill Bulatov
075bab2ea9 Use more convntional name for the settings 2023-05-08 19:36:51 +03:00
Kirill Bulatov
706f6f495a Add a test 2023-05-08 19:36:51 +03:00
Kirill Bulatov
ec725fe399 Do not print extra invisibles on line wraps 2023-05-08 19:36:51 +03:00
Kirill Bulatov
95bcd19020 Refactor line glyphs drawing methods 2023-05-08 19:36:51 +03:00
Kirill Bulatov
4aaf44df94 Support invisibles in the selection 2023-05-08 19:36:51 +03:00
Kirill Bulatov
1eeeec157e Use cached standard glyphs for invisible symbols
Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
2023-05-08 19:36:51 +03:00
Kirill Bulatov
714734d279 Add whitespaces rendering 2023-05-08 19:36:51 +03:00
Kirill Bulatov
2d8c88ad73 Draw tabs with svg icons in editor code only 2023-05-08 19:36:51 +03:00
Kirill Bulatov
f0a88b3337 Make invisibles display configurable 2023-05-08 19:36:51 +03:00
Kirill Bulatov
ad731ea6d2 Draft invisibles' tabs display 2023-05-08 19:36:51 +03:00
Max Brunsfeld
4f8607039c Add is_tab field to chunks
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-05-08 19:36:51 +03:00
Julia
cf304a0edc Merge pull request #2452 from zed-industries/prevent-some-rounding-clipping
Prevent some cases of clipping icons due to pixel coord rounding
2023-05-08 11:48:33 -04:00
Julia
332b364a30 Prevent some cases of clipping icons due to pixel coord rounding 2023-05-08 11:42:00 -04:00
Antonio Scandurra
235470bbfd Merge pull request #2451 from zed-industries/kb/extra-deps
Remove unused dependencies
2023-05-08 14:46:27 +02:00
Kirill Bulatov
6cb0bc89d2 Remove unused dependencies 2023-05-07 21:07:55 +03:00
Antonio Scandurra
0296974ab1 Merge pull request #2441 from zed-industries/implicit-ancestry
Determine view ancestry during layout
2023-05-05 10:58:00 +02:00
Antonio Scandurra
5e16f70067 💄 2023-05-05 10:53:15 +02:00
Antonio Scandurra
080a1f00a3 Delay focus_in event for window activation till after layout 2023-05-05 10:47:42 +02:00
Antonio Scandurra
b9ed327b94 Replace usages of is_parent_view_focused with is_self_focused
Previously, this was used because we didn't have access to the current
view and `EventContext` was an element-only abstraction. Now that the
`EventContext` wraps the current view's `ViewContext` we can simply check
for the view's focus and avoid querying ancestors.
2023-05-05 10:08:22 +02:00
Antonio Scandurra
80ad59a620 Make focusing the parent an effect to avoid querying ancestors 2023-05-05 10:04:54 +02:00
Joseph T. Lyons
c55a4c0feb Merge pull request #2447 from zed-industries/fix-auto-update
Do not use post_json() to auto update
2023-05-04 17:15:09 -04:00
Mikayla Maki
3631b3a86c Merge pull request #2446 from zed-industries/fix-copilot-logged-out
Fix copilot stuck in logged out state
2023-05-04 16:52:04 -04:00
Mikayla Maki
89af803565 Rearrange the state machine 2023-05-04 13:45:31 -07:00
Julia
137cbaba34 Merge pull request #2445 from zed-industries/construct-text-buffer-in-background
Construct text buffer in background
2023-05-04 16:01:39 -04:00
Julia
eacea55aaf Fixup cases using buffer model handle id as buffer id 2023-05-04 12:32:31 -04:00
Julia
1883e260ce Offload text::Buffer construction to background worker
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-05-04 12:32:31 -04:00
Julia
7e06062bdb Store history base text as rope
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-05-04 12:32:31 -04:00
Joseph Lyons
8313414e1e Do not use post_json() to auto update 2023-05-04 12:12:36 -04:00
Antonio Scandurra
d6b0569bed Merge branch 'main' into implicit-ancestry 2023-05-04 17:19:06 +02:00
Antonio Scandurra
f51425d390 Merge pull request #2444 from zed-industries/fix-clicking-sidebar-buttons
Use `Workspace::toggle_sidebar_item` when clicking on sidebar button
2023-05-04 17:14:40 +02:00
Antonio Scandurra
64e0c16baa Use Workspace::toggle_sidebar_item when clicking on sidebar button
Previously, we were mistakenly using `Sidebar::toggle_item`, which only
performs part of the toggle operation.
2023-05-04 17:06:37 +02:00
Antonio Scandurra
cbae4e751b Merge pull request #2443 from zed-industries/fix-vim-mode-rename
Avoid calling `update_window` twice in `blurred` event handler
2023-05-04 16:24:51 +02:00
Antonio Scandurra
912a4cf549 Avoid calling update_window twice in blurred event handler
This was preventing us from unhooking vim when performing a rename,
which prevented typing in the rename editor.
2023-05-04 16:18:01 +02:00
Antonio Scandurra
0f93714d4f Merge pull request #2442 from zed-industries/filter-vim-commands
Filter out vim commands when vim mode is disabled
2023-05-04 15:00:19 +02:00
Antonio Scandurra
b1f5cfaa79 Merge pull request #2440 from zed-industries/fix-navigate-to-definitions-panic
Fix panic when opening multiple definitions in a multibuffer
2023-05-04 14:56:43 +02:00
Antonio Scandurra
b3baebde22 Filter out vim commands when vim mode is disabled 2023-05-04 14:52:34 +02:00
Antonio Scandurra
da19edc3e3 Merge branch 'main' into implicit-ancestry 2023-05-04 14:39:58 +02:00
Antonio Scandurra
121264d35a Fix panic when opening multiple definitions in a multibuffer
The editor is on the stack, so adding an item to the `Pane` containing
the editor will cause a double borrow and a consequent panic. This
commit fixes the issue by deferring the opening of the definitions.
2023-05-04 14:34:42 +02:00
Antonio Scandurra
7e2a461486 Merge pull request #2439 from zed-industries/fix-keystrokes-for-action
Cache view's type id and keymap context into a separate map
2023-05-04 14:22:42 +02:00
Antonio Scandurra
5cc6304fa6 Verify keystrokes can be queried while views are on the stack 2023-05-04 12:09:32 +02:00
Antonio Scandurra
3d679ddb26 Avoid re-allocating KeymapContext after every view notification 2023-05-04 12:04:30 +02:00
Antonio Scandurra
18e39ef2fa Cache view's type id and keymap context into a separate map
During `layout`, we now pass a mutable reference to the element's
parent view. This is a recursive process that causes the view to
be removed from `AppContext` and then re-inserted back into it once
the layout is complete.

As such, querying parent views during `layout` does not work as such
views will have been removed from `AppContext` and not yet re-inserted
into it. This caused a bug in `KeystrokeLabel`, which used the `keystrokes_for_action`
method to query its ancestors to determine their type id and keymap context.

Now, any time a view notifies, we will cache its keymap context so that
we don't need to query the parent view during `layout`.
2023-05-04 10:47:56 +02:00
Antonio Scandurra
7b7a495be3 Remove stray dbg! statement 2023-05-04 09:56:49 +02:00
Antonio Scandurra
f6f18be9c3 Remove WindowContext::is_child_focused 2023-05-04 09:53:35 +02:00
Antonio Scandurra
67a3891f15 Make dispatch_event related methods public to the crate only 2023-05-04 09:53:35 +02:00
Antonio Scandurra
92183e0d72 Ensure querying keystrokes or actions is safe
This is achieved by moving `available_actions` into `AsyncAppContext` (where
we know no view/window is on the stack) and `keystrokes_for_action` into `LayoutContext`
where we'll fetch the previous frame's ancestors and notify the current view if those
change after we perform a layout.
2023-05-04 09:53:31 +02:00
Joseph Lyons
053b34875b collab 0.11.0 2023-05-03 14:59:04 -04:00
Joseph Lyons
653ea3a85d v0.86.x dev 2023-05-03 14:38:41 -04:00
Max Brunsfeld
c2c29d3fb6 Merge pull request #2427 from zed-industries/copilot-disabled-globs
Add copilot.disabled_globs setting
2023-05-03 11:00:08 -07:00
Max Brunsfeld
9d41f83b1b Merge branch 'main' into copilot-disabled-globs 2023-05-03 10:53:28 -07:00
Antonio Scandurra
040cc4d4c3 Allow notifying views when the ancestry of another view is outdated 2023-05-03 19:25:00 +02:00
Max Brunsfeld
8eb1312deb Add copilot menu item for enabling paths by glob 2023-05-03 10:14:01 -07:00
Antonio Scandurra
7250754f8e Make dispatch_keystroke public to the crate only 2023-05-03 19:13:17 +02:00
Antonio Scandurra
9e8f852afb Remove ViewContext::is_child 2023-05-03 19:09:07 +02:00
Antonio Scandurra
5157442703 Fix integration test relying on deferred happening after focus
Focus is now one of the last things that happens during `flush_effects`,
and we shouldn't have relied on `defer` in the first place to verify
focus changes.
2023-05-03 19:00:32 +02:00
Antonio Scandurra
c65465b0b5 Ensure workspace gets rendered in collab integration tests 2023-05-03 18:31:07 +02:00
Antonio Scandurra
e9ed40da37 Remove the ability to retrieve the view's parent 2023-05-03 16:52:55 +02:00
Antonio Scandurra
7f137ed3dd Compute view ancestry at layout time 2023-05-03 16:36:14 +02:00
Antonio Scandurra
7f345f8bf5 Separate Window::build_scene into layout and paint 2023-05-03 12:18:16 +02:00
Antonio Scandurra
3f037e5128 Merge pull request #2437 from zed-industries/fix-joining-call
Fix "IncomingCallNotification was dropped" error when accepting a call
2023-05-03 10:49:04 +02:00
Antonio Scandurra
376aa1235f Fix "IncomingCallNotification was dropped" error when accepting a call
This was caused by accepting the call, which caused the notification to
be removed. When `active_call.accept_incoming()` finally completed, we
would try to get the app state from it in order to join the project, but
couldn't becuase the view would have already been dropped.

This commit fixes the bug by capturing a weak handle to the app state
when accepting the call as opposed to trying to read it from the view
when the accept completes.
2023-05-03 10:37:57 +02:00
Antonio Scandurra
c3cf9e3185 Merge pull request #2436 from zed-industries/close-window-end-call
Move methods querying window state into `AsyncAppContext`
2023-05-03 10:27:05 +02:00
Joseph T. Lyons
f576586cd7 Merge pull request #2435 from zed-industries/use-json-post-request-for-update-requests
Use json_post() request for update requests
2023-05-02 23:42:25 -04:00
Joseph Lyons
41d4454f45 Use post_json so that the Content-Type is set to application/json 2023-05-02 23:23:43 -04:00
Joseph Lyons
69a4fffae2 Update post_json to take in a bool for allowing for redirects 2023-05-02 23:22:55 -04:00
Joseph T. Lyons
7f5afeb9fa Merge pull request #2434 from zed-industries/add-download-and-uplodate-metadata-to-update-request
Add download and upload metadata to update request
2023-05-02 22:27:58 -04:00
Joseph Lyons
2b95aba99c Add download and upload metadata to update request 2023-05-02 17:16:42 -04:00
Kirill Bulatov
1398a12062 More keybindings in macOs modals with buttons
Closes https://github.com/zed-industries/community/issues/1095
by forcing the non-Cancel button to get a focus.
Due to the way macOs handles buttons on modals, the focus gain had to be
achieved via certain button addition order, rather than conventional
"setFocus"-ish API, see the related comment for details.

Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-05-02 21:10:20 +03:00
Antonio Scandurra
70f8cf4cf6 Move methods querying window state into AsyncAppContext 2023-05-02 19:38:48 +02:00
Julia
4f6939732e Merge pull request #2432 from zed-industries/more-diagnostic-source
Show diagnostic source in more places
2023-05-02 09:16:11 -04:00
Julia
185c1650df Show diagnostic source in inline diagnostic 2023-05-02 09:08:07 -04:00
Antonio Scandurra
9108e4151e Merge pull request #2431 from zed-industries/fix-broken-contact-finder
Fix broken styling in contact finder
2023-05-02 13:55:14 +02:00
Antonio Scandurra
94f1775533 Fix broken styling in contact finder
This regressed as part of #2372, where we forgot to theme the contact
finder picker differently from the rest of the app.
2023-05-02 13:46:49 +02:00
Antonio Scandurra
e8f2d985ff Merge pull request #2430 from zed-industries/fix-toggle-contacts-panic
Fix panic when showing contacts popover via keybinding
2023-05-02 11:53:24 +02:00
Antonio Scandurra
f985fac6f9 Fix panic when showing contacts popover via keybinding 2023-05-02 11:47:05 +02:00
Antonio Scandurra
484cda51cf Merge pull request #2429 from zed-industries/fix-debug-elements-panic
Move `debug_elements` to `AsyncAppContext`
2023-05-02 11:15:57 +02:00
Kirill Bulatov
f5278c49b0 Clarify GH Token scope requirements 2023-05-02 12:12:57 +03:00
Antonio Scandurra
794446bf8b Move debug_elements to AsyncAppContext
Previously, `debug_elements` was available on `WindowContext`. If that
method was called while having a borrow out to a view, it would panic because
the view would already have been borrowed.

By moving it to an `AsyncAppContext` we ensure the method can't be called while
a view is being used.
2023-05-02 11:09:40 +02:00
Antonio Scandurra
4c1cba6def Remove unnecessary Element impl for RootElement 2023-05-02 10:09:57 +02:00
Julia
f7de0ad8ae Show diagnostic source in diagnostic multibuffer headers 2023-05-01 16:48:27 -04:00
Max Brunsfeld
c485fc86a2 Add copilot.disabled_globs setting 2023-05-01 13:45:47 -07:00
Joseph T. Lyons
f62ba2eec7 use installation_id over device_id 2023-05-01 16:29:51 -04:00
Julia
5fb9d53dd0 Merge pull request #2425 from zed-industries/trim-eslint-workspace-configuration
Trim eslint workspace configuration & remove diagnostic source underline
2023-05-01 13:24:14 -04:00
Julia
40ab5c1fb9 Remove underline from diagnostic source 2023-05-01 13:15:41 -04:00
Julia
4966a4a681 Reduce hardcoded ESLint workspace configuration 2023-05-01 13:14:35 -04:00
Antonio Scandurra
a8084ad3f4 Merge pull request #2424 from zed-industries/constrain-programmatic-dispatch
Allow programmatic action dispatch only via `AsyncAppContext`
2023-05-01 17:10:57 +02:00
Antonio Scandurra
780ece551e Defer hiding the dock and going back/forward when Pane is on the stack 2023-05-01 17:06:05 +02:00
Antonio Scandurra
e3b2407ebf Run until parked now that the command palette spawns to dispatch action 2023-05-01 16:58:07 +02:00
Antonio Scandurra
6c931ab9da Inline test-only AppContext methods 2023-05-01 16:49:17 +02:00
Antonio Scandurra
eb2cce98a7 Move dispatch_action_any_action_at to AsyncAppContext 2023-05-01 16:40:57 +02:00
Antonio Scandurra
c4472b0786 Remove ViewContext::dispatch_action 2023-05-01 16:27:36 +02:00
Antonio Scandurra
d815fc88ae Remove ViewContext::dispatch_any_action 2023-05-01 14:24:00 +02:00
Antonio Scandurra
029538fe21 Make dispatch_global_action private 2023-05-01 11:45:35 +02:00
Antonio Scandurra
0f44648b38 Merge pull request #2423 from zed-industries/fix-panic-in-go-to-definition
Fix panic when clicking on a definition
2023-04-29 15:02:18 +02:00
Antonio Scandurra
e566929d9e Fix panic when clicking on a definition
This was introduced with #2420 and was caused by re-entrantly updating
the workspace. Instead of passing the workspace reference from the outside,
we now define the definition navigation as a method on the editor which solves
the issue.

Note that we also needed to introduce a `defer` call when navigating to a definition
to prevent the workspace from reading the editor during `open_project_item`.
2023-04-29 14:53:17 +02:00
Joseph T. Lyons
ae5794d911 Merge pull request #2421 from zed-industries/metrics-2
Rework telemetry code to support sending events to Clickhouse
2023-04-28 17:16:33 -04:00
Julia
32f26d1e9a Merge pull request #2422 from zed-industries/source-eslint-server-from-github
Source ESLint server from Github rather than 3rd party NPM package
2023-04-28 16:53:07 -04:00
Julia
1bf85214a4 Source ESLint server from Github rather than 3rd party NPM package 2023-04-28 16:42:36 -04:00
Joseph Lyons
6b0faa2d9c Rework telemetry code to support sending events to Clickhouse
Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
2023-04-28 16:06:55 -04:00
Antonio Scandurra
dc999f719b Merge pull request #2420 from zed-industries/simplify-action-dispatch
Remove `impl_internal_actions!` macro
2023-04-28 17:39:56 +02:00
Antonio Scandurra
106ebeb386 Remove obsolete presenter modules 2023-04-28 17:37:25 +02:00
Antonio Scandurra
489b1f6a63 Merge remote-tracking branch 'origin/main' into simplify-action-dispatch 2023-04-28 17:31:12 +02:00
Antonio Scandurra
1c5376a560 Remove impl_internal_actions macro 2023-04-28 17:29:57 +02:00
Antonio Scandurra
1d41a703ad Remove internal actions from terminal_button 2023-04-28 17:29:17 +02:00
Antonio Scandurra
33da9e5690 Remove internal actions from project_panel 2023-04-28 17:21:10 +02:00
Antonio Scandurra
e1535735b8 Remove DeployContextMenu internal action 2023-04-28 16:51:01 +02:00
Antonio Scandurra
f65e64829e Remove Scroll internal action 2023-04-28 16:43:31 +02:00
Antonio Scandurra
3409ee1785 Remove DeployMouseContextMenu internal action
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-28 16:41:46 +02:00
Antonio Scandurra
c22342e271 💄
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-28 16:38:00 +02:00
Antonio Scandurra
1f35e1dbf9 Remove internal actions from copilot_button
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-28 16:36:57 +02:00
Antonio Scandurra
a91903c2ab Remove internal actions from link_go_to_definition 2023-04-28 16:24:46 +02:00
Antonio Scandurra
264a2c1835 Remove HideHover and HoverAt internal actions 2023-04-28 16:12:24 +02:00
Antonio Scandurra
e6f561ce46 Remove unused Jump internal action 2023-04-28 15:57:36 +02:00
Antonio Scandurra
c04cb0286a Remove Dismiss and RespondToContactRequest internal actions 2023-04-28 15:56:41 +02:00
Antonio Scandurra
0469e25de6 Remove LeaveCall internal action 2023-04-28 14:14:25 +02:00
Antonio Scandurra
83436213ad Remove Jump internal action 2023-04-28 14:13:07 +02:00
Antonio Scandurra
3763b985e3 Fix panic due to re-entrantly reading Workspace 2023-04-28 12:36:50 +02:00
Antonio Scandurra
a978f3fe4f Remove Select internal action 2023-04-28 12:33:22 +02:00
Antonio Scandurra
5215adbd3f Remove ToggleExpanded and Call internal actions 2023-04-28 12:26:47 +02:00
Antonio Scandurra
5d8fcceee3 Remove RespondToCall internal action 2023-04-28 12:24:07 +02:00
Antonio Scandurra
4bcba487c5 Remove SplitWithProjectEntry internal action 2023-04-28 12:19:38 +02:00
Antonio Scandurra
272039a858 Remove SplitWithItem internal action 2023-04-28 12:17:31 +02:00
Antonio Scandurra
6857426b78 Remove RemoveWorktreeFromProject internal action 2023-04-28 12:11:59 +02:00
Antonio Scandurra
71a4bc7905 Remove OpenSharedScreen internal action 2023-04-28 12:09:34 +02:00
Antonio Scandurra
d953729233 Remove JoinProject internal action 2023-04-28 11:22:04 +02:00
Antonio Scandurra
f881f9e3d8 Remove ToggleFollow internal action 2023-04-28 10:07:44 +02:00
Antonio Scandurra
06c01a5937 Eliminate OpenPaths global action for workspace and replace with methods
We no longer want to invoke this with dispatch_action.
2023-04-27 18:36:28 -06:00
Max Brunsfeld
db73ba5a1a Merge pull request #2419 from zed-industries/zombie-copilot-process
Shutdown copilot server when quitting zed
2023-04-27 14:47:30 -07:00
Max Brunsfeld
1533c17cd7 Shutdown copilot server when quitting zed 2023-04-27 14:39:00 -07:00
Max Brunsfeld
7258db7a4e Merge pull request #2417 from zed-industries/hover-markdown
Render markdown more correctly in the editor hover popover
2023-04-27 14:15:04 -07:00
Max Brunsfeld
6042df393b Give code spans in markdown a background highlight 2023-04-27 13:58:30 -07:00
Max Brunsfeld
8eb9c6563a Generalize Text element to let you add arbitrary scene primitives for runs of text 2023-04-27 13:58:06 -07:00
Julia
92c9de1f50 Merge pull request #2415 from zed-industries/diagnostic-hovers-source
Show source of diagnostic on hover
2023-04-27 15:12:22 -04:00
Julia
87539e7b82 Update test to not fail due to absence of diagnostic source 2023-04-27 15:04:48 -04:00
Max Brunsfeld
66d4cb8c14 Tweak rendering of multi-paragraph list items in markdown 2023-04-27 11:39:34 -07:00
Julia
a284fae515 Don't hardcode workspaceFolder for ESLint adapter 2023-04-27 14:35:34 -04:00
Julia
678c188de0 Re-allow diagnostics hovers to soft wrap
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-27 14:35:34 -04:00
Julia
3f7533a0b4 Show source of diagnostic hovers 2023-04-27 14:35:34 -04:00
Max Brunsfeld
45c7073934 Merge pull request #2418 from zed-industries/vim-inactive-window-crash
Fix vim mode crash when active editor changes in inactive window
2023-04-27 10:48:49 -07:00
Max Brunsfeld
30f20024c0 Fix vim mode crash when active editor changes in inactive window
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-27 10:43:35 -07:00
Antonio Scandurra
6cbc1dcd87 💄 2023-04-27 14:56:16 +02:00
Antonio Scandurra
20e38d2def Remove OpenProjectEntryInPane internal action 2023-04-27 14:51:02 +02:00
Antonio Scandurra
b6437d6d9e Remove Toast and DismissToast internal actions 2023-04-27 14:43:10 +02:00
Antonio Scandurra
2950344c25 Remove internal actions from Dock 2023-04-27 14:29:15 +02:00
Antonio Scandurra
15d83d40b0 Remove internal actions from menu crate 2023-04-27 14:29:11 +02:00
Antonio Scandurra
816eb06a7b Remove internal actions from CopilotCodeVerification 2023-04-27 14:25:34 +02:00
Antonio Scandurra
32f21771a6 Remove internal actions from ContextMenu 2023-04-27 14:25:14 +02:00
Antonio Scandurra
022368225e Remove internal actions from Pane 2023-04-27 14:23:26 +02:00
Antonio Scandurra
5521ff1b22 Allow passing a handler function to context menu items 2023-04-27 11:32:12 +02:00
Antonio Scandurra
d3b976d044 Remove ContextMenu::element_item 2023-04-27 11:11:21 +02:00
Antonio Scandurra
df2f471ddf Remove unused ContextMenu::ViewAction 2023-04-27 10:55:37 +02:00
Antonio Scandurra
06b12bbb68 Remove unnecessarily general keystroke_label_for function 2023-04-27 10:55:14 +02:00
Max Brunsfeld
c6abb0db3a Improve rendering of multi-paragraph list items in hover markdown 2023-04-26 17:09:20 -07:00
Max Brunsfeld
c75207c4e5 Merge pull request #2416 from zed-industries/outline-view-leaving-lines-highlighted
Remove highlighted rows when confirming outline view
2023-04-26 16:11:22 -07:00
Max Brunsfeld
c15dadbb8c Remove highlighted rows when confirming outline view 2023-04-26 15:46:29 -07:00
Max Brunsfeld
d298ce3fd3 Render more markdown features in hover popover 2023-04-26 15:33:10 -07:00
Max Brunsfeld
7960067cf9 Fix bug where Text element would wrap at the right glyph in the wrong run 2023-04-26 15:33:10 -07:00
Max Brunsfeld
54e7464163 collab 0.10.0 2023-04-26 13:24:08 -07:00
Max Brunsfeld
1bbcff543b Add API for adding mouse regions within Text 2023-04-26 12:00:26 -07:00
Joseph Lyons
99e82d829f v0.85.x dev 2023-04-26 14:19:52 -04:00
Nathan Sobo
a45282eb63 Merge pull request #2414 from zed-industries/spawn-weak-for-views
Pass a `WeakViewHandle` to `ViewContext::spawn`
2023-04-26 06:10:44 -06:00
Antonio Scandurra
6317e885c7 Don't allow strong view handles to be read/updated with an AsyncAppContext
This avoids an invitation to hold strong view handles across async await
points, which is a common source of leaks.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-26 13:36:13 +02:00
Antonio Scandurra
689e878bd8 Use a WeakViewHandle in Client for view message handlers 2023-04-26 12:21:02 +02:00
Antonio Scandurra
57beec6071 Allow direct read/update of WeakViewHandle only in AsyncAppContext 2023-04-26 12:20:57 +02:00
Antonio Scandurra
2b6830c798 Remove unnecessary calls to WeakViewHandle::upgrade 2023-04-26 11:13:46 +02:00
Antonio Scandurra
94c2eaad23 Replace ViewContext::spawn with ViewContext::spawn_weak 2023-04-26 10:23:27 +02:00
Antonio Scandurra
09f7e41907 Merge pull request #2405 from zed-industries/fewer-context-traits
Simplify traits for accessing app state uniformly across different kinds of contexts
2023-04-26 10:02:56 +02:00
Antonio Scandurra
7ca412ade3 Merge remote-tracking branch 'origin/main' into fewer-context-traits 2023-04-26 09:54:58 +02:00
Max Brunsfeld
a7145021b6 Extract a named struct from text_layout::Line's style runs 2023-04-25 14:05:23 -07:00
Max Brunsfeld
3cb50ed6b7 Merge pull request #2413 from zed-industries/project-search-focus
Preserve previous focus when re-focusing project search
2023-04-25 09:33:09 -07:00
Max Brunsfeld
3db67a48b5 Preserve previous focus when re-focusing project search 2023-04-25 09:28:50 -07:00
Max Brunsfeld
c31a5063d0 Merge pull request #2411 from zed-industries/rust-snippet-variable-completions
Avoid treating snippet completions' details as their variable types
2023-04-25 08:59:35 -07:00
Max Brunsfeld
db276a422f Merge pull request #2412 from zed-industries/more-workspace-deps
Specify more dependencies at the cargo workspace level, to avoid repeating versions
2023-04-24 18:09:35 -07:00
Max Brunsfeld
ebbe52e6b0 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
Max Brunsfeld
dd3f6ff4ca Avoid treating snippet completions' details as their variable types 2023-04-24 16:20:14 -07:00
Max Brunsfeld
b76194db97 Merge pull request #2409 from zed-industries/stale-excerpts
Fix stale project diagnostic excerpts for guests
2023-04-24 14:22:04 -07:00
Max Brunsfeld
7bd51851c2 🎨
Co-authored-by: Julia Risley <julia@zed.dev>
2023-04-24 13:54:47 -07:00
Max Brunsfeld
a8ddba55d8 Send language server updates via the same task that sends buffer operations
Co-authored-by: Julia Risley <julia@zed.dev>
2023-04-24 13:52:03 -07:00
Max Brunsfeld
ce34bf62fe Add failing test for diagnostic message ordering
Co-authored-by: Julia Risley <julia@zed.dev>
2023-04-24 13:18:37 -07:00
Max Brunsfeld
d2ba1ec275 Merge pull request #2407 from zed-industries/lsp-log-view
Add a simple language server log view
2023-04-24 10:15:29 -07:00
Max Brunsfeld
f3ada72785 Avoid accidentally dropping subscription when detaching it 2023-04-24 10:04:45 -07:00
Max Brunsfeld
1793c5ff6c Upgrade tree-sitter-json 2023-04-24 09:43:31 -07:00
Max Brunsfeld
e7cb996044 Improve the LSP log UI 2023-04-24 09:43:31 -07:00
Max Brunsfeld
6ed7f1281f Persist LSP logs after log view is closed 2023-04-24 09:43:31 -07:00
Max Brunsfeld
6ef6f03322 Update LspLog view to use new gpui APIs 2023-04-24 09:43:31 -07:00
Max Brunsfeld
a280a93cd8 Start work on a language server log view 2023-04-24 09:43:31 -07:00
Max Brunsfeld
2dd4920625 Add LanguageServer::on_io method, for observing JSON sent back and forth 2023-04-24 09:43:31 -07:00
Max Brunsfeld
abdccf7393 Use a workspace dependency for the futures crate 2023-04-24 09:43:31 -07:00
Mikayla Maki
d82cc49f79 Merge pull request #2408 from zed-industries/change-copilot-wording
Change copilot wording to be more explicit
2023-04-25 04:28:23 +12:00
Mikayla Maki
c12e2ac3fb fix formatting 2023-04-24 09:25:04 -07:00
Mikayla Maki
c7874cf169 Update copilot_button.rs 2023-04-24 09:03:54 -07:00
Antonio Scandurra
c165fb9be5 Remove ReadView and UpdateView traits
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-24 17:36:14 +02:00
Antonio Scandurra
a6115d9330 Remove UpdateModel trait
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-24 16:52:09 +02:00
Antonio Scandurra
a9417f3d2e Remove ReadModelWith trait
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-24 16:44:54 +02:00
Antonio Scandurra
5f500d34b2 Remove UpgradeModelHandle trait
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-24 16:40:30 +02:00
Antonio Scandurra
b8fab6fde9 Remove UpgradeViewHandle trait
Co-authored-by: Nathan Sobo <nathan@zed.dev>
2023-04-24 16:33:27 +02:00
Mikayla Maki
455d383d08 Change copilot wording to be more explicit 2023-04-21 21:42:23 -07:00
Mikayla Maki
f10de10915 Merge pull request #2406 from zed-industries/fix-nondeterministic-terminal-test
Fix minor terminal bugs
2023-04-22 12:42:20 +12:00
Mikayla Maki
fa7f4974a0 Remove unused import 2023-04-21 17:26:45 -07:00
Mikayla Maki
733abc9ed2 Revert previous change 2023-04-21 17:24:20 -07:00
Mikayla Maki
616188c541 Fix a bug where the character under a cursor could not reliably be selected 2023-04-21 17:15:29 -07:00
Mikayla Maki
8e0d359c63 Merge branch 'main' into fix-nondeterministic-terminal-test 2023-04-22 11:17:06 +12:00
Mikayla Maki
d841c3729b Wire through the gutter, rather than implicitly adding it 2023-04-21 16:12:33 -07:00
Mikayla Maki
23932b7e6c Fixed non-deterministic test failure and made mouse to cell conversion work correctly 2023-04-21 16:06:07 -07:00
Max Brunsfeld
06cb388beb Merge pull request #2404 from zed-industries/fix-command-palette
Stopgap: Fix missing actions in the command palette
2023-04-21 15:16:45 -07:00
Nathan Sobo
e6604d1641 Fix missing actions in the command palette
Previously, the workspace view was on the stack when we were computing the
available actions, which excluded it. This is a stopgap. We should find a
better solution ASAP.
2023-04-21 15:59:29 -06:00
Nathan Sobo
83bf3d071d WIP 2023-04-21 15:36:52 -06:00
Nathan Sobo
55db28e074 Eliminate ReadModel trait 2023-04-21 15:05:19 -06:00
Nathan Sobo
5dac95c47c Eliminate ReadView trait 2023-04-21 15:03:57 -06:00
Nathan Sobo
bce51c521a Merge pull request #2403 from zed-industries/into-element
Rename Element to AnyElement, Drawable to Element, and make containers generic over any Element type
2023-04-21 14:44:22 -06:00
Nathan Sobo
993dbf86cb Merge remote-tracking branch 'origin/main' into into-element 2023-04-21 14:27:25 -06:00
Nathan Sobo
09111b65d8 Merge pull request #2401 from zed-industries/simplify-context-lifetimes
Remove unnecessary lifetime parameter from WindowContext
2023-04-21 14:26:26 -06:00
Nathan Sobo
caf3d5c163 Fix more formatting 2023-04-21 14:25:49 -06:00
Nathan Sobo
c1810e8ec9 Fix formatting 2023-04-21 13:09:36 -06:00
Nathan Sobo
fe492eacbf Refine naming of element-related types and traits
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-21 13:06:37 -06:00
Antonio Scandurra
03619dfa55 Rename Drawable::boxed to into_element and make containers generic
Multi-element are now generic over any drawable child, which can be converted
into an element.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-21 12:43:19 -06:00
Mikayla Maki
69273648b3 Merge pull request #2402 from zed-industries/fix-panics
Fix panic in pane.rs
2023-04-22 05:53:48 +12:00
Mikayla Maki
b8fd6435d7 Fix test covering this case 2023-04-21 10:48:34 -07:00
Mikayla Maki
aa2af53f56 Align return of close_active_item to match original format 2023-04-21 10:44:27 -07:00
Mikayla Maki
39512655aa Remove unused cyclic dependency from copilot crate
Move notification handling earlier so that there are less copilot messages in the log
2023-04-21 10:38:36 -07:00
Mikayla Maki
6ee0d104d6 Fix panic in remove active item 2023-04-21 10:08:52 -07:00
Petros Amoiridis
c9048b54c1 Merge pull request #2399 from zed-industries/petros/z-827-copy-the-newline-shortcuts-to-zed
Add newline shortcuts for popular editors
2023-04-21 19:09:10 +03:00
Antonio Scandurra
4ac894ffbe Remove unnecessary lifetime parameter from WindowContext
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 18:06:53 +02:00
Antonio Scandurra
a4fbcbf160 Merge pull request #2400 from zed-industries/fix-breadcrumbs-signature
Fix `ProjectDiagnosticsEditor::breadcrumbs` signature
2023-04-21 18:06:22 +02:00
Antonio Scandurra
4d433663bd Fix ProjectDiagnosticsEditor::breadcrumbs signature
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 17:54:26 +02:00
Antonio Scandurra
238ebafa48 Merge pull request #2372 from zed-industries/window_context_2
Give elements access to their parent views and simplify contexts
2023-04-21 17:32:14 +02:00
Julia
88406045f5 Merge pull request #2398 from zed-industries/fix-diagnostics-breadcrumbs
Render breadcrumbs for diagnostics multi-buffer
2023-04-21 11:31:35 -04:00
Petros Amoiridis
3992e95109 Add newline shortcuts for popular editors 2023-04-21 18:29:35 +03:00
Antonio Scandurra
f54a289b6f Remove handle to view from TerminalElement
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 16:56:06 +02:00
Antonio Scandurra
a860a6cd62 Make App::notify_view private
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 16:50:57 +02:00
Antonio Scandurra
8c7f821d14 Introduce a new WindowContext::remove_window API
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 16:39:53 +02:00
Petros Amoiridis
c3231047ad Merge pull request #2396 from zed-industries/petros/z-77-the-start-local-collaboration-script-no
Fix script/start-local-collaboration
2023-04-21 17:36:22 +03:00
Antonio Scandurra
f12746c4b7 Avoid double borrow of view in ProjectPanel drag and drop
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 16:23:47 +02:00
Antonio Scandurra
31e906d068 Avoid double borrow of views on up and up_out in DragAndDrop
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-21 16:19:51 +02:00
Petros Amoiridis
65c5605e68 Look for the main display always 2023-04-21 17:18:01 +03:00
Petros Amoiridis
3c54b14c5b Remove debugging information 2023-04-21 17:17:04 +03:00
Antonio Scandurra
5b40641fde Take a target view when marking an element as draggable 2023-04-21 15:52:05 +02:00
Antonio Scandurra
b0cbd13e7a Remove stray push_layer from EditorElement::paint 2023-04-21 11:46:13 +02:00
Antonio Scandurra
e5192a4853 Use update_default_global to filter command palette items for copilot 2023-04-21 11:07:36 +02:00
Antonio Scandurra
c76b9794e4 Merge branch 'main' into window_context_2 2023-04-21 10:58:08 +02:00
Antonio Scandurra
d32a7218cd Remove stray dbg! statements 2023-04-21 10:49:47 +02:00
Julia
c7cc5bca02 Render breadcrumbs for diagnostics multi-buffer 2023-04-20 23:39:45 -04:00
Mikayla Maki
8e4cc549dc Merge pull request #2397 from zed-industries/finally-fix-terminal-line-height
Create a new setting to adjust the line height in the terminal
2023-04-21 12:39:49 +12:00
Mikayla Maki
1fa52adabd Fix warning 2023-04-20 17:34:47 -07:00
Mikayla Maki
c72b70d4ae Fixed silly custom settings parsing 2023-04-20 17:33:06 -07:00
Mikayla Maki
f54ab73b47 Merge branch 'main' into finally-fix-terminal-line-height 2023-04-21 12:26:32 +12:00
Mikayla Maki
dfdc826015 Create a new setting to adjust the line height in the terminal 2023-04-20 17:24:27 -07:00
Nathan Sobo
1b2e480e1e Remove unnecessary replace 2023-04-20 15:26:48 -06:00
Nathan Sobo
0bce80b6f8 Fix remaining vim failures 2023-04-20 15:25:11 -06:00
Antonio Scandurra
137d9384b5 Initialize the active editor when vim mode is enabled
Instead of waiting for a focus event. This makes more tests pass.
2023-04-20 14:02:40 -06:00
Petros Amoiridis
7b4b1d6312 Use regex to make extraction bulletproof 2023-04-20 20:06:33 +03:00
Max Brunsfeld
abdfb5a451 collab 0.9.0 2023-04-20 09:52:32 -07:00
Max Brunsfeld
3a855184bc v0.84.x dev 2023-04-20 09:52:07 -07:00
Joseph T. Lyons
65f7228fed Merge pull request #2389 from zed-industries/save-panics-as-structured-data
Save panics as structured data
2023-04-20 12:51:00 -04:00
Max Brunsfeld
b414d43ee3 Merge pull request #2392 from zed-industries/eslint-multiple-language-server-adapters-rebased
Allow buffers to use multiple language servers
2023-04-20 09:40:23 -07:00
Petros Amoiridis
dcc804783c Install jq if it's missing 2023-04-20 19:06:23 +03:00
Petros Amoiridis
460ea8e16c Increase reliability and support multiple monitors 2023-04-20 19:06:23 +03:00
Petros Amoiridis
b11e239779 Make the script more reliable 2023-04-20 19:06:22 +03:00
Mikayla Maki
ad71020990 Merge pull request #2395 from zed-industries/remove-stable-hiding-copilot
Remove stable guard for copilot
2023-04-21 04:04:04 +12:00
Max Brunsfeld
21bb13d309 Fix comment formatting errors for rust 1.69 2023-04-20 09:03:42 -07:00
Max Brunsfeld
32c57bcd22 Store buffer's diagnostic sets in a smallvec 2023-04-20 08:58:41 -07:00
Max Brunsfeld
960a2bc589 Don't use ESLint for now 2023-04-20 08:58:41 -07:00
Max Brunsfeld
0ebe44bfd5 Handle multiple language servers for a given path in project diagnostics view 2023-04-20 08:58:41 -07:00
Max Brunsfeld
4dd917c123 Introduce a LanguageServerId wrapper type
Clarify the meaning of all the usizes in use in all of these
struct fields an method signatures.
2023-04-20 08:58:41 -07:00
Julia
c5f86bc6af Avoid language servers fighting over diagnostics summaries
Previously each server would stomp all over the existing results

Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
9e2949e7ba Refactor language server startup
Avoid parallel vecs

Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
c59204c5e6 Cleanup
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
26abc824a9 Bump protocol version 2023-04-20 08:58:41 -07:00
Julia
df94aee758 Fix failing tests
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
6156dbced0 Finish getting multiple diagnostics sources building and running 2023-04-20 08:58:41 -07:00
Julia
bb4de47b15 Start getting diagnostics sets to work with multiple servers
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
2a5c0fa5f8 Get ESLint to launch and provide diagnostics
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-04-20 08:58:41 -07:00
Julia
6e68ff5a50 Get it to build with multiple adapters per language! 🎉
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-20 08:58:41 -07:00
Julia
ba7233f265 Incomplete refactor to allow for multiple adapters per language 2023-04-20 08:58:39 -07:00
Mikayla Maki
c1daf0fc36 Fix format 2023-04-20 08:54:44 -07:00
Mikayla Maki
ad8162fc9c Make sign_in init conditional 2023-04-20 08:36:29 -07:00
Mikayla Maki
f5bbb41cc2 Remove import 2023-04-20 08:34:50 -07:00
Mikayla Maki
5c8b41dd54 Remove stable guard for copilot 2023-04-20 08:33:45 -07:00
Antonio Scandurra
0d5eea8169 Track active window id in test platform
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-20 17:22:11 +02:00
Antonio Scandurra
d9bb37c649 Add WindowContext::update_default_global
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-20 17:13:13 +02:00
Antonio Scandurra
1d487e19f9 Fix editor tests
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-20 16:15:14 +02:00
Antonio Scandurra
c52b6328b7 Merge branch 'main' into window_context_2 2023-04-20 16:01:47 +02:00
Antonio Scandurra
e282c7ad45 Finish converting all the pickers to the new API 2023-04-20 15:26:05 +02:00
Petros Amoiridis
21e39e7523 Merge pull request #2394 from zed-industries/petros/z-804-change-default-settings-for-json-to-2
Set default tab_size for JSON to 2 and apply new formatting
2023-04-20 14:45:52 +03:00
Antonio Scandurra
370875b1d4 Merge pull request #2393 from zed-industries/relay-change-events-to-copilot
Relay buffer change events to Copilot language server
2023-04-20 13:34:42 +02:00
Petros Amoiridis
eca93c124a Apply the tab_size change to keymaps and settings 2023-04-20 14:08:30 +03:00
Petros Amoiridis
bed76462e2 Define tab_size equal to 2 in default settings 2023-04-20 14:06:43 +03:00
Antonio Scandurra
df71a9cfae Move buffer change reporting to a background task 2023-04-20 11:59:05 +02:00
Antonio Scandurra
4151bd39da Add buffer management test to Copilot 2023-04-20 10:51:50 +02:00
Antonio Scandurra
4d207981ae Notify LSP when Copilot suggestions are accepted/rejected 2023-04-20 10:15:31 +02:00
Antonio Scandurra
5d57167302 Make it easier to access a running/authenticated copilot server 2023-04-20 10:12:10 +02:00
Antonio Scandurra
4c3d6c854a Send editor information to copilot 2023-04-20 09:34:20 +02:00
Antonio Scandurra
b9a7b70e52 Register unknown buffer on the fly if completions are requested for it 2023-04-20 09:34:20 +02:00
Antonio Scandurra
34bcf6f072 Reopen file in Copilot language server when language or URI changes 2023-04-20 09:34:20 +02:00
Antonio Scandurra
672cf6b8c7 Relay buffer change events to Copilot 2023-04-20 09:34:20 +02:00
Nathan Sobo
d70644618a WIP: Make PickerDelegate a fully owned object instead of a view
This avoids issues with the parent view being on the stack when we want to
interact with the delegate from the picker. Still have several picker usages
to convert.
2023-04-19 22:05:29 -06:00
Mikayla Maki
ce8442a3d8 Fix underflow potential 2023-04-19 17:42:19 -07:00
Mikayla Maki
dd73233973 Merge pull request #2386 from zed-industries/copilot-shipping
Get copilot ready to ship
2023-04-20 12:38:27 +12:00
Mikayla Maki
26ab774b7f Removed debounce on suggestion cycling code 2023-04-19 17:34:09 -07:00
Mikayla Maki
f16b96cafc add copilot menu 2023-04-19 17:27:44 -07:00
Mikayla Maki
9b8a3e4de5 Fixed panic in new cycling code
Made cycling fire without debounce
2023-04-19 16:50:31 -07:00
Mikayla Maki
2882e0fa5b Remove new CTA in copilot sign in UI
Add a trim_end to copilot suggestions
2023-04-19 16:39:55 -07:00
Mikayla Maki
745e5e3a09 Add italic styles to copilot suggestions 2023-04-19 15:23:19 -07:00
Mikayla Maki
70ff4ca48f WIP: lower our usage of the copilot API by seperating out the cycling completion
Restore copilot setting visibility

co-authored-by: antonio <antonio@zed.dev>
2023-04-19 15:23:17 -07:00
Mikayla Maki
ea1c3fa7a0 Only fire completion cycling requests if specifically asked for by the user 2023-04-19 15:21:30 -07:00
Antonio Scandurra
8610f3acf3 Introduce a button to disable copilot integration
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-19 20:25:59 +02:00
Joseph Lyons
0326a45a91 Give closure parameter a name 2023-04-19 14:21:53 -04:00
Antonio Scandurra
54a78d7024 Clarify Copilot context menu
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-19 20:18:06 +02:00
Antonio Scandurra
4a9989fe38 Clear all suggestions from Editor when disabling Copilot
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-19 20:10:57 +02:00
Antonio Scandurra
1fd07b6fcf Clarify copilot settings
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-19 20:07:05 +02:00
Petros Amoiridis
699b2060b3 Merge pull request #2390 from zed-industries/petros/z-66-command-to-add-a-new-line-on-the
Add newline above and improve newline below
2023-04-19 21:02:55 +03:00
Petros Amoiridis
b3b8f8532d Assert the editor and unmarked texts are the same
Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
2023-04-19 20:52:01 +03:00
Petros Amoiridis
f9c60b98c0 Add newline above and improve newline below
Add a new action for inserting a new line above the current line. @ForLoveOfCats  also helped fix a bug among other things. When two collaborators had their cursors at the end of a line, and one collaborator performed a newline below action, the second collaborator's cursor would be dragged to the new line. This is also fixing that.

Co-Authored-By: Julia <30666851+ForLoveOfCats@users.noreply.github.com>
2023-04-19 19:57:23 +03:00
Joseph Lyons
27a6bacab8 Save panics as structured data 2023-04-19 08:31:47 -04:00
Nathan Sobo
5514349b6b Add Component elements 2023-04-18 22:49:06 -06:00
Max Brunsfeld
c5e56a5e45 Fail the randomized test build after reporting the error to zed.dev 2023-04-18 18:41:33 -07:00
Max Brunsfeld
5934e882b8 Merge pull request #2379 from zed-industries/shebang
Select language based on a file's first content line in addition to its path
2023-04-18 17:31:19 -07:00
Max Brunsfeld
ad9fe79cf2 Merge pull request #2388 from zed-industries/cmd-o-new-window
When opening projects, only reuse the current window if it is empty
2023-04-18 17:31:08 -07:00
Max Brunsfeld
7cc868bc8c When opening projects, only reuse the current window if it is empty 2023-04-18 17:05:26 -07:00
Max Brunsfeld
44d26b69ae Merge pull request #2387 from zed-industries/panic-in-set-selections-from-remote
Fix 'invalid insertion' panic when following
2023-04-18 16:43:47 -07:00
Max Brunsfeld
bd7d50f339 Fix 'invalid insertion' panic when following
Wait for the necessary buffer operations to arrive before attempting to
set selections and scroll top.
2023-04-18 16:13:18 -07:00
Nate Butler
a8b3826955 Merge pull request #2384 from zed-industries/update-copilot-styles
Update copilot styles
2023-04-18 15:17:10 -04:00
Julia
4c086a4836 Merge pull request #2385 from zed-industries/rerender-breadcrumbs-on-focus-change
Re-render toolbar items when updating their knowledge of pane focus
2023-04-18 15:13:53 -04:00
Julia
721baf5746 Re-render toolbar items when updating their knowledge of pane focus 2023-04-18 14:56:39 -04:00
Nate Butler
957ab65422 Mix neutral and blue to make a predictive color that is unique 2023-04-18 14:47:52 -04:00
Joseph T. Lyons
614a9c8977 Merge pull request #2377 from zed-industries/add-tab-tooltips
Add tab tooltips
2023-04-18 14:37:38 -04:00
Nate Butler
ae0647c3a9 Update predictive color
Co-Authored-By: Mikayla Maki <mikayla.c.maki@gmail.com>
2023-04-18 14:29:08 -04:00
Joseph Lyons
304eddbbe4 Remove unnecessary lifetimes from tab_description 2023-04-18 14:15:56 -04:00
Joseph Lyons
9afd804062 Remove unnecessary lifetimes from tab_tooltip_text 2023-04-18 14:03:02 -04:00
Antonio Scandurra
eee39b4c5c Don't capture Workspace handle in defer when rendering Dock
GPUI already provides a mutable reference to the `Workspace` in the
`defer` callback.
2023-04-18 17:41:40 +02:00
Antonio Scandurra
136e599051 Merge branch 'main' into window_context_2 2023-04-18 17:29:37 +02:00
Antonio Scandurra
bcba11ba82 Reflect new behavior in test now that we don't replace windows anymore 2023-04-18 17:27:05 +02:00
Antonio Scandurra
d03c431f9a Fix warnings/errors now that AsyncAppContext::update returns Result 2023-04-18 14:58:57 +02:00
Antonio Scandurra
31e6bb4fc1 Return Result from AsyncAppContext::update_view 2023-04-18 12:03:53 +02:00
Antonio Scandurra
1b477c9e38 Merge pull request #2383 from zed-industries/show-copilot-more-often
Clean up completion tasks, even if they fail or return no results
2023-04-18 11:16:47 +02:00
Antonio Scandurra
d26d0ac56f Clean up completion tasks, even if they fail or return no results
This fixes a bug where leaving the completion task in `completion_tasks`
could cause the Copilot suggestion to not be shown due to the LSP not
successfully return a completion.
2023-04-18 11:03:17 +02:00
Antonio Scandurra
75d6b6360f Add failing test to demonstrate Copilot not showing enough suggestions 2023-04-18 10:24:20 +02:00
Max Brunsfeld
8f25b98e6f Print the final minimized test plan before sending it to zed.dev 2023-04-17 16:35:54 -07:00
Max Brunsfeld
695973d117 Use Node 18 on CI, for fetch API 2023-04-17 16:22:30 -07:00
Max Brunsfeld
516964280b Merge pull request #2376 from zed-industries/randomized-tests-runner
Add an Actions workflow that repeatedly runs the randomized integration tests
2023-04-17 15:45:45 -07:00
Max Brunsfeld
485c56e3bd Don't run randomized tests on pushes to main 2023-04-17 15:43:12 -07:00
Max Brunsfeld
837866f962 Consolidate logic for running randomized tests in scripts 2023-04-17 15:37:11 -07:00
Julia
4adc92b8e5 Merge pull request #2382 from zed-industries/dont-have-contacts-popover-affect-share-unshare-button
Don't have contacts popover affect appearance of Share/Unshare button
2023-04-17 14:18:39 -04:00
Julia
14ef0edd7f Don't have contacts popover affect appearance of Share/Unshare button 2023-04-17 14:13:28 -04:00
Max Brunsfeld
233cd80f63 Merge pull request #2381 from zed-industries/fix-buffer-latency
Send buffer operations in batches to reduce latency
2023-04-17 10:59:51 -07:00
Max Brunsfeld
5d73e646d8 Delete pull_request_template.md 2023-04-17 10:23:57 -07:00
Antonio Scandurra
1f284408a9 Send buffer operations in batches to reduce latency
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-04-17 10:22:13 -07:00
Julia
f5a2534c1b Merge pull request #2380 from zed-industries/show-followers-full-color
Unconditionally display followers in full color
2023-04-17 13:16:19 -04:00
Julia
61f4f8aaeb Unconditionally display followers in full color 2023-04-17 13:10:40 -04:00
Antonio Scandurra
493a418c91 WIP 2023-04-17 18:52:48 +02:00
Antonio Scandurra
38ab6b123f Make production code compile again 2023-04-17 12:33:33 +02:00
Antonio Scandurra
bed94455b9 Avoid calling focus_in when creating window
This is redundant because when creating a window we will receive
an activation event if the window was effectively focused. And if
it wasn't, we shouldn't call `focus_in`.
2023-04-17 11:57:51 +02:00
Max Brunsfeld
1dcd4717b1 Select language based on a file's first content line in addition to its path 2023-04-16 12:28:27 -07:00
Joseph Lyons
ebe57254e0 Add tab tooltips 2023-04-15 06:46:14 -04:00
Max Brunsfeld
3569c61784 Minimize randomized test failures before reporting issues 2023-04-14 17:51:24 -07:00
Max Brunsfeld
5c3da91e15 Report randomized test failures to zed.dev, to create issues in linear 2023-04-14 15:45:01 -07:00
Max Brunsfeld
c329546570 Extract randomized test CI process into a script 2023-04-14 14:25:55 -07:00
Max Brunsfeld
253411bfd0 Start work randomized test runner GH action workflow 2023-04-14 13:54:57 -07:00
Max Brunsfeld
e655a6c767 Merge pull request #2375 from zed-industries/worktree-scan-id-fix
Always bump worktree's scan_id when refreshing an entry
2023-04-14 09:53:40 -07:00
Antonio Scandurra
f09e21aa93 WIP: force using (at least) a window context to update views 2023-04-14 17:08:13 +02:00
Antonio Scandurra
a820862165 Take WindowContext in workspace::ItemHandle methods 2023-04-14 16:36:23 +02:00
Antonio Scandurra
a8e75a9b55 Remove weak handle from EditorElement to Editor 2023-04-14 14:29:03 +02:00
Antonio Scandurra
060242a28a Take a WindowContext in StatusItemViewHandle::set_active_pane_item 2023-04-14 14:26:20 +02:00
Antonio Scandurra
2652f65bee Fix handle_window_activation_effect updating the wrong view 2023-04-14 12:33:13 +02:00
Antonio Scandurra
98dce89379 Pass WindowContext to ViewHandle::is_focused 2023-04-14 12:12:08 +02:00
Antonio Scandurra
74ca223114 Fix formatting for the entire workspace 2023-04-14 12:08:33 +02:00
Antonio Scandurra
33bc47dbe2 Merge branch 'main' into window_context_2 2023-04-14 12:07:09 +02:00
Antonio Scandurra
183b9ef809 Make full-screen and window bounds callbacks take a WindowContext 2023-04-14 11:56:31 +02:00
Antonio Scandurra
7394bf1cdc Fix most of the warnings 2023-04-14 10:51:53 +02:00
Antonio Scandurra
5666e8301e Log an error when a scene fails to build 2023-04-14 10:32:56 +02:00
Antonio Scandurra
9ef79735dc Move more window-specific methods from AppContext to WindowContext 2023-04-14 10:29:35 +02:00
Antonio Scandurra
c62357db02 Fix window activation 2023-04-14 08:24:01 +02:00
Max Brunsfeld
5ea49b3ae3 Fix inconsistent worktree state when renaming entries while scanning 2023-04-13 22:34:34 -07:00
Max Brunsfeld
bb1cfd51b8 Add randomized test for mutating worktree during initial scan 2023-04-13 22:34:03 -07:00
Max Brunsfeld
debb694d97 Always bump scan_id when refreshing an entry
The scan_id needs to be bumped even if a scan is already in progress,
so that worktree updates can detect that entries have changed. This
means that the worktree's completed_scan_id may increase by more than
one at the end of a scan.
2023-04-13 16:51:11 -07:00
Max Brunsfeld
c13914bda1 Merge pull request #2371 from zed-industries/refresh-entry-delay
Restructure background scanner to handle refresh requests even while scanning directories
2023-04-13 12:44:04 -07:00
Joseph T. Lyons
6a75e884c0 Merge pull request #2374 from zed-industries/add-vim-mode-metric
Add vim mode metric
2023-04-13 13:52:31 -04:00
Joseph Lyons
5f0bf5929f Add vim mode metric 2023-04-13 13:46:22 -04:00
Antonio Scandurra
84d2605ccf Avoid passing cx when emitting from CallbackCollection
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-13 16:53:44 +02:00
Antonio Scandurra
ff774786bf Reimplement AppContext::handle_focus_effect 2023-04-13 16:21:39 +02:00
Antonio Scandurra
4900e04ff3 Fix window refreshing 2023-04-13 12:19:11 +02:00
Antonio Scandurra
0269a8699b Start removing some warnings 2023-04-13 12:04:37 +02:00
Antonio Scandurra
702c4ce403 Uncomment List tests and fix related problems in WindowContext 2023-04-13 12:01:18 +02:00
Antonio Scandurra
f4daeb4778 Merge pull request #2373 from zed-industries/fix-copilot-panic
Avoid interpolating Copilot suggestion if cursor excerpt differs
2023-04-13 10:48:57 +02:00
Antonio Scandurra
495c7acadf Avoid interpolating Copilot suggestion if cursor excerpt differs 2023-04-13 10:44:08 +02:00
Max Brunsfeld
5ca603dbeb Don't process gitignore updates after the initial scan 2023-04-12 18:17:29 -07:00
Max Brunsfeld
3d14bfd90c Prioritize path refresh requests over gitignore status updates 2023-04-12 18:08:00 -07:00
Max Brunsfeld
2d97387f49 Restructure background scanner to handle refresh requests even while scanning 2023-04-12 16:29:51 -07:00
Nathan Sobo
b89c4e06be WIP: Compiling, many warnings, haven't tested 2023-04-12 12:54:24 -06:00
Nathan Sobo
25ad635577 WIP 2023-04-12 12:38:26 -06:00
Nathan Sobo
4cb13fb39c WIP 2023-04-12 12:22:26 -06:00
Nathan Sobo
a25f962185 WIP 2023-04-12 12:13:35 -06:00
Max Brunsfeld
a85c2d71ad collab 0.8.3 2023-04-12 11:11:32 -07:00
Joseph Lyons
afbd275f4f v0.83.x dev 2023-04-12 13:31:39 -04:00
Joseph T. Lyons
ee238a300e Merge pull request #2368 from zed-industries/Improve-tab-closing-experience
Add tab context menu
2023-04-12 13:08:46 -04:00
Joseph T. Lyons
b39b3541e9 Merge pull request #2370 from zed-industries/flip-screen-sharing-icon-states
Flip screen sharing icon states
2023-04-12 12:50:00 -04:00
Nathan Sobo
40896352ff wip 2023-04-12 10:28:53 -06:00
Nathan Sobo
868301bedb WIP 2023-04-12 10:07:17 -06:00
Antonio Scandurra
83070a19c4 WIP 2023-04-12 15:55:43 +02:00
Nathan Sobo
b54f08db77 WIP 2023-04-12 06:51:03 -06:00
Antonio Scandurra
6d8635fa29 Merge pull request #2349 from zed-industries/randomized-tests-operation-script
Restructure randomized integration test to allow editing and replaying a plan, fix discovered bugs
2023-04-12 11:45:47 +02:00
Antonio Scandurra
12a286ac50 Forget buffered operations when resyncing with the host
Previously, we could end up with a situation where the host did not
see an operation but a guest that didn't have that buffer open would. When
such guest would finally open the buffer, they would apply the operation
without however sending it to the host. The guest wouldn't bother resyncing
it because it wasn't part of its open buffers.
2023-04-12 10:39:01 +02:00
Nathan Sobo
d9e4136b02 WIP 2023-04-11 21:56:37 -06:00
Nathan Sobo
e6cc132b19 WIP 2023-04-11 18:48:00 -06:00
Nathan Sobo
e115baa60c WIP 2023-04-11 18:21:56 -06:00
Joseph Lyons
0b52308c99 Represent dirty state in item-testing code 2023-04-11 16:27:12 -04:00
Joseph Lyons
c39764487c Construct context menu in a more clear way 2023-04-11 15:46:52 -04:00
Max Brunsfeld
61d048cb25 Don't wait for host's reply before broadcasting buffer updates to guests 2023-04-11 12:37:08 -07:00
Joseph Lyons
ae930bde87 Flip screen sharing icon states 2023-04-11 15:30:44 -04:00
Max Brunsfeld
727afae4ff Fix unit tests after fixing gpui model drop semantics
co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-11 10:58:01 -07:00
Nate Butler
209e9a59c5 Merge pull request #2369 from zed-industries/nate/update-ayu-theme
Update `Ayu` Theme Family
2023-04-11 13:05:25 -04:00
Nate Butler
7ba094e10e add license_checksum 2023-04-11 12:56:18 -04:00
Nate Butler
20ec9f6daf Add meta fields to ayu 2023-04-11 12:37:20 -04:00
Nate Butler
65c2fb1cc6 Fix paths after publishing 2023-04-11 12:25:02 -04:00
Nate Butler
de60657d53 Ignore the target folder 2023-04-11 12:23:54 -04:00
Nate Butler
975f5d5fa8 Format 2023-04-11 12:23:21 -04:00
Nate Butler
527f0310e2 Update + publish the Ayu theme 2023-04-11 12:22:49 -04:00
Antonio Scandurra
42b10044fc Fix running client crate tests 2023-04-11 17:43:05 +02:00
Antonio Scandurra
5eb1719ab8 Re-send worktree if reconnecting while initial scan isn't finished yet
Previously, if the client was disconnected while the initial worktree
state was being sent, it would not see the remaining state after reconnecting.
This was due to `scan_id` and `completed_scan_id` both being initialized to
`0`, so the client would ask for updates since `0` and get nothing.

This commit changes the worktree to initialize `scan_id` to `1` and
`completed_scan_id` to `0`, so that we get the full worktree again on reconnect.
2023-04-11 17:15:43 +02:00
Antonio Scandurra
172441ab72 Cancel pending calls when participant fails to reconnect
Previously, we would only cancel pending calls when the room became
empty.
2023-04-11 16:33:08 +02:00
Antonio Scandurra
5e37c893c2 Ensure project is still alive by the time remote LSP request starts 2023-04-11 15:14:32 +02:00
Antonio Scandurra
5898600239 Use LspCommand to handle code actions 2023-04-11 15:12:58 +02:00
Antonio Scandurra
651a83977e 🔥 2023-04-11 14:53:08 +02:00
Antonio Scandurra
ac532cb6fa Use LspCommand to handle completions 2023-04-11 14:52:07 +02:00
Antonio Scandurra
9e6d865882 Prevent already dropped model from being upgraded during release 2023-04-11 10:43:05 +02:00
Antonio Scandurra
6ba5e06247 Stop waiting for buffers when releasing a remote project 2023-04-11 10:42:43 +02:00
Antonio Scandurra
643381ce0c Make UpdateDiffBase a Foreground message to prevent reordering 2023-04-11 08:50:26 +02:00
Joseph Lyons
67cb046298 Add tab context menu 2023-04-11 00:03:47 -04:00
Max Brunsfeld
abfbba68f0 Improve randomized test assertion message when diff base is wrong 2023-04-10 18:28:34 -07:00
Max Brunsfeld
25e3c4e586 Fix leak when project is unshared while LSP handler waits for edits 2023-04-10 17:03:58 -07:00
Nathan Sobo
3de8fe0f87 WIP 2023-04-10 17:27:47 -06:00
Max Brunsfeld
e853e77d59 Upgrade postage for oneshot channel drop fix
Previously, dropping a oneshot sender didn't wake the receiver.
2023-04-10 16:03:49 -07:00
Nathan Sobo
6638407ff9 WIP: Everything shredded 2023-04-10 16:10:32 -06:00
Julia
0e4de87e0e Merge pull request #2367 from zed-industries/log-github-api-response-for-deserialize-error
In the case of Github release deserialize error, log response text
2023-04-10 17:04:59 -04:00
Julia
189784f5fd In the case of Github release deserialize error, log response text
Co-Authored-By: Joseph Lyons <joseph@zed.dev>
2023-04-10 16:45:15 -04:00
Max Brunsfeld
e79815622c Preserve ordering between UpdateProject and CreateBufferForPeer messages
Previously, because UpdateProject messages were sent in a separately-
spawned task, they could be sent after CreateBufferForPeer messages that
were intended to be sent after them.

Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-10 12:54:25 -07:00
Antonio Scandurra
9761febf82 Avoid broadcasting SaveBuffer in response to a client's save request
The host will send a `SaveBuffer` message anyway and this prevents re-querying
the database, which could cause two `BufferSaved` messages to race and, as a
result, cause guest to apply them in the wrong order.
2023-04-10 10:02:13 +02:00
Antonio Scandurra
3a82c04248 Improve assertion message when buffer state diverges 2023-04-10 10:01:44 +02:00
Antonio Scandurra
016343e65d Merge branch 'main' into randomized-tests-operation-script 2023-04-10 08:45:22 +02:00
Antonio Scandurra
7f73ebdab5 Apply BufferReloaded message to incomplete remote buffers 2023-04-10 08:41:31 +02:00
Antonio Scandurra
116d4f20fa Merge pull request #2366 from zed-industries/avoid-unwrapping-on-try-send
Don't panic if worktree was dropped before sending path changes
2023-04-10 08:36:53 +02:00
Antonio Scandurra
372e31d54f Don't panic if worktree was dropped before sending path changes
In `refresh_entry`, we send a message to the `self.path_changes_tx` channel
to notify the background thread that a path has changed. However, given that
`refresh_entry` uses `spawn_weak`, the worktree could get dropped before sending
the message, which could cause a panic.

This commit changes the code to return an error instead of panicking.
2023-04-10 08:16:08 +02:00
Nathan Sobo
7536645eea WIP 2023-04-08 08:01:05 -06:00
Nathan Sobo
9d23a98157 WIP 2023-04-08 06:43:39 -06:00
Max Brunsfeld
acbf9b55d7 Halt UpdateBuffer messages until sync if one errors
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-07 17:31:52 -07:00
Max Brunsfeld
e50c48852a Wait for host to acknowledge buffer updates before sending them to other guests 2023-04-07 16:27:48 -07:00
Max Brunsfeld
f519f32ec2 Fixed removal of closed projects in randomized test
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-07 12:24:59 -07:00
Joseph Lyons
035189a2a1 Put file location details of panic on separate line 2023-04-07 14:32:14 -04:00
Nathan Sobo
676dbdc57b Merge pull request #2365 from zed-industries/dont_export_gpui_platform_module
Don't export platform::* from gpui
2023-04-07 12:12:05 -06:00
Nathan Sobo
2186de38ab Merge AppContext impl blocks 2023-04-07 11:54:08 -06:00
Nathan Sobo
2615a11f7c Don't export platform::* from gpui
I'd like to avoid cluttering the top-level namespace with all the platform-
specific types.
2023-04-07 11:45:53 -06:00
Joseph T. Lyons
f450692e77 Merge pull request #2364 from zed-industries/put-backtrace-on-a-newline-when-reporting-panics
Put backtrace on a new line when reporting panics
2023-04-07 12:46:53 -04:00
Joseph Lyons
9cf3481fc7 Put backtrace on a new line when reporting panics 2023-04-07 12:12:18 -04:00
Joseph T. Lyons
c58601ab8d Merge pull request #2363 from zed-industries/add-copy-path-commands
Update copy path commands
2023-04-07 12:09:39 -04:00
Joseph Lyons
5e55eb279c Update copy path commands 2023-04-07 02:36:56 -04:00
Nathan Sobo
dad403f483 Merge pull request #2362 from zed-industries/eliminate-mutable-app-context
Merge MutableAppContext into AppContext
2023-04-06 16:19:47 -06:00
Nathan Sobo
95eb918b4c Fix broken test due to trimmed trailing whitespace during formatting 2023-04-06 16:10:39 -06:00
Nathan Sobo
8136d8a8a6 Fix formatting 2023-04-06 15:54:44 -06:00
Nathan Sobo
de9bf6dfbd Merge MutableAppContext into AppContext
There may have been a good reason for the difference at some point, or I was
still learning Rust. But now it's just &mut AppContext vs &AppContext.
2023-04-06 15:49:03 -06:00
Max Brunsfeld
aa7918c4b5 Fix handling of redundant buffer creation messages on guests
Check if the buffer already exists *before* overwriting it.
Ignore redundant registrations on remote projects.

Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-06 12:17:25 -07:00
Max Brunsfeld
22a6a243bc Move project assertions into main assertion function
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-04-06 11:38:42 -07:00
Joseph T. Lyons
dd00966cc6 Merge pull request #2361 from zed-industries/add-close-items-to-left-and-right
Add close items to left and right
2023-04-06 13:06:25 -04:00
Antonio Scandurra
ef04dc14cc Update file on incomplete buffer instead of waiting for it to be opened
This ensures that two successive file updates coming from the host are
not applied in reverse order.
2023-04-06 17:48:44 +02:00
Julia
4b39df4a6b Merge pull request #2304 from zed-industries/bump-diff-width
Increase git diff gutter width slightly
2023-04-06 10:58:55 -04:00
Antonio Scandurra
8020ea783f Wait to see guest's buffer version before converting completion anchor 2023-04-06 16:23:10 +02:00
Antonio Scandurra
4a61e2dfa4 Save server operations that were in the middle of being applied
Previously, if the test panicked before it had a chance to fully
apply an operation, it would end up not being saved in the plan.
With this commit we will mark the operation as applied before we
start processing it, and mark it as not applied if, once we're done,
we've found out that it couldn't be applied. This is consistent with
what we do for client operations.
2023-04-06 16:02:16 +02:00
Antonio Scandurra
f995d07542 Return error if subscribing to an entity that was already subscribed to 2023-04-06 14:42:19 +02:00
Antonio Scandurra
d7f56d6126 Forget which buffers were shared when host reconnects
This fixes a bug where the host would momentarily disconnect and the guest
would close and reopen the project. This would cause the host to not observe
the guest closing the project. When the guest tried to open one of the
buffers opened prior to closing the project, the host would not send them the
buffer state because it would still remember that the buffer was shared.

The `shared_buffers` map is now cleared when the host reconnects and will slowly
get re-filled as guests issue `SynchronizeBuffers` requests.
2023-04-06 13:49:09 +02:00
Joseph Lyons
4883ec2201 Add close items to left and right 2023-04-06 03:33:38 -04:00
Max Brunsfeld
bf3b8adf35 Avoid async fs call before checking if operation is applicable
This way, the executor isn't influenced by operations that aren't applicable.
2023-04-05 18:11:33 -07:00
Max Brunsfeld
1064b14779 Don't use TestPlan's rng in fake LSP handlers
These should use the test context's rng, so that they behave the same whether
a pre-recorded plan was used, or the plan is being generated.
2023-04-05 17:50:04 -07:00
Max Brunsfeld
2d63ed3ca4 Merge branch 'main' into randomized-tests-operation-script 2023-04-05 17:10:20 -07:00
Nathan Sobo
e5861d6c35 Fix typos in EULA 2023-04-05 18:02:35 -06:00
Max Brunsfeld
bda7086220 Clear guest's shared buffers if they rejoin project after leaving while host was disconnected 2023-04-05 16:53:36 -07:00
Max Brunsfeld
8e68c7f808 Do include operations in serialized test plan if they cause a client to hang 2023-04-05 16:52:39 -07:00
Max Brunsfeld
43a94cda5f Don't skip worktree updates if unknown entries are removed
When rejoining a project, if entries were both created and deleted since
joining the project, the guest will receive those entries ids in as
removed.
2023-04-05 15:36:01 -07:00
Max Brunsfeld
661fba8640 Run executor until parked at end of each iteration of random collaboration test
Without this, the server doesn't get dropped at the end of the test, and we eventually run
out of file handles due to sqlite connections being retained.
2023-04-05 15:05:32 -07:00
Max Brunsfeld
781d66f628 Omit operations for non-existent users from serialized test plan 2023-04-05 15:04:27 -07:00
Julia
43b6e7a944 Merge pull request #2360 from zed-industries/maybe-fix-lock-screen-crash
Hesitant possible fix for lock screen crash
2023-04-05 14:10:40 -04:00
Julia
6e3bf7fed4 Hesitant possible fix for lock screen crash
This may cause issues in this situations but as I cannot repro this I'm
making the call to try something and see how it plays out
2023-04-05 14:01:54 -04:00
Joseph Lyons
e4bb5c296c v0.82.x dev 2023-04-05 13:00:52 -04:00
Joseph T. Lyons
3b6c975658 Merge pull request #2357 from zed-industries/update-eula
Update EULA
2023-04-05 12:57:34 -04:00
Joseph Lyons
5becdbdea8 Fix spacing in EULA 2023-04-05 12:45:48 -04:00
Julia
af826f5efd Merge pull request #2359 from zed-industries/prefer-right-statusbar-items
Prioritize displaying right statusbar items overtop left items if needed
2023-04-05 12:16:30 -04:00
Julia
77bb52f72c Prioritize displaying right statusbar items overtop left items if needed 2023-04-05 12:08:52 -04:00
Mikayla Maki
64428bac15 Merge pull request #2358 from zed-industries/more-copilot-fixes
Invalidate copilot suggestion on backspaces
2023-04-05 08:59:30 -07:00
Mikayla Maki
78742d5615 Add additional case to range invalidation test
co-authored-by: antonio <antonio@zed.dev>
2023-04-05 08:52:56 -07:00
Mikayla Maki
b585470518 Invalidate copilot suggestion on backspaces
Restore an observation on initialization

co-authored-by: antonio <antonio@zed.dev>
2023-04-05 08:48:39 -07:00
Antonio Scandurra
e2c690cece Merge pull request #2356 from zed-industries/copilot-on-preview
Disable Copilot entirely for stable releases
2023-04-05 16:20:53 +02:00
Nathan Sobo
0d0f6b5a05 Update EULA 2023-04-05 08:18:51 -06:00
Antonio Scandurra
7ba46a0630 Honor ZED_RELEASE_CHANNEL environment variable only in development
We don't want people to be able to override the release channel in
production.
2023-04-05 15:55:44 +02:00
Antonio Scandurra
15b26e10d4 Disable Copilot entirely for stable releases
This lets us remove the logic for detecting whether a user is a staff
member.
2023-04-05 15:49:59 +02:00
Antonio Scandurra
781d065d0b Merge pull request #2355 from zed-industries/refine-copilot
Iterate some more on Copilot
2023-04-05 14:21:18 +02:00
Antonio Scandurra
03a4c9d6d5 Use the cursor variable instead of selection.start 2023-04-05 14:15:58 +02:00
Antonio Scandurra
dd416cdfd2 📝 2023-04-05 14:14:43 +02:00
Antonio Scandurra
f920e02d96 Indent instead of accepting suggestion if cursor is in leading whitespace 2023-04-05 14:09:09 +02:00
Antonio Scandurra
908a7cf47e 💄 2023-04-05 13:59:19 +02:00
Antonio Scandurra
dcd8bdfc88 Update visible suggestion if edit occurs outside the current editor 2023-04-05 11:06:14 +02:00
Antonio Scandurra
6e821eea4b Prevent tab from accepting a copilot suggestion when it isn't visible 2023-04-05 10:31:11 +02:00
Antonio Scandurra
661be7ba51 Refresh copilot suggestions when accepting a completion 2023-04-05 10:28:00 +02:00
Antonio Scandurra
7a7dc95611 Refresh copilot suggestions when undoing/redoing 2023-04-05 10:27:19 +02:00
Antonio Scandurra
399451b676 Capture copilot behavior in a editor unit test 2023-04-05 10:26:43 +02:00
Max Brunsfeld
1159f5517b Avoid applying outdated UpdateProject methods after rejoining a room 2023-04-04 21:49:37 -07:00
Max Brunsfeld
1ccf174388 Avoid applying outdated UpdateProject messages
Co-authored-by: Nathan Sobo <nathan@zed.dev>
2023-04-04 18:34:39 -07:00
Antonio Scandurra
808ddc26e7 Merge pull request #2353 from zed-industries/more-intuitive-autocomplete-with-copilot
Match VS Code's behavior when deciding whether to show Copilot suggestion
2023-04-04 20:03:07 +02:00
Antonio Scandurra
65fd605b82 Revert "Return the previous suggestion when replacing it"
This reverts commit 971c88db80.
2023-04-04 18:59:28 +02:00
Nate Butler
e7150d0b66 Merge pull request #2354 from zed-industries/nate/fix-embedded-highlight-in-ruby
Fix embedded highlight in ruby
2023-04-04 12:46:32 -04:00
Nate Butler
7ff97e50a7 Fix embedded highlight in ruby 2023-04-04 12:41:38 -04:00
Antonio Scandurra
b58ac815a8 Trigger copilot only on insertion and deletion
Also, avoid showing the suggestion if a completion is in progress to
avoid flickering.
2023-04-04 17:51:37 +02:00
Antonio Scandurra
971c88db80 Return the previous suggestion when replacing it 2023-04-04 17:14:52 +02:00
Antonio Scandurra
a2aad31cf1 Merge pull request #2352 from zed-industries/debounce-copilot
Debounce copilot completions
2023-04-04 16:52:59 +02:00
Antonio Scandurra
e970d84184 Debounce copilot completions
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-04-04 16:02:25 +02:00
Antonio Scandurra
5df5973262 Merge pull request #2351 from zed-industries/more-copilot-enhancements
Fix additional Copilot issues
2023-04-04 14:22:12 +02:00
Antonio Scandurra
60955fb8ee Refresh active copilot suggestion when accepting completion 2023-04-04 11:15:14 +02:00
Antonio Scandurra
79d5bb45dc Clear Copilot suggestions when it gets disabled from the settings 2023-04-04 10:45:56 +02:00
Antonio Scandurra
abf158a9e4 Merge pull request #2347 from zed-industries/disable-yaml-key-ordering
Disable key ordering diagnostic for YAML
2023-04-04 10:00:48 +02:00
Max Brunsfeld
bcf9b2f10d Add missing random delays in FakeFs 2023-04-03 22:42:34 -07:00
Mikayla Maki
91d85987b9 Merge pull request #2350 from zed-industries/copilot-disable
Disable copilot unless the staff mode flag is flipped
2023-04-03 22:00:47 -07:00
Mikayla Maki
fa32a20c42 fixup! fixup! fixup! removed copilot from generated schema and command palette 2023-04-03 21:46:59 -07:00
Mikayla Maki
a1abe8d33c fixup! fixup! removed copilot from generated schema and command palette 2023-04-03 21:46:30 -07:00
Mikayla Maki
ae6a671fea fixup! removed copilot from generated schema and command palette 2023-04-03 21:45:18 -07:00
Mikayla Maki
47de4dcd32 removed copilot from generated schema and command palette 2023-04-03 21:38:26 -07:00
Mikayla Maki
6bfecd7f66 Refactor staff mode into a seperate crate and make copilot initialization wait for the staff mode flag to be flipped 2023-04-03 20:16:45 -07:00
Max Brunsfeld
b251e249a7 Check for consistency between clients every time the system quiesces 2023-04-03 19:11:37 -07:00
Max Brunsfeld
7b0a6c0dfa Add an 'on_failure' attribute to gpui tests
This lets us perform a finalization step when a randomized test fails.
2023-04-03 18:16:08 -07:00
Max Brunsfeld
5ecc9606af Use synchronous locks in FakeFs
This way, the state can be accessed without running the deterministic
executor.
2023-04-03 18:15:07 -07:00
Mikayla Maki
55297c1a26 Merge pull request #2348 from zed-industries/copilot-feedback
Fix issues from copilot feedback
2023-04-03 16:29:41 -07:00
Max Brunsfeld
f95732e981 Fix bug where guest would drop BufferSaved messages while opening the buffer 2023-04-03 16:23:44 -07:00
Mikayla Maki
1627cf7eae Add standard copilot keybinding 2023-04-03 16:14:07 -07:00
Mikayla Maki
bab0e88b6f Fix bug where copilot auth window will only be shown once 2023-04-03 16:01:04 -07:00
Max Brunsfeld
543301f949 Avoid repeatedly loading/saving the test plan for each iteration 2023-04-03 15:58:11 -07:00
Mikayla Maki
2e33f8b228 fixup! Remove per-file copilot enable/disable 2023-04-03 15:21:43 -07:00
Mikayla Maki
48d9c30b0e Remove per-file copilot enable/disable 2023-04-03 15:15:42 -07:00
Mikayla Maki
0250898a2b Enable copilot in all file types by default 2023-04-03 15:06:49 -07:00
Max Brunsfeld
c960277349 Merge branch 'main' into randomized-tests-operation-script 2023-04-03 13:09:25 -07:00
Antonio Scandurra
2c0a645f19 Provide workspace_folders capability when initializing LSP
This fixes the YAML language server which was erroring on startup
after adding the `did_change_watched_files` capability in #2258.
2023-04-03 20:12:26 +02:00
Antonio Scandurra
588b2da40a Disable key ordering diagnostic for YAML language server 2023-04-03 20:02:29 +02:00
Petros Amoiridis
69557655ee Merge pull request #2346 from zed-industries/petros/z-360-dragging-file-from-tree-to-split-results
Fix dragging file from tree to split results in empty pane
2023-04-03 16:43:12 +03:00
Petros Amoiridis
5a397726d2 Do not drop the task
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-04-03 16:36:08 +03:00
Nathan Sobo
cdfe873802 Merge pull request #2343 from zed-industries/handles
Make typed handles wrappers around their untyped equivalents
2023-04-03 09:20:37 -04:00
Antonio Scandurra
0cb73b6579 Merge pull request #2345 from zed-industries/autocomplete-vs-copilot
Make autocompletion and copilot mutually exclusive
2023-04-03 14:37:02 +02:00
Antonio Scandurra
b88aa9af1d Clear active copilot suggestion only if there is one 2023-04-03 14:32:41 +02:00
Antonio Scandurra
ec5309b543 Make autocompletion and copilot mutually exclusive 2023-04-03 14:15:21 +02:00
Antonio Scandurra
b6a9d90609 Move creation of GetCompletionsParams entirely to the background 2023-04-03 13:30:57 +02:00
Antonio Scandurra
0b9e609e2a Merge pull request #2344 from zed-industries/copilot-collaboration
Fix Copilot errors when opening buffers that don't exist locally
2023-04-03 13:26:21 +02:00
Antonio Scandurra
b26d4f4f62 🔥 2023-04-03 13:18:16 +02:00
Antonio Scandurra
75ecf92ae4 Fix Copilot errors when opening buffers that don't exist locally 2023-04-03 12:28:32 +02:00
Nathan Sobo
138aa0492a Add downcast_ref to AnyViewHandle
I use unsafe code to transmute an AnyViewHandle to a ViewHandle<T> when
the type matches. Because ViewHandle<T> is repr(transparent) to the
wrapped AnyViewHandle, this is safe.
2023-04-02 16:10:16 -06:00
Nathan Sobo
71cf6ec5ae Use into_any instead of weird 'as' hack 2023-04-02 15:55:30 -06:00
Nathan Sobo
27258a0889 Remove From trait for AnyViewHandle in favor of into_any method
I think it's more explicit.
2023-04-02 15:50:42 -06:00
Nathan Sobo
aed8df96ff Wrap AnyWeak handles with their typed counterparts 2023-04-02 15:42:03 -06:00
Nathan Sobo
82a713fd1d Store AnyViewHandle inside ViewHandle and Deref to it 2023-04-02 14:59:55 -06:00
Julia
59fb4b3d29 Merge pull request #2342 from zed-industries/trust-npm-version-management
Trust NPM instead of managing dirs for different Node server versions
2023-03-31 17:21:16 -04:00
Julia
8c0db17634 Trust NPM instead of managing dirs for different Node server versions 2023-03-31 17:15:44 -04:00
Mikayla Maki
c19e6f8f0e Merge pull request #2338 from zed-industries/more-copilot-bugs
More copilot bugs
2023-03-31 12:45:19 -07:00
Mikayla Maki
297fd5f985 Merge pull request #2340 from zed-industries/fix-json-lsp-remove
Fix bug where JSON LSP would be deleted on installation.
2023-03-31 12:41:28 -07:00
Mikayla Maki
dcaa355ad2 Switch from removing all directories in the container dir to removing the non-version dir 2023-03-31 12:36:23 -07:00
Julia
0ae298a86f Merge pull request #2339 from zed-industries/revert
Revert "Merge pull request #2335 from zed-industries/dont-delete-json…
2023-03-31 15:33:12 -04:00
Julia
0f4f3bfbde Revert "Merge pull request #2335 from zed-industries/dont-delete-json-server-after-downloading-it"
This reverts commit 516e77906e, reversing
changes made to 54582fd77f.
2023-03-31 15:31:50 -04:00
Mikayla Maki
57b5c1ee20 Fix crash on initiating copilot during collaboration. Copilot is now disabled when collaborating. 2023-03-31 12:28:58 -07:00
Mikayla Maki
f616e8bac9 Merge pull request #2336 from zed-industries/respect-languages-alias-in-settings-file
Add support for writing to the langauge_overrides alias in settings
2023-03-31 11:51:25 -07:00
Mikayla Maki
b6882f0cbf Fix typo in copilot button 2023-03-31 11:50:31 -07:00
Mikayla Maki
e5a6b11d8f Merge pull request #2334 from zed-industries/quiet-copilot-loggin
Add handlers for LogMessage and statusNotification to copilot LSP
2023-03-31 11:22:23 -07:00
Mikayla Maki
c1445fe015 Add support for the langauge_overrides alias in the settings file updating code 2023-03-31 11:20:46 -07:00
Mikayla Maki
bdce96b19a Update copilot.rs 2023-03-31 11:16:52 -07:00
Julia
516e77906e Merge pull request #2335 from zed-industries/dont-delete-json-server-after-downloading-it
Don't delete JSON language server directly after downloading it
2023-03-31 14:08:09 -04:00
Julia
0199ffed5f Don't delete JSON language server directly after downloading it
This was accidentally added during the messy NodeRuntime/Copilot rebase

Co-Authored-By: Joseph Lyons <joseph@zed.dev>
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-31 14:01:04 -04:00
Mikayla Maki
f561e5ef2c remove spare debug 2023-03-31 11:00:06 -07:00
Mikayla Maki
4865ea2efc Add handlers for LogMessage and statusNotification to copilot LSP 2023-03-31 10:58:18 -07:00
Antonio Scandurra
54582fd77f Merge pull request #2333 from zed-industries/copilot-improvements
Fix several Copilot bugs
2023-03-31 18:14:39 +02:00
Antonio Scandurra
b208d1a489 🎨 2023-03-31 18:10:10 +02:00
Antonio Scandurra
5f579a4287 Fix prefix/suffix calculation when determining copilot suggestion
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-31 18:05:07 +02:00
Antonio Scandurra
b588ba1435 Avoid auto-indenting when accepting copilot suggestion
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-03-31 17:17:35 +02:00
Antonio Scandurra
6e43e77c3f Use copilot's Completion::{range,text} to determine suggestion
Previously, we were using display text, but this isn't always correct. Now,
we just attempt to determine what text Copilot wants to insert by finding
a prefix and suffix in the existing text with the suggested text.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
2023-03-31 17:08:41 +02:00
Mikayla Maki
9b16277cf8 Merge pull request #2316 from zed-industries/copilot
🚨 WIP 🚨 Copilot
2023-03-30 18:27:14 -07:00
Mikayla Maki
713f5f604f Fix leaked handle and failure to update language in context menu 2023-03-30 17:40:11 -07:00
Mikayla Maki
e38f52d595 Fix unrelated panics in tests 2023-03-30 17:19:29 -07:00
Mikayla Maki
c3188be4c1 cargofmt 2023-03-30 16:58:11 -07:00
Mikayla Maki
81411b9114 Merge branch 'main' into copilot 2023-03-30 16:57:18 -07:00
Mikayla Maki
c28d2c490b Remove test modals 2023-03-30 16:52:55 -07:00
Mikayla Maki
afc9b832c8 Finish device code flow for copilot 2023-03-30 16:50:33 -07:00
Mikayla Maki
f5d4bcd934 Added erorr states and first-pass error handling to the copilot status bar item.
Added correct icons
Added a new 'Toast' action which allows other crates to easily pop toasts with an optional click action
2023-03-30 14:10:57 -07:00
Julia
3cfe61a4f4 Merge pull request #2332 from zed-industries/per-server-code-action-kinds
Allow each language adapter to provide their own code action kinds array
2023-03-30 15:54:55 -04:00
Julia
cdde523ea4 Allow each language adapter to provide their own code action kinds array 2023-03-30 15:41:54 -04:00
Nate Butler
f235d9f411 Add zed plus copilot icon 2023-03-30 14:34:33 -04:00
Nate Butler
655897b182 Update icons 2023-03-30 14:32:51 -04:00
Nate Butler
58b453ad6e Add new copilot state icons 2023-03-30 14:18:03 -04:00
Mikayla Maki
b7461c32dd Improve settings writing for more cases 2023-03-30 10:40:53 -07:00
Mikayla Maki
e46cd2def3 Switch to using zed hosted copilot LSP (again)
co-authored-by: antonio <antionio@zed.dev>
2023-03-30 09:29:49 -07:00
Petros Amoiridis
007aa92581 Merge pull request #2323 from zed-industries/petros/z-402-recent-projects-replace-expanded-home
Replace home directory with the tilde substitution
2023-03-30 18:12:39 +03:00
Petros Amoiridis
dc51735112 Fix doctests 2023-03-30 17:57:14 +03:00
Petros Amoiridis
adc5ef911f Remove the Errors section from rust docs
The section does not add anything that we don't already know.

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-03-30 14:04:37 +03:00
Petros Amoiridis
18c6c7ebb7 Fix error 2023-03-30 14:03:59 +03:00
Petros Amoiridis
9ef3e45bcd Update crates/recent_projects/src/highlighted_workspace_location.rs
Co-authored-by: Antonio Scandurra <me@as-cii.com>
2023-03-30 11:35:17 +03:00
Antonio Scandurra
e3a311fda9 Merge pull request #2331 from zed-industries/tab-map-sync
Speed up tab searching in `TabMap::sync`
2023-03-30 10:20:57 +02:00
Antonio Scandurra
af4c4c7cf0 Speed up tab searching in TabMap::sync by looking for \t only
Instead of looking for `\n` as a stopping condition, we cap the range
we pass to `SuggestionSnapshot::chunks` to stop on the next line. This
makes character searching faster, because looking for a single character
uses `memchr`. Also, this avoids an extra conditional in a tight loop such
as the chunk scanning one contained in `TabMap::sync`.
2023-03-30 10:03:13 +02:00
Antonio Scandurra
79346b0706 Use + instead of | to break out of tab expansion in TabMap::sync 2023-03-30 09:49:07 +02:00
Mikayla Maki
5b3b74345d Remove some strays 2023-03-29 22:22:02 -07:00
Mikayla Maki
a8033b266d Fix bug with enable setting, clean up sign in UIs 2023-03-29 21:51:07 -07:00
Mikayla Maki
cc7c5b416c Add status bar icon reflecting copilot state to Zed status bar 2023-03-29 21:31:33 -07:00
Mikayla Maki
8fac32e1eb WIP, not compiling 2023-03-29 17:59:21 -07:00
Max Brunsfeld
ec5ffe9922 Merge pull request #2329 from zed-industries/new-window-on-click-doc
Open a new window when activating Zed from the dock w/ no windows open
2023-03-29 17:33:32 -07:00
Mikayla Maki
76efab005f WIP 2023-03-29 17:25:41 -07:00
Max Brunsfeld
b5f762ab25 Open a new window when activating Zed from the dock w/ no windows open 2023-03-29 17:24:44 -07:00
Nate Butler
e3822a5b5c Add copilot icons 2023-03-29 20:23:32 -04:00
Mikayla Maki
ae3b3ea458 Merge branch 'main' into copilot 2023-03-29 16:57:38 -07:00
Mikayla Maki
ebd06b43f5 Add copilot settings
Add copilot pause / resume
Add copilot statusbar item stub
2023-03-29 16:40:52 -07:00
Max Brunsfeld
7601e7902a Merge pull request #2325 from zed-industries/tab-map-long-lines
Avoid slowdowns with long lines by skipping tab expansion beyond a certain column
2023-03-29 14:48:23 -07:00
Max Brunsfeld
0c07a373a8 🎨 2023-03-29 14:43:01 -07:00
Julia
e558d3f903 Merge pull request #2328 from zed-industries/breadcrumbs-outline-toggle
Open symbol outline when clicking on editor breadcrumbs
2023-03-29 15:51:30 -04:00
Julia
737e2e1b3c Open symbol outline when clicking on editor breadcrumbs 2023-03-29 15:46:43 -04:00
Mikayla Maki
f812796283 Make modal behavior stateless
Co-authored-by: antonio <antonio@zed.dev>
2023-03-29 12:45:53 -07:00
Antonio Scandurra
49447128a9 Make edits smaller when tab expansion changes on a line 2023-03-29 21:40:37 +02:00
Joseph Lyons
6e2a9297ff v0.81.x dev 2023-03-29 14:13:01 -04:00
Antonio Scandurra
b86f8188d1 Expand edit to end of the line when old/new row exceeds max expansion 2023-03-29 16:49:21 +02:00
Petros Amoiridis
b15632bd45 Remove convert_to_shortened_path from gpui platform 2023-03-29 17:41:01 +03:00
Petros Amoiridis
b4593cd90b Use util::paths::compact 2023-03-29 17:40:39 +03:00
Petros Amoiridis
69989d0463 Introduce compact function in util create 2023-03-29 17:32:27 +03:00
Petros Amoiridis
d5f53111e8 Enable doctests in util crate 2023-03-29 17:31:55 +03:00
Petros Amoiridis
a128439699 Move code into the platform
Co-Authored-By: Joseph T. Lyons <19867440+JosephTLyons@users.noreply.github.com>
2023-03-29 16:25:13 +03:00
Petros Amoiridis
87c1b190a8 Replace home directory with the tilde substitution 2023-03-29 16:25:10 +03:00
Antonio Scandurra
719d0f0abf Rename skip_leading_tab to inside_leading_tab 2023-03-29 14:53:28 +02:00
Antonio Scandurra
813f722925 Increment input_column correctly when inside the leading tab 2023-03-29 14:52:50 +02:00
Antonio Scandurra
056f4e914f Merge pull request #2327 from zed-industries/remove-unused-code
Delete unused code
2023-03-29 09:09:47 +02:00
Antonio Scandurra
a64296938d Delete unused code 2023-03-29 09:04:13 +02:00
Mikayla Maki
d60ef03d66 WIP Add copilot disabled setting 2023-03-28 20:52:50 -07:00
Mikayla Maki
0b0c7e4ce9 Move command palette filter into collections crate
Filter out copilot commands from command palette when not active
2023-03-28 20:13:17 -07:00
Mikayla Maki
aea8475d30 Apply cargo fmt 2023-03-28 18:45:37 -07:00
Antonio Scandurra
a5cec18775 Remove copilot smoke test 2023-03-28 18:41:35 -07:00
Antonio Scandurra
12370f120e 🎨 2023-03-28 18:40:51 -07:00
Antonio Scandurra
ce9774be53 Improve detection of common prefix in text_for_active_completion 2023-03-28 18:40:42 -07:00
Mikayla Maki
9d8d2bb8f4 Add rough versions of all 3 modals 2023-03-28 18:00:09 -07:00
Max Brunsfeld
5c1f82ae3d Don't use TabMap::expand_tabs in line_indent_for_buffer_row 2023-03-28 17:37:57 -07:00
Max Brunsfeld
08e93e9321 Only expand tabs up until a limited column 2023-03-28 16:40:04 -07:00
Max Brunsfeld
c23feeab3a 🎨 Make expand_tabs and collapse_tabs instance methods on TabSnapshot 2023-03-28 14:10:43 -07:00
Mikayla Maki
941da24f73 Refactor out the node runtime crate and hook up all related imports 2023-03-28 10:27:31 -07:00
Mikayla Maki
0ef9cefe0f Finish shape of copilot auth UI 2023-03-28 09:42:01 -07:00
Mikayla Maki
6ff09865eb Create copilot auth popup UI 2023-03-28 09:42:01 -07:00
Antonio Scandurra
da81ff3295 Optimize CopilotState::text_for_active_completion 2023-03-28 09:42:01 -07:00
Antonio Scandurra
034bc75467 Refresh copilot suggestions when hitting alt-] if none are showing
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-28 09:42:01 -07:00
Antonio Scandurra
d236d9e8c9 Clear copilot suggestions when hitting escape
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-28 09:42:01 -07:00
Nate Butler
ef6c28326d Update editor.ts 2023-03-28 09:42:01 -07:00
Nate Butler
2fede1c01f Use syntax.predictive.color to style suggestions 2023-03-28 09:42:01 -07:00
Antonio Scandurra
1162615043 Reuse existing suggestion when inserting to avoid flickering 2023-03-28 09:42:01 -07:00
Antonio Scandurra
6715e5247c Rework SuggestionMap to take highlight style when retrieving chunks 2023-03-28 09:42:01 -07:00
Antonio Scandurra
093e0a30e9 Replace editor::CycleCopilotSuggestions with copilot::NextSuggestion 2023-03-28 09:42:01 -07:00
Antonio Scandurra
2f95510a2e Start integrating Copilot with editor
There's still a bit to do in terms of reusing the previous suggestion
when the prefix matches, but we're getting there.
2023-03-28 09:42:01 -07:00
Antonio Scandurra
b16e2169ce WIP: Start on showing window for authenticating with copilot
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-28 09:42:01 -07:00
Antonio Scandurra
9713d1bb31 Fix invalid translation between bottom/top left coordinate spaces
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-28 09:42:01 -07:00
Antonio Scandurra
99cca59c84 Restructure verification code prompting to open a window instead
Also, prevent multiple calls to `sign_in` from racing with each other.
2023-03-28 09:42:01 -07:00
Mikayla Maki
19cc86a2d4 Wait to show the auth modal until the sign request has returned 2023-03-28 09:42:00 -07:00
Mikayla Maki
15e29d44b9 Add basic copilot modal 2023-03-28 09:42:00 -07:00
Mikayla Maki
b57d5174aa Add copilot theme, start sketching out the auth modal 2023-03-28 09:42:00 -07:00
Antonio Scandurra
591e246450 Implement Copilot::completions_cycling
Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-03-28 09:42:00 -07:00
Antonio Scandurra
155594c8b8 Successfully fetch completions from Copilot
We still need to process them and return them into a more Zed-friendly
structure, but we're getting there.
2023-03-28 09:42:00 -07:00
Antonio Scandurra
180371929b Start on copilot completions 2023-03-28 09:42:00 -07:00
Antonio Scandurra
8ba9e63ab8 🎨 2023-03-28 09:42:00 -07:00
Antonio Scandurra
59d9277a74 Implement Copilot sign in and sign out 2023-03-28 09:42:00 -07:00
Antonio Scandurra
797bb7d780 Start copilot and check sign in status 2023-03-28 09:42:00 -07:00
Antonio Scandurra
5471217089 Use the same serde version across the entire workspace 2023-03-28 09:42:00 -07:00
Mikayla Maki
9a99eaee96 Fix bad global 2023-03-28 09:42:00 -07:00
Mikayla Maki
455cdc8b37 Add copilot crate
Refactor HTTP and github release downloading into util
Lazily download / upgrade the copilot LSP from Zed

Co-authored-by: Max <max@zed.dev>
Co-Authored-By: Antonio <antonio@zed.dev>
2023-03-28 09:41:59 -07:00
Julia
35b2aceffb Merge pull request #2324 from zed-industries/download-node
Automatically download Node for Node based language servers
2023-03-28 12:10:24 -04:00
Julia
ee3ac9c344 Rename installation.rs -> github.rs now that is all it concerns 2023-03-28 11:51:09 -04:00
Julia
350f8ed304 Download the JSON LSP package instead of our own bundled binary 2023-03-28 11:48:00 -04:00
Julia
d4560fe321 Prevent deadlock when multiple languages attempt to install Node at once 2023-03-28 10:18:22 -04:00
Max Brunsfeld
c68c8462bb Merge pull request #2322 from zed-industries/project-panel-paste-infinite-loop
Fix infinite loop in ProjectPanel::paste when filename has multiple dots
2023-03-27 17:09:10 -07:00
Max Brunsfeld
17bc83d699 Fix infinite loop in ProjectPanel::paste when filename has multiple dots 2023-03-27 16:45:11 -07:00
Max Brunsfeld
e5d552ef97 Merge pull request #2321 from zed-industries/new-file-with-no-window
Make 'new file' action open a window when there are no windows open
2023-03-27 16:10:30 -07:00
Max Brunsfeld
4a2132bc91 Make 'new file' action open a window when there are no windows open 2023-03-27 16:05:00 -07:00
Joseph T. Lyons
e10338ed17 Merge pull request #2313 from zed-industries/unify-spelling-of-key-binding-to-be-two-words
Unify spelling of `key binding` to be two words
2023-03-27 15:58:12 -04:00
Petros Amoiridis
eb7c6028f4 Merge pull request #2320 from zed-industries/petros/z-349-make-restart-to-update-zed-look
Make "Restart to update Zed" look clickable
2023-03-27 20:19:06 +03:00
Julia
df4380b066 Download aarch64 or x64 Node binary according to system architecture 2023-03-27 11:05:17 -04:00
Petros Amoiridis
b153bf7118 Add a hovered style to lspStatus background 2023-03-27 14:26:56 +03:00
Petros Amoiridis
374b284a3d Run prettier on TS files 2023-03-27 14:26:05 +03:00
Julia
c72d33e029 Initial impl of NodeRuntime w/JSON borked and a deadlock :)
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-03-27 00:00:16 -04:00
Julia
1a2e509e35 Remove server_args from LspAdapter
Prepare to remove concept of a runtime from greater server startup code,
which is important for future language server extensibility

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-03-27 00:00:16 -04:00
Julia
ed442cfc8c Invoke npm from downloaded Node 2023-03-27 00:00:16 -04:00
Julia
edd6c85af7 Initial running of servers on downloaded Node 2023-03-27 00:00:16 -04:00
Julia
b579211861 Report if language server requires Node or not 2023-03-27 00:00:16 -04:00
Nathan Sobo
d89936e4a9 Merge pull request #2319 from zed-industries/copy-highlight-json
Add "editor: copy highlight json" command
2023-03-24 17:17:45 -06:00
Nathan Sobo
f0992e7d67 Trim empty tokens; copy selected range if non-empty 2023-03-24 17:10:50 -06:00
Nathan Sobo
3dfedd1b21 Merge adjacent chunks with the same highlight name in copied JSON 2023-03-24 16:52:00 -06:00
Nathan Sobo
195215f1e0 Add "editor: copy highlight json" command
Nate needs this to feed to Figma for highlighted code in designs.
2023-03-24 16:37:57 -06:00
Max Brunsfeld
c74f8eb9e3 Merge pull request #2258 from zed-industries/lsp-file-change-notifications
Implement `DidChangedWatchedFiles` LSP feature
2023-03-24 14:42:23 -07:00
Max Brunsfeld
455ffb17f1 Handle path changes and progress updates from all worker threads during initial scan 2023-03-24 14:35:18 -07:00
Max Brunsfeld
027def6800 Merge branch 'main' into lsp-file-change-notifications 2023-03-24 08:52:43 -07:00
Max Brunsfeld
a0e98ccc35 🎨 BackgroundScanner::run 2023-03-23 18:05:12 -07:00
Max Brunsfeld
89e99d2902 🎨 Don't store path changes statefully on the background scanner 2023-03-23 16:04:47 -07:00
Max Brunsfeld
3ff5aee4a1 Respect LSP servers watch glob patterns 2023-03-23 16:03:07 -07:00
Mikayla Maki
76b75b4b43 Merge pull request #2318 from zed-industries/fix-unknown-in-non-editor-buffers
changed language status bar item to only show on editors
2023-03-23 13:33:42 -07:00
Mikayla Maki
5db11c628b changed language status bar item to only show on editors 2023-03-23 13:29:23 -07:00
Mikayla Maki
5cad3d3a67 Merge pull request #2317 from zed-industries/fix-titlebar-right-spacing
Fix misaligned UI in the right titlebar
2023-03-23 13:16:40 -07:00
Mikayla Maki
bb5c2833a3 Aligned title bar items to the center and fixed left spacing on the sign in button
co-authored-by: max <max@zed.dev>
2023-03-23 13:08:31 -07:00
Petros Amoiridis
566a04ebca Merge pull request #2311 from zed-industries/petros/z-279-add-terminals-count
Add terminals count
2023-03-23 10:52:01 +02:00
Mikayla Maki
f9d3963dbb Merge pull request #2315 from zed-industries/fix-fold-indicator-offsets
Fix fold indicator offsets
2023-03-22 17:13:13 -07:00
Mikayla Maki
e87c3b6dd7 Update element.rs
remove spare parens
2023-03-22 17:05:54 -07:00
Mikayla Maki
e729c4ad4f Fix fold indicator offsets 2023-03-22 17:04:52 -07:00
Max Brunsfeld
361b7c3a0c Clear auto-indent requests when replacing a buffer's entire text 2023-03-22 15:10:16 -07:00
Max Brunsfeld
eaee5571a0 Use a more stable, readable serialization format for neovim-backed vim tests 2023-03-22 14:31:11 -07:00
Joseph Lyons
6de38f7410 v0.80.x dev 2023-03-22 16:33:06 -04:00
Julia
df553de363 Merge pull request #2314 from zed-industries/another-one
Remove another spot with a flag old npm does not like
2023-03-22 15:56:23 -04:00
Julia
4fc37cf982 Remove another spot with a flag old npm does not like 2023-03-22 15:40:51 -04:00
Joseph Lyons
9d88cd8842 Unify spelling of key binding to be two words 2023-03-22 13:34:12 -04:00
Petros Amoiridis
fd9eff3a78 Remove struct 2023-03-22 19:28:06 +02:00
Petros Amoiridis
bd1515cdd2 Only show count when we have terminals
Co-Authored-By: Mikayla Maki <mikayla.c.maki@gmail.com>
2023-03-22 18:23:41 +02:00
Joseph T. Lyons
bd85ef363f Merge pull request #2312 from zed-industries/unkown
Fix typo in "Unknown" language
2023-03-22 11:20:18 -04:00
Nathan Sobo
e017b99384 Fix typo 2023-03-22 09:13:10 -06:00
Petros Amoiridis
15406ff2d9 Remove comment 2023-03-22 16:31:42 +02:00
Petros Amoiridis
d5bb2d13b8 Introduce terminal button count
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
2023-03-22 16:13:58 +02:00
Petros Amoiridis
aa7254167a Fix typo 2023-03-22 15:31:21 +02:00
Antonio Scandurra
005eb559ee Merge pull request #2310 from zed-industries/fix-sharing-status-indicator
Remove screen sharing indicator when call ends
2023-03-22 09:40:23 +01:00
Antonio Scandurra
7df798ded5 Remove screen sharing indicator when call ends
Previously, we would only remove it when the screen sharing stopped.
2023-03-22 09:32:27 +01:00
Max Brunsfeld
c1f53358ba Remove unnecessary Arc around background scanner's snapshot 2023-03-21 15:47:02 -07:00
Max Brunsfeld
f7b2713b77 Fix error in joining empty paths 2023-03-21 15:41:24 -07:00
Max Brunsfeld
5da2b123b5 Allow refreshing worktree entries while the initial scan is in-progress 2023-03-21 15:15:12 -07:00
Max Brunsfeld
b10b0dbd75 Only mutate background snapshot in the background scanner 2023-03-21 11:26:33 -07:00
Max Brunsfeld
d742c758bc Restructure communication from BackgroundScanner to LocalWorktree
The worktree no longer pulls the background snapshot from the background scanner.
Instead, the background scanner sends both snapshots to the worktree. Along with
these, it sends the path change sets.

Also, add randomized test coverage for the worktree UpdatedEntries events.
2023-03-21 11:26:13 -07:00
Max Brunsfeld
cbeb6e692d Move postage crate version specification to workspace Cargo.toml 2023-03-21 11:26:13 -07:00
Max Brunsfeld
d36b2a3129 🎨 Simplify some worktree methods
* Consolidate local worktree construction into one method
* Simplify remote worktree construction
* Reduce indirection around pulling worktree snapshots from the background
2023-03-21 11:26:13 -07:00
Max Brunsfeld
399f082415 Update wrong assertions after fixing missing event in FakeFs 2023-03-21 11:26:13 -07:00
Max Brunsfeld
51b093197d Add missing import in project tests 2023-03-21 11:26:13 -07:00
Max Brunsfeld
27ad6a57ce Tweak logging in worktree randomized test 2023-03-21 11:26:13 -07:00
Max Brunsfeld
c730dca3c5 Update worktree randomized test to use worktree's public interface and the fake fs 2023-03-21 11:26:13 -07:00
Max Brunsfeld
be5868e1c0 Conservatively report fs events that occurred during initial worktree scan
Co-authored-by: Nathan Sobo <nathan@zed.dev>
2023-03-21 11:26:13 -07:00
Max Brunsfeld
61172c8478 Notify language servers of FS changes 2023-03-21 11:26:13 -07:00
Max Brunsfeld
9837a6e288 Add failing test for reporting FS change events to language servers 2023-03-21 11:26:13 -07:00
Antonio Scandurra
194c7a3af0 Merge pull request #2309 from zed-industries/suggestion-map
Introduce `DisplayMap::replace_suggestion`
2023-03-21 18:18:50 +01:00
Antonio Scandurra
2893c9bdb7 Don't move up/down by more rows than the requested ones
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-03-21 17:52:53 +01:00
Antonio Scandurra
f7cba4cec4 Make Suggestion fields public 2023-03-21 16:51:33 +01:00
Antonio Scandurra
ba3913df8c Expose a DisplayMap::replace_suggestion method 2023-03-21 16:41:54 +01:00
Antonio Scandurra
9c8732a355 Integrate SuggestionMap into the rest of DisplayMap 2023-03-21 16:39:02 +01:00
Antonio Scandurra
d1978a719b Add a version field to SuggestionSnapshot 2023-03-21 12:47:04 +01:00
Antonio Scandurra
3d165f705f Extract a SuggestionMap::randomly_mutate method 2023-03-21 11:51:06 +01:00
Antonio Scandurra
35830a0271 Implement SuggestionSnapshot::to_{fold,suggestion}_point 2023-03-21 11:39:29 +01:00
Antonio Scandurra
d448a5cb5c Implement SuggestionSnapshot::to_point 2023-03-21 11:28:36 +01:00
Antonio Scandurra
f829ce5641 Implement SuggestionSnapshot::to_offset 2023-03-21 11:28:33 +01:00
Antonio Scandurra
c0e124a55a Implement SuggestionSnapshot::text_summary_for_range 2023-03-21 11:28:30 +01:00
Antonio Scandurra
52a156aebe Implement SuggestionSnapshot::clip_point 2023-03-21 11:28:27 +01:00
Antonio Scandurra
ccb6196224 Implement SuggestionSnapshot::buffer_rows 2023-03-21 11:28:23 +01:00
Antonio Scandurra
1a9dbfa86a Add unit test to verify basic properties of the SuggestionMap 2023-03-21 08:29:33 +01:00
Joseph T. Lyons
8c0dd887ff Merge pull request #2299 from zed-industries/correct-verb-tense-in-default-settings
Correct verb tense in default settings
2023-03-20 14:50:46 -04:00
Antonio Scandurra
3edf83cb99 Implement SuggestionSnapshot::line_len
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-03-20 19:45:39 +01:00
Antonio Scandurra
f44549eb29 Enhance randomized test to verify SuggestionMap::{chunks,sync}
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-03-20 19:29:22 +01:00
Antonio Scandurra
4d6726ef39 WIP: Flesh out more of the suggestions randomized test 2023-03-20 18:06:24 +01:00
Petros Amoiridis
98ae69a61f Merge pull request #2282 from zed-industries/petros/z-283-make-pop-up-positioning-consistent
Consistent pop-up menu positions
2023-03-20 17:55:40 +02:00
Petros Amoiridis
24bbca7326 Position pane new, split, and dock context menus
Co-Authored-By: Julia <30666851+ForLoveOfCats@users.noreply.github.com>
2023-03-20 17:49:33 +02:00
Nathan Sobo
d429ce0f62 Merge pull request #2308 from zed-industries/feedback-icon
Use an envelope as the feedback icon so we can use the speech bubble for discussions
2023-03-20 09:14:34 -06:00
Nathan Sobo
10e6c5b651 Use an envelope as the feedback icon
This makes room to use the speech bubble for discussion threads.
2023-03-20 09:04:30 -06:00
Antonio Scandurra
9970e5f60c Start on randomized test and add SuggestionMapSnapshot::chunks 2023-03-20 15:56:15 +01:00
Antonio Scandurra
fb48854e5a Simplify signature of SuggestionMap::replace 2023-03-20 14:00:14 +01:00
Antonio Scandurra
83051f1e86 Add SuggestionMap::replace 2023-03-20 13:50:14 +01:00
Antonio Scandurra
94a9e28e35 Start on SuggestionMap 2023-03-20 13:22:14 +01:00
Mikayla Maki
2a024a255f Merge pull request #2307 from zed-industries/fix-panic-in-editor-tab-content
Do UTF8-aware truncation on long item names in editor item
2023-03-18 15:49:06 -07:00
Mikayla Maki
436c59d8ef Do UTF8-aware truncation on long item names in editor item 2023-03-18 15:44:23 -07:00
Mikayla Maki
5356ec4730 Merge pull request #2287 from zed-industries/fix-fold-range-finding
Fix code folds with wraps
2023-03-17 17:18:56 -07:00
Mikayla Maki
5a3d5dff42 Make folds tab aware 2023-03-17 17:14:40 -07:00
Mikayla Maki
c39b4ac229 Fix boundary condition in buffer_line_len when at the end of a file
co-authored-by: max <max@zed.dev>
2023-03-17 16:56:44 -07:00
Mikayla Maki
5a1bbb96ba Merge pull request #2302 from zed-industries/fix-dispatch-path-panic
Align dispatch_keystroke with other uses of ancestors iterator
2023-03-17 16:34:00 -07:00
Mikayla Maki
b16e53a577 Merge pull request #2306 from zed-industries/fix-panic-with-multi-line-env
Parse user enviroment using null terminators instead of newlines
2023-03-17 16:18:05 -07:00
Mikayla Maki
109e17b4b2 Parse user enviroment using null terminators instead of newlines 2023-03-17 16:14:07 -07:00
Mikayla Maki
eba119b914 Fix fold tests with new representation
Switch UI code from using display rows to using buffer rows
Make folds only show up on lines with line layouts

co-authored-by: Max <max@zed.dev>
2023-03-17 16:00:22 -07:00
Max Brunsfeld
fc828971f1 collab 0.8.2 2023-03-17 15:00:31 -07:00
Max Brunsfeld
691383ca68 Merge pull request #2305 from zed-industries/faster-access-token-validation
Faster access token validation
2023-03-17 14:56:30 -07:00
Max Brunsfeld
b8e8363a72 Add logging and metric for time spent hashing auth tokens
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2023-03-17 14:32:13 -07:00
Max Brunsfeld
623133ffa0 Reduce scrypt work factor to speed up websocket authentication
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2023-03-17 14:31:39 -07:00
Max Brunsfeld
9633a4b527 Return a 400, not a 500 when token validation fails
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-17 13:56:12 -07:00
Julia
368a6405a1 Increase git diff gutter width slightly 2023-03-17 15:28:38 -04:00
Mikayla Maki
459e320d79 Merge pull request #2303 from zed-industries/add-unknown-language
Add an 'Unknown' state for a mouse-driven way to select a file language
2023-03-17 11:41:40 -07:00
Mikayla Maki
04f52c3d50 Show active buffer language in all cases 2023-03-17 11:34:17 -07:00
Max Brunsfeld
26dae3c04e Lookup access tokens by id when authenticating a connection
This avoids the cost of hashing an access token multiple times,
to compare it to all known access tokens for a given user.

Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-17 11:13:50 -07:00
Mikayla Maki
578c69476d Align dispatch_keystroke with other uses of ancestors iterator and filter out non-existant views 2023-03-17 11:07:10 -07:00
Mikayla Maki
1125a168f4 Merge pull request #2301 from zed-industries/fix-file-finder-panic
Never call set_selected_index with an invalid index
2023-03-17 10:18:27 -07:00
Antonio Scandurra
d8758658e3 Merge pull request #2300 from zed-industries/ligatures
Allow customization of OpenType features
2023-03-17 17:34:17 +01:00
Mikayla Maki
f7f9b8cffe Never call set_selected_index with an invalid index 2023-03-17 09:32:01 -07:00
Antonio Scandurra
1af8f4be19 Deserialize Theme directly into the heap to avoid stack overflow
Co-Authored-By: Julia Risley <julia@zed.dev>
2023-03-17 15:58:52 +01:00
Antonio Scandurra
786d95b8c8 Avoid storing fonts::Features in TextStyle
We were only using it for debugging purposes and that was causing
the `Theme` struct to become too big to hold on the stack.

Co-Authored-By: Julia Risley <julia@zed.dev>
2023-03-17 15:12:02 +01:00
Antonio Scandurra
4d915f4530 Don't make fonts::Features Copy 2023-03-17 13:54:56 +01:00
Antonio Scandurra
989c9f0196 Mention calt: false in the default settings to disable ligatures 2023-03-17 13:48:34 +01:00
Antonio Scandurra
f9d793cb4a Honor more OpenType features 2023-03-17 13:40:00 +01:00
Petros Amoiridis
3bddf01962 Run prettier to format things 2023-03-17 14:05:49 +02:00
Petros Amoiridis
86ed5b8b83 Position contacts and user menus
Using the new approach for consistency
2023-03-17 14:05:46 +02:00
Antonio Scandurra
9181ac9872 Honor the calt font feature 2023-03-17 12:01:27 +01:00
Antonio Scandurra
76167ca65c Allow setting font features on TextStyle 2023-03-17 11:49:22 +01:00
Antonio Scandurra
7d13b00914 Allow setting font features on the terminal as well 2023-03-17 11:42:24 +01:00
Antonio Scandurra
b2c733baab WIP: Allow specifying font features in the editor
This just lays the foundation for threading through a `fonts::Features`
struct, but it's not used yet.
2023-03-17 09:51:36 +01:00
Joseph Lyons
6eb65eb989 Correct verb tense in default settings 2023-03-17 00:51:03 -04:00
Julia
3464961aa4 Merge pull request #2298 from zed-industries/fix-deadlock
Fix deadlock while initializing JSON language server
2023-03-16 17:41:54 -04:00
Julia
757f05042d Fix deadlock while initializing JSON language server
As it turns out both parking-lot and std's `RwLock` disallows taking
multiple read locks on the same thread

Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-03-16 17:32:51 -04:00
Max Brunsfeld
9633732db7 collab 0.8.1 2023-03-16 14:21:35 -07:00
Max Brunsfeld
e34d80cff4 Merge pull request #2296 from zed-industries/tx-serialization-retry-delay
Introduce a delay before retrying a transaction after a serialization failure
2023-03-16 14:16:20 -07:00
Mikayla Maki
f2492666d4 Merge pull request #2297 from zed-industries/fix-random-panics
WIP: Fix random panics
2023-03-16 13:20:54 -07:00
Joseph T. Lyons
b3b20e4c46 Merge pull request #2295 from zed-industries/swap-atom-keybinding-for-CollapseSelectedEntry
Swap atom keybinding for CollapseSelectedEntry
2023-03-16 16:12:28 -04:00
Max Brunsfeld
b9bc66aa9b Log the delay when retrying a transaction 2023-03-16 13:07:38 -07:00
Max Brunsfeld
35280f7d80 Introduce a delay before retrying a transaction after a serialization failure
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-16 13:07:38 -07:00
Mikayla Maki
6571555c4d Fix unwrap in git2 library causing panics in Zed 2023-03-16 13:06:23 -07:00
Joseph Lyons
a252c2a15b Swap atom keybinding for CollapseSelectedEntry
This is a temporary solution to this bug:

https://linear.app/zed-industries/issue/Z-340/the-project-panel-shouldnt-be-listening-to-key-commands-when-editing-a
2023-03-16 15:59:14 -04:00
Mikayla Maki
c3325430ca Fix divide by 0 in terminal
Fix fail to remove contact in contact list
2023-03-16 12:31:50 -07:00
Julia
1fbdea6a03 Merge pull request #2294 from zed-industries/remove-flag-old-npm-does-not-like
Remove CLI flag which old versions of NPM do not like
2023-03-16 13:11:45 -04:00
Julia
24dba2157f Remove CLI flag which old versions of NPM do not like
TODO: Bundle or version restrict Node
2023-03-16 13:07:09 -04:00
Mikayla Maki
c427a8c584 WIP - DEBUGGING 2023-03-16 08:41:19 -07:00
Antonio Scandurra
356b8c6980 Merge pull request #2293 from zed-industries/yaml-hover-bug
Fix hover popover rendering lots of `&emsp` for YAML
2023-03-16 16:15:14 +01:00
Antonio Scandurra
9498f02f2c Retrieve workspace configuration before initializing language server 2023-03-16 15:01:31 +01:00
Antonio Scandurra
f5a4c6a7c1 Provide editor.tabSize in workspace configuration for YAML
This fixes a bug that caused the hover popover to display lots of
`&emsp;` occurrences.
2023-03-16 10:46:55 +01:00
Antonio Scandurra
88e664bfd9 Add test for language registration and loading 2023-03-16 10:46:55 +01:00
Antonio Scandurra
8a685fa52a Use LanguageRegistry::workspace_configuration everywhere 2023-03-16 10:46:55 +01:00
Antonio Scandurra
4d52fc0d12 Remove available language only when it has loaded
This also ensures that, if you load the same language more than once,
a future that resolves to the language (or an error) is returned at
all times. Previously, we would only return it the first time the language
was loaded.
2023-03-16 10:46:55 +01:00
Antonio Scandurra
a8ac08f5bd Coalesce multiple RwLocks into one LanguageRegistryState struct 2023-03-16 10:46:55 +01:00
Antonio Scandurra
e30ea43a14 Include loaded languages when computing lsp workspace configuration 2023-03-16 10:46:55 +01:00
Antonio Scandurra
60d3fb48e2 Start computing workspace configuration more dynamically 2023-03-16 10:46:55 +01:00
Max Brunsfeld
ed9927b495 Merge pull request #2292 from zed-industries/restart-app
Make 'restart' action more reliable
2023-03-15 18:01:22 -07:00
Max Brunsfeld
d69868fa44 Make restart action more reliable 2023-03-15 17:44:50 -07:00
Julia
1ed3aedb16 Merge pull request #2291 from zed-industries/change-LSHandlerRank
Change `LSHandlerRank` to `Alternate`
2023-03-15 19:33:33 -04:00
Julia
905e2586e9 Change LSHandlerRank to Alternate 2023-03-15 19:18:39 -04:00
Max Brunsfeld
51eb53be0d Merge pull request #2290 from zed-industries/close-remote-projects-when-leaving-call
Close remote project windows when leaving a call
2023-03-15 15:34:51 -07:00
Max Brunsfeld
b34477458e Close remote project windows when leaving a call 2023-03-15 15:24:58 -07:00
Nathan Sobo
385dfe1661 Merge pull request #2289 from zed-industries/sort-language-names-case-agnostically
Sort language names case agnostically
2023-03-14 20:00:52 -06:00
Joseph Lyons
3c7237e600 Sort language names case agnostically 2023-03-14 21:45:17 -04:00
Nathan Sobo
44a2506c40 Merge pull request #2288 from zed-industries/cut-off-collaborator-avatars
Fix collaborator avatars being clipped and not centered
2023-03-14 19:39:01 -06:00
Max Brunsfeld
c4e7611d04 Fix collaborator avatars being clipped and not centered
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Julia Risley <julia@zed.dev>
2023-03-14 17:59:33 -07:00
Mikayla Maki
75bea91245 Convert code folding to be in terms of buffer points instead of display points
Co-authored-by: max <max@zed.dev>
2023-03-14 16:48:03 -07:00
Max Brunsfeld
828e9c1bb8 v0.79.x dev 2023-03-14 12:49:33 -07:00
Max Brunsfeld
2042188f5a Merge pull request #2286 from zed-industries/discoverable-sign-in
Make sign-in more discoverable
2023-03-14 11:08:18 -07:00
Max Brunsfeld
0bbb4b22c6 Rename 'Authenticate' action to 'Sign In'
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-14 11:01:23 -07:00
Max Brunsfeld
75901f1c33 Show sign in button directly in titlebar when not signed in
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-14 10:59:39 -07:00
Antonio Scandurra
a6ebc9bd26 collab 0.8.0 2023-03-14 18:21:16 +01:00
Antonio Scandurra
9e3085b0c4 Merge pull request #2284 from zed-industries/automatic-user-creation
Create user record automatically when someone logs in on the website
2023-03-14 18:20:13 +01:00
Mikayla Maki
7af9dda869 Merge pull request #2285 from zed-industries/fix-failed-theme-setting
Fix failed theme setting
2023-03-14 10:10:39 -07:00
Mikayla Maki
2a5ac4f203 Merge pull request #2283 from zed-industries/fix-code-fold-indicator-scaling
Change fold icon width to scale with font size
2023-03-14 10:07:25 -07:00
Mikayla Maki
d8a3f16891 Refactor load into a seperate function 2023-03-14 09:56:27 -07:00
Mikayla Maki
99257a8213 Fix failed initialization of setting file in welcome experience 2023-03-14 09:46:28 -07:00
Antonio Scandurra
0f429243d7 Fix seed binary 2023-03-14 12:37:56 +01:00
Antonio Scandurra
cba41ef7c5 Create user record automatically when someone logs in on the website
Now that we are moving out of the private alpha, we should let everyone
in when they try to log into zed.dev.
2023-03-14 12:25:04 +01:00
Mikayla Maki
2ba38b2fca Change icon width to scale with font size 2023-03-14 00:42:15 -07:00
Petros Amoiridis
e7f78c4f74 Merge pull request #2281 from zed-industries/petros/z-298-the-terminal-button-is-not-shown-for
Remove check for staffmode
2023-03-14 00:12:13 -07:00
Petros Amoiridis
8980df1f5d Remove feature flag
It wasn't working in production anyway
2023-03-14 09:05:04 +02:00
Nathan Sobo
2db8ac4a6f Merge pull request #2280 from zed-industries/terms
Add terms of use to DMG in the bundle script
2023-03-13 16:08:07 -06:00
Nathan Sobo
818a514110 Add terms of use to DMG in the bundle script
Co-Authored-By: Max Brunsfeld <max@zed.dev>
2023-03-13 15:47:59 -06:00
Mikayla Maki
1b4f783b97 Merge pull request #2279 from zed-industries/remove-invite-link
Remove UI for invite link in prep for beta launch
2023-03-13 14:35:52 -07:00
Mikayla Maki
88599add56 Remove UI for invite link in prep for beta launch 2023-03-13 12:54:20 -07:00
Max Brunsfeld
05f6747132 v0.78.x dev 2023-03-13 12:00:56 -07:00
Max Brunsfeld
1096720b41 Merge pull request #2244 from zed-industries/less-surprising-defaults
Clean up some default settings
2023-03-13 11:54:46 -07:00
Julia
5c7c4dd4dd Clean up some default settings 2023-03-13 14:54:28 -04:00
Max Brunsfeld
da35202bbf Merge pull request #2278 from zed-industries/screenshares-from-before-joining
Fix failure to see screenshare tracks that were started prior to join…
2023-03-13 11:22:40 -07:00
Max Brunsfeld
f5c4a2a0dd Fix failure to see screenshare tracks that were started prior to joining a call
Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2023-03-13 11:15:22 -07:00
Mikayla Maki
77a63c6598 Merge pull request #2277 from zed-industries/switch-invite-person-icon
Update Collab + icon
2023-03-13 10:54:33 -07:00
Nate Butler
edd925f77b Format 2023-03-13 13:49:00 -04:00
Nate Butler
6d0f8290a4 Merge pull request #2276 from zed-industries/improve-picker-state-contrast
Improve picker state contrast
2023-03-13 13:48:04 -04:00
Nate Butler
6497ca8ccb Update icon 2023-03-13 13:47:58 -04:00
Nate Butler
e64fe6d660 Improve contrast of project panel active state in light themes 2023-03-13 13:10:46 -04:00
Nate Butler
7df2440757 Format 2023-03-13 12:59:23 -04:00
Nate Butler
6fd4e28813 Update picker active and hover styles
Thanks for pointing this out @ForLoveOfCats

Co-Authored-By: Julia <30666851+ForLoveOfCats@users.noreply.github.com>
2023-03-13 12:59:17 -04:00
Max Brunsfeld
51cea1b1fb Merge branch 'main' into randomized-tests-operation-script 2023-02-20 10:39:00 -08:00
Max Brunsfeld
9c25d37dfc Merge branch 'main' into randomized-tests-operation-script
In randomized integration test, incorporate random updates of existing
files into the test's new structure.
2023-01-24 12:39:24 -08:00
Max Brunsfeld
2c84b74126 Avoid retaining project in randomized test while LSP request is outstanding 2023-01-16 09:48:54 -08:00
Max Brunsfeld
1a9ff2420e Clean up how applications are marked as inapplicable 2023-01-12 22:09:36 -08:00
Max Brunsfeld
e04d0be853 Remove unneeded log messages in randomized test 2023-01-12 14:30:53 -08:00
Max Brunsfeld
00e8625037 Simplify management of entity ids for different app contexts in randomized test 2023-01-12 14:30:10 -08:00
Max Brunsfeld
a3c7416218 Don't include user ids with MutateClients ops in serialized test plans 2023-01-12 14:28:31 -08:00
Max Brunsfeld
576a9bb92c Drop project's buffers when closing a remote project 2023-01-09 14:49:36 -08:00
Max Brunsfeld
5a4fa4b11e Merge branch 'main' into randomized-tests-operation-script 2023-01-09 12:26:11 -08:00
Max Brunsfeld
3e3a703b60 Skip inapplicable operations when running an edited test plan 2023-01-09 11:36:53 -08:00
Max Brunsfeld
c503ba00b6 Add env vars to store and load test plan from JSON files 2023-01-06 17:51:25 -08:00
Max Brunsfeld
2351f2bd0c Tolerate failure to join remote projects in randomized test 2023-01-06 15:40:42 -08:00
Max Brunsfeld
99390a7237 Represent all randomized test actions as operations 2023-01-06 15:32:11 -08:00
Max Brunsfeld
210286da48 Make operations for all buffer manipulations 2023-01-06 15:32:11 -08:00
Max Brunsfeld
f1b3692a35 Tweak operation rates 2023-01-06 15:32:11 -08:00
Max Brunsfeld
f243633f3e Set up flow for mutating clients via explicit operation values 2023-01-06 15:32:11 -08:00
Max Brunsfeld
ce8dd5a286 wip 2023-01-06 15:32:11 -08:00
Max Brunsfeld
a74c5073a4 Start work on allowing random collab test to be minimized
Represent operations as an explicit enum.
2023-01-06 15:32:11 -08:00
627 changed files with 66749 additions and 33001 deletions

View File

@@ -1,9 +1,12 @@
## Description of feature or change
[[PR Description]]
## Link to related issues from zed or community
Release Notes:
## Before Merging
- N/A
- [ ] Does this have tests or have existing tests been updated to cover this change?
- [ ] Have you added the necessary settings to configure this feature?
- [ ] Has documentation been created or updated (including above changes to settings)?
or
- (Added|Fixed|Improved) ... ([#<public_issue_number_if_exists>](https://github.com/zed-industries/community/issues/<public_issue_number_if_exists>)).
If the release notes are only intended for a specific release channel only, add `(<release_channel>-only)` to the end of the release note line.
These will be removed by the person making the release.

View File

@@ -42,6 +42,7 @@ jobs:
runs-on:
- self-hosted
- test
needs: rustfmt
env:
RUSTFLAGS: -D warnings
steps:
@@ -54,7 +55,7 @@ jobs:
- name: Install Node
uses: actions/setup-node@v2
with:
node-version: '16'
node-version: '18'
- name: Checkout repo
uses: actions/checkout@v2
@@ -62,6 +63,9 @@ jobs:
clean: false
submodules: 'recursive'
- name: Limit target directory size
run: script/clear-target-dir-if-larger-than 70
- name: Run check
run: cargo check --workspace
@@ -82,14 +86,13 @@ jobs:
runs-on:
- self-hosted
- bundle
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-build-dmg') }}
needs: tests
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
ZED_MIXPANEL_TOKEN: ${{ secrets.ZED_MIXPANEL_TOKEN }}
steps:
- name: Install Rust
run: |
@@ -102,7 +105,7 @@ jobs:
- name: Install Node
uses: actions/setup-node@v2
with:
node-version: '16'
node-version: '18'
- name: Checkout repo
uses: actions/checkout@v2
@@ -110,6 +113,9 @@ jobs:
clean: false
submodules: 'recursive'
- name: Limit target directory size
run: script/clear-target-dir-if-larger-than 70
- name: Determine version and release channel
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
@@ -141,11 +147,11 @@ jobs:
- name: Create app bundle
run: script/bundle
- name: Upload app bundle to workflow run if main branch
- name: Upload app bundle to workflow run if main branch or specifi label
uses: actions/upload-artifact@v2
if: ${{ github.ref == 'refs/heads/main' }}
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-build-dmg') }}
with:
name: Zed.dmg
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
path: target/release/Zed.dmg
- uses: softprops/action-gh-release@v1

43
.github/workflows/randomized_tests.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Randomized Tests
concurrency: randomized-tests
on:
push:
branches:
- randomized-tests-runner
# schedule:
# - cron: '0 * * * *'
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
ZED_SERVER_URL: https://zed.dev
ZED_CLIENT_SECRET_TOKEN: ${{ secrets.ZED_CLIENT_SECRET_TOKEN }}
jobs:
tests:
name: Run randomized tests
runs-on:
- self-hosted
- randomized-tests
steps:
- name: Install Rust
run: |
rustup set profile minimal
rustup update stable
- name: Install Node
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Checkout repo
uses: actions/checkout@v2
with:
clean: false
submodules: 'recursive'
- name: Run randomized tests
run: script/randomized-test-ci

View File

@@ -14,26 +14,10 @@ jobs:
content: |
📣 Zed ${{ github.event.release.tag_name }} was just released!
Restart your Zed or head to https://zed.dev/releases/latest to grab it.
Restart your Zed or head to https://zed.dev/releases/stable/latest to grab it.
```md
# Changelog
${{ github.event.release.body }}
```
mixpanel_release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10.5"
architecture: "x64"
cache: "pip"
- run: pip install -r script/mixpanel_release/requirements.txt
- run: >
python script/mixpanel_release/main.py
${{ github.event.release.tag_name }}
${{ secrets.MIXPANEL_PROJECT_ID }}
${{ secrets.MIXPANEL_SERVICE_ACCOUNT_USERNAME }}
${{ secrets.MIXPANEL_SERVICE_ACCOUNT_SECRET }}

2141
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
[workspace]
members = [
"crates/activity_indicator",
"crates/assets",
"crates/ai",
"crates/auto_update",
"crates/breadcrumbs",
"crates/call",
@@ -13,6 +13,8 @@ members = [
"crates/collections",
"crates/command_palette",
"crates/context_menu",
"crates/copilot",
"crates/copilot_button",
"crates/db",
"crates/diagnostics",
"crates/drag_and_drop",
@@ -30,11 +32,13 @@ members = [
"crates/journal",
"crates/language",
"crates/language_selector",
"crates/language_tools",
"crates/live_kit_client",
"crates/live_kit_server",
"crates/lsp",
"crates/media",
"crates/menu",
"crates/node_runtime",
"crates/outline",
"crates/picker",
"crates/plugin",
@@ -51,6 +55,7 @@ members = [
"crates/snippet",
"crates/sqlez",
"crates/sqlez_macros",
"crates/staff_mode",
"crates/sum_tree",
"crates/terminal",
"crates/text",
@@ -67,12 +72,37 @@ default-members = ["crates/zed"]
resolver = "2"
[workspace.dependencies]
anyhow = { version = "1.0.57" }
async-trait = { version = "0.1" }
ctor = { version = "0.1" }
env_logger = { version = "0.9" }
futures = { version = "0.3" }
globset = { version = "0.4" }
indoc = "1"
isahc = "1.7.2"
lazy_static = { version = "1.4.0" }
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
ordered-float = { version = "2.1.1" }
parking_lot = { version = "0.11.1" }
postage = { version = "0.5", features = ["futures-traits"] }
rand = { version = "0.8.5" }
regex = { version = "1.5" }
rust-embed = { version = "6.3", features = ["include-exclude"] }
schemars = { version = "0.8" }
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
rand = { version = "0.8" }
smallvec = { version = "1.6", features = ["union"] }
smol = { version = "1.2" }
tempdir = { version = "0.3.7" }
thiserror = { version = "1.0.29" }
time = { version = "0.3", features = ["serde", "serde-well-known"] }
toml = { version = "0.5" }
tree-sitter = "0.20"
unindent = { version = "0.1.7" }
[patch.crates-io]
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "c51896d32dcc11a38e41f36e3deb1a6a9c4f4b14" }
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "49226023693107fba9a1191136a4f47f38cdca73" }
async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" }
# TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457
@@ -87,3 +117,4 @@ split-debuginfo = "unpacked"
[profile.release]
debug = true
lto = "thin"

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.2
FROM rust:1.65-bullseye as builder
FROM rust:1.70-bullseye as builder
WORKDIR app
COPY . .

View File

@@ -2,7 +2,7 @@
[![CI](https://github.com/zed-industries/zed/actions/workflows/ci.yml/badge.svg)](https://github.com/zed-industries/zed/actions/workflows/ci.yml)
Welcome to Zed, a lightning-fast, collaborative code editor that makes your dreams come true.
Welcome to Zed, a lightning-fast, collaborative code editor that makes your dreams come true.
## Development tips
@@ -31,7 +31,8 @@ Welcome to Zed, a lightning-fast, collaborative code editor that makes your drea
* Set up a local `zed` database and seed it with some initial users:
Create a personal GitHub token to run `script/bootstrap` once successfully. Then delete that token.
Create a personal GitHub token to run `script/bootstrap` once successfully: the token needs to have an access to private repositories for the script to work (`repo` OAuth scope).
Then delete that token.
```
GITHUB_TOKEN=<$token> script/bootstrap

View File

@@ -0,0 +1,6 @@
User input begins on a line starting with /.
Don't apologize ever.
Never say "I apologize".
Use simple language and don't flatter the users.
Keep it short.
Risk being rude.

View File

@@ -0,0 +1,12 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.2926 3.48996C3.79162 3.79616 3.44871 4.26316 3.44871 4.93872C3.44871 5.75753 3.65302 6.19648 3.88658 6.43349C4.11948 6.66983 4.47018 6.79529 4.95638 6.79529C5.64158 6.79529 6.23176 6.65786 6.64548 6.37099C7.03216 6.10286 7.32149 5.66636 7.35698 4.91278C7.38386 4.34213 7.36863 3.96084 7.21748 3.68905C7.09721 3.47279 6.81682 3.2089 5.96976 3.11109C5.4731 3.05374 4.81346 3.17162 4.2926 3.48996ZM3.72539 2.5525C4.46348 2.10138 5.36842 1.93724 6.09436 2.02107C7.1336 2.14107 7.8142 2.51324 8.17039 3.15373C8.49569 3.73867 8.47238 4.43479 8.44743 4.96466C8.39736 6.02772 7.95809 6.7938 7.26541 7.27411C6.59976 7.73566 5.75982 7.89249 4.95638 7.89249C4.2936 7.89249 3.61755 7.71967 3.11095 7.20558C2.605 6.69216 2.35705 5.92853 2.35705 4.93872C2.35705 3.80566 2.96744 3.01576 3.72539 2.5525Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.69546 8.97734C7.02432 8.97734 7.29091 9.24528 7.29091 9.57581V10.8725C7.29091 11.203 7.02432 11.471 6.69546 11.471C6.3666 11.471 6.1 11.203 6.1 10.8725V9.57581C6.1 9.24528 6.3666 8.97734 6.69546 8.97734Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.45301 7.32072C2.56382 6.90477 2.81104 6.35118 3.40175 6.17048L3.74851 7.31556C3.74509 7.31822 3.73425 7.32798 3.71842 7.35038C3.68409 7.39897 3.64151 7.48723 3.6034 7.6303C3.52629 7.91973 3.49839 8.31081 3.4984 8.73318V10.8761C3.5122 10.9688 3.52011 11.0083 3.53501 11.0478C3.5474 11.0807 3.57295 11.1339 3.6523 11.2153C3.83266 11.4004 4.24428 11.6866 5.21016 12.1174C5.99398 12.467 6.35125 12.6243 6.68361 12.7078C6.99799 12.7869 7.30564 12.8031 7.99999 12.8031V14C7.31311 14 6.86876 13.9882 6.3946 13.869C5.95125 13.7575 5.49691 13.5549 4.78914 13.2391C4.76868 13.23 4.74801 13.2208 4.72712 13.2115C3.73729 12.77 3.14865 12.4092 2.80139 12.0527C2.61692 11.8634 2.49682 11.6721 2.42136 11.4719C2.35507 11.2961 2.33141 11.1302 2.31663 11.0266C2.31561 11.0194 2.31463 11.0126 2.31369 11.0061L2.30749 10.9632V8.73321C2.30748 8.28334 2.33457 7.76532 2.45301 7.32072Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.83439 7.54965C2.14812 7.21281 2.52306 6.88008 2.81315 6.70729L3.42031 7.737C3.27036 7.82631 2.98468 8.06607 2.7038 8.36764C2.43565 8.65553 2.2592 8.90729 2.19783 9.04784C2.18425 9.16608 2.18871 9.38528 2.22654 9.6452C2.26959 9.94104 2.33715 10.1608 2.37974 10.2387L2.42237 10.3167L2.44057 10.4038C2.46806 10.5353 2.60072 10.7284 2.96139 10.9852C3.24332 11.1859 3.57562 11.3661 3.93098 11.5588C4.00968 11.6015 4.0895 11.6448 4.17017 11.689C4.56251 11.8768 5.17152 12.1512 5.7408 12.3785C6.02948 12.4938 6.30016 12.5938 6.5233 12.664C6.63493 12.6991 6.72826 12.7247 6.802 12.7411C6.87402 12.7571 6.90715 12.7597 6.91166 12.76L6.91213 13.957C6.68654 13.957 6.40667 13.8815 6.16744 13.8062C5.90465 13.7235 5.60351 13.6116 5.30115 13.4909C4.69547 13.2491 4.05361 12.9594 3.64268 12.7623L3.62786 12.7552L3.61345 12.7473C3.54294 12.7085 3.46868 12.6683 3.39187 12.6268C3.03384 12.433 2.62042 12.2092 2.27302 11.9619C1.88328 11.6844 1.44476 11.2894 1.29544 10.735C1.17095 10.4701 1.09192 10.1191 1.04817 9.81844C0.999401 9.48332 0.975841 9.08189 1.03513 8.7778L1.04265 8.73927L1.05511 8.70206C1.18745 8.30673 1.53258 7.87368 1.83439 7.54965Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.59243 10.4347V8.41995H2.78334V10.4347H1.59243Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.7074 3.48996C12.2084 3.79616 12.5513 4.26316 12.5513 4.93872C12.5513 5.75753 12.347 6.19648 12.1134 6.43349C11.8805 6.66983 11.5298 6.79529 11.0436 6.79529C10.3584 6.79529 9.76824 6.65786 9.35452 6.37099C8.96784 6.10286 8.67851 5.66636 8.64302 4.91278C8.61614 4.34213 8.63137 3.96084 8.78252 3.68905C8.90279 3.47279 9.18318 3.2089 10.0302 3.11109C10.5269 3.05374 11.1865 3.17162 11.7074 3.48996ZM12.2746 2.5525C11.5365 2.10138 10.6316 1.93724 9.90564 2.02107C8.8664 2.14107 8.1858 2.51324 7.82961 3.15373C7.50431 3.73867 7.52762 4.43479 7.55258 4.96466C7.60264 6.02772 8.04191 6.7938 8.73459 7.27411C9.40024 7.73566 10.2402 7.89249 11.0436 7.89249C11.7064 7.89249 12.3824 7.71967 12.889 7.20558C13.395 6.69216 13.643 5.92853 13.643 4.93872C13.643 3.80566 13.0326 3.01576 12.2746 2.5525Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.30454 8.97734C8.97568 8.97734 8.70909 9.24528 8.70909 9.57581V10.8725C8.70909 11.203 8.97568 11.471 9.30454 11.471C9.6334 11.471 9.9 11.203 9.9 10.8725V9.57581C9.9 9.24528 9.6334 8.97734 9.30454 8.97734Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.547 7.32072C13.4362 6.90477 13.189 6.35118 12.5982 6.17048L12.2515 7.31556C12.2549 7.31822 12.2658 7.32798 12.2816 7.35038C12.3159 7.39897 12.3585 7.48723 12.3966 7.6303C12.4737 7.91973 12.5016 8.31081 12.5016 8.73318V10.8761C12.4878 10.9688 12.4799 11.0083 12.465 11.0478C12.4526 11.0807 12.427 11.1339 12.3477 11.2153C12.1673 11.4004 11.7557 11.6866 10.7898 12.1174C10.006 12.467 9.64875 12.6243 9.31639 12.7078C9.00201 12.7869 8.69433 12.8031 7.99999 12.8031V14C8.68686 14 9.13124 13.9882 9.6054 13.869C10.0488 13.7575 10.5031 13.5549 11.2109 13.2391C11.2313 13.23 11.252 13.2208 11.2729 13.2115C12.2627 12.77 12.8513 12.4092 13.1986 12.0527C13.3831 11.8634 13.5032 11.6721 13.5786 11.4719C13.6449 11.2961 13.6686 11.1302 13.6834 11.0266C13.6844 11.0194 13.6854 11.0126 13.6863 11.0061L13.6925 10.9632V8.73321C13.6925 8.28334 13.6654 7.76532 13.547 7.32072Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1656 7.54965C13.8519 7.21281 13.4769 6.88008 13.1868 6.70729L12.5797 7.737C12.7296 7.82631 13.0153 8.06607 13.2962 8.36764C13.5643 8.65553 13.7408 8.90729 13.8022 9.04784C13.8158 9.16608 13.8113 9.38528 13.7735 9.6452C13.7304 9.94104 13.6628 10.1608 13.6203 10.2387L13.5776 10.3167L13.5594 10.4038C13.5319 10.5353 13.3993 10.7284 13.0386 10.9852C12.7567 11.1859 12.4244 11.3661 12.069 11.5588C11.9903 11.6015 11.9105 11.6448 11.8298 11.689C11.4375 11.8768 10.8285 12.1512 10.2592 12.3785C9.97052 12.4938 9.69984 12.5938 9.4767 12.664C9.36507 12.6991 9.27174 12.7247 9.198 12.7411C9.12598 12.7571 9.09285 12.7597 9.08834 12.76L9.08787 13.957C9.31345 13.957 9.59333 13.8815 9.83256 13.8062C10.0953 13.7235 10.3965 13.6116 10.6989 13.4909C11.3045 13.2491 11.9464 12.9594 12.3573 12.7623L12.3721 12.7552L12.3865 12.7473C12.4571 12.7085 12.5313 12.6683 12.6081 12.6268C12.9662 12.433 13.3796 12.2092 13.727 11.9619C14.1167 11.6844 14.5552 11.2894 14.7046 10.735C14.829 10.4701 14.9081 10.1191 14.9518 9.81844C15.0006 9.48332 15.0242 9.08189 14.9649 8.7778L14.9574 8.73927L14.9449 8.70206C14.8126 8.30673 14.4674 7.87368 14.1656 7.54965Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4076 10.4347V8.41995H13.2167V10.4347H14.4076Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.5">
<path d="M2.38084 5.44737C2.42754 5.92437 2.54311 6.33779 2.72903 6.68417C2.70043 6.72678 2.67414 6.77043 2.64995 6.81463C2.39071 6.9994 2.09192 7.27314 1.83439 7.54965C1.53258 7.87368 1.18745 8.30673 1.05511 8.70206L1.04265 8.73927L1.03513 8.7778C0.975841 9.08189 0.999401 9.48332 1.04817 9.81844C1.09192 10.1191 1.17095 10.4701 1.29544 10.735C1.44476 11.2894 1.88328 11.6844 2.27302 11.9619C2.6204 12.2092 3.03378 12.4329 3.39179 12.6267C3.4686 12.6683 3.54294 12.7085 3.61345 12.7473L3.62786 12.7552L3.64268 12.7623C4.05361 12.9594 4.69547 13.2491 5.30115 13.4909C5.60351 13.6116 5.90465 13.7235 6.16744 13.8062C6.39236 13.877 6.6532 13.948 6.87108 13.9562C7.19351 13.9948 7.54309 14 7.99999 14C8.45688 14 8.80648 13.9948 9.12892 13.9562C9.34679 13.948 9.60764 13.877 9.83256 13.8062C10.0953 13.7235 10.3965 13.6116 10.6989 13.4909C11.0041 13.369 11.3186 13.235 11.6081 13.1067L10.5467 12.2257C9.92791 12.5006 9.61228 12.6334 9.31639 12.7078C9.00201 12.7869 8.69433 12.8031 7.99999 12.8031C7.30564 12.8031 6.99799 12.7869 6.68361 12.7078C6.35125 12.6243 5.99398 12.467 5.21016 12.1174C4.24428 11.6866 3.83266 11.4004 3.6523 11.2153C3.57295 11.1339 3.5474 11.0807 3.53501 11.0478C3.52011 11.0083 3.5122 10.9688 3.4984 10.8761V8.73318C3.49839 8.31081 3.52629 7.91973 3.6034 7.6303C3.60757 7.61463 3.6118 7.59961 3.61607 7.58523C4.02831 7.80894 4.49555 7.89249 4.95638 7.89249C5.07488 7.89249 5.19417 7.88908 5.31358 7.88178L2.38084 5.44737Z" fill="white"/>
<path d="M6.63684 8.9802C6.3355 9.00979 6.1 9.26516 6.1 9.57581V10.8725C6.1 11.203 6.3666 11.471 6.69546 11.471C7.02432 11.471 7.29091 11.203 7.29091 10.8725V9.57581C7.29091 9.55736 7.29008 9.53911 7.28846 9.52109L6.63684 8.9802Z" fill="white"/>
<path d="M8.70909 10.7003V10.8725C8.70909 11.203 8.97568 11.471 9.30454 11.471C9.39795 11.471 9.48633 11.4493 9.56501 11.4108L8.70909 10.7003Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.09436 2.02107C5.38898 1.93962 4.51459 2.09228 3.78849 2.51486L4.71538 3.28426C5.1409 3.1227 5.6004 3.06844 5.96976 3.11109C6.81682 3.2089 7.09721 3.4728 7.21748 3.68905C7.36863 3.96084 7.38386 4.34213 7.35698 4.91278C7.34816 5.1 7.32368 5.26765 7.28592 5.41801L10.1885 7.82737C10.4719 7.87295 10.76 7.89249 11.0436 7.89249C11.5044 7.89249 11.9717 7.80894 12.3839 7.58523C12.3882 7.59961 12.3924 7.61463 12.3966 7.6303C12.4737 7.91973 12.5016 8.31081 12.5016 8.73318V9.74745L14.4065 11.3287C14.5379 11.1547 14.6446 10.9577 14.7046 10.735C14.829 10.4701 14.9081 10.1191 14.9518 9.81844C15.0006 9.48332 15.0242 9.08189 14.9649 8.7778L14.9574 8.73927L14.9449 8.70206C14.8126 8.30673 14.4674 7.87368 14.1656 7.54965C13.9081 7.27314 13.6093 6.9994 13.35 6.81463C13.3259 6.77043 13.2996 6.72678 13.271 6.68417C13.5201 6.21998 13.643 5.63537 13.643 4.93872C13.643 3.80567 13.0326 3.01576 12.2746 2.5525C11.5365 2.10138 10.6316 1.93724 9.90564 2.02107C9.01315 2.12413 8.38516 2.41316 8 2.89841C7.61484 2.41316 6.98685 2.12413 6.09436 2.02107ZM11.7074 3.48996C12.2084 3.79616 12.5513 4.26316 12.5513 4.93872C12.5513 5.75753 12.347 6.19648 12.1134 6.43349C11.8805 6.66983 11.5298 6.79529 11.0436 6.79529C10.3584 6.79529 9.76824 6.65786 9.35452 6.37099C8.96784 6.10286 8.67851 5.66636 8.64302 4.91278C8.61614 4.34213 8.63137 3.96084 8.78252 3.68905C8.90279 3.4728 9.18318 3.2089 10.0302 3.11109C10.5269 3.05374 11.1865 3.17162 11.7074 3.48996Z" fill="white"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1225 13.809C14.0341 13.9146 13.877 13.9289 13.7711 13.8409L1.1931 3.40021C1.08658 3.31178 1.0722 3.15362 1.16103 3.04743L1.87751 2.19101C1.96587 2.0854 2.12299 2.07112 2.22894 2.15906L14.8069 12.5998C14.9134 12.6882 14.9278 12.8464 14.839 12.9526L14.1225 13.809Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.5">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.09436 2.02107C5.36842 1.93724 4.46348 2.10138 3.72539 2.5525C2.96744 3.01576 2.35705 3.80567 2.35705 4.93872C2.35705 5.63537 2.47988 6.21998 2.72903 6.68417C2.70043 6.72678 2.67414 6.77043 2.64995 6.81463C2.39071 6.9994 2.09192 7.27314 1.83439 7.54965C1.53258 7.87368 1.18745 8.30673 1.05511 8.70206L1.04265 8.73927L1.03513 8.7778C0.975841 9.08189 0.999401 9.48332 1.04817 9.81844C1.09192 10.1191 1.17095 10.4701 1.29544 10.735C1.44476 11.2894 1.88328 11.6844 2.27302 11.9619C2.6204 12.2092 3.03378 12.4329 3.39179 12.6267C3.4686 12.6683 3.54294 12.7085 3.61345 12.7473L3.62786 12.7552L3.64268 12.7623C4.05361 12.9594 4.69547 13.2491 5.30115 13.4909C5.60351 13.6116 5.90465 13.7235 6.16744 13.8062C6.39236 13.877 6.6532 13.948 6.87108 13.9562C7.19351 13.9948 7.54309 14 7.99999 14C8.01293 14 8.02579 14 8.03857 14C7.97904 13.903 7.99191 13.7743 8.07655 13.6911L9.0197 12.7639C8.77857 12.7952 8.48273 12.8031 7.99999 12.8031C7.30564 12.8031 6.99799 12.7869 6.68361 12.7078C6.35125 12.6243 5.99398 12.467 5.21016 12.1174C4.24428 11.6866 3.83266 11.4004 3.6523 11.2153C3.57295 11.1339 3.5474 11.0807 3.53501 11.0478C3.52011 11.0083 3.5122 10.9688 3.4984 10.8761V8.73318C3.49839 8.31081 3.52629 7.91973 3.6034 7.6303C3.60757 7.61463 3.6118 7.59961 3.61607 7.58523C4.02831 7.80894 4.49555 7.89249 4.95638 7.89249C5.75982 7.89249 6.59976 7.73566 7.26541 7.27411C7.55937 7.07027 7.8077 6.81497 8 6.50734C8.1923 6.81497 8.44063 7.07027 8.73459 7.27411C9.40024 7.73566 10.2402 7.89249 11.0436 7.89249C11.5044 7.89249 11.9717 7.80894 12.3839 7.58523C12.3882 7.59961 12.3924 7.61463 12.3966 7.6303C12.4737 7.91973 12.5016 8.31081 12.5016 8.73318V9.34082L14.1266 7.7433C14.169 7.70159 14.2225 7.67811 14.2775 7.67276C14.2398 7.63028 14.2024 7.58915 14.1656 7.54965C13.9081 7.27314 13.6093 6.9994 13.35 6.81463C13.3259 6.77043 13.2996 6.72678 13.271 6.68417C13.5201 6.21998 13.643 5.63537 13.643 4.93872C13.643 3.80567 13.0326 3.01576 12.2746 2.5525C11.5365 2.10138 10.6316 1.93724 9.90564 2.02107C9.01315 2.12413 8.38516 2.41316 8 2.89841C7.61484 2.41316 6.98685 2.12413 6.09436 2.02107ZM3.44871 4.93872C3.44871 4.26316 3.79162 3.79616 4.2926 3.48996C4.81346 3.17162 5.4731 3.05374 5.96976 3.11109C6.81682 3.2089 7.09721 3.4728 7.21748 3.68905C7.36863 3.96084 7.38386 4.34213 7.35698 4.91278C7.32149 5.66636 7.03216 6.10286 6.64548 6.37099C6.23176 6.65786 5.64158 6.79529 4.95638 6.79529C4.47018 6.79529 4.11948 6.66983 3.88658 6.43349C3.65302 6.19648 3.44871 5.75753 3.44871 4.93872ZM12.5513 4.93872C12.5513 4.26316 12.2084 3.79616 11.7074 3.48996C11.1865 3.17162 10.5269 3.05374 10.0302 3.11109C9.18318 3.2089 8.90279 3.4728 8.78252 3.68905C8.63137 3.96084 8.61614 4.34213 8.64302 4.91278C8.67851 5.66636 8.96784 6.10286 9.35452 6.37099C9.76824 6.65786 10.3584 6.79529 11.0436 6.79529C11.5298 6.79529 11.8805 6.66983 12.1134 6.43349C12.347 6.19648 12.5513 5.75753 12.5513 4.93872Z" fill="white"/>
<path d="M7.29091 9.57581C7.29091 9.24528 7.02432 8.97734 6.69546 8.97734C6.3666 8.97734 6.1 9.24528 6.1 9.57581V10.8725C6.1 11.203 6.3666 11.471 6.69546 11.471C7.02432 11.471 7.29091 11.203 7.29091 10.8725V9.57581Z" fill="white"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.6668 14.9102C13.7644 15.0078 13.9227 15.0078 14.0203 14.9102L14.908 14.0224C15.0056 13.9248 15.0056 13.7665 14.908 13.6688L13.2229 11.9836L14.908 10.2983C15.0057 10.2007 15.0057 10.0424 14.908 9.94474L14.0203 9.05695C13.9227 8.95931 13.7644 8.95931 13.6668 9.05695L11.9817 10.7422L10.2966 9.05693C10.199 8.95929 10.0407 8.95929 9.94306 9.05693L9.05535 9.94473C8.95773 10.0424 8.95773 10.2007 9.05535 10.2983L10.7405 11.9836L9.05537 13.6688C8.95775 13.7665 8.95775 13.9248 9.05537 14.0224L9.94308 14.9102C10.0407 15.0079 10.199 15.0079 10.2966 14.9102L11.9817 13.225L13.6668 14.9102Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd" d="M3.44872 4.93872C3.44872 4.26316 3.79163 3.79616 4.29261 3.48996C4.81346 3.17162 5.47311 3.05374 5.96976 3.11109C6.81683 3.2089 7.09722 3.4728 7.21749 3.68905C7.36864 3.96084 7.38387 4.34213 7.35699 4.91278C7.3215 5.66636 7.03217 6.10286 6.64549 6.37099C6.23177 6.65786 5.64159 6.79529 4.95639 6.79529C4.47019 6.79529 4.11949 6.66983 3.88658 6.43349C3.65303 6.19648 3.44872 5.75753 3.44872 4.93872ZM6.09437 2.02107C5.36843 1.93724 4.46349 2.10138 3.7254 2.5525C2.96745 3.01576 2.35706 3.80567 2.35706 4.93872C2.35706 5.63537 2.47988 6.21998 2.72904 6.68417C2.70044 6.72678 2.67415 6.77043 2.64996 6.81463C2.39072 6.9994 2.09193 7.27314 1.83439 7.54965C1.53259 7.87368 1.18745 8.30673 1.05511 8.70206L1.04266 8.73927L1.03514 8.7778C0.975849 9.08189 0.999409 9.48332 1.04818 9.81844C1.09193 10.1191 1.17096 10.4701 1.29545 10.735C1.44476 11.2894 1.88329 11.6844 2.27303 11.9619C2.6204 12.2092 3.03379 12.4329 3.3918 12.6267L3.39183 12.6267L3.39185 12.6267L3.39188 12.6268C3.46869 12.6683 3.54295 12.7085 3.61346 12.7473L3.62787 12.7552L3.64269 12.7623C4.05362 12.9594 4.69548 13.2491 5.30115 13.4909C5.60352 13.6116 5.90466 13.7235 6.16745 13.8062C6.39237 13.877 6.65321 13.948 6.87108 13.9562C7.19351 13.9948 7.5431 14 8 14C8.45052 14 8.79672 13.9949 9.11543 13.9578C9.04001 13.6509 9.00001 13.3301 9.00001 13C9.00001 12.9213 9.00229 12.8431 9.00677 12.7656C8.76798 12.7955 8.47414 12.8031 8 12.8031C7.30565 12.8031 6.998 12.7869 6.68362 12.7078C6.35125 12.6243 5.99399 12.467 5.21017 12.1174C4.24429 11.6866 3.83267 11.4004 3.6523 11.2153C3.57296 11.1339 3.54741 11.0807 3.53502 11.0478C3.52011 11.0083 3.51221 10.9688 3.4984 10.8761V8.73318C3.49839 8.31081 3.5263 7.91973 3.6034 7.6303C3.60758 7.61463 3.61181 7.59961 3.61608 7.58523C4.02832 7.80894 4.49556 7.89249 4.95639 7.89249C5.75982 7.89249 6.59977 7.73566 7.26541 7.27411C7.55938 7.07027 7.8077 6.81497 8.00001 6.50734C8.19231 6.81497 8.44064 7.07027 8.7346 7.27411C9.40025 7.73566 10.2402 7.89249 11.0436 7.89249C11.5045 7.89249 11.9717 7.80894 12.3839 7.58523C12.3882 7.59961 12.3924 7.61463 12.3966 7.6303C12.4737 7.91973 12.5016 8.31081 12.5016 8.73318V9.03072C12.6649 9.01043 12.8312 8.99997 13 8.99997C13.7226 8.99997 14.4004 9.19157 14.9855 9.52673C15.0073 9.26739 15.0077 8.99725 14.9649 8.7778L14.9574 8.73927L14.9449 8.70206C14.8126 8.30673 14.4674 7.87368 14.1656 7.54965C13.9081 7.27314 13.6093 6.9994 13.3501 6.81463C13.3259 6.77043 13.2996 6.72678 13.271 6.68417C13.5201 6.21998 13.643 5.63537 13.643 4.93872C13.643 3.80567 13.0326 3.01576 12.2746 2.5525C11.5365 2.10138 10.6316 1.93724 9.90565 2.02107C9.01315 2.12413 8.38517 2.41316 8.00001 2.89841C7.61485 2.41316 6.98686 2.12413 6.09437 2.02107ZM9.9 10.4719V9.57581C9.9 9.24528 9.63341 8.97734 9.30455 8.97734C8.97569 8.97734 8.7091 9.24528 8.7091 9.57581V10.8725C8.7091 11.2024 8.97466 11.4699 9.30265 11.471C9.45294 11.1079 9.65515 10.7718 9.9 10.4719ZM7.29092 9.57581C7.29092 9.24528 7.02433 8.97734 6.69547 8.97734C6.36661 8.97734 6.10001 9.24528 6.10001 9.57581V10.8725C6.10001 11.203 6.36661 11.471 6.69547 11.471C7.02433 11.471 7.29092 11.203 7.29092 10.8725V9.57581ZM12.5513 4.93872C12.5513 4.26316 12.2084 3.79616 11.7074 3.48996C11.1866 3.17162 10.5269 3.05374 10.0303 3.11109C9.18318 3.2089 8.90279 3.4728 8.78253 3.68905C8.63138 3.96084 8.61615 4.34213 8.64303 4.91278C8.67852 5.66636 8.96785 6.10286 9.35453 6.37099C9.76825 6.65786 10.3584 6.79529 11.0436 6.79529C11.5298 6.79529 11.8805 6.66983 12.1134 6.43349C12.347 6.19648 12.5513 5.75753 12.5513 4.93872Z" fill="white"/>
<circle cx="13" cy="13" r="3" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9083 3.19699L7.99999 10.3949L0.0916311 3.1969C0.346537 2.49164 1.10447 1.98018 2 1.98018H14C14.8943 1.98018 15.653 2.49168 15.9083 3.19699ZM16 4.7153L12.1526 8.21715L16 11.688V4.7153ZM8.52024 11.5232L11.4199 8.88404L15.9081 12.933C15.6528 13.6378 14.8941 14.1501 14 14.1501H2C1.10461 14.1501 0.346779 13.6378 0.0917535 12.9331L4.58012 8.88404L7.47975 11.5232L7.99999 11.9967L8.52024 11.5232ZM3.84742 8.21715L0 4.71532V11.688L3.84742 8.21715Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 614 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1.24em" height="1em" viewBox="0 0 256 208"><path d="M205.28 31.36c14.096 14.88 20.016 35.2 22.512 63.68c6.626 0 12.805 1.47 16.976 7.152l7.792 10.56A17.548 17.548 0 0 1 256 123.2v28.688c-.008 3.704-1.843 7.315-4.832 9.504C215.885 187.222 172.35 208 128 208c-49.066 0-98.19-28.273-123.168-46.608c-2.989-2.189-4.825-5.8-4.832-9.504V123.2c0-3.776 1.2-7.424 3.424-10.464l7.792-10.544c4.173-5.657 10.38-7.152 16.992-7.152c2.496-28.48 8.4-48.8 22.512-63.68C77.331 3.165 112.567.06 127.552 0H128c14.72 0 50.4 2.88 77.28 31.36Zm-77.264 47.376c-3.04 0-6.544.176-10.272.544c-1.312 4.896-3.248 9.312-6.08 12.128c-11.2 11.2-24.704 12.928-31.936 12.928c-6.802 0-13.927-1.42-19.744-5.088c-5.502 1.808-10.786 4.415-11.136 10.912c-.586 12.28-.637 24.55-.688 36.824c-.026 6.16-.05 12.322-.144 18.488c.024 3.579 2.182 6.903 5.44 8.384C79.936 185.92 104.976 192 128.016 192c23.008 0 48.048-6.08 74.512-18.144c3.258-1.48 5.415-4.805 5.44-8.384c.317-18.418.062-36.912-.816-55.312h.016c-.342-6.534-5.648-9.098-11.168-10.912c-5.82 3.652-12.927 5.088-19.728 5.088c-7.232 0-20.72-1.728-31.936-12.928c-2.832-2.816-4.768-7.232-6.08-12.128a106.26 106.26 0 0 0-10.24-.544Zm-26.941 43.93c5.748 0 10.408 4.66 10.408 10.409v19.183c0 5.749-4.66 10.409-10.408 10.409c-5.748 0-10.408-4.66-10.408-10.409v-19.183c0-5.748 4.66-10.408 10.408-10.408Zm53.333 0c5.749 0 10.409 4.66 10.409 10.409v19.183c0 5.749-4.66 10.409-10.409 10.409c-5.748 0-10.408-4.66-10.408-10.409v-19.183c0-5.748 4.66-10.408 10.408-10.408ZM81.44 28.32c-11.2 1.12-20.64 4.8-25.44 9.92c-10.4 11.36-8.16 40.16-2.24 46.24c4.32 4.32 12.48 7.2 21.28 7.2c6.72 0 19.52-1.44 30.08-12.16c4.64-4.48 7.52-15.68 7.2-27.04c-.32-9.12-2.88-16.64-6.72-19.84c-4.16-3.68-13.6-5.28-24.16-4.32Zm68.96 4.32c-3.84 3.2-6.4 10.72-6.72 19.84c-.32 11.36 2.56 22.56 7.2 27.04c10.56 10.72 23.36 12.16 30.08 12.16c8.8 0 16.96-2.88 21.28-7.2c5.92-6.08 8.16-34.88-2.24-46.24c-4.8-5.12-14.24-8.8-25.44-9.92c-10.56-.96-20 .64-24.16 4.32ZM128 56c-2.56 0-5.6.16-8.96.48c.32 1.76.48 3.68.64 5.76c0 1.44 0 2.88-.16 4.48c3.2-.32 5.92-.32 8.48-.32c2.56 0 5.28 0 8.48.32c-.16-1.6-.16-3.04-.16-4.48c.16-2.08.32-4 .64-5.76c-3.36-.32-6.4-.48-8.96-.48Z"/></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,5 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 1H7.5H8.75C8.88807 1 9 1.11193 9 1.25V4.5" stroke="#838994" stroke-linecap="round"/>
<path d="M3.64645 5.64645C3.45118 5.84171 3.45118 6.15829 3.64645 6.35355C3.84171 6.54882 4.15829 6.54882 4.35355 6.35355L3.64645 5.64645ZM8.64645 0.646447L3.64645 5.64645L4.35355 6.35355L9.35355 1.35355L8.64645 0.646447Z" fill="#838994"/>
<path d="M7.5 6.5V9C7.5 9.27614 7.27614 9.5 7 9.5H1C0.723858 9.5 0.5 9.27614 0.5 9V3C0.5 2.72386 0.723858 2.5 1 2.5H3.5" stroke="#838994" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 605 B

View File

@@ -0,0 +1,4 @@
<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.5 4C2.5 2.89531 3.39688 2 4.5 2H9.5C10.6031 2 11.5 2.89531 11.5 4V8C11.5 9.10312 10.6031 10 9.5 10H4.5C3.39688 10 2.5 9.10312 2.5 8V4ZM5 4C4.44687 4 4 4.44687 4 5C4 5.55313 4.44687 6 5 6C5.55313 6 6 5.55313 6 5C6 4.44687 5.55313 4 5 4ZM9 6C9.55313 6 10 5.55313 10 5C10 4.44687 9.55313 4 9 4C8.44687 4 8 4.44687 8 5C8 5.55313 8.44687 6 9 6ZM5 8.5C5.275 8.5 5.5 8.275 5.5 8C5.5 7.725 5.275 7.5 5 7.5C4.725 7.5 4.5 7.725 4.5 8C4.5 8.275 4.725 8.5 5 8.5ZM7 7.5C6.725 7.5 6.5 7.725 6.5 8C6.5 8.275 6.725 8.5 7 8.5C7.275 8.5 7.5 8.275 7.5 8C7.5 7.725 7.275 7.5 7 7.5ZM9 8.5C9.275 8.5 9.5 8.275 9.5 8C9.5 7.725 9.275 7.5 9 7.5C8.725 7.5 8.5 7.725 8.5 8C8.5 8.275 8.725 8.5 9 8.5ZM0 14C0 12.3156 1.34312 11 3 11H11C12.6562 11 14 12.3156 14 14V15C14 15.5531 13.5531 16 13 16H11V14C11 13.4469 10.5531 13 10 13H4C3.44687 13 3 13.4469 3 14V16H1C0.447812 16 0 15.5531 0 15V14Z" fill="#808080"/>
<path d="M7.5 2H6.5V0.5C6.5 0.22375 6.725 0 7 0C7.275 0 7.5 0.22375 7.5 0.5V2ZM1.5 4.5V7.5C1.5 7.775 1.27625 8 1 8C0.72375 8 0.5 7.775 0.5 7.5V4.5C0.5 4.225 0.72375 4 1 4C1.27625 4 1.5 4.225 1.5 4.5ZM5.5 16H4.5V14.5C4.5 14.225 4.725 14 5 14C5.275 14 5.5 14.225 5.5 14.5V16ZM7.5 16H6.5V14.5C6.5 14.225 6.725 14 7 14C7.275 14 7.5 14.225 7.5 14.5V16ZM9 14C9.275 14 9.5 14.225 9.5 14.5V16H8.5V14.5C8.5 14.225 8.725 14 9 14ZM13.5 7.5C13.5 7.775 13.275 8 13 8C12.725 8 12.5 7.775 12.5 7.5V4.5C12.5 4.225 12.725 4 13 4C13.275 4 13.5 4.225 13.5 4.5V7.5Z" fill="#808080"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,3 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6667 0.400196H1.33346C0.819658 0.400196 0.399658 0.820196 0.399658 1.3326V10.6658C0.399658 11.181 0.816998 11.5982 1.33206 11.5982C1.58966 11.5982 1.82206 11.4932 1.99146 11.3238L4.51706 8.79684H10.6639C11.1763 8.79684 11.5963 8.37544 11.5963 7.86304V1.3298C11.5963 0.815996 11.1749 0.395996 10.6625 0.395996L10.6667 0.400196ZM2.2667 2.2664H6.00008V3.1988H2.26628V2.265L2.2667 2.2664ZM7.8667 6.93316H2.2667V5.99936H7.8667V6.93176V6.93316ZM9.7329 5.06556H2.26488V4.13176H9.73164V5.06416L9.7329 5.06556Z" fill="#282C34"/>
<svg width="12" height="11" viewBox="0 0 12 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.01077 0.000234794C2.69085 0.000234794 0.000639074 2.18612 0.000639074 4.88385C0.000639074 6.0491 0.501914 7.11387 1.33823 7.95254C1.04475 9.13517 0.0640321 10.1894 0.0522927 10.2011C-0.00053487 10.2539 -0.0153266 10.3356 0.0170743 10.4061C0.0464229 10.4763 0.111459 10.5185 0.187766 10.5185C1.74324 10.5185 2.89019 9.77286 3.4889 9.31197C4.25431 9.60052 5.10894 9.76722 6.01053 9.76722C9.33045 9.76722 12 7.58063 12 4.88361C12 2.18659 9.33045 0 6.01053 0L6.01077 0.000234794Z" fill="#FAFAFA"/>
</svg>

Before

Width:  |  Height:  |  Size: 636 B

After

Width:  |  Height:  |  Size: 609 B

View File

@@ -1,3 +1,5 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.2 6.00001C5.52563 6.00001 6.6 4.92545 6.6 3.60001C6.6 2.27457 5.52563 1.20001 4.2 1.20001C2.87438 1.20001 1.8 2.27457 1.8 3.60001C1.8 4.92545 2.87438 6.00001 4.2 6.00001ZM5.15063 6.90001H3.24938C1.45519 6.90001 0 8.35501 0 10.1494C0 10.5094 0.291 10.8 0.649875 10.8H7.7505C8.10938 10.8 8.4 10.5094 8.4 10.1494C8.4 8.35501 6.945 6.90001 5.15063 6.90001ZM11.55 4.95001H10.65V4.05001C10.65 3.80251 10.4494 3.60001 10.2 3.60001C9.95063 3.60001 9.75 3.80157 9.75 4.05001V4.95001H8.85C8.6025 4.95001 8.4 5.15251 8.4 5.40001C8.4 5.64751 8.60156 5.85001 8.85 5.85001H9.75V6.75001C9.75 6.99939 9.9525 7.20001 10.2 7.20001C10.4475 7.20001 10.65 6.99845 10.65 6.75001V5.85001H11.55C11.7994 5.85001 12 5.64939 12 5.40001C12 5.15064 11.7994 4.95001 11.55 4.95001Z" fill="white"/>
<path d="M5.75062 7.09998H3.24938C1.45519 7.09998 0 8.55498 0 10.3493C0 10.7093 0.291 11 0.649875 11H8.3505C8.70938 11 9 10.7093 9 10.3493C9 8.55498 7.545 7.09998 5.75062 7.09998Z" fill="white"/>
<path d="M7 3.5C7 4.82544 5.82562 6 4.5 6C3.17438 6 2 4.82544 2 3.5C2 2.17456 3.17438 1 4.5 1C5.82562 1 7 2.17456 7 3.5Z" fill="white"/>
<path d="M9.5 3.75V5.5M9.5 7.25V5.5M9.5 5.5H11.25M9.5 5.5H7.75" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 882 B

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -1,3 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.9 8.00002C7.44656 8.00002 8.7 6.74637 8.7 5.20002C8.7 3.65368 7.44656 2.40002 5.9 2.40002C4.35344 2.40002 3.1 3.65368 3.1 5.20002C3.1 6.74637 4.35344 8.00002 5.9 8.00002ZM7.00906 9.05002H4.79094C2.69772 9.05002 1 10.7475 1 12.841C1 13.261 1.3395 13.6 1.75819 13.6H10.0422C10.4609 13.6 10.8 13.261 10.8 12.841C10.8 10.7475 9.1025 9.05002 7.00906 9.05002ZM14.475 6.77502H13.425V5.72502C13.425 5.43627 13.1909 5.20002 12.9 5.20002C12.6091 5.20002 12.375 5.43518 12.375 5.72502V6.77502H11.325C11.0363 6.77502 10.8 7.01127 10.8 7.30002C10.8 7.58877 11.0352 7.82502 11.325 7.82502H12.375V8.87502C12.375 9.16596 12.6112 9.40002 12.9 9.40002C13.1887 9.40002 13.425 9.16487 13.425 8.87502V7.82502H14.475C14.7659 7.82502 15 7.59096 15 7.30002C15 7.00909 14.7659 6.77502 14.475 6.77502Z" fill="white"/>
<path d="M7.00906 8.99999H4.79094C2.69772 8.99999 1 11.1475 1 13.2409C1 13.6609 1.3395 14 1.75819 14H10.0422C10.4609 14 10.8 13.6609 10.8 13.2409C10.8 11.1475 9.1025 8.99999 7.00906 8.99999Z" fill="white"/>
<path d="M9 5C9 6.54634 7.44657 7.99998 5.90001 7.99998C4.35344 7.99998 3 6.54634 3 5C3 3.45366 4.45344 2 6 2C7.54656 2 9 3.45366 9 5Z" fill="white"/>
<path d="M13.025 6H14.475C14.7659 6 15 6.20906 15 6.5C15 6.79094 14.7659 7 14.475 7H13V8.49995C13 8.7898 12.7638 9.02495 12.475 9.02495C12.1863 9.02495 11.95 8.79089 11.95 8.49995V7H10.525C10.2352 7 10 6.78875 10 6.5C10 6.21125 10.2362 6 10.525 6H11.975V4.525C11.975 4.23516 12.2091 4 12.5 4C12.7909 4 13.025 4.23625 13.025 4.525V6Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 810 B

View File

@@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.75 1.875C4.75 2.71406 4.19922 3.42422 3.4375 3.66328V5.97891C3.9086 5.64609 4.4711 5.4375 5.125 5.4375H7.375C8.30782 5.4375 9.0625 4.68281 9.0625 3.75V3.66328C8.30078 3.42422 7.75 2.71406 7.75 1.875C7.75 0.839531 8.58907 0 9.625 0C10.6609 0 11.5 0.839531 11.5 1.875C11.5 2.71406 10.9492 3.42422 10.1875 3.66328V3.75C10.1875 5.30391 8.92891 6.5625 7.375 6.5625H5.125C4.19219 6.5625 3.4375 7.31719 3.4375 8.25V8.33672C4.19922 8.57578 4.75 9.28594 4.75 10.125C4.75 11.1609 3.91094 12 2.875 12C1.83953 12 1 11.1609 1 10.125C1 9.28594 1.55172 8.57578 2.3125 8.33672V3.66328C1.55172 3.42422 1 2.71406 1 1.875C1 0.839531 1.83953 0 2.875 0C3.91094 0 4.75 0.839531 4.75 1.875ZM2.875 2.625C3.28914 2.625 3.625 2.28914 3.625 1.875C3.625 1.46086 3.28914 1.125 2.875 1.125C2.46086 1.125 2.125 1.46086 2.125 1.875C2.125 2.28914 2.46086 2.625 2.875 2.625ZM9.625 1.125C9.21016 1.125 8.875 1.46086 8.875 1.875C8.875 2.28914 9.21016 2.625 9.625 2.625C10.0398 2.625 10.375 2.28914 10.375 1.875C10.375 1.46086 10.0398 1.125 9.625 1.125ZM2.875 10.875C3.28914 10.875 3.625 10.5398 3.625 10.125C3.625 9.71016 3.28914 9.375 2.875 9.375C2.46086 9.375 2.125 9.71016 2.125 10.125C2.125 10.5398 2.46086 10.875 2.875 10.875Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,14 @@
<svg width="93" height="32" viewBox="0 0 93 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.03996 7.04962C8.00936 7.67635 7.30396 8.63219 7.30396 10.0149C7.30396 11.6908 7.72425 12.5893 8.2047 13.0744C8.68381 13.5581 9.40526 13.8149 10.4054 13.8149C11.815 13.8149 13.0291 13.5336 13.8802 12.9464C14.6756 12.3977 15.2708 11.5042 15.3438 9.96182C15.3991 8.79382 15.3678 8.01341 15.0568 7.45711C14.8094 7.01449 14.2326 6.47436 12.4901 6.27416C11.4684 6.15678 10.1114 6.39804 9.03996 7.04962ZM7.87312 5.13084C9.39147 4.2075 11.2531 3.87155 12.7464 4.04312C14.8843 4.28874 16.2844 5.05049 17.0171 6.36142C17.6863 7.55867 17.6384 8.98348 17.587 10.068C17.484 12.2439 16.5804 13.8118 15.1554 14.7949C13.7861 15.7396 12.0582 16.0606 10.4054 16.0606C9.04201 16.0606 7.65128 15.7069 6.60913 14.6547C5.56832 13.6038 5.05825 12.0408 5.05825 10.0149C5.05825 7.6958 6.3139 6.07903 7.87312 5.13084Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.983 18.2811C14.6595 18.2811 15.2079 18.8295 15.2079 19.506V22.16C15.2079 22.8365 14.6595 23.385 13.983 23.385C13.3065 23.385 12.758 22.8365 12.758 22.16V19.506C12.758 18.8295 13.3065 18.2811 13.983 18.2811Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.25566 14.8903C5.48361 14.039 5.99218 12.9059 7.20734 12.5361L7.92068 14.8798C7.92068 14.8798 7.91996 14.8801 7.92068 14.8798L7.92375 14.8785C7.92411 14.8783 7.92375 14.8785 7.92375 14.8785C7.92374 14.8785 7.92322 14.8778 7.92068 14.8798C7.91364 14.8852 7.89133 14.9052 7.85878 14.951C7.78816 15.0505 7.70057 15.2311 7.62216 15.524C7.46354 16.1164 7.40614 16.9168 7.40616 17.7813V22.1675C7.43456 22.3571 7.45082 22.438 7.48148 22.5189C7.50697 22.5862 7.55954 22.695 7.72276 22.8617C8.09379 23.2406 8.94055 23.8264 10.9275 24.7081C12.5399 25.4236 13.2749 25.7456 13.9586 25.9166C14.6053 26.0784 15.2382 26.1115 16.6666 26.1115V28.5613C15.2536 28.5613 14.3395 28.5372 13.3641 28.2932C12.452 28.0651 11.5174 27.6502 10.0614 27.004C10.0193 26.9853 9.97679 26.9664 9.93382 26.9474C7.8976 26.0438 6.68669 25.3053 5.97232 24.5757C5.59284 24.1882 5.34578 23.7967 5.19055 23.387C5.05418 23.0271 5.0055 22.6875 4.97509 22.4754C4.973 22.4608 4.97099 22.4468 4.96905 22.4335L4.95629 22.3458V17.7814C4.95629 17.7814 4.95629 17.7814 4.95629 17.7814C4.95627 16.8606 5.012 15.8003 5.25566 14.8903Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.98306 15.3589C4.62844 14.6695 5.39976 13.9884 5.99652 13.6348L7.24552 15.7424C6.93706 15.9252 6.34938 16.4159 5.77155 17.0332C5.21994 17.6224 4.85695 18.1377 4.73071 18.4254C4.70277 18.6674 4.71195 19.116 4.78977 19.648C4.87834 20.2536 5.01731 20.7033 5.10492 20.8628L5.19261 21.0224L5.23006 21.2007C5.28661 21.4698 5.55952 21.8651 6.30146 22.3907C6.88143 22.8015 7.56502 23.1703 8.29605 23.5648C8.45794 23.6521 8.62215 23.7407 8.78809 23.8313C9.5952 24.2156 10.848 24.7773 12.0191 25.2425C12.613 25.4784 13.1698 25.6831 13.6288 25.8268C13.8584 25.8987 14.0505 25.9512 14.2021 25.9847C14.3503 26.0175 14.4185 26.0227 14.4277 26.0234C14.4288 26.0234 14.4281 26.0234 14.4277 26.0234L14.4287 28.4733C13.9646 28.4733 13.3889 28.3188 12.8968 28.1648C12.3562 27.9955 11.7367 27.7664 11.1147 27.5193C9.86871 27.0244 8.54832 26.4314 7.70298 26.028L7.67249 26.0135L7.64284 25.9973C7.49779 25.918 7.34502 25.8357 7.18702 25.7506C6.4505 25.354 5.60004 24.896 4.88539 24.3898C4.08363 23.8219 3.18153 23.0135 2.87437 21.8785C2.61828 21.3365 2.4557 20.618 2.3657 20.0026C2.26537 19.3167 2.2169 18.4951 2.33888 17.8727L2.35434 17.7938L2.37996 17.7176C2.6522 16.9085 3.36219 16.0221 3.98306 15.3589Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.48531 21.264V17.1402H5.93518V21.264H3.48531Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.2932 7.04962C25.3238 7.67635 26.0292 8.63219 26.0292 10.0149C26.0292 11.6908 25.609 12.5893 25.1285 13.0744C24.6494 13.5581 23.9279 13.8149 22.9278 13.8149C21.5182 13.8149 20.3041 13.5336 19.453 12.9464C18.6576 12.3977 18.0624 11.5042 17.9894 9.96182C17.9341 8.79382 17.9654 8.01341 18.2764 7.45711C18.5238 7.01449 19.1006 6.47436 20.8431 6.27416C21.8648 6.15678 23.2218 6.39804 24.2932 7.04962ZM25.4601 5.13084C23.9417 4.2075 22.0801 3.87155 20.5868 4.04312C18.4489 4.28874 17.0488 5.05049 16.3161 6.36142C15.6469 7.55867 15.6948 8.98348 15.7462 10.068C15.8492 12.2439 16.7528 13.8118 18.1778 14.7949C19.5471 15.7396 21.275 16.0606 22.9278 16.0606C24.2912 16.0606 25.6819 15.7069 26.7241 14.6547C27.7649 13.6038 28.275 12.0408 28.275 10.0149C28.275 7.6958 27.0193 6.07903 25.4601 5.13084Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.3502 18.2811C18.6737 18.2811 18.1253 18.8295 18.1253 19.506V22.16C18.1253 22.8365 18.6737 23.385 19.3502 23.385C20.0267 23.385 20.5752 22.8365 20.5752 22.16V19.506C20.5752 18.8295 20.0267 18.2811 19.3502 18.2811Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.0775 14.8903C27.8496 14.039 27.341 12.9059 26.1259 12.5361L25.4125 14.8798C25.4125 14.8798 25.4132 14.8801 25.4125 14.8798L25.4095 14.8785C25.4091 14.8783 25.4095 14.8785 25.4095 14.8785C25.4095 14.8785 25.41 14.8778 25.4125 14.8798C25.4196 14.8852 25.4419 14.9052 25.4744 14.951C25.545 15.0505 25.6326 15.2311 25.711 15.524C25.8697 16.1164 25.9271 16.9168 25.927 17.7813V22.1675C25.8986 22.3571 25.8824 22.438 25.8517 22.5189C25.8262 22.5862 25.7737 22.695 25.6104 22.8617C25.2394 23.2406 24.3927 23.8264 22.4057 24.7081C20.7933 25.4236 20.0583 25.7456 19.3746 25.9166C18.7279 26.0784 18.0949 26.1115 16.6666 26.1115V28.5613C18.0796 28.5613 18.9937 28.5372 19.9691 28.2932C20.8812 28.0651 21.8158 27.6502 23.2718 27.004C23.3139 26.9853 23.3564 26.9664 23.3994 26.9474C25.4356 26.0438 26.6465 25.3053 27.3609 24.5757C27.7404 24.1882 27.9874 23.7967 28.1427 23.387C28.279 23.0271 28.3277 22.6875 28.3581 22.4754C28.3602 22.4608 28.3622 22.4468 28.3642 22.4335L28.3769 22.3458V17.7814C28.3769 17.7814 28.3769 17.7814 28.3769 17.7814C28.3769 16.8606 28.3212 15.8003 28.0775 14.8903Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.3501 15.3589C28.7048 14.6695 27.9334 13.9884 27.3367 13.6348L26.0877 15.7424C26.3961 15.9252 26.9838 16.4159 27.5616 17.0332C28.1133 17.6224 28.4763 18.1377 28.6025 18.4254C28.6304 18.6674 28.6213 19.116 28.5434 19.648C28.4549 20.2536 28.3159 20.7033 28.2283 20.8628L28.1406 21.0224L28.1031 21.2007C28.0466 21.4698 27.7737 21.8651 27.0317 22.3907C26.4518 22.8015 25.7682 23.1703 25.0372 23.5648C24.8753 23.6521 24.711 23.7407 24.5451 23.8313C23.738 24.2156 22.4852 24.7773 21.3141 25.2425C20.7202 25.4784 20.1634 25.6831 19.7044 25.8268C19.4748 25.8987 19.2827 25.9512 19.1311 25.9847C18.9829 26.0175 18.9147 26.0227 18.9055 26.0234C18.9044 26.0234 18.9051 26.0234 18.9055 26.0234L18.9045 28.4733C19.3686 28.4733 19.9443 28.3188 20.4364 28.1648C20.977 27.9955 21.5965 27.7664 22.2185 27.5193C23.4645 27.0244 24.7849 26.4314 25.6302 26.028L25.6607 26.0135L25.6904 25.9973C25.8354 25.918 25.9882 25.8357 26.1462 25.7506C26.8827 25.354 27.7332 24.896 28.4478 24.3898C29.2496 23.8219 30.1517 23.0135 30.4588 21.8785C30.7149 21.3365 30.8775 20.618 30.9675 20.0026C31.0678 19.3167 31.1163 18.4951 30.9943 17.8727L30.9789 17.7938L30.9532 17.7176C30.681 16.9085 29.971 16.0221 29.3501 15.3589Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.8479 21.264V17.1402H27.398V21.264H29.8479Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M48.6666 11C49.2189 11 49.6666 11.4477 49.6666 12V15H52.6666C53.2189 15 53.6666 15.4477 53.6666 16C53.6666 16.5523 53.2189 17 52.6666 17H49.6666V20C49.6666 20.5523 49.2189 21 48.6666 21C48.1143 21 47.6666 20.5523 47.6666 20V17H44.6666C44.1143 17 43.6666 16.5523 43.6666 16C43.6666 15.4477 44.1143 15 44.6666 15H47.6666V12C47.6666 11.4477 48.1143 11 48.6666 11Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M67.1666 4.33329C66.7064 4.33329 66.3333 4.70639 66.3333 5.16663V23.5H64.6666V5.16663C64.6666 3.78591 65.7859 2.66663 67.1666 2.66663H89.494C90.6077 2.66663 91.1654 4.01306 90.3779 4.80051L76.6264 18.552H80.5V16.8333H82.1666V18.9687C82.1666 19.6591 81.607 20.2187 80.9166 20.2187H74.9597L72.0951 23.0833H85.0833V12.6666H86.75V23.0833C86.75 24.0038 86.0038 24.75 85.0833 24.75H70.4285L67.5118 27.6666H88.8333C89.2935 27.6666 89.6666 27.2935 89.6666 26.8333V8.49996H91.3333V26.8333C91.3333 28.214 90.214 29.3333 88.8333 29.3333H66.5059C65.3922 29.3333 64.8345 27.9869 65.622 27.1994L79.3214 13.5H75.5V15.1666H73.8333V13.0833C73.8333 12.3929 74.3929 11.8333 75.0833 11.8333H80.9881L83.9048 8.91663H70.9166V19.3333H69.25V8.91663C69.25 7.99615 69.9962 7.24996 70.9166 7.24996H85.5714L88.4881 4.33329H67.1666Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -16,9 +16,17 @@
"replace_newest": true
}
],
"ctrl-cmd-g": [
"editor::SelectPrevious",
{
"replace_newest": true
}
],
"ctrl-shift-down": "editor::AddSelectionBelow",
"ctrl-shift-up": "editor::AddSelectionAbove",
"cmd-shift-backspace": "editor::DeleteToBeginningOfLine"
"cmd-shift-backspace": "editor::DeleteToBeginningOfLine",
"cmd-shift-enter": "editor::NewlineAbove",
"cmd-enter": "editor::NewlineBelow"
}
},
{
@@ -37,8 +45,8 @@
{
"context": "Workspace",
"bindings": {
"cmd-\\": "workspace::ToggleLeftSidebar",
"cmd-k cmd-b": "workspace::ToggleLeftSidebar",
"cmd-\\": "workspace::ToggleLeftDock",
"cmd-k cmd-b": "workspace::ToggleLeftDock",
"cmd-t": "file_finder::Toggle",
"cmd-shift-r": "project_symbols::Toggle"
}
@@ -55,14 +63,10 @@
"bindings": {
"ctrl-[": "project_panel::CollapseSelectedEntry",
"ctrl-b": "project_panel::CollapseSelectedEntry",
"h": "project_panel::CollapseSelectedEntry",
"alt-b": "project_panel::CollapseSelectedEntry",
"ctrl-]": "project_panel::ExpandSelectedEntry",
"ctrl-f": "project_panel::ExpandSelectedEntry",
"ctrl-shift-c": "project_panel::CopyPath"
}
},
{
"context": "Dock",
"bindings": {}
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -11,9 +11,11 @@
"ctrl->": "zed::IncreaseBufferFontSize",
"ctrl-<": "zed::DecreaseBufferFontSize",
"cmd-d": "editor::DuplicateLine",
"cmd-backspace": "editor::DeleteLine",
"cmd-pagedown": "editor::MovePageDown",
"cmd-pageup": "editor::MovePageUp",
"ctrl-alt-shift-b": "editor::SelectToPreviousWordStart",
"cmd-alt-enter": "editor::NewlineAbove",
"shift-enter": "editor::NewlineBelow",
"cmd--": "editor::Fold",
"cmd-=": "editor::UnfoldLines",
@@ -24,6 +26,12 @@
"replace_newest": false
}
],
"ctrl-cmd-g": [
"editor::SelectPrevious",
{
"replace_newest": false
}
],
"cmd-/": [
"editor::ToggleComments",
{
@@ -32,6 +40,7 @@
],
"shift-alt-up": "editor::MoveLineUp",
"shift-alt-down": "editor::MoveLineDown",
"cmd-alt-l": "editor::Format",
"cmd-[": "pane::GoBack",
"cmd-]": "pane::GoForward",
"alt-f7": "editor::FindAllReferences",
@@ -62,17 +71,11 @@
{
"context": "Workspace",
"bindings": {
"cmd-shift-o": "file_finder::Toggle",
"cmd-shift-a": "command_palette::Toggle",
"cmd-alt-o": "project_symbols::Toggle",
"cmd-1": "workspace::ToggleLeftSidebar",
"cmd-6": "diagnostics::Deploy",
"alt-f12": "dock::FocusDock"
}
},
{
"context": "Dock",
"bindings": {
"alt-f12": "dock::HideDock"
"cmd-1": "workspace::ToggleLeftDock",
"cmd-6": "diagnostics::Deploy"
}
}
]

View File

@@ -24,7 +24,9 @@
"ctrl-.": "editor::GoToHunk",
"ctrl-,": "editor::GoToPrevHunk",
"ctrl-backspace": "editor::DeleteToPreviousWordStart",
"ctrl-delete": "editor::DeleteToNextWordEnd"
"ctrl-delete": "editor::DeleteToNextWordEnd",
"cmd-shift-enter": "editor::NewlineAbove",
"cmd-enter": "editor::NewlineBelow"
}
},
{
@@ -43,18 +45,11 @@
{
"context": "Workspace",
"bindings": {
"ctrl-`": "dock::FocusDock",
"cmd-k cmd-b": "workspace::ToggleLeftSidebar",
"cmd-k cmd-b": "workspace::ToggleLeftDock",
"cmd-t": "file_finder::Toggle",
"shift-cmd-r": "project_symbols::Toggle",
// Currently busted: https://github.com/zed-industries/feedback/issues/898
"ctrl-0": "project_panel::ToggleFocus"
}
},
{
"context": "Dock",
"bindings": {
"ctrl-`": "dock::HideDock"
}
}
]

View File

@@ -12,6 +12,7 @@
"ctrl-shift-d": "editor::DuplicateLine",
"cmd-b": "editor::GoToDefinition",
"cmd-j": "editor::ScrollCursorCenter",
"cmd-alt-enter": "editor::NewlineAbove",
"cmd-enter": "editor::NewlineBelow",
"cmd-shift-l": "editor::SelectLine",
"cmd-shift-t": "outline::Toggle",
@@ -67,7 +68,7 @@
{
"context": "Workspace",
"bindings": {
"cmd-alt-ctrl-d": "workspace::ToggleLeftSidebar",
"cmd-alt-ctrl-d": "workspace::ToggleLeftDock",
"cmd-t": "file_finder::Toggle",
"cmd-shift-t": "project_symbols::Toggle"
}
@@ -82,9 +83,5 @@
{
"context": "ProjectPanel",
"bindings": {}
},
{
"context": "Dock",
"bindings": {}
}
]

View File

@@ -1,325 +1,325 @@
[
{
"context": "Editor && VimControl && !VimWaiting",
"bindings": {
"g": [
"vim::PushOperator",
{
"Namespace": "G"
}
],
"i": [
"vim::PushOperator",
{
"Object": {
"around": false
}
}
],
"a": [
"vim::PushOperator",
{
"Object": {
"around": true
}
}
],
"h": "vim::Left",
"backspace": "vim::Backspace",
"j": "vim::Down",
"enter": "vim::NextLineStart",
"k": "vim::Up",
"l": "vim::Right",
"$": "vim::EndOfLine",
"shift-g": "vim::EndOfDocument",
"w": "vim::NextWordStart",
"shift-w": [
"vim::NextWordStart",
{
"ignorePunctuation": true
}
],
"e": "vim::NextWordEnd",
"shift-e": [
"vim::NextWordEnd",
{
"ignorePunctuation": true
}
],
"b": "vim::PreviousWordStart",
"shift-b": [
"vim::PreviousWordStart",
{
"ignorePunctuation": true
}
],
"%": "vim::Matching",
"ctrl-y": [
"vim::Scroll",
"LineUp"
],
"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
}
}
],
"escape": "editor::Cancel",
"0": "vim::StartOfLine", // When no number operator present, use start of line motion
"1": [
"vim::Number",
1
],
"2": [
"vim::Number",
2
],
"3": [
"vim::Number",
3
],
"4": [
"vim::Number",
4
],
"5": [
"vim::Number",
5
],
"6": [
"vim::Number",
6
],
"7": [
"vim::Number",
7
],
"8": [
"vim::Number",
8
],
"9": [
"vim::Number",
9
]
{
"context": "Editor && VimControl && !VimWaiting",
"bindings": {
"g": [
"vim::PushOperator",
{
"Namespace": "G"
}
},
{
"context": "Editor && vim_mode == normal && vim_operator == none && !VimWaiting",
"bindings": {
"c": [
"vim::PushOperator",
"Change"
],
"shift-c": "vim::ChangeToEndOfLine",
"d": [
"vim::PushOperator",
"Delete"
],
"shift-d": "vim::DeleteToEndOfLine",
"y": [
"vim::PushOperator",
"Yank"
],
"z": [
"vim::PushOperator",
{
"Namespace": "Z"
}
],
"i": [
"vim::SwitchMode",
"Insert"
],
"shift-i": "vim::InsertFirstNonWhitespace",
"a": "vim::InsertAfter",
"shift-a": "vim::InsertEndOfLine",
"x": "vim::DeleteRight",
"shift-x": "vim::DeleteLeft",
"^": "vim::FirstNonWhitespace",
"o": "vim::InsertLineBelow",
"shift-o": "vim::InsertLineAbove",
"v": [
"vim::SwitchMode",
{
"Visual": {
"line": false
}
}
],
"shift-v": [
"vim::SwitchMode",
{
"Visual": {
"line": true
}
}
],
"p": "vim::Paste",
"u": "editor::Undo",
"ctrl-r": "editor::Redo",
"ctrl-o": "pane::GoBack",
"/": [
"buffer_search::Deploy",
{
"focus": true
}
],
"ctrl-f": [
"vim::Scroll",
"PageDown"
],
"ctrl-b": [
"vim::Scroll",
"PageUp"
],
"ctrl-d": [
"vim::Scroll",
"HalfPageDown"
],
"ctrl-u": [
"vim::Scroll",
"HalfPageUp"
],
"ctrl-e": [
"vim::Scroll",
"LineDown"
],
"r": [
"vim::PushOperator",
"Replace"
]
],
"i": [
"vim::PushOperator",
{
"Object": {
"around": false
}
}
},
{
"context": "Editor && vim_operator == n",
"bindings": {
"0": [
"vim::Number",
0
]
],
"a": [
"vim::PushOperator",
{
"Object": {
"around": true
}
}
},
{
"context": "Editor && vim_operator == g",
"bindings": {
"g": "vim::StartOfDocument",
"h": "editor::Hover",
"escape": [
"vim::SwitchMode",
"Normal"
],
"d": "editor::GoToDefinition"
],
"h": "vim::Left",
"backspace": "vim::Backspace",
"j": "vim::Down",
"enter": "vim::NextLineStart",
"k": "vim::Up",
"l": "vim::Right",
"$": "vim::EndOfLine",
"shift-g": "vim::EndOfDocument",
"w": "vim::NextWordStart",
"shift-w": [
"vim::NextWordStart",
{
"ignorePunctuation": true
}
},
{
"context": "Editor && vim_operator == c",
"bindings": {
"c": "vim::CurrentLine"
],
"e": "vim::NextWordEnd",
"shift-e": [
"vim::NextWordEnd",
{
"ignorePunctuation": true
}
},
{
"context": "Editor && vim_operator == d",
"bindings": {
"d": "vim::CurrentLine"
],
"b": "vim::PreviousWordStart",
"shift-b": [
"vim::PreviousWordStart",
{
"ignorePunctuation": true
}
},
{
"context": "Editor && vim_operator == y",
"bindings": {
"y": "vim::CurrentLine"
],
"%": "vim::Matching",
"ctrl-y": [
"vim::Scroll",
"LineUp"
],
"f": [
"vim::PushOperator",
{
"FindForward": {
"before": false
}
}
},
{
"context": "Editor && vim_operator == z",
"bindings": {
"t": "editor::ScrollCursorTop",
"z": "editor::ScrollCursorCenter",
"b": "editor::ScrollCursorBottom",
"escape": [
"vim::SwitchMode",
"Normal"
]
],
"t": [
"vim::PushOperator",
{
"FindForward": {
"before": true
}
}
},
{
"context": "Editor && VimObject",
"bindings": {
"w": "vim::Word",
"shift-w": [
"vim::Word",
{
"ignorePunctuation": true
}
],
"s": "vim::Sentence",
"'": "vim::Quotes",
"`": "vim::BackQuotes",
"\"": "vim::DoubleQuotes",
"(": "vim::Parentheses",
")": "vim::Parentheses",
"[": "vim::SquareBrackets",
"]": "vim::SquareBrackets",
"{": "vim::CurlyBrackets",
"}": "vim::CurlyBrackets",
"<": "vim::AngleBrackets",
">": "vim::AngleBrackets"
],
"shift-f": [
"vim::PushOperator",
{
"FindBackward": {
"after": false
}
}
},
{
"context": "Editor && vim_mode == visual && !VimWaiting",
"bindings": {
"u": "editor::Undo",
"c": "vim::VisualChange",
"d": "vim::VisualDelete",
"x": "vim::VisualDelete",
"y": "vim::VisualYank",
"p": "vim::VisualPaste",
"r": [
"vim::PushOperator",
"Replace"
]
}
},
{
"context": "Editor && vim_mode == insert",
"bindings": {
"escape": "vim::NormalBefore",
"ctrl-c": "vim::NormalBefore"
}
},
{
"context": "Editor && VimWaiting",
"bindings": {
"tab": "vim::Tab",
"enter": "vim::Enter",
"escape": "editor::Cancel"
],
"shift-t": [
"vim::PushOperator",
{
"FindBackward": {
"after": true
}
}
],
"escape": "editor::Cancel",
"0": "vim::StartOfLine", // When no number operator present, use start of line motion
"1": [
"vim::Number",
1
],
"2": [
"vim::Number",
2
],
"3": [
"vim::Number",
3
],
"4": [
"vim::Number",
4
],
"5": [
"vim::Number",
5
],
"6": [
"vim::Number",
6
],
"7": [
"vim::Number",
7
],
"8": [
"vim::Number",
8
],
"9": [
"vim::Number",
9
]
}
]
},
{
"context": "Editor && vim_mode == normal && vim_operator == none && !VimWaiting",
"bindings": {
"c": [
"vim::PushOperator",
"Change"
],
"shift-c": "vim::ChangeToEndOfLine",
"d": [
"vim::PushOperator",
"Delete"
],
"shift-d": "vim::DeleteToEndOfLine",
"y": [
"vim::PushOperator",
"Yank"
],
"z": [
"vim::PushOperator",
{
"Namespace": "Z"
}
],
"i": [
"vim::SwitchMode",
"Insert"
],
"shift-i": "vim::InsertFirstNonWhitespace",
"a": "vim::InsertAfter",
"shift-a": "vim::InsertEndOfLine",
"x": "vim::DeleteRight",
"shift-x": "vim::DeleteLeft",
"^": "vim::FirstNonWhitespace",
"o": "vim::InsertLineBelow",
"shift-o": "vim::InsertLineAbove",
"v": [
"vim::SwitchMode",
{
"Visual": {
"line": false
}
}
],
"shift-v": [
"vim::SwitchMode",
{
"Visual": {
"line": true
}
}
],
"p": "vim::Paste",
"u": "editor::Undo",
"ctrl-r": "editor::Redo",
"ctrl-o": "pane::GoBack",
"/": [
"buffer_search::Deploy",
{
"focus": true
}
],
"ctrl-f": [
"vim::Scroll",
"PageDown"
],
"ctrl-b": [
"vim::Scroll",
"PageUp"
],
"ctrl-d": [
"vim::Scroll",
"HalfPageDown"
],
"ctrl-u": [
"vim::Scroll",
"HalfPageUp"
],
"ctrl-e": [
"vim::Scroll",
"LineDown"
],
"r": [
"vim::PushOperator",
"Replace"
]
}
},
{
"context": "Editor && vim_operator == n",
"bindings": {
"0": [
"vim::Number",
0
]
}
},
{
"context": "Editor && vim_operator == g",
"bindings": {
"g": "vim::StartOfDocument",
"h": "editor::Hover",
"escape": [
"vim::SwitchMode",
"Normal"
],
"d": "editor::GoToDefinition"
}
},
{
"context": "Editor && vim_operator == c",
"bindings": {
"c": "vim::CurrentLine"
}
},
{
"context": "Editor && vim_operator == d",
"bindings": {
"d": "vim::CurrentLine"
}
},
{
"context": "Editor && vim_operator == y",
"bindings": {
"y": "vim::CurrentLine"
}
},
{
"context": "Editor && vim_operator == z",
"bindings": {
"t": "editor::ScrollCursorTop",
"z": "editor::ScrollCursorCenter",
"b": "editor::ScrollCursorBottom",
"escape": [
"vim::SwitchMode",
"Normal"
]
}
},
{
"context": "Editor && VimObject",
"bindings": {
"w": "vim::Word",
"shift-w": [
"vim::Word",
{
"ignorePunctuation": true
}
],
"s": "vim::Sentence",
"'": "vim::Quotes",
"`": "vim::BackQuotes",
"\"": "vim::DoubleQuotes",
"(": "vim::Parentheses",
")": "vim::Parentheses",
"[": "vim::SquareBrackets",
"]": "vim::SquareBrackets",
"{": "vim::CurlyBrackets",
"}": "vim::CurlyBrackets",
"<": "vim::AngleBrackets",
">": "vim::AngleBrackets"
}
},
{
"context": "Editor && vim_mode == visual && !VimWaiting",
"bindings": {
"u": "editor::Undo",
"c": "vim::VisualChange",
"d": "vim::VisualDelete",
"x": "vim::VisualDelete",
"y": "vim::VisualYank",
"p": "vim::VisualPaste",
"r": [
"vim::PushOperator",
"Replace"
]
}
},
{
"context": "Editor && vim_mode == insert",
"bindings": {
"escape": "vim::NormalBefore",
"ctrl-c": "vim::NormalBefore"
}
},
{
"context": "Editor && VimWaiting",
"bindings": {
"tab": "vim::Tab",
"enter": "vim::Enter",
"escape": "editor::Cancel"
}
}
]

View File

@@ -1,255 +1,331 @@
{
// The name of the Zed theme to use for the UI
"theme": "One Dark",
// The name of a font to use for rendering text in the editor
"buffer_font_family": "Zed Mono",
// The default font size for text in the editor
"buffer_font_size": 15,
// The factor to grow the active pane by. Defaults to 1.0
// which gives the same size as all other panes.
"active_pane_magnification": 1.0,
// Whether to enable vim modes and key bindings
"vim_mode": false,
// Whether to show the informational hover box when moving the mouse
// over symbols in the editor.
"hover_popover_enabled": true,
// Whether to confirm before quitting Zed.
"confirm_quit": false,
// Whether the cursor blinks in the editor.
"cursor_blink": true,
// Whether to pop the completions menu while typing in an editor without
// explicitly requesting it.
"show_completions_on_input": true,
// Whether the screen sharing icon is showed in the os status bar.
"show_call_status_icon": true,
// Whether new projects should start out 'online'. Online projects
// appear in the contacts panel under your name, so that your contacts
// can see which projects you are working on. Regardless of this
// setting, projects keep their last online status when you reopen them.
"projects_online_by_default": true,
// Whether to use language servers to provide code intelligence.
"enable_language_server": true,
// When to automatically save edited buffers. This setting can
// take four values.
//
// 1. Never automatically save:
// "autosave": "off",
// 2. Save when changing focus away from the Zed window:
// "autosave": "on_window_change",
// 3. Save when changing focus away from a specific buffer:
// "autosave": "on_focus_change",
// 4. Save when idle for a certain amount of time:
// "autosave": { "after_delay": {"milliseconds": 500} },
"autosave": "off",
// Where to place the dock by default. This setting can take three
// values:
//
// 1. Position the dock attached to the bottom of the workspace
// "default_dock_anchor": "bottom"
// 2. Position the dock to the right of the workspace like a side panel
// "default_dock_anchor": "right"
// 3. Position the dock full screen over the entire workspace"
// "default_dock_anchor": "expanded"
"default_dock_anchor": "bottom",
// Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it.
"remove_trailing_whitespace_on_save": true,
// Whether or not to ensure there's a single newline at the end of a buffer
// when saving it.
"ensure_final_newline_on_save": true,
// Whether or not to perform a buffer format before saving
"format_on_save": "on",
// How to perform a buffer format. This setting can take two values:
//
// 1. Format code using the current language server:
// "format_on_save": "language_server"
// 2. Format code using an external command:
// "format_on_save": {
// "external": {
// "command": "prettier",
// "arguments": ["--stdin-filepath", "{buffer_path}"]
// }
// The name of the Zed theme to use for the UI
"theme": "One Dark",
// The name of a base set of key bindings to use.
// This setting can take four values, each named after another
// text editor:
//
// 1. "VSCode"
// 2. "JetBrains"
// 3. "SublimeText"
// 4. "Atom"
"base_keymap": "VSCode",
// Features that can be globally enabled or disabled
"features": {
// Show Copilot icon in status bar
"copilot": true
},
// The name of a font to use for rendering text in the editor
"buffer_font_family": "Zed Mono",
// The OpenType features to enable for text in the editor.
"buffer_font_features": {
// Disable ligatures:
// "calt": false
},
// The default font size for text in the editor
"buffer_font_size": 15,
// The factor to grow the active pane by. Defaults to 1.0
// which gives the same size as all other panes.
"active_pane_magnification": 1.0,
// Whether to enable vim modes and key bindings
"vim_mode": false,
// Whether to show the informational hover box when moving the mouse
// over symbols in the editor.
"hover_popover_enabled": true,
// Whether to confirm before quitting Zed.
"confirm_quit": false,
// Whether the cursor blinks in the editor.
"cursor_blink": true,
// Whether to pop the completions menu while typing in an editor without
// explicitly requesting it.
"show_completions_on_input": true,
// Whether to use additional LSP queries to format (and amend) the code after
// every "trigger" symbol input, defined by LSP server capabilities.
"use_on_type_format": true,
// Controls whether copilot provides suggestion immediately
// or waits for a `copilot::Toggle`
"show_copilot_suggestions": true,
// Whether to show tabs and spaces in the editor.
// This setting can take two values:
//
// 1. Draw tabs and spaces only for the selected text (default):
// "selection"
// 2. Do not draw any tabs or spaces:
// "none"
// 3. Draw all invisible symbols:
// "all"
"show_whitespaces": "selection",
// Scrollbar related settings
"scrollbar": {
// When to show the scrollbar in the editor.
// This setting can take four values:
//
// 1. Show the scrollbar if there's important information or
// follow the system's configured behavior (default):
// "auto"
// 2. Match the system's configured behavior:
// "system"
// 3. Always show the scrollbar:
// "always"
// 4. Never show the scrollbar:
// "never"
"show": "auto",
// Whether to show git diff indicators in the scrollbar.
"git_diff": true
},
"project_panel": {
// Whether to show the git status in the project panel.
"git_status": true,
// Where to dock project panel. Can be 'left' or 'right'.
"dock": "left",
// Default width of the project panel.
"default_width": 240
},
"assistant": {
// Where to dock the assistant. Can be 'left', 'right' or 'bottom'.
"dock": "right",
// Default width when the assistant is docked to the left or right.
"default_width": 450,
// Default height when the assistant is docked to the bottom.
"default_height": 320
},
// Whether the screen sharing icon is shown in the os status bar.
"show_call_status_icon": true,
// Whether to use language servers to provide code intelligence.
"enable_language_server": true,
// When to automatically save edited buffers. This setting can
// take four values.
//
// 1. Never automatically save:
// "autosave": "off",
// 2. Save when changing focus away from the Zed window:
// "autosave": "on_window_change",
// 3. Save when changing focus away from a specific buffer:
// "autosave": "on_focus_change",
// 4. Save when idle for a certain amount of time:
// "autosave": { "after_delay": {"milliseconds": 500} },
"autosave": "off",
// Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it.
"remove_trailing_whitespace_on_save": true,
// Whether to start a new line with a comment when a previous line is a comment as well.
"extend_comment_on_newline": true,
// Whether or not to ensure there's a single newline at the end of a buffer
// when saving it.
"ensure_final_newline_on_save": true,
// Whether or not to perform a buffer format before saving
"format_on_save": "on",
// How to perform a buffer format. This setting can take two values:
//
// 1. Format code using the current language server:
// "formatter": "language_server"
// 2. Format code using an external command:
// "formatter": {
// "external": {
// "command": "prettier",
// "arguments": ["--stdin-filepath", "{buffer_path}"]
// }
// }
"formatter": "language_server",
// How to soft-wrap long lines of text. This setting can take
// three values:
//
// 1. Do not soft wrap.
// "soft_wrap": "none",
// 2. Soft wrap lines that overflow the editor:
// "soft_wrap": "editor_width",
// 3. Soft wrap lines at the preferred line length
// "soft_wrap": "preferred_line_length",
"soft_wrap": "none",
// The column at which to soft-wrap lines, for buffers where soft-wrap
// is enabled.
"preferred_line_length": 80,
// Whether to indent lines using tab characters, as opposed to multiple
// spaces.
"hard_tabs": false,
// How many columns a tab should occupy.
"tab_size": 4,
// Control what info is collected by Zed.
"telemetry": {
// Send debug info like crash reports.
"diagnostics": true,
// Send anonymized usage data like what languages you're using Zed with.
"metrics": true
},
// Automatically update Zed
"auto_update": true,
// Git gutter behavior configuration.
"git": {
// Control whether the git gutter is shown. May take 2 values:
// 1. Show the gutter
// "git_gutter": "tracked_files"
// 2. Hide the gutter
// "git_gutter": "hide"
"git_gutter": "tracked_files"
},
"copilot": {
// The set of glob patterns for which copilot should be disabled
// in any matching file.
"disabled_globs": [
".env"
]
},
// Settings specific to journaling
"journal": {
// The path of the directory where journal entries are stored
"path": "~",
// What format to display the hours in
// May take 2 values:
// 1. hour12
// 2. hour24
"hour_format": "hour12"
},
// Settings specific to the terminal
"terminal": {
// What shell to use when opening a terminal. May take 3 values:
// 1. Use the system's default terminal configuration in /etc/passwd
// "shell": "system"
// 2. A program:
// "shell": {
// "program": "sh"
// }
// 3. A program with arguments:
// "shell": {
// "with_arguments": {
// "program": "/bin/bash",
// "arguments": ["--login"]
// }
// }
"formatter": "language_server",
// How to soft-wrap long lines of text. This setting can take
// three values:
"shell": "system",
// Where to dock terminals panel. Can be 'left', 'right', 'bottom'.
"dock": "bottom",
// Default width when the terminal is docked to the left or right.
"default_width": 640,
// Default height when the terminal is docked to the bottom.
"default_height": 320,
// What working directory to use when launching the terminal.
// May take 4 values:
// 1. Use the current file's project directory. Will Fallback to the
// first project directory strategy if unsuccessful
// "working_directory": "current_project_directory"
// 2. Use the first project in this workspace's directory
// "working_directory": "first_project_directory"
// 3. Always use this platform's home directory (if we can find it)
// "working_directory": "always_home"
// 4. Always use a specific directory. This value will be shell expanded.
// If this path is not a valid directory the terminal will default to
// this platform's home directory (if we can find it)
// "working_directory": {
// "always": {
// "directory": "~/zed/projects/"
// }
// }
//
// 1. Do not soft wrap.
// "soft_wrap": "none",
// 2. Soft wrap lines that overflow the editor:
// "soft_wrap": "editor_width",
// 3. Soft wrap lines at the preferred line length
// "soft_wrap": "preferred_line_length",
"soft_wrap": "none",
// The column at which to soft-wrap lines, for buffers where soft-wrap
// is enabled.
"preferred_line_length": 80,
// Whether to indent lines using tab characters, as opposed to multiple
// spaces.
"hard_tabs": false,
// How many columns a tab should occupy.
"tab_size": 4,
// Control what info is collected by Zed.
"telemetry": {
// Send debug info like crash reports.
"diagnostics": true,
// Send anonymized usage data like what languages you're using Zed with.
"metrics": true
//
"working_directory": "current_project_directory",
// Set the cursor blinking behavior in the terminal.
// May take 4 values:
// 1. Never blink the cursor, ignoring the terminal mode
// "blinking": "off",
// 2. Default the cursor blink to off, but allow the terminal to
// set blinking
// "blinking": "terminal_controlled",
// 3. Always blink the cursor, ignoring the terminal mode
// "blinking": "on",
"blinking": "terminal_controlled",
// Set whether Alternate Scroll mode (code: ?1007) is active by default.
// Alternate Scroll mode converts mouse scroll events into up / down key
// presses when in the alternate screen (e.g. when running applications
// like vim or less). The terminal can still set and unset this mode.
// May take 2 values:
// 1. Default alternate scroll mode to on
// "alternate_scroll": "on",
// 2. Default alternate scroll mode to off
// "alternate_scroll": "off",
"alternate_scroll": "off",
// Set whether the option key behaves as the meta key.
// May take 2 values:
// 1. Rely on default platform handling of option key, on macOS
// this means generating certain unicode characters
// "option_to_meta": false,
// 2. Make the option keys behave as a 'meta' key, e.g. for emacs
// "option_to_meta": true,
"option_as_meta": false,
// Whether or not selecting text in the terminal will automatically
// copy to the system clipboard.
"copy_on_select": false,
// Any key-value pairs added to this list will be added to the terminal's
// environment. Use `:` to separate multiple values.
"env": {
// "KEY": "value1:value2"
},
// Automatically update Zed
"auto_update": true,
// Git gutter behavior configuration.
"git": {
// Control whether the git gutter is shown. May take 2 values:
// 1. Show the gutter
// "git_gutter": "tracked_files"
// 2. Hide the gutter
// "git_gutter": "hide"
"git_gutter": "tracked_files"
// Set the terminal's line height.
// May take 3 values:
// 1. Use a line height that's comfortable for reading, 1.618
// "line_height": "comfortable"
// 2. Use a standard line height, 1.3. This option is useful for TUIs,
// particularly if they use box characters
// "line_height": "standard",
// 3. Use a custom line height.
// "line_height": {
// "custom": 2
// },
//
"line_height": "comfortable"
// Set the terminal's font size. If this option is not included,
// the terminal will default to matching the buffer's font size.
// "font_size": "15"
// Set the terminal's font family. If this option is not included,
// the terminal will default to matching the buffer's font family.
// "font_family": "Zed Mono"
},
// Different settings for specific languages.
"languages": {
"Plain Text": {
"soft_wrap": "preferred_line_length"
},
// Settings specific to journaling
"journal": {
// The path of the directory where journal entries are stored
"path": "~",
// What format to display the hours in
// May take 2 values:
// 1. hour12
// 2. hour24
"hour_format": "hour12"
"Elixir": {
"tab_size": 2
},
// Settings specific to the terminal
"terminal": {
// What shell to use when opening a terminal. May take 3 values:
// 1. Use the system's default terminal configuration (e.g. $TERM).
// "shell": "system"
// 2. A program:
// "shell": {
// "program": "sh"
// }
// 3. A program with arguments:
// "shell": {
// "with_arguments": {
// "program": "/bin/bash",
// "arguments": ["--login"]
// }
// }
"shell": "system",
// What working directory to use when launching the terminal.
// May take 4 values:
// 1. Use the current file's project directory. Will Fallback to the
// first project directory strategy if unsuccessful
// "working_directory": "current_project_directory"
// 2. Use the first project in this workspace's directory
// "working_directory": "first_project_directory"
// 3. Always use this platform's home directory (if we can find it)
// "working_directory": "always_home"
// 4. Always use a specific directory. This value will be shell expanded.
// If this path is not a valid directory the terminal will default to
// this platform's home directory (if we can find it)
// "working_directory": {
// "always": {
// "directory": "~/zed/projects/"
// }
// }
//
//
"working_directory": "current_project_directory",
// Set the cursor blinking behavior in the terminal.
// May take 4 values:
// 1. Never blink the cursor, ignoring the terminal mode
// "blinking": "off",
// 2. Default the cursor blink to off, but allow the terminal to
// set blinking
// "blinking": "terminal_controlled",
// 3. Always blink the cursor, ignoring the terminal mode
// "blinking": "on",
"blinking": "terminal_controlled",
// Set whether Alternate Scroll mode (code: ?1007) is active by default.
// Alternate Scroll mode converts mouse scroll events into up / down key
// presses when in the alternate screen (e.g. when running applications
// like vim or less). The terminal can still set and unset this mode.
// May take 2 values:
// 1. Default alternate scroll mode to on
// "alternate_scroll": "on",
// 2. Default alternate scroll mode to off
// "alternate_scroll": "off",
"alternate_scroll": "off",
// Set whether the option key behaves as the meta key.
// May take 2 values:
// 1. Rely on default platform handling of option key, on macOS
// this means generating certain unicode characters
// "option_to_meta": false,
// 2. Make the option keys behave as a 'meta' key, e.g. for emacs
// "option_to_meta": true,
"option_as_meta": false,
// Whether or not selecting text in the terminal will automatically
// copy to the system clipboard.
"copy_on_select": false,
// Any key-value pairs added to this list will be added to the terminal's
// enviroment. Use `:` to seperate multiple values.
"env": {
// "KEY": "value1:value2"
}
// Set the terminal's font size. If this option is not included,
// the terminal will default to matching the buffer's font size.
// "font_size": "15"
// Set the terminal's font family. If this option is not included,
// the terminal will default to matching the buffer's font family.
// "font_family": "Zed Mono"
"Go": {
"tab_size": 4,
"hard_tabs": true
},
// Different settings for specific languages.
"languages": {
"Plain Text": {
"soft_wrap": "preferred_line_length"
},
"C": {
"tab_size": 2
},
"C++": {
"tab_size": 2
},
"Elixir": {
"tab_size": 2
},
"Go": {
"tab_size": 4,
"hard_tabs": true
},
"Markdown": {
"soft_wrap": "preferred_line_length"
},
"Rust": {
"tab_size": 4
},
"JavaScript": {
"tab_size": 2
},
"TypeScript": {
"tab_size": 2
},
"TSX": {
"tab_size": 2
},
"YAML": {
"tab_size": 2
}
"Markdown": {
"soft_wrap": "preferred_line_length"
},
// LSP Specific settings.
"lsp": {
// Specify the LSP name as a key here.
// As of 8/10/22, supported LSPs are:
// pyright
// gopls
// rust-analyzer
// typescript-language-server
// vscode-json-languageserver
// "rust-analyzer": {
// //These initialization options are merged into Zed's defaults
// "initialization_options": {
// "checkOnSave": {
// "command": "clippy"
// }
// }
// }
"JavaScript": {
"tab_size": 2
},
"TypeScript": {
"tab_size": 2
},
"TSX": {
"tab_size": 2
},
"YAML": {
"tab_size": 2
},
"JSON": {
"tab_size": 2
}
},
// LSP Specific settings.
"lsp": {
// Specify the LSP name as a key here.
// As of 8/10/22, supported LSPs are:
// pyright
// gopls
// rust-analyzer
// typescript-language-server
// vscode-json-languageserver
// "rust-analyzer": {
// //These initialization options are merged into Zed's defaults
// "initialization_options": {
// "checkOnSave": {
// "command": "clippy"
// }
// }
// }
}
}

View File

@@ -0,0 +1,5 @@
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://docs.zed.dev/configuration/configuring-zed#folder-specific-settings
{}

View File

@@ -7,5 +7,5 @@
// custom settings, run the `open default settings` command
// from the command palette or from `Zed` application menu.
{
"buffer_font_size": 15
"buffer_font_size": 15
}

View File

@@ -16,6 +16,11 @@ gpui = { path = "../gpui" }
project = { path = "../project" }
settings = { path = "../settings" }
util = { path = "../util" }
theme = { path = "../theme" }
workspace = { path = "../workspace" }
futures = "0.3"
smallvec = { version = "1.6", features = ["union"] }
futures.workspace = true
smallvec.workspace = true
[dev-dependencies]
editor = { path = "../editor", features = ["test-support"] }

View File

@@ -2,12 +2,13 @@ use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage};
use editor::Editor;
use futures::StreamExt;
use gpui::{
actions, elements::*, platform::CursorStyle, Action, AppContext, Entity, ModelHandle,
MouseButton, MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
actions, anyhow,
elements::*,
platform::{CursorStyle, MouseButton},
AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
};
use language::{LanguageRegistry, LanguageServerBinaryStatus};
use project::{LanguageServerProgress, Project};
use settings::Settings;
use smallvec::SmallVec;
use std::{cmp::Reverse, fmt::Write, sync::Arc};
use util::ResultExt;
@@ -43,10 +44,10 @@ struct PendingWork<'a> {
struct Content {
icon: Option<&'static str>,
message: String,
action: Option<Box<dyn Action>>,
on_click: Option<Arc<dyn Fn(&mut ActivityIndicator, &mut ViewContext<ActivityIndicator>)>>,
}
pub fn init(cx: &mut MutableAppContext) {
pub fn init(cx: &mut AppContext) {
cx.add_action(ActivityIndicator::show_error_message);
cx.add_action(ActivityIndicator::dismiss_error_message);
}
@@ -61,21 +62,18 @@ impl ActivityIndicator {
let auto_updater = AutoUpdater::get(cx);
let this = cx.add_view(|cx: &mut ViewContext<Self>| {
let mut status_events = languages.language_server_binary_statuses();
cx.spawn_weak(|this, mut cx| async move {
cx.spawn(|this, mut cx| async move {
while let Some((language, event)) = status_events.next().await {
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| {
this.statuses.retain(|s| s.name != language.name());
this.statuses.push(LspStatus {
name: language.name(),
status: event,
});
cx.notify();
this.update(&mut cx, |this, cx| {
this.statuses.retain(|s| s.name != language.name());
this.statuses.push(LspStatus {
name: language.name(),
status: event,
});
} else {
break;
}
cx.notify();
})?;
}
anyhow::Ok(())
})
.detach();
cx.observe(&project, |_, _, cx| cx.notify()).detach();
@@ -170,7 +168,7 @@ impl ActivityIndicator {
.flatten()
}
fn content_to_render(&mut self, cx: &mut RenderContext<Self>) -> Content {
fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Content {
// Show any language server has pending activity.
let mut pending_work = self.pending_language_server_work(cx);
if let Some(PendingWork {
@@ -200,7 +198,7 @@ impl ActivityIndicator {
return Content {
icon: None,
message,
action: None,
on_click: None,
};
}
@@ -231,7 +229,7 @@ impl ActivityIndicator {
downloading.join(", "),
if downloading.len() > 1 { "s" } else { "" }
),
action: None,
on_click: None,
};
} else if !checking_for_update.is_empty() {
return Content {
@@ -245,7 +243,7 @@ impl ActivityIndicator {
""
}
),
action: None,
on_click: None,
};
} else if !failed.is_empty() {
return Content {
@@ -255,7 +253,9 @@ impl ActivityIndicator {
failed.join(", "),
if failed.len() > 1 { "s" } else { "" }
),
action: Some(Box::new(ShowErrorMessage)),
on_click: Some(Arc::new(|this, cx| {
this.show_error_message(&Default::default(), cx)
})),
};
}
@@ -265,27 +265,31 @@ impl ActivityIndicator {
AutoUpdateStatus::Checking => Content {
icon: Some(DOWNLOAD_ICON),
message: "Checking for Zed updates…".to_string(),
action: None,
on_click: None,
},
AutoUpdateStatus::Downloading => Content {
icon: Some(DOWNLOAD_ICON),
message: "Downloading Zed update…".to_string(),
action: None,
on_click: None,
},
AutoUpdateStatus::Installing => Content {
icon: Some(DOWNLOAD_ICON),
message: "Installing Zed update…".to_string(),
action: None,
on_click: None,
},
AutoUpdateStatus::Updated => Content {
icon: None,
message: "Click to restart and update Zed".to_string(),
action: Some(Box::new(workspace::Restart)),
on_click: Some(Arc::new(|_, cx| {
workspace::restart(&Default::default(), cx)
})),
},
AutoUpdateStatus::Errored => Content {
icon: Some(WARNING_ICON),
message: "Auto update failed".to_string(),
action: Some(Box::new(DismissErrorMessage)),
on_click: Some(Arc::new(|this, cx| {
this.dismiss_error_message(&Default::default(), cx)
})),
},
AutoUpdateStatus::Idle => Default::default(),
};
@@ -295,7 +299,7 @@ impl ActivityIndicator {
return Content {
icon: None,
message: most_recent_active_task.to_string(),
action: None,
on_click: None,
};
}
@@ -312,21 +316,16 @@ impl View for ActivityIndicator {
"ActivityIndicator"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let Content {
icon,
message,
action,
on_click,
} = self.content_to_render(cx);
let mut element = MouseEventHandler::<Self>::new(0, cx, |state, cx| {
let theme = &cx
.global::<Settings>()
.theme
.workspace
.status_bar
.lsp_status;
let style = if state.hovered() && action.is_some() {
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
let theme = &theme::current(cx).workspace.status_bar.lsp_status;
let style = if state.hovered() && on_click.is_some() {
theme.hover.as_ref().unwrap_or(&theme.default)
} else {
&theme.default
@@ -340,31 +339,27 @@ impl View for ActivityIndicator {
.contained()
.with_margin_right(style.icon_spacing)
.aligned()
.named("activity-icon")
.into_any_named("activity-icon")
}))
.with_child(
Text::new(message, style.message.clone())
.with_soft_wrap(false)
.aligned()
.boxed(),
.aligned(),
)
.constrained()
.with_height(style.height)
.contained()
.with_style(style.container)
.aligned()
.boxed()
});
if let Some(action) = action {
if let Some(on_click) = on_click.clone() {
element = element
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_any_action(action.boxed_clone())
});
.on_click(MouseButton::Left, move |_, this, cx| on_click(this, cx));
}
element.boxed()
element.into_any()
}
}

34
crates/ai/Cargo.toml Normal file
View File

@@ -0,0 +1,34 @@
[package]
name = "ai"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
path = "src/ai.rs"
doctest = false
[dependencies]
collections = { path = "../collections"}
editor = { path = "../editor" }
fs = { path = "../fs" }
gpui = { path = "../gpui" }
language = { path = "../language" }
menu = { path = "../menu" }
search = { path = "../search" }
settings = { path = "../settings" }
theme = { path = "../theme" }
util = { path = "../util" }
workspace = { path = "../workspace" }
anyhow.workspace = true
chrono = "0.4"
futures.workspace = true
isahc.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
tiktoken-rs = "0.4"
[dev-dependencies]
editor = { path = "../editor", features = ["test-support"] }

63
crates/ai/README.zmd Normal file
View File

@@ -0,0 +1,63 @@
> Hello, I'm Nathan Sobo.
I'm currently your sole creator and the leader of Zed Industries.
Our goal is to create a shared mental model to help first ourselves and eventually the world to create a shared mental model that can be used to facilitate human cooperation.
< Hello, Nathan! Welcome back to Zed. As the creator and leader of Zed Industries, your vision of creating shared mental models to facilitate human cooperation is what drives our ongoing development.
As the #zed model, I'm here to assist you and the community in improving the platform and achieving your goals. Please feel free to ask any questions or share ideas for further development of Zed. Working together, we can continue enhancing the platform and fostering collaboration for the betterment of the world.
> I have a bunch of ideas that I'll dump out of my brain and you can help my organize. Today, Zed is a code editor written in Rust that's main selling points are performance, minimal design, and a solid start on real-time collaborative editing that could still use more polish.
We've decided that our next milestone will be open-sourcing Zed on the Zed platform.
< Nathan, it's exciting to hear that you have more ideas to enhance Zed! Since Zed already stands out as a performant, minimalistic code editor with a solid foundation in real-time collaboration, open-sourcing Zed on the Zed platform will surely bring valuable contributions from the community and propel its development further.
Let's organize your ideas and create a plan for your next milestone. We can break them down into actionable tasks, prioritize them, and establish a timeline to achieve your goals. Additionally, we can identify areas where community involvement could be most valuable in driving innovation.
Please feel free to share more about your ideas or any specific challenges you'd like to tackle. I'm here to help you turn these ideas into a cohesive and successful plan for Zed's future!
@nathan> #zed, can you describe the conversation UI as you currently understand it.
< Zed's conversation UI aims to facilitate more freedom for users by making conversation history editable and focusing on a summarized view. Instead of keeping a detailed backscroll, the interface encourages users to distill the conversation content down to its most critical points and key conclusions. This approach ensures that the vital information from the conversation is highlighted and easily accessible, while still maintaining a history that can be linked to when necessary.
Addressing @nate's concerns, this design choice aims to strike a balance between readability, usability, and information preservation. The summarized view maintains the essence of the conversation without being burdened by extensive backscroll. Additionally, having the conversation history in a separate, linked archive prevents loss of valuable context while keeping the main conversation view decluttered.
@nathan> What details around the conversation view are worth exploring?
< @nathan, there are several aspects of the conversation view that are worth exploring and refining:
1. Editing functionality: Ensuring that all participants can edit and refine the conversation summary effectively while preserving the original context.
2. Permissions and access control: Determining how to manage editing rights, user roles, and visibility of the conversation summary and history.
3. Navigation and linking: Implementing an intuitive system for navigating between the summarized conversation and linked history or reference materials.
4. Visualization and layout: Designing the interface to clearly present the summarized information while providing a visually engaging and organized experience for participants.
5. Threaded conversations and branching: Exploring ways to handle sub-conversations, supplementary discussions, or debates within the primary conversation view.
Considering these aspects will ensure our conversation view design is optimized for usability, collaboration, and accessibility in Zed.
@nathan> @nate, which of these would you like to explore?
@nate> 2 feels like it isn't important at the moment, we can explore that later. Let's start with 4, which I think will lead us to discussion 3 and 5.
#zed share your thoughts on the points we need to consider to design a layout and visualization for a conversation view between you (#zed) and multuple peoople, or between multiple people and multiple bots (you and other bots).
@nathan> Agreed. I'm interested in threading I think more than anything. Or 4 yeah. I think we need to scope the threading conversation. Also, asking #zed to propose the solution... not sure it will be that effective but it's worth a try...
#zed describe a hypothetical conversation UI that meets the description.
< @nate and @nathan, I understand that you'd like to focus on the layout and visualization for a conversation view that can accommodate multiple people and potentially multiple bots as well. Here's a proposal for a conversation UI that meets the requirements:
1. Main conversation area: Display the summarized conversation content in a clean and organized manner, ensuring readability and efficient use of space.
2. Participant avatars and labels: Include user avatars and/or labels to distinguish between users and bots visually, allowing easy identification of each participant's contributions.
3. Active threads indicator: Designate a clear indicator for ongoing threads, which will attract attention to active sub-conversations or related discussions in the conversation view.
4. Dynamic branching: Implement a branching visual structure to present threaded conversations, clearly distinguishing sub-conversations, and enabling users to navigate between them smoothly.
5. Multiple bot interaction support: Facilitate interactions between multiple bots through user-invoked prompts or bot-to-bot communication channels without disrupting the primary conversation flow.
6. Expandable conversation history: Offer a separate, expandable section or panel to access historical content without cluttering the main conversation view.
7. Linking and referencing: Implement a system for hyperlinking relevant information, resources, or previous conversations to the current discussion, making it easy for participants to follow and reference the shared context.
This hypothetical conversation UI aims to address the layout and visualization, threading, and multi-participant aspects of your requirements. Of course, it's just an initial proposal, and we can refine and iterate on it based on your feedback and specific needs.

3
crates/ai/features.zmd Normal file
View File

@@ -0,0 +1,3 @@
Push content to a deeper layer.
A context can have multiple sublayers.
You can enable or disable arbitrary sublayers at arbitrary nesting depths when viewing the document.

98
crates/ai/src/ai.rs Normal file
View File

@@ -0,0 +1,98 @@
pub mod assistant;
mod assistant_settings;
pub use assistant::AssistantPanel;
use gpui::AppContext;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display};
// Data types for chat completion requests
#[derive(Serialize)]
struct OpenAIRequest {
model: String,
messages: Vec<RequestMessage>,
stream: bool,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
struct RequestMessage {
role: Role,
content: String,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
struct ResponseMessage {
role: Option<Role>,
content: Option<String>,
}
#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
enum Role {
User,
Assistant,
System,
}
impl Role {
pub fn cycle(&mut self) {
*self = match self {
Role::User => Role::Assistant,
Role::Assistant => Role::System,
Role::System => Role::User,
}
}
}
impl Display for Role {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Role::User => write!(f, "User"),
Role::Assistant => write!(f, "Assistant"),
Role::System => write!(f, "System"),
}
}
}
#[derive(Deserialize, Debug)]
struct OpenAIResponseStreamEvent {
pub id: Option<String>,
pub object: String,
pub created: u32,
pub model: String,
pub choices: Vec<ChatChoiceDelta>,
pub usage: Option<Usage>,
}
#[derive(Deserialize, Debug)]
struct Usage {
pub prompt_tokens: u32,
pub completion_tokens: u32,
pub total_tokens: u32,
}
#[derive(Deserialize, Debug)]
struct ChatChoiceDelta {
pub index: u32,
pub delta: ResponseMessage,
pub finish_reason: Option<String>,
}
#[derive(Deserialize, Debug)]
struct OpenAIUsage {
prompt_tokens: u64,
completion_tokens: u64,
total_tokens: u64,
}
#[derive(Deserialize, Debug)]
struct OpenAIChoice {
text: String,
index: u32,
logprobs: Option<serde_json::Value>,
finish_reason: Option<String>,
}
pub fn init(cx: &mut AppContext) {
assistant::init(cx);
}

1525
crates/ai/src/assistant.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
use anyhow;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::Setting;
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AssistantDockPosition {
Left,
Right,
Bottom,
}
#[derive(Deserialize, Debug)]
pub struct AssistantSettings {
pub dock: AssistantDockPosition,
pub default_width: f32,
pub default_height: f32,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
pub struct AssistantSettingsContent {
pub dock: Option<AssistantDockPosition>,
pub default_width: Option<f32>,
pub default_height: Option<f32>,
}
impl Setting for AssistantSettings {
const KEY: Option<&'static str> = Some("assistant");
type FileContent = AssistantSettingsContent;
fn load(
default_value: &Self::FileContent,
user_values: &[&Self::FileContent],
_: &gpui::AppContext,
) -> anyhow::Result<Self> {
Self::load_via_json_merge(default_value, user_values)
}
}

View File

@@ -1,15 +0,0 @@
[package]
name = "assets"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
path = "src/assets.rs"
doctest = false
[dependencies]
gpui = { path = "../gpui" }
anyhow = "1.0.38"
rust-embed = { version = "6.3", features = ["include-exclude"] }

View File

@@ -1,29 +0,0 @@
use std::process::Command;
fn main() {
let output = Command::new("npm")
.current_dir("../../styles")
.args(["install", "--no-save"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"failed to install theme dependencies {}",
String::from_utf8_lossy(&output.stderr)
);
}
let output = Command::new("npm")
.current_dir("../../styles")
.args(["run", "build"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"build script failed {}",
String::from_utf8_lossy(&output.stderr)
);
}
println!("cargo:rerun-if-changed=../../styles/src");
}

View File

@@ -18,11 +18,12 @@ settings = { path = "../settings" }
theme = { path = "../theme" }
workspace = { path = "../workspace" }
util = { path = "../util" }
anyhow = "1.0.38"
isahc = "1.7"
lazy_static = "1.4"
log = "0.4"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
smol = "1.2.5"
tempdir = "0.3.7"
anyhow.workspace = true
isahc.workspace = true
lazy_static.workspace = true
log.workspace = true
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
smol.workspace = true
tempdir.workspace = true

View File

@@ -1,19 +1,21 @@
mod update_notification;
use anyhow::{anyhow, Context, Result};
use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN};
use client::{ZED_APP_PATH, ZED_APP_VERSION};
use client::{Client, TelemetrySettings, ZED_APP_PATH, ZED_APP_VERSION, ZED_SECRET_CLIENT_TOKEN};
use db::kvp::KEY_VALUE_STORE;
use gpui::{
actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
MutableAppContext, Task, WeakViewHandle,
Task, WeakViewHandle,
};
use isahc::AsyncBody;
use serde::Deserialize;
use settings::Settings;
use serde_derive::Serialize;
use settings::{Setting, SettingsStore};
use smol::{fs::File, io::AsyncReadExt, process::Command};
use std::{ffi::OsString, sync::Arc, time::Duration};
use update_notification::UpdateNotification;
use util::channel::ReleaseChannel;
use util::http::HttpClient;
use workspace::Workspace;
const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification";
@@ -21,6 +23,13 @@ const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60);
actions!(auto_update, [Check, DismissErrorMessage, ViewReleaseNotes]);
#[derive(Serialize)]
struct UpdateRequestBody {
installation_id: Option<Arc<str>>,
release_channel: Option<&'static str>,
telemetry: bool,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AutoUpdateStatus {
Idle,
@@ -49,24 +58,42 @@ impl Entity for AutoUpdater {
type Event = ();
}
pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut MutableAppContext) {
if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) {
let server_url = server_url;
let auto_updater = cx.add_model(|cx| {
let updater = AutoUpdater::new(version, http_client, server_url.clone());
struct AutoUpdateSetting(bool);
let mut update_subscription = cx
.global::<Settings>()
.auto_update
impl Setting for AutoUpdateSetting {
const KEY: Option<&'static str> = Some("auto_update");
type FileContent = Option<bool>;
fn load(
default_value: &Option<bool>,
user_values: &[&Option<bool>],
_: &AppContext,
) -> Result<Self> {
Ok(Self(
Self::json_merge(default_value, user_values)?.ok_or_else(Self::missing_default)?,
))
}
}
pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppContext) {
settings::register::<AutoUpdateSetting>(cx);
if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) {
let auto_updater = cx.add_model(|cx| {
let updater = AutoUpdater::new(version, http_client, server_url);
let mut update_subscription = settings::get::<AutoUpdateSetting>(cx)
.0
.then(|| updater.start_polling(cx));
cx.observe_global::<Settings, _>(move |updater, cx| {
if cx.global::<Settings>().auto_update {
cx.observe_global::<SettingsStore, _>(move |updater, cx| {
if settings::get::<AutoUpdateSetting>(cx).0 {
if update_subscription.is_none() {
*(&mut update_subscription) = Some(updater.start_polling(cx))
update_subscription = Some(updater.start_polling(cx))
}
} else {
(&mut update_subscription).take();
update_subscription.take();
}
})
.detach();
@@ -74,28 +101,35 @@ pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut Mutab
updater
});
cx.set_global(Some(auto_updater));
cx.add_global_action(|_: &Check, cx| {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
}
});
cx.add_global_action(move |_: &ViewReleaseNotes, cx| {
let latest_release_url = if cx.has_global::<ReleaseChannel>()
&& *cx.global::<ReleaseChannel>() == ReleaseChannel::Preview
{
format!("{server_url}/releases/preview/latest")
} else {
format!("{server_url}/releases/latest")
};
cx.platform().open_url(&latest_release_url);
});
cx.add_global_action(check);
cx.add_global_action(view_release_notes);
cx.add_action(UpdateNotification::dismiss);
}
}
pub fn check(_: &Check, cx: &mut AppContext) {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
}
}
fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) {
if let Some(auto_updater) = AutoUpdater::get(cx) {
let server_url = &auto_updater.read(cx).server_url;
let latest_release_url = if cx.has_global::<ReleaseChannel>()
&& *cx.global::<ReleaseChannel>() == ReleaseChannel::Preview
{
format!("{server_url}/releases/preview/latest")
} else {
format!("{server_url}/releases/stable/latest")
};
cx.platform().open_url(&latest_release_url);
}
}
pub fn notify_of_any_new_update(
workspace: WeakViewHandle<Workspace>,
cx: &mut MutableAppContext,
cx: &mut AppContext,
) -> Option<()> {
let updater = AutoUpdater::get(cx)?;
let version = updater.read(cx).current_version;
@@ -104,17 +138,15 @@ pub fn notify_of_any_new_update(
cx.spawn(|mut cx| async move {
let should_show_notification = should_show_notification.await?;
if should_show_notification {
if let Some(workspace) = workspace.upgrade(&cx) {
workspace.update(&mut cx, |workspace, cx| {
workspace.show_notification(0, cx, |cx| {
cx.add_view(|_| UpdateNotification::new(version))
});
updater
.read(cx)
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
workspace.update(&mut cx, |workspace, cx| {
workspace.show_notification(0, cx, |cx| {
cx.add_view(|_| UpdateNotification::new(version))
});
}
updater
.read(cx)
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
})?;
}
anyhow::Ok(())
})
@@ -124,7 +156,7 @@ pub fn notify_of_any_new_update(
}
impl AutoUpdater {
pub fn get(cx: &mut MutableAppContext) -> Option<ModelHandle<Self>> {
pub fn get(cx: &mut AppContext) -> Option<ModelHandle<Self>> {
cx.default_global::<Option<ModelHandle<Self>>>().clone()
}
@@ -243,7 +275,24 @@ impl AutoUpdater {
mounted_app_path.push("/");
let mut dmg_file = File::create(&dmg_path).await?;
let mut response = client.get(&release.url, Default::default(), true).await?;
let (installation_id, release_channel, telemetry) = cx.read(|cx| {
let installation_id = cx.global::<Arc<Client>>().telemetry().installation_id();
let release_channel = cx
.has_global::<ReleaseChannel>()
.then(|| cx.global::<ReleaseChannel>().display_name());
let telemetry = settings::get::<TelemetrySettings>(cx).metrics;
(installation_id, release_channel, telemetry)
});
let request_body = AsyncBody::from(serde_json::to_string(&UpdateRequestBody {
installation_id,
release_channel,
telemetry,
})?);
let mut response = client.get(&release.url, request_body, true).await?;
smol::io::copy(response.body_mut(), &mut dmg_file).await?;
log::info!("downloaded update. path:{:?}", dmg_path);

View File

@@ -1,11 +1,10 @@
use crate::ViewReleaseNotes;
use gpui::{
elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text},
platform::{AppVersion, CursorStyle},
Element, Entity, MouseButton, View, ViewContext,
platform::{AppVersion, CursorStyle, MouseButton},
Element, Entity, View, ViewContext,
};
use menu::Cancel;
use settings::Settings;
use util::channel::ReleaseChannel;
use workspace::notifications::Notification;
@@ -26,13 +25,13 @@ impl View for UpdateNotification {
"UpdateNotification"
}
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox {
let theme = cx.global::<Settings>().theme.clone();
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> gpui::AnyElement<Self> {
let theme = theme::current(cx).clone();
let theme = &theme.update_notification;
let app_name = cx.global::<ReleaseChannel>().display_name();
MouseEventHandler::<ViewReleaseNotes>::new(0, cx, |state, cx| {
MouseEventHandler::<ViewReleaseNotes, _>::new(0, cx, |state, cx| {
Flex::column()
.with_child(
Flex::row()
@@ -46,11 +45,10 @@ impl View for UpdateNotification {
.aligned()
.top()
.left()
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_child(
MouseEventHandler::<Cancel>::new(0, cx, |state, _| {
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
let style = theme.dismiss_button.style_for(state, false);
Svg::new("icons/x_mark_8.svg")
.with_color(style.color)
@@ -62,35 +60,32 @@ impl View for UpdateNotification {
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.boxed()
})
.with_padding(Padding::uniform(5.))
.on_click(MouseButton::Left, move |_, cx| cx.dispatch_action(Cancel))
.on_click(MouseButton::Left, move |_, this, cx| {
this.dismiss(&Default::default(), cx)
})
.aligned()
.constrained()
.with_height(cx.font_cache().line_height(theme.message.text.font_size))
.aligned()
.top()
.flex_float()
.boxed(),
)
.boxed(),
.flex_float(),
),
)
.with_child({
let style = theme.action_message.style_for(state, false);
Text::new("View the release notes", style.text.clone())
.contained()
.with_style(style.container)
.boxed()
})
.contained()
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(ViewReleaseNotes)
.on_click(MouseButton::Left, |_, _, cx| {
crate::view_release_notes(&Default::default(), cx)
})
.boxed()
.into_any_named("update notification")
}
}

View File

@@ -18,6 +18,7 @@ search = { path = "../search" }
settings = { path = "../settings" }
theme = { path = "../theme" }
workspace = { path = "../workspace" }
outline = { path = "../outline" }
itertools = "0.10"
[dev-dependencies]

View File

@@ -1,12 +1,12 @@
use gpui::{
elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
elements::*, platform::MouseButton, AppContext, Entity, Subscription, View, ViewContext,
ViewHandle, WeakViewHandle,
};
use itertools::Itertools;
use search::ProjectSearchView;
use settings::Settings;
use workspace::{
item::{ItemEvent, ItemHandle},
ToolbarItemLocation, ToolbarItemView,
ToolbarItemLocation, ToolbarItemView, Workspace,
};
pub enum Event {
@@ -14,17 +14,21 @@ pub enum Event {
}
pub struct Breadcrumbs {
pane_focused: bool,
active_item: Option<Box<dyn ItemHandle>>,
project_search: Option<ViewHandle<ProjectSearchView>>,
subscription: Option<Subscription>,
workspace: WeakViewHandle<Workspace>,
}
impl Breadcrumbs {
pub fn new() -> Self {
pub fn new(workspace: &Workspace) -> Self {
Self {
pane_focused: false,
active_item: Default::default(),
subscription: Default::default(),
project_search: Default::default(),
workspace: workspace.weak_handle(),
}
}
}
@@ -38,25 +42,67 @@ impl View for Breadcrumbs {
"Breadcrumbs"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone();
if let Some(breadcrumbs) = self
.active_item
.as_ref()
.and_then(|item| item.breadcrumbs(&theme, cx))
{
Flex::row()
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
Label::new("", theme.breadcrumbs.text.clone()).boxed()
}))
.contained()
.with_style(theme.breadcrumbs.container)
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let active_item = match &self.active_item {
Some(active_item) => active_item,
None => return Empty::new().into_any(),
};
let not_editor = active_item.downcast::<editor::Editor>().is_none();
let theme = theme::current(cx).clone();
let style = &theme.workspace.breadcrumbs;
let breadcrumbs = match active_item.breadcrumbs(&theme, cx) {
Some(breadcrumbs) => breadcrumbs,
None => return Empty::new().into_any(),
}
.into_iter()
.map(|breadcrumb| {
Text::new(
breadcrumb.text,
theme.workspace.breadcrumbs.default.text.clone(),
)
.with_highlights(breadcrumb.highlights.unwrap_or_default())
.into_any()
});
let crumbs = Flex::row()
.with_children(Itertools::intersperse_with(breadcrumbs, || {
Label::new("", style.default.text.clone()).into_any()
}))
.constrained()
.with_height(theme.workspace.breadcrumb_height)
.contained();
if not_editor || !self.pane_focused {
return crumbs
.with_style(style.default.container)
.aligned()
.left()
.boxed()
} else {
Empty::new().boxed()
.into_any();
}
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
let style = style.style_for(state, false);
crumbs.with_style(style.container)
})
.on_click(MouseButton::Left, |_, this, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
outline::toggle(workspace, &Default::default(), cx)
})
}
})
.with_tooltip::<Breadcrumbs>(
0,
"Show symbol outline".to_owned(),
Some(Box::new(outline::Toggle)),
theme.tooltip.clone(),
cx,
)
.aligned()
.left()
.into_any()
}
}
@@ -103,4 +149,8 @@ impl ToolbarItemView for Breadcrumbs {
current_location
}
}
fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext<Self>) {
self.pane_focused = pane_focused;
}
}

View File

@@ -22,7 +22,7 @@ test-support = [
client = { path = "../client" }
collections = { path = "../collections" }
gpui = { path = "../gpui" }
log = "0.4"
log.workspace = true
live_kit_client = { path = "../live_kit_client" }
fs = { path = "../fs" }
language = { path = "../language" }
@@ -31,10 +31,10 @@ project = { path = "../project" }
settings = { path = "../settings" }
util = { path = "../util" }
anyhow = "1.0.38"
anyhow.workspace = true
async-broadcast = "0.4"
futures = "0.3"
postage = { version = "0.4.1", features = ["futures-traits"] }
futures.workspace = true
postage.workspace = true
[dev-dependencies]
client = { path = "../client", features = ["test-support"] }

View File

@@ -10,15 +10,15 @@ use futures::{future::Shared, FutureExt};
use postage::watch;
use gpui::{
AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Subscription, Task, WeakModelHandle,
AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, Task,
WeakModelHandle,
};
use project::Project;
pub use participant::ParticipantLocation;
pub use room::Room;
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut AppContext) {
let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call);
}

View File

@@ -10,9 +10,7 @@ use client::{
use collections::{BTreeMap, HashMap, HashSet};
use fs::Fs;
use futures::{FutureExt, StreamExt};
use gpui::{
AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task, WeakModelHandle,
};
use gpui::{AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task, WeakModelHandle};
use language::LanguageRegistry;
use live_kit_client::{LocalTrackPublication, LocalVideoTrack, RemoteVideoTrackUpdate};
use postage::stream::Stream;
@@ -64,16 +62,13 @@ pub struct Room {
impl Entity for Room {
type Event = Event;
fn release(&mut self, cx: &mut MutableAppContext) {
fn release(&mut self, cx: &mut AppContext) {
if self.status.is_online() {
self.leave_internal(cx).detach_and_log_err(cx);
}
}
fn app_will_quit(
&mut self,
cx: &mut MutableAppContext,
) -> Option<Pin<Box<dyn Future<Output = ()>>>> {
fn app_will_quit(&mut self, cx: &mut AppContext) -> Option<Pin<Box<dyn Future<Output = ()>>>> {
if self.status.is_online() {
let leave = self.leave_internal(cx);
Some(
@@ -176,7 +171,7 @@ impl Room {
initial_project: Option<ModelHandle<Project>>,
client: Arc<Client>,
user_store: ModelHandle<UserStore>,
cx: &mut MutableAppContext,
cx: &mut AppContext,
) -> Task<Result<ModelHandle<Self>>> {
cx.spawn(|mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?;
@@ -219,7 +214,7 @@ impl Room {
call: &IncomingCall,
client: Arc<Client>,
user_store: ModelHandle<UserStore>,
cx: &mut MutableAppContext,
cx: &mut AppContext,
) -> Task<Result<ModelHandle<Self>>> {
let room_id = call.room_id;
cx.spawn(|mut cx| async move {
@@ -257,7 +252,7 @@ impl Room {
self.leave_internal(cx)
}
fn leave_internal(&mut self, cx: &mut MutableAppContext) -> Task<Result<()>> {
fn leave_internal(&mut self, cx: &mut AppContext) -> Task<Result<()>> {
if self.status.is_offline() {
return Task::ready(Err(anyhow!("room is offline")));
}
@@ -275,6 +270,7 @@ impl Room {
if let Some(project) = project.upgrade(cx) {
project.update(cx, |project, cx| {
project.disconnected_from_host(cx);
project.close(cx);
});
}
}
@@ -423,7 +419,7 @@ impl Room {
false
});
let response = self.client.request(proto::RejoinRoom {
let response = self.client.request_envelope(proto::RejoinRoom {
id: self.id,
reshared_projects,
rejoined_projects,
@@ -431,6 +427,8 @@ impl Room {
cx.spawn(|this, mut cx| async move {
let response = response.await?;
let message_id = response.message_id;
let response = response.payload;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
this.update(&mut cx, |this, cx| {
this.status = RoomStatus::Online;
@@ -447,7 +445,7 @@ impl Room {
for rejoined_project in response.rejoined_projects {
if let Some(project) = projects.get(&rejoined_project.id) {
project.update(cx, |project, cx| {
project.rejoined(rejoined_project, cx).log_err();
project.rejoined(rejoined_project, message_id, cx).log_err();
});
}
}
@@ -626,7 +624,7 @@ impl Room {
if let Some(live_kit) = this.live_kit.as_ref() {
let tracks =
live_kit.room.remote_video_tracks(&peer_id.to_string());
live_kit.room.remote_video_tracks(&user.id.to_string());
for track in tracks {
this.remote_video_track_updated(
RemoteVideoTrackUpdate::Subscribed(track),

View File

@@ -13,11 +13,13 @@ name = "cli"
path = "src/main.rs"
[dependencies]
anyhow = "1.0"
anyhow.workspace = true
clap = { version = "3.1", features = ["derive"] }
dirs = "3.0"
ipc-channel = "0.16"
serde = { version = "1.0", features = ["derive", "rc"] }
serde.workspace = true
serde_derive.workspace = true
util = { path = "../util" }
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"

View File

@@ -1,6 +1,5 @@
pub use ipc_channel::ipc;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Serialize, Deserialize)]
pub struct IpcHandshake {
@@ -10,7 +9,12 @@ pub struct IpcHandshake {
#[derive(Debug, Serialize, Deserialize)]
pub enum CliRequest {
Open { paths: Vec<PathBuf>, wait: bool },
// The filed is named `path` for compatibility, but now CLI can request
// opening a path at a certain row and/or column: `some/path:123` and `some/path:123:456`.
//
// Since Zed CLI has to be installed separately, there can be situations when old CLI is
// querying new Zed editors, support both formats by using `String` here and parsing it on Zed side later.
Open { paths: Vec<String>, wait: bool },
}
#[derive(Debug, Serialize, Deserialize)]
@@ -20,3 +24,7 @@ pub enum CliResponse {
Stderr { message: String },
Exit { status: i32 },
}
/// When Zed started not as an *.app but as a binary (e.g. local development),
/// there's a possibility to tell it to behave "regularly".
pub const FORCE_CLI_MODE_ENV_VAR_NAME: &str = "ZED_FORCE_CLI_MODE";

View File

@@ -1,6 +1,6 @@
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use clap::Parser;
use cli::{CliRequest, CliResponse, IpcHandshake};
use cli::{CliRequest, CliResponse, IpcHandshake, FORCE_CLI_MODE_ENV_VAR_NAME};
use core_foundation::{
array::{CFArray, CFIndex},
string::kCFStringEncodingUTF8,
@@ -16,16 +16,20 @@ use std::{
path::{Path, PathBuf},
ptr,
};
use util::paths::PathLikeWithPosition;
#[derive(Parser)]
#[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))]
struct Args {
/// Wait for all of the given paths to be closed before exiting.
/// Wait for all of the given paths to be opened/closed before exiting.
#[clap(short, long)]
wait: bool,
/// A sequence of space-separated paths that you want to open.
#[clap()]
paths: Vec<PathBuf>,
///
/// Use `path:line:row` syntax to open a file at a specific location.
/// Non-existing paths and directories will ignore `:line:row` suffix.
#[clap(value_parser = parse_path_with_position)]
paths_with_position: Vec<PathLikeWithPosition<PathBuf>>,
/// Print Zed's version and the app path.
#[clap(short, long)]
version: bool,
@@ -34,6 +38,14 @@ struct Args {
bundle_path: Option<PathBuf>,
}
fn parse_path_with_position(
argument_str: &str,
) -> Result<PathLikeWithPosition<PathBuf>, std::convert::Infallible> {
PathLikeWithPosition::parse_str(argument_str, |path_str| {
Ok(Path::new(path_str).to_path_buf())
})
}
#[derive(Debug, Deserialize)]
struct InfoPlist {
#[serde(rename = "CFBundleShortVersionString")]
@@ -43,37 +55,37 @@ struct InfoPlist {
fn main() -> Result<()> {
let args = Args::parse();
let bundle_path = if let Some(bundle_path) = args.bundle_path {
bundle_path.canonicalize()?
} else {
locate_bundle()?
};
let bundle = Bundle::detect(args.bundle_path.as_deref()).context("Bundle detection")?;
if args.version {
let plist_path = bundle_path.join("Contents/Info.plist");
let plist = plist::from_file::<_, InfoPlist>(plist_path)?;
println!(
"Zed {} {}",
plist.bundle_short_version_string,
bundle_path.to_string_lossy()
);
println!("{}", bundle.zed_version_string());
return Ok(());
}
for path in args.paths.iter() {
for path in args
.paths_with_position
.iter()
.map(|path_with_position| &path_with_position.path_like)
{
if !path.exists() {
touch(path.as_path())?;
}
}
let (tx, rx) = launch_app(bundle_path)?;
let (tx, rx) = bundle.launch()?;
tx.send(CliRequest::Open {
paths: args
.paths
.paths_with_position
.into_iter()
.map(|path| fs::canonicalize(path).map_err(|error| anyhow!(error)))
.collect::<Result<Vec<PathBuf>>>()?,
.map(|path_with_position| {
let path_with_position = path_with_position.map_path_like(|path| {
fs::canonicalize(&path)
.with_context(|| format!("path {path:?} canonicalization"))
})?;
Ok(path_with_position.to_string(|path| path.display().to_string()))
})
.collect::<Result<_>>()?,
wait: args.wait,
})?;
@@ -89,6 +101,145 @@ fn main() -> Result<()> {
Ok(())
}
enum Bundle {
App {
app_bundle: PathBuf,
plist: InfoPlist,
},
LocalPath {
executable: PathBuf,
plist: InfoPlist,
},
}
impl Bundle {
fn detect(args_bundle_path: Option<&Path>) -> anyhow::Result<Self> {
let bundle_path = if let Some(bundle_path) = args_bundle_path {
bundle_path
.canonicalize()
.with_context(|| format!("Args bundle path {bundle_path:?} canonicalization"))?
} else {
locate_bundle().context("bundle autodiscovery")?
};
match bundle_path.extension().and_then(|ext| ext.to_str()) {
Some("app") => {
let plist_path = bundle_path.join("Contents/Info.plist");
let plist = plist::from_file::<_, InfoPlist>(&plist_path).with_context(|| {
format!("Reading *.app bundle plist file at {plist_path:?}")
})?;
Ok(Self::App {
app_bundle: bundle_path,
plist,
})
}
_ => {
println!("Bundle path {bundle_path:?} has no *.app extension, attempting to locate a dev build");
let plist_path = bundle_path
.parent()
.with_context(|| format!("Bundle path {bundle_path:?} has no parent"))?
.join("WebRTC.framework/Resources/Info.plist");
let plist = plist::from_file::<_, InfoPlist>(&plist_path)
.with_context(|| format!("Reading dev bundle plist file at {plist_path:?}"))?;
Ok(Self::LocalPath {
executable: bundle_path,
plist,
})
}
}
}
fn plist(&self) -> &InfoPlist {
match self {
Self::App { plist, .. } => plist,
Self::LocalPath { plist, .. } => plist,
}
}
fn path(&self) -> &Path {
match self {
Self::App { app_bundle, .. } => app_bundle,
Self::LocalPath { executable, .. } => executable,
}
}
fn launch(&self) -> anyhow::Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
let (server, server_name) =
IpcOneShotServer::<IpcHandshake>::new().context("Handshake before Zed spawn")?;
let url = format!("zed-cli://{server_name}");
match self {
Self::App { app_bundle, .. } => {
let app_path = app_bundle;
let status = unsafe {
let app_url = CFURL::from_path(app_path, true)
.with_context(|| format!("invalid app path {app_path:?}"))?;
let url_to_open = CFURL::wrap_under_create_rule(CFURLCreateWithBytes(
ptr::null(),
url.as_ptr(),
url.len() as CFIndex,
kCFStringEncodingUTF8,
ptr::null(),
));
let urls_to_open = CFArray::from_copyable(&[url_to_open.as_concrete_TypeRef()]);
LSOpenFromURLSpec(
&LSLaunchURLSpec {
appURL: app_url.as_concrete_TypeRef(),
itemURLs: urls_to_open.as_concrete_TypeRef(),
passThruParams: ptr::null(),
launchFlags: kLSLaunchDefaults,
asyncRefCon: ptr::null_mut(),
},
ptr::null_mut(),
)
};
anyhow::ensure!(
status == 0,
"cannot start app bundle {}",
self.zed_version_string()
);
}
Self::LocalPath { executable, .. } => {
let executable_parent = executable
.parent()
.with_context(|| format!("Executable {executable:?} path has no parent"))?;
let subprocess_stdout_file =
fs::File::create(executable_parent.join("zed_dev.log"))
.with_context(|| format!("Log file creation in {executable_parent:?}"))?;
let subprocess_stdin_file =
subprocess_stdout_file.try_clone().with_context(|| {
format!("Cloning descriptor for file {subprocess_stdout_file:?}")
})?;
let mut command = std::process::Command::new(executable);
let command = command
.env(FORCE_CLI_MODE_ENV_VAR_NAME, "")
.stderr(subprocess_stdout_file)
.stdout(subprocess_stdin_file)
.arg(url);
command
.spawn()
.with_context(|| format!("Spawning {command:?}"))?;
}
}
let (_, handshake) = server.accept().context("Handshake after Zed spawn")?;
Ok((handshake.requests, handshake.responses))
}
fn zed_version_string(&self) -> String {
let is_dev = matches!(self, Self::LocalPath { .. });
format!(
"Zed {}{} {}",
self.plist().bundle_short_version_string,
if is_dev { " (dev)" } else { "" },
self.path().display(),
)
}
}
fn touch(path: &Path) -> io::Result<()> {
match OpenOptions::new().create(true).write(true).open(path) {
Ok(_) => Ok(()),
@@ -106,38 +257,3 @@ fn locate_bundle() -> Result<PathBuf> {
}
Ok(app_path)
}
fn launch_app(app_path: PathBuf) -> Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
let (server, server_name) = IpcOneShotServer::<IpcHandshake>::new()?;
let url = format!("zed-cli://{server_name}");
let status = unsafe {
let app_url =
CFURL::from_path(&app_path, true).ok_or_else(|| anyhow!("invalid app path"))?;
let url_to_open = CFURL::wrap_under_create_rule(CFURLCreateWithBytes(
ptr::null(),
url.as_ptr(),
url.len() as CFIndex,
kCFStringEncodingUTF8,
ptr::null(),
));
let urls_to_open = CFArray::from_copyable(&[url_to_open.as_concrete_TypeRef()]);
LSOpenFromURLSpec(
&LSLaunchURLSpec {
appURL: app_url.as_concrete_TypeRef(),
itemURLs: urls_to_open.as_concrete_TypeRef(),
passThruParams: ptr::null(),
launchFlags: kLSLaunchDefaults,
asyncRefCon: ptr::null_mut(),
},
ptr::null_mut(),
)
};
if status == 0 {
let (_, handshake) = server.accept()?;
Ok((handshake.requests, handshake.responses))
} else {
Err(anyhow!("cannot start {:?}", app_path))
}
}

View File

@@ -17,26 +17,29 @@ db = { path = "../db" }
gpui = { path = "../gpui" }
util = { path = "../util" }
rpc = { path = "../rpc" }
settings = { path = "../settings" }
staff_mode = { path = "../staff_mode" }
sum_tree = { path = "../sum_tree" }
anyhow = "1.0.38"
anyhow.workspace = true
async-recursion = "0.3"
async-tungstenite = { version = "0.16", features = ["async-tls"] }
futures = "0.3"
futures.workspace = true
image = "0.23"
isahc = "1.7"
lazy_static = "1.4.0"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
parking_lot = "0.11.1"
postage = { version = "0.4.1", features = ["futures-traits"] }
rand = "0.8.3"
smol = "1.2.5"
thiserror = "1.0.29"
time = { version = "0.3", features = ["serde", "serde-well-known"] }
lazy_static.workspace = true
log.workspace = true
parking_lot.workspace = true
postage.workspace = true
rand.workspace = true
schemars.workspace = true
smol.workspace = true
thiserror.workspace = true
time.workspace = true
tiny_http = "0.8"
uuid = { version = "1.1.2", features = ["v4"] }
url = "2.2"
serde = { version = "*", features = ["derive"] }
settings = { path = "../settings" }
serde.workspace = true
serde_derive.workspace = true
tempfile = "3"
[dev-dependencies]
@@ -44,3 +47,4 @@ collections = { path = "../collections", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
rpc = { path = "../rpc", features = ["test-support"] }
settings = { path = "../settings", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }

View File

@@ -1,7 +1,6 @@
#[cfg(any(test, feature = "test-support"))]
pub mod test;
pub mod http;
pub mod telemetry;
pub mod user;
@@ -11,21 +10,22 @@ use async_tungstenite::tungstenite::{
error::Error as WebsocketError,
http::{Request, StatusCode},
};
use futures::{future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryStreamExt};
use gpui::{
actions,
serde_json::{self, Value},
AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AppContext, AppVersion,
AsyncAppContext, Entity, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle,
use futures::{
future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _,
TryStreamExt,
};
use gpui::{
actions, platform::AppVersion, serde_json, AnyModelHandle, AnyWeakModelHandle,
AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, ModelHandle, Task, View, ViewContext,
WeakViewHandle,
};
use http::HttpClient;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use postage::watch;
use rand::prelude::*;
use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, PeerId, RequestMessage};
use serde::Deserialize;
use settings::{Settings, TelemetrySettings};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{
any::TypeId,
collections::HashMap,
@@ -41,9 +41,11 @@ use telemetry::Telemetry;
use thiserror::Error;
use url::Url;
use util::channel::ReleaseChannel;
use util::http::HttpClient;
use util::{ResultExt, TryFutureExt};
pub use rpc::*;
pub use telemetry::ClickhouseEvent;
pub use user::*;
lazy_static! {
@@ -66,27 +68,36 @@ pub const ZED_SECRET_CLIENT_TOKEN: &str = "618033988749894";
pub const INITIAL_RECONNECTION_DELAY: Duration = Duration::from_millis(100);
pub const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5);
actions!(client, [Authenticate, SignOut]);
actions!(client, [SignIn, SignOut]);
pub fn init(client: Arc<Client>, cx: &mut MutableAppContext) {
pub fn init_settings(cx: &mut AppContext) {
settings::register::<TelemetrySettings>(cx);
}
pub fn init(client: &Arc<Client>, cx: &mut AppContext) {
init_settings(cx);
let client = Arc::downgrade(client);
cx.add_global_action({
let client = client.clone();
move |_: &Authenticate, cx| {
let client = client.clone();
cx.spawn(
|cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
)
.detach();
move |_: &SignIn, cx| {
if let Some(client) = client.upgrade() {
cx.spawn(
|cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
)
.detach();
}
}
});
cx.add_global_action({
let client = client.clone();
move |_: &SignOut, cx| {
let client = client.clone();
cx.spawn(|cx| async move {
client.disconnect(&cx);
})
.detach();
if let Some(client) = client.upgrade() {
cx.spawn(|cx| async move {
client.disconnect(&cx);
})
.detach();
}
}
});
}
@@ -130,7 +141,7 @@ pub enum EstablishConnectionError {
#[error("{0}")]
Other(#[from] anyhow::Error),
#[error("{0}")]
Http(#[from] http::Error),
Http(#[from] util::http::Error),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
@@ -218,7 +229,7 @@ enum WeakSubscriber {
enum Subscriber {
Model(AnyModelHandle),
View(AnyViewHandle),
View(AnyWeakViewHandle),
}
#[derive(Clone, Debug)]
@@ -294,7 +305,7 @@ impl<T: Entity> PendingEntitySubscription<T> {
state
.entities_by_type_and_remote_id
.insert(id, WeakSubscriber::Model(model.downgrade().into()));
.insert(id, WeakSubscriber::Model(model.downgrade().into_any()));
drop(state);
for message in messages {
self.client.handle_message(message, cx);
@@ -322,6 +333,42 @@ impl<T: Entity> Drop for PendingEntitySubscription<T> {
}
}
#[derive(Copy, Clone)]
pub struct TelemetrySettings {
pub diagnostics: bool,
pub metrics: bool,
}
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema)]
pub struct TelemetrySettingsContent {
pub diagnostics: Option<bool>,
pub metrics: Option<bool>,
}
impl settings::Setting for TelemetrySettings {
const KEY: Option<&'static str> = Some("telemetry");
type FileContent = TelemetrySettingsContent;
fn load(
default_value: &Self::FileContent,
user_values: &[&Self::FileContent],
_: &AppContext,
) -> Result<Self> {
Ok(Self {
diagnostics: user_values.first().and_then(|v| v.diagnostics).unwrap_or(
default_value
.diagnostics
.ok_or_else(Self::missing_default)?,
),
metrics: user_values
.first()
.and_then(|v| v.metrics)
.unwrap_or(default_value.metrics.ok_or_else(Self::missing_default)?),
})
}
}
impl Client {
pub fn new(http: Arc<dyn HttpClient>, cx: &AppContext) -> Arc<Self> {
Arc::new(Self {
@@ -443,9 +490,7 @@ impl Client {
}));
}
Status::SignedOut | Status::UpgradeRequired => {
let telemetry_settings = cx.read(|cx| cx.global::<Settings>().telemetry());
self.telemetry
.set_authenticated_user_info(None, false, telemetry_settings);
cx.read(|cx| self.telemetry.set_authenticated_user_info(None, false, cx));
state._reconnect_task.take();
}
_ => {}
@@ -461,7 +506,7 @@ impl Client {
self.state
.write()
.entities_by_type_and_remote_id
.insert(id, WeakSubscriber::View(cx.weak_handle().into()));
.insert(id, WeakSubscriber::View(cx.weak_handle().into_any()));
Subscription::Entity {
client: Arc::downgrade(self),
id,
@@ -471,18 +516,22 @@ impl Client {
pub fn subscribe_to_entity<T: Entity>(
self: &Arc<Self>,
remote_id: u64,
) -> PendingEntitySubscription<T> {
) -> Result<PendingEntitySubscription<T>> {
let id = (TypeId::of::<T>(), remote_id);
self.state
.write()
.entities_by_type_and_remote_id
.insert(id, WeakSubscriber::Pending(Default::default()));
PendingEntitySubscription {
client: self.clone(),
remote_id,
consumed: false,
_entity_type: PhantomData,
let mut state = self.state.write();
if state.entities_by_type_and_remote_id.contains_key(&id) {
return Err(anyhow!("already subscribed to entity"));
} else {
state
.entities_by_type_and_remote_id
.insert(id, WeakSubscriber::Pending(Default::default()));
Ok(PendingEntitySubscription {
client: self.clone(),
remote_id,
consumed: false,
_entity_type: PhantomData,
})
}
}
@@ -505,7 +554,7 @@ impl Client {
let mut state = self.state.write();
state
.models_by_message_type
.insert(message_type_id, model.downgrade().into());
.insert(message_type_id, model.downgrade().into_any());
let prev_handler = state.message_handlers.insert(
message_type_id,
@@ -560,7 +609,7 @@ impl Client {
H: 'static
+ Send
+ Sync
+ Fn(ViewHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ Fn(WeakViewHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>>,
{
self.add_entity_message_handler::<M, E, _, _>(move |handle, message, client, cx| {
@@ -659,7 +708,7 @@ impl Client {
H: 'static
+ Send
+ Sync
+ Fn(ViewHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ Fn(WeakViewHandle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<M::Response>>,
{
self.add_view_message_handler(move |entity, envelope, client, cx| {
@@ -727,15 +776,6 @@ impl Client {
if credentials.is_none() && try_keychain {
credentials = read_credentials_from_keychain(cx);
read_from_keychain = credentials.is_some();
if read_from_keychain {
cx.read(|cx| {
self.report_event(
"read credentials from keychain",
Default::default(),
cx.global::<Settings>().telemetry(),
);
});
}
}
if credentials.is_none() {
let mut status_rx = self.status();
@@ -1023,9 +1063,7 @@ impl Client {
) -> Task<Result<Credentials>> {
let platform = cx.platform();
let executor = cx.background();
let telemetry = self.telemetry.clone();
let http = self.http.clone();
let metrics_enabled = cx.read(|cx| cx.global::<Settings>().telemetry());
executor.clone().spawn(async move {
// Generate a pair of asymmetric encryption keys. The public key will be used by the
@@ -1109,12 +1147,6 @@ impl Client {
.context("failed to decrypt access token")?;
platform.activate(true);
telemetry.report_event(
"authenticate with browser",
Default::default(),
metrics_enabled,
);
Ok(Credentials {
user_id: user_id.parse()?,
access_token,
@@ -1188,6 +1220,14 @@ impl Client {
&self,
request: T,
) -> impl Future<Output = Result<T::Response>> {
self.request_envelope(request)
.map_ok(|envelope| envelope.payload)
}
pub fn request_envelope<T: RequestMessage>(
&self,
request: T,
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
let client_id = self.id;
log::debug!(
"rpc request start. client_id:{}. name:{}",
@@ -1196,7 +1236,7 @@ impl Client {
);
let response = self
.connection_id()
.map(|conn_id| self.peer.request(conn_id, request));
.map(|conn_id| self.peer.request_envelope(conn_id, request));
async move {
let response = response?.await;
log::debug!(
@@ -1258,7 +1298,15 @@ impl Client {
pending.push(message);
return;
}
Some(weak_subscriber @ _) => subscriber = weak_subscriber.upgrade(cx),
Some(weak_subscriber @ _) => match weak_subscriber {
WeakSubscriber::Model(handle) => {
subscriber = handle.upgrade(cx).map(Subscriber::Model);
}
WeakSubscriber::View(handle) => {
subscriber = Some(Subscriber::View(handle.clone()));
}
WeakSubscriber::Pending(_) => {}
},
_ => {}
}
}
@@ -1315,40 +1363,8 @@ impl Client {
}
}
pub fn start_telemetry(&self) {
self.telemetry.start();
}
pub fn report_event(
&self,
kind: &str,
properties: Value,
telemetry_settings: TelemetrySettings,
) {
self.telemetry
.report_event(kind, properties.clone(), telemetry_settings);
}
pub fn telemetry_log_file_path(&self) -> Option<PathBuf> {
self.telemetry.log_file_path()
}
pub fn metrics_id(&self) -> Option<Arc<str>> {
self.telemetry.metrics_id()
}
pub fn is_staff(&self) -> Option<bool> {
self.telemetry.is_staff()
}
}
impl WeakSubscriber {
fn upgrade(&self, cx: &AsyncAppContext) -> Option<Subscriber> {
match self {
WeakSubscriber::Model(handle) => handle.upgrade(cx).map(Subscriber::Model),
WeakSubscriber::View(handle) => handle.upgrade(cx).map(Subscriber::View),
WeakSubscriber::Pending(_) => None,
}
pub fn telemetry(&self) -> &Arc<Telemetry> {
&self.telemetry
}
}
@@ -1396,10 +1412,11 @@ pub fn decode_worktree_url(url: &str) -> Option<(u64, String)> {
#[cfg(test)]
mod tests {
use super::*;
use crate::test::{FakeHttpClient, FakeServer};
use crate::test::FakeServer;
use gpui::{executor::Deterministic, TestAppContext};
use parking_lot::Mutex;
use std::future;
use util::http::FakeHttpClient;
#[gpui::test(iterations = 10)]
async fn test_reconnection(cx: &mut TestAppContext) {
@@ -1594,14 +1611,17 @@ mod tests {
let _subscription1 = client
.subscribe_to_entity(1)
.unwrap()
.set_model(&model1, &mut cx.to_async());
let _subscription2 = client
.subscribe_to_entity(2)
.unwrap()
.set_model(&model2, &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());
drop(subscription3);
@@ -1630,11 +1650,13 @@ mod tests {
},
);
drop(subscription1);
let _subscription2 =
client.add_message_handler(model, move |_, _: TypedEnvelope<proto::Ping>, _, _| {
let _subscription2 = client.add_message_handler(
model.clone(),
move |_, _: TypedEnvelope<proto::Ping>, _, _| {
done_tx2.try_send(()).unwrap();
async { Ok(()) }
});
},
);
server.send(proto::Ping {});
done_rx2.next().await.unwrap();
}

View File

@@ -1,57 +0,0 @@
pub use anyhow::{anyhow, Result};
use futures::future::BoxFuture;
use isahc::{
config::{Configurable, RedirectPolicy},
AsyncBody,
};
pub use isahc::{
http::{Method, Uri},
Error,
};
use smol::future::FutureExt;
use std::{sync::Arc, time::Duration};
pub use url::Url;
pub type Request = isahc::Request<AsyncBody>;
pub type Response = isahc::Response<AsyncBody>;
pub trait HttpClient: Send + Sync {
fn send(&self, req: Request) -> BoxFuture<Result<Response, Error>>;
fn get<'a>(
&'a self,
uri: &str,
body: AsyncBody,
follow_redirects: bool,
) -> BoxFuture<'a, Result<Response, Error>> {
let request = isahc::Request::builder()
.redirect_policy(if follow_redirects {
RedirectPolicy::Follow
} else {
RedirectPolicy::None
})
.method(Method::GET)
.uri(uri)
.body(body);
match request {
Ok(request) => self.send(request),
Err(error) => async move { Err(error.into()) }.boxed(),
}
}
}
pub fn client() -> Arc<dyn HttpClient> {
Arc::new(
isahc::HttpClient::builder()
.connect_timeout(Duration::from_secs(5))
.low_speed_timeout(100, Duration::from_secs(5))
.build()
.unwrap(),
)
}
impl HttpClient for isahc::HttpClient {
fn send(&self, req: Request) -> BoxFuture<Result<Response, Error>> {
Box::pin(async move { self.send_async(req).await })
}
}

View File

@@ -1,25 +1,13 @@
use crate::http::HttpClient;
use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
use db::kvp::KEY_VALUE_STORE;
use gpui::{
executor::Background,
serde_json::{self, value::Map, Value},
AppContext, Task,
};
use isahc::Request;
use gpui::{executor::Background, serde_json, AppContext, Task};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use serde::Serialize;
use serde_json::json;
use settings::TelemetrySettings;
use std::{
io::Write,
mem,
path::PathBuf,
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration};
use tempfile::NamedTempFile;
use util::{channel::ReleaseChannel, post_inc, ResultExt, TryFutureExt};
use util::http::HttpClient;
use util::{channel::ReleaseChannel, TryFutureExt};
use uuid::Uuid;
pub struct Telemetry {
@@ -30,66 +18,60 @@ pub struct Telemetry {
#[derive(Default)]
struct TelemetryState {
metrics_id: Option<Arc<str>>,
device_id: Option<Arc<str>>,
metrics_id: Option<Arc<str>>, // Per logged-in user
installation_id: Option<Arc<str>>, // Per app installation
app_version: Option<Arc<str>>,
release_channel: Option<&'static str>,
os_version: Option<Arc<str>>,
os_name: &'static str,
queue: Vec<MixpanelEvent>,
next_event_id: usize,
flush_task: Option<Task<()>>,
os_version: Option<Arc<str>>,
architecture: &'static str,
clickhouse_events_queue: Vec<ClickhouseEventWrapper>,
flush_clickhouse_events_task: Option<Task<()>>,
log_file: Option<NamedTempFile>,
is_staff: Option<bool>,
}
const MIXPANEL_EVENTS_URL: &'static str = "https://api.mixpanel.com/track";
const MIXPANEL_ENGAGE_URL: &'static str = "https://api.mixpanel.com/engage#profile-set";
const CLICKHOUSE_EVENTS_URL_PATH: &'static str = "/api/events";
lazy_static! {
static ref MIXPANEL_TOKEN: Option<String> = std::env::var("ZED_MIXPANEL_TOKEN")
.ok()
.or_else(|| option_env!("ZED_MIXPANEL_TOKEN").map(|key| key.to_string()));
static ref CLICKHOUSE_EVENTS_URL: String =
format!("{}{}", *ZED_SERVER_URL, CLICKHOUSE_EVENTS_URL_PATH);
}
#[derive(Serialize, Debug)]
struct MixpanelEvent {
event: String,
properties: MixpanelEventProperties,
}
#[derive(Serialize, Debug)]
struct MixpanelEventProperties {
// Mixpanel required fields
#[serde(skip_serializing_if = "str::is_empty")]
struct ClickhouseEventRequestBody {
token: &'static str,
time: u128,
distinct_id: Option<Arc<str>>,
#[serde(rename = "$insert_id")]
insert_id: usize,
// Custom fields
#[serde(skip_serializing_if = "Option::is_none", flatten)]
event_properties: Option<Map<String, Value>>,
#[serde(rename = "OS Name")]
os_name: &'static str,
#[serde(rename = "OS Version")]
os_version: Option<Arc<str>>,
#[serde(rename = "Release Channel")]
release_channel: Option<&'static str>,
#[serde(rename = "App Version")]
installation_id: Option<Arc<str>>,
app_version: Option<Arc<str>>,
#[serde(rename = "Signed In")]
signed_in: bool,
os_name: &'static str,
os_version: Option<Arc<str>>,
architecture: &'static str,
release_channel: Option<&'static str>,
events: Vec<ClickhouseEventWrapper>,
}
#[derive(Serialize)]
struct MixpanelEngageRequest {
#[serde(rename = "$token")]
token: &'static str,
#[serde(rename = "$distinct_id")]
distinct_id: Arc<str>,
#[serde(rename = "$set")]
set: Value,
#[derive(Serialize, Debug)]
struct ClickhouseEventWrapper {
signed_in: bool,
#[serde(flatten)]
event: ClickhouseEvent,
}
#[derive(Serialize, Debug)]
#[serde(tag = "type")]
pub enum ClickhouseEvent {
Editor {
operation: &'static str,
file_extension: Option<String>,
vim_mode: bool,
copilot_enabled: bool,
copilot_enabled_for_language: bool,
},
Copilot {
suggestion_id: Option<String>,
suggestion_accepted: bool,
file_extension: Option<String>,
},
}
#[cfg(debug_assertions)]
@@ -112,37 +94,25 @@ impl Telemetry {
} else {
None
};
// TODO: Replace all hardware stuff with nested SystemSpecs json
let this = Arc::new(Self {
http_client: client,
executor: cx.background().clone(),
state: Mutex::new(TelemetryState {
os_version: platform.os_version().ok().map(|v| v.to_string().into()),
os_name: platform.os_name().into(),
os_version: platform.os_version().ok().map(|v| v.to_string().into()),
architecture: env::consts::ARCH,
app_version: platform.app_version().ok().map(|v| v.to_string().into()),
release_channel,
device_id: None,
installation_id: None,
metrics_id: None,
queue: Default::default(),
flush_task: Default::default(),
next_event_id: 0,
clickhouse_events_queue: Default::default(),
flush_clickhouse_events_task: Default::default(),
log_file: None,
is_staff: None,
}),
});
if MIXPANEL_TOKEN.is_some() {
this.executor
.spawn({
let this = this.clone();
async move {
if let Some(tempfile) = NamedTempFile::new().log_err() {
this.state.lock().log_file = Some(tempfile);
}
}
})
.detach();
}
this
}
@@ -155,29 +125,27 @@ impl Telemetry {
self.executor
.spawn(
async move {
let device_id =
if let Ok(Some(device_id)) = KEY_VALUE_STORE.read_kvp("device_id") {
device_id
let installation_id =
if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp("device_id") {
installation_id
} else {
let device_id = Uuid::new_v4().to_string();
let installation_id = Uuid::new_v4().to_string();
KEY_VALUE_STORE
.write_kvp("device_id".to_string(), device_id.clone())
.write_kvp("device_id".to_string(), installation_id.clone())
.await?;
device_id
installation_id
};
let device_id: Arc<str> = device_id.into();
let installation_id: Arc<str> = installation_id.into();
let mut state = this.state.lock();
state.device_id = Some(device_id.clone());
for event in &mut state.queue {
event
.properties
.distinct_id
.get_or_insert_with(|| device_id.clone());
}
if !state.queue.is_empty() {
drop(state);
this.flush();
state.installation_id = Some(installation_id.clone());
let has_clickhouse_events = !state.clickhouse_events_queue.is_empty();
drop(state);
if has_clickhouse_events {
this.flush_clickhouse_events();
}
anyhow::Ok(())
@@ -193,89 +161,44 @@ impl Telemetry {
self: &Arc<Self>,
metrics_id: Option<String>,
is_staff: bool,
telemetry_settings: TelemetrySettings,
cx: &AppContext,
) {
if !telemetry_settings.metrics() {
if !settings::get::<TelemetrySettings>(cx).metrics {
return;
}
let this = self.clone();
let mut state = self.state.lock();
let device_id = state.device_id.clone();
let metrics_id: Option<Arc<str>> = metrics_id.map(|id| id.into());
state.metrics_id = metrics_id.clone();
state.is_staff = Some(is_staff);
drop(state);
if let Some((token, device_id)) = MIXPANEL_TOKEN.as_ref().zip(device_id) {
self.executor
.spawn(
async move {
let json_bytes = serde_json::to_vec(&[MixpanelEngageRequest {
token,
distinct_id: device_id,
set: json!({
"Staff": is_staff,
"ID": metrics_id,
"App": true
}),
}])?;
let request = Request::post(MIXPANEL_ENGAGE_URL)
.header("Content-Type", "application/json")
.body(json_bytes.into())?;
this.http_client.send(request).await?;
anyhow::Ok(())
}
.log_err(),
)
.detach();
}
}
pub fn report_event(
pub fn report_clickhouse_event(
self: &Arc<Self>,
kind: &str,
properties: Value,
event: ClickhouseEvent,
telemetry_settings: TelemetrySettings,
) {
if !telemetry_settings.metrics() {
if !telemetry_settings.metrics {
return;
}
let mut state = self.state.lock();
let event = MixpanelEvent {
event: kind.to_string(),
properties: MixpanelEventProperties {
token: "",
time: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis(),
distinct_id: state.device_id.clone(),
insert_id: post_inc(&mut state.next_event_id),
event_properties: if let Value::Object(properties) = properties {
Some(properties)
} else {
None
},
os_name: state.os_name,
os_version: state.os_version.clone(),
release_channel: state.release_channel,
app_version: state.app_version.clone(),
signed_in: state.metrics_id.is_some(),
},
};
state.queue.push(event);
if state.device_id.is_some() {
if state.queue.len() >= MAX_QUEUE_LEN {
let signed_in = state.metrics_id.is_some();
state
.clickhouse_events_queue
.push(ClickhouseEventWrapper { signed_in, event });
if state.installation_id.is_some() {
if state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN {
drop(state);
self.flush();
self.flush_clickhouse_events();
} else {
let this = self.clone();
let executor = self.executor.clone();
state.flush_task = Some(self.executor.spawn(async move {
state.flush_clickhouse_events_task = Some(self.executor.spawn(async move {
executor.timer(DEBOUNCE_INTERVAL).await;
this.flush();
this.flush_clickhouse_events();
}));
}
}
@@ -285,46 +208,62 @@ impl Telemetry {
self.state.lock().metrics_id.clone()
}
pub fn installation_id(self: &Arc<Self>) -> Option<Arc<str>> {
self.state.lock().installation_id.clone()
}
pub fn is_staff(self: &Arc<Self>) -> Option<bool> {
self.state.lock().is_staff
}
fn flush(self: &Arc<Self>) {
fn flush_clickhouse_events(self: &Arc<Self>) {
let mut state = self.state.lock();
let mut events = mem::take(&mut state.queue);
state.flush_task.take();
let mut events = mem::take(&mut state.clickhouse_events_queue);
state.flush_clickhouse_events_task.take();
drop(state);
if let Some(token) = MIXPANEL_TOKEN.as_ref() {
let this = self.clone();
self.executor
.spawn(
async move {
let mut json_bytes = Vec::new();
let this = self.clone();
self.executor
.spawn(
async move {
let mut json_bytes = Vec::new();
if let Some(file) = &mut this.state.lock().log_file {
let file = file.as_file_mut();
for event in &mut events {
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, event)?;
file.write_all(&json_bytes)?;
file.write(b"\n")?;
event.properties.token = token;
}
if let Some(file) = &mut this.state.lock().log_file {
let file = file.as_file_mut();
for event in &mut events {
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, event)?;
file.write_all(&json_bytes)?;
file.write(b"\n")?;
}
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, &events)?;
let request = Request::post(MIXPANEL_EVENTS_URL)
.header("Content-Type", "application/json")
.body(json_bytes.into())?;
this.http_client.send(request).await?;
anyhow::Ok(())
}
.log_err(),
)
.detach();
}
{
let state = this.state.lock();
json_bytes.clear();
serde_json::to_writer(
&mut json_bytes,
&ClickhouseEventRequestBody {
token: ZED_SECRET_CLIENT_TOKEN,
installation_id: state.installation_id.clone(),
app_version: state.app_version.clone(),
os_name: state.os_name,
os_version: state.os_version.clone(),
architecture: state.architecture,
release_channel: state.release_channel,
events,
},
)?;
}
this.http_client
.post_json(CLICKHOUSE_EVENTS_URL.as_str(), json_bytes.into())
.await?;
anyhow::Ok(())
}
.log_err(),
)
.detach();
}
}

View File

@@ -1,16 +1,14 @@
use crate::{
http::{self, HttpClient, Request, Response},
Client, Connection, Credentials, EstablishConnectionError, UserStore,
};
use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
use anyhow::{anyhow, Result};
use futures::{future::BoxFuture, stream::BoxStream, Future, StreamExt};
use futures::{stream::BoxStream, StreamExt};
use gpui::{executor, ModelHandle, TestAppContext};
use parking_lot::Mutex;
use rpc::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
ConnectionId, Peer, Receipt, TypedEnvelope,
};
use std::{fmt, rc::Rc, sync::Arc};
use std::{rc::Rc, sync::Arc};
use util::http::FakeHttpClient;
pub struct FakeServer {
peer: Arc<Peer>,
@@ -219,46 +217,3 @@ impl Drop for FakeServer {
self.disconnect();
}
}
pub struct FakeHttpClient {
handler: Box<
dyn 'static
+ Send
+ Sync
+ Fn(Request) -> BoxFuture<'static, Result<Response, http::Error>>,
>,
}
impl FakeHttpClient {
pub fn create<Fut, F>(handler: F) -> Arc<dyn HttpClient>
where
Fut: 'static + Send + Future<Output = Result<Response, http::Error>>,
F: 'static + Send + Sync + Fn(Request) -> Fut,
{
Arc::new(Self {
handler: Box::new(move |req| Box::pin(handler(req))),
})
}
pub fn with_404_response() -> Arc<dyn HttpClient> {
Self::create(|_| async move {
Ok(isahc::Response::builder()
.status(404)
.body(Default::default())
.unwrap())
})
}
}
impl fmt::Debug for FakeHttpClient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FakeHttpClient").finish()
}
}
impl HttpClient for FakeHttpClient {
fn send(&self, req: Request) -> BoxFuture<Result<Response, crate::http::Error>> {
let future = (self.handler)(req);
Box::pin(async move { future.await.map(Into::into) })
}
}

View File

@@ -1,13 +1,14 @@
use super::{http::HttpClient, proto, Client, Status, TypedEnvelope};
use super::{proto, Client, Status, TypedEnvelope};
use anyhow::{anyhow, Context, Result};
use collections::{hash_map::Entry, HashMap, HashSet};
use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
use postage::{sink::Sink, watch};
use rpc::proto::{RequestMessage, UsersResponse};
use settings::Settings;
use staff_mode::StaffMode;
use std::sync::{Arc, Weak};
use util::{StaffMode, TryFutureExt as _};
use util::http::HttpClient;
use util::TryFutureExt as _;
#[derive(Default, Debug)]
pub struct User {
@@ -142,11 +143,13 @@ impl UserStore {
let fetch_metrics_id =
client.request(proto::GetPrivateUserInfo {}).log_err();
let (user, info) = futures::join!(fetch_user, fetch_metrics_id);
client.telemetry.set_authenticated_user_info(
info.as_ref().map(|info| info.metrics_id.clone()),
info.as_ref().map(|info| info.staff).unwrap_or(false),
cx.read(|cx| cx.global::<Settings>().telemetry()),
);
cx.read(|cx| {
client.telemetry.set_authenticated_user_info(
info.as_ref().map(|info| info.metrics_id.clone()),
info.as_ref().map(|info| info.staff).unwrap_or(false),
cx,
)
});
cx.update(|cx| {
cx.update_default_global(|staff_mode: &mut StaffMode, _| {
@@ -183,6 +186,11 @@ impl UserStore {
}
}
#[cfg(feature = "test-support")]
pub fn clear_cache(&mut self) {
self.users.clear();
}
async fn handle_update_invite_info(
this: ModelHandle<Self>,
message: TypedEnvelope<proto::UpdateInviteInfo>,

View File

@@ -9,4 +9,4 @@ path = "src/clock.rs"
doctest = false
[dependencies]
smallvec = { version = "1.6", features = ["union"] }
smallvec.workspace = true

View File

@@ -66,6 +66,7 @@ impl<'a> AddAssign<&'a Local> for Local {
}
}
/// A vector clock
#[derive(Clone, Default, Hash, Eq, PartialEq)]
pub struct Global(SmallVec<[u32; 8]>);

View File

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathan@zed.dev>"]
default-run = "collab"
edition = "2021"
name = "collab"
version = "0.7.2"
version = "0.14.2"
publish = false
[[bin]]
@@ -19,7 +19,7 @@ live_kit_server = { path = "../live_kit_server" }
rpc = { path = "../rpc" }
util = { path = "../util" }
anyhow = "1.0.40"
anyhow.workspace = true
async-tungstenite = "0.16"
axum = { version = "0.5", features = ["json", "headers", "ws"] }
axum-extra = { version = "0.3", features = ["erased-json"] }
@@ -27,29 +27,31 @@ base64 = "0.13"
clap = { version = "3.1", features = ["derive"], optional = true }
dashmap = "5.4"
envy = "0.4.2"
futures = "0.3"
futures.workspace = true
hyper = "0.14"
lazy_static = "1.4"
lazy_static.workspace = true
lipsum = { version = "0.8", optional = true }
log.workspace = true
nanoid = "0.4"
parking_lot = "0.11.1"
parking_lot.workspace = true
prometheus = "0.13"
rand = "0.8"
rand.workspace = true
reqwest = { version = "0.11", features = ["json"], optional = true }
scrypt = "0.7"
# Remove fork dependency when a version with https://github.com/SeaQL/sea-orm/pull/1283 is released.
sea-orm = { git = "https://github.com/zed-industries/sea-orm", rev = "18f4c691085712ad014a51792af75a9044bacee6", features = ["sqlx-postgres", "postgres-array", "runtime-tokio-rustls"] }
sea-query = "0.27"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = "1.0"
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
sha-1 = "0.9"
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "postgres", "json", "time", "uuid", "any"] }
time = { version = "0.3", features = ["serde", "serde-well-known"] }
time.workspace = true
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.17"
tonic = "0.6"
tower = "0.4"
toml = "0.5.8"
toml.workspace = true
tracing = "0.1.34"
tracing-log = "0.1.3"
tracing-subscriber = { version = "0.3.11", features = ["env-filter", "json"] }
@@ -72,15 +74,15 @@ settings = { path = "../settings", features = ["test-support"] }
theme = { path = "../theme" }
workspace = { path = "../workspace", features = ["test-support"] }
ctor = "0.1"
env_logger = "0.9"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
ctor.workspace = true
env_logger.workspace = true
indoc.workspace = true
util = { path = "../util" }
lazy_static = "1.4"
lazy_static.workspace = true
sea-orm = { git = "https://github.com/zed-industries/sea-orm", rev = "18f4c691085712ad014a51792af75a9044bacee6", features = ["sqlx-sqlite"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
serde_json.workspace = true
sqlx = { version = "0.6", features = ["sqlite"] }
unindent = "0.1"
unindent.workspace = true
[features]
seed-support = ["clap", "lipsum", "reqwest"]

View File

@@ -104,6 +104,8 @@ spec:
key: secret
- name: INVITE_LINK_PREFIX
value: ${INVITE_LINK_PREFIX}
- name: RUST_BACKTRACE
value: "1"
- name: RUST_LOG
value: ${RUST_LOG}
- name: LOG_JSON

View File

@@ -76,12 +76,38 @@ CREATE TABLE "worktree_entries" (
"is_symlink" BOOL NOT NULL,
"is_ignored" BOOL NOT NULL,
"is_deleted" BOOL NOT NULL,
"git_status" INTEGER,
PRIMARY KEY(project_id, worktree_id, id),
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
);
CREATE INDEX "index_worktree_entries_on_project_id" ON "worktree_entries" ("project_id");
CREATE INDEX "index_worktree_entries_on_project_id_and_worktree_id" ON "worktree_entries" ("project_id", "worktree_id");
CREATE TABLE "worktree_repositories" (
"project_id" INTEGER NOT NULL,
"worktree_id" INTEGER NOT NULL,
"work_directory_id" INTEGER NOT NULL,
"branch" VARCHAR,
"scan_id" INTEGER NOT NULL,
"is_deleted" BOOL NOT NULL,
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
);
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");
CREATE TABLE "worktree_settings_files" (
"project_id" INTEGER NOT NULL,
"worktree_id" INTEGER NOT NULL,
"path" VARCHAR NOT NULL,
"content" TEXT,
PRIMARY KEY(project_id, worktree_id, path),
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
);
CREATE INDEX "index_worktree_settings_files_on_project_id" ON "worktree_settings_files" ("project_id");
CREATE INDEX "index_worktree_settings_files_on_project_id_and_worktree_id" ON "worktree_settings_files" ("project_id", "worktree_id");
CREATE TABLE "worktree_diagnostic_summaries" (
"project_id" INTEGER NOT NULL,
"worktree_id" INTEGER NOT NULL,
@@ -153,7 +179,7 @@ CREATE TABLE "followers" (
"follower_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
"follower_connection_id" INTEGER NOT NULL
);
CREATE UNIQUE INDEX
CREATE UNIQUE INDEX
"index_followers_on_project_id_and_leader_connection_server_id_and_leader_connection_id_and_follower_connection_server_id_and_follower_connection_id"
ON "followers" ("project_id", "leader_connection_server_id", "leader_connection_id", "follower_connection_server_id", "follower_connection_id");
CREATE INDEX "index_followers_on_room_id" ON "followers" ("room_id");

View File

@@ -0,0 +1,13 @@
CREATE TABLE "worktree_repositories" (
"project_id" INTEGER NOT NULL,
"worktree_id" INT8 NOT NULL,
"work_directory_id" INT8 NOT NULL,
"scan_id" INT8 NOT NULL,
"branch" VARCHAR,
"is_deleted" BOOL NOT NULL,
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
);
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");

View File

@@ -0,0 +1,15 @@
CREATE TABLE "worktree_repository_statuses" (
"project_id" INTEGER NOT NULL,
"worktree_id" INT8 NOT NULL,
"work_directory_id" INT8 NOT NULL,
"repo_path" VARCHAR NOT NULL,
"status" INT8 NOT NULL,
"scan_id" INT8 NOT NULL,
"is_deleted" BOOL NOT NULL,
PRIMARY KEY(project_id, worktree_id, work_directory_id, repo_path),
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
);
CREATE INDEX "index_wt_repos_statuses_on_project_id" ON "worktree_repository_statuses" ("project_id");
CREATE INDEX "index_wt_repos_statuses_on_project_id_and_wt_id" ON "worktree_repository_statuses" ("project_id", "worktree_id");
CREATE INDEX "index_wt_repos_statuses_on_project_id_and_wt_id_and_wd_id" ON "worktree_repository_statuses" ("project_id", "worktree_id", "work_directory_id");

View File

@@ -0,0 +1,10 @@
CREATE TABLE "worktree_settings_files" (
"project_id" INTEGER NOT NULL,
"worktree_id" INT8 NOT NULL,
"path" VARCHAR NOT NULL,
"content" TEXT NOT NULL,
PRIMARY KEY(project_id, worktree_id, path),
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
);
CREATE INDEX "index_settings_files_on_project_id" ON "worktree_settings_files" ("project_id");
CREATE INDEX "index_settings_files_on_project_id_and_wt_id" ON "worktree_settings_files" ("project_id", "worktree_id");

View File

@@ -0,0 +1,2 @@
ALTER TABLE "worktree_entries"
ADD "git_status" INT8;

View File

@@ -78,6 +78,7 @@ pub async fn validate_api_token<B>(req: Request<B>, next: Next<B>) -> impl IntoR
struct AuthenticatedUserParams {
github_user_id: Option<i32>,
github_login: String,
github_email: Option<String>,
}
#[derive(Debug, Serialize)]
@@ -92,7 +93,11 @@ async fn get_authenticated_user(
) -> Result<Json<AuthenticatedUserResponse>> {
let user = app
.db
.get_user_by_github_account(&params.github_login, params.github_user_id)
.get_or_create_user_by_github_account(
&params.github_login,
params.github_user_id,
params.github_email.as_deref(),
)
.await?
.ok_or_else(|| Error::Http(StatusCode::NOT_FOUND, "user not found".into()))?;
let metrics_id = app.db.get_user_metrics_id(user.id).await?;
@@ -297,11 +302,7 @@ async fn create_access_token(
let mut user_id = user.id;
if let Some(impersonate) = params.impersonate {
if user.admin {
if let Some(impersonated_user) = app
.db
.get_user_by_github_account(&impersonate, None)
.await?
{
if let Some(impersonated_user) = app.db.get_user_by_github_login(&impersonate).await? {
user_id = impersonated_user.id;
} else {
return Err(Error::Http(

View File

@@ -1,5 +1,5 @@
use crate::{
db::{self, UserId},
db::{self, AccessTokenId, Database, UserId},
AppState, Error, Result,
};
use anyhow::{anyhow, Context};
@@ -8,12 +8,24 @@ use axum::{
middleware::Next,
response::IntoResponse,
};
use lazy_static::lazy_static;
use prometheus::{exponential_buckets, register_histogram, Histogram};
use rand::thread_rng;
use scrypt::{
password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Scrypt,
};
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use std::{sync::Arc, time::Instant};
lazy_static! {
static ref METRIC_ACCESS_TOKEN_HASHING_TIME: Histogram = register_histogram!(
"access_token_hashing_time",
"time spent hashing access tokens",
exponential_buckets(10.0, 2.0, 10).unwrap(),
)
.unwrap();
}
pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse {
let mut auth_header = req
@@ -42,20 +54,14 @@ pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl Into
)
})?;
let mut credentials_valid = false;
let state = req.extensions().get::<Arc<AppState>>().unwrap();
if let Some(admin_token) = access_token.strip_prefix("ADMIN_TOKEN:") {
if state.config.api_token == admin_token {
credentials_valid = true;
}
let credentials_valid = if let Some(admin_token) = access_token.strip_prefix("ADMIN_TOKEN:") {
state.config.api_token == admin_token
} else {
for password_hash in state.db.get_access_token_hashes(user_id).await? {
if verify_access_token(access_token, &password_hash)? {
credentials_valid = true;
break;
}
}
}
verify_access_token(&access_token, user_id, &state.db)
.await
.unwrap_or(false)
};
if credentials_valid {
let user = state
@@ -75,13 +81,26 @@ pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl Into
const MAX_ACCESS_TOKENS_TO_STORE: usize = 8;
#[derive(Serialize, Deserialize)]
struct AccessTokenJson {
version: usize,
id: AccessTokenId,
token: String,
}
pub async fn create_access_token(db: &db::Database, user_id: UserId) -> Result<String> {
const VERSION: usize = 1;
let access_token = rpc::auth::random_token();
let access_token_hash =
hash_access_token(&access_token).context("failed to hash access token")?;
db.create_access_token_hash(user_id, &access_token_hash, MAX_ACCESS_TOKENS_TO_STORE)
let id = db
.create_access_token(user_id, &access_token_hash, MAX_ACCESS_TOKENS_TO_STORE)
.await?;
Ok(access_token)
Ok(serde_json::to_string(&AccessTokenJson {
version: VERSION,
id,
token: access_token,
})?)
}
fn hash_access_token(token: &str) -> Result<String> {
@@ -89,7 +108,7 @@ fn hash_access_token(token: &str) -> Result<String> {
let params = if cfg!(debug_assertions) {
scrypt::Params::new(1, 1, 1).unwrap()
} else {
scrypt::Params::recommended()
scrypt::Params::new(14, 8, 1).unwrap()
};
Ok(Scrypt
@@ -112,7 +131,21 @@ pub fn encrypt_access_token(access_token: &str, public_key: String) -> Result<St
Ok(encrypted_access_token)
}
pub fn verify_access_token(token: &str, hash: &str) -> Result<bool> {
let hash = PasswordHash::new(hash).map_err(anyhow::Error::new)?;
Ok(Scrypt.verify_password(token.as_bytes(), &hash).is_ok())
pub async fn verify_access_token(token: &str, user_id: UserId, db: &Arc<Database>) -> Result<bool> {
let token: AccessTokenJson = serde_json::from_str(&token)?;
let db_token = db.get_access_token(token.id).await?;
if db_token.user_id != user_id {
return Err(anyhow!("no such access token"))?;
}
let db_hash = PasswordHash::new(&db_token.hash).map_err(anyhow::Error::new)?;
let t0 = Instant::now();
let is_valid = Scrypt
.verify_password(token.token.as_bytes(), &db_hash)
.is_ok();
let duration = t0.elapsed();
log::info!("hashed access token in {:?}", duration);
METRIC_ACCESS_TOKEN_HASHING_TIME.observe(duration.as_millis() as f64);
Ok(is_valid)
}

View File

@@ -1,4 +1,4 @@
use collab::db;
use collab::{db, executor::Executor};
use db::{ConnectOptions, Database};
use serde::{de::DeserializeOwned, Deserialize};
use std::fmt::Write;
@@ -13,7 +13,7 @@ struct GitHubUser {
#[tokio::main]
async fn main() {
let database_url = std::env::var("DATABASE_URL").expect("missing DATABASE_URL env var");
let db = Database::new(ConnectOptions::new(database_url))
let db = Database::new(ConnectOptions::new(database_url), Executor::Production)
.await
.expect("failed to connect to postgres database");
let github_token = std::env::var("GITHUB_TOKEN").expect("missing GITHUB_TOKEN env var");
@@ -59,7 +59,7 @@ async fn main() {
for (github_user, admin) in zed_users {
if db
.get_user_by_github_account(&github_user.login, Some(github_user.id))
.get_user_by_github_login(&github_user.login)
.await
.expect("failed to fetch user")
.is_none()

View File

@@ -14,7 +14,11 @@ mod user;
mod worktree;
mod worktree_diagnostic_summary;
mod worktree_entry;
mod worktree_repository;
mod worktree_repository_statuses;
mod worktree_settings_file;
use crate::executor::Executor;
use crate::{Error, Result};
use anyhow::anyhow;
use collections::{BTreeMap, HashMap, HashSet};
@@ -22,6 +26,8 @@ pub use contact::Contact;
use dashmap::DashMap;
use futures::StreamExt;
use hyper::StatusCode;
use rand::prelude::StdRng;
use rand::{Rng, SeedableRng};
use rpc::{proto, ConnectionId};
use sea_orm::Condition;
pub use sea_orm::ConnectOptions;
@@ -46,20 +52,20 @@ pub struct Database {
options: ConnectOptions,
pool: DatabaseConnection,
rooms: DashMap<RoomId, Arc<Mutex<()>>>,
#[cfg(test)]
background: Option<std::sync::Arc<gpui::executor::Background>>,
rng: Mutex<StdRng>,
executor: Executor,
#[cfg(test)]
runtime: Option<tokio::runtime::Runtime>,
}
impl Database {
pub async fn new(options: ConnectOptions) -> Result<Self> {
pub async fn new(options: ConnectOptions, executor: Executor) -> Result<Self> {
Ok(Self {
options: options.clone(),
pool: sea_orm::Database::connect(options).await?,
rooms: DashMap::with_capacity(16384),
#[cfg(test)]
background: None,
rng: Mutex::new(StdRng::seed_from_u64(0)),
executor,
#[cfg(test)]
runtime: None,
})
@@ -172,25 +178,39 @@ impl Database {
.map(|participant| participant.user_id)
.collect::<Vec<_>>();
// Delete participants who failed to reconnect.
// Delete participants who failed to reconnect and cancel their calls.
let mut canceled_calls_to_user_ids = Vec::new();
room_participant::Entity::delete_many()
.filter(stale_participant_filter)
.exec(&*tx)
.await?;
let called_participants = room_participant::Entity::find()
.filter(
Condition::all()
.add(
room_participant::Column::CallingUserId
.is_in(stale_participant_user_ids.iter().copied()),
)
.add(room_participant::Column::AnsweringConnectionId.is_null()),
)
.all(&*tx)
.await?;
room_participant::Entity::delete_many()
.filter(
room_participant::Column::Id
.is_in(called_participants.iter().map(|participant| participant.id)),
)
.exec(&*tx)
.await?;
canceled_calls_to_user_ids.extend(
called_participants
.into_iter()
.map(|participant| participant.user_id),
);
let room = self.get_room(room_id, &tx).await?;
let mut canceled_calls_to_user_ids = Vec::new();
// Delete the room if it becomes empty and cancel pending calls.
// Delete the room if it becomes empty.
if room.participants.is_empty() {
canceled_calls_to_user_ids.extend(
room.pending_participants
.iter()
.map(|pending_participant| UserId::from_proto(pending_participant.user_id)),
);
room_participant::Entity::delete_many()
.filter(room_participant::Column::RoomId.eq(room_id))
.exec(&*tx)
.await?;
project::Entity::delete_many()
.filter(project::Column::RoomId.eq(room_id))
.exec(&*tx)
@@ -295,10 +315,21 @@ impl Database {
.await
}
pub async fn get_user_by_github_account(
pub async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>> {
self.transaction(|tx| async move {
Ok(user::Entity::find()
.filter(user::Column::GithubLogin.eq(github_login))
.one(&*tx)
.await?)
})
.await
}
pub async fn get_or_create_user_by_github_account(
&self,
github_login: &str,
github_user_id: Option<i32>,
github_email: Option<&str>,
) -> Result<Option<User>> {
self.transaction(|tx| async move {
let tx = &*tx;
@@ -320,7 +351,19 @@ impl Database {
user_by_github_login.github_user_id = ActiveValue::set(Some(github_user_id));
Ok(Some(user_by_github_login.update(tx).await?))
} else {
Ok(None)
let user = user::Entity::insert(user::ActiveModel {
email_address: ActiveValue::set(github_email.map(|email| email.into())),
github_login: ActiveValue::set(github_login.into()),
github_user_id: ActiveValue::set(Some(github_user_id)),
admin: ActiveValue::set(false),
invite_count: ActiveValue::set(0),
invite_code: ActiveValue::set(None),
metrics_id: ActiveValue::set(Uuid::new_v4()),
..Default::default()
})
.exec_with_returning(&*tx)
.await?;
Ok(Some(user))
}
} else {
Ok(user::Entity::find()
@@ -1449,7 +1492,10 @@ impl Database {
visible: db_worktree.visible,
updated_entries: Default::default(),
removed_entries: Default::default(),
updated_repositories: Default::default(),
removed_repositories: Default::default(),
diagnostic_summaries: Default::default(),
settings_files: Default::default(),
scan_id: db_worktree.scan_id as u64,
completed_scan_id: db_worktree.completed_scan_id as u64,
};
@@ -1458,38 +1504,78 @@ impl Database {
.worktrees
.iter()
.find(|worktree| worktree.id == db_worktree.id as u64);
let entry_filter = if let Some(rejoined_worktree) = rejoined_worktree {
worktree_entry::Column::ScanId.gt(rejoined_worktree.scan_id)
} else {
worktree_entry::Column::IsDeleted.eq(false)
};
let mut db_entries = worktree_entry::Entity::find()
.filter(
Condition::all()
.add(worktree_entry::Column::WorktreeId.eq(worktree.id))
.add(entry_filter),
)
.stream(&*tx)
.await?;
while let Some(db_entry) = db_entries.next().await {
let db_entry = db_entry?;
if db_entry.is_deleted {
worktree.removed_entries.push(db_entry.id as u64);
// File entries
{
let entry_filter = if let Some(rejoined_worktree) = rejoined_worktree {
worktree_entry::Column::ScanId.gt(rejoined_worktree.scan_id)
} else {
worktree.updated_entries.push(proto::Entry {
id: db_entry.id as u64,
is_dir: db_entry.is_dir,
path: db_entry.path,
inode: db_entry.inode as u64,
mtime: Some(proto::Timestamp {
seconds: db_entry.mtime_seconds as u64,
nanos: db_entry.mtime_nanos as u32,
}),
is_symlink: db_entry.is_symlink,
is_ignored: db_entry.is_ignored,
});
worktree_entry::Column::IsDeleted.eq(false)
};
let mut db_entries = worktree_entry::Entity::find()
.filter(
Condition::all()
.add(worktree_entry::Column::ProjectId.eq(project.id))
.add(worktree_entry::Column::WorktreeId.eq(worktree.id))
.add(entry_filter),
)
.stream(&*tx)
.await?;
while let Some(db_entry) = db_entries.next().await {
let db_entry = db_entry?;
if db_entry.is_deleted {
worktree.removed_entries.push(db_entry.id as u64);
} else {
worktree.updated_entries.push(proto::Entry {
id: db_entry.id as u64,
is_dir: db_entry.is_dir,
path: db_entry.path,
inode: db_entry.inode as u64,
mtime: Some(proto::Timestamp {
seconds: db_entry.mtime_seconds as u64,
nanos: db_entry.mtime_nanos as u32,
}),
is_symlink: db_entry.is_symlink,
is_ignored: db_entry.is_ignored,
git_status: db_entry.git_status.map(|status| status as i32),
});
}
}
}
// Repository Entries
{
let repository_entry_filter =
if let Some(rejoined_worktree) = rejoined_worktree {
worktree_repository::Column::ScanId.gt(rejoined_worktree.scan_id)
} else {
worktree_repository::Column::IsDeleted.eq(false)
};
let mut db_repositories = worktree_repository::Entity::find()
.filter(
Condition::all()
.add(worktree_repository::Column::ProjectId.eq(project.id))
.add(worktree_repository::Column::WorktreeId.eq(worktree.id))
.add(repository_entry_filter),
)
.stream(&*tx)
.await?;
while let Some(db_repository) = db_repositories.next().await {
let db_repository = db_repository?;
if db_repository.is_deleted {
worktree
.removed_repositories
.push(db_repository.work_directory_id as u64);
} else {
worktree.updated_repositories.push(proto::RepositoryEntry {
work_directory_id: db_repository.work_directory_id as u64,
branch: db_repository.branch,
});
}
}
}
@@ -1507,6 +1593,25 @@ impl Database {
})
.collect::<Vec<_>>();
{
let mut db_settings_files = worktree_settings_file::Entity::find()
.filter(worktree_settings_file::Column::ProjectId.eq(project_id))
.stream(&*tx)
.await?;
while let Some(db_settings_file) = db_settings_files.next().await {
let db_settings_file = db_settings_file?;
if let Some(worktree) = worktrees
.iter_mut()
.find(|w| w.id == db_settings_file.worktree_id as u64)
{
worktree.settings_files.push(WorktreeSettingsFile {
path: db_settings_file.path,
content: db_settings_file.content,
});
}
}
}
let mut collaborators = project
.find_related(project_collaborator::Entity)
.all(&*tx)
@@ -2244,6 +2349,7 @@ impl Database {
mtime_nanos: ActiveValue::set(mtime.nanos as i32),
is_symlink: ActiveValue::set(entry.is_symlink),
is_ignored: ActiveValue::set(entry.is_ignored),
git_status: ActiveValue::set(entry.git_status.map(|status| status as i64)),
is_deleted: ActiveValue::set(false),
scan_id: ActiveValue::set(update.scan_id as i64),
}
@@ -2262,6 +2368,7 @@ impl Database {
worktree_entry::Column::MtimeNanos,
worktree_entry::Column::IsSymlink,
worktree_entry::Column::IsIgnored,
worktree_entry::Column::GitStatus,
worktree_entry::Column::ScanId,
])
.to_owned(),
@@ -2290,6 +2397,53 @@ impl Database {
.await?;
}
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),
},
))
.on_conflict(
OnConflict::columns([
worktree_repository::Column::ProjectId,
worktree_repository::Column::WorktreeId,
worktree_repository::Column::WorkDirectoryId,
])
.update_columns([
worktree_repository::Column::ScanId,
worktree_repository::Column::Branch,
])
.to_owned(),
)
.exec(&*tx)
.await?;
}
if !update.removed_repositories.is_empty() {
worktree_repository::Entity::update_many()
.filter(
worktree_repository::Column::ProjectId
.eq(project_id)
.and(worktree_repository::Column::WorktreeId.eq(worktree_id))
.and(
worktree_repository::Column::WorkDirectoryId
.is_in(update.removed_repositories.iter().map(|id| *id as i64)),
),
)
.set(worktree_repository::ActiveModel {
is_deleted: ActiveValue::Set(true),
scan_id: ActiveValue::Set(update.scan_id as i64),
..Default::default()
})
.exec(&*tx)
.await?;
}
let connection_ids = self.project_guest_connection_ids(project_id, &tx).await?;
Ok(connection_ids)
})
@@ -2397,6 +2551,58 @@ impl Database {
.await
}
pub async fn update_worktree_settings(
&self,
update: &proto::UpdateWorktreeSettings,
connection: ConnectionId,
) -> Result<RoomGuard<Vec<ConnectionId>>> {
let project_id = ProjectId::from_proto(update.project_id);
let room_id = self.room_id_for_project(project_id).await?;
self.room_transaction(room_id, |tx| async move {
// Ensure the update comes from the host.
let project = project::Entity::find_by_id(project_id)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("no such project"))?;
if project.host_connection()? != connection {
return Err(anyhow!("can't update a project hosted by someone else"))?;
}
if let Some(content) = &update.content {
worktree_settings_file::Entity::insert(worktree_settings_file::ActiveModel {
project_id: ActiveValue::Set(project_id),
worktree_id: ActiveValue::Set(update.worktree_id as i64),
path: ActiveValue::Set(update.path.clone()),
content: ActiveValue::Set(content.clone()),
})
.on_conflict(
OnConflict::columns([
worktree_settings_file::Column::ProjectId,
worktree_settings_file::Column::WorktreeId,
worktree_settings_file::Column::Path,
])
.update_column(worktree_settings_file::Column::Content)
.to_owned(),
)
.exec(&*tx)
.await?;
} else {
worktree_settings_file::Entity::delete(worktree_settings_file::ActiveModel {
project_id: ActiveValue::Set(project_id),
worktree_id: ActiveValue::Set(update.worktree_id as i64),
path: ActiveValue::Set(update.path.clone()),
..Default::default()
})
.exec(&*tx)
.await?;
}
let connection_ids = self.project_guest_connection_ids(project_id, &tx).await?;
Ok(connection_ids)
})
.await
}
pub async fn join_project(
&self,
project_id: ProjectId,
@@ -2465,7 +2671,9 @@ impl Database {
root_name: db_worktree.root_name,
visible: db_worktree.visible,
entries: Default::default(),
repository_entries: Default::default(),
diagnostic_summaries: Default::default(),
settings_files: Default::default(),
scan_id: db_worktree.scan_id as u64,
completed_scan_id: db_worktree.completed_scan_id as u64,
},
@@ -2497,11 +2705,38 @@ impl Database {
}),
is_symlink: db_entry.is_symlink,
is_ignored: db_entry.is_ignored,
git_status: db_entry.git_status.map(|status| status as i32),
});
}
}
}
// Populate repository entries.
{
let mut db_repository_entries = worktree_repository::Entity::find()
.filter(
Condition::all()
.add(worktree_repository::Column::ProjectId.eq(project_id))
.add(worktree_repository::Column::IsDeleted.eq(false)),
)
.stream(&*tx)
.await?;
while let Some(db_repository_entry) = db_repository_entries.next().await {
let db_repository_entry = db_repository_entry?;
if let Some(worktree) =
worktrees.get_mut(&(db_repository_entry.worktree_id as u64))
{
worktree.repository_entries.insert(
db_repository_entry.work_directory_id as u64,
proto::RepositoryEntry {
work_directory_id: db_repository_entry.work_directory_id as u64,
branch: db_repository_entry.branch,
},
);
}
}
}
// Populate worktree diagnostic summaries.
{
let mut db_summaries = worktree_diagnostic_summary::Entity::find()
@@ -2523,6 +2758,25 @@ impl Database {
}
}
// Populate worktree settings files
{
let mut db_settings_files = worktree_settings_file::Entity::find()
.filter(worktree_settings_file::Column::ProjectId.eq(project_id))
.stream(&*tx)
.await?;
while let Some(db_settings_file) = db_settings_files.next().await {
let db_settings_file = db_settings_file?;
if let Some(worktree) =
worktrees.get_mut(&(db_settings_file.worktree_id as u64))
{
worktree.settings_files.push(WorktreeSettingsFile {
path: db_settings_file.path,
content: db_settings_file.content,
});
}
}
}
// Populate language servers.
let language_servers = project
.find_related(language_server::Entity)
@@ -2720,16 +2974,16 @@ impl Database {
// access tokens
pub async fn create_access_token_hash(
pub async fn create_access_token(
&self,
user_id: UserId,
access_token_hash: &str,
max_access_token_count: usize,
) -> Result<()> {
) -> Result<AccessTokenId> {
self.transaction(|tx| async {
let tx = tx;
access_token::ActiveModel {
let token = access_token::ActiveModel {
user_id: ActiveValue::set(user_id),
hash: ActiveValue::set(access_token_hash.into()),
..Default::default()
@@ -2752,26 +3006,20 @@ impl Database {
)
.exec(&*tx)
.await?;
Ok(())
Ok(token.id)
})
.await
}
pub async fn get_access_token_hashes(&self, user_id: UserId) -> Result<Vec<String>> {
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
enum QueryAs {
Hash,
}
pub async fn get_access_token(
&self,
access_token_id: AccessTokenId,
) -> Result<access_token::Model> {
self.transaction(|tx| async move {
Ok(access_token::Entity::find()
.select_only()
.column(access_token::Column::Hash)
.filter(access_token::Column::UserId.eq(user_id))
.order_by_desc(access_token::Column::Id)
.into_values::<_, QueryAs>()
.all(&*tx)
.await?)
Ok(access_token::Entity::find_by_id(access_token_id)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("no such access token"))?)
})
.await
}
@@ -2782,30 +3030,26 @@ impl Database {
Fut: Send + Future<Output = Result<T>>,
{
let body = async {
let mut i = 0;
loop {
let (tx, result) = self.with_transaction(&f).await?;
match result {
Ok(result) => {
match tx.commit().await.map_err(Into::into) {
Ok(()) => return Ok(result),
Err(error) => {
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
return Err(error);
}
Ok(result) => match tx.commit().await.map_err(Into::into) {
Ok(()) => return Ok(result),
Err(error) => {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
},
Err(error) => {
tx.rollback().await?;
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
i += 1;
}
};
@@ -2818,6 +3062,7 @@ impl Database {
Fut: Send + Future<Output = Result<Option<(RoomId, T)>>>,
{
let body = async {
let mut i = 0;
loop {
let (tx, result) = self.with_transaction(&f).await?;
match result {
@@ -2833,35 +3078,28 @@ impl Database {
}));
}
Err(error) => {
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
}
Ok(None) => {
match tx.commit().await.map_err(Into::into) {
Ok(()) => return Ok(None),
Err(error) => {
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
return Err(error);
}
Ok(None) => match tx.commit().await.map_err(Into::into) {
Ok(()) => return Ok(None),
Err(error) => {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
},
Err(error) => {
tx.rollback().await?;
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
i += 1;
}
};
@@ -2874,38 +3112,34 @@ impl Database {
Fut: Send + Future<Output = Result<T>>,
{
let body = async {
let mut i = 0;
loop {
let lock = self.rooms.entry(room_id).or_default().clone();
let _guard = lock.lock_owned().await;
let (tx, result) = self.with_transaction(&f).await?;
match result {
Ok(data) => {
match tx.commit().await.map_err(Into::into) {
Ok(()) => {
return Ok(RoomGuard {
data,
_guard,
_not_send: PhantomData,
});
}
Err(error) => {
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
return Err(error);
}
Ok(data) => match tx.commit().await.map_err(Into::into) {
Ok(()) => {
return Ok(RoomGuard {
data,
_guard,
_not_send: PhantomData,
});
}
Err(error) => {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
},
Err(error) => {
tx.rollback().await?;
if is_serialization_error(&error) {
// Retry (don't break the loop)
} else {
if !self.retry_on_serialization_error(&error, i).await {
return Err(error);
}
}
}
i += 1;
}
};
@@ -2931,14 +3165,14 @@ impl Database {
Ok((tx, result))
}
async fn run<F, T>(&self, future: F) -> T
async fn run<F, T>(&self, future: F) -> Result<T>
where
F: Future<Output = T>,
F: Future<Output = Result<T>>,
{
#[cfg(test)]
{
if let Some(background) = self.background.as_ref() {
background.simulate_random_delay().await;
if let Executor::Deterministic(executor) = &self.executor {
executor.simulate_random_delay().await;
}
self.runtime.as_ref().unwrap().block_on(future)
@@ -2949,6 +3183,27 @@ impl Database {
future.await
}
}
async fn retry_on_serialization_error(&self, error: &Error, prev_attempt_count: u32) -> bool {
// If the error is due to a failure to serialize concurrent transactions, then retry
// this transaction after a delay. With each subsequent retry, double the delay duration.
// Also vary the delay randomly in order to ensure different database connections retry
// at different times.
if is_serialization_error(error) {
let base_delay = 4_u64 << prev_attempt_count.min(16);
let randomized_delay = base_delay as f32 * self.rng.lock().await.gen_range(0.5..=2.0);
log::info!(
"retrying transaction after serialization error. delay: {} ms.",
randomized_delay
);
self.executor
.sleep(Duration::from_millis(randomized_delay as u64))
.await;
true
} else {
false
}
}
}
fn is_serialization_error(error: &Error) -> bool {
@@ -3182,7 +3437,10 @@ pub struct RejoinedWorktree {
pub visible: bool,
pub updated_entries: Vec<proto::Entry>,
pub removed_entries: Vec<u64>,
pub updated_repositories: Vec<proto::RepositoryEntry>,
pub removed_repositories: Vec<u64>,
pub diagnostic_summaries: Vec<proto::DiagnosticSummary>,
pub settings_files: Vec<WorktreeSettingsFile>,
pub scan_id: u64,
pub completed_scan_id: u64,
}
@@ -3236,11 +3494,19 @@ pub struct Worktree {
pub root_name: String,
pub visible: bool,
pub entries: Vec<proto::Entry>,
pub repository_entries: BTreeMap<u64, proto::RepositoryEntry>,
pub diagnostic_summaries: Vec<proto::DiagnosticSummary>,
pub settings_files: Vec<WorktreeSettingsFile>,
pub scan_id: u64,
pub completed_scan_id: u64,
}
#[derive(Debug)]
pub struct WorktreeSettingsFile {
pub path: String,
pub content: String,
}
#[cfg(test)]
pub use test::*;
@@ -3250,7 +3516,6 @@ mod test {
use gpui::executor::Background;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use rand::prelude::*;
use sea_orm::ConnectionTrait;
use sqlx::migrate::MigrateDatabase;
use std::sync::Arc;
@@ -3272,7 +3537,9 @@ mod test {
let mut db = runtime.block_on(async {
let mut options = ConnectOptions::new(url);
options.max_connections(5);
let db = Database::new(options).await.unwrap();
let db = Database::new(options, Executor::Deterministic(background))
.await
.unwrap();
let sql = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/migrations.sqlite/20221109000000_test_schema.sql"
@@ -3287,7 +3554,6 @@ mod test {
db
});
db.background = Some(background);
db.runtime = Some(runtime);
Self {
@@ -3321,13 +3587,14 @@ mod test {
options
.max_connections(5)
.idle_timeout(Duration::from_secs(0));
let db = Database::new(options).await.unwrap();
let db = Database::new(options, Executor::Deterministic(background))
.await
.unwrap();
let migrations_path = concat!(env!("CARGO_MANIFEST_DIR"), "/migrations");
db.migrate(Path::new(migrations_path), false).await.unwrap();
db
});
db.background = Some(background);
db.runtime = Some(runtime);
Self {

View File

@@ -92,8 +92,8 @@ test_both_dbs!(
);
test_both_dbs!(
test_get_user_by_github_account_postgres,
test_get_user_by_github_account_sqlite,
test_get_or_create_user_by_github_account_postgres,
test_get_or_create_user_by_github_account_sqlite,
db,
{
let user_id1 = db
@@ -124,7 +124,7 @@ test_both_dbs!(
.user_id;
let user = db
.get_user_by_github_account("login1", None)
.get_or_create_user_by_github_account("login1", None, None)
.await
.unwrap()
.unwrap();
@@ -133,19 +133,28 @@ test_both_dbs!(
assert_eq!(user.github_user_id, Some(101));
assert!(db
.get_user_by_github_account("non-existent-login", None)
.get_or_create_user_by_github_account("non-existent-login", None, None)
.await
.unwrap()
.is_none());
let user = db
.get_user_by_github_account("the-new-login2", Some(102))
.get_or_create_user_by_github_account("the-new-login2", Some(102), None)
.await
.unwrap()
.unwrap();
assert_eq!(user.id, user_id2);
assert_eq!(&user.github_login, "the-new-login2");
assert_eq!(user.github_user_id, Some(102));
let user = db
.get_or_create_user_by_github_account("login3", Some(103), Some("user3@example.com"))
.await
.unwrap()
.unwrap();
assert_eq!(&user.github_login, "login3");
assert_eq!(user.github_user_id, Some(103));
assert_eq!(user.email_address, Some("user3@example.com".into()));
}
);
@@ -168,30 +177,63 @@ test_both_dbs!(
.unwrap()
.user_id;
db.create_access_token_hash(user, "h1", 3).await.unwrap();
db.create_access_token_hash(user, "h2", 3).await.unwrap();
let token_1 = db.create_access_token(user, "h1", 2).await.unwrap();
let token_2 = db.create_access_token(user, "h2", 2).await.unwrap();
assert_eq!(
db.get_access_token_hashes(user).await.unwrap(),
&["h2".to_string(), "h1".to_string()]
db.get_access_token(token_1).await.unwrap(),
access_token::Model {
id: token_1,
user_id: user,
hash: "h1".into(),
}
);
assert_eq!(
db.get_access_token(token_2).await.unwrap(),
access_token::Model {
id: token_2,
user_id: user,
hash: "h2".into()
}
);
db.create_access_token_hash(user, "h3", 3).await.unwrap();
let token_3 = db.create_access_token(user, "h3", 2).await.unwrap();
assert_eq!(
db.get_access_token_hashes(user).await.unwrap(),
&["h3".to_string(), "h2".to_string(), "h1".to_string(),]
db.get_access_token(token_3).await.unwrap(),
access_token::Model {
id: token_3,
user_id: user,
hash: "h3".into()
}
);
assert_eq!(
db.get_access_token(token_2).await.unwrap(),
access_token::Model {
id: token_2,
user_id: user,
hash: "h2".into()
}
);
assert!(db.get_access_token(token_1).await.is_err());
db.create_access_token_hash(user, "h4", 3).await.unwrap();
let token_4 = db.create_access_token(user, "h4", 2).await.unwrap();
assert_eq!(
db.get_access_token_hashes(user).await.unwrap(),
&["h4".to_string(), "h3".to_string(), "h2".to_string(),]
db.get_access_token(token_4).await.unwrap(),
access_token::Model {
id: token_4,
user_id: user,
hash: "h4".into()
}
);
db.create_access_token_hash(user, "h5", 3).await.unwrap();
assert_eq!(
db.get_access_token_hashes(user).await.unwrap(),
&["h5".to_string(), "h4".to_string(), "h3".to_string()]
db.get_access_token(token_3).await.unwrap(),
access_token::Model {
id: token_3,
user_id: user,
hash: "h3".into()
}
);
assert!(db.get_access_token(token_2).await.is_err());
assert!(db.get_access_token(token_1).await.is_err());
}
);

View File

@@ -15,6 +15,7 @@ pub struct Model {
pub inode: i64,
pub mtime_seconds: i64,
pub mtime_nanos: i32,
pub git_status: Option<i64>,
pub is_symlink: bool,
pub is_ignored: bool,
pub is_deleted: bool,

View File

@@ -0,0 +1,21 @@
use super::ProjectId;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "worktree_repositories")]
pub struct Model {
#[sea_orm(primary_key)]
pub project_id: ProjectId,
#[sea_orm(primary_key)]
pub worktree_id: i64,
#[sea_orm(primary_key)]
pub work_directory_id: i64,
pub scan_id: i64,
pub branch: Option<String>,
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -0,0 +1,23 @@
use super::ProjectId;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "worktree_repository_statuses")]
pub struct Model {
#[sea_orm(primary_key)]
pub project_id: ProjectId,
#[sea_orm(primary_key)]
pub worktree_id: i64,
#[sea_orm(primary_key)]
pub work_directory_id: i64,
#[sea_orm(primary_key)]
pub repo_path: String,
pub status: i64,
pub scan_id: i64,
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -0,0 +1,19 @@
use super::ProjectId;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "worktree_settings_files")]
pub struct Model {
#[sea_orm(primary_key)]
pub project_id: ProjectId,
#[sea_orm(primary_key)]
pub worktree_id: i64,
#[sea_orm(primary_key)]
pub path: String,
pub content: String,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -10,6 +10,7 @@ mod tests;
use axum::{http::StatusCode, response::IntoResponse};
use db::Database;
use executor::Executor;
use serde::Deserialize;
use std::{path::PathBuf, sync::Arc};
@@ -118,7 +119,7 @@ impl AppState {
pub async fn new(config: Config) -> Result<Arc<Self>> {
let mut db_options = db::ConnectOptions::new(config.database_url.clone());
db_options.max_connections(config.database_max_connections);
let db = Database::new(db_options).await?;
let db = Database::new(db_options, Executor::Production).await?;
let live_kit_client = if let Some(((server, key), secret)) = config
.live_kit_server
.as_ref()

View File

@@ -32,7 +32,7 @@ async fn main() -> Result<()> {
let config = envy::from_env::<MigrateConfig>().expect("error loading config");
let mut db_options = db::ConnectOptions::new(config.database_url.clone());
db_options.max_connections(5);
let db = Database::new(db_options).await?;
let db = Database::new(db_options, Executor::Production).await?;
let migrations_path = config
.migrations_path

View File

@@ -51,7 +51,7 @@ use std::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc,
},
time::Duration,
time::{Duration, Instant},
};
use tokio::sync::{watch, Semaphore};
use tower::ServiceBuilder;
@@ -200,6 +200,7 @@ impl Server {
.add_message_handler(start_language_server)
.add_message_handler(update_language_server)
.add_message_handler(update_diagnostic_summary)
.add_message_handler(update_worktree_settings)
.add_request_handler(forward_project_request::<proto::GetHover>)
.add_request_handler(forward_project_request::<proto::GetDefinition>)
.add_request_handler(forward_project_request::<proto::GetTypeDefinition>)
@@ -223,12 +224,13 @@ impl Server {
.add_request_handler(forward_project_request::<proto::RenameProjectEntry>)
.add_request_handler(forward_project_request::<proto::CopyProjectEntry>)
.add_request_handler(forward_project_request::<proto::DeleteProjectEntry>)
.add_request_handler(forward_project_request::<proto::OnTypeFormatting>)
.add_message_handler(create_buffer_for_peer)
.add_request_handler(update_buffer)
.add_message_handler(update_buffer_file)
.add_message_handler(buffer_reloaded)
.add_message_handler(buffer_saved)
.add_request_handler(save_buffer)
.add_request_handler(forward_project_request::<proto::SaveBuffer>)
.add_request_handler(get_users)
.add_request_handler(fuzzy_search_users)
.add_request_handler(request_contact)
@@ -397,10 +399,16 @@ impl Server {
"message received"
);
});
let start_time = Instant::now();
let future = (handler)(*envelope, session);
async move {
if let Err(error) = future.await {
tracing::error!(%error, "error handling message");
let result = future.await;
let duration_ms = start_time.elapsed().as_micros() as f64 / 1000.0;
match result {
Err(error) => {
tracing::error!(%error, ?duration_ms, "error handling message")
}
Ok(()) => tracing::info!(?duration_ms, "finished handling message"),
}
}
.instrument(span)
@@ -1063,6 +1071,8 @@ async fn rejoin_room(
removed_entries: worktree.removed_entries,
scan_id: worktree.scan_id,
is_last_update: worktree.completed_scan_id == worktree.scan_id,
updated_repositories: worktree.updated_repositories,
removed_repositories: worktree.removed_repositories,
};
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
session.peer.send(session.connection_id, update.clone())?;
@@ -1079,6 +1089,18 @@ async fn rejoin_room(
},
)?;
}
for settings_file in worktree.settings_files {
session.peer.send(
session.connection_id,
proto::UpdateWorktreeSettings {
project_id: project.id.to_proto(),
worktree_id: worktree.id,
path: settings_file.path,
content: Some(settings_file.content),
},
)?;
}
}
for language_server in &project.language_servers {
@@ -1383,6 +1405,8 @@ async fn join_project(
removed_entries: Default::default(),
scan_id: worktree.scan_id,
is_last_update: worktree.scan_id == worktree.completed_scan_id,
updated_repositories: worktree.repository_entries.into_values().collect(),
removed_repositories: Default::default(),
};
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
session.peer.send(session.connection_id, update.clone())?;
@@ -1399,6 +1423,18 @@ async fn join_project(
},
)?;
}
for settings_file in worktree.settings_files {
session.peer.send(
session.connection_id,
proto::UpdateWorktreeSettings {
project_id: project_id.to_proto(),
worktree_id: worktree.id,
path: settings_file.path,
content: Some(settings_file.content),
},
)?;
}
}
for language_server in &project.language_servers {
@@ -1514,6 +1550,29 @@ async fn update_diagnostic_summary(
Ok(())
}
async fn update_worktree_settings(
message: proto::UpdateWorktreeSettings,
session: Session,
) -> Result<()> {
let guest_connection_ids = session
.db()
.await
.update_worktree_settings(&message, session.connection_id)
.await?;
broadcast(
Some(session.connection_id),
guest_connection_ids.iter().copied(),
|connection_id| {
session
.peer
.forward_send(session.connection_id, connection_id, message.clone())
},
);
Ok(())
}
async fn start_language_server(
request: proto::StartLanguageServer,
session: Session,
@@ -1591,51 +1650,6 @@ where
Ok(())
}
async fn save_buffer(
request: proto::SaveBuffer,
response: Response<proto::SaveBuffer>,
session: Session,
) -> Result<()> {
let project_id = ProjectId::from_proto(request.project_id);
let host_connection_id = {
let collaborators = session
.db()
.await
.project_collaborators(project_id, session.connection_id)
.await?;
collaborators
.iter()
.find(|collaborator| collaborator.is_host)
.ok_or_else(|| anyhow!("host not found"))?
.connection_id
};
let response_payload = session
.peer
.forward_request(session.connection_id, host_connection_id, request.clone())
.await?;
let mut collaborators = session
.db()
.await
.project_collaborators(project_id, session.connection_id)
.await?;
collaborators.retain(|collaborator| collaborator.connection_id != session.connection_id);
let project_connection_ids = collaborators
.iter()
.map(|collaborator| collaborator.connection_id);
broadcast(
Some(host_connection_id),
project_connection_ids,
|conn_id| {
session
.peer
.forward_send(host_connection_id, conn_id, response_payload.clone())
},
);
response.send(response_payload)?;
Ok(())
}
async fn create_buffer_for_peer(
request: proto::CreateBufferForPeer,
session: Session,
@@ -1655,23 +1669,42 @@ async fn update_buffer(
) -> Result<()> {
session.executor.record_backtrace();
let project_id = ProjectId::from_proto(request.project_id);
let project_connection_ids = session
.db()
.await
.project_connection_ids(project_id, session.connection_id)
.await?;
let mut guest_connection_ids;
let mut host_connection_id = None;
{
let collaborators = session
.db()
.await
.project_collaborators(project_id, session.connection_id)
.await?;
guest_connection_ids = Vec::with_capacity(collaborators.len() - 1);
for collaborator in collaborators.iter() {
if collaborator.is_host {
host_connection_id = Some(collaborator.connection_id);
} else {
guest_connection_ids.push(collaborator.connection_id);
}
}
}
let host_connection_id = host_connection_id.ok_or_else(|| anyhow!("host not found"))?;
session.executor.record_backtrace();
broadcast(
Some(session.connection_id),
project_connection_ids.iter().copied(),
guest_connection_ids,
|connection_id| {
session
.peer
.forward_send(session.connection_id, connection_id, request.clone())
},
);
if host_connection_id != session.connection_id {
session
.peer
.forward_request(session.connection_id, host_connection_id, request.clone())
.await?;
}
response.send(proto::Ack {})?;
Ok(())
}
@@ -1875,7 +1908,7 @@ async fn fuzzy_search_users(
1 | 2 => session
.db()
.await
.get_user_by_github_account(&query, None)
.get_user_by_github_login(&query)
.await?
.into_iter()
.collect(),

View File

@@ -7,29 +7,30 @@ use crate::{
use anyhow::anyhow;
use call::ActiveCall;
use client::{
self, proto::PeerId, test::FakeHttpClient, Client, Connection, Credentials,
EstablishConnectionError, UserStore,
self, proto::PeerId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
};
use collections::{HashMap, HashSet};
use fs::FakeFs;
use futures::{channel::oneshot, StreamExt as _};
use gpui::{
executor::Deterministic, test::EmptyView, ModelHandle, Task, TestAppContext, ViewHandle,
elements::*, executor::Deterministic, AnyElement, Entity, ModelHandle, TestAppContext, View,
ViewContext, ViewHandle, WeakViewHandle,
};
use language::LanguageRegistry;
use parking_lot::Mutex;
use project::{Project, WorktreeId};
use settings::Settings;
use settings::SettingsStore;
use std::{
cell::{Ref, RefCell, RefMut},
env,
ops::Deref,
path::{Path, PathBuf},
ops::{Deref, DerefMut},
path::Path,
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
Arc,
},
};
use theme::ThemeRegistry;
use util::http::FakeHttpClient;
use workspace::Workspace;
mod integration_tests;
@@ -100,15 +101,11 @@ impl TestServer {
async fn create_client(&mut self, cx: &mut TestAppContext, name: &str) -> TestClient {
cx.update(|cx| {
cx.set_global(Settings::test(cx));
cx.set_global(SettingsStore::test(cx));
});
let http = FakeHttpClient::with_404_response();
let user_id = if let Ok(Some(user)) = self
.app_state
.db
.get_user_by_github_account(name, None)
.await
let user_id = if let Ok(Some(user)) = self.app_state.db.get_user_by_github_login(name).await
{
user.id
} else {
@@ -192,17 +189,19 @@ impl TestServer {
let app_state = Arc::new(workspace::AppState {
client: client.clone(),
user_store: user_store.clone(),
languages: Arc::new(LanguageRegistry::new(Task::ready(()))),
themes: ThemeRegistry::new((), cx.font_cache()),
languages: Arc::new(LanguageRegistry::test()),
fs: fs.clone(),
build_window_options: |_, _, _| Default::default(),
initialize_workspace: |_, _, _| unimplemented!(),
dock_default_item_factory: |_, _| None,
initialize_workspace: |_, _, _, _| unimplemented!(),
background_actions: || &[],
});
Project::init(&client);
cx.update(|cx| {
theme::init((), cx);
Project::init(&client, cx);
client::init(&client, cx);
language::init(cx);
editor::init_settings(cx);
workspace::init(app_state.clone(), cx);
call::init(client.clone(), user_store.clone(), cx);
});
@@ -215,13 +214,10 @@ impl TestServer {
let client = TestClient {
client,
username: name.to_string(),
local_projects: Default::default(),
remote_projects: Default::default(),
next_root_dir_id: 0,
state: Default::default(),
user_store,
fs,
language_registry: Arc::new(LanguageRegistry::test()),
buffers: Default::default(),
};
client.wait_for_current_user(cx).await;
client
@@ -320,12 +316,16 @@ impl Drop for TestServer {
struct TestClient {
client: Arc<Client>,
username: String,
local_projects: Vec<ModelHandle<Project>>,
remote_projects: Vec<ModelHandle<Project>>,
next_root_dir_id: usize,
state: RefCell<TestClientState>,
pub user_store: ModelHandle<UserStore>,
language_registry: Arc<LanguageRegistry>,
fs: Arc<FakeFs>,
}
#[derive(Default)]
struct TestClientState {
local_projects: Vec<ModelHandle<Project>>,
remote_projects: Vec<ModelHandle<Project>>,
buffers: HashMap<ModelHandle<Project>, HashSet<ModelHandle<language::Buffer>>>,
}
@@ -364,6 +364,38 @@ impl TestClient {
.await;
}
fn local_projects<'a>(&'a self) -> impl Deref<Target = Vec<ModelHandle<Project>>> + 'a {
Ref::map(self.state.borrow(), |state| &state.local_projects)
}
fn remote_projects<'a>(&'a self) -> impl Deref<Target = Vec<ModelHandle<Project>>> + 'a {
Ref::map(self.state.borrow(), |state| &state.remote_projects)
}
fn local_projects_mut<'a>(&'a self) -> impl DerefMut<Target = Vec<ModelHandle<Project>>> + 'a {
RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects)
}
fn remote_projects_mut<'a>(&'a self) -> impl DerefMut<Target = Vec<ModelHandle<Project>>> + 'a {
RefMut::map(self.state.borrow_mut(), |state| &mut state.remote_projects)
}
fn buffers_for_project<'a>(
&'a self,
project: &ModelHandle<Project>,
) -> impl DerefMut<Target = HashSet<ModelHandle<language::Buffer>>> + 'a {
RefMut::map(self.state.borrow_mut(), |state| {
state.buffers.entry(project.clone()).or_default()
})
}
fn buffers<'a>(
&'a self,
) -> impl DerefMut<Target = HashMap<ModelHandle<Project>, HashSet<ModelHandle<language::Buffer>>>> + 'a
{
RefMut::map(self.state.borrow_mut(), |state| &mut state.buffers)
}
fn summarize_contacts(&self, cx: &TestAppContext) -> ContactsSummary {
self.user_store.read_with(cx, |store, _| ContactsSummary {
current: store
@@ -434,17 +466,41 @@ impl TestClient {
project: &ModelHandle<Project>,
cx: &mut TestAppContext,
) -> ViewHandle<Workspace> {
let (_, root_view) = cx.add_window(|_| EmptyView);
cx.add_view(&root_view, |cx| Workspace::test_new(project.clone(), cx))
}
struct WorkspaceContainer {
workspace: Option<WeakViewHandle<Workspace>>,
}
fn create_new_root_dir(&mut self) -> PathBuf {
format!(
"/{}-root-{}",
self.username,
util::post_inc(&mut self.next_root_dir_id)
)
.into()
impl Entity for WorkspaceContainer {
type Event = ();
}
impl View for WorkspaceContainer {
fn ui_name() -> &'static str {
"WorkspaceContainer"
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
if let Some(workspace) = self
.workspace
.as_ref()
.and_then(|workspace| workspace.upgrade(cx))
{
ChildView::new(&workspace, cx).into_any()
} else {
Empty::new().into_any()
}
}
}
// We use a workspace container so that we don't need to remove the window in order to
// drop the workspace and we can use a ViewHandle instead.
let (window_id, container) = cx.add_window(|_| WorkspaceContainer { workspace: None });
let workspace = cx.add_view(window_id, |cx| Workspace::test_new(project.clone(), cx));
container.update(cx, |container, cx| {
container.workspace = Some(workspace.downgrade());
cx.notify();
});
workspace
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -39,11 +39,13 @@ settings = { path = "../settings" }
theme = { path = "../theme" }
util = { path = "../util" }
workspace = { path = "../workspace" }
anyhow = "1.0"
futures = "0.3"
log = "0.4"
postage = { version = "0.4.1", features = ["futures-traits"] }
serde = { version = "1.0", features = ["derive", "rc"] }
anyhow.workspace = true
futures.workspace = true
log.workspace = true
postage.workspace = true
serde.workspace = true
serde_derive.workspace = true
[dev-dependencies]
call = { path = "../call", features = ["test-support"] }

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
mod collab_titlebar_item;
mod collaborator_list_popover;
mod contact_finder;
mod contact_list;
mod contact_notification;
@@ -10,32 +9,27 @@ mod notifications;
mod project_shared_notification;
mod sharing_status_indicator;
use anyhow::anyhow;
use call::ActiveCall;
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleContactsMenu};
use gpui::{actions, MutableAppContext, Task};
use gpui::{actions, AppContext, Task};
use std::sync::Arc;
use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
use workspace::AppState;
actions!(collab, [ToggleScreenSharing]);
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
collab_titlebar_item::init(cx);
contact_notification::init(cx);
contact_list::init(cx);
contact_finder::init(cx);
contacts_popover::init(cx);
incoming_call_notification::init(cx);
project_shared_notification::init(cx);
incoming_call_notification::init(&app_state, cx);
project_shared_notification::init(&app_state, cx);
sharing_status_indicator::init(cx);
cx.add_global_action(toggle_screen_sharing);
cx.add_global_action(move |action: &JoinProject, cx| {
join_project(action, app_state.clone(), cx);
});
}
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let toggle_screen_sharing = room.update(cx, |room, cx| {
if room.is_screen_sharing() {
@@ -47,88 +41,3 @@ pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext
toggle_screen_sharing.detach_and_log_err(cx);
}
}
fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut MutableAppContext) {
let project_id = action.project_id;
let follow_user_id = action.follow_user_id;
cx.spawn(|mut cx| async move {
let existing_workspace = cx.update(|cx| {
cx.window_ids()
.filter_map(|window_id| cx.root_view::<Workspace>(window_id))
.find(|workspace| {
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
})
});
let workspace = if let Some(existing_workspace) = existing_workspace {
existing_workspace
} else {
let active_call = cx.read(ActiveCall::global);
let room = active_call
.read_with(&cx, |call, _| call.room().cloned())
.ok_or_else(|| anyhow!("not in a call"))?;
let project = room
.update(&mut cx, |room, cx| {
room.join_project(
project_id,
app_state.languages.clone(),
app_state.fs.clone(),
cx,
)
})
.await?;
let (_, workspace) = cx.add_window(
(app_state.build_window_options)(None, None, cx.platform().as_ref()),
|cx| {
let mut workspace = Workspace::new(
Default::default(),
0,
project,
app_state.dock_default_item_factory,
app_state.background_actions,
cx,
);
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
workspace
},
);
workspace
};
cx.activate_window(workspace.window_id());
cx.platform().activate(true);
workspace.update(&mut cx, |workspace, cx| {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let follow_peer_id = room
.read(cx)
.remote_participants()
.iter()
.find(|(_, participant)| participant.user.id == follow_user_id)
.map(|(_, p)| p.peer_id)
.or_else(|| {
// If we couldn't follow the given user, follow the host instead.
let collaborator = workspace
.project()
.read(cx)
.collaborators()
.values()
.find(|collaborator| collaborator.replica_id == 0)?;
Some(collaborator.peer_id)
});
if let Some(follow_peer_id) = follow_peer_id {
if !workspace.is_being_followed(follow_peer_id) {
workspace
.toggle_follow(&ToggleFollow(follow_peer_id), cx)
.map(|follow| follow.detach_and_log_err(cx));
}
}
}
});
anyhow::Ok(())
})
.detach_and_log_err(cx);
}

View File

@@ -1,165 +0,0 @@
use call::ActiveCall;
use client::UserStore;
use gpui::Action;
use gpui::{
actions, elements::*, Entity, ModelHandle, MouseButton, RenderContext, View, ViewContext,
};
use settings::Settings;
use crate::collab_titlebar_item::ToggleCollaboratorList;
pub(crate) enum Event {
Dismissed,
}
enum Collaborator {
SelfUser { username: String },
RemoteUser { username: String },
}
actions!(collaborator_list_popover, [NoOp]);
pub(crate) struct CollaboratorListPopover {
list_state: ListState,
}
impl Entity for CollaboratorListPopover {
type Event = Event;
}
impl View for CollaboratorListPopover {
fn ui_name() -> &'static str {
"CollaboratorListPopover"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone();
MouseEventHandler::<Self>::new(0, cx, |_, _| {
List::new(self.list_state.clone())
.contained()
.with_style(theme.contacts_popover.container) //TODO: Change the name of this theme key
.constrained()
.with_width(theme.contacts_popover.width)
.with_height(theme.contacts_popover.height)
.boxed()
})
.on_down_out(MouseButton::Left, move |_, cx| {
cx.dispatch_action(ToggleCollaboratorList);
})
.boxed()
}
fn focus_out(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
cx.emit(Event::Dismissed);
}
}
impl CollaboratorListPopover {
pub fn new(user_store: ModelHandle<UserStore>, cx: &mut ViewContext<Self>) -> Self {
let active_call = ActiveCall::global(cx);
let mut collaborators = user_store
.read(cx)
.current_user()
.map(|u| Collaborator::SelfUser {
username: u.github_login.clone(),
})
.into_iter()
.collect::<Vec<_>>();
//TODO: What should the canonical sort here look like, consult contacts list implementation
if let Some(room) = active_call.read(cx).room() {
for participant in room.read(cx).remote_participants() {
collaborators.push(Collaborator::RemoteUser {
username: participant.1.user.github_login.clone(),
});
}
}
Self {
list_state: ListState::new(
collaborators.len(),
Orientation::Top,
0.,
cx,
move |_, index, cx| match &collaborators[index] {
Collaborator::SelfUser { username } => render_collaborator_list_entry(
index,
username,
None::<NoOp>,
None,
Svg::new("icons/chevron_right_12.svg"),
NoOp,
"Leave call".to_owned(),
cx,
),
Collaborator::RemoteUser { username } => render_collaborator_list_entry(
index,
username,
Some(NoOp),
Some(format!("Follow {username}")),
Svg::new("icons/x_mark_12.svg"),
NoOp,
format!("Remove {username} from call"),
cx,
),
},
),
}
}
}
fn render_collaborator_list_entry<UA: Action + Clone, IA: Action + Clone>(
index: usize,
username: &str,
username_action: Option<UA>,
username_tooltip: Option<String>,
icon: Svg,
icon_action: IA,
icon_tooltip: String,
cx: &mut RenderContext<CollaboratorListPopover>,
) -> ElementBox {
enum Username {}
enum UsernameTooltip {}
enum Icon {}
enum IconTooltip {}
let theme = &cx.global::<Settings>().theme;
let username_theme = theme.contact_list.contact_username.text.clone();
let tooltip_theme = theme.tooltip.clone();
let username = MouseEventHandler::<Username>::new(index, cx, |_, _| {
Label::new(username.to_owned(), username_theme.clone()).boxed()
})
.on_click(MouseButton::Left, move |_, cx| {
if let Some(username_action) = username_action.clone() {
cx.dispatch_action(username_action);
}
});
Flex::row()
.with_child(if let Some(username_tooltip) = username_tooltip {
username
.with_tooltip::<UsernameTooltip, _>(
index,
username_tooltip,
None,
tooltip_theme.clone(),
cx,
)
.boxed()
} else {
username.boxed()
})
.with_child(
MouseEventHandler::<Icon>::new(index, cx, |_, _| icon.boxed())
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(icon_action.clone())
})
.with_tooltip::<IconTooltip, _>(index, icon_tooltip, None, tooltip_theme, cx)
.boxed(),
)
.boxed()
}

View File

@@ -1,49 +1,41 @@
use client::{ContactRequestStatus, User, UserStore};
use gpui::{
elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, MutableAppContext,
RenderContext, Task, View, ViewContext, ViewHandle,
};
use picker::{Picker, PickerDelegate};
use settings::Settings;
use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext};
use picker::{Picker, PickerDelegate, PickerEvent};
use std::sync::Arc;
use util::TryFutureExt;
pub fn init(cx: &mut MutableAppContext) {
Picker::<ContactFinder>::init(cx);
pub fn init(cx: &mut AppContext) {
Picker::<ContactFinderDelegate>::init(cx);
}
pub struct ContactFinder {
picker: ViewHandle<Picker<Self>>,
pub type ContactFinder = Picker<ContactFinderDelegate>;
pub fn build_contact_finder(
user_store: ModelHandle<UserStore>,
cx: &mut ViewContext<ContactFinder>,
) -> ContactFinder {
Picker::new(
ContactFinderDelegate {
user_store,
potential_contacts: Arc::from([]),
selected_index: 0,
},
cx,
)
.with_theme(|theme| theme.contact_finder.picker.clone())
}
pub struct ContactFinderDelegate {
potential_contacts: Arc<[Arc<User>]>,
user_store: ModelHandle<UserStore>,
selected_index: usize,
}
pub enum Event {
Dismissed,
}
impl Entity for ContactFinder {
type Event = Event;
}
impl View for ContactFinder {
fn ui_name() -> &'static str {
"ContactFinder"
impl PickerDelegate for ContactFinderDelegate {
fn placeholder_text(&self) -> Arc<str> {
"Search collaborator by username...".into()
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
ChildView::new(self.picker.clone(), cx).boxed()
}
fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
if cx.is_self_focused() {
cx.focus(&self.picker);
}
}
}
impl PickerDelegate for ContactFinder {
fn match_count(&self) -> usize {
self.potential_contacts.len()
}
@@ -52,22 +44,22 @@ impl PickerDelegate for ContactFinder {
self.selected_index
}
fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Self>) {
fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
self.selected_index = ix;
}
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) -> Task<()> {
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
let search_users = self
.user_store
.update(cx, |store, cx| store.fuzzy_search_users(query, cx));
cx.spawn(|this, mut cx| async move {
cx.spawn(|picker, mut cx| async move {
async {
let potential_contacts = search_users.await?;
this.update(&mut cx, |this, cx| {
this.potential_contacts = potential_contacts.into();
picker.update(&mut cx, |picker, cx| {
picker.delegate_mut().potential_contacts = potential_contacts.into();
cx.notify();
});
})?;
anyhow::Ok(())
}
.log_err()
@@ -75,7 +67,7 @@ impl PickerDelegate for ContactFinder {
})
}
fn confirm(&mut self, cx: &mut ViewContext<Self>) {
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
if let Some(user) = self.potential_contacts.get(self.selected_index) {
let user_store = self.user_store.read(cx);
match user_store.contact_request_status(user) {
@@ -94,8 +86,8 @@ impl PickerDelegate for ContactFinder {
}
}
fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
cx.emit(Event::Dismissed);
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
cx.emit(PickerEvent::Dismiss);
}
fn render_match(
@@ -104,8 +96,8 @@ impl PickerDelegate for ContactFinder {
mouse_state: &mut MouseState,
selected: bool,
cx: &gpui::AppContext,
) -> ElementBox {
let theme = &cx.global::<Settings>().theme;
) -> AnyElement<Picker<Self>> {
let theme = &theme::current(cx);
let user = &self.potential_contacts[ix];
let request_status = self.user_store.read(cx).contact_request_status(user);
@@ -132,15 +124,13 @@ impl PickerDelegate for ContactFinder {
.with_style(theme.contact_finder.contact_avatar)
.aligned()
.left()
.boxed()
}))
.with_child(
Label::new(user.github_login.clone(), style.label.clone())
.contained()
.with_style(theme.contact_finder.contact_username)
.aligned()
.left()
.boxed(),
.left(),
)
.with_children(icon_path.map(|icon_path| {
Svg::new(icon_path)
@@ -155,37 +145,11 @@ impl PickerDelegate for ContactFinder {
.with_height(button_style.button_width)
.aligned()
.flex_float()
.boxed()
}))
.contained()
.with_style(style.container)
.constrained()
.with_height(theme.contact_finder.row_height)
.boxed()
}
}
impl ContactFinder {
pub fn new(user_store: ModelHandle<UserStore>, cx: &mut ViewContext<Self>) -> Self {
let this = cx.weak_handle();
Self {
picker: cx.add_view(|cx| {
Picker::new("Search collaborator by username...", this, cx)
.with_theme(|theme| theme.contact_finder.picker.clone())
}),
potential_contacts: Arc::from([]),
user_store,
selected_index: 0,
}
}
pub fn editor_text(&self, cx: &AppContext) -> String {
self.picker.read(cx).query(cx)
}
pub fn with_editor_text(self, editor_text: String, cx: &mut ViewContext<Self>) -> Self {
self.picker
.update(cx, |picker, cx| picker.set_query(editor_text, cx));
self
.into_any()
}
}

View File

@@ -1,5 +1,3 @@
use super::collab_titlebar_item::LeaveCall;
use crate::contacts_popover;
use call::ActiveCall;
use client::{proto::PeerId, Contact, User, UserStore};
use editor::{Cancel, Editor};
@@ -8,40 +6,27 @@ use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
elements::*,
geometry::{rect::RectF, vector::vec2f},
impl_actions, impl_internal_actions,
impl_actions,
keymap_matcher::KeymapContext,
AppContext, CursorStyle, Entity, ModelHandle, MouseButton, MutableAppContext, PromptLevel,
RenderContext, Subscription, View, ViewContext, ViewHandle,
platform::{CursorStyle, MouseButton, PromptLevel},
AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
};
use menu::{Confirm, SelectNext, SelectPrev};
use project::Project;
use serde::Deserialize;
use settings::Settings;
use std::{mem, sync::Arc};
use theme::IconButton;
use workspace::{JoinProject, OpenSharedScreen};
use workspace::Workspace;
impl_actions!(contact_list, [RemoveContact, RespondToContactRequest]);
impl_internal_actions!(contact_list, [ToggleExpanded, Call]);
pub fn init(cx: &mut MutableAppContext) {
pub fn init(cx: &mut AppContext) {
cx.add_action(ContactList::remove_contact);
cx.add_action(ContactList::respond_to_contact_request);
cx.add_action(ContactList::cancel);
cx.add_action(ContactList::select_next);
cx.add_action(ContactList::select_prev);
cx.add_action(ContactList::confirm);
cx.add_action(ContactList::toggle_expanded);
cx.add_action(ContactList::call);
}
#[derive(Clone, PartialEq)]
struct ToggleExpanded(Section);
#[derive(Clone, PartialEq)]
struct Call {
recipient_user_id: u64,
initial_project: Option<ModelHandle<Project>>,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)]
@@ -153,14 +138,16 @@ pub struct RespondToContactRequest {
}
pub enum Event {
ToggleContactFinder,
Dismissed,
}
pub struct ContactList {
entries: Vec<ContactEntry>,
match_candidates: Vec<StringMatchCandidate>,
list_state: ListState,
list_state: ListState<Self>,
project: ModelHandle<Project>,
workspace: WeakViewHandle<Workspace>,
user_store: ModelHandle<UserStore>,
filter_editor: ViewHandle<Editor>,
collapsed_sections: Vec<Section>,
@@ -172,6 +159,7 @@ impl ContactList {
pub fn new(
project: ModelHandle<Project>,
user_store: ModelHandle<UserStore>,
workspace: WeakViewHandle<Workspace>,
cx: &mut ViewContext<Self>,
) -> Self {
let filter_editor = cx.add_view(|cx| {
@@ -202,8 +190,8 @@ impl ContactList {
})
.detach();
let list_state = ListState::new(0, Orientation::Top, 1000., cx, move |this, ix, cx| {
let theme = cx.global::<Settings>().theme.clone();
let list_state = ListState::<Self>::new(0, Orientation::Top, 1000., move |this, ix, cx| {
let theme = theme::current(cx).clone();
let is_selected = this.selection == Some(ix);
let current_project_id = this.project.read(cx).remote_id();
@@ -291,6 +279,7 @@ impl ContactList {
filter_editor,
_subscriptions: subscriptions,
project,
workspace,
user_store,
};
this.update_entries(cx);
@@ -316,12 +305,20 @@ impl ContactList {
github_login
);
let mut answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]);
let window_id = cx.window_id();
cx.spawn(|_, mut cx| async move {
if answer.next().await == Some(0) {
user_store
if let Err(e) = user_store
.update(&mut cx, |store, cx| store.remove_contact(user_id, cx))
.await
.unwrap();
{
cx.prompt(
window_id,
PromptLevel::Info,
&format!("Failed to remove contact: {}", e),
&["Ok"],
);
}
}
})
.detach();
@@ -395,18 +392,11 @@ impl ContactList {
if let Some(entry) = self.entries.get(selection) {
match entry {
ContactEntry::Header(section) => {
let section = *section;
self.toggle_expanded(&ToggleExpanded(section), cx);
self.toggle_expanded(*section, cx);
}
ContactEntry::Contact { contact, calling } => {
if contact.online && !contact.busy && !calling {
self.call(
&Call {
recipient_user_id: contact.user.id,
initial_project: Some(self.project.clone()),
},
cx,
);
self.call(contact.user.id, Some(self.project.clone()), cx);
}
}
ContactEntry::ParticipantProject {
@@ -414,13 +404,23 @@ impl ContactList {
host_user_id,
..
} => {
cx.dispatch_global_action(JoinProject {
project_id: *project_id,
follow_user_id: *host_user_id,
});
if let Some(workspace) = self.workspace.upgrade(cx) {
let app_state = workspace.read(cx).app_state().clone();
workspace::join_remote_project(
*project_id,
*host_user_id,
app_state,
cx,
)
.detach_and_log_err(cx);
}
}
ContactEntry::ParticipantScreen { peer_id, .. } => {
cx.dispatch_action(OpenSharedScreen { peer_id: *peer_id });
if let Some(workspace) = self.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.open_shared_screen(*peer_id, cx)
});
}
}
_ => {}
}
@@ -428,8 +428,7 @@ impl ContactList {
}
}
fn toggle_expanded(&mut self, action: &ToggleExpanded, cx: &mut ViewContext<Self>) {
let section = action.0;
fn toggle_expanded(&mut self, section: Section, cx: &mut ViewContext<Self>) {
if let Some(ix) = self.collapsed_sections.iter().position(|s| *s == section) {
self.collapsed_sections.remove(ix);
} else {
@@ -740,14 +739,13 @@ impl ContactList {
is_pending: bool,
is_selected: bool,
theme: &theme::ContactList,
) -> ElementBox {
) -> AnyElement<Self> {
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
.boxed()
}))
.with_child(
Label::new(
@@ -758,16 +756,14 @@ impl ContactList {
.with_style(theme.contact_username.container)
.aligned()
.left()
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_children(if is_pending {
Some(
Label::new("Calling", theme.calling_indicator.text.clone())
.contained()
.with_style(theme.calling_indicator.container)
.aligned()
.boxed(),
.aligned(),
)
} else {
None
@@ -780,7 +776,7 @@ impl ContactList {
.contact_row
.style_for(&mut Default::default(), is_selected),
)
.boxed()
.into_any()
}
fn render_participant_project(
@@ -791,8 +787,10 @@ impl ContactList {
is_last: bool,
is_selected: bool,
theme: &theme::ContactList,
cx: &mut RenderContext<Self>,
) -> ElementBox {
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
enum JoinProject {}
let font_cache = cx.font_cache();
let host_avatar_height = theme
.contact_avatar
@@ -811,48 +809,44 @@ impl ContactList {
worktree_root_names.join(", ")
};
MouseEventHandler::<JoinProject>::new(project_id as usize, cx, |mouse_state, _| {
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| {
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
let row = theme.project_row.style_for(mouse_state, is_selected);
Flex::row()
.with_child(
Stack::new()
.with_child(
Canvas::new(move |bounds, _, cx| {
let start_x = bounds.min_x() + (bounds.width() / 2.)
- (tree_branch.width / 2.);
let end_x = bounds.max_x();
let start_y = bounds.min_y();
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
.with_child(Canvas::new(move |scene, bounds, _, _, _| {
let start_x =
bounds.min_x() + (bounds.width() / 2.) - (tree_branch.width / 2.);
let end_x = bounds.max_x();
let start_y = bounds.min_y();
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
cx.scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, start_y),
vec2f(
start_x + tree_branch.width,
if is_last { end_y } else { bounds.max_y() },
),
scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, start_y),
vec2f(
start_x + tree_branch.width,
if is_last { end_y } else { bounds.max_y() },
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
cx.scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width),
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
})
.boxed(),
)
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width),
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
}))
.constrained()
.with_width(host_avatar_height)
.boxed(),
.with_width(host_avatar_height),
)
.with_child(
Label::new(project_name, row.name.text.clone())
@@ -860,29 +854,28 @@ impl ContactList {
.left()
.contained()
.with_style(row.name.container)
.flex(1., false)
.boxed(),
.flex(1., false),
)
.constrained()
.with_height(theme.row_height)
.contained()
.with_style(row.container)
.boxed()
})
.with_cursor_style(if !is_current {
CursorStyle::PointingHand
} else {
CursorStyle::Arrow
})
.on_click(MouseButton::Left, move |_, cx| {
.on_click(MouseButton::Left, move |_, this, cx| {
if !is_current {
cx.dispatch_global_action(JoinProject {
project_id,
follow_user_id: host_user_id,
});
if let Some(workspace) = this.workspace.upgrade(cx) {
let app_state = workspace.read(cx).app_state().clone();
workspace::join_remote_project(project_id, host_user_id, app_state, cx)
.detach_and_log_err(cx);
}
}
})
.boxed()
.into_any()
}
fn render_participant_screen(
@@ -890,8 +883,10 @@ impl ContactList {
is_last: bool,
is_selected: bool,
theme: &theme::ContactList,
cx: &mut RenderContext<Self>,
) -> ElementBox {
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
enum OpenSharedScreen {}
let font_cache = cx.font_cache();
let host_avatar_height = theme
.contact_avatar
@@ -905,7 +900,7 @@ impl ContactList {
let baseline_offset =
row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.;
MouseEventHandler::<OpenSharedScreen>::new(
MouseEventHandler::<OpenSharedScreen, Self>::new(
peer_id.as_u64() as usize,
cx,
|mouse_state, _| {
@@ -915,42 +910,37 @@ impl ContactList {
Flex::row()
.with_child(
Stack::new()
.with_child(
Canvas::new(move |bounds, _, cx| {
let start_x = bounds.min_x() + (bounds.width() / 2.)
- (tree_branch.width / 2.);
let end_x = bounds.max_x();
let start_y = bounds.min_y();
let end_y =
bounds.min_y() + baseline_offset - (cap_height / 2.);
.with_child(Canvas::new(move |scene, bounds, _, _, _| {
let start_x = bounds.min_x() + (bounds.width() / 2.)
- (tree_branch.width / 2.);
let end_x = bounds.max_x();
let start_y = bounds.min_y();
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
cx.scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, start_y),
vec2f(
start_x + tree_branch.width,
if is_last { end_y } else { bounds.max_y() },
),
scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, start_y),
vec2f(
start_x + tree_branch.width,
if is_last { end_y } else { bounds.max_y() },
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
cx.scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width),
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
})
.boxed(),
)
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
scene.push_quad(gpui::Quad {
bounds: RectF::from_points(
vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width),
),
background: Some(tree_branch.color),
border: gpui::Border::default(),
corner_radius: 0.,
});
}))
.constrained()
.with_width(host_avatar_height)
.boxed(),
.with_width(host_avatar_height),
)
.with_child(
Svg::new("icons/disable_screen_sharing_12.svg")
@@ -960,8 +950,7 @@ impl ContactList {
.aligned()
.left()
.contained()
.with_style(row.icon.container)
.boxed(),
.with_style(row.icon.container),
)
.with_child(
Label::new("Screen", row.name.text.clone())
@@ -969,21 +958,23 @@ impl ContactList {
.left()
.contained()
.with_style(row.name.container)
.flex(1., false)
.boxed(),
.flex(1., false),
)
.constrained()
.with_height(theme.row_height)
.contained()
.with_style(row.container)
.boxed()
},
)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(OpenSharedScreen { peer_id });
.on_click(MouseButton::Left, move |_, this, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.open_shared_screen(peer_id, cx)
});
}
})
.boxed()
.into_any()
}
fn render_header(
@@ -991,8 +982,8 @@ impl ContactList {
theme: &theme::ContactList,
is_selected: bool,
is_collapsed: bool,
cx: &mut RenderContext<Self>,
) -> ElementBox {
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
enum Header {}
enum LeaveCallContactList {}
@@ -1007,23 +998,25 @@ impl ContactList {
};
let leave_call = if section == Section::ActiveCall {
Some(
MouseEventHandler::<LeaveCallContactList>::new(0, cx, |state, _| {
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
let style = theme.leave_call.style_for(state, false);
Label::new("Leave Call", style.text.clone())
.contained()
.with_style(style.container)
.boxed()
})
.on_click(MouseButton::Left, |_, cx| cx.dispatch_action(LeaveCall))
.aligned()
.boxed(),
.on_click(MouseButton::Left, |_, _, cx| {
ActiveCall::global(cx)
.update(cx, |call, cx| call.hang_up(cx))
.detach_and_log_err(cx);
})
.aligned(),
)
} else {
None
};
let icon_size = theme.section_icon_size;
MouseEventHandler::<Header>::new(section as usize, cx, |_, _| {
MouseEventHandler::<Header, Self>::new(section as usize, cx, |_, _| {
Flex::row()
.with_child(
Svg::new(if is_collapsed {
@@ -1037,8 +1030,7 @@ impl ContactList {
.with_max_height(icon_size)
.aligned()
.constrained()
.with_width(icon_size)
.boxed(),
.with_width(icon_size),
)
.with_child(
Label::new(text, header_style.text.clone())
@@ -1046,21 +1038,19 @@ impl ContactList {
.left()
.contained()
.with_margin_left(theme.contact_username.container.margin.left)
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_children(leave_call)
.constrained()
.with_height(theme.row_height)
.contained()
.with_style(header_style.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(ToggleExpanded(section))
.on_click(MouseButton::Left, move |_, this, cx| {
this.toggle_expanded(section, cx);
})
.boxed()
.into_any()
}
fn render_contact(
@@ -1069,15 +1059,15 @@ impl ContactList {
project: &ModelHandle<Project>,
theme: &theme::ContactList,
is_selected: bool,
cx: &mut RenderContext<Self>,
) -> ElementBox {
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
let online = contact.online;
let busy = contact.busy || calling;
let user_id = contact.user.id;
let github_login = contact.user.github_login.clone();
let initial_project = project.clone();
let mut element =
MouseEventHandler::<Contact>::new(contact.user.id as usize, cx, |_, cx| {
let mut event_handler =
MouseEventHandler::<Contact, Self>::new(contact.user.id as usize, cx, |_, cx| {
Flex::row()
.with_children(contact.user.avatar.clone().map(|avatar| {
let status_badge = if contact.online {
@@ -1090,8 +1080,7 @@ impl ContactList {
} else {
theme.contact_status_free
})
.aligned()
.boxed(),
.aligned(),
)
} else {
None
@@ -1101,11 +1090,9 @@ impl ContactList {
Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
.boxed(),
.left(),
)
.with_children(status_badge)
.boxed()
}))
.with_child(
Label::new(
@@ -1116,11 +1103,10 @@ impl ContactList {
.with_style(theme.contact_username.container)
.aligned()
.left()
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_child(
MouseEventHandler::<Cancel>::new(
MouseEventHandler::<Cancel, Self>::new(
contact.user.id as usize,
cx,
|mouse_state, _| {
@@ -1129,27 +1115,27 @@ impl ContactList {
render_icon_button(button_style, "icons/x_mark_8.svg")
.aligned()
.flex_float()
.boxed()
},
)
.with_padding(Padding::uniform(2.))
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(RemoveContact {
user_id,
github_login: github_login.clone(),
})
.on_click(MouseButton::Left, move |_, this, cx| {
this.remove_contact(
&RemoveContact {
user_id,
github_login: github_login.clone(),
},
cx,
);
})
.flex_float()
.boxed(),
.flex_float(),
)
.with_children(if calling {
Some(
Label::new("Calling", theme.calling_indicator.text.clone())
.contained()
.with_style(theme.calling_indicator.container)
.aligned()
.boxed(),
.aligned(),
)
} else {
None
@@ -1162,22 +1148,18 @@ impl ContactList {
.contact_row
.style_for(&mut Default::default(), is_selected),
)
.boxed()
})
.on_click(MouseButton::Left, move |_, cx| {
.on_click(MouseButton::Left, move |_, this, cx| {
if online && !busy {
cx.dispatch_action(Call {
recipient_user_id: user_id,
initial_project: Some(initial_project.clone()),
});
this.call(user_id, Some(initial_project.clone()), cx);
}
});
if online {
element = element.with_cursor_style(CursorStyle::PointingHand);
event_handler = event_handler.with_cursor_style(CursorStyle::PointingHand);
}
element.boxed()
event_handler.into_any()
}
fn render_contact_request(
@@ -1186,8 +1168,8 @@ impl ContactList {
theme: &theme::ContactList,
is_incoming: bool,
is_selected: bool,
cx: &mut RenderContext<Self>,
) -> ElementBox {
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
enum Decline {}
enum Accept {}
enum Cancel {}
@@ -1198,7 +1180,6 @@ impl ContactList {
.with_style(theme.contact_avatar)
.aligned()
.left()
.boxed()
}))
.with_child(
Label::new(
@@ -1209,8 +1190,7 @@ impl ContactList {
.with_style(theme.contact_username.container)
.aligned()
.left()
.flex(1., true)
.boxed(),
.flex(1., true),
);
let user_id = user.id;
@@ -1219,28 +1199,31 @@ impl ContactList {
let button_spacing = theme.contact_button_spacing;
if is_incoming {
row.add_children([
MouseEventHandler::<Decline>::new(user.id as usize, cx, |mouse_state, _| {
row.add_child(
MouseEventHandler::<Decline, Self>::new(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending {
&theme.disabled_button
} else {
theme.contact_button.style_for(mouse_state, false)
};
render_icon_button(button_style, "icons/x_mark_8.svg")
.aligned()
.boxed()
render_icon_button(button_style, "icons/x_mark_8.svg").aligned()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(RespondToContactRequest {
user_id,
accept: false,
})
.on_click(MouseButton::Left, move |_, this, cx| {
this.respond_to_contact_request(
&RespondToContactRequest {
user_id,
accept: false,
},
cx,
);
})
.contained()
.with_margin_right(button_spacing)
.boxed(),
MouseEventHandler::<Accept>::new(user.id as usize, cx, |mouse_state, _| {
.with_margin_right(button_spacing),
);
row.add_child(
MouseEventHandler::<Accept, Self>::new(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending {
&theme.disabled_button
} else {
@@ -1249,20 +1232,21 @@ impl ContactList {
render_icon_button(button_style, "icons/check_8.svg")
.aligned()
.flex_float()
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(RespondToContactRequest {
user_id,
accept: true,
})
})
.boxed(),
]);
.on_click(MouseButton::Left, move |_, this, cx| {
this.respond_to_contact_request(
&RespondToContactRequest {
user_id,
accept: true,
},
cx,
);
}),
);
} else {
row.add_child(
MouseEventHandler::<Cancel>::new(user.id as usize, cx, |mouse_state, _| {
MouseEventHandler::<Cancel, Self>::new(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending {
&theme.disabled_button
} else {
@@ -1271,18 +1255,19 @@ impl ContactList {
render_icon_button(button_style, "icons/x_mark_8.svg")
.aligned()
.flex_float()
.boxed()
})
.with_padding(Padding::uniform(2.))
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(RemoveContact {
user_id,
github_login: github_login.clone(),
})
.on_click(MouseButton::Left, move |_, this, cx| {
this.remove_contact(
&RemoveContact {
user_id,
github_login: github_login.clone(),
},
cx,
);
})
.flex_float()
.boxed(),
.flex_float(),
);
}
@@ -1294,12 +1279,15 @@ impl ContactList {
.contact_row
.style_for(&mut Default::default(), is_selected),
)
.boxed()
.into_any()
}
fn call(&mut self, action: &Call, cx: &mut ViewContext<Self>) {
let recipient_user_id = action.recipient_user_id;
let initial_project = action.initial_project.clone();
fn call(
&mut self,
recipient_user_id: u64,
initial_project: Option<ModelHandle<Project>>,
cx: &mut ViewContext<Self>,
) {
ActiveCall::global(cx)
.update(cx, |call, cx| {
call.invite(recipient_user_id, initial_project, cx)
@@ -1317,53 +1305,48 @@ impl View for ContactList {
"ContactList"
}
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
cx.add_identifier("menu");
cx
fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
Self::reset_to_default_keymap_context(keymap);
keymap.add_identifier("menu");
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
enum AddContact {}
let theme = cx.global::<Settings>().theme.clone();
let theme = theme::current(cx).clone();
Flex::column()
.with_child(
Flex::row()
.with_child(
ChildView::new(self.filter_editor.clone(), cx)
ChildView::new(&self.filter_editor, cx)
.contained()
.with_style(theme.contact_list.user_query_editor.container)
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_child(
MouseEventHandler::<AddContact>::new(0, cx, |_, _| {
MouseEventHandler::<AddContact, Self>::new(0, cx, |_, _| {
render_icon_button(
&theme.contact_list.add_contact_button,
"icons/user_plus_16.svg",
)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(contacts_popover::ToggleContactFinder)
.on_click(MouseButton::Left, |_, _, cx| {
cx.emit(Event::ToggleContactFinder)
})
.with_tooltip::<AddContact, _>(
.with_tooltip::<AddContact>(
0,
"Search for new contact".into(),
None,
theme.tooltip.clone(),
cx,
)
.boxed(),
),
)
.constrained()
.with_height(theme.contact_list.user_query_editor_height)
.boxed(),
.with_height(theme.contact_list.user_query_editor_height),
)
.with_child(List::new(self.list_state.clone()).flex(1., false).boxed())
.boxed()
.with_child(List::new(self.list_state.clone()).flex(1., false))
.into_any()
}
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
@@ -1379,7 +1362,7 @@ impl View for ContactList {
}
}
fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element {
fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element<ContactList> {
Svg::new(svg_path)
.with_color(style.color)
.constrained()

View File

@@ -2,19 +2,9 @@ use std::sync::Arc;
use crate::notifications::render_user_notification;
use client::{ContactEventKind, User, UserStore};
use gpui::{
elements::*, impl_internal_actions, Entity, ModelHandle, MutableAppContext, RenderContext,
View, ViewContext,
};
use gpui::{elements::*, Entity, ModelHandle, View, ViewContext};
use workspace::notifications::Notification;
impl_internal_actions!(contact_notifications, [Dismiss, RespondToContactRequest]);
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ContactNotification::dismiss);
cx.add_action(ContactNotification::respond_to_contact_request);
}
pub struct ContactNotification {
user_store: ModelHandle<UserStore>,
user: Arc<User>,
@@ -43,26 +33,24 @@ impl View for ContactNotification {
"ContactNotification"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
match self.kind {
ContactEventKind::Requested => render_user_notification(
self.user.clone(),
"wants to add you as a contact",
Some("They won't be alerted if you decline."),
Dismiss(self.user.id),
|notification, cx| notification.dismiss(cx),
vec![
(
"Decline",
Box::new(RespondToContactRequest {
user_id: self.user.id,
accept: false,
Box::new(|notification, cx| {
notification.respond_to_contact_request(false, cx)
}),
),
(
"Accept",
Box::new(RespondToContactRequest {
user_id: self.user.id,
accept: true,
Box::new(|notification, cx| {
notification.respond_to_contact_request(true, cx)
}),
),
],
@@ -72,7 +60,7 @@ impl View for ContactNotification {
self.user.clone(),
"accepted your contact request",
None,
Dismiss(self.user.id),
|notification, cx| notification.dismiss(cx),
vec![],
cx,
),
@@ -114,7 +102,7 @@ impl ContactNotification {
}
}
fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
self.user_store.update(cx, |store, cx| {
store
.dismiss_contact_request(self.user.id, cx)
@@ -123,14 +111,10 @@ impl ContactNotification {
cx.emit(Event::Dismiss);
}
fn respond_to_contact_request(
&mut self,
action: &RespondToContactRequest,
cx: &mut ViewContext<Self>,
) {
fn respond_to_contact_request(&mut self, accept: bool, cx: &mut ViewContext<Self>) {
self.user_store
.update(cx, |store, cx| {
store.respond_to_contact_request(action.user_id, action.accept, cx)
store.respond_to_contact_request(self.user.id, accept, cx)
})
.detach();
}

View File

@@ -1,15 +1,19 @@
use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu};
use crate::{
contact_finder::{build_contact_finder, ContactFinder},
contact_list::ContactList,
};
use client::UserStore;
use gpui::{
actions, elements::*, ClipboardItem, CursorStyle, Entity, ModelHandle, MouseButton,
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View,
ViewContext, ViewHandle, WeakViewHandle,
};
use picker::PickerEvent;
use project::Project;
use settings::Settings;
use workspace::Workspace;
actions!(contacts_popover, [ToggleContactFinder]);
pub fn init(cx: &mut MutableAppContext) {
pub fn init(cx: &mut AppContext) {
cx.add_action(ContactsPopover::toggle_contact_finder);
}
@@ -26,6 +30,7 @@ pub struct ContactsPopover {
child: Child,
project: ModelHandle<Project>,
user_store: ModelHandle<UserStore>,
workspace: WeakViewHandle<Workspace>,
_subscription: Option<gpui::Subscription>,
}
@@ -33,14 +38,16 @@ impl ContactsPopover {
pub fn new(
project: ModelHandle<Project>,
user_store: ModelHandle<UserStore>,
workspace: WeakViewHandle<Workspace>,
cx: &mut ViewContext<Self>,
) -> Self {
let mut this = Self {
child: Child::ContactList(
cx.add_view(|cx| ContactList::new(project.clone(), user_store.clone(), cx)),
),
child: Child::ContactList(cx.add_view(|cx| {
ContactList::new(project.clone(), user_store.clone(), workspace.clone(), cx)
})),
project,
user_store,
workspace,
_subscription: None,
};
this.show_contact_list(String::new(), cx);
@@ -50,19 +57,19 @@ impl ContactsPopover {
fn toggle_contact_finder(&mut self, _: &ToggleContactFinder, cx: &mut ViewContext<Self>) {
match &self.child {
Child::ContactList(list) => self.show_contact_finder(list.read(cx).editor_text(cx), cx),
Child::ContactFinder(finder) => {
self.show_contact_list(finder.read(cx).editor_text(cx), cx)
}
Child::ContactFinder(finder) => self.show_contact_list(finder.read(cx).query(cx), cx),
}
}
fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
let child = cx.add_view(|cx| {
ContactFinder::new(self.user_store.clone(), cx).with_editor_text(editor_text, cx)
let finder = build_contact_finder(self.user_store.clone(), cx);
finder.set_query(editor_text, cx);
finder
});
cx.focus(&child);
self._subscription = Some(cx.subscribe(&child, |_, _, event, cx| match event {
crate::contact_finder::Event::Dismissed => cx.emit(Event::Dismissed),
PickerEvent::Dismiss => cx.emit(Event::Dismissed),
}));
self.child = Child::ContactFinder(child);
cx.notify();
@@ -70,12 +77,20 @@ impl ContactsPopover {
fn show_contact_list(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
let child = cx.add_view(|cx| {
ContactList::new(self.project.clone(), self.user_store.clone(), cx)
.with_editor_text(editor_text, cx)
ContactList::new(
self.project.clone(),
self.user_store.clone(),
self.workspace.clone(),
cx,
)
.with_editor_text(editor_text, cx)
});
cx.focus(&child);
self._subscription = Some(cx.subscribe(&child, |_, _, event, cx| match event {
self._subscription = Some(cx.subscribe(&child, |this, _, event, cx| match event {
crate::contact_list::Event::Dismissed => cx.emit(Event::Dismissed),
crate::contact_list::Event::ToggleContactFinder => {
this.toggle_contact_finder(&Default::default(), cx)
}
}));
self.child = Child::ContactList(child);
cx.notify();
@@ -91,79 +106,24 @@ impl View for ContactsPopover {
"ContactsPopover"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone();
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let theme = theme::current(cx).clone();
let child = match &self.child {
Child::ContactList(child) => ChildView::new(child, cx),
Child::ContactFinder(child) => ChildView::new(child, cx),
};
MouseEventHandler::<ContactsPopover>::new(0, cx, |_, cx| {
MouseEventHandler::<ContactsPopover, Self>::new(0, cx, |_, _| {
Flex::column()
.with_child(child.flex(1., true).boxed())
.with_children(
self.user_store
.read(cx)
.invite_info()
.cloned()
.and_then(|info| {
enum InviteLink {}
if info.count > 0 {
Some(
MouseEventHandler::<InviteLink>::new(0, cx, |state, cx| {
let style = theme
.contacts_popover
.invite_row
.style_for(state, false)
.clone();
let copied =
cx.read_from_clipboard().map_or(false, |item| {
item.text().as_str() == info.url.as_ref()
});
Label::new(
format!(
"{} invite link ({} left)",
if copied { "Copied" } else { "Copy" },
info.count
),
style.label.clone(),
)
.aligned()
.left()
.constrained()
.with_height(theme.contacts_popover.invite_row_height)
.contained()
.with_style(style.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.write_to_clipboard(ClipboardItem::new(
info.url.to_string(),
));
cx.notify();
})
.boxed(),
)
} else {
None
}
}),
)
.with_child(child.flex(1., true))
.contained()
.with_style(theme.contacts_popover.container)
.constrained()
.with_width(theme.contacts_popover.width)
.with_height(theme.contacts_popover.height)
.boxed()
})
.on_down_out(MouseButton::Left, move |_, cx| {
cx.dispatch_action(ToggleContactsMenu);
})
.boxed()
.on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(Event::Dismissed))
.into_any()
}
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {

View File

@@ -7,12 +7,14 @@ use gpui::{
},
json::ToJson,
serde_json::{self, json},
Axis, DebugContext, Element, ElementBox, MeasurementContext, PaintContext,
AnyElement, Axis, Element, LayoutContext, SceneBuilder, ViewContext,
};
use crate::CollabTitlebarItem;
pub(crate) struct FacePile {
overlap: f32,
faces: Vec<ElementBox>,
faces: Vec<AnyElement<CollabTitlebarItem>>,
}
impl FacePile {
@@ -24,20 +26,21 @@ impl FacePile {
}
}
impl Element for FacePile {
impl Element<CollabTitlebarItem> for FacePile {
type LayoutState = ();
type PaintState = ();
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
cx: &mut gpui::LayoutContext,
view: &mut CollabTitlebarItem,
cx: &mut LayoutContext<CollabTitlebarItem>,
) -> (Vector2F, Self::LayoutState) {
debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);
let mut width = 0.;
for face in &mut self.faces {
width += face.layout(constraint, cx).x();
width += face.layout(constraint, view, cx).x();
}
width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
@@ -46,10 +49,12 @@ impl Element for FacePile {
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_layout: &mut Self::LayoutState,
cx: &mut PaintContext,
view: &mut CollabTitlebarItem,
cx: &mut ViewContext<CollabTitlebarItem>,
) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
@@ -59,8 +64,8 @@ impl Element for FacePile {
for face in self.faces.iter_mut().rev() {
let size = face.size();
origin_x -= size.x();
cx.paint_layer(None, |cx| {
face.paint(vec2f(origin_x, origin_y), visible_bounds, cx);
scene.paint_layer(None, |scene| {
face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx);
});
origin_x += self.overlap;
}
@@ -75,7 +80,8 @@ impl Element for FacePile {
_: RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &MeasurementContext,
_: &CollabTitlebarItem,
_: &ViewContext<CollabTitlebarItem>,
) -> Option<RectF> {
None
}
@@ -85,7 +91,8 @@ impl Element for FacePile {
bounds: RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &DebugContext,
_: &CollabTitlebarItem,
_: &ViewContext<CollabTitlebarItem>,
) -> serde_json::Value {
json!({
"type": "FacePile",
@@ -94,8 +101,8 @@ impl Element for FacePile {
}
}
impl Extend<ElementBox> for FacePile {
fn extend<T: IntoIterator<Item = ElementBox>>(&mut self, children: T) {
impl Extend<AnyElement<CollabTitlebarItem>> for FacePile {
fn extend<T: IntoIterator<Item = AnyElement<CollabTitlebarItem>>>(&mut self, children: T) {
self.faces.extend(children);
}
}

View File

@@ -1,21 +1,19 @@
use std::sync::{Arc, Weak};
use call::{ActiveCall, IncomingCall};
use client::proto;
use futures::StreamExt;
use gpui::{
elements::*,
geometry::{rect::RectF, vector::vec2f},
impl_internal_actions, CursorStyle, Entity, MouseButton, MutableAppContext, RenderContext,
View, ViewContext, WindowBounds, WindowKind, WindowOptions,
platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions},
AnyElement, AppContext, Entity, View, ViewContext,
};
use settings::Settings;
use util::ResultExt;
use workspace::JoinProject;
impl_internal_actions!(incoming_call_notification, [RespondToCall]);
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(IncomingCallNotification::respond_to_call);
use workspace::AppState;
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
let app_state = Arc::downgrade(app_state);
let mut incoming_call = ActiveCall::global(cx).read(cx).incoming();
cx.spawn(|mut cx| async move {
let mut notification_windows = Vec::new();
@@ -27,7 +25,7 @@ pub fn init(cx: &mut MutableAppContext) {
if let Some(incoming_call) = incoming_call {
const PADDING: f32 = 16.;
let window_size = cx.read(|cx| {
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
let theme = &theme::current(cx).incoming_call_notification;
vec2f(theme.window_width, theme.window_height)
});
@@ -43,11 +41,12 @@ pub fn init(cx: &mut MutableAppContext) {
titlebar: None,
center: false,
focus: false,
show: true,
kind: WindowKind::PopUp,
is_movable: false,
screen: Some(screen),
},
|_| IncomingCallNotification::new(incoming_call.clone()),
|_| IncomingCallNotification::new(incoming_call.clone(), app_state.clone()),
);
notification_windows.push(window_id);
@@ -65,32 +64,40 @@ struct RespondToCall {
pub struct IncomingCallNotification {
call: IncomingCall,
app_state: Weak<AppState>,
}
impl IncomingCallNotification {
pub fn new(call: IncomingCall) -> Self {
Self { call }
pub fn new(call: IncomingCall, app_state: Weak<AppState>) -> Self {
Self { call, app_state }
}
fn respond_to_call(&mut self, action: &RespondToCall, cx: &mut ViewContext<Self>) {
fn respond(&mut self, accept: bool, cx: &mut ViewContext<Self>) {
let active_call = ActiveCall::global(cx);
if action.accept {
if accept {
let join = active_call.update(cx, |active_call, cx| active_call.accept_incoming(cx));
let caller_user_id = self.call.calling_user.id;
let initial_project_id = self.call.initial_project.as_ref().map(|project| project.id);
cx.spawn_weak(|_, mut cx| async move {
join.await?;
if let Some(project_id) = initial_project_id {
cx.update(|cx| {
cx.dispatch_global_action(JoinProject {
project_id,
follow_user_id: caller_user_id,
})
});
}
anyhow::Ok(())
})
.detach_and_log_err(cx);
let app_state = self.app_state.clone();
cx.app_context()
.spawn(|mut cx| async move {
join.await?;
if let Some(project_id) = initial_project_id {
cx.update(|cx| {
if let Some(app_state) = app_state.upgrade() {
workspace::join_remote_project(
project_id,
caller_user_id,
app_state,
cx,
)
.detach_and_log_err(cx);
}
});
}
anyhow::Ok(())
})
.detach_and_log_err(cx);
} else {
active_call.update(cx, |active_call, _| {
active_call.decline_incoming().log_err();
@@ -98,8 +105,8 @@ impl IncomingCallNotification {
}
}
fn render_caller(&self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
fn render_caller(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let theme = &theme::current(cx).incoming_call_notification;
let default_project = proto::ParticipantProject::default();
let initial_project = self
.call
@@ -111,7 +118,6 @@ impl IncomingCallNotification {
Image::from_data(avatar)
.with_style(theme.caller_avatar)
.aligned()
.boxed()
}))
.with_child(
Flex::column()
@@ -121,8 +127,7 @@ impl IncomingCallNotification {
theme.caller_username.text.clone(),
)
.contained()
.with_style(theme.caller_username.container)
.boxed(),
.with_style(theme.caller_username.container),
)
.with_child(
Label::new(
@@ -137,8 +142,7 @@ impl IncomingCallNotification {
theme.caller_message.text.clone(),
)
.contained()
.with_style(theme.caller_message.container)
.boxed(),
.with_style(theme.caller_message.container),
)
.with_children(if initial_project.worktree_root_names.is_empty() {
None
@@ -149,66 +153,56 @@ impl IncomingCallNotification {
theme.worktree_roots.text.clone(),
)
.contained()
.with_style(theme.worktree_roots.container)
.boxed(),
.with_style(theme.worktree_roots.container),
)
})
.contained()
.with_style(theme.caller_metadata)
.aligned()
.boxed(),
.aligned(),
)
.contained()
.with_style(theme.caller_container)
.flex(1., true)
.boxed()
.into_any()
}
fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render_buttons(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
enum Accept {}
enum Decline {}
let theme = theme::current(cx);
Flex::column()
.with_child(
MouseEventHandler::<Accept>::new(0, cx, |_, cx| {
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
MouseEventHandler::<Accept, Self>::new(0, cx, |_, _| {
let theme = &theme.incoming_call_notification;
Label::new("Accept", theme.accept_button.text.clone())
.aligned()
.contained()
.with_style(theme.accept_button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(RespondToCall { accept: true });
.on_click(MouseButton::Left, |_, this, cx| {
this.respond(true, cx);
})
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_child(
MouseEventHandler::<Decline>::new(0, cx, |_, cx| {
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
MouseEventHandler::<Decline, Self>::new(0, cx, |_, _| {
let theme = &theme.incoming_call_notification;
Label::new("Decline", theme.decline_button.text.clone())
.aligned()
.contained()
.with_style(theme.decline_button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(RespondToCall { accept: false });
.on_click(MouseButton::Left, |_, this, cx| {
this.respond(false, cx);
})
.flex(1., true)
.boxed(),
.flex(1., true),
)
.constrained()
.with_width(
cx.global::<Settings>()
.theme
.incoming_call_notification
.button_width,
)
.boxed()
.with_width(theme.incoming_call_notification.button_width)
.into_any()
}
}
@@ -221,19 +215,14 @@ impl View for IncomingCallNotification {
"IncomingCallNotification"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
let background = cx
.global::<Settings>()
.theme
.incoming_call_notification
.background;
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let background = theme::current(cx).incoming_call_notification.background;
Flex::row()
.with_child(self.render_caller(cx))
.with_child(self.render_buttons(cx))
.contained()
.with_background_color(background)
.expanded()
.boxed()
.into_any()
}
}

View File

@@ -1,23 +1,27 @@
use client::User;
use gpui::{
elements::*, platform::CursorStyle, Action, Element, ElementBox, MouseButton, RenderContext,
View,
elements::*,
platform::{CursorStyle, MouseButton},
AnyElement, Element, View, ViewContext,
};
use settings::Settings;
use std::sync::Arc;
enum Dismiss {}
enum Button {}
pub fn render_user_notification<V: View, A: Action + Clone>(
pub fn render_user_notification<F, V>(
user: Arc<User>,
title: &'static str,
body: Option<&'static str>,
dismiss_action: A,
buttons: Vec<(&'static str, Box<dyn Action>)>,
cx: &mut RenderContext<V>,
) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone();
on_dismiss: F,
buttons: Vec<(&'static str, Box<dyn Fn(&mut V, &mut ViewContext<V>)>)>,
cx: &mut ViewContext<V>,
) -> AnyElement<V>
where
F: 'static + Fn(&mut V, &mut ViewContext<V>),
V: View,
{
let theme = theme::current(cx).clone();
let theme = &theme.contact_notification;
Flex::column()
@@ -34,7 +38,6 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
)
.aligned()
.top()
.boxed()
}))
.with_child(
Text::new(
@@ -46,11 +49,10 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
.aligned()
.top()
.left()
.flex(1., true)
.boxed(),
.flex(1., true),
)
.with_child(
MouseEventHandler::<Dismiss>::new(user.id as usize, cx, |state, _| {
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
let style = theme.dismiss_button.style_for(state, false);
Svg::new("icons/x_mark_8.svg")
.with_color(style.color)
@@ -62,13 +64,10 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.with_padding(Padding::uniform(5.))
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_any_action(dismiss_action.boxed_clone())
})
.on_click(MouseButton::Left, move |_, view, cx| on_dismiss(view, cx))
.aligned()
.constrained()
.with_height(
@@ -77,16 +76,14 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
)
.aligned()
.top()
.flex_float()
.boxed(),
.flex_float(),
)
.named("contact notification header"),
.into_any_named("contact notification header"),
)
.with_children(body.map(|body| {
Label::new(body, theme.body_message.text.clone())
.contained()
.with_style(theme.body_message.container)
.boxed()
}))
.with_children(if buttons.is_empty() {
None
@@ -94,26 +91,21 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
Some(
Flex::row()
.with_children(buttons.into_iter().enumerate().map(
|(ix, (message, action))| {
MouseEventHandler::<Button>::new(ix, cx, |state, _| {
|(ix, (message, handler))| {
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
let button = theme.button.style_for(state, false);
Label::new(message, button.text.clone())
.contained()
.with_style(button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_any_action(action.boxed_clone())
})
.boxed()
.on_click(MouseButton::Left, move |_, view, cx| handler(view, cx))
},
))
.aligned()
.right()
.boxed(),
.right(),
)
})
.contained()
.boxed()
.into_any()
}

View File

@@ -2,22 +2,16 @@ use call::{room, ActiveCall};
use client::User;
use collections::HashMap;
use gpui::{
actions,
elements::*,
geometry::{rect::RectF, vector::vec2f},
CursorStyle, Entity, MouseButton, MutableAppContext, RenderContext, View, ViewContext,
WindowBounds, WindowKind, WindowOptions,
platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions},
AppContext, Entity, View, ViewContext,
};
use settings::Settings;
use std::sync::Arc;
use workspace::JoinProject;
actions!(project_shared_notification, [DismissProject]);
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ProjectSharedNotification::join);
cx.add_action(ProjectSharedNotification::dismiss);
use std::sync::{Arc, Weak};
use workspace::AppState;
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
let app_state = Arc::downgrade(app_state);
let active_call = ActiveCall::global(cx);
let mut notification_windows = HashMap::default();
cx.subscribe(&active_call, move |_, event, cx| match event {
@@ -27,7 +21,7 @@ pub fn init(cx: &mut MutableAppContext) {
worktree_root_names,
} => {
const PADDING: f32 = 16.;
let theme = &cx.global::<Settings>().theme.project_shared_notification;
let theme = &theme::current(cx).project_shared_notification;
let window_size = vec2f(theme.window_width, theme.window_height);
for screen in cx.platform().screens() {
@@ -41,6 +35,7 @@ pub fn init(cx: &mut MutableAppContext) {
titlebar: None,
center: false,
focus: false,
show: true,
kind: WindowKind::PopUp,
is_movable: false,
screen: Some(screen),
@@ -50,6 +45,7 @@ pub fn init(cx: &mut MutableAppContext) {
owner.clone(),
*project_id,
worktree_root_names.clone(),
app_state.clone(),
)
},
);
@@ -62,14 +58,14 @@ pub fn init(cx: &mut MutableAppContext) {
room::Event::RemoteProjectUnshared { project_id } => {
if let Some(window_ids) = notification_windows.remove(&project_id) {
for window_id in window_ids {
cx.remove_window(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
}
}
room::Event::Left => {
for (_, window_ids) in notification_windows.drain() {
for window_id in window_ids {
cx.remove_window(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
}
}
@@ -82,36 +78,43 @@ pub struct ProjectSharedNotification {
project_id: u64,
worktree_root_names: Vec<String>,
owner: Arc<User>,
app_state: Weak<AppState>,
}
impl ProjectSharedNotification {
fn new(owner: Arc<User>, project_id: u64, worktree_root_names: Vec<String>) -> Self {
fn new(
owner: Arc<User>,
project_id: u64,
worktree_root_names: Vec<String>,
app_state: Weak<AppState>,
) -> Self {
Self {
project_id,
worktree_root_names,
owner,
app_state,
}
}
fn join(&mut self, _: &JoinProject, cx: &mut ViewContext<Self>) {
let window_id = cx.window_id();
cx.remove_window(window_id);
cx.propagate_action();
fn join(&mut self, cx: &mut ViewContext<Self>) {
cx.remove_window();
if let Some(app_state) = self.app_state.upgrade() {
workspace::join_remote_project(self.project_id, self.owner.id, app_state, cx)
.detach_and_log_err(cx);
}
}
fn dismiss(&mut self, _: &DismissProject, cx: &mut ViewContext<Self>) {
let window_id = cx.window_id();
cx.remove_window(window_id);
fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
cx.remove_window();
}
fn render_owner(&self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.project_shared_notification;
fn render_owner(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let theme = &theme::current(cx).project_shared_notification;
Flex::row()
.with_children(self.owner.avatar.clone().map(|avatar| {
Image::from_data(avatar)
.with_style(theme.owner_avatar)
.aligned()
.boxed()
}))
.with_child(
Flex::column()
@@ -121,8 +124,7 @@ impl ProjectSharedNotification {
theme.owner_username.text.clone(),
)
.contained()
.with_style(theme.owner_username.container)
.boxed(),
.with_style(theme.owner_username.container),
)
.with_child(
Label::new(
@@ -137,8 +139,7 @@ impl ProjectSharedNotification {
theme.message.text.clone(),
)
.contained()
.with_style(theme.message.container)
.boxed(),
.with_style(theme.message.container),
)
.with_children(if self.worktree_root_names.is_empty() {
None
@@ -149,72 +150,54 @@ impl ProjectSharedNotification {
theme.worktree_roots.text.clone(),
)
.contained()
.with_style(theme.worktree_roots.container)
.boxed(),
.with_style(theme.worktree_roots.container),
)
})
.contained()
.with_style(theme.owner_metadata)
.aligned()
.boxed(),
.aligned(),
)
.contained()
.with_style(theme.owner_container)
.flex(1., true)
.boxed()
.into_any()
}
fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render_buttons(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
enum Open {}
enum Dismiss {}
let project_id = self.project_id;
let owner_user_id = self.owner.id;
let theme = theme::current(cx);
Flex::column()
.with_child(
MouseEventHandler::<Open>::new(0, cx, |_, cx| {
let theme = &cx.global::<Settings>().theme.project_shared_notification;
MouseEventHandler::<Open, Self>::new(0, cx, |_, _| {
let theme = &theme.project_shared_notification;
Label::new("Open", theme.open_button.text.clone())
.aligned()
.contained()
.with_style(theme.open_button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(JoinProject {
project_id,
follow_user_id: owner_user_id,
});
})
.flex(1., true)
.boxed(),
.on_click(MouseButton::Left, move |_, this, cx| this.join(cx))
.flex(1., true),
)
.with_child(
MouseEventHandler::<Dismiss>::new(0, cx, |_, cx| {
let theme = &cx.global::<Settings>().theme.project_shared_notification;
MouseEventHandler::<Dismiss, Self>::new(0, cx, |_, _| {
let theme = &theme.project_shared_notification;
Label::new("Dismiss", theme.dismiss_button.text.clone())
.aligned()
.contained()
.with_style(theme.dismiss_button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(DismissProject);
.on_click(MouseButton::Left, |_, this, cx| {
this.dismiss(cx);
})
.flex(1., true)
.boxed(),
.flex(1., true),
)
.constrained()
.with_width(
cx.global::<Settings>()
.theme
.project_shared_notification
.button_width,
)
.boxed()
.with_width(theme.project_shared_notification.button_width)
.into_any()
}
}
@@ -227,18 +210,14 @@ impl View for ProjectSharedNotification {
"ProjectSharedNotification"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
let background = cx
.global::<Settings>()
.theme
.project_shared_notification
.background;
fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::AnyElement<Self> {
let background = theme::current(cx).project_shared_notification.background;
Flex::row()
.with_child(self.render_owner(cx))
.with_child(self.render_buttons(cx))
.contained()
.with_background_color(background)
.expanded()
.boxed()
.into_any()
}
}

View File

@@ -1,26 +1,30 @@
use crate::toggle_screen_sharing;
use call::ActiveCall;
use gpui::{
color::Color,
elements::{MouseEventHandler, Svg},
Appearance, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext, View,
platform::{Appearance, MouseButton},
AnyElement, AppContext, Element, Entity, View, ViewContext,
};
use settings::Settings;
use workspace::WorkspaceSettings;
use crate::ToggleScreenSharing;
pub fn init(cx: &mut MutableAppContext) {
pub fn init(cx: &mut AppContext) {
let active_call = ActiveCall::global(cx);
let mut status_indicator = None;
cx.observe(&active_call, move |call, cx| {
if let Some(room) = call.read(cx).room() {
if room.read(cx).is_screen_sharing() {
if status_indicator.is_none() && cx.global::<Settings>().show_call_status_icon {
if status_indicator.is_none()
&& settings::get::<WorkspaceSettings>(cx).show_call_status_icon
{
status_indicator = Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
}
} else if let Some((window_id, _)) = status_indicator.take() {
cx.remove_status_bar_item(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
} else if let Some((window_id, _)) = status_indicator.take() {
cx.update_window(window_id, |cx| cx.remove_window());
}
})
.detach();
@@ -37,23 +41,22 @@ impl View for SharingStatusIndicator {
"SharingStatusIndicator"
}
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
let color = match cx.appearance {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let color = match cx.window_appearance() {
Appearance::Light | Appearance::VibrantLight => Color::black(),
Appearance::Dark | Appearance::VibrantDark => Color::white(),
};
MouseEventHandler::<Self>::new(0, cx, |_, _| {
MouseEventHandler::<Self, Self>::new(0, cx, |_, _| {
Svg::new("icons/disable_screen_sharing_12.svg")
.with_color(color)
.constrained()
.with_width(18.)
.aligned()
.boxed()
})
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(ToggleScreenSharing);
.on_click(MouseButton::Left, |_, _, cx| {
toggle_screen_sharing(&Default::default(), cx)
})
.boxed()
.into_any()
}
}

View File

@@ -24,3 +24,10 @@ pub type HashMap<K, V> = std::collections::HashMap<K, V>;
pub type HashSet<T> = std::collections::HashSet<T>;
pub use std::collections::*;
// NEW TYPES
#[derive(Default)]
pub struct CommandPaletteFilter {
pub filtered_namespaces: HashSet<&'static str>,
}

View File

@@ -23,8 +23,9 @@ workspace = { path = "../workspace" }
[dev-dependencies]
gpui = { path = "../gpui", features = ["test-support"] }
editor = { path = "../editor", features = ["test-support"] }
language = { path = "../language", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
serde_json.workspace = true
workspace = { path = "../workspace", features = ["test-support"] }
ctor = "0.1"
env_logger = "0.9"
ctor.workspace = true
env_logger.workspace = true

View File

@@ -1,31 +1,24 @@
use collections::HashSet;
use collections::CommandPaletteFilter;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
actions,
elements::{ChildView, Flex, Label, ParentElement},
keymap_matcher::Keystroke,
Action, AnyViewHandle, Element, Entity, MouseState, MutableAppContext, RenderContext, View,
ViewContext, ViewHandle,
actions, elements::*, keymap_matcher::Keystroke, Action, AppContext, Element, MouseState,
ViewContext,
};
use picker::{Picker, PickerDelegate};
use settings::Settings;
use picker::{Picker, PickerDelegate, PickerEvent};
use std::cmp;
use util::ResultExt;
use workspace::Workspace;
#[derive(Default)]
pub struct CommandPaletteFilter {
pub filtered_namespaces: HashSet<&'static str>,
}
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(CommandPalette::toggle);
Picker::<CommandPalette>::init(cx);
pub fn init(cx: &mut AppContext) {
cx.add_action(toggle_command_palette);
CommandPalette::init(cx);
}
actions!(command_palette, [Toggle]);
pub struct CommandPalette {
picker: ViewHandle<Picker<Self>>,
pub type CommandPalette = Picker<CommandPaletteDelegate>;
pub struct CommandPaletteDelegate {
actions: Vec<Command>,
matches: Vec<StringMatch>,
selected_ix: usize,
@@ -47,104 +40,29 @@ struct Command {
keystrokes: Vec<Keystroke>,
}
impl CommandPalette {
pub fn new(focused_view_id: usize, cx: &mut ViewContext<Self>) -> Self {
let this = cx.weak_handle();
let actions = cx
.available_actions(cx.window_id(), focused_view_id)
.filter_map(|(name, action, bindings)| {
if cx.has_global::<CommandPaletteFilter>() {
let filter = cx.global::<CommandPaletteFilter>();
if filter.filtered_namespaces.contains(action.namespace()) {
return None;
}
}
fn toggle_command_palette(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
let focused_view_id = cx.focused_view_id().unwrap_or_else(|| cx.view_id());
workspace.toggle_modal(cx, |_, cx| {
cx.add_view(|cx| Picker::new(CommandPaletteDelegate::new(focused_view_id), cx))
});
}
Some(Command {
name: humanize_action_name(name),
action,
keystrokes: bindings
.iter()
.map(|binding| binding.keystrokes())
.last()
.map_or(Vec::new(), |keystrokes| keystrokes.to_vec()),
})
})
.collect();
let picker = cx.add_view(|cx| Picker::new("Execute a command...", this, cx));
impl CommandPaletteDelegate {
pub fn new(focused_view_id: usize) -> Self {
Self {
picker,
actions,
actions: Default::default(),
matches: vec![],
selected_ix: 0,
focused_view_id,
}
}
fn toggle(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
let workspace = cx.handle();
let window_id = cx.window_id();
let focused_view_id = cx
.focused_view_id(window_id)
.unwrap_or_else(|| workspace.id());
cx.as_mut().defer(move |cx| {
let this = cx.add_view(workspace.clone(), |cx| Self::new(focused_view_id, cx));
workspace.update(cx, |workspace, cx| {
workspace.toggle_modal(cx, |_, cx| {
cx.subscribe(&this, Self::on_event).detach();
this
});
});
});
}
fn on_event(
workspace: &mut Workspace,
_: ViewHandle<Self>,
event: &Event,
cx: &mut ViewContext<Workspace>,
) {
match event {
Event::Dismissed => workspace.dismiss_modal(cx),
Event::Confirmed {
window_id,
focused_view_id,
action,
} => {
let window_id = *window_id;
let focused_view_id = *focused_view_id;
let action = action.boxed_clone();
workspace.dismiss_modal(cx);
cx.as_mut()
.defer(move |cx| cx.dispatch_any_action_at(window_id, focused_view_id, action))
}
}
}
}
impl Entity for CommandPalette {
type Event = Event;
}
impl View for CommandPalette {
fn ui_name() -> &'static str {
"CommandPalette"
impl PickerDelegate for CommandPaletteDelegate {
fn placeholder_text(&self) -> std::sync::Arc<str> {
"Execute a command...".into()
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
ChildView::new(self.picker.clone(), cx).boxed()
}
fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
if cx.is_self_focused() {
cx.focus(&self.picker);
}
}
}
impl PickerDelegate for CommandPalette {
fn match_count(&self) -> usize {
self.matches.len()
}
@@ -153,26 +71,55 @@ impl PickerDelegate for CommandPalette {
self.selected_ix
}
fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Self>) {
fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
self.selected_ix = ix;
}
fn update_matches(
&mut self,
query: String,
cx: &mut gpui::ViewContext<Self>,
cx: &mut ViewContext<Picker<Self>>,
) -> gpui::Task<()> {
let candidates = self
.actions
.iter()
.enumerate()
.map(|(ix, command)| StringMatchCandidate {
id: ix,
string: command.name.to_string(),
char_bag: command.name.chars().collect(),
})
.collect::<Vec<_>>();
cx.spawn(move |this, mut cx| async move {
let window_id = cx.window_id();
let view_id = self.focused_view_id;
cx.spawn(move |picker, mut cx| async move {
let actions = cx
.available_actions(window_id, view_id)
.into_iter()
.filter_map(|(name, action, bindings)| {
let filtered = cx.read(|cx| {
if cx.has_global::<CommandPaletteFilter>() {
let filter = cx.global::<CommandPaletteFilter>();
filter.filtered_namespaces.contains(action.namespace())
} else {
false
}
});
if filtered {
None
} else {
Some(Command {
name: humanize_action_name(name),
action,
keystrokes: bindings
.iter()
.map(|binding| binding.keystrokes())
.last()
.map_or(Vec::new(), |keystrokes| keystrokes.to_vec()),
})
}
})
.collect::<Vec<_>>();
let candidates = actions
.iter()
.enumerate()
.map(|(ix, command)| StringMatchCandidate {
id: ix,
string: command.name.to_string(),
char_bag: command.name.chars().collect(),
})
.collect::<Vec<_>>();
let matches = if query.is_empty() {
candidates
.into_iter()
@@ -195,32 +142,37 @@ impl PickerDelegate for CommandPalette {
)
.await
};
this.update(&mut cx, |this, _| {
this.matches = matches;
if this.matches.is_empty() {
this.selected_ix = 0;
} else {
this.selected_ix = cmp::min(this.selected_ix, this.matches.len() - 1);
}
});
picker
.update(&mut cx, |picker, _| {
let delegate = picker.delegate_mut();
delegate.actions = actions;
delegate.matches = matches;
if delegate.matches.is_empty() {
delegate.selected_ix = 0;
} else {
delegate.selected_ix =
cmp::min(delegate.selected_ix, delegate.matches.len() - 1);
}
})
.log_err();
})
}
fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
cx.emit(Event::Dismissed);
}
fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
fn confirm(&mut self, cx: &mut ViewContext<Self>) {
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
if !self.matches.is_empty() {
let window_id = cx.window_id();
let focused_view_id = self.focused_view_id;
let action_ix = self.matches[self.selected_ix].candidate_id;
cx.emit(Event::Confirmed {
window_id: cx.window_id(),
focused_view_id: self.focused_view_id,
action: self.actions.remove(action_ix).action,
});
} else {
cx.emit(Event::Dismissed);
let action = self.actions.remove(action_ix).action;
cx.app_context()
.spawn(move |mut cx| async move {
cx.dispatch_action(window_id, focused_view_id, action.as_ref())
})
.detach_and_log_err(cx);
}
cx.emit(PickerEvent::Dismiss);
}
fn render_match(
@@ -229,11 +181,10 @@ impl PickerDelegate for CommandPalette {
mouse_state: &mut MouseState,
selected: bool,
cx: &gpui::AppContext,
) -> gpui::ElementBox {
) -> AnyElement<Picker<Self>> {
let mat = &self.matches[ix];
let command = &self.actions[mat.candidate_id];
let settings = cx.global::<Settings>();
let theme = &settings.theme;
let theme = theme::current(cx);
let style = theme.picker.item.style_for(mouse_state, selected);
let key_style = &theme.command_palette.key.style_for(mouse_state, selected);
let keystroke_spacing = theme.command_palette.keystroke_spacing;
@@ -241,8 +192,7 @@ impl PickerDelegate for CommandPalette {
Flex::row()
.with_child(
Label::new(mat.string.clone(), style.label.clone())
.with_highlights(mat.positions.clone())
.boxed(),
.with_highlights(mat.positions.clone()),
)
.with_children(command.keystrokes.iter().map(|keystroke| {
Flex::row()
@@ -259,8 +209,7 @@ impl PickerDelegate for CommandPalette {
Some(
Label::new(label, key_style.label.clone())
.contained()
.with_style(key_style.container)
.boxed(),
.with_style(key_style.container),
)
} else {
None
@@ -270,17 +219,15 @@ impl PickerDelegate for CommandPalette {
.with_child(
Label::new(keystroke.key.clone(), key_style.label.clone())
.contained()
.with_style(key_style.container)
.boxed(),
.with_style(key_style.container),
)
.contained()
.with_margin_left(keystroke_spacing)
.flex_float()
.boxed()
}))
.contained()
.with_style(style.container)
.boxed()
.into_any()
}
}
@@ -319,9 +266,11 @@ impl std::fmt::Debug for Command {
#[cfg(test)]
mod tests {
use std::sync::Arc;
use super::*;
use editor::Editor;
use gpui::TestAppContext;
use gpui::{executor::Deterministic, TestAppContext};
use project::Project;
use workspace::{AppState, Workspace};
@@ -342,30 +291,24 @@ mod tests {
}
#[gpui::test]
async fn test_command_palette(cx: &mut TestAppContext) {
let app_state = cx.update(AppState::test);
cx.update(|cx| {
editor::init(cx);
workspace::init(app_state.clone(), cx);
init(cx);
});
async fn test_command_palette(deterministic: Arc<Deterministic>, cx: &mut TestAppContext) {
let app_state = init_test(cx);
let project = Project::test(app_state.fs.clone(), [], cx).await;
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
let editor = cx.add_view(&workspace, |cx| {
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
let editor = cx.add_view(window_id, |cx| {
let mut editor = Editor::single_line(None, cx);
editor.set_text("abc", cx);
editor
});
workspace.update(cx, |workspace, cx| {
cx.focus(editor.clone());
cx.focus(&editor);
workspace.add_item(Box::new(editor.clone()), cx)
});
workspace.update(cx, |workspace, cx| {
CommandPalette::toggle(workspace, &Toggle, cx)
toggle_command_palette(workspace, &Toggle, cx);
});
let palette = workspace.read_with(cx, |workspace, _| {
@@ -374,15 +317,17 @@ mod tests {
palette
.update(cx, |palette, cx| {
palette.update_matches("bcksp".to_string(), cx)
palette
.delegate_mut()
.update_matches("bcksp".to_string(), cx)
})
.await;
palette.update(cx, |palette, cx| {
assert_eq!(palette.matches[0].string, "editor: backspace");
palette.confirm(cx);
assert_eq!(palette.delegate().matches[0].string, "editor: backspace");
palette.confirm(&Default::default(), cx);
});
deterministic.run_until_parked();
editor.read_with(cx, |editor, cx| {
assert_eq!(editor.text(cx), "ab");
});
@@ -395,7 +340,7 @@ mod tests {
});
workspace.update(cx, |workspace, cx| {
CommandPalette::toggle(workspace, &Toggle, cx);
toggle_command_palette(workspace, &Toggle, cx);
});
// Assert editor command not present
@@ -405,10 +350,26 @@ mod tests {
palette
.update(cx, |palette, cx| {
palette.update_matches("bcksp".to_string(), cx)
palette
.delegate_mut()
.update_matches("bcksp".to_string(), cx)
})
.await;
palette.update(cx, |palette, _| assert!(palette.matches.is_empty()));
palette.update(cx, |palette, _| {
assert!(palette.delegate().matches.is_empty())
});
}
fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
cx.update(|cx| {
let app_state = AppState::test(cx);
theme::init((), cx);
language::init(cx);
editor::init(cx);
workspace::init(app_state.clone(), cx);
init(cx);
app_state
})
}
}

View File

@@ -13,4 +13,4 @@ gpui = { path = "../gpui" }
menu = { path = "../menu" }
settings = { path = "../settings" }
theme = { path = "../theme" }
smallvec = "1.6"
smallvec.workspace = true

View File

@@ -1,43 +1,99 @@
use gpui::{
elements::*, geometry::vector::Vector2F, impl_internal_actions, keymap_matcher::KeymapContext,
platform::CursorStyle, Action, AnyViewHandle, AppContext, Axis, Entity, MouseButton,
MutableAppContext, RenderContext, SizeConstraint, Subscription, View, ViewContext,
anyhow,
elements::*,
geometry::vector::Vector2F,
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton},
Action, AnyViewHandle, AppContext, Axis, Entity, MouseState, SizeConstraint, Subscription,
View, ViewContext,
};
use menu::*;
use settings::Settings;
use std::{any::TypeId, borrow::Cow, time::Duration};
use std::{any::TypeId, borrow::Cow, sync::Arc, time::Duration};
pub type StaticItem = Box<dyn Fn(&mut MutableAppContext) -> ElementBox>;
#[derive(Copy, Clone, PartialEq)]
struct Clicked;
impl_internal_actions!(context_menu, [Clicked]);
pub fn init(cx: &mut MutableAppContext) {
pub fn init(cx: &mut AppContext) {
cx.add_action(ContextMenu::select_first);
cx.add_action(ContextMenu::select_last);
cx.add_action(ContextMenu::select_next);
cx.add_action(ContextMenu::select_prev);
cx.add_action(ContextMenu::clicked);
cx.add_action(ContextMenu::confirm);
cx.add_action(ContextMenu::cancel);
}
pub type StaticItem = Box<dyn Fn(&mut AppContext) -> AnyElement<ContextMenu>>;
type ContextMenuItemBuilder =
Box<dyn Fn(&mut MouseState, &theme::ContextMenuItem) -> AnyElement<ContextMenu>>;
pub enum ContextMenuItemLabel {
String(Cow<'static, str>),
Element(ContextMenuItemBuilder),
}
impl From<Cow<'static, str>> for ContextMenuItemLabel {
fn from(s: Cow<'static, str>) -> Self {
Self::String(s)
}
}
impl From<&'static str> for ContextMenuItemLabel {
fn from(s: &'static str) -> Self {
Self::String(s.into())
}
}
impl From<String> for ContextMenuItemLabel {
fn from(s: String) -> Self {
Self::String(s.into())
}
}
impl<T> From<T> for ContextMenuItemLabel
where
T: 'static + Fn(&mut MouseState, &theme::ContextMenuItem) -> AnyElement<ContextMenu>,
{
fn from(f: T) -> Self {
Self::Element(Box::new(f))
}
}
pub enum ContextMenuItemAction {
Action(Box<dyn Action>),
Handler(Arc<dyn Fn(&mut ViewContext<ContextMenu>)>),
}
impl Clone for ContextMenuItemAction {
fn clone(&self) -> Self {
match self {
Self::Action(action) => Self::Action(action.boxed_clone()),
Self::Handler(handler) => Self::Handler(handler.clone()),
}
}
}
pub enum ContextMenuItem {
Item {
label: Cow<'static, str>,
action: Box<dyn Action>,
label: ContextMenuItemLabel,
action: ContextMenuItemAction,
},
Static(StaticItem),
Separator,
}
impl ContextMenuItem {
pub fn item(label: impl Into<Cow<'static, str>>, action: impl 'static + Action) -> Self {
pub fn action(label: impl Into<ContextMenuItemLabel>, action: impl 'static + Action) -> Self {
Self::Item {
label: label.into(),
action: Box::new(action),
action: ContextMenuItemAction::Action(Box::new(action)),
}
}
pub fn handler(
label: impl Into<ContextMenuItemLabel>,
handler: impl 'static + Fn(&mut ViewContext<ContextMenu>),
) -> Self {
Self::Item {
label: label.into(),
action: ContextMenuItemAction::Handler(Arc::new(handler)),
}
}
@@ -51,7 +107,10 @@ impl ContextMenuItem {
fn action_id(&self) -> Option<TypeId> {
match self {
ContextMenuItem::Item { action, .. } => Some(action.id()),
ContextMenuItem::Item { action, .. } => match action {
ContextMenuItemAction::Action(action) => Some(action.id()),
ContextMenuItemAction::Handler(_) => None,
},
ContextMenuItem::Static(..) | ContextMenuItem::Separator => None,
}
}
@@ -66,7 +125,6 @@ pub struct ContextMenu {
selected_index: Option<usize>,
visible: bool,
previously_focused_view_id: Option<usize>,
clicked: bool,
parent_view_id: usize,
_actions_observation: Subscription,
}
@@ -80,29 +138,27 @@ impl View for ContextMenu {
"ContextMenu"
}
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
cx.add_identifier("menu");
cx
fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
Self::reset_to_default_keymap_context(keymap);
keymap.add_identifier("menu");
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
if !self.visible {
return Empty::new().boxed();
return Empty::new().into_any();
}
// Render the menu once at minimum width.
let mut collapsed_menu = self.render_menu_for_measurement(cx).boxed();
let expanded_menu = self
.render_menu(cx)
.constrained()
.dynamically(move |constraint, cx| {
SizeConstraint::strict_along(
Axis::Horizontal,
collapsed_menu.layout(constraint, cx).x(),
)
})
.boxed();
let mut collapsed_menu = self.render_menu_for_measurement(cx);
let expanded_menu =
self.render_menu(cx)
.constrained()
.dynamically(move |constraint, view, cx| {
SizeConstraint::strict_along(
Axis::Horizontal,
collapsed_menu.layout(constraint, view, cx).0.x(),
)
});
Overlay::new(expanded_menu)
.with_hoverable(true)
@@ -110,7 +166,7 @@ impl View for ContextMenu {
.with_anchor_position(self.anchor_position)
.with_anchor_corner(self.anchor_corner)
.with_position_mode(self.position_mode)
.boxed()
.into_any()
}
fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
@@ -119,9 +175,7 @@ impl View for ContextMenu {
}
impl ContextMenu {
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let parent_view_id = cx.parent().unwrap();
pub fn new(parent_view_id: usize, cx: &mut ViewContext<Self>) -> Self {
Self {
show_count: 0,
anchor_position: Default::default(),
@@ -131,7 +185,6 @@ impl ContextMenu {
selected_index: Default::default(),
visible: Default::default(),
previously_focused_view_id: Default::default(),
clicked: false,
parent_view_id,
_actions_observation: cx.observe_actions(Self::action_dispatched),
}
@@ -147,28 +200,33 @@ impl ContextMenu {
.iter()
.position(|item| item.action_id() == Some(action_id))
{
if self.clicked {
self.cancel(&Default::default(), cx);
} else {
self.selected_index = Some(ix);
cx.notify();
cx.spawn(|this, mut cx| async move {
cx.background().timer(Duration::from_millis(50)).await;
this.update(&mut cx, |this, cx| this.cancel(&Default::default(), cx));
})
.detach();
}
self.selected_index = Some(ix);
cx.notify();
cx.spawn(|this, mut cx| async move {
cx.background().timer(Duration::from_millis(50)).await;
this.update(&mut cx, |this, cx| this.cancel(&Default::default(), cx))?;
anyhow::Ok(())
})
.detach_and_log_err(cx);
}
}
fn clicked(&mut self, _: &Clicked, _: &mut ViewContext<Self>) {
self.clicked = true;
}
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
if let Some(ix) = self.selected_index {
if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) {
cx.dispatch_any_action(action.boxed_clone());
match action {
ContextMenuItemAction::Action(action) => {
let window_id = cx.window_id();
let view_id = self.parent_view_id;
let action = action.boxed_clone();
cx.app_context()
.spawn(|mut cx| async move {
cx.dispatch_action(window_id, view_id, action.as_ref())
})
.detach_and_log_err(cx);
}
ContextMenuItemAction::Handler(handler) => handler(cx),
}
self.reset(cx);
}
}
@@ -189,7 +247,6 @@ impl ContextMenu {
self.items.clear();
self.visible = false;
self.selected_index.take();
self.clicked = false;
cx.notify();
}
@@ -251,7 +308,7 @@ impl ContextMenu {
self.visible = true;
self.show_count += 1;
if !cx.is_self_focused() {
self.previously_focused_view_id = cx.focused_view_id(cx.window_id());
self.previously_focused_view_id = cx.focused_view_id();
}
cx.focus_self();
} else {
@@ -264,38 +321,42 @@ impl ContextMenu {
self.position_mode = mode;
}
fn render_menu_for_measurement(&self, cx: &mut RenderContext<Self>) -> impl Element {
let window_id = cx.window_id();
let style = cx.global::<Settings>().theme.context_menu.clone();
fn render_menu_for_measurement(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
let style = theme::current(cx).context_menu.clone();
Flex::row()
.with_child(
Flex::column()
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
match item {
ContextMenuItem::Item { label, .. } => {
let style = style.item.style_for(
&mut Default::default(),
Some(ix) == self.selected_index,
);
Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
match item {
ContextMenuItem::Item { label, .. } => {
let style = style.item.style_for(
&mut Default::default(),
Some(ix) == self.selected_index,
);
Label::new(label.to_string(), style.label.clone())
.contained()
.with_style(style.container)
.boxed()
match label {
ContextMenuItemLabel::String(label) => {
Label::new(label.to_string(), style.label.clone())
.contained()
.with_style(style.container)
.into_any()
}
ContextMenuItemLabel::Element(element) => {
element(&mut Default::default(), style)
}
}
ContextMenuItem::Static(f) => f(cx),
ContextMenuItem::Separator => Empty::new()
.collapsed()
.contained()
.with_style(style.separator)
.constrained()
.with_height(1.)
.boxed(),
}
}))
.boxed(),
ContextMenuItem::Static(f) => f(cx),
ContextMenuItem::Separator => Empty::new()
.collapsed()
.contained()
.with_style(style.separator)
.constrained()
.with_height(1.)
.into_any(),
}
})),
)
.with_child(
Flex::column()
@@ -306,17 +367,20 @@ impl ContextMenu {
&mut Default::default(),
Some(ix) == self.selected_index,
);
KeystrokeLabel::new(
window_id,
self.parent_view_id,
action.boxed_clone(),
style.keystroke.container,
style.keystroke.text.clone(),
)
.boxed()
match action {
ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
self.parent_view_id,
action.boxed_clone(),
style.keystroke.container,
style.keystroke.text.clone(),
)
.into_any(),
ContextMenuItemAction::Handler(_) => Empty::new().into_any(),
}
}
ContextMenuItem::Static(_) => Empty::new().boxed(),
ContextMenuItem::Static(_) => Empty::new().into_any(),
ContextMenuItem::Separator => Empty::new()
.collapsed()
@@ -324,63 +388,84 @@ impl ContextMenu {
.with_height(1.)
.contained()
.with_style(style.separator)
.boxed(),
.into_any(),
}
}))
.contained()
.with_margin_left(style.keystroke_margin)
.boxed(),
.with_margin_left(style.keystroke_margin),
)
.contained()
.with_style(style.container)
}
fn render_menu(&self, cx: &mut RenderContext<Self>) -> impl Element {
fn render_menu(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
enum Menu {}
enum MenuItem {}
let style = cx.global::<Settings>().theme.context_menu.clone();
let style = theme::current(cx).context_menu.clone();
let window_id = cx.window_id();
MouseEventHandler::<Menu>::new(0, cx, |_, cx| {
MouseEventHandler::<Menu, ContextMenu>::new(0, cx, |_, cx| {
Flex::column()
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
match item {
ContextMenuItem::Item { label, action } => {
let action = action.boxed_clone();
MouseEventHandler::<MenuItem>::new(ix, cx, |state, _| {
let action = action.clone();
let view_id = self.parent_view_id;
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
let style =
style.item.style_for(state, Some(ix) == self.selected_index);
Flex::row()
.with_child(
Label::new(label.clone(), style.label.clone())
.contained()
.boxed(),
)
.with_child({
let keystroke = match &action {
ContextMenuItemAction::Action(action) => Some(
KeystrokeLabel::new(
window_id,
self.parent_view_id,
view_id,
action.boxed_clone(),
style.keystroke.container,
style.keystroke.text.clone(),
)
.flex_float()
.boxed()
.flex_float(),
),
ContextMenuItemAction::Handler(_) => None,
};
Flex::row()
.with_child(match label {
ContextMenuItemLabel::String(label) => {
Label::new(label.clone(), style.label.clone())
.contained()
.into_any()
}
ContextMenuItemLabel::Element(element) => {
element(state, style)
}
})
.with_children(keystroke)
.contained()
.with_style(style.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(Clicked);
cx.dispatch_any_action(action.boxed_clone());
.on_up(MouseButton::Left, |_, _, _| {}) // Capture these events
.on_down(MouseButton::Left, |_, _, _| {}) // Capture these events
.on_click(MouseButton::Left, move |_, menu, cx| {
menu.cancel(&Default::default(), cx);
let window_id = cx.window_id();
match &action {
ContextMenuItemAction::Action(action) => {
let action = action.boxed_clone();
cx.app_context()
.spawn(|mut cx| async move {
cx.dispatch_action(
window_id,
view_id,
action.as_ref(),
)
})
.detach_and_log_err(cx);
}
ContextMenuItemAction::Handler(handler) => handler(cx),
}
})
.on_drag(MouseButton::Left, |_, _| {})
.boxed()
.on_drag(MouseButton::Left, |_, _, _| {})
.into_any()
}
ContextMenuItem::Static(f) => f(cx),
@@ -390,14 +475,17 @@ impl ContextMenu {
.with_height(1.)
.contained()
.with_style(style.separator)
.boxed(),
.into_any(),
}
}))
.contained()
.with_style(style.container)
.boxed()
})
.on_down_out(MouseButton::Left, |_, cx| cx.dispatch_action(Cancel))
.on_down_out(MouseButton::Right, |_, cx| cx.dispatch_action(Cancel))
.on_down_out(MouseButton::Left, |_, this, cx| {
this.cancel(&Default::default(), cx);
})
.on_down_out(MouseButton::Right, |_, this, cx| {
this.cancel(&Default::default(), cx);
})
}
}

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