refactor(format): update formatter interface to return command from enabled() (#20703)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { text } from "node:stream/consumers"
|
import { text } from "node:stream/consumers"
|
||||||
|
import { Npm } from "@/npm"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
import { Filesystem } from "../util/filesystem"
|
import { Filesystem } from "../util/filesystem"
|
||||||
import { Process } from "../util/process"
|
import { Process } from "../util/process"
|
||||||
@@ -7,33 +8,33 @@ import { Flag } from "@/flag/flag"
|
|||||||
|
|
||||||
export interface Info {
|
export interface Info {
|
||||||
name: string
|
name: string
|
||||||
command: string[]
|
|
||||||
environment?: Record<string, string>
|
environment?: Record<string, string>
|
||||||
extensions: string[]
|
extensions: string[]
|
||||||
enabled(): Promise<boolean>
|
enabled(): Promise<string[] | false>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const gofmt: Info = {
|
export const gofmt: Info = {
|
||||||
name: "gofmt",
|
name: "gofmt",
|
||||||
command: ["gofmt", "-w", "$FILE"],
|
|
||||||
extensions: [".go"],
|
extensions: [".go"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("gofmt") !== null
|
const match = which("gofmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-w", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mix: Info = {
|
export const mix: Info = {
|
||||||
name: "mix",
|
name: "mix",
|
||||||
command: ["mix", "format", "$FILE"],
|
|
||||||
extensions: [".ex", ".exs", ".eex", ".heex", ".leex", ".neex", ".sface"],
|
extensions: [".ex", ".exs", ".eex", ".heex", ".leex", ".neex", ".sface"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("mix") !== null
|
const match = which("mix")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "format", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const prettier: Info = {
|
export const prettier: Info = {
|
||||||
name: "prettier",
|
name: "prettier",
|
||||||
command: ["bun", "x", "prettier", "--write", "$FILE"],
|
|
||||||
environment: {
|
environment: {
|
||||||
BUN_BE_BUN: "1",
|
BUN_BE_BUN: "1",
|
||||||
},
|
},
|
||||||
@@ -72,8 +73,10 @@ export const prettier: Info = {
|
|||||||
dependencies?: Record<string, string>
|
dependencies?: Record<string, string>
|
||||||
devDependencies?: Record<string, string>
|
devDependencies?: Record<string, string>
|
||||||
}>(item)
|
}>(item)
|
||||||
if (json.dependencies?.prettier) return true
|
if (json.dependencies?.prettier || json.devDependencies?.prettier) {
|
||||||
if (json.devDependencies?.prettier) return true
|
const bin = await Npm.which("prettier")
|
||||||
|
if (bin) return [bin, "--write", "$FILE"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
@@ -81,7 +84,6 @@ export const prettier: Info = {
|
|||||||
|
|
||||||
export const oxfmt: Info = {
|
export const oxfmt: Info = {
|
||||||
name: "oxfmt",
|
name: "oxfmt",
|
||||||
command: ["bun", "x", "oxfmt", "$FILE"],
|
|
||||||
environment: {
|
environment: {
|
||||||
BUN_BE_BUN: "1",
|
BUN_BE_BUN: "1",
|
||||||
},
|
},
|
||||||
@@ -94,8 +96,10 @@ export const oxfmt: Info = {
|
|||||||
dependencies?: Record<string, string>
|
dependencies?: Record<string, string>
|
||||||
devDependencies?: Record<string, string>
|
devDependencies?: Record<string, string>
|
||||||
}>(item)
|
}>(item)
|
||||||
if (json.dependencies?.oxfmt) return true
|
if (json.dependencies?.oxfmt || json.devDependencies?.oxfmt) {
|
||||||
if (json.devDependencies?.oxfmt) return true
|
const bin = await Npm.which("oxfmt")
|
||||||
|
if (bin) return [bin, "$FILE"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
@@ -103,7 +107,6 @@ export const oxfmt: Info = {
|
|||||||
|
|
||||||
export const biome: Info = {
|
export const biome: Info = {
|
||||||
name: "biome",
|
name: "biome",
|
||||||
command: ["bun", "x", "@biomejs/biome", "format", "--write", "$FILE"],
|
|
||||||
environment: {
|
environment: {
|
||||||
BUN_BE_BUN: "1",
|
BUN_BE_BUN: "1",
|
||||||
},
|
},
|
||||||
@@ -140,7 +143,8 @@ export const biome: Info = {
|
|||||||
for (const config of configs) {
|
for (const config of configs) {
|
||||||
const found = await Filesystem.findUp(config, Instance.directory, Instance.worktree)
|
const found = await Filesystem.findUp(config, Instance.directory, Instance.worktree)
|
||||||
if (found.length > 0) {
|
if (found.length > 0) {
|
||||||
return true
|
const bin = await Npm.which("@biomejs/biome")
|
||||||
|
if (bin) return [bin, "format", "--write", "$FILE"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -149,35 +153,39 @@ export const biome: Info = {
|
|||||||
|
|
||||||
export const zig: Info = {
|
export const zig: Info = {
|
||||||
name: "zig",
|
name: "zig",
|
||||||
command: ["zig", "fmt", "$FILE"],
|
|
||||||
extensions: [".zig", ".zon"],
|
extensions: [".zig", ".zon"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("zig") !== null
|
const match = which("zig")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "fmt", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clang: Info = {
|
export const clang: Info = {
|
||||||
name: "clang-format",
|
name: "clang-format",
|
||||||
command: ["clang-format", "-i", "$FILE"],
|
|
||||||
extensions: [".c", ".cc", ".cpp", ".cxx", ".c++", ".h", ".hh", ".hpp", ".hxx", ".h++", ".ino", ".C", ".H"],
|
extensions: [".c", ".cc", ".cpp", ".cxx", ".c++", ".h", ".hh", ".hpp", ".hxx", ".h++", ".ino", ".C", ".H"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
const items = await Filesystem.findUp(".clang-format", Instance.directory, Instance.worktree)
|
const items = await Filesystem.findUp(".clang-format", Instance.directory, Instance.worktree)
|
||||||
return items.length > 0
|
if (items.length > 0) {
|
||||||
|
const match = which("clang-format")
|
||||||
|
if (match) return [match, "-i", "$FILE"]
|
||||||
|
}
|
||||||
|
return false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ktlint: Info = {
|
export const ktlint: Info = {
|
||||||
name: "ktlint",
|
name: "ktlint",
|
||||||
command: ["ktlint", "-F", "$FILE"],
|
|
||||||
extensions: [".kt", ".kts"],
|
extensions: [".kt", ".kts"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("ktlint") !== null
|
const match = which("ktlint")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-F", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ruff: Info = {
|
export const ruff: Info = {
|
||||||
name: "ruff",
|
name: "ruff",
|
||||||
command: ["ruff", "format", "$FILE"],
|
|
||||||
extensions: [".py", ".pyi"],
|
extensions: [".py", ".pyi"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
if (!which("ruff")) return false
|
if (!which("ruff")) return false
|
||||||
@@ -187,9 +195,9 @@ export const ruff: Info = {
|
|||||||
if (found.length > 0) {
|
if (found.length > 0) {
|
||||||
if (config === "pyproject.toml") {
|
if (config === "pyproject.toml") {
|
||||||
const content = await Filesystem.readText(found[0])
|
const content = await Filesystem.readText(found[0])
|
||||||
if (content.includes("[tool.ruff]")) return true
|
if (content.includes("[tool.ruff]")) return ["ruff", "format", "$FILE"]
|
||||||
} else {
|
} else {
|
||||||
return true
|
return ["ruff", "format", "$FILE"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +206,7 @@ export const ruff: Info = {
|
|||||||
const found = await Filesystem.findUp(dep, Instance.directory, Instance.worktree)
|
const found = await Filesystem.findUp(dep, Instance.directory, Instance.worktree)
|
||||||
if (found.length > 0) {
|
if (found.length > 0) {
|
||||||
const content = await Filesystem.readText(found[0])
|
const content = await Filesystem.readText(found[0])
|
||||||
if (content.includes("ruff")) return true
|
if (content.includes("ruff")) return ["ruff", "format", "$FILE"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -207,7 +215,6 @@ export const ruff: Info = {
|
|||||||
|
|
||||||
export const rlang: Info = {
|
export const rlang: Info = {
|
||||||
name: "air",
|
name: "air",
|
||||||
command: ["air", "format", "$FILE"],
|
|
||||||
extensions: [".R"],
|
extensions: [".R"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
const airPath = which("air")
|
const airPath = which("air")
|
||||||
@@ -226,23 +233,23 @@ export const rlang: Info = {
|
|||||||
const firstLine = output.split("\n")[0]
|
const firstLine = output.split("\n")[0]
|
||||||
const hasR = firstLine.includes("R language")
|
const hasR = firstLine.includes("R language")
|
||||||
const hasFormatter = firstLine.includes("formatter")
|
const hasFormatter = firstLine.includes("formatter")
|
||||||
return hasR && hasFormatter
|
if (hasR && hasFormatter) return ["air", "format", "$FILE"]
|
||||||
} catch (error) {
|
} catch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const uvformat: Info = {
|
export const uvformat: Info = {
|
||||||
name: "uv",
|
name: "uv",
|
||||||
command: ["uv", "format", "--", "$FILE"],
|
|
||||||
extensions: [".py", ".pyi"],
|
extensions: [".py", ".pyi"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
if (await ruff.enabled()) return false
|
if (await ruff.enabled()) return false
|
||||||
if (which("uv") !== null) {
|
if (which("uv") !== null) {
|
||||||
const proc = Process.spawn(["uv", "format", "--help"], { stderr: "pipe", stdout: "pipe" })
|
const proc = Process.spawn(["uv", "format", "--help"], { stderr: "pipe", stdout: "pipe" })
|
||||||
const code = await proc.exited
|
const code = await proc.exited
|
||||||
return code === 0
|
if (code === 0) return ["uv", "format", "--", "$FILE"]
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
@@ -250,108 +257,117 @@ export const uvformat: Info = {
|
|||||||
|
|
||||||
export const rubocop: Info = {
|
export const rubocop: Info = {
|
||||||
name: "rubocop",
|
name: "rubocop",
|
||||||
command: ["rubocop", "--autocorrect", "$FILE"],
|
|
||||||
extensions: [".rb", ".rake", ".gemspec", ".ru"],
|
extensions: [".rb", ".rake", ".gemspec", ".ru"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("rubocop") !== null
|
const match = which("rubocop")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "--autocorrect", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const standardrb: Info = {
|
export const standardrb: Info = {
|
||||||
name: "standardrb",
|
name: "standardrb",
|
||||||
command: ["standardrb", "--fix", "$FILE"],
|
|
||||||
extensions: [".rb", ".rake", ".gemspec", ".ru"],
|
extensions: [".rb", ".rake", ".gemspec", ".ru"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("standardrb") !== null
|
const match = which("standardrb")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "--fix", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const htmlbeautifier: Info = {
|
export const htmlbeautifier: Info = {
|
||||||
name: "htmlbeautifier",
|
name: "htmlbeautifier",
|
||||||
command: ["htmlbeautifier", "$FILE"],
|
|
||||||
extensions: [".erb", ".html.erb"],
|
extensions: [".erb", ".html.erb"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("htmlbeautifier") !== null
|
const match = which("htmlbeautifier")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const dart: Info = {
|
export const dart: Info = {
|
||||||
name: "dart",
|
name: "dart",
|
||||||
command: ["dart", "format", "$FILE"],
|
|
||||||
extensions: [".dart"],
|
extensions: [".dart"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("dart") !== null
|
const match = which("dart")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "format", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ocamlformat: Info = {
|
export const ocamlformat: Info = {
|
||||||
name: "ocamlformat",
|
name: "ocamlformat",
|
||||||
command: ["ocamlformat", "-i", "$FILE"],
|
|
||||||
extensions: [".ml", ".mli"],
|
extensions: [".ml", ".mli"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
if (!which("ocamlformat")) return false
|
if (!which("ocamlformat")) return false
|
||||||
const items = await Filesystem.findUp(".ocamlformat", Instance.directory, Instance.worktree)
|
const items = await Filesystem.findUp(".ocamlformat", Instance.directory, Instance.worktree)
|
||||||
return items.length > 0
|
if (items.length > 0) return ["ocamlformat", "-i", "$FILE"]
|
||||||
|
return false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const terraform: Info = {
|
export const terraform: Info = {
|
||||||
name: "terraform",
|
name: "terraform",
|
||||||
command: ["terraform", "fmt", "$FILE"],
|
|
||||||
extensions: [".tf", ".tfvars"],
|
extensions: [".tf", ".tfvars"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("terraform") !== null
|
const match = which("terraform")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "fmt", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const latexindent: Info = {
|
export const latexindent: Info = {
|
||||||
name: "latexindent",
|
name: "latexindent",
|
||||||
command: ["latexindent", "-w", "-s", "$FILE"],
|
|
||||||
extensions: [".tex"],
|
extensions: [".tex"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("latexindent") !== null
|
const match = which("latexindent")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-w", "-s", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const gleam: Info = {
|
export const gleam: Info = {
|
||||||
name: "gleam",
|
name: "gleam",
|
||||||
command: ["gleam", "format", "$FILE"],
|
|
||||||
extensions: [".gleam"],
|
extensions: [".gleam"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("gleam") !== null
|
const match = which("gleam")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "format", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shfmt: Info = {
|
export const shfmt: Info = {
|
||||||
name: "shfmt",
|
name: "shfmt",
|
||||||
command: ["shfmt", "-w", "$FILE"],
|
|
||||||
extensions: [".sh", ".bash"],
|
extensions: [".sh", ".bash"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("shfmt") !== null
|
const match = which("shfmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-w", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nixfmt: Info = {
|
export const nixfmt: Info = {
|
||||||
name: "nixfmt",
|
name: "nixfmt",
|
||||||
command: ["nixfmt", "$FILE"],
|
|
||||||
extensions: [".nix"],
|
extensions: [".nix"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("nixfmt") !== null
|
const match = which("nixfmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rustfmt: Info = {
|
export const rustfmt: Info = {
|
||||||
name: "rustfmt",
|
name: "rustfmt",
|
||||||
command: ["rustfmt", "$FILE"],
|
|
||||||
extensions: [".rs"],
|
extensions: [".rs"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("rustfmt") !== null
|
const match = which("rustfmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pint: Info = {
|
export const pint: Info = {
|
||||||
name: "pint",
|
name: "pint",
|
||||||
command: ["./vendor/bin/pint", "$FILE"],
|
|
||||||
extensions: [".php"],
|
extensions: [".php"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
const items = await Filesystem.findUp("composer.json", Instance.directory, Instance.worktree)
|
const items = await Filesystem.findUp("composer.json", Instance.directory, Instance.worktree)
|
||||||
@@ -360,8 +376,7 @@ export const pint: Info = {
|
|||||||
require?: Record<string, string>
|
require?: Record<string, string>
|
||||||
"require-dev"?: Record<string, string>
|
"require-dev"?: Record<string, string>
|
||||||
}>(item)
|
}>(item)
|
||||||
if (json.require?.["laravel/pint"]) return true
|
if (json.require?.["laravel/pint"] || json["require-dev"]?.["laravel/pint"]) return ["./vendor/bin/pint", "$FILE"]
|
||||||
if (json["require-dev"]?.["laravel/pint"]) return true
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
@@ -369,27 +384,30 @@ export const pint: Info = {
|
|||||||
|
|
||||||
export const ormolu: Info = {
|
export const ormolu: Info = {
|
||||||
name: "ormolu",
|
name: "ormolu",
|
||||||
command: ["ormolu", "-i", "$FILE"],
|
|
||||||
extensions: [".hs"],
|
extensions: [".hs"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("ormolu") !== null
|
const match = which("ormolu")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-i", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cljfmt: Info = {
|
export const cljfmt: Info = {
|
||||||
name: "cljfmt",
|
name: "cljfmt",
|
||||||
command: ["cljfmt", "fix", "--quiet", "$FILE"],
|
|
||||||
extensions: [".clj", ".cljs", ".cljc", ".edn"],
|
extensions: [".clj", ".cljs", ".cljc", ".edn"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("cljfmt") !== null
|
const match = which("cljfmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "fix", "--quiet", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const dfmt: Info = {
|
export const dfmt: Info = {
|
||||||
name: "dfmt",
|
name: "dfmt",
|
||||||
command: ["dfmt", "-i", "$FILE"],
|
|
||||||
extensions: [".d"],
|
extensions: [".d"],
|
||||||
async enabled() {
|
async enabled() {
|
||||||
return which("dfmt") !== null
|
const match = which("dfmt")
|
||||||
|
if (!match) return false
|
||||||
|
return [match, "-i", "$FILE"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export namespace Format {
|
|||||||
|
|
||||||
const state = yield* InstanceState.make(
|
const state = yield* InstanceState.make(
|
||||||
Effect.fn("Format.state")(function* (_ctx) {
|
Effect.fn("Format.state")(function* (_ctx) {
|
||||||
const enabled: Record<string, boolean> = {}
|
const commands: Record<string, string[] | false> = {}
|
||||||
const formatters: Record<string, Formatter.Info> = {}
|
const formatters: Record<string, Formatter.Info> = {}
|
||||||
|
|
||||||
const cfg = yield* config.get()
|
const cfg = yield* config.get()
|
||||||
@@ -56,30 +56,32 @@ export namespace Format {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const info = mergeDeep(formatters[name] ?? {}, {
|
const info = mergeDeep(formatters[name] ?? {}, {
|
||||||
command: [],
|
|
||||||
extensions: [],
|
extensions: [],
|
||||||
...item,
|
...item,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (info.command.length === 0) continue
|
|
||||||
|
|
||||||
formatters[name] = {
|
formatters[name] = {
|
||||||
...info,
|
...info,
|
||||||
name,
|
name,
|
||||||
enabled: async () => true,
|
enabled: async () => info.command ?? false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("all formatters are disabled")
|
log.info("all formatters are disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isEnabled(item: Formatter.Info) {
|
async function getCommand(item: Formatter.Info) {
|
||||||
let status = enabled[item.name]
|
let cmd = commands[item.name]
|
||||||
if (status === undefined) {
|
if (cmd === false || cmd === undefined) {
|
||||||
status = await item.enabled()
|
cmd = await item.enabled()
|
||||||
enabled[item.name] = status
|
commands[item.name] = cmd
|
||||||
}
|
}
|
||||||
return status
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
async function isEnabled(item: Formatter.Info) {
|
||||||
|
const cmd = await getCommand(item)
|
||||||
|
return cmd !== false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFormatter(ext: string) {
|
async function getFormatter(ext: string) {
|
||||||
@@ -87,17 +89,17 @@ export namespace Format {
|
|||||||
const checks = await Promise.all(
|
const checks = await Promise.all(
|
||||||
matching.map(async (item) => {
|
matching.map(async (item) => {
|
||||||
log.info("checking", { name: item.name, ext })
|
log.info("checking", { name: item.name, ext })
|
||||||
const on = await isEnabled(item)
|
const cmd = await getCommand(item)
|
||||||
if (on) {
|
if (cmd) {
|
||||||
log.info("enabled", { name: item.name, ext })
|
log.info("enabled", { name: item.name, ext })
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
item,
|
item,
|
||||||
enabled: on,
|
cmd,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return checks.filter((x) => x.enabled).map((x) => x.item)
|
return checks.filter((x) => x.cmd).map((x) => ({ item: x.item, cmd: x.cmd! }))
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatFile(filepath: string) {
|
function formatFile(filepath: string) {
|
||||||
@@ -105,13 +107,14 @@ export namespace Format {
|
|||||||
log.info("formatting", { file: filepath })
|
log.info("formatting", { file: filepath })
|
||||||
const ext = path.extname(filepath)
|
const ext = path.extname(filepath)
|
||||||
|
|
||||||
for (const item of yield* Effect.promise(() => getFormatter(ext))) {
|
for (const { item, cmd } of yield* Effect.promise(() => getFormatter(ext))) {
|
||||||
log.info("running", { command: item.command })
|
if (cmd === false) continue
|
||||||
const cmd = item.command.map((x) => x.replace("$FILE", filepath))
|
log.info("running", { command: cmd })
|
||||||
|
const replaced = cmd.map((x) => x.replace("$FILE", filepath))
|
||||||
const dir = yield* InstanceState.directory
|
const dir = yield* InstanceState.directory
|
||||||
const code = yield* spawner
|
const code = yield* spawner
|
||||||
.spawn(
|
.spawn(
|
||||||
ChildProcess.make(cmd[0]!, cmd.slice(1), {
|
ChildProcess.make(replaced[0]!, replaced.slice(1), {
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
env: item.environment,
|
env: item.environment,
|
||||||
extendEnv: true,
|
extendEnv: true,
|
||||||
@@ -124,7 +127,7 @@ export namespace Format {
|
|||||||
Effect.sync(() => {
|
Effect.sync(() => {
|
||||||
log.error("failed to format file", {
|
log.error("failed to format file", {
|
||||||
error: "spawn failed",
|
error: "spawn failed",
|
||||||
command: item.command,
|
command: cmd,
|
||||||
...item.environment,
|
...item.environment,
|
||||||
file: filepath,
|
file: filepath,
|
||||||
})
|
})
|
||||||
@@ -134,7 +137,7 @@ export namespace Format {
|
|||||||
)
|
)
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
log.error("failed", {
|
log.error("failed", {
|
||||||
command: item.command,
|
command: cmd,
|
||||||
...item.environment,
|
...item.environment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,12 +87,10 @@ describe("Format", () => {
|
|||||||
const one = {
|
const one = {
|
||||||
extensions: Formatter.gofmt.extensions,
|
extensions: Formatter.gofmt.extensions,
|
||||||
enabled: Formatter.gofmt.enabled,
|
enabled: Formatter.gofmt.enabled,
|
||||||
command: Formatter.gofmt.command,
|
|
||||||
}
|
}
|
||||||
const two = {
|
const two = {
|
||||||
extensions: Formatter.mix.extensions,
|
extensions: Formatter.mix.extensions,
|
||||||
enabled: Formatter.mix.enabled,
|
enabled: Formatter.mix.enabled,
|
||||||
command: Formatter.mix.command,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let active = 0
|
let active = 0
|
||||||
@@ -102,21 +100,19 @@ describe("Format", () => {
|
|||||||
Effect.sync(() => {
|
Effect.sync(() => {
|
||||||
Formatter.gofmt.extensions = [".parallel"]
|
Formatter.gofmt.extensions = [".parallel"]
|
||||||
Formatter.mix.extensions = [".parallel"]
|
Formatter.mix.extensions = [".parallel"]
|
||||||
Formatter.gofmt.command = ["sh", "-c", "true"]
|
|
||||||
Formatter.mix.command = ["sh", "-c", "true"]
|
|
||||||
Formatter.gofmt.enabled = async () => {
|
Formatter.gofmt.enabled = async () => {
|
||||||
active++
|
active++
|
||||||
max = Math.max(max, active)
|
max = Math.max(max, active)
|
||||||
await Bun.sleep(20)
|
await Bun.sleep(20)
|
||||||
active--
|
active--
|
||||||
return true
|
return ["sh", "-c", "true"]
|
||||||
}
|
}
|
||||||
Formatter.mix.enabled = async () => {
|
Formatter.mix.enabled = async () => {
|
||||||
active++
|
active++
|
||||||
max = Math.max(max, active)
|
max = Math.max(max, active)
|
||||||
await Bun.sleep(20)
|
await Bun.sleep(20)
|
||||||
active--
|
active--
|
||||||
return true
|
return ["sh", "-c", "true"]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
() =>
|
() =>
|
||||||
@@ -130,10 +126,8 @@ describe("Format", () => {
|
|||||||
Effect.sync(() => {
|
Effect.sync(() => {
|
||||||
Formatter.gofmt.extensions = one.extensions
|
Formatter.gofmt.extensions = one.extensions
|
||||||
Formatter.gofmt.enabled = one.enabled
|
Formatter.gofmt.enabled = one.enabled
|
||||||
Formatter.gofmt.command = one.command
|
|
||||||
Formatter.mix.extensions = two.extensions
|
Formatter.mix.extensions = two.extensions
|
||||||
Formatter.mix.enabled = two.enabled
|
Formatter.mix.enabled = two.enabled
|
||||||
Formatter.mix.command = two.command
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user