@@ -330,6 +330,10 @@ protected function askDatabaseType(): string
330330 try {
331331 while (true ) {
332332 $ key = fread (STDIN , 3 );
333+ if ($ key === '' || $ key === false ) {
334+ usleep (20000 );
335+ continue ;
336+ }
333337
334338 switch ($ key ) {
335339 case "\033[D " : // ←
@@ -537,16 +541,20 @@ protected function askRetryDatabaseConnection(): bool
537541 try {
538542 while (true ) {
539543 $ key = fread (STDIN , 3 );
544+ if ($ key === '' || $ key === false ) {
545+ usleep (20000 );
546+ continue ;
547+ }
540548
541549 switch ($ key ) {
542550 case "\033[D " : // ←
543551 case "\033[A " : // ↑
544- $ active = max (0 , $ active - 1 ) ? true : false ;
552+ $ active = max (0 , $ active - 1 );
545553 break ;
546554
547555 case "\033[C " : // →
548556 case "\033[B " : // ↓
549- $ active = min (count ($ options ) - 1 , $ active + 1 ) ? true : false ;
557+ $ active = min (count ($ options ) - 1 , $ active + 1 );
550558 break ;
551559
552560 case "\n" : // Enter
@@ -702,6 +710,10 @@ protected function askLanguage(): string
702710 try {
703711 while (true ) {
704712 $ key = fread (STDIN , 3 );
713+ if ($ key === '' || $ key === false ) {
714+ usleep (20000 );
715+ continue ;
716+ }
705717
706718 switch ($ key ) {
707719 case "\033[A " : // ↑
@@ -3068,7 +3080,8 @@ protected function setSttyMode(string $mode): void
30683080 return ;
30693081 }
30703082
3071- $ modeTokens = preg_split ('/ \\s+/ ' , $ mode ) ?: [];
3083+ $ normalized = $ this ->normalizeSttyMode ($ mode );
3084+ $ modeTokens = preg_split ('/ \\s+/ ' , $ normalized ) ?: [];
30723085 $ modeArgs = implode (' ' , array_map ('escapeshellarg ' , $ modeTokens ));
30733086
30743087 // Set stty mode and ensure it takes effect
@@ -3077,6 +3090,34 @@ protected function setSttyMode(string $mode): void
30773090 @shell_exec ('stty ' . $ modeArgs . ' 2>/dev/null ' );
30783091 }
30793092
3093+ protected function normalizeSttyMode (string $ mode ): string
3094+ {
3095+ $ mode = trim ($ mode );
3096+ if ($ mode === '' ) {
3097+ return $ mode ;
3098+ }
3099+
3100+ $ tokens = preg_split ('/ \\s+/ ' , $ mode ) ?: [];
3101+ $ hasIcanon = in_array ('-icanon ' , $ tokens , true );
3102+ if (!$ hasIcanon ) {
3103+ return implode (' ' , $ tokens );
3104+ }
3105+
3106+ // Ensure reads block in non-canonical mode (prevents busy-loop rendering on some systems).
3107+ $ hasMin = in_array ('min ' , $ tokens , true );
3108+ $ hasTime = in_array ('time ' , $ tokens , true );
3109+ if (!$ hasMin ) {
3110+ $ tokens [] = 'min ' ;
3111+ $ tokens [] = '1 ' ;
3112+ }
3113+ if (!$ hasTime ) {
3114+ $ tokens [] = 'time ' ;
3115+ $ tokens [] = '0 ' ;
3116+ }
3117+
3118+ return implode (' ' , $ tokens );
3119+ }
3120+
30803121 protected function removeDirectory (string $ dir ): void
30813122 {
30823123 if (!is_dir ($ dir )) {
0 commit comments