@@ -107,12 +107,41 @@ func (f *Formatter) Apply(ctx context.Context, files []*walk.File) error {
107107 return nil
108108 }
109109
110- // append paths to the args
111- for _ , file := range files {
112- if file .TmpPath != "" {
113- args = append (args , file .TmpPath )
114- } else {
115- args = append (args , file .RelPath )
110+ onlyFile := (* walk .File )(nil )
111+ if len (files ) == 1 {
112+ onlyFile = files [0 ]
113+ }
114+
115+ // If we have a TmpPath, that means we're formatting something other than the file's RelPath
116+ // mode". If the underlying formatter has its own stdin mode support, then
117+ // we can invoke it in a way where we pass along the files's RelPath as an
118+ // "advisory path", which may affect the behavior of the formatter.
119+ useStdinMode := files [0 ].TmpPath != "" && f .config .StdinOptions != nil
120+
121+ stdin := (* os .File )(nil )
122+
123+ if useStdinMode {
124+ // Feed the file to the formatter via stdin.
125+ tmpFile , err := os .Open (onlyFile .TmpPath )
126+ if err != nil {
127+ panic (err )
128+ }
129+ defer tmpFile .Close ()
130+
131+ stdin = tmpFile
132+
133+ replacer := strings .NewReplacer ("$path" , onlyFile .RelPath )
134+ for _ , arg := range f .config .StdinOptions {
135+ args = append (args , replacer .Replace (arg ))
136+ }
137+ } else {
138+ // append paths to the args
139+ for _ , file := range files {
140+ if file .TmpPath != "" {
141+ args = append (args , file .TmpPath )
142+ } else {
143+ args = append (args , file .RelPath )
144+ }
116145 }
117146 }
118147
@@ -123,11 +152,13 @@ func (f *Formatter) Apply(ctx context.Context, files []*walk.File) error {
123152 return cmd .Process .Signal (os .Interrupt )
124153 }
125154 cmd .Dir = f .workingDir
155+ cmd .Stdin = stdin
126156
127157 // log out the command being executed
128158 f .log .Debugf ("executing: %s" , cmd .String ())
129159
130- if out , err := cmd .CombinedOutput (); err != nil {
160+ out , err := cmd .CombinedOutput ()
161+ if err != nil {
131162 f .log .Errorf ("failed to apply with options '%v': %s" , f .config .Options , err )
132163
133164 if len (out ) > 0 {
@@ -137,6 +168,16 @@ func (f *Formatter) Apply(ctx context.Context, files []*walk.File) error {
137168 return fmt .Errorf ("formatter '%s' with options '%v' failed to apply: %w" , f .config .Command , f .config .Options , err )
138169 }
139170
171+ // In stdin mode, the formatter won't write to the filesystem, it instead
172+ // prints the formatted file to stdout. Take that output and write it back
173+ // to the input file (`TmpPath`).
174+ if useStdinMode {
175+ path := onlyFile .TmpPath
176+ if err = os .WriteFile (path , out , 0o600 ); err != nil {
177+ return fmt .Errorf ("couldn't write to '%s'" , path )
178+ }
179+ }
180+
140181 f .log .Infof ("%v file(s) processed in %v" , len (files ), time .Since (start ))
141182
142183 return nil
0 commit comments