zed icon indicating copy to clipboard operation
zed copied to clipboard

Language specific hard_tabs setting is ignored.

Open foonly opened this issue 9 months ago • 4 comments

Summary

In languages like PHP, which are two languages (HTML+PHP), the behavior of the tab key in a given file can vary depending on position if hard_tabs is set for PHP, but not HTML.

Steps to trigger the problem:

  1. Use the following settings:
{
  "hard_tabs": false,
  "languages": {
    "PHP": {
      "hard_tabs": true
    },
    "Twig": {
      "hard_tabs": true
    }
  }
}
  1. Create a PHP file:
<?php

?>
  1. On fresh restart, placing the cursor between the php tags the first tab gives a hard tab then, second tab spaces. Undo and retab, spaces. Reload Zed and you get one tab again.

Expected Behavior: Hard tabs are always used if set for a given language

Actual Behavior: an odd mix of hard tabs and spaces are used.

Zed Version and System Specs

Zed: v0.178.5 (Zed) OS: Linux Wayland arch unknown Memory: 14.5 GiB Architecture: x86_64 GPU: AMD Radeon Graphics (RADV RENOIR) || radv || Mesa 25.0.2-arch1.2

foonly avatar Mar 27 '25 15:03 foonly

I cannot reproduce with those settings creating a PHP file in an empty directory. But I can reproduce if I create something.php in a directory which has a .zed/settings.json that has hard_tabs = false (e.g. inside the zed repo: https://github.com/zed-industries/zed/blob/2dee03ebca65d95fb2524eed9802f4b1eaadbf0c/.zed/settings.json#L45

Do you perhaps have a .zed/settings.json or an .editorconfig with indent_style = space? I believe .editorconfig apply from parent directory as well. Do any of the parent directories have an editorconfig? (e.g. your home directory)

notpeter avatar Mar 27 '25 17:03 notpeter

I checked my whole drive for .editorconfig files, and made a new project with just an JavaScript file and a PHP file, as well as a .zed/settings.json override where I tested the settings.

I did some further testing on this project, and there is clearly some missing information. The setting works correctly on JavaScript files, but on PHP files it has a very strange behavior, where the first tab follows the language specific setting, but subsequent ones follow the global setting.

So with hard tabs on in the language, and off globally, it produces one tab, then 3 spaces, and then 4 spaces for the rest of the line. The other way around it produces 4 spaces and then tabs for the rest of the line. If I don't use a language specific override for PHP, it follows the global setting.

I tried turning off all language server features, but the problem persists.

I don't currently have access to any non Arch Linux systems, but I will try to install something else in a virtual machine, and see if I can reproduce it there.

foonly avatar Mar 27 '25 20:03 foonly

I installed Fedora 41 on a virtual machine, and used the install script to install zed. I have the exact same behavior there, but I noticed something new: Before the <?php start tag, the language specific setting has no effect, whereas after the start tag, the first tab behaves according to the language specific setting, and subsequent ones ignore it. After additional testing, I noticed that the "wrong" tabs are actually following the "hard_tabs" setting from HTML. I didn't have an HTML language definition in my settings.json file, hence it defaulted to the global setting.

This seem to be a problem only with PHP, and it might be more related to the PHP plugin. Let me know if I should re-file it somewhere else.

foonly avatar Mar 27 '25 22:03 foonly

There's some wonky stuff going on here. I can reproduce multiple broken behaviors.

With a user settings.json of:

{
  "show_edit_predictions": false,
  "show_whitespaces": "all"
}

And a project .zed/settings.json:

{
  "languages": {
    "PHP": {
      "hard_tabs": true
    }
  }
}

And a single a.php file:

<?php

?>

On fresh restart, placing the cursor between the php tags the first tab gives a hard tab then it's broken. Second tab spaces. Undo and retab, spaces. Reload Zed and you get one tab again.

https://github.com/user-attachments/assets/a4436c15-cf39-4cf3-a0ea-b7a340e88b8d

As a workaround, to get Zed to consistently use hard tabs in PHP requires the following settings (ugh):

    "HTML": {
      "hard_tabs": true
    }

If you want to see explicitly where it's incorrectly using the HTML in PHP files:

    "HTML": {
      "tab_size": 8
    }

Thanks for reporting and taking the time to help flesh out a proper repro.

notpeter avatar Apr 02 '25 13:04 notpeter