Skip to content

Commit 2c33b79

Browse files
committed
Use glob pattern for formatting of files
1 parent 1ff84de commit 2c33b79

3 files changed

Lines changed: 138 additions & 22 deletions

File tree

packages/septic/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"license": "MIT",
2323
"dependencies": {
2424
"ajv": "^8.17.1",
25+
"glob": "^13.0.0",
2526
"js-yaml": "^4.1.1",
2627
"vscode-languageserver-textdocument": "^1.0.12",
2728
"yargs": "^18.0.0"

packages/septic/src/cli/format.ts

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import yargs, { CommandModule } from "yargs";
77
import { TextDocument, TextEdit } from "vscode-languageserver-textdocument";
88
import * as fs from "fs";
99
import * as path from "path";
10+
import { glob } from "glob";
1011
import { SepticCnfg } from "../cnfg";
1112
import { SepticCnfgFormatter } from "../formatter";
1213
import { createDocumentFromFile } from "../configProvider";
@@ -74,67 +75,131 @@ function checkFormatting(
7475
return originalContent === formattedContent;
7576
}
7677

77-
async function handler(options: FormatOptions): Promise<void> {
78-
const document = await createDocumentFromFile(options.file);
78+
async function formatSingleFile(
79+
filePath: string,
80+
check: boolean,
81+
outputPath?: string,
82+
): Promise<{ needsFormatting: boolean; filePath: string }> {
83+
const document = await createDocumentFromFile(filePath);
7984
const originalContent = document.getText();
8085

8186
const edits = formatSepticConfig(document);
8287
const formattedContent = applyTextEdits(originalContent, edits);
8388

84-
if (options.check) {
85-
const isFormatted = checkFormatting(originalContent, formattedContent);
89+
const isFormatted = checkFormatting(originalContent, formattedContent);
90+
91+
if (check) {
8692
if (isFormatted) {
87-
console.log(`✓ ${options.file} is formatted correctly`);
88-
process.exit(0);
93+
console.log(`✓ ${filePath} is formatted correctly`);
8994
} else {
90-
console.log(`✗ ${options.file} needs formatting`);
91-
process.exit(1);
95+
console.log(`✗ ${filePath} needs formatting`);
9296
}
97+
return { needsFormatting: !isFormatted, filePath };
9398
}
9499

95-
const outputPath = options.output || options.file;
96-
97-
const outputDir = path.dirname(outputPath);
100+
const actualOutputPath = outputPath || filePath;
101+
const outputDir = path.dirname(actualOutputPath);
98102
if (!fs.existsSync(outputDir)) {
99103
fs.mkdirSync(outputDir, { recursive: true });
100104
}
101105

102-
fs.writeFileSync(outputPath, formattedContent, "utf-8");
106+
fs.writeFileSync(actualOutputPath, formattedContent, "utf-8");
103107

104-
if (options.output) {
105-
console.log(`✓ Formatted file saved to: ${outputPath}`);
108+
if (outputPath) {
109+
console.log(`✓ Formatted file saved to: ${actualOutputPath}`);
106110
} else {
107-
console.log(`✓ Formatted: ${options.file}`);
111+
console.log(`✓ Formatted: ${filePath}`);
112+
}
113+
114+
return { needsFormatting: false, filePath };
115+
}
116+
117+
async function handler(options: FormatOptions): Promise<void> {
118+
// Ensure the pattern includes .cnfg extension
119+
let pattern = options.file;
120+
if (!pattern.endsWith(".cnfg")) {
121+
pattern = pattern + ".cnfg";
122+
}
123+
124+
// Find all files matching the pattern
125+
const files = await glob(pattern, {
126+
absolute: true,
127+
nodir: true,
128+
windowsPathsNoEscape: true,
129+
});
130+
131+
if (files.length === 0) {
132+
// Try treating it as a literal file path
133+
if (fs.existsSync(pattern)) {
134+
files.push(path.resolve(pattern));
135+
} else {
136+
console.error(`No files found matching pattern: ${pattern}`);
137+
process.exit(1);
138+
}
139+
}
140+
141+
// If output is specified and multiple files matched, this is an error
142+
if (options.output && files.length > 1) {
143+
console.error(
144+
`Error: Cannot specify --output when multiple files match the pattern`,
145+
);
146+
process.exit(1);
147+
}
148+
149+
const results = await Promise.all(
150+
files.map((file) =>
151+
formatSingleFile(file, options.check || false, options.output),
152+
),
153+
);
154+
155+
if (options.check) {
156+
const filesNeedingFormatting = results.filter((r) => r.needsFormatting);
157+
if (filesNeedingFormatting.length > 0) {
158+
console.log(
159+
`\n${filesNeedingFormatting.length} file(s) need formatting`,
160+
);
161+
process.exit(1);
162+
} else {
163+
console.log(
164+
`\nAll ${files.length} file(s) are formatted correctly`,
165+
);
166+
process.exit(0);
167+
}
108168
}
109169
}
110170

111171
export const formatCommand: CommandModule<object, FormatOptions> = {
112172
command: "format <file>",
113-
describe: "Format a Septic config file",
173+
describe: "Format Septic config file(s) matching a pattern",
114174
builder: (yargs) => {
115175
return yargs
116176
.positional("file", {
117177
type: "string",
118-
description: "Path to Septic config file to format",
178+
description:
179+
"Path or glob pattern to Septic config file(s) to format",
119180
demandOption: true,
120181
})
121182
.option("check", {
122183
alias: "c",
123184
type: "boolean",
124185
description:
125-
"Check if the file is formatted without modifying it",
186+
"Check if file(s) are formatted without modifying them",
126187
default: false,
127188
})
128189
.option("output", {
129190
alias: "o",
130191
type: "string",
131192
description:
132-
"Output path for formatted file (default: overwrites input file)",
193+
"Output path for formatted file (only works with single file)",
133194
})
134-
.example("$0 format config.cnfg", "Format a config file")
195+
.example("$0 format config.cnfg", "Format a single config file")
196+
.example(
197+
"$0 format '**/*.cnfg'",
198+
"Format all .cnfg files recursively",
199+
)
135200
.example(
136-
"$0 format config.cnfg --check",
137-
"Check if a config file is formatted",
201+
"$0 format '**/*.cnfg' --check",
202+
"Check if all .cnfg files are formatted",
138203
)
139204
.example(
140205
"$0 format config.cnfg --output formatted.cnfg",

pnpm-lock.yaml

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)