Commit graph

106 commits

Author SHA1 Message Date
Ian Chamberlain
5409d4793f
vim: Change surrounds with Mini{Quotes,Brackets} and AnyQuotes (#51067)
Part of #48241 (`dsq` still needs to be implemented, I can try to do in
another PR if+when this is merged)

AnyBrackets was already supported, and these various surrounds were
supported with other vim motions, this just brings parity for "change
surrounds".
	
Also adds MiniBrackets support since it works the same way as MiniQuotes
does.

Most of this change is just test cases for vim edits with `csq` + `csb`,
using the keybinds described in the docs:
https://zed.dev/docs/vim#any-bracket-functionality

Also did a slight refactor to reuse some constants for supported pairs,
for consistency.


Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Fixed vim `change surrounds` for MiniQuotes, MiniBrackets, and
AnyQuotes
2026-05-09 04:10:54 +00:00
Cole Miller
2a15bf630d
Require multibuffer excerpts to be ordered and nonoverlapping (#52364)
TODO:
- [x] merge main
- [x] nonshrinking `set_excerpts_for_path`
- [x] Test-drive potential problem areas in the app
- [x] prepare cloud side
- [x] test collaboration
- [ ] docstrings
- [ ] ???

## Context

### Background

Currently, a multibuffer consists of an arbitrary list of
anchor-delimited excerpts from individual buffers. Excerpt ranges for a
fixed buffer are permitted to overlap, and can appear in any order in
the multibuffer, possibly separated by excerpts from other buffers.
However, in practice all code that constructs multibuffers does so using
the APIs defined in the `path_key` submodule of the `multi_buffer` crate
(`set_excerpts_for_path` etc.) If you only use these APIs, the resulting
multibuffer will maintain the following invariants:

- All excerpts for the same buffer appear contiguously in the
multibuffer
- Excerpts for the same buffer cannot overlap
- Excerpts for the same buffer appear in order
- The placement of the excerpts for a specific buffer in the multibuffer
are determined by the `PathKey` passed to `set_excerpts_for_path`. There
is exactly one `PathKey` per buffer in the multibuffer

### Purpose of this PR

This PR changes the multibuffer so that the invariants maintained by the
`path_key` APIs *always* hold. It's no longer possible to construct a
multibuffer with overlapping excerpts, etc. The APIs that permitted
this, like `insert_excerpts_with_ids_after`, have been removed in favor
of the `path_key` suite.

The main upshot of this is that given a `text::Anchor` and a
multibuffer, it's possible to efficiently figure out the unique excerpt
that includes that anchor, if any:

```
impl MultiBufferSnapshot {
    fn buffer_anchor_to_anchor(&self, anchor: text::Anchor) -> Option<multi_buffer::Anchor>;
}
```

And in the other direction, given a `multi_buffer::Anchor`, we can look
at its `text::Anchor` to locate the excerpt that contains it. That means
we don't need an `ExcerptId` to create or resolve
`multi_buffer::Anchor`, and in fact we can delete `ExcerptId` entirely,
so that excerpts no longer have any identity outside their
`Range<text::Anchor>`.

There are a large number of changes to `editor` and other downstream
crates as a result of removing `ExcerptId` and multibuffer APIs that
assumed it.

### Other changes

There are some other improvements that are not immediate consequences of
that big change, but helped make it smoother. Notably:

- The `buffer_id` field of `text::Anchor` is no longer optional.
`text::Anchor::{MIN, MAX}` have been removed in favor of
`min_for_buffer`, etc.
- `multi_buffer::Anchor` is now a three-variant enum (inlined slightly):

```
enum Anchor {
    Min,
    Excerpt {
        text_anchor: text::Anchor,
        path_key_index: PathKeyIndex,
        diff_base_anchor: Option<text::Anchor>,
    },
    Max,
}
```

That means it's no longer possible to unconditionally access the
`text_anchor` field, which is good because most of the places that were
doing that were buggy for min/max! Instead, we have a new API that
correctly resolves min/max to the start of the first excerpt or the end
of the last excerpt:


```
impl MultiBufferSnapshot {
    fn anchor_to_buffer_anchor(&self, anchor: multi_buffer::Anchor) -> Option<text::Anchor>;
}
```
- `MultiBufferExcerpt` has been removed in favor of a new
`map_excerpt_ranges` API directly on `MultiBufferSnapshot`.

## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Co-authored-by: Conrad <conrad@zed.dev>
2026-04-01 17:25:32 +00:00
Lukas Wirth
7d80412cca
Reduce amount of monomorphizations from FnMut closures (#49453)
Replaces a bunch of `impl FnMut` parameters with `&mut dyn FnMut` for
functions where this is the sole generic parameter.
Release Notes:

- N/A *or* Added/Fixed/Improved ...
2026-02-18 12:00:02 +01:00
Xin Zhao
05a021c4a3
docs: Correct action descriptions to reflect actual purpose (#46931)
Thanks @injust for pointing this out. It seems a few other action docs
were also copied from elsewhere and weren't updated to reflect their
actual purpose. This PR fixes those, though I may not have covered all
of them.

Closes #46832

Release Notes:

- N/A

---------

Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
2026-01-28 23:10:25 +00:00
Will Garrison
5a8a7d8666
vim: Change logic in subword motion subword_start calculation (#45341)
- Update subword boundary detection to stop at semantic punctuation
  (quotes, brackets, parens)
- Treat `.`, `-`, and `_` as subword separators for consistent behavior
- Extract `is_subword_start` and `is_subword_end` helpers for reuse in
  motion and object handling
- Add comprehensive tests for all subword motions matching vim's
  CamelCaseMotion behavior

Closes #23344

Release Notes:

- Fixed bug in Vim mode's subword motion punctuation handling

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-01-13 18:02:59 +00:00
Mateo Kruk
4dd54c6742
vim: Fix word object count multiplier (2aw, 2iw) (#45686)
Closes #44251

## Context

Commands like `2daw` or `c2iw` were ignoring the count multiplier
because the word text object functions (`in_word`, `around_word`)
weren't using the `times` parameter. This fix propagates the count
through these functions so all operators correctly handle multiple
words.

## Before


https://github.com/user-attachments/assets/d5effa8a-4c04-4d70-a6b5-389cba730ca9

## After


https://github.com/user-attachments/assets/c50e4c0c-ea5c-4673-9c98-3d924b448025


Release Notes:

- Fixed vim mode count multiplier for word text objects (`2aw`, `2iw`,
`2aW`, `2iW`)
2026-01-05 09:13:25 -07:00
Ben Kunkle
435d4c5f24
vim: Make vaf include const for arrow functions in JS/TS/TSX (#45327)
Closes #24264

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-12-18 21:56:47 -05:00
Dino
14958a47ed
vim: Attempt to fix flaky vim tests on windows (#45089)
Both `test_miniquotes_object` and `test_minibrackets_object` rely on
tree-sitter parsing for `MultiBufferSnapshot.bracket_ranges` to find
quote/bracket pairs. The `VimTestContext.set_state` call eventually
triggers async tree-sitter parsing, but `run_until_parked` doesn't
guarantee parsing completion.

We suspect this is what might be causing the flakiness on Windows, as
the syntax might not yet be parsed when the
`VimTestContext.simulate_keystrokes` call is made, so there's no bracket
pairs returned.

This commit adds an explicit await call on `Bufffer.parsing_idle` after
each `VimTestContext.set_state` call, to ensure tree-sitter parsing
completes before simulating keystrokes.

Release Notes:

- N/A
2025-12-17 10:31:36 +00:00
Kirill Bulatov
bd5569b338
Bump tree-sitter to the latest (#44963)
Release Notes:

- N/A

Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
2025-12-16 20:41:38 +02:00
Kirill Bulatov
16666f5357
Use single languages::{rust_lang, markdown_lang} in tests across the codebase (#44282)
This allows referencing proper queries and keeping the tests up-to-date.

Release Notes:

- N/A
2025-12-06 18:49:21 +00:00
Lukas Wirth
628c52a96a
buffer: Keep the shorter language setting names for the common operation (#43915)
cc
https://github.com/zed-industries/zed/pull/43888#issuecomment-3597265087

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-12-01 18:55:33 +01:00
Lukas Wirth
9af6e82e65
language: Only block the foreground on buffer reparsing when necessary (#43888)
Gist is we only need to block the foreground thread for reparsing if
immediate language changes are useful to the user. That is usually only
the case when they edit the buffer

Release Notes:

- Improved performance of large project searches and project diffs

Co-authored by: David Kleingeld <david@zed.dev>
2025-12-01 14:57:15 +01:00
Lukas Wirth
c98b2d6944
multi_buffer: Typed MultiBufferOffset (#42707)
This PR introduces a new `MultiBufferOffset` new type wrapping size. The
goal of this is to make it clear at the type level when we are
interacting with offsets of a multi buffer versus offsets of a language
/ text buffer. This improves readability of things quite a bit by making
it clear what kind of offsets one is working with while also reducing
accidental bugs by using the wrong kin of offset for the wrong API.

This PR also uncovered two minor bugs due to that.

Does not yet introduce the MultiBufferPoint equivalent, that is for a
follow up PR.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-11-19 22:00:58 +00:00
Dino
8d15ec7f99
vim: Fix mini delimiters in multibuffer (#41834)
- Update `vim::object::find_mini_delimiters` in order to filter out the
  ranges before calling `vim::object::cover_or_next`, ensuring that the
  provided ranges are converted from multibuffer space into buffer
  space.
- Remove the `range_filter` from `vim::object::cover_or_next` was the
  `find_mini_delimiters` function is the only caller and no longer uses
  it

Closes #41346 

Release Notes:

- Fixed a crash that could occur when using `vim::MiniQuotes` and
`vim::MiniBrackets` in a multibuffer
2025-11-04 11:08:51 +00:00
Dino
3d4f488d46
vim: Update change surrounds to match vim's behavior (#38721)
These changes refactor the whitespace handling logic for Vim's change
surrounds command (`cs`), making its behavior closely match
[tpope/vim-surround](https://github.com/tpope/vim-surround), following
[this
discussion](https://github.com/zed-industries/zed/issues/38169#issuecomment-3304129461).

Zed's current implementation has two main differences when compared to
[tpope/vim-surround](https://github.com/tpope/vim-surround):

- It only considers whether a single space should be added or removed,
instead of all the space that is between the surrounding character and
the content
- It only takes into consideration the new surrounding characters in
order to determine whether to add or remove that space

A review of
[tpope/vim-surround](https://github.com/tpope/vim-surround)'s behavior
reveals these rules for whitespace:

* Quote to Quote
    * Whitespace is never changed
* Quote to Bracket
    * If opening bracket, add one space
    * If closing bracket, do not add space
* Bracket to Bracket
    * If opening to opening, keep only one space
    * If opening to closing, remove all space
    * If closing to opening, add one space
    * If closing to closing, do not change space
* Bracket to Quote
    * If opening, remove all space
    * If closing, preserve all space

Below is a table with examples for each scenario. A new test has also
been added to specifically check the scenarios outlined above,
`vim::surrounds::test::test_change_surrounds_vim`.

| Type              | Before      | Command | After         |
|-------------------|-------------|---------|---------------|
| Quote → Quote     | `'   a   '` | `cs'"`  | `"   a   "`   |
| Quote → Quote     | `"   a   "` | `cs"'`  | `'   a   '`   |
| Quote → Bracket   | `'   a   '` | `cs'{`  | `{    a    }` |
| Quote → Bracket   | `'   a   '` | `cs'}`  | `{   a   }`   |
| Bracket → Bracket | `[   a   ]` | `cs[{`  | `{ a }`       |
| Bracket → Bracket | `[   a   ]` | `cs[}`  | `{a}`         |
| Bracket → Bracket | `[   a   ]` | `cs]{`  | `{    a    }` |
| Bracket → Bracket | `[   a   ]` | `cs]}`  | `{   a   }`   |
| Bracket → Quote   | `[   a   ]` | `cs['`  | `'a'`         |
| Bracket → Quote   | `[   a   ]` | `cs]'`  | `'   a   '`   |

These changes diverge from
[tpope/vim-surround](https://github.com/tpope/vim-surround) when
handling newlines. For example, with the following snippet:

```rust
fn test_surround() {
    if 2 > 1 {
        println!("place cursor here");
    }
};
```

Placing the cursor inside the string and running any combination of
‎`cs{[`, ‎`cs{]`, ‎`cs}[`, or ‎`cs}]` would previously remove newline
characters. With these changes, using commands like ‎`cs}]` will now
preserve newlines.

Related to #38169
Closes #39334

Release Notes:

- Improved Vim’s change surround command to closely match
[tpope/vim-surround](https://github.com/tpope/vim-surround) behavior.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-10-09 12:18:48 +01:00
Lukas Wirth
2bfcd60b88
editor: Shrink DisplayMapSnapshot from 824 to 256 bytes (#39568)
We have unnecessary clones for the fields here as most of the snapshots
contain the others hierarchically.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-10-06 08:08:49 +00:00
Piotr Osiewicz
a90abb1009
Bump Rust to 1.90 (#38436)
Release Notes:

- N/A

---------

Co-authored-by: Nia Espera <nia@zed.dev>
Co-authored-by: Julia Ryan <juliaryan3.14@gmail.com>
2025-09-22 14:36:10 -07:00
Romans Malinovskis
cba9ff55c7
Helix Select Mode (#37748)
Please credit @eliaperantoni, for the original PR (#34136).
Merge after (#34060) to avoid conflicts.

Closes https://github.com/zed-industries/zed/issues/33838
Closes https://github.com/zed-industries/zed/issues/33906

Release Notes:
- Helix will no longer sometimes fall out into "normal" mode, will
remain in "helix normal" (example: vv)
- Added dedicated "helix select" mode that can be targeted by
keybindings

Known issues:
- [ ] Helix motion, especially surround-add will not properly work in
visual mode, as it won't call `helix_move_cursor`. It is possible
however to respect self.mode in change_selection now.
- [ ] Some operations, such as `Ctrl+A` (increment) or `>` (indent) will
collapse selection also. I haven't found a way to avoid it.

---------

Co-authored-by: fantacell <ghub@giggo.de>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-09-12 17:47:07 +02:00
fantacell
10989c702c
helix: Add match operator (#34060)
This is an implementation of matching like "m i (", as well as "] (" and
"[ (" in `helix_mode` with a few supported objects and a basis for more.

Release Notes:

- Added helix operators for selecting text objects

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-09-08 08:48:47 -06:00
Dino
e5a968b709
vim: Fix change surround with any brackets text object (#37386)
This commit fixes an issue with how the `AnyBrackets` object was handled
with change surrounds (`cs`). With the keymap below, if one was to use
`csb{` with the text `(bracketed)` and the cursor inside the
parentheses, the text would not change.

```json
{
  "context": "vim_operator == a || vim_operator == i || vim_operator == cs",
  "bindings": {
    "b": "vim::AnyBrackets"
  }
}
```

Unfortunately there was no implementation for finding a corresponding
`BracketPair` for the `AnyBrackets` object, meaning that, when using
`cs` (change surrounds) the code would simply do nothing.

This commit updates this logic so as to try and find the nearest
surrounding bracket (parentheses, curly brackets, square brackets or
angle brackets), ensuring that `cs` also works with `AnyBrackets`.

Closes #24439

Release Notes:

- Fixed handling of `AnyBrackets` in vim's change surrounds (`cs`)
2025-09-02 16:03:14 -07:00
tidely
7bdc99abc1
Fix clippy::redundant_clone lint violations (#36558)
This removes around 900 unnecessary clones, ranging from cloning a few
ints all the way to large data structures and images.

A lot of these were fixed using `cargo clippy --fix --workspace
--all-targets`, however it often breaks other lints and needs to be run
again. This was then followed up with some manual fixing.

I understand this is a large diff, but all the changes are pretty
trivial. Rust is doing some heavy lifting here for us. Once I get it up
to speed with main, I'd appreciate this getting merged rather sooner
than later.

Release Notes:

- N/A
2025-08-20 12:20:13 +02:00
Piotr Osiewicz
8f567383e4
Auto-fix clippy::collapsible_if violations (#36428)
Release Notes:

- N/A
2025-08-19 13:27:24 +00:00
Lucas Vieira
768b2de368
vim: Fix ap text object selection when there is line wrapping (#35485)
In Vim mode, `ap` text object (used in `vap`, `dap`, `cap`) was
selecting multiple paragraphs when soft wrap was enabled. The bug was
caused by using DisplayRow coordinates for arithmetic instead of buffer
row coordinates in the paragraph boundary calculation.

Fix by converting to buffer coordinates before arithmetic, then back to
display coordinates for the final result.

Closes #35085

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-08-18 09:57:53 -06:00
Ben Kunkle
6cd4dbdea1
gpui: Store action documentation (#33809)
Closes #ISSUE

Adds a new `documentation` method to actions, that is extracted from doc
comments when using the `actions!` or derive macros.

Additionally, this PR adds doc comments to as many action definitions in
Zed as possible.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-02 21:14:33 -04:00
Rift
97c5c5a6e7
vim: Respect count for paragraphs (#33489)
Closes #32462 

Release Notes:

- vim: Paragraph objects now support counts (`d2ap`, `v2ap`, etc.)

---------

Co-authored-by: Rift <no@e.mail>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-06-27 22:05:47 -06:00
Michael Sloan
24c94d474e
gpui: Simplify Action macros + support doc comments in actions! (#33263)
Instead of a menagerie of macros for implementing `Action`, now there
are just two:

* `actions!(editor, [MoveLeft, MoveRight])`
* `#[derive(..., Action)]` with `#[action(namespace = editor)]`

In both contexts, `///` doc comments can be provided and will be used in
`JsonSchema`.

In both contexts, parameters can provided in `#[action(...)]`:

- `namespace = some_namespace` sets the namespace. In Zed this is
required.

- `name = "ActionName"` overrides the action's name. This must not
contain "::".

- `no_json` causes the `build` method to always error and
`action_json_schema` to return `None`
and allows actions not implement `serde::Serialize` and
`schemars::JsonSchema`.

- `no_register` skips registering the action. This is useful for
implementing the `Action` trait
while not supporting invocation by name or JSON deserialization.

- `deprecated_aliases = ["editor::SomeAction"]` specifies deprecated old
names for the action.
These action names should *not* correspond to any actions that are
registered. These old names
can then still be used to refer to invoke this action. In Zed, the
keymap JSON schema will
accept these old names and provide warnings.

- `deprecated = "Message about why this action is deprecation"`
specifies a deprecation message.
In Zed, the keymap JSON schema will cause this to be displayed as a
warning. This is a new feature.

Also makes the following changes since this seems like a good time to
make breaking changes:

* In `zed.rs` tests adds a test with an explicit list of namespaces. The
rationale for this is that there is otherwise no checking of `namespace
= ...` attributes.

* `Action::debug_name` renamed to `name_for_type`, since its only
difference with `name` was that it

* `Action::name` now returns `&'static str` instead of `&str` to match
the return of `name_for_type`. This makes the action trait more limited,
but the code was already assuming that `name_for_type` is the same as
`name`, and it requires `&'static`. So really this just makes the trait
harder to misuse.

* Various action reflection methods now use `&'static str` instead of
`SharedString`.

Release Notes:

- N/A
2025-06-24 04:34:51 +00:00
Osvaldo
a09e5d255b
vim: Create anyquotes, anybrackets, miniquotes, and minibrackets text objects (#26748)
## Why?
Some users expressed a preference for the AnyQuotes and AnyBrackets text
objects to align more closely with traditional Vim behavior, rather than
the mini.ai plugin's approach. To address this, I’ve introduced two new
text objects: MiniQuotes and MiniBrackets. These retain the mini.ai
plugin behavior, while the updated AnyQuotes and AnyBrackets now follow
the logic described in [this bug
report](https://github.com/zed-industries/zed/issues/25563) and [this
bug report](https://github.com/zed-industries/zed/issues/25562).

## Behavior Overview:
### AnyQuotes and AnyBrackets:
These now prioritize the innermost range first (e.g., the closest quotes
or brackets). If none are found, they fall back to searching the current
line. This aligns with the behavior requested in the issue.

### MiniQuotes and MiniBrackets:
These maintain the mini.ai plugin behavior, prioritizing the current
line before expanding the search outward.

### Usage Examples:
AnyQuotes: Works like ```ci', ci", ci` , ca', ca", ca` , etc.```

AnyBrackets: Works like ```ci(, ci[, ci{, ci<, ca(, ca[, ca{, ca<,
etc.```

Please give these changes a try and let me know your thoughts!

### Release Notes:

- vim: Add AnyQuotes, AnyBrackets, MiniQuotes and MiniBrackets text
objects

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-04-29 22:09:27 +00:00
Piotr Osiewicz
dc64ec9cc8
chore: Bump Rust edition to 2024 (#27800)
Follow-up to https://github.com/zed-industries/zed/pull/27791

Release Notes:

- N/A
2025-03-31 20:55:27 +02:00
Yicheng Liu
089ea5da50
vim: Fix back quotes not recognized as object (#24999)
Currently back quotes ``` `` ``` not recognized as an object in vim
mode, so ```c i ` ```, ```d i ` ``` not working.

It seems to be a typo introduced in #22632 : The`DoubleQuotes` line was
doubled while the `BackQuotes` line was missing.

Release Notes:

- vim: Fixed back quotes ``` `` ``` not recognized as object.

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-02-26 14:21:12 -05:00
5brian
52f73e0c2d
vim: Refactor and fix multiline operations (#25055)
Changes:
- [x] Cursor at the start during yank operations on objects (`yip`,
`yab` etc).
- [x] Refactors this: Trim all leading and trailing whitespace from
inner multiline bracket selection.
  - This leaves a nicely indented line when doing `ci{` `vi{d` etc
  - [x] Checks for empty selection
  - [x] Removed moving cursor to the start in visual bracket operations

This cleans up the previous implementation by providing a simpler check
in `surrounding_markers`, instead of calling a new function in
`expand_object`. No functionality was changed there except for handling
the empty selection and removing some cursor adjustments that should not
have been there after further testing.

Release Notes:

- N/A
2025-02-24 18:30:21 -07:00
5brian
bbb8d63de0
vim: Register backquote object (#25502)
Closes #25496

Release Notes:

- vim: Fixed operations on backtick quotes
2025-02-24 15:33:17 -07:00
Marshall Bowers
3b3c379852
docs: Fix casing of "Tree-sitter" (#25427)
This PR fixes the casing of "Tree-sitter" in the docs.

It is "Tree-sitter", not "Tree Sitter" or "Tree-Sitter".

Release Notes:

- N/A
2025-02-23 15:30:10 +00:00
Conrad Irwin
13da468e22
Fix for #25039 (#25138)
Release Notes:

- vim: Fix crash in `ci{`
2025-02-19 06:24:54 +00:00
Osvaldo
e068c7b4b4
vim: Update anyquotes and anybrackets to behave like mini.ai plugin (#24167)
### Overview
This PR improves the existing
[mini.ai‐like](https://github.com/echasnovski/mini.ai) text-object logic
for both “AnyQuotes” (quotes) and “AnyBrackets” (brackets) by adding a
multi‐line fallback. The first pass searches only the current line for a
best match (cover or next); if none are found, we do a multi‐line pass.
This preserves mini.ai's usual “line priority” while ensuring we can
detect pairs that start on one line and end on another.

### What Changed
1. Brackets
- Line-based pass uses `gather_line_brackets(map, caret.row()) `to find
bracket pairs `((), [], {}, <>) `on the caret’s line.
- If that fails, we call `gather_brackets_multiline(map)` to single‐pass
scan the entire buffer, collecting bracket pairs that might span
multiple lines.
- Finally, we apply the mini.ai “**cover or next**” logic
(`pick_best_range`) to choose the best.
2.  Quotes
  - Similar line-based pass with `gather_line_quotes(map, caret.row())`.
- If no local quotes found, we do a multi‐line fallback with
`gather_quotes_multiline(map)`, building a big string for the whole
buffer and using naive regex for "...", '...', and `...`.
  - Also preserves “inner vs. outer” logic:
- For inner (e.g. `ciq`), we skip bounding quotes or brackets if the
range is at least 2 characters wide.
    - For outer (`caq`), we return the entire range.
3. Shared “`finalize`” helpers
- `finalize_bracket_range` and `finalize_quote_range` handle the “inner”
skip‐chars vs. “outer” logic.
  - Both rely on the same “line first, then full fallback” approach.

### Why This Matters
- **Old Behavior**: If you had multi‐line brackets { ... } or multi‐line
quotes spanning multiple lines, they weren’t found at all, since we only
scanned line by line. That made text objects like ci{ or ciq fail in
multi-line scenarios.
- **New Behavior**: We still do a quick line pass (for user‐friendly
“line priority”), but now if that fails, we do a single‐pass approach
across the entire buffer. This detects multi‐line pairs and maintains
mini.ai’s “cover‐or‐next” picking logic.

### Example Use Cases
- **Curly braces:** e.g., opening { on line 10, closing } on line 15 →
previously missed; now recognized.
- **Multi‐line quotes**: e.g., "'Line 1\nLine 2', no longer missed. We
do gather_quotes_multiline with a naive regex matching across newlines.

### Tests
- Updated and expanded coverage in:
  - test_anyquotes_object:
    - Includes a multi-line '...' test case.
- E.g. 'first' false\n<caret>string 'second' → ensuring we detect
multi‐line quotes.
  - test_anybrackets_object:
- Verifies line‐based priority but also multi‐line bracket detection.
- E.g., an open bracket ( on line 3, close ) on line 5, which used to
fail.

### Limitations / Future Enhancements
- **Escaping**: The current approach for quotes is naive and doesn’t
handle escape sequences (like \") or advanced parser logic. For deeper
correctness, we’ll need more advanced logic, this is also not supported
in the original mini.ai plugin so it is a known issue that won't be
attended for now.

### Important Notes
- Fix for the bug: https://github.com/zed-industries/zed/issues/23889
this PR addresses that bug specifically for the AnyQuotes text object.
Note that the issue still remains in the built-in motions (ci', ci",
ci`).
- Caret Position Differences: The caret position now slightly deviates
from Vim’s default behavior. This is intentional. I aim to closely mimic
the mini.ai plugin. Because these text objects are optional
(configurable via vim.json), this adjusted behavior is considered
acceptable and in my opinion the new behavior is better and it should be
the default in vim. Please review the new tests for details and context.
- Improved Special Cases: I’ve also refined how “false strings” in the
middle and certain curly-bracket scenarios are handled. The test suite
reflects these improvements, resulting in a more seamless coding
experience overall.

### References:
- Mini.AI plugin in nvim: https://github.com/echasnovski/mini.ai

Thank you for reviewing these changes!

Release Notes:

- Improve logic of aq, iq, ab and ib motions to work more like mini.ai
plugin
2025-02-17 14:55:48 -07:00
5brian
0a146793ea
vim: Prevent around word operations from selecting indentation (#24635)
Closes https://github.com/zed-industries/zed/issues/15323

Changes:
Added check for first word on line

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

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

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



Release Notes:

- vim: Prevent around word operations from selecting indentation
2025-02-11 11:35:59 -07:00
5brian
236f51cddd
vim: Update vi{ (#24601)
Small fix: Following up on
https://github.com/zed-industries/zed/pull/24518 where i missed `vi{`.

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

Also moved the cursor to the start.

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

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

Release Notes:

- N/A
2025-02-10 22:26:26 -07:00
5brian
69d415c8d0
vim: Multiline operation improvements (#24518)
Closes #15711

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

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

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

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

Release Notes:

- vim: Improved multi-line operations
2025-02-10 08:45:06 -07:00
5brian
7bddb390ca
vim: Preserve trailing whitespace in inner text object selections (#24481)
Closes #24438

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

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



Release Notes:

- vim: Preserve trailing whitespace in inner text object selections

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-02-08 02:50:34 +00:00
smit
00c2a30059
Migrate keymap and settings + edit predictions rename (#23834)
- [x] snake case keymap properties
- [x] flatten actions
- [x] keymap migration + notfication
- [x] settings migration + notification
- [x] inline completions -> edit predictions 

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

Release Notes:

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

---------

Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2025-02-07 21:17:07 +05:30
0x2CA
c24f22cd14
vim: Fix Around Subword not including whitespace (#24356)
Closes #24271

Release Notes:

- Fixed Around Subword No Include Whitespace
2025-02-06 08:54:04 -07:00
Conrad Irwin
a3c7dc3321
vim: Add textobject e for entire file (#24039)
Co-Authored-By: Thomas Heartman <zed@thomasheartman.com>

Release Notes:

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

Co-authored-by: Thomas Heartman <zed@thomasheartman.com>
2025-01-31 21:38:19 -07:00
Osvaldo
9e31b1019e
vim: Add any brackets to support motions like ab and ib to work with any type of brackets (#23679)
# Add AnyBrackets text object for Vim mode

## Overview
This PR introduces a new text object `AnyBrackets` that allows
operations on the closest matching pair of brackets, regardless of the
bracket type. This enhances the editing experience by reducing the need
to identify specific bracket types before performing text operations.

By default, this feature is NOT mapped to any key in vim.json. However,
it can be enabled manually, and the recommended key for mapping is b:

If you want to add it to your zed keymap config you need to add the
following config:
```json
{
	"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
	"bindings": {
		"b": "vim::AnyBrackets"
	}
}
```

## Features
- New text object that works with parentheses `()`, square brackets
`[]`, curly braces `{}`, they are also know as round brackets, square
brackets and curly brackets in english.
- Automatically finds the closest matching pair of any bracket type
- Works with all standard Vim operators (delete, change, yank)
- Supports both "inside" and "around" variants (`i` and `a`)

## Usage Examples
```vim
# Delete inside the closest brackets
di(  # Works on (), [] or {} depending on which is closest

# Change around the closest brackets
ca[  # Works on (), [] or {}  depending on which is closest

# Visual select inside the closest brackets
vi{  # Works on (), [] or {}  depending on which is closest
```

# References:
- Based on the popular plugin https://github.com/echasnovski/mini.ai

# Important Notes
This PR also fixes a bug with nested quotes on AnyQuotes, now it works
fine with any type of quotes or brackets.
Please take a look at the new tests to understand the expected behavior.

Release Notes:

- vim: Add `ab`/`ib` "AnyBrackets" text objects that are the smallest of
`a(`, `a[` or `a{` or `i(`, `i[` or `i{`
- vim: Fix aq/iq "AnyQuotes" text objects when they are nested
2025-01-28 20:23:17 -07:00
Nathan Sobo
6fca1d2b0b
Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
2025-01-26 03:02:45 +00:00
Max Brunsfeld
d2c55cbe3d
Rework diff rendering to allow putting the cursor into deleted text, soft-wrapping and scrolling deleted text correctly (#22994)
Closes #12553

* [x] Fix `diff_hunk_before`
* [x] Fix failure to show deleted text when expanding hunk w/ cursor on
second line of the hunk
* [x] Failure to expand diff hunk below the cursor.
* [x] Delete the whole file, and expand the diff. Backspace over the
deleted hunk, panic!
* [x] Go-to-line now counts the diff hunks, but it should not
* [x] backspace at the beginning of a deleted hunk deletes too much text
* [x] Indent guides are rendered incorrectly 
* [ ] Fix randomized multi buffer tests

Maybe:
* [ ] Buffer search should include deleted text (in vim mode it turns
out I use `/x` all the time to jump to the next x I can see).
* [ ] vim: should refuse to switch into insert mode if selection is
fully within a diff.
* [ ] vim `o` command when cursor is on last line of deleted hunk.
* [ ] vim `shift-o` on first line of deleted hunk moves cursor but
doesn't insert line
* [x] `enter` at end of diff hunk inserts a new line but doesn't move
cursor
* [x] (`shift-enter` at start of diff hunk does nothing)
* [ ] Inserting a line just before an expanded hunk collapses it

Release Notes:


- Improved diff rendering, allowing you to navigate with your cursor
inside of deleted text in diff hunks.

---------

Co-authored-by: Conrad <conrad@zed.dev>
Co-authored-by: Cole <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Michael <michael@zed.dev>
Co-authored-by: Agus <agus@zed.dev>
Co-authored-by: João <joao@zed.dev>
2025-01-24 14:18:22 -07:00
0x2CA
26be440d99
vim: Add Subword Textobject (#22387)
Closes #22761

[Vim: subword text object?
#22280](https://github.com/zed-industries/zed/discussions/22280)

Release Notes:

- Added Vim SubWord TextObject

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-01-14 03:34:49 +00:00
Michael Sloan
6aba3950d2
Improve keymap json schema (#23044)
Also:

* Adds `impl_internal_actions!` for deriving the `Action` trait without
registering.

* Removes some deserializers that immediately fail in favor of
`#[serde(skip)]` on fields where they were used. This also omits them
from the schema.

Release Notes:

- Keymap settings file now has more JSON schema information to inform
`json-language-server` completions and info, particularly for actions
that take input.
2025-01-13 02:34:35 +00:00
Osvaldo
222b04548d
vim: Add AnyQuotes support for unified quote handling similar to mini.ai nvim (#22263)
### Edit 1:
I tested it locally and it works!

### IMPORTANT: 
**Feedback and suggestions for improvement are greatly appreciated!**

This commit introduces a new AnyQuotes text object to handle text
surrounded by single quotes ('), double quotes ("), or back quotes (`)
seamlessly. The following changes are included:

- Added AnyQuotes to the Object enum to represent the new feature.
- Registered AnyQuotes as an action in the actions! macro and register
function to ensure proper integration with Vim actions like ci, ca, di,
and da.
- Extended Object::range to check for surrounding single, double, or
back quotes sequentially.
- Updated methods like is_multiline and always_expands_both_ways to
ensure consistent behavior with other text objects.
- Added support in surrounding_markers to evaluate any of the quote
types when AnyQuotes is invoked.
- This enhancement provides users with a flexible and unified way to
interact with text objects enclosed by different types of quotes.

Release Notes:

- vim: Add `aq`/`iq` "any quote" text objects that are the smallest of
`a"`, `a'` or <code>a`</code>
2025-01-08 03:00:20 +00:00
Conrad Irwin
44c492b3c0
Fix panic in vim text-objects (#22753)
Caused by messing up offsets between multi-buffers and excerpts :(

Fixes #22739

Release Notes:

- Fixed a panic in vim text objects in multibuffers
2025-01-07 15:55:25 +00:00
Conrad Irwin
196fd65601
Fix panic folding in multi-buffers (#21511)
Closes #19054

Rename `max_buffer_row()` to `widest_line_number()` to (hopefully)
prevent
people assuming it means the same as `max_point().row`.

Release Notes:

- Fixed a panic when folding in a multibuffer
2024-12-04 00:01:32 -07:00
Waleed Dahshan
8f08787cf0
Implement Helix Support (WIP) (#19175)
Closes #4642 

- Added the ability to switch to helix normal mode, with an additional
helix visual mode.
- <kbd>ctrl</kbd><kbd>h</kbd> from Insert mode goes to Helix Normal
mode. <kbd> i </kbd> and <kbd> a </kbd> to go back.
- Need to find a way to perform the helix normal mode selection with
<kbd> w </kbd>, <kbd>e </kbd>, <kbd> b </kbd> as a first step. Need to
figure out how the mode will interoperate with the VIM mode as the new
additions are in the same crate.
2024-12-03 23:19:52 -07:00