|
1 | 1 | #!/usr/bin/env node |
2 | 2 |
|
3 | | -import { defineCommand, runMain } from "citty"; |
| 3 | +import { parseArgs } from "node:util"; |
4 | 4 | import { format as prettierFormat } from "prettier"; |
5 | 5 | import { format as sqlFormat, SqlLanguage, supportedDialects } from "sql-formatter"; |
6 | 6 | import { |
@@ -74,58 +74,91 @@ async function readStdin(): Promise<string> { |
74 | 74 | return chunks.join(""); |
75 | 75 | } |
76 | 76 |
|
77 | | -const main = defineCommand({ |
78 | | - meta: { description: "Format code from the clipboard" }, |
79 | | - args: { |
80 | | - language: { |
81 | | - type: "positional", |
82 | | - description: `Language to format (${languages.join(", ")})`, |
83 | | - required: true, |
84 | | - }, |
85 | | - "print-width": { |
86 | | - type: "string", |
87 | | - description: "Prettier print width", |
88 | | - default: "100", |
89 | | - }, |
90 | | - "sql-dialect": { |
91 | | - type: "string", |
92 | | - description: `SQL dialect (${supportedDialects.join(", ")})`, |
93 | | - default: "sql", |
| 77 | +function fail(message: string): never { |
| 78 | + console.error(message); |
| 79 | + process.exit(1); |
| 80 | +} |
| 81 | + |
| 82 | +function checkPrintWidth(value: string): number { |
| 83 | + const printWidth = parsePrintWidth(value); |
| 84 | + |
| 85 | + if (printWidth === undefined) { |
| 86 | + fail(`Invalid print width: ${value}\nPrint width must be a positive integer`); |
| 87 | + } |
| 88 | + |
| 89 | + return printWidth; |
| 90 | +} |
| 91 | + |
| 92 | +function checkSqlDialect(value: string): SqlLanguage { |
| 93 | + if (!isSqlLanguage(value)) { |
| 94 | + fail(`Unknown SQL dialect: ${value}\nSQL dialects: ${supportedDialects.join(", ")}`); |
| 95 | + } |
| 96 | + |
| 97 | + return value; |
| 98 | +} |
| 99 | + |
| 100 | +function checkLanguage(value: string): Language { |
| 101 | + if (!isLanguage(value)) { |
| 102 | + fail(`Unknown language: ${value}\nLanguages: ${languages.join(", ")}`); |
| 103 | + } |
| 104 | + |
| 105 | + return value; |
| 106 | +} |
| 107 | + |
| 108 | +const usage = `Usage: |
| 109 | + format-code <language> [options] < input |
| 110 | +
|
| 111 | +Format the code from stdin and write the result to stdout. |
| 112 | +
|
| 113 | +Languages: |
| 114 | + ${languages.join(", ")} |
| 115 | +
|
| 116 | +Options: |
| 117 | + --print-width N Prettier print width (default: 100) |
| 118 | + --sql-dialect NAME SQL dialect (default: sql) |
| 119 | + -h, --help Show this help |
| 120 | +
|
| 121 | +SQL dialects: |
| 122 | + ${supportedDialects.join(", ")}`; |
| 123 | + |
| 124 | +type CommandValues = { |
| 125 | + "print-width"?: string; |
| 126 | + "sql-dialect"?: string; |
| 127 | +}; |
| 128 | + |
| 129 | +async function runFormat(language: Language, values: CommandValues) { |
| 130 | + const printWidth = checkPrintWidth(values["print-width"] ?? "100"); |
| 131 | + const sqlDialect = checkSqlDialect(values["sql-dialect"] ?? "sql"); |
| 132 | + const input = await readStdin(); |
| 133 | + |
| 134 | + process.stdout.write(format({ language, input, printWidth, sqlDialect })); |
| 135 | +} |
| 136 | + |
| 137 | +async function main() { |
| 138 | + const { values, positionals } = parseArgs({ |
| 139 | + allowPositionals: true, |
| 140 | + options: { |
| 141 | + "print-width": { type: "string" }, |
| 142 | + "sql-dialect": { type: "string" }, |
| 143 | + help: { type: "boolean", short: "h" }, |
94 | 144 | }, |
95 | | - }, |
96 | | - async run({ args }) { |
97 | | - const language = args.language; |
98 | | - const printWidth = parsePrintWidth(args["print-width"]); |
99 | | - const sqlDialect = args["sql-dialect"]; |
100 | | - |
101 | | - if (!isLanguage(language)) { |
102 | | - console.error(`Unknown language: ${language}`); |
103 | | - console.error(`Languages: ${languages.join(", ")}`); |
104 | | - process.exit(1); |
105 | | - } |
| 145 | + }); |
| 146 | + const [command, ...rest] = positionals; |
106 | 147 |
|
107 | | - if (printWidth === undefined) { |
108 | | - console.error(`Invalid print width: ${args["print-width"]}`); |
109 | | - console.error("Print width must be a positive integer"); |
110 | | - process.exit(1); |
111 | | - } |
| 148 | + if (values.help) { |
| 149 | + console.log(usage); |
| 150 | + return; |
| 151 | + } |
112 | 152 |
|
113 | | - if (!isSqlLanguage(sqlDialect)) { |
114 | | - console.error(`Unknown SQL dialect: ${sqlDialect}`); |
115 | | - console.error(`SQL dialects: ${supportedDialects.join(", ")}`); |
116 | | - process.exit(1); |
117 | | - } |
| 153 | + if (command === undefined) { |
| 154 | + fail(usage); |
| 155 | + } |
118 | 156 |
|
119 | | - try { |
120 | | - const input = await readStdin(); |
121 | | - const output = format({ language, input, printWidth, sqlDialect }); |
| 157 | + if (rest.length > 0) { |
| 158 | + fail(`Unexpected argument: ${rest[0]}`); |
| 159 | + } |
122 | 160 |
|
123 | | - process.stdout.write(output); |
124 | | - } catch (e) { |
125 | | - console.error(e instanceof Error ? e.message : e); |
126 | | - process.exit(1); |
127 | | - } |
128 | | - }, |
129 | | -}); |
| 161 | + await runFormat(checkLanguage(command), values); |
| 162 | +} |
130 | 163 |
|
131 | | -runMain(main); |
| 164 | +main().catch((e) => fail(e instanceof Error ? e.message : String(e))); |
0 commit comments