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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
- Change to the directory where you would want to use **would-reformat**:
|
||||
`$ cd ~/devel/my-project`
|
||||
- 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/_reformat-common.sh`,
|
||||
`~/devel/my-project/do-reformat.sh`, and
|
||||
- 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
|
||||
@@ -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
|
||||
(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
|
||||
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
|
||||
- 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="$?"
|
||||
success_retval=0
|
||||
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="$?"
|
||||
success_retval=0
|
||||
else
|
||||
|
||||
@@ -29,7 +29,7 @@ if [[ $file_type = "javascript" || \
|
||||
syntax_error_retval=2
|
||||
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="$?"
|
||||
|
||||
success_retval=0
|
||||
@@ -42,6 +42,31 @@ elif [[ $file_type == "python" ]]; then
|
||||
else
|
||||
retval="$isort_retval"
|
||||
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
|
||||
echo -n "ignoring"
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user