Compare commits

..

10 Commits

Author SHA1 Message Date
Michael Wolf
c4cac19501 Document situation to be signaled
Lame formatters cannot distinguish between when there are syntax errors and
when code should be reformatted.
2024-10-30 21:59:40 -06:00
Michael Wolf
44fd5a350f Improve documentation slightly 2024-10-30 21:59:10 -06:00
Michael Wolf
e8771f1156 Add shfmt.sh 2024-04-03 11:29:32 -06:00
Michael Wolf
7c503cecf7 Try to do a few things
FIXME: do them correctly; squash and reword this travesty of a commit.
2024-04-03 11:26:50 -06:00
Michael Wolf
1957698fc4 Update years in license 2024-04-03 11:26:36 -06:00
Michael Wolf
970a92def9 Update some docs 2024-04-03 11:26:30 -06:00
Michael Wolf
d16dfaff1f Add doc re new formatters 2024-04-03 11:26:15 -06:00
Michael Wolf
b54ee4a69e Note an obvious error 2024-03-13 09:49:38 -06:00
Michael Wolf
897a91b350 Bake in support for rustfmt 2023-12-07 09:53:21 -06:00
Michael Wolf
5c987ae777 Fix gofmt.sh 2023-09-30 20:59:19 -06:00
12 changed files with 255 additions and 31 deletions

View File

@@ -40,19 +40,19 @@ exit 0
[here](./examples/custom-sniffer).)
Now, if you run this script against a file that ends in `.pl` or `.ts`,
`would-reformat` will not treat the file as perl or typescript as usual, but
instead as prolog or a qt-translation file. But if you run this script
against a file that ends in `.py` then it'll continue to be treated as python
as usual.
`would-reformat` will not treat the file as perl or typescript, which is what
happens by default, but instead as prolog or a qt-translation file. But if
you run this script against a file that ends in `.py` then it'll continue to
be treated as python as usual.
You can perform arbitrarily sophisticated checks here. They're not limited to
file names or extensions. You can take paths into account. You can can even
take files' contents into account. But do keep in mind that this program
will be run often. If it's slow you'll be frustrated by it.
Don't forget that this program can be written in something other than shell,
in case that's easier for you or if performance is a serious concern. It
doesn't actually need to be a "script".
This program can be written in something other than shell. This might make
implementation easier, and it might be worthwhile if performance is a serious
concern. It doesn't actually need to be a "script".
Finally, keep in mind that if `would-reformat`'s defaults work for you, there
is no need to have this file at all.
@@ -67,7 +67,8 @@ include the `/` character. `would-reformat` doesn't care if you use
uppercase, but some case-preserving filesystems make things difficult.
It must not output `custom-sniffer`. If there is a hitherto unknown
programming language named "custom sniffer" you'll have to output something else.
programming language named "custom sniffer" you'll have to output something
else.
## Return values
@@ -158,6 +159,8 @@ As output, this script should emit whatever the programs it calls emit.
- 0: file wouldn't be reformatted
- 1: file would be reformatted
- 2: file has at least one syntax error
- 3: file would be reformatted or it has at least one syntax error but we
cannot distinguish which
- 252: Unexpected return value from the tool; that is, the value of `$?` is
unexpected and thus unhandled
- 253: Unexpected output from the tool; that is, the output emitted by the
@@ -168,15 +171,15 @@ As output, this script should emit whatever the programs it calls emit.
- 255: error internal to the script in question
(FIXME: Unsurprisingly, `gofmt` is the only tool I've tested so far that gets
this right. That a file should be reformatted isn't an exceptional condition,
so there's no good reason to signal failure here.
this right. It isn't an exceptional condition when a file should be
reformatted, so there's no good reason to signal failure here.
Even less unsurprisingly, Laravel pint gets it worse than all the others I
checked; it doesn't distinguish misformatted files from files with actual
syntax errors.
checked; it doesn't distinguish files that need to be reformatted from files
with actual syntax errors.
Anyway, `gofmt` is the obviously the model to follow. So we should
probably drop `1`.)
If possible, then, we should return 1 or 2 when relevant. When they can't be
distinguished, return 3.)
### in `do_format` mode

View File

