[Fix] cleanup

This commit is contained in:
coja
2026-08-13 01:11:41 +02:00
parent f62cb40499
commit 86726cddce
312 changed files with 12274 additions and 10772 deletions
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/env python3
"""PostToolUse hook: format an edited file with the right formatter.
Reads the hook JSON from stdin, extracts the edited file path, and runs a
language-appropriate formatter -- but, to avoid imposing a style on a project
that never asked for it, opinionated formatters (stylua, ruff, prettier, taplo)
only run when the project opts in via a config file discoverable by walking up
from the edited file. Canonical single-style toolchains run on sight: gofmt and
rustfmt on their go.mod / Cargo.toml marker; fish_indent and shfmt whenever the
tool itself is installed (shell and fish have one de-facto style, no config).
Best-effort: always exits 0 so a format hiccup never blocks an edit. jq is not
guaranteed on the host, hence python for the stdin JSON parse.
"""
import json
import os
import shutil
import subprocess
import sys
def find_up(start, names):
"""Nearest ancestor dir (incl. the file's own) containing any of `names`."""
d = os.path.dirname(os.path.abspath(start))
while True:
if any(os.path.exists(os.path.join(d, n)) for n in names):
return d
parent = os.path.dirname(d)
if parent == d:
return None
d = parent
def has_toml_section(start, filename, section):
"""True if the nearest ancestor `filename` contains `section`."""
d = find_up(start, [filename])
if not d:
return False
try:
with open(os.path.join(d, filename), errors="ignore") as fh:
return section in fh.read()
except Exception:
return False
def stylua_cmd(path):
exe = os.path.expanduser("~/.local/share/nvim/mason/bin/stylua")
if not os.access(exe, os.X_OK):
exe = shutil.which("stylua")
if exe and find_up(path, [".stylua.toml", "stylua.toml"]):
return [exe, path]
return None
def ruff_cmd(path):
exe = shutil.which("ruff")
if exe and (find_up(path, ["ruff.toml", ".ruff.toml"])
or has_toml_section(path, "pyproject.toml", "[tool.ruff")):
return [exe, "format", path]
return None
_PRETTIER_CFGS = [
".prettierrc", ".prettierrc.json", ".prettierrc.yaml", ".prettierrc.yml",
".prettierrc.json5", ".prettierrc.js", ".prettierrc.cjs", ".prettierrc.mjs",
".prettierrc.toml", "prettier.config.js", "prettier.config.cjs",
"prettier.config.mjs",
]
def prettier_cmd(path):
exe = shutil.which("prettier")
if exe and find_up(path, _PRETTIER_CFGS):
return [exe, "--write", path]
return None
def gofmt_cmd(path):
exe = shutil.which("gofmt")
if exe and find_up(path, ["go.mod"]): # one canonical style
return [exe, "-w", path]
return None
def rustfmt_cmd(path):
exe = shutil.which("rustfmt")
if exe and find_up(path, ["Cargo.toml", "rustfmt.toml", ".rustfmt.toml"]):
return [exe, path]
return None
def fish_cmd(path):
exe = shutil.which("fish_indent") # ships with fish, one canonical style
return [exe, "-w", path] if exe else None
def shfmt_cmd(path):
exe = shutil.which("shfmt") # de-facto shell formatter, sane defaults
return [exe, "-w", path] if exe else None
def taplo_cmd(path):
exe = shutil.which("taplo")
# opt-in: TOML reflow/align is intrusive, so only where the project asked.
if exe and find_up(path, ["taplo.toml", ".taplo.toml"]):
return [exe, "format", path]
return None
HANDLERS = {
".lua": stylua_cmd,
".py": ruff_cmd,
".js": prettier_cmd, ".jsx": prettier_cmd, ".mjs": prettier_cmd,
".cjs": prettier_cmd, ".ts": prettier_cmd, ".tsx": prettier_cmd,
".css": prettier_cmd, ".scss": prettier_cmd, ".less": prettier_cmd,
".html": prettier_cmd, ".vue": prettier_cmd, ".json": prettier_cmd,
".md": prettier_cmd, ".yaml": prettier_cmd, ".yml": prettier_cmd,
".go": gofmt_cmd,
".rs": rustfmt_cmd,
".fish": fish_cmd,
".sh": shfmt_cmd, ".bash": shfmt_cmd,
".toml": taplo_cmd,
}
def main():
try:
data = json.load(sys.stdin)
except Exception:
return
ti = data.get("tool_input") or {}
tr = data.get("tool_response") or {}
path = ti.get("file_path") or tr.get("filePath") or ""
if not path or not os.path.isfile(path):
return
handler = HANDLERS.get(os.path.splitext(path)[1].lower())
if not handler:
return
cmd = handler(path)
if not cmd:
return
try:
subprocess.run(cmd, timeout=15, capture_output=True)
except Exception:
pass
if __name__ == "__main__":
main()