@@ -109,6 +109,8 @@ private function doAsk(OutputInterface $output, Question $question)
109
109
$ inputStream = $ this ->inputStream ?: STDIN ;
110
110
$ autocomplete = $ question ->getAutocompleterCallback ();
111
111
112
+ $ cursor = new Cursor ($ output );
113
+
112
114
if (null === $ autocomplete || !Terminal::hasSttyAvailable ()) {
113
115
$ ret = false ;
114
116
if ($ question ->isHidden ()) {
@@ -123,10 +125,80 @@ private function doAsk(OutputInterface $output, Question $question)
123
125
}
124
126
125
127
if (false === $ ret ) {
126
- $ ret = fgets ($ inputStream , 4096 );
127
- if (false === $ ret ) {
128
- throw new MissingInputException ('Aborted. ' );
128
+ if (!Terminal::hasSttyAvailable ()) {
129
+ $ ret = fgets ($ inputStream , 4096 );
130
+ if (false === $ ret ) {
131
+ throw new MissingInputException ('Aborted. ' );
132
+ }
133
+ } else {
134
+ $ sttyMode = shell_exec ('stty -g ' );
135
+
136
+ shell_exec ('stty -icanon -echo ' );
137
+
138
+ $ k = null ;
139
+ $ string = '' ;
140
+
141
+ [$ x ] = $ cursor ->getCurrentPosition ();
142
+
143
+ while (10 !== $ k && 0 !== $ k ) {
144
+ [$ pos ] = $ cursor ->getCurrentPosition ();
145
+ $ pos -= $ x ;
146
+
147
+ $ ret = fgetc ($ inputStream );
148
+ if (false === $ ret && '' === $ string ) {
149
+ shell_exec (sprintf ('stty %s ' , $ sttyMode ));
150
+ throw new MissingInputException ('Aborted. ' );
151
+ }
152
+
153
+ $ k = ord ($ ret );
154
+
155
+ if (27 === $ k ) {
156
+ fgetc ($ inputStream );
157
+ $ k = ord (fgetc ($ inputStream ));
158
+
159
+ switch (true ) {
160
+ case 67 === $ k && $ pos < self ::strlen ($ string ):
161
+ $ cursor ->moveRight ();
162
+ break ;
163
+ case 68 === $ k && $ pos > 0 :
164
+ $ cursor ->moveLeft ();
165
+ break ;
166
+ case 51 === $ k && $ pos >= 0 :
167
+ $ string = self ::substr ($ string , 0 , $ pos ).self ::substr ($ string , $ pos + 1 );
168
+ $ cursor ->clearLineAfter ();
169
+ $ output ->write (self ::substr ($ string , $ pos ));
170
+ $ cursor ->moveToColumn ($ pos + $ x );
171
+ break ;
172
+ }
173
+ } else if (127 === $ k ) {
174
+ if ($ pos > 0 ) {
175
+ $ string = self ::substr ($ string , 0 , $ pos - 1 ).self ::substr ($ string , $ pos );
176
+
177
+ $ cursor ->moveToColumn ($ x );
178
+ $ output ->write ($ string );
179
+ $ cursor ->clearLineAfter ()
180
+ ->moveToColumn (($ pos + $ x ) - 1 );
181
+ }
182
+ } else if ($ k >= 32 && $ k <= 126 ) {
183
+ if ($ pos > 0 && $ pos < \strlen ($ string )) {
184
+ $ string = self ::substr ($ string , 0 , $ pos ).$ ret .self ::substr ($ string , $ pos );
185
+ $ output ->write ($ ret .self ::substr ($ string , $ pos + 1 ));
186
+ $ cursor ->clearLineAfter ()
187
+ ->moveToColumn ($ pos + $ x + 1 );
188
+ } else {
189
+ $ string .= $ ret ;
190
+ $ output ->write ($ ret );
191
+ }
192
+ } else {
193
+ $ output ->write ($ ret );
194
+ }
195
+ }
196
+
197
+ shell_exec (sprintf ('stty %s ' , $ sttyMode ));
198
+
199
+ $ ret = $ string ;
129
200
}
201
+
130
202
if ($ question ->isTrimmable ()) {
131
203
$ ret = trim ($ ret );
132
204
}
0 commit comments