Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions packages/rstack/src/fmt/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface ParsedFmtCLIArgs {
mode: FmtMode;
patterns: string[];
ignorePaths: string[];
noErrorOnUnmatchedPattern: boolean;
maxWorkers?: number;
help: boolean;
/** Path the stdin content is formatted as; it need not exist on disk. */
Expand All @@ -26,13 +27,14 @@ ${color.yellow(' $ rs fmt [options] [files/globs...]')}
Format files with Prettier.

${color.cyan('Options')}:
--write Write formatted files in place (default)
--check Check whether files are formatted
--list-different Print paths of unformatted files
--ignore-path <path> Path to an additional ignore file (repeatable)
--parallel-workers <count> Number of parallel workers
--stdin-filepath <path> Format stdin as if it were saved at <path>
-h, --help Display this help message`;
--write Write formatted files in place (default)
--check Check whether files are formatted
--list-different Print paths of unformatted files
--ignore-path <path> Path to an additional ignore file (repeatable)
--no-error-on-unmatched-pattern Do not error when no files match
--parallel-workers <count> Number of parallel workers
--stdin-filepath <path> Format stdin as if it were saved at <path>
-h, --help Display this help message`;

const parseMaxWorkers = (
kebabValue: string | undefined,
Expand Down Expand Up @@ -60,6 +62,8 @@ const parseFmtCLIArgs = (args: string[]): ParsedFmtCLIArgs => {
'list-different': { type: 'boolean' },
listDifferent: { type: 'boolean' },
'ignore-path': { type: 'string', multiple: true },
'no-error-on-unmatched-pattern': { type: 'boolean' },
noErrorOnUnmatchedPattern: { type: 'boolean' },
'parallel-workers': { type: 'string' },
parallelWorkers: { type: 'string' },
'stdin-filepath': { type: 'string' },
Expand All @@ -77,6 +81,8 @@ const parseFmtCLIArgs = (args: string[]): ParsedFmtCLIArgs => {
}

const mode = values.check ? 'check' : listDifferent ? 'list-different' : 'write';
const noErrorOnUnmatchedPattern =
values['no-error-on-unmatched-pattern'] ?? values.noErrorOnUnmatchedPattern ?? false;
const maxWorkers = parseMaxWorkers(values['parallel-workers'], values.parallelWorkers);
const stdinFilepath = values['stdin-filepath'] ?? values.stdinFilepath;

Expand All @@ -96,6 +102,7 @@ const parseFmtCLIArgs = (args: string[]): ParsedFmtCLIArgs => {
mode,
patterns: positionals,
ignorePaths: values['ignore-path'] ?? [],
noErrorOnUnmatchedPattern,
maxWorkers,
help: values.help ?? false,
stdinFilepath,
Expand Down Expand Up @@ -214,7 +221,15 @@ const runFmtCLI = async (args: string[]): Promise<void> => {
// Argument errors are reported like every other failure so that a single
// exit code identifies "rs fmt refused to run".
try {
const { help, ignorePaths, maxWorkers, mode, patterns, stdinFilepath } = parseFmtCLIArgs(args);
const {
help,
ignorePaths,
maxWorkers,
mode,
noErrorOnUnmatchedPattern,
patterns,
stdinFilepath,
} = parseFmtCLIArgs(args);
if (help) {
logger.log(fmtHelpMessage);
return;
Expand Down Expand Up @@ -243,6 +258,9 @@ const runFmtCLI = async (args: string[]): Promise<void> => {
});

if (files.length === 0) {
if (noErrorOnUnmatchedPattern) {
return;
}
const targets = (patterns.length ? patterns : ['.'])
.map((pattern) => color.cyan(JSON.stringify(pattern)))
.join(', ');
Expand Down
13 changes: 13 additions & 0 deletions packages/rstack/tests/cli/fmt/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,3 +597,16 @@ test('returns exit code 2 when no files match', () => {
expect(result.stderr).not.toContain('\n at ');
}
});

test.each(['--no-error-on-unmatched-pattern', '--noErrorOnUnmatchedPattern'])(
'allows no files to match with %s',
(option) => {
for (const modeArgs of [[], ['--check'], ['--list-different']]) {
const result = runFmt([...modeArgs, option, 'missing/**/*.ts']);

expect(result.status).toBe(0);
expect(result.stdout).toBe('');
expect(result.stderr).toBe('');
}
},
);
15 changes: 8 additions & 7 deletions packages/rstack/tests/fmt/__snapshots__/cli.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ exports[`provides command help 1`] = `
Format files with Prettier.

Options:
--write Write formatted files in place (default)
--check Check whether files are formatted
--list-different Print paths of unformatted files
--ignore-path <path> Path to an additional ignore file (repeatable)
--parallel-workers <count> Number of parallel workers
--stdin-filepath <path> Format stdin as if it were saved at <path>
-h, --help Display this help message"
--write Write formatted files in place (default)
--check Check whether files are formatted
--list-different Print paths of unformatted files
--ignore-path <path> Path to an additional ignore file (repeatable)
--no-error-on-unmatched-pattern Do not error when no files match
--parallel-workers <count> Number of parallel workers
--stdin-filepath <path> Format stdin as if it were saved at <path>
-h, --help Display this help message"
`;
14 changes: 14 additions & 0 deletions packages/rstack/tests/fmt/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test('uses write mode by default', () => {
mode: 'write',
patterns: [],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: undefined,
help: false,
});
Expand All @@ -37,6 +38,7 @@ test.each([
mode,
patterns: [],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: undefined,
help: false,
});
Expand All @@ -49,6 +51,7 @@ test.each(['--parallel-workers', '--parallelWorkers'])(
mode: 'write',
patterns: [],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: 3,
help: false,
});
Expand All @@ -75,6 +78,7 @@ test('preserves file paths and globs', () => {
mode: 'check',
patterns,
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: undefined,
help: false,
});
Expand All @@ -85,6 +89,7 @@ test('treats arguments after the terminator as paths', () => {
mode: 'check',
patterns: ['--write', '--help'],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: undefined,
help: false,
});
Expand All @@ -101,11 +106,19 @@ test('collects repeated ignore paths', () => {
).toEqual(['.prettierignore', 'config/format.ignore']);
});

test.each(['--no-error-on-unmatched-pattern', '--noErrorOnUnmatchedPattern'])(
'parses %s',
(option) => {
expect(parseFmtCLIArgs([option]).noErrorOnUnmatchedPattern).toBe(true);
},
);

test.each(['--stdin-filepath', '--stdinFilepath'])('parses %s', (option) => {
expect(parseFmtCLIArgs([option, 'src/index.ts'])).toEqual({
mode: 'write',
patterns: [],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: undefined,
help: false,
stdinFilepath: 'src/index.ts',
Expand All @@ -117,6 +130,7 @@ test('accepts a worker count with --stdin-filepath', () => {
mode: 'write',
patterns: [],
ignorePaths: [],
noErrorOnUnmatchedPattern: false,
maxWorkers: 2,
help: false,
stdinFilepath: 'index.ts',
Expand Down
20 changes: 15 additions & 5 deletions website/docs/en/guide/cli/fmt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ rs fmt . --check

The command uses the following exit codes:

| Code | Meaning |
| ---- | --------------------------------------------------------- |
| `0` | All matched files are formatted. |
| `1` | One or more matched files have formatting issues. |
| `2` | `rs fmt` could not run or encountered a formatting error. |
| Code | Meaning |
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0` | All matched files are formatted; or no supported files matched, but [`--no-error-on-unmatched-pattern`](#--no-error-on-unmatched-pattern) was specified. |
| `1` | One or more matched files have formatting issues. |
| `2` | `rs fmt` could not run or encountered a formatting error. |

### `-h, --help`

Expand Down Expand Up @@ -97,6 +97,16 @@ rs fmt . --list-different

The option uses the same exit codes as `--check` and cannot be combined with `--write` or `--check`.

### `--no-error-on-unmatched-pattern`

Exit successfully without diagnostics when no supported files match the provided paths or globs, including when all matching files are ignored:

```bash
rs fmt --no-error-on-unmatched-pattern 'src/**/*.ts'
```

For example, a pre-commit script may always run `rs fmt`, even when the staged changes contain no supported files. This option lets the command exit successfully in that case instead of blocking the commit.

### `--parallel-workers <count>`

Set the maximum number of formatting workers to a positive integer:
Expand Down
20 changes: 15 additions & 5 deletions website/docs/zh/guide/cli/fmt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ rs fmt . --check

该命令使用以下退出状态码:

| 状态码 | 含义 |
| ------ | ------------------------------------------- |
| `0` | 所有匹配的文件均已格式化 |
| `1` | 一个或多个匹配的文件存在格式问题。 |
| `2` | `rs fmt` 无法运行或在格式化过程中遇到错误。 |
| 状态码 | 含义 |
| ------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `0` | 所有匹配的文件均已格式化;或未匹配到支持的文件,但指定了 [`--no-error-on-unmatched-pattern`](#--no-error-on-unmatched-pattern)。 |
| `1` | 一个或多个匹配的文件存在格式问题。 |
| `2` | `rs fmt` 无法运行或在格式化过程中遇到错误。 |

### `-h, --help`

Expand Down Expand Up @@ -97,6 +97,16 @@ rs fmt . --list-different

此选项与 `--check` 使用相同的退出状态码,且不能与 `--write` 或 `--check` 同时使用。

### `--no-error-on-unmatched-pattern`

如果传入的路径或 glob 没有匹配任何支持的文件(包括所有匹配文件均被忽略的情况),则不输出诊断信息并成功退出:

```bash
rs fmt --no-error-on-unmatched-pattern 'src/**/*.ts'
```

例如,pre-commit 脚本可能会始终运行 `rs fmt`,即使暂存的改动中没有支持的文件。此选项可让命令在这种情况下成功退出,避免阻止提交。

### `--parallel-workers <count>`

将格式化 worker 的最大数量设置为正整数:
Expand Down