@@ -6,13 +6,16 @@ import { loadRstackConfig } from '../config.ts';
66import { resolveFmtConfig } from './config.ts' ;
77import { discoverFmtFiles } from './discovery.ts' ;
88import { runFmtFiles } from './runner.ts' ;
9- import type { FmtMode , FmtRunResult } from './types.ts' ;
9+ import { runFmtStdin } from './stdin.ts' ;
10+ import type { FmtMode , FmtRunResult , ResolvedFmtConfig } from './types.ts' ;
1011
1112interface ParsedFmtCLIArgs {
1213 mode : FmtMode ;
1314 patterns : string [ ] ;
1415 maxWorkers ?: number ;
1516 help : boolean ;
17+ /** Path the stdin content is formatted as; it need not exist on disk. */
18+ stdinFilepath ?: string ;
1619}
1720
1821const fmtHelpMessage : string = `Rstack v${ RSTACK_VERSION }
@@ -27,6 +30,7 @@ ${color.cyan('Options')}:
2730 --check Check whether files are formatted
2831 --list-different Print paths of unformatted files
2932 --parallel-workers <count> Number of parallel workers
33+ --stdin-filepath <path> Format stdin as if it were saved at <path>
3034 -h, --help Display this help message` ;
3135
3236const parseMaxWorkers = (
@@ -56,6 +60,8 @@ const parseFmtCLIArgs = (args: string[]): ParsedFmtCLIArgs => {
5660 listDifferent : { type : 'boolean' } ,
5761 'parallel-workers' : { type : 'string' } ,
5862 parallelWorkers : { type : 'string' } ,
63+ 'stdin-filepath' : { type : 'string' } ,
64+ stdinFilepath : { type : 'string' } ,
5965 help : { type : 'boolean' , short : 'h' } ,
6066 } ,
6167 allowPositionals : true ,
@@ -70,12 +76,26 @@ const parseFmtCLIArgs = (args: string[]): ParsedFmtCLIArgs => {
7076
7177 const mode = values . check ? 'check' : listDifferent ? 'list-different' : 'write' ;
7278 const maxWorkers = parseMaxWorkers ( values [ 'parallel-workers' ] , values . parallelWorkers ) ;
79+ const stdinFilepath = values [ 'stdin-filepath' ] ?? values . stdinFilepath ;
80+
81+ if ( stdinFilepath !== undefined ) {
82+ if ( modes . length > 0 ) {
83+ throw new Error (
84+ 'The --stdin-filepath option cannot be used with --write, --check, or --list-different.' ,
85+ ) ;
86+ }
87+
88+ if ( positionals . length > 0 ) {
89+ throw new Error ( 'The --stdin-filepath option cannot be used with file arguments.' ) ;
90+ }
91+ }
7392
7493 return {
7594 mode,
7695 patterns : positionals ,
7796 maxWorkers,
7897 help : values . help ?? false ,
98+ stdinFilepath,
7999 } ;
80100} ;
81101
@@ -174,23 +194,35 @@ const logFmtResult = (
174194 }
175195} ;
176196
177- const runFmtCLI = async ( args : string [ ] ) : Promise < void > => {
178- const { help, maxWorkers, mode, patterns } = parseFmtCLIArgs ( args ) ;
179- if ( help ) {
180- logger . log ( fmtHelpMessage ) ;
181- return ;
182- }
197+ const loadFmtConfig = async ( cwd : string ) : Promise < ResolvedFmtConfig > => {
198+ const { configs, filePath } = await loadRstackConfig ( ) ;
183199
200+ return resolveFmtConfig ( {
201+ definition : configs . fmt ,
202+ configFilePath : filePath ,
203+ cwd,
204+ } ) ;
205+ } ;
206+
207+ const runFmtCLI = async ( args : string [ ] ) : Promise < void > => {
184208 const cwd = process . cwd ( ) ;
185209 const startTime = performance . now ( ) ;
186210
211+ // Argument errors are reported like every other failure so that a single
212+ // exit code identifies "rs fmt refused to run".
187213 try {
188- const { configs, filePath } = await loadRstackConfig ( ) ;
189- const config = await resolveFmtConfig ( {
190- definition : configs . fmt ,
191- configFilePath : filePath ,
192- cwd,
193- } ) ;
214+ const { help, maxWorkers, mode, patterns, stdinFilepath } = parseFmtCLIArgs ( args ) ;
215+ if ( help ) {
216+ logger . log ( fmtHelpMessage ) ;
217+ return ;
218+ }
219+
220+ if ( stdinFilepath !== undefined ) {
221+ await runFmtStdin ( { filepath : stdinFilepath , cwd, loadConfig : ( ) => loadFmtConfig ( cwd ) } ) ;
222+ return ;
223+ }
224+
225+ const config = await loadFmtConfig ( cwd ) ;
194226 const files = await discoverFmtFiles ( { cwd, patterns, config } ) ;
195227
196228 if ( files . length === 0 ) {
0 commit comments