formatter.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { App } from "../app/app"
  2. import { BunProc } from "../bun"
  3. import { Filesystem } from "../util/filesystem"
  4. import path from "path"
  5. export interface Info {
  6. name: string
  7. command: string[]
  8. environment?: Record<string, string>
  9. extensions: string[]
  10. enabled(): Promise<boolean>
  11. }
  12. export const gofmt: Info = {
  13. name: "gofmt",
  14. command: ["gofmt", "-w", "$FILE"],
  15. extensions: [".go"],
  16. async enabled() {
  17. return Bun.which("gofmt") !== null
  18. },
  19. }
  20. export const mix: Info = {
  21. name: "mix",
  22. command: ["mix", "format", "$FILE"],
  23. extensions: [".ex", ".exs", ".eex", ".heex", ".leex", ".neex", ".sface"],
  24. async enabled() {
  25. return Bun.which("mix") !== null
  26. },
  27. }
  28. export const prettier: Info = {
  29. name: "prettier",
  30. command: [BunProc.which(), "x", "prettier", "--write", "$FILE"],
  31. environment: {
  32. BUN_BE_BUN: "1",
  33. },
  34. extensions: [
  35. ".js",
  36. ".jsx",
  37. ".mjs",
  38. ".cjs",
  39. ".ts",
  40. ".tsx",
  41. ".mts",
  42. ".cts",
  43. ".html",
  44. ".htm",
  45. ".css",
  46. ".scss",
  47. ".sass",
  48. ".less",
  49. ".vue",
  50. ".svelte",
  51. ".json",
  52. ".jsonc",
  53. ".yaml",
  54. ".yml",
  55. ".toml",
  56. ".xml",
  57. ".md",
  58. ".mdx",
  59. ".graphql",
  60. ".gql",
  61. ],
  62. async enabled() {
  63. const app = App.info()
  64. const nms = await Filesystem.findUp("node_modules", app.path.cwd, app.path.root)
  65. for (const item of nms) {
  66. if (await Bun.file(path.join(item, ".bin", "prettier")).exists()) return true
  67. }
  68. return false
  69. },
  70. }
  71. export const zig: Info = {
  72. name: "zig",
  73. command: ["zig", "fmt", "$FILE"],
  74. extensions: [".zig", ".zon"],
  75. async enabled() {
  76. return Bun.which("zig") !== null
  77. },
  78. }
  79. export const clang: Info = {
  80. name: "clang-format",
  81. command: ["clang-format", "-i", "$FILE"],
  82. extensions: [".c", ".cc", ".cpp", ".cxx", ".c++", ".h", ".hh", ".hpp", ".hxx", ".h++", ".ino", ".C", ".H"],
  83. async enabled() {
  84. return Bun.which("clang-format") !== null
  85. },
  86. }
  87. export const ktlint: Info = {
  88. name: "ktlint",
  89. command: ["ktlint", "-F", "$FILE"],
  90. extensions: [".kt", ".kts"],
  91. async enabled() {
  92. return Bun.which("ktlint") !== null
  93. },
  94. }
  95. export const ruff: Info = {
  96. name: "ruff",
  97. command: ["ruff", "format", "$FILE"],
  98. extensions: [".py", ".pyi"],
  99. async enabled() {
  100. if (!Bun.which("ruff")) return false
  101. const app = App.info()
  102. const configs = ["pyproject.toml", "ruff.toml", ".ruff.toml"]
  103. for (const config of configs) {
  104. const found = await Filesystem.findUp(config, app.path.cwd, app.path.root)
  105. if (found.length > 0) {
  106. if (config === "pyproject.toml") {
  107. const content = await Bun.file(found[0]).text()
  108. if (content.includes("[tool.ruff]")) return true
  109. } else {
  110. return true
  111. }
  112. }
  113. }
  114. const deps = ["requirements.txt", "pyproject.toml", "Pipfile"]
  115. for (const dep of deps) {
  116. const found = await Filesystem.findUp(dep, app.path.cwd, app.path.root)
  117. if (found.length > 0) {
  118. const content = await Bun.file(found[0]).text()
  119. if (content.includes("ruff")) return true
  120. }
  121. }
  122. return false
  123. },
  124. }
  125. export const rubocop: Info = {
  126. name: "rubocop",
  127. command: ["rubocop", "--autocorrect", "$FILE"],
  128. extensions: [".rb", ".rake", ".gemspec", ".ru"],
  129. async enabled() {
  130. return Bun.which("rubocop") !== null
  131. },
  132. }
  133. export const standardrb: Info = {
  134. name: "standardrb",
  135. command: ["standardrb", "--fix", "$FILE"],
  136. extensions: [".rb", ".rake", ".gemspec", ".ru"],
  137. async enabled() {
  138. return Bun.which("standardrb") !== null
  139. },
  140. }
  141. export const htmlbeautifier: Info = {
  142. name: "htmlbeautifier",
  143. command: ["htmlbeautifier", "$FILE"],
  144. extensions: [".erb", ".html.erb"],
  145. async enabled() {
  146. return Bun.which("htmlbeautifier") !== null
  147. },
  148. }