Files
would-reformat/README.md
2023-01-03 12:20:49 -06:00

3.8 KiB

would-reformat - automatic reformatting for emacs without being annoying

Motivation

I've never liked it when a text editor formats code for me without my asking. I don't like it when the editor uses cheap heuristics (indent a new line to match the previous one? blah!) and I don't like it when the editor shells out to one of the new generation of automatic code formatters.

But I don't enjoy formatting code by hand either. Who does?

This is my solution: some shell scripts and some emacs lisp code.

The shell script would-reformat.sh takes a file's full path as its argument. It tells you if that file would be reformatted.

The shell script do-reformat.sh takes a file's full path as its argument. It reformats the file.

Finally, there is some rudimentary machinery to run would-reformat.sh when saving a file and to run do-reformat.sh when you hit <F1>.

Supported programming languages and file formats

  • python
  • go
  • javascript
  • typescript
  • vue
  • css
  • php
  • html
  • jsx
  • tsx
  • css
  • scss
  • sh
  • dart

Python uses black; go uses gofmt; dart uses dart format. The rest use prettier. Adding new programming languages is easy, assuming they have a formatter with a dry run mode.

Installation

  • Change to the directory where you want to use would-reformat: you@host:~ $ cd ~/devel/my-project
  • From that directory, call the script install.sh in the directory where you have would-reformat checked out: you@host:~/devel/my-project $ ~/src/would-reformat/install.sh

Be sure to run the installation script from the root of your project's directory, not a subdirectory.

This will do the following:

  • create the directory ~/devel/my-project/bin if it does not exist
  • create ~/devel/my-project/bin/_reformat-common.sh, ~/devel/my-project/bin/do-reformat.sh, and ~/devel/my-project/bin/would-reformat.sh as symlinks to files with the same names in ~/src/would-reformat.
  • create ~/devel/my-project/.dir-locals.el as a symlink to the file with the same name in ~/src/would-reformat.

This should work from a checkout wherever you happen to have it. It doesn't need to be in ~/src. However, if you remove the checkout, then the symlinks will break, so don't do that. If you rename the checkout, the symlinks will break.

The directory bin with respect to my-project however is hardcoded (enhancements here are welcome).

The script install.sh favors conservatism over cleverness: for example, if it finds the file ~/devel/my-project/bin/do-reformat.sh then it checks whether it is a symlink to ~/src/would-reformat/do-reformat.sh. If it is not, then it just prints a warning rather than attempting to correct the situation.

Troubleshooting

nothing works from emacs

Be sure to run the install script from your project's root as determined by (projectile-project-root).

problems with nvm, pyenv, goenv, etc

The problem might be that their shims aren't in your PATH. To work around this sort of problem I run emacs from a wrapper script that ensures the shims are loaded in my PATH.

Running prettier is slow

The scripts by default call npx prettier with some arguments. If you call these scripts from a directory where there's a node_modules/ directory with prettier and plugins, if necessary, installed, then npx should be fast enough.

The solution, therefore, seems to be to say yarn add --dev prettier (or npm install --dev prettier) in the right place.

(This seems to work for me, but it is admittedly still uncomfortably cargoculty. There should be a more solid basis for this answer.)

problems running black

The solution seems to be to run pip install black pipx somewhere.

Development

Wishlist

  • Generalize this beyond emacs
  • Add support for more programming languages and file formats
  • Clean up shell script code
  • Be better at "just working"