Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .mise/tasks/fmt/_default
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
#MISE description="Run all formatters."
#MISE depends=[{ task = "fmt:*", optional = true }]
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats shell scripts."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/bash.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats Go source files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/go.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats JavaScript files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/js.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats Jsonnet files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/jsonnet.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/prettier
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats YAML, JSON, Markdown, and TypeScript files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/prettier.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/protobuf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats Protobuf files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/protobuf.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/terraform
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats Terraform files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/terraform.sh"
9 changes: 9 additions & 0 deletions .mise/tasks/fmt/toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
#MISE description="Formats TOML files."

set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
SHELL_DIR="$DIR/../../../shell"

exec "$SHELL_DIR/run-formatter.sh" "$SHELL_DIR/linters/toml.sh"
36 changes: 36 additions & 0 deletions docs/linters.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,39 @@ To add a linter place the linter shell script in `scripts/linters/<lintername>.s
The linter will be discovered when globbing `.sh` files run with the built-in
linters. Follow the conventions of the existing linter shell scripts when creating
the new linter.

## Running formatters via mise

`mise run fmt` is the mise-native equivalent of `make fmt`. `mise run fmt:<name>`
(e.g. `mise run fmt:go`, `mise run fmt:bash`) runs a single formatter. Run
`mise tasks ls` to see the full list of `fmt:*` tasks.

Unlike `make fmt`, which auto-discovers `scripts/linters/*.sh` by globbing,
`mise run fmt` only runs formatters registered as `fmt:<name>` mise tasks. A
project-specific linter (added as above) needs its own `fmt:<name>` task to be
picked up by `mise run fmt`, via either:

1. A file-based task at `.mise/tasks/fmt/<name>` that delegates to devbase's
shared runner via `scripts/shell-wrapper.sh` (the same wrapper `make fmt`
itself uses to reach devbase's vendored shell scripts):

```bash
#!/usr/bin/env bash
#MISE description="Formats <your language> files."

set -euo pipefail

exec "$MISE_PROJECT_ROOT/scripts/shell-wrapper.sh" run-formatter.sh "$MISE_PROJECT_ROOT/scripts/linters/<name>.sh"
```

2. A plain TOML task in your own `mise.toml`, with no dependency on the
`extensions`/`formatter()` convention at all:

```toml
[tasks."fmt:<name>"]
description = "Formats <your language> files."
run = "your-formatter-command --write ."
```

Both forms are discovered identically by `mise run fmt`, since mise treats
file-based and TOML-defined tasks the same way for task lookup.
43 changes: 1 addition & 42 deletions shell/fmt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,10 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"

# shellcheck source=./lib/bootstrap.sh
source "$DIR/lib/bootstrap.sh"
# shellcheck source=./lib/github.sh
source "$DIR/lib/github.sh"
# shellcheck source=./lib/logging.sh
source "$DIR/lib/logging.sh"
# shellcheck source=./lib/mise.sh
source "$DIR/lib/mise.sh"
# shellcheck source=./lib/shell.sh
source "$DIR/lib/shell.sh"
# shellcheck source=./lib/version.sh
source "$DIR/lib/version.sh"

# add extra (per project) linters
linters=("$DIR/linters"/*.sh)
Expand All @@ -32,42 +26,7 @@ info "Running formatters"

started_at="$(get_time_ms)"
for linterScript in "${linters[@]}"; do

# We use a sub-shell to prevent inheriting
# the changes to functions/variables to the parent
# (this) script
(
# Note: These are modified by the source'd language file
# extensions are the extensions this linter should run on
extensions=()

# Why: Dynamic
# shellcheck disable=SC1090
source "$linterScript"

matched=false
if [[ "$(find_files_with_extensions "${extensions[@]}" | wc -l | tr -d ' ')" -gt 0 ]]; then
matched=true
fi

if [[ $matched == "false" ]]; then
exit 0
fi

# Note: extensions is set by the linter.
# Why: We're OK with declaring and assigning.
# shellcheck disable=SC2155,SC2001
extensionsString=$(sed 's/ /,./g' <<<"${extensions[*]}" | sed 's/^/./')

# show is used by run_command as metadata to be shown along with the command name
show=$extensionsString

# Set by the language file
if ! formatter; then
error "Formatter failed to run"
exit 1
fi
)
"$DIR/run-formatter.sh" "$linterScript" || exit 1
done
finished_at="$(get_time_ms)"
duration="$((finished_at - started_at))"
Expand Down
53 changes: 53 additions & 0 deletions shell/run-formatter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Runs the formatter() function defined by a single linter script (see
# shell/linters/*.sh) against the files it declares via `extensions`.
#
# Used by shell/fmt.sh (in series) and by the per-formatter mise tasks
# under .mise/tasks/fmt/ (which mise may run in parallel).
set -e -o pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"

# shellcheck source=./lib/bootstrap.sh
source "$DIR/lib/bootstrap.sh"
# shellcheck source=./lib/github.sh
source "$DIR/lib/github.sh"
# shellcheck source=./lib/logging.sh
source "$DIR/lib/logging.sh"
# shellcheck source=./lib/mise.sh
source "$DIR/lib/mise.sh"
# shellcheck source=./lib/shell.sh
source "$DIR/lib/shell.sh"
# shellcheck source=./lib/version.sh
source "$DIR/lib/version.sh"

linterScript="${1:-}"
if [[ -z $linterScript ]]; then
fatal "Usage: run-formatter.sh <path-to-linter-script>"
fi

# Note: extensions is set by the linter script sourced below.
extensions=()

# Why: Dynamic
# shellcheck disable=SC1090
source "$linterScript"

if [[ "$(find_files_with_extensions "${extensions[@]}" | wc -l | tr -d ' ')" -eq 0 ]]; then
exit 0
fi

# Note: extensions is set by the linter.
extensionsPrefixed=("${extensions[@]/#/.}")
IFS=,
extensionsString="${extensionsPrefixed[*]}"
unset IFS

# show is used by run_command as metadata to be shown along with the command name
show=$extensionsString

# Set by the linter script.
if ! formatter; then
error "Formatter failed to run"
exit 1
fi
Loading