@@ -86,10 +86,13 @@ public function ask(OutputInterface $output, $question, $default = null, array $
8686 }
8787 $ ret = trim ($ ret );
8888 } else {
89- $ i = 0 ;
90- $ currentMatched = false ;
9189 $ ret = '' ;
9290
91+ $ i = 0 ;
92+ $ matches = array ();
93+ $ numMatches = 0 ;
94+ $ ofs = 0 ;
95+
9396 // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
9497 shell_exec ('stty -icanon -echo ' );
9598
@@ -98,25 +101,9 @@ public function ask(OutputInterface $output, $question, $default = null, array $
98101
99102 // Read a keypress
100103 while ($ c = fread ($ inputStream , 1 )) {
101- // Did we read an escape sequence?
102- if ("\033" === $ c ) {
103- $ c .= fread ($ inputStream , 2 );
104-
105- // Escape sequences for arrow keys
106- if ('A ' === $ c [2 ] || 'B ' === $ c [2 ] || 'C ' === $ c [2 ] || 'D ' === $ c [2 ]) {
107- // todo
108- }
109-
110- continue ;
111- }
112-
113104 // Backspace Character
114105 if ("\177" === $ c ) {
115- if ($ i === 0 ) {
116- continue ;
117- }
118-
119- if (false === $ currentMatched ) {
106+ if (0 === $ numMatches && 0 !== $ i ) {
120107 $ i --;
121108 // Move cursor backwards
122109 $ output ->write ("\033[1D " );
@@ -126,63 +113,77 @@ public function ask(OutputInterface $output, $question, $default = null, array $
126113 $ output ->write ("\033[K " );
127114 $ ret = substr ($ ret , 0 , $ i );
128115
129- $ currentMatched = false ;
116+ $ matches = array ();
117+ $ numMatches = 0 ;
130118
131119 continue ;
132120 }
133121
134- if ("\t" === $ c || "\n" === $ c ) {
135- if (false !== $ currentMatched ) {
136- // Echo out completed match
137- $ output ->write (substr ($ autocomplete [$ currentMatched ], strlen ($ ret )));
138- $ ret = $ autocomplete [$ currentMatched ];
139- $ i = strlen ($ ret );
140- }
122+ // Did we read an escape sequence?
123+ if ("\033" === $ c ) {
124+ $ c .= fread ($ inputStream , 2 );
125+
126+ if ('A ' === $ c [2 ] || 'B ' === $ c [2 ]) {
127+ if (0 === $ i ) {
128+ $ matches = $ autocomplete ;
129+ $ numMatches = count ($ matches );
130+ }
141131
142- if ("\n" === $ c ) {
143- $ output ->write ($ c );
144- break ;
132+ if (0 === $ numMatches ) {
133+ continue ;
134+ }
135+
136+ $ ofs += ('A ' === $ c [2 ]) ? -1 : 1 ;
137+ $ ofs = ($ numMatches + $ ofs ) % $ numMatches ;
145138 }
139+ } else if (ord ($ c ) < 32 ) {
140+ if ("\t" === $ c || "\n" === $ c ) {
141+ if ($ numMatches > 0 ) {
142+ $ ret = $ matches [$ ofs ];
143+ // Echo out completed match
144+ $ output ->write (substr ($ ret , $ i ));
145+ $ i = strlen ($ ret );
146+ }
146147
147- $ currentMatched = false ;
148+ if ("\n" === $ c ) {
149+ $ output ->write ($ c );
150+ break ;
151+ }
148152
149- continue ;
150- }
153+ $ matches = array ();
154+ $ numMatches = 0 ;
155+ }
151156
152- if (ord ($ c ) < 32 ) {
153157 continue ;
154- }
155-
156- $ output ->write ($ c );
157- $ ret .= $ c ;
158- $ i ++;
158+ } else {
159+ $ output ->write ($ c );
160+ $ ret .= $ c ;
161+ $ i ++;
159162
160- // Erase characters from cursor to end of line
161- $ output ->write ("\033[K " );
163+ $ matches = array ();
164+ $ numMatches = 0 ;
165+ $ ofs = 0 ;
162166
163- foreach ($ autocomplete as $ j => $ value ) {
164- // Get a substring of the current autocomplete item based on number of chars typed (e.g. AcmeDemoBundle = Acme)
165- $ matchTest = substr ($ value , 0 , $ i );
167+ foreach ($ autocomplete as $ value ) {
168+ // Get a substring of the current autocomplete item based on number of chars typed (e.g. AcmeDemoBundle = Acme)
169+ $ matchTest = substr ($ value , 0 , $ i );
166170
167- if ($ ret === $ matchTest ) {
168- if ($ i === strlen ($ value )) {
169- $ currentMatched = false ;
170- break ;
171+ if ($ ret === $ matchTest && $ i !== strlen ($ value )) {
172+ $ matches [$ numMatches ++] = $ value ;
171173 }
172-
173- // Save cursor position
174- $ output ->write ("\0337 " );
175-
176- $ output ->write ('<hl> ' . substr ($ value , $ i ) . '</hl> ' );
177-
178- // Restore cursor position
179- $ output ->write ("\0338 " );
180-
181- $ currentMatched = $ j ;
182- break ;
183174 }
175+ }
176+
177+ // Erase characters from cursor to end of line
178+ $ output ->write ("\033[K " );
184179
185- $ currentMatched = false ;
180+ if ($ numMatches > 0 ) {
181+ // Save cursor position
182+ $ output ->write ("\0337 " );
183+ // Write highlighted text
184+ $ output ->write ('<hl> ' . substr ($ matches [$ ofs ], $ i ) . '</hl> ' );
185+ // Restore cursor position
186+ $ output ->write ("\0338 " );
186187 }
187188 }
188189
0 commit comments