formatter.ts 4.4 KB

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