stevearc / conform.nvim

Lightweight yet powerful formatter plugin for Neovim
MIT License
2.89k stars 150 forks source link

question: How to execute prettier with yarn? #323

Closed ralinc closed 5 months ago

ralinc commented 6 months ago

Neovim version (nvim -v)

0.9.5

Operating system/version

MacOS 14.4

Add the debug logs

Log file

[WARN] No formatters found for file.tsx

Describe the bug

Hello there,

I am trying everything but cannot make prettier be executed by yarn. I don't have prettier globally installed and I don't want to. Having a config like this:

  {
    'stevearc/conform.nvim',
    opts = {
      formatters_by_ft = {
        typescript = { 'prettier' },
      },
  },

fails to find prettier and logs this warning:

[WARN] No formatters found for file.tsx

So, I am trying all possible combinations following the readme, but nothing seems to work. Here are my experiments, but there were more :)

  {
    'stevearc/conform.nvim',
    opts = {
      formatters_by_ft = {
        -- typescriptreact = { 'prettier' },
      },
      formatters = {
        typescriptreact = {
          inherit = false,
          command = 'yarn',
          args = { 'prettier', '--stdin-filepath', '$FILENAME' },
        },
      },
      format_on_save = {
        timeout_ms = 500,
      },
    },
    config = function()
      require('conform').formatters.typescriptreact = {
        inherit = false,
        command = 'yarn',
        args = { 'prettier', '--stdin-filepath', '$FILENAME' },
      }
    end,
  },

With this config nothing seems to happen.

Help! How to invoke prettier with yarn?

Thanks.

What is the severity of this bug?

blocking (cannot use plugin)

Steps To Reproduce

  1. Use latest yarn version 4.
  2. Add prettier to project dev dependencies.
  3. Try to format any tsx file using the prettier from the project.

Expected Behavior

The file is properly formatted using the prettier from the project.

Minimal example file

function Empty() {
  return (
    <div />
  )
}

Minimal init.lua

No response

Additional context

No response

stevearc commented 5 months ago

When you run prettier with yarn, it should just be looking for the executable under node_modules/.bin/. Conform attempts to do the exact same thing by default, if you look at the definition of the prettier formatter: https://github.com/stevearc/conform.nvim/blob/0a530b31acacf10eca9f9a74b2434ece4d232ca3/lua/conform/formatters/prettier.lua#L54 and the definition of that utility function https://github.com/stevearc/conform.nvim/blob/0a530b31acacf10eca9f9a74b2434ece4d232ca3/lua/conform/util.lua#L3-L8

You will want to have

      formatters_by_ft = {
        typescript = { 'prettier' },
        typescriptreact = { 'prettier' },
      },

If the node_modules/.bin/prettier executable does exist and this config doesn't work for you, paste in the output of :ConformInfo so I can see what formatters are defined and their status.

mikavilpas commented 5 months ago

I think this might be related to yarn plug and play (https://yarnpkg.com/features/pnp), which

I ran into some issues using yarn pnp when working with another project a couple of months ago, and was able to opt out of plug and play on the project level with nodeLinker: node-modules. However, because this is a project level setting it might not be possible to apply this to all projects because yarn pnp has other features that are useful.

My understanding of this issue is not that good, but for what it's worth, I'd like to make some recommendations:

A workaround

Looks like someone was able to opt out of yarn pnp for prettier specifically using a command on their system only: https://github.com/yarnpkg/berry/discussions/5576

My guess is that you would also have to do this for all the prettier plugins that your project uses, but I have not tried this option myself.

A long term fix

To get the benefits of yarn pnp for all users of conform.nvim automatically, I think yarn's editor sdks would be the correct way to do it (https://yarnpkg.com/getting-started/editor-sdks). It does mention neovim on the page, but I have to admit I don't understand this very well.

ralinc commented 5 months ago

@mikavilpas I use Yarn v4, but with linker node_modules. I don't use PnP.

@stevearc I have prettier in node_modules/.bin but the plugin cannot find it. Here is the output of :ConformInfo

Log file: ~/.local/state/nvim/conform.log

Formatters for this buffer:
<none>

Other formatters:
prettier unavailable: Command not found

I think this may be related to Volta. For all my projects I install and pin Yarn versions with Volta.

mikavilpas commented 5 months ago

I see, it looks like the same setup that is working for me (namely, yarn 4 without pnp + conform.nvim). You could try ruling out Volta by using a project without it.

Maybe you already have a project like this, but if not, you can clone https://github.com/GregRos/parjs/ and try it there.

ralinc commented 5 months ago

I found the problem.

I've installed the prettier as a dev dependency using package.json. But I have the following directory/file setup in my node_modules.

$ ls node_modules/.bin

lrwxr-xr-x@ 1 ralin  staff    28B Jan 26 09:48 prettier@ -> ../prettier/bin/prettier.cjs

Now, when I try to run node_modules/.bin/prettier in my shell, it tries to execute ../prettier/bin/prettier.cjs which is not an executable and fails with: zsh: permission denied: node_modules/.bin/prettier.

But I don't know how to fix it. This node_modules is generated by yarn install. Any ideas?

You can tell me how to run prettier with yarn using the plugin configuration. That will solve my issue as well. I want to do yarn prettier ....

mikavilpas commented 5 months ago

Can you provide a reproduction repo where you have this issue?

It works for me in parjs:

image

My config: https://github.com/mikavilpas/dotfiles/blob/d8cdf9489cbcab8ad8d1946189966c6d350e917d/.config/nvim/lua/plugins/formatting.lua?plain=1#L26

(I use prettierd but it also works if I change it to prettier)

My :ConformInfo (here I changed it to prettier to make things simpler): image

ralinc commented 5 months ago

Ok. It works with Parjs. It works with two other TS projects of mine. I guess the problem is with one specific project. The problem is not with the Conform plugin. I confirm. Thank you so much for your help!

crierr commented 4 months ago

Thanks for the information. I have two projects that one is using Yarn PnP and the other is using npm. Running globally installed version of prettier doesn't work with locally installed prettier-plugin-tailwindcss.

I ended up making this configuration for myself. It might be useful someone who have to use yarn pnp.

https://gist.github.com/crierr/322ea6711df7614a000cb3f3be87bf93

-- If prettier is installed with Yarn PnP, run below command to generate bin-prettier.js.
-- `yarn dlx @yarnpkg/sdks base`
-- @see https://yarnpkg.com/getting-started/editor-sdks
local util = require("conform.util")
local fs = require("conform.fs")

return {
  "stevearc/conform.nvim",
  opts = {
    formatters = {
      prettier = {
        command = function(self, bufnr)
          local cmd = util.find_executable({ ".yarn/sdks/prettier/bin-prettier.js" }, "")(self, bufnr)
          if cmd ~= "" then
            return cmd
          end
          -- return type of util.from_node_modules is fun(self: conform.FormatterConfig, ctx: conform.Context): string
          ---@diagnostic disable-next-line
          return util.from_node_modules(fs.is_windows and "prettier.cmd" or "prettier")(self, bufnr)
        end,
      },
    },
  },
}
Mautjee commented 4 months ago

@crierr

I ended up making this configuration for myself. It might be useful someone who have to use yarn pnp.

this solved my problem thanks!!