@@ -106,6 +106,15 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
106106
107107 /** @var int Current indentation level. */
108108 protected int $ indentLevel ;
109+ /** @var string String for single level of indentation */
110+ private string $ indent ;
111+ /** @var int Width in spaces to indent by. */
112+ private int $ indentWidth ;
113+ /** @var bool Whether to use tab indentation. */
114+ private bool $ useTabs ;
115+ /** @var int Width in spaces of one tab. */
116+ private int $ tabWidth = 4 ;
117+
109118 /** @var string Newline style. Does not include current indentation. */
110119 protected string $ newline ;
111120 /** @var string Newline including current indentation. */
@@ -170,12 +179,14 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
170179 * PHP version while specifying an older target (but the result will
171180 * of course not be compatible with the older version in that case).
172181 * * string $newline: The newline style to use. Should be "\n" (default) or "\r\n".
182+ * * string $indent: The indentation to use. Should either be all spaces or a single
183+ * tab. Defaults to four spaces (" ").
173184 * * bool $shortArraySyntax: Whether to use [] instead of array() as the default array
174185 * syntax, if the node does not specify a format. Defaults to whether
175186 * the phpVersion support short array syntax.
176187 *
177188 * @param array{
178- * phpVersion?: PhpVersion, newline?: string, shortArraySyntax?: bool
189+ * phpVersion?: PhpVersion, newline?: string, indent?: string, shortArraySyntax?: bool
179190 * } $options Dictionary of formatting options
180191 */
181192 public function __construct (array $ options = []) {
@@ -190,6 +201,17 @@ public function __construct(array $options = []) {
190201 $ options ['shortArraySyntax ' ] ?? $ this ->phpVersion ->supportsShortArraySyntax ();
191202 $ this ->docStringEndToken =
192203 $ this ->phpVersion ->supportsFlexibleHeredoc () ? null : '_DOC_STRING_END_ ' . mt_rand ();
204+
205+ $ this ->indent = $ indent = $ options ['indent ' ] ?? ' ' ;
206+ if ($ indent === "\t" ) {
207+ $ this ->useTabs = true ;
208+ $ this ->indentWidth = $ this ->tabWidth ;
209+ } elseif ($ indent === \str_repeat (' ' , \strlen ($ indent ))) {
210+ $ this ->useTabs = false ;
211+ $ this ->indentWidth = \strlen ($ indent );
212+ } else {
213+ throw new \LogicException ('Option "indent" must either be all spaces or a single tab ' );
214+ }
193215 }
194216
195217 /**
@@ -208,24 +230,29 @@ protected function resetState(): void {
208230 */
209231 protected function setIndentLevel (int $ level ): void {
210232 $ this ->indentLevel = $ level ;
211- $ this ->nl = $ this ->newline . \str_repeat (' ' , $ level );
233+ if ($ this ->useTabs ) {
234+ $ tabs = \intdiv ($ level , $ this ->tabWidth );
235+ $ spaces = $ level % $ this ->tabWidth ;
236+ $ this ->nl = $ this ->newline . \str_repeat ("\t" , $ tabs ) . \str_repeat (' ' , $ spaces );
237+ } else {
238+ $ this ->nl = $ this ->newline . \str_repeat (' ' , $ level );
239+ }
212240 }
213241
214242 /**
215243 * Increase indentation level.
216244 */
217245 protected function indent (): void {
218- $ this ->indentLevel += 4 ;
219- $ this ->nl .= ' ' ;
246+ $ this ->indentLevel += $ this -> indentWidth ;
247+ $ this ->nl .= $ this -> indent ;
220248 }
221249
222250 /**
223251 * Decrease indentation level.
224252 */
225253 protected function outdent (): void {
226- assert ($ this ->indentLevel >= 4 );
227- $ this ->indentLevel -= 4 ;
228- $ this ->nl = $ this ->newline . str_repeat (' ' , $ this ->indentLevel );
254+ assert ($ this ->indentLevel >= $ this ->indentWidth );
255+ $ this ->setIndentLevel ($ this ->indentLevel - $ this ->indentWidth );
229256 }
230257
231258 /**
@@ -537,7 +564,7 @@ public function printFormatPreserving(array $stmts, array $origStmts, array $ori
537564 $ this ->initializeModifierChangeMap ();
538565
539566 $ this ->resetState ();
540- $ this ->origTokens = new TokenStream ($ origTokens );
567+ $ this ->origTokens = new TokenStream ($ origTokens, $ this -> tabWidth );
541568
542569 $ this ->preprocessNodes ($ stmts );
543570
0 commit comments