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
46.97k stars 2.7k forks source link

format_on_save external command quality of life improvements (cwd for monorepos) #15205

Open bcheidemann opened 1 month ago

bcheidemann commented 1 month ago

Check for existing issues

Describe the feature

Currently, the format_on_save external command option is difficult to set up in monorepos due to the default working directory being in the project root, instead of the containing directory of the .zed folder. Consider the following:

project_root
|_ .zed
| |_ settings.json
|
|_ apps
| |_ some_app
| | |_ .zed
| |   |_ settings.json
| |_ ...
|_ ... 

If I am using an external formatting tool in some_app (e.g. prettier) then I likely need to run that tool with apps/some_app as the working directory.

Intuitively, I would set this up as follows:

// apps/some_app/.zed/settings.json
{
    "tab_size": 4,
    "format_on_save": "off",
    "file_types": {
        "Blade": ["*.blade.php"]
    },
    "languages": {
        "Blade": {
            "tab_size": 2,
            "format_on_save": {
                "external": {
                    // Expect this to run in `<project_root>/apps/some_app` but actually runs in `<project_root>`
                    "command": "npx",
                    "arguments": [
                        "prettier",
                        "--stdin-filepath",
                        "{buffer_path}"
                    ]
                }
            }
        }
    }
}

(yes, I'm using prettier to format blade files... don't ask!)

Because the default file path is not set correctly, I need to use the following counterintuitive workaround:

// apps/some_app/.zed/settings.json
                  "external": {
 -                    "command": "npx",
 -                    "arguments": [
 -                        "prettier",
 -                        "--stdin-filepath",
 -                        "{buffer_path}"
 -                    ]
 +                    "command": "sh",
 +                    "arguments": [
 +                        "-c",
 +                        "cd ./apps/some_app && npx prettier --stdin-filepath '{buffer_path}'"
 +                    ]
                  }

Ideally, the current working directory would default to the directory containing the .zed/settings.json file in which the external command is configured, or failing this, it should be configurable.

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

If the default working directory were changed to be the containing folder of the .zed/settings.json file, then no new config options would be required.

If configurable working directories were to be introduced, this could be done as follows:

            "format_on_save": {
                "external": {
                    "working_directory": "{local_config_root}", // Where `{local_config_root}` is `<project_root>/apps/some_app`
                    "working_directory": "{global_config_root}", // Where `{global_config_root}` is `<project_root>`
                    "working_directory": "./some/sub/directory", // Resolves to "{local_config_root}/some/sub/directory" or "{global_config_root}/some/sub/directory" depending on default
                    "command": "...",
                    "arguments": ["..."]
                }
            }
bcheidemann commented 1 month ago

Happy to implement the required changes here once/if they are decided.