@@ -8,8 +8,8 @@ following tools installed:
- [shfmt](https://github.com/mvdan/sh)
In general, code should pass shellcheck without warnings, be formatted with
shfmt (please use it with `-i 4`), and come with new tests and pass them when
relevant.
shfmt (please use it with `-i 4`), and when relevant come with new tests and
pass them.
If any of this causes you trouble, don't worry. Please submit your pull
request anyway and we can work on getting it up to snuff.
@@ -24,11 +24,13 @@ request anyway and we can work on getting it up to snuff.
- Be easy to configure.
- Be clearly documented. Remember that many programmers are working in
high-stress situations. Documentation that is incomplete, unclear, or cute
will make things even worse for them. Use English correctly and, to the
extent possible, unambiguously.
makes things even worse for them. Use English correctly and, to the extent
possible, unambiguously.
## Non-goals
- We don't want to do anything with warnings etc that aren't specifically
formatting-related
# Wishlist
@@ -45,13 +47,17 @@ request anyway and we can work on getting it up to snuff.
probably be more confusing than helpful but I'm not wedded to this
conclusion.
- Write a doctor command to identify potential issues (you'd probably run it
similarly to how you run the install script, but `s/install/doctor`).
similarly to how you run the install script, but `s/install/doctor/`).
- Create a nix setup that includes all the tools as fallbacks
- Cache file type sniffing results? How?
# Problems
- It would probably be better if we wrote reformatted code to temp files and
atomically renamed them. This might mean that the tool-specific programs
should emit diffs rather than working silently as they currently do.
should emit diffs rather than working silently as they currently do. The
rationale is that this makes it a lot easier to atomically apply two or more
fixers.
- It probably doesn't work on Windows as-is.
- There are probably some Linuxisms and maybe even some recentbashisms.
- It doesn't work with tramp.

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020, 2021, 2022, 2023 Michael Wolf
Copyright (c) 2020, 2021, 2022, 2023, 2024 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
NEW-FORMATTERS.md Normal file
View File

@@ -0,0 +1,91 @@
## available environment variables
- `PROJECT_ROOT` is the root directory of your project, the one
with files that need to be reformatted. Currently (as of 2023-09) this is
just the output of `git rev-parse --show-toplevel` but it may be improved.
- `WF_ROOT` is the root directory of the `would-format` checkout
file checking and sniffing
## file type sniffing
You can override a file type by creating an executable in
`$WOULD_FORMAT_PROJECT_ROOT/.would-format/sniffer`. This is typically a shell
script, but it doesn't have to be. It takes one argument, the full path of
the file to be checked.
This file should print the type of file it should be treated as. If the
script has no opinion on the matter, it should print nothing and exit. Here
is an example:
```shell-script
#!/usr/bin/env bash
file="$1"
if [[ $file == *.pl ]] ; then
# the default is that .pl corresponds to perl, but not here!
echo -n "prolog"
fi
if [[ $file == *.ts ]] ; then
# qt translations, who knew
echo -n "qt-translation"
fi
# We're fine with the defaults for other types of files so we don't
# print anything else.
exit 0
```
Return values:
- 0: success
- 254: file can't be read due to permissions, etc ("etc" is as of
2023-Q3 broad in scope; it could include trying and failing to read a file
on a NFS mount)
- 255: some sort of internal error
## return value normalization for formatters
In general, low-numbered codes are related to the code to be analyzed
or reformatted and high-numbered codes have to do with problems with these
scripts themselves.
### In `would_format` mode
`would-format.sh` interprets return values to mean the following:
FIXME: Unsurprisingly, `gofmt` gets this right, even if none of the other
tools does. Drop `1`.
- 0: file wouldn't be reformatted
- 1: file would be reformatted
- 2: file has at least one syntax error
- 3: file would be reformatted or it has at least one syntax error but we
cannot distinguish which
- 252: Unexpected return value from the tool; that is, the value of `$?` is
unexpected and thus unhandled
- 253: Unexpected output from the tool; that is, the output emitted by the
tool is unexpected and thus unhandled
- 254: file can't be read due to permissions, etc ("etc" is as of
2023-Q3 broad in scope; it could include trying and failing to read a file
on a NFS mount)
- 255: error internal to the script in question
# in `do_format` mode
`do-format.sh` interprets return values to mean the following:
- 0: file was successfully reformatted
- 1: file was not successfully reformatted, presumably due to a syntax error
- 254: file can't be rewritten due to permissions, etc ("etc" is as of
2023-Q3 broad in scope; it could include trying and failing to read a file
on a NFS mount)
- 255: error internal to the script in question

View File

@@ -1,4 +1,4 @@
would-reformat - automatic reformatting for emacs without being annoying
would-reformat - automatic reformatting for emacs (and maybe other editors) without being annoying
# Motivation
@@ -38,9 +38,13 @@ saving a file and to run `do-reformat.sh` when you hit `<F1>`.
- typescript
- vue
Out of the box, python uses `isort` and `black`, go uses `gofmt`, and dart
uses `dart format`. The rest use `prettier`. Adding new programming
languages is easy, assuming they have a formatter with a dry run mode.
Out of the box, for python we use `isort` and `black`, for go we use `gofmt`,
for dart we use `dart format`, for rust we use `rustfmt`, and for everything
else we use `prettier`.
Adding suuport for other programming languages is easy, assuming they have a
formatter with a dry run mode. And even if they don't it shouldn't be that
bad.
# Installation

View File

