feat: support 'prettierd' in autofmt
prettierd is a daemon for prettier, allowing lower latency formats see https://github.com/fsouza/prettierd
This commit is contained in:
parent
0a5d9bfc17
commit
1052a1ccc3
2 changed files with 55 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env node
|
||||
// autofmt v1 by paper clover
|
||||
// autofmt v2 by paper clover
|
||||
// https://paperclover.dev/nix/config/src/branch/main/packages/autofmt/autofmt.js
|
||||
//
|
||||
// Different codebases use different formatters. Autofmt looks for project
|
||||
|
@ -25,6 +25,10 @@
|
|||
// }
|
||||
// },
|
||||
//
|
||||
// CHANGELOG
|
||||
// v2: added 'prettierd' as a supported formatter option.
|
||||
// v1: initial release
|
||||
//
|
||||
// @ts-nocheck
|
||||
|
||||
// -- definitions --
|
||||
|
@ -72,6 +76,15 @@ const formatters = {
|
|||
cmd: ["deno", "fmt", "--", "$files"],
|
||||
stdin: (file) => ["deno", "fmt", "--ext", path.extname(file).slice(1), "-"],
|
||||
},
|
||||
prettierd: {
|
||||
// keep in mind that pretterd never exits.
|
||||
// https://github.com/fsouza/prettierd/issues/645
|
||||
languages: ["javascript", "markdown", "json", "yaml", "mdx", "html", "css"],
|
||||
mustMatchFile: true,
|
||||
files: { "node_modules/.bin/prettier": () => which("prettierd") },
|
||||
cmd: null,
|
||||
stdin: (file) => ["prettierd", file],
|
||||
},
|
||||
prettier: {
|
||||
languages: ["javascript", "markdown", "json", "yaml", "mdx", "html", "css"],
|
||||
files: ["node_modules/.bin/prettier"],
|
||||
|
@ -91,7 +104,7 @@ const formatters = {
|
|||
"nixfmt-rfc-style": {
|
||||
languages: ["nix"],
|
||||
files: {
|
||||
"flake.nix": (contents) => contents.includes("nixfmt"),
|
||||
"flake.nix": ({ text }) => text.includes("nixfmt"),
|
||||
},
|
||||
cmd: ["nixfmt", "--", "$files"],
|
||||
stdin: (file) => ["nixfmt", `--filename=${file}`],
|
||||
|
@ -99,7 +112,7 @@ const formatters = {
|
|||
alejandra: {
|
||||
languages: ["nix"],
|
||||
files: {
|
||||
"flake.nix": (contents) => contents.includes("alejandra"),
|
||||
"flake.nix": ({ text }) => text.includes("alejandra"),
|
||||
},
|
||||
cmd: ["alejandra", "--", "$files"],
|
||||
stdin: () => ["alejandra"],
|
||||
|
@ -498,24 +511,31 @@ function pickFormatter(file) {
|
|||
return walkUp(dir, (x) => {
|
||||
const children = readDir(x);
|
||||
for (const fmt of order) {
|
||||
if (formatters[fmt][stdio ? "stdin" : "cmd"] == null) continue;
|
||||
|
||||
let matches = false;
|
||||
if (formatters[fmt].files === true) {
|
||||
matches = true;
|
||||
}
|
||||
if (!matches) {
|
||||
const filesToCheck = Array.isArray(formatters[fmt].files)
|
||||
? formatters[fmt].files.map((base) => ({ base, contents: true }))
|
||||
? formatters[fmt].files.map((base) => ({ base, check: true }))
|
||||
: Object.entries(formatters[fmt].files)
|
||||
.map(([base, contents]) => ({ base, contents }));
|
||||
for (const { base, contents } of filesToCheck) {
|
||||
.map(([base, check]) => ({ base, check }));
|
||||
for (const { base, check } of filesToCheck) {
|
||||
if (base.includes("/")) {
|
||||
matches = readDir(path.join(x, path.dirname(base))) //
|
||||
.includes(path.basename(base));
|
||||
} else {
|
||||
matches = children.includes(base);
|
||||
}
|
||||
if (matches && typeof contents === "function") {
|
||||
matches = !!contents(fs.readFileSync(path.join(x, base), "utf-8"));
|
||||
if (matches && typeof check === "function") {
|
||||
let text;
|
||||
matches = !!check({
|
||||
get text() {
|
||||
return text ??= fs.readFileSync(path.join(x, base), "utf-8");
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +546,7 @@ function pickFormatter(file) {
|
|||
return formatterId;
|
||||
}
|
||||
}
|
||||
}) ?? possible[0];
|
||||
}) ?? possible.find((fmt) => !formatters[fmt].mustMatchFile);
|
||||
}
|
||||
|
||||
/** @param dir {string} @param find {(x: string) => any} */
|
||||
|
@ -581,6 +601,29 @@ function readGitIgnore(dir) {
|
|||
}
|
||||
}
|
||||
|
||||
/** @param {string} name @returns {string | null} */
|
||||
export function which(name) {
|
||||
const paths =
|
||||
process.env.PATH?.split(process.platform === "win32" ? ";" : ":") ?? [];
|
||||
const exts = process.platform === "win32"
|
||||
? (process.env.PATHEXT?.split(";") ?? [".exe", ".cmd", ".bat", ".com"])
|
||||
: [""];
|
||||
|
||||
for (const dir of paths) {
|
||||
if (!dir) continue;
|
||||
try {
|
||||
const entries = readDir(dir);
|
||||
for (const ext of exts) {
|
||||
const target = name + ext;
|
||||
if (entries.includes(target)) {
|
||||
return dir + sep + target;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function escapeGlob(str) {
|
||||
return str.replace(/[\\*,{}]/g, "\\$&");
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ pkgs.writeShellApplication {
|
|||
name = "autofmt";
|
||||
runtimeInputs = with pkgs; [
|
||||
# include only a couple of formatters by default
|
||||
clang-tools
|
||||
deno
|
||||
nixfmt-rfc-style
|
||||
dprint
|
||||
nixfmt-rfc-style
|
||||
prettierd # autofmt only runs on a local build of prettier
|
||||
rustfmt
|
||||
zig
|
||||
clang-tools
|
||||
];
|
||||
text = ''exec ${pkgs.nodejs}/bin/node ${./autofmt.js} "$@"'';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue