question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A better Prettier CLI and config file

See original GitHub issue

I would like to present a completely new take on Prettier’s CLI. Let’s restart from scratch. This isn’t a complete spec or even fully thought through yet. But I’ve been having this on my mind for a long time and wanted to get something out there for discussion.

Goal: Make it easy to do the right thing, and hard to do the wrong thing. Simplify everything! No magic! More explicitness! But still easy to use.

This is a bad thing:

{
    "scripts": {
        "prettier": "prettier --single-quote --write \"src/**/*.{js,css}\" \"docs/**/*.md\""
    }
}

Why?

  • Editors won’t know which options to use, and which files to work on.
  • How do you run that with --check for CI?
  • What about git hooks or lint-staged?
  • What if you want to run prettier on a couple of files from the command line for a one-off task?
  • It is annoying to write those globs.

Globs and --foo-style options for formatting are anti-patterns. I suggest we get rid of them!

Instead, imagine having this:

{
    "scripts": {
        "prettier": "prettier format",
        "prettier:check": "prettier check"
    }
}

Nice, huh?

prettier

A subcommand is required. Print help.

prettier format [PATH]...

Format files and overwrite them on disk. Like today’s --write, more or less.

Passing no paths is a shortcut for prettier format ..

If a PATH points to a file, that file is formatted. If the file is ignored a note about that is printed. (We could have a --force flag to override.) If the file type isn’t something that Prettier handles, an error is printed.

If a PATH points to a directory, Prettier will automatically find all files to work deeply and format them. Which files exactly? More on that later.

Regarding the output, I think we can take inspiration from black. Let’s be minimal and print stuff like “✨All files formatted with Prettier!” and “✨Formatted 5 files.”

Who will use this?

  • People who for whatever reason don’t run Prettier in their editor.
  • After adding Prettier to a project, or changing an option.
  • After a CI failure, you can run prettier format to fix everything.
  • After a big find-and-replace refactor in src/components you can run prettier format src/components to fix formatting (without having to run on the entire project).
  • git hooks.
  • lint-staged (it passes absolute paths to tools).

Note: I think we should ditch built-in support for globs altogether. They’re not needed! If you need globs for a one-off command, then it’s up to you to get a good shell for yourself and use its globs.

prettier check [PATH]...

Like prettier format, but only checks if files are already formatted or not. Like today’s --check.

Who will use this?

  • CI.
  • Git hooks and lint-staged could alternatively use this instead of prettier format.

prettier stdio FILE

Run Prettier over stdin and stdout.

The FILE argument is required, so that Prettier knows what file type the content is, and if the file should be ignored or not.

If FILE exists, prettier stdio some/file.js is a shortcut for prettier stdio some/file.js < some/file.js.

If FILE is ignored, or isn’t supported by Prettier we should use exit codes and stuff to let the caller know.

Who will use this?

  • vim-prettier, and other editors that shell out to format.
  • People who occasionally use Prettier as a unix tool. prettier stdio tmp/index.min.js | grep foo.

prettier.json

Prettier advocates for few options, but our configuration is super complicated! I think we should take a step back and re-think here.

Let’s have one config file to rule them all – prettier.json. A prettier.json should be required for Prettier to run – this makes Prettier opt-in. For every file Prettier formats, there must be a prettier.json next to it or up the file tree. Only the first found prettier.json is used – there’s no cascade.

Making Prettier opt-in would make it super clear that a project is using Prettier. For example, it would help editor integrations. I hate it when my editor changes an entire file on save when I just wanted to make a quick edit in somebody else’s non-Prettier project.

A --force flag could be used for one-off formatting of files with no prettier.json. That would use the default options. --config ~/foo/prettier.json could use a specified one.

prettier.json should specify:

  • Options. Global ones, as well as options per language. Not per file. Per language. This allows having double quotes in HTML, but single quotes in JS – even inside <script> tags in HTML. Some options can only be set per language and not globally – such as which parser to use.
  • File extension mappings. You should be able to map .foo to be handled as JSON, for example. When running prettier format ., Prettier looks for all files with known file extensions.
  • What files to ignore. An array of gitignore-style patterns. And the possibility to link to ignore files, such as .gitignore and .eslintignore. Or .prettierignore or .whateverignore if you want! Explicit and no magic. Ignore *.html to opt out of HTML formatting, for example.
  • Anything you’d ever need to configure, so you don’t need CLI flags. prettier.json should be the source of truth so that other tools know what to do.