@@ -1,3 +1,11 @@
function log () {
msg=$@
if [[ ! -z "${LOG_TO+}" ]] ; then
echo "$msg" >> $LOG_TO
fi
}
function get_os() {
un=$(uname)
@@ -139,14 +147,17 @@ function sniff_file_type() {
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
elif [[ $ff = *.dart ]]; then
file_type="dart"
elif [[ $ff = *.sh ]]; then
# .sh isn't enough; we'll need other extns
file_type="shell"
elif [[ $ff = *.pl ]]; then
file_type="perl"
elif [[ $ff = *.rs ]] ; then
file_type="rust"
fi
echo $file_type
@@ -184,15 +195,18 @@ function choose_wrapper() {
$file_type = "jsx" ||
$file_type = "tsx" ||
$file_type == "css" ||
$file_type == "scss" ||
$file_type = "sh" ]]; then
$file_type == "scss" ]]; then
out="$WF_ROOT"/./prettier.sh
elif [[ $file_type == "python" ]]; then
out="$WF_ROOT"/./isort-and-black.sh
elif [[ $file_type == "golang" ]]; then
out="$WF_ROOT"/./gofmt.sh
elif [[ $file_type == "rust" ]] ; then
out="$WF_ROOT"/./rustfmt.sh
elif [[ $file_type == "dart" ]]; then
out="$WF_ROOT"/./dart_format.sh
elif [[ $file_type == "shell" ]] ; then
out="$WF_ROOT"/./shfmt.sh
else
out="$WF_ROOT"/./default.sh
fi

View File

@@ -30,6 +30,7 @@ if [[ "$WOULD_REFORMAT" = "would_reformat" ]]; then
fi
if [[ "$WOULD_REFORMAT" = "do_reformat" ]]; then
# FIXME this is obviously obviously obviously wrong
out=$(npx prettier --write "$file" 2>&1 >/dev/null)
retval="$?"

View File

@@ -7,6 +7,8 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$DIR/_reformat-common.bash"
#export LOG_DEST="$LOG_TO"
file="$1"
PROJECT_ROOT=$(project_root "$file")

View File

@@ -37,7 +37,7 @@ if [[ "$WOULD_REFORMAT" = "would_reformat" ]]; then
fi
if [[ "$WOULD_REFORMAT" = "do_reformat" ]]; then
out=$(npx prettier --write "$file" 2>&1 >/dev/null)
out=$(gofmt -w "$file" 2>&1 >/dev/null)
retval="$?"
echo "$out"

50
rustfmt.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
set -uo pipefail
IFS=$'\n\t'
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$DIR/_reformat-common.bash"
log "in rustfmt.sh"
set -e
file="$1"
log what
pushd "$(dirname "$file")" 2>&1
if [[ "$WOULD_REFORMAT" = "would_reformat" ]]; then
log beavis
set +e
out=$(rustfmt --check "$file" 2>&1 >/dev/null)
retval="$?"
set -e
log got back retval $retval
exit "$retval"
fi
if [[ "$WOULD_REFORMAT" = "do_reformat" ]]; then
log in do reformat mode
out=$(rustfmt "$file" 2>&1 >/dev/null)
retval="$?"
echo "$out"
log $out
exit "$retval"
fi
log are we here now
exit 255

39
shfmt.sh Normal file
View File

@@ -0,0 +1,39 @@
set -uo pipefail
IFS=$'\n\t'
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$DIR/_reformat-common.bash"
set -e
file="$1"
pushd "$(dirname "$file")" 2>&1
if [[ "$WOULD_REFORMAT" = "would_reformat" ]]; then
# probably others too :(
syntax_error_retval=1
set +e
out=$(dart format -o none --set-exit-if-changed "$file"
retval="$?"
set -e
if [[ "$retval" = "$syntax_error_retval" ]]; then
retval=2
fi
exit "$retval"
fi
if [[ "$WOULD_REFORMAT" = "do_reformat" ]]; then
out=$(shfmt -w "$file" 2>&1 > /dev/null)
retval="$?"
echo "$out"
exit "$retval"
fi
exit 255

View File

@@ -10,6 +10,12 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# wrflog before sourcing common funcs, I think i am in dir: $(pwd)
source "$DIR/_reformat-common.bash"
#export LOG_DEST="$LOG_TO"
log "is this thing on"
log i think it is on
file="$1"
PROJECT_ROOT=$(project_root "$file")
export PROJECT_ROOT="$PROJECT_ROOT"
@@ -24,11 +30,19 @@ export WOULD_REFORMAT=would_reformat
wrapper=$(choose_wrapper "$file_type")
log wrapper is "$wrapper"
set +e
echo asdf
out=$("$wrapper" "$file" 2>&1 >/dev/null)
retval="$?"
echo fdsa
set -e
echo retval "$retval"
success_retval=0
would_reformat_retval=1
syntax_error_retval=2