Compare commits
14 Commits
2eb0d7b9b0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a033dfbfee | ||
|
|
44b129951e | ||
|
|
d1e6e953d1 | ||
|
|
bbcd4449f2 | ||
|
|
304e5d2f87 | ||
|
|
7a6fe0925d | ||
|
|
f8046c6d1d | ||
|
|
0c4f4f91f9 | ||
|
|
965295ad21 | ||
|
|
863f89f350 | ||
|
|
4e9affa44f | ||
|
|
1ed6175656 | ||
|
|
ecf60a5f2f | ||
|
|
969f6edc39 |
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Michael Wolf
|
Copyright (c) 2020, 2021, 2022, 2023 Michael Wolf
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
91
README.md
91
README.md
@@ -2,19 +2,62 @@ would-reformat - automatic reformatting for emacs without being annoying
|
|||||||
|
|
||||||
# Motivation
|
# 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
|
||||||
|
|
||||||
|
<!-- please keep this list sorted alphabetically -->
|
||||||
|
|
||||||
|
- css
|
||||||
|
- dart
|
||||||
|
- go
|
||||||
|
- html
|
||||||
|
- javascript
|
||||||
|
- jsx
|
||||||
|
- php
|
||||||
|
- python
|
||||||
|
- scss
|
||||||
|
- sh
|
||||||
|
- tsx
|
||||||
|
- typescript
|
||||||
|
- vue
|
||||||
|
|
||||||
|
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
|
# Installation
|
||||||
|
|
||||||
- Change to the directory where you would want to use **would-reformat**:
|
- Change to the directory where you want to use **would-reformat**:
|
||||||
`$ cd ~/devel/my-project`
|
`you@host:~ $ cd ~/devel/my-project`
|
||||||
- From that directory, call the script `install.sh` in the directory where
|
- From that directory, call the script `install.sh` in the directory where
|
||||||
you have **would-reformat** checked out:
|
you have **would-reformat** checked out:
|
||||||
`you@host:~/devel/my-project $ ~/src/would-reformat/install.sh`
|
`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:
|
This will do the following:
|
||||||
|
|
||||||
- create the directory `~/devel/my-project/bin` if it does not exist
|
- create the directory `~/devel/my-project/bin` if it does not exist
|
||||||
- create `~/devel/my-project/_reformat-common.sh`,
|
- create `~/devel/my-project/bin/_reformat-common.sh`,
|
||||||
`~/devel/my-project/do-reformat.sh`, and
|
`~/devel/my-project/bin/do-reformat.sh`, and
|
||||||
`~/devel/my-project/bin/would-reformat.sh` as symlinks to files with
|
`~/devel/my-project/bin/would-reformat.sh` as symlinks to files with
|
||||||
the same names in `~/src/would-reformat`.
|
the same names in `~/src/would-reformat`.
|
||||||
- create `~/devel/my-project/.dir-locals.el` as a symlink to the file
|
- create `~/devel/my-project/.dir-locals.el` as a symlink to the file
|
||||||
@@ -27,12 +70,50 @@ will break, so don't do that. If you rename the checkout, the symlinks will bre
|
|||||||
The directory `bin` with respect to `my-project` however is hardcoded
|
The directory `bin` with respect to `my-project` however is hardcoded
|
||||||
(enhancements here are welcome).
|
(enhancements here are welcome).
|
||||||
|
|
||||||
The script `install.sh` favors conservatism over being clever: for example,
|
The script `install.sh` favors conservatism over cleverness: for example,
|
||||||
if it finds the file `~/devel/my-project/bin/do-reformat.sh` then it
|
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`.
|
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
|
If it is not, then it just prints a warning rather than attempting to correct
|
||||||
the situation.
|
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
|
# Development
|
||||||
|
|
||||||
|
# Wishlist
|
||||||
|
|
||||||
|
- Generalize this beyond emacs
|
||||||
|
- In emacs, provide a minor mode or something to use instead of
|
||||||
|
`.dir-locals.el`, which I've always found to be very fragile
|
||||||
|
- Add support for more programming languages and file formats
|
||||||
|
- Clean up shell script code
|
||||||
|
- Be better at "just working"
|
||||||
|
- Make it easy to add "private" and alternate formatters
|
||||||
|
|||||||
41
_reformat-common.bash
Normal file
41
_reformat-common.bash
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
function root() {
|
||||||
|
echo "$(git rev-parse --show-toplevel)"
|
||||||
|
}
|
||||||
|
|
||||||
|
function sniff_file_type() {
|
||||||
|
ff=$1
|
||||||
|
shift
|
||||||
|
file_type=
|
||||||
|
|
||||||
|
if [[ $ff == *.py ]]; then
|
||||||
|
file_type="python"
|
||||||
|
elif [[ $ff == *.js ]]; then
|
||||||
|
file_type="javascript"
|
||||||
|
elif [[ $ff == *.ts ]]; then
|
||||||
|
file_type="typescript"
|
||||||
|
elif [[ $ff == *.vue ]]; then
|
||||||
|
file_type="vue"
|
||||||
|
elif [[ $ff == *.css ]]; then
|
||||||
|
file_type="css"
|
||||||
|
elif [[ $ff == *.php ]]; then
|
||||||
|
file_type="php"
|
||||||
|
elif [[ $ff == *.html ]]; then
|
||||||
|
file_type="html"
|
||||||
|
elif [[ $ff == *.jsx ]]; then
|
||||||
|
file_type="jsx"
|
||||||
|
elif [[ $ff == *.tsx ]]; then
|
||||||
|
file_type="tsx"
|
||||||
|
elif [[ $ff == *.css ]] ; then
|
||||||
|
file_type="css"
|
||||||
|
elif [[ $ff == *.scss ]] ; then
|
||||||
|
file_type="scss"
|
||||||
|
elif [[ $ff = *.sh ]]; then
|
||||||
|
file_type="sh"
|
||||||
|
elif [[ $ff = *.go ]] ; then
|
||||||
|
file_type="golang"
|
||||||
|
elif [[ $ff = *.dart ]] ; then
|
||||||
|
file_type="dart"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $file_type
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
function sniff_file_type() {
|
|
||||||
ff=$1
|
|
||||||
shift
|
|
||||||
file_type=
|
|
||||||
|
|
||||||
if [[ $ff == *.py ]]; then
|
|
||||||
file_type="python"
|
|
||||||
elif [[ $ff == *.js ]]; then
|
|
||||||
file_type="javascript"
|
|
||||||
elif [[ $ff == *.ts ]]; then
|
|
||||||
file_type="typescript"
|
|
||||||
elif [[ $ff == *.vue ]]; then
|
|
||||||
file_type="vue"
|
|
||||||
elif [[ $ff == *.css ]]; then
|
|
||||||
file_type="css"
|
|
||||||
elif [[ $ff == *.php ]]; then
|
|
||||||
file_type="php"
|
|
||||||
elif [[ $ff == *.html ]]; then
|
|
||||||
file_type="html"
|
|
||||||
elif [[ $ff == *.jsx ]]; then
|
|
||||||
file_type="jsx"
|
|
||||||
elif [[ $ff == *.tsx ]]; then
|
|
||||||
file_type="tsx"
|
|
||||||
elif [[ $ff == *.css ]] ; then
|
|
||||||
file_type="css"
|
|
||||||
elif [[ $ff == *.scss ]] ; then
|
|
||||||
file_type="scss"
|
|
||||||
elif [[ $ff = *.sh ]]; then
|
|
||||||
file_type="sh"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $file_type
|
|
||||||
}
|
|
||||||
1
_reformat-common.sh
Symbolic link
1
_reformat-common.sh
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
_reformat-common.bash
|
||||||
@@ -26,7 +26,15 @@ if [[ $file_type == "javascript" || \
|
|||||||
retval="$?"
|
retval="$?"
|
||||||
success_retval=0
|
success_retval=0
|
||||||
elif [[ $file_type == "python" ]]; then
|
elif [[ $file_type == "python" ]]; then
|
||||||
out=$(pipx run black $file 2>/dev/null && pipx run isort $file 2>/dev/null)
|
out=$(pipx run black $file 2>/dev/null && pipx run isort --profile black $file 2>/dev/null)
|
||||||
|
retval="$?"
|
||||||
|
success_retval=0
|
||||||
|
elif [[ $file_type == "golang" ]] ; then
|
||||||
|
out=$(gofmt -w "$file" 2>/dev/null)
|
||||||
|
retval="$?"
|
||||||
|
success_retval=0
|
||||||
|
elif [[ $file_type == "dart" ]] ; then
|
||||||
|
out=$(dart format $file)
|
||||||
retval="$?"
|
retval="$?"
|
||||||
success_retval=0
|
success_retval=0
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ if [[ $file_type = "javascript" || \
|
|||||||
syntax_error_retval=2
|
syntax_error_retval=2
|
||||||
elif [[ $file_type == "python" ]]; then
|
elif [[ $file_type == "python" ]]; then
|
||||||
|
|
||||||
out=$(pipx run isort --check $file 2>/dev/null)
|
out=$(pipx run isort --profile black --check $file 2>/dev/null)
|
||||||
isort_retval="$?"
|
isort_retval="$?"
|
||||||
|
|
||||||
success_retval=0
|
success_retval=0
|
||||||
@@ -42,6 +42,31 @@ elif [[ $file_type == "python" ]]; then
|
|||||||
else
|
else
|
||||||
retval="$isort_retval"
|
retval="$isort_retval"
|
||||||
fi
|
fi
|
||||||
|
elif [[ $file_type == "golang" ]] ; then
|
||||||
|
success_retval=0
|
||||||
|
would_reformat_retval=1
|
||||||
|
syntax_error_retval=2
|
||||||
|
|
||||||
|
out=$(gofmt -l $file)
|
||||||
|
exitval="$?"
|
||||||
|
|
||||||
|
if [[ x"$exitval" = x"$syntax_error_retval" ]] ; then
|
||||||
|
retval="$exitval"
|
||||||
|
elif [[ x"$out" = x"$file" ]] ; then
|
||||||
|
retval="$would_reformat_retval"
|
||||||
|
else
|
||||||
|
# success
|
||||||
|
retval="$exitval"
|
||||||
|
fi
|
||||||
|
elif [[ $file_type == "dart" ]] ; then
|
||||||
|
success_retval=0
|
||||||
|
would_reformat_retval=1
|
||||||
|
# probably others too :(
|
||||||
|
syntax_error_retval=65
|
||||||
|
|
||||||
|
out=$(dart format -o none --set-exit-if-changed $file)
|
||||||
|
exitval="$?"
|
||||||
|
retval="$exitval"
|
||||||
else
|
else
|
||||||
echo -n "ignoring"
|
echo -n "ignoring"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user