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
|
#!/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
|
// https://paperclover.dev/nix/config/src/branch/main/packages/autofmt/autofmt.js
|
||||||
//
|
//
|
||||||
// Different codebases use different formatters. Autofmt looks for project
|
// 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
|
// @ts-nocheck
|
||||||
|
|
||||||
// -- definitions --
|
// -- definitions --
|
||||||
|
@ -72,6 +76,15 @@ const formatters = {
|
||||||
cmd: ["deno", "fmt", "--", "$files"],
|
cmd: ["deno", "fmt", "--", "$files"],
|
||||||
stdin: (file) => ["deno", "fmt", "--ext", path.extname(file).slice(1), "-"],
|
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: {
|
prettier: {
|
||||||
languages: ["javascript", "markdown", "json", "yaml", "mdx", "html", "css"],
|
languages: ["javascript", "markdown", "json", "yaml", "mdx", "html", "css"],
|
||||||
files: ["node_modules/.bin/prettier"],
|
files: ["node_modules/.bin/prettier"],
|
||||||
|
@ -91,7 +104,7 @@ const formatters = {
|
||||||
"nixfmt-rfc-style": {
|
"nixfmt-rfc-style": {
|
||||||
languages: ["nix"],
|
languages: ["nix"],
|
||||||
files: {
|
files: {
|
||||||
"flake.nix": (contents) => contents.includes("nixfmt"),
|
"flake.nix": ({ text }) => text.includes("nixfmt"),
|
||||||
},
|
},
|
||||||
cmd: ["nixfmt", "--", "$files"],
|
cmd: ["nixfmt", "--", "$files"],
|
||||||
stdin: (file) => ["nixfmt", `--filename=${file}`],
|
stdin: (file) => ["nixfmt", `--filename=${file}`],
|
||||||
|
@ -99,7 +112,7 @@ const formatters = {
|
||||||
alejandra: {
|
alejandra: {
|
||||||
languages: ["nix"],
|
languages: ["nix"],
|
||||||
files: {
|
files: {
|
||||||
"flake.nix": (contents) => contents.includes("alejandra"),
|
"flake.nix": ({ text }) => text.includes("alejandra"),
|
||||||
},
|
},
|
||||||
cmd: ["alejandra", "--", "$files"],
|
cmd: ["alejandra", "--", "$files"],
|
||||||
stdin: () => ["alejandra"],
|
stdin: () => ["alejandra"],
|
||||||
|
@ -498,24 +511,31 @@ function pickFormatter(file) {
|
||||||
return walkUp(dir, (x) => {
|
return walkUp(dir, (x) => {
|
||||||
const children = readDir(x);
|
const children = readDir(x);
|
||||||
for (const fmt of order) {
|
for (const fmt of order) {
|
||||||
|
if (formatters[fmt][stdio ? "stdin" : "cmd"] == null) continue;
|
||||||
|
|
||||||
let matches = false;
|
let matches = false;
|
||||||
if (formatters[fmt].files === true) {
|
if (formatters[fmt].files === true) {
|
||||||
matches = true;
|
matches = true;
|
||||||
}
|
}
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
const filesToCheck = Array.isArray(formatters[fmt].files)
|
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)
|
: Object.entries(formatters[fmt].files)
|
||||||
.map(([base, contents]) => ({ base, contents }));
|
.map(([base, check]) => ({ base, check }));
|
||||||
for (const { base, contents } of filesToCheck) {
|
for (const { base, check } of filesToCheck) {
|
||||||
if (base.includes("/")) {
|
if (base.includes("/")) {
|
||||||
matches = readDir(path.join(x, path.dirname(base))) //
|
matches = readDir(path.join(x, path.dirname(base))) //
|
||||||
.includes(path.basename(base));
|
.includes(path.basename(base));
|
||||||
} else {
|
} else {
|
||||||
matches = children.includes(base);
|
matches = children.includes(base);
|
||||||
}
|
}
|
||||||
if (matches && typeof contents === "function") {
|
if (matches && typeof check === "function") {
|
||||||
matches = !!contents(fs.readFileSync(path.join(x, base), "utf-8"));
|
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;
|
return formatterId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) ?? possible[0];
|
}) ?? possible.find((fmt) => !formatters[fmt].mustMatchFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param dir {string} @param find {(x: string) => any} */
|
/** @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) {
|
function escapeGlob(str) {
|
||||||
return str.replace(/[\\*,{}]/g, "\\$&");
|
return str.replace(/[\\*,{}]/g, "\\$&");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,13 @@ pkgs.writeShellApplication {
|
||||||
name = "autofmt";
|
name = "autofmt";
|
||||||
runtimeInputs = with pkgs; [
|
runtimeInputs = with pkgs; [
|
||||||
# include only a couple of formatters by default
|
# include only a couple of formatters by default
|
||||||
|
clang-tools
|
||||||
deno
|
deno
|
||||||
nixfmt-rfc-style
|
|
||||||
dprint
|
dprint
|
||||||
|
nixfmt-rfc-style
|
||||||
|
prettierd # autofmt only runs on a local build of prettier
|
||||||
rustfmt
|
rustfmt
|
||||||
zig
|
zig
|
||||||
clang-tools
|
|
||||||
];
|
];
|
||||||
text = ''exec ${pkgs.nodejs}/bin/node ${./autofmt.js} "$@"'';
|
text = ''exec ${pkgs.nodejs}/bin/node ${./autofmt.js} "$@"'';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue