zed-industries / zed

Code at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.
https://zed.dev
Other
51.05k stars 3.17k forks source link

Tab indentation broken in PHP files (spaces vs tabs not respected, three spaces sometimes inserted) #21167

Open LinusU opened 1 week ago

LinusU commented 1 week ago

Check for existing issues

Describe the bug / provide steps to reproduce it

I've recently have been mucking about in some of our old PHP files, and it seems like the indentation isn't working that well with Zed.

Here is my .zed/settings.json:

{
  "languages": {
    "JSON": {
      "tab_size": 4
    },
    "PHP": {
      "hard_tabs": true,
      "tab_size": 4
    }
  }
}

Let me show you an easy to reproduce example is below:

Type the following code into the editor:

@php
    $today = Carbon::now()->format('Y-m-d');

    if (!isset($result->opening_hours[$today])) {
        $oh_class = 'noinfo';
        $oh_title = 'Våra öppettider';
    } else if (empty($result->opening_hours[$today]->hours)) {
        $oh_class = 'closed';
        if (empty($result->opening_hours[$today]->title)) {
            $oh_title = 'Stängt för dagen';
        } else {
            $oh_title = $result->opening_hours[$today]->title;
        }
    } else {
    HERE
    }
@endphp

<div class="opening-hours {{ $result->opening_hours_badge->class }}" data-toggle="popover" data-placement="top" title="Öppettider" data-content="{{ $result->opening_hours_popover }}">
    <i class="icon-clock"></i>&nbsp;{{ $result->opening_hours_badge->label }}
</div>

Make sure that the indentation is all tabs. Now select the HERE text, delete it by pressing backspace, and then press tab in order to indent the now empty line one step. Instead of inserting one tab character, Zed inserts three spaces.

I've accidentally committed code with a three space indentation that should have been a tab 😅

I've only observed this when writing PHP. Rust and JavaScript have been working fine for me, but in those projects I use autoformatting via dprint/rustfmt and indent using spaces so the setup is a bit different.

Accepting Copilot suggestions also inserts spaces instead of tabs, and trying to replace them by going to the line and press shift-tab until the entire line is totally de-dented, and then indenting it again seems to insert the random three spaces indentation as well.

Environment

Zed: v0.161.2 (Zed) OS: macOS 15.0.1 Memory: 36 GiB Architecture: aarch64

If applicable, add mockups / screenshots to help explain present your vision of the feature

Screenshot 2024-11-25 at 15 44 28

If applicable, attach your Zed.log file to this issue.

No response

LinusU commented 1 week ago

Also, trying to fix the indentation manually after copilot insertion have wrecked it is a bit frustrating 😅

https://github.com/user-attachments/assets/89ddab98-486c-4cd0-8c89-2858673e403c

Here I'm trying to copy two tabs, and then replace all the first 8 spaces with the two tabs by selecting them and pasting. Somehow most of the tabs ends up on the last line 😁

LinusU commented 1 week ago

(and most importantly, don't judge my for my PHP here, I'm working in a 20+ year old system 🙈)

LinusU commented 1 week ago

Another funny edge case, for some reason, on these specific lines, pressing tab produces 4 spaces at the start of the lines before all the tabs:

https://github.com/user-attachments/assets/5b48208a-6b77-4694-a265-4299217a065b

pjv commented 1 week ago

I’m guessing the issue here is likely Zed not recognizing the @php and @endphp tags and so not seeing all the code in between those tags as code.

Try putting this into your editor and see if you get different behavior:

<?php
    $today = Carbon::now()->format('Y-m-d');

    if (!isset($result->opening_hours[$today])) {
        $oh_class = 'noinfo';
        $oh_title = 'Våra öppettider';
    } else if (empty($result->opening_hours[$today]->hours)) {
        $oh_class = 'closed';
        if (empty($result->opening_hours[$today]->title)) {
            $oh_title = 'Stängt för dagen';
        } else {
            $oh_title = $result->opening_hours[$today]->title;
        }
    } else {
    HERE
    }
?>

<div class="opening-hours {{ $result->opening_hours_badge->class }}" data-toggle="popover" data-placement="top" title="Öppettider" data-content="{{ $result->opening_hours_popover }}">
    <i class="icon-clock"></i>&nbsp;{{ $result->opening_hours_badge->label }}
</div>
RemcoSmitsDev commented 1 week ago

Yeah, you might need to install this Laravel blade extension that adds support for blade files, as they are not normal PHP files.