We should continue supporting "@company/prettier-config" and similar to load the config from an npm package.

prettier init could be an interactive command to help create a prettier.json. For most people, it will just contain {} (an empty object), though. For example, it could ask which languages your are/aren’t interested in formatting (based on what files we find on disk) and help set up ignore patterns. And we could detect .gitignore and .eslintignore and ask if we should link to them.

Not sure if we need overrides.

Some options could take a "editorconfig" as a value. If so, we’ll look for .editorconfig to figure out what value to use. No magic!

What about YAML or TOML or whatever instead of JSON? Keep it simple, I’d say! prettier.json should ideally be so short and simple that we don’t need a fancy language to write it.

{
  "useTabs": true,
  "javascript": {
    "singleQuote": true,
    "parser": "babel-flow"
  },
  "fileExtensions": {
    ".foo": "javascript"
  },
  "ignore": [
    "*.html",
    "/legacy/",
    { "include": "./.gitignore" },
    "!*.config.js"
  ]
}

Open questions

  • --range-start, --range-end and --cursor-offset. Not sure how they fit in yet.
  • --insert-pragma and --require-pragma. I’ve never used these myself so I’m not sure.
  • --file-info and --support-info. Not sure these are going to be needed anymore.
  • Many other little command line options…

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:60
  • Comments:26 (18 by maintainers)

github_iconTop GitHub Comments

5reactions
kachkaevcommented, Oct 20, 2020

Wow! configplugins works indeed and this trick is also compatible with Yarn PnP / v2! Terrific! I just tweaked my personal shared Prettier config, updated the config package in https://github.com/kachkaev/njt/pull/29 and Prettier picked the right plugins! I did not have to add them as the project dependencies, having @kachkaev/prettier-config was enough! 🕺

Perhaps, we could improve docs to help Yarn PnP / v2 Berry folks with their shared config? Lack of node_modules in such setups makes plugin autodiscovery unavailable, so setting configplugins becomes only working solution.

3reactions
octogonzcommented, Dec 9, 2019

Making Prettier opt-in would make it super clear that a project is using Prettier. For example, it would help editor integrations. I hate it when my editor changes an entire file on save when I just wanted to make a quick edit in somebody else’s non-Prettier project.

+1

I’ll mention that in a large monorepo, we generally prefer for each project to have its own local tooling config files. In most cases the config will be a single line that $extends from a boilerplate "@company/foo-config", with occasional extra options for certain projects. This makes it easier to move projects around between folders/monorepos without worrying about coordinating changes in a centralized config file. It also reduces the overhead for updates, since modifying a centralized file in a large monorepo typically requires extra approvals/signoffs that can slow people down.

At least, this was certainly the case for files like tsconfig.json, eslintrc.js, jest.config.js, etc. With TypeScript/ESLint we also had to worry about different projects using different versions of the tool/plugins, essentially requiring the tool to be invoked separately in each folder. The Prettier config /might/ avoid this concern, since migrating to a new Prettier release should require no human effort. So maybe Prettier’s CLI can always be invoked once for an entire monorepo. I haven’t used it enough to have a good sense of this yet.

Just something to think about in your design discussion.

Read more comments on GitHub >

github_iconTop Results From Across the Web

CLI - Prettier
It's better to use a configuration file for formatting options like --single-quote and --trailing-comma instead of passing them as CLI flags.
Read more >
CLI | Dev Cheatsheets - Michael Currin
... Prettier can be used as a CLI tool. See the Prettier CLI page of the Prettier docs for more info. ... These...
Read more >
How to Format All Files in a Directory with Prettier
If you want to change Prettier's configuration, put a .prettierrc file in the root folder of your project, and then run the prettier...
Read more >
How to configure Prettier and VSCode - Gleb Bahmutov
Formatting every file as you save it is nice, but we can also format ALL source files at once using Prettier CLI. In...
Read more >
Run prettier from CLI with config in package.json
Prettier uses cosmiconfig for configuration file support. This means you can configure prettier via (in order of precedence):. A "prettier" key ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found