|
4 | 4 | #include "strbuf.h"
|
5 | 5 | #include "run-command.h"
|
6 | 6 | #include "string-list.h"
|
| 7 | +#include "argv-array.h" |
7 | 8 |
|
8 | 9 | #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
|
9 | 10 |
|
@@ -161,6 +162,37 @@ static int enable_non_canonical(void)
|
161 | 162 | return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
162 | 163 | }
|
163 | 164 |
|
| 165 | +/* |
| 166 | + * Override `getchar()`, as the default implementation does not use |
| 167 | + * `ReadFile()`. |
| 168 | + * |
| 169 | + * This poses a problem when we want to see whether the standard |
| 170 | + * input has more characters, as the default of Git for Windows is to start the |
| 171 | + * Bash in a MinTTY, which uses a named pipe to emulate a pty, in which case |
| 172 | + * our `poll()` emulation calls `PeekNamedPipe()`, which seems to require |
| 173 | + * `ReadFile()` to be called first to work properly (it only reports 0 |
| 174 | + * available bytes, otherwise). |
| 175 | + * |
| 176 | + * So let's just override `getchar()` with a version backed by `ReadFile()` and |
| 177 | + * go our merry ways from here. |
| 178 | + */ |
| 179 | +static int mingw_getchar(void) |
| 180 | +{ |
| 181 | + DWORD read = 0; |
| 182 | + unsigned char ch; |
| 183 | + |
| 184 | + if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &read, NULL)) |
| 185 | + return EOF; |
| 186 | + |
| 187 | + if (!read) { |
| 188 | + error("Unexpected 0 read"); |
| 189 | + return EOF; |
| 190 | + } |
| 191 | + |
| 192 | + return ch; |
| 193 | +} |
| 194 | +#define getchar mingw_getchar |
| 195 | + |
164 | 196 | #endif
|
165 | 197 |
|
166 | 198 | #ifndef FORCE_TEXT
|
@@ -228,8 +260,31 @@ int read_key_without_echo(struct strbuf *buf)
|
228 | 260 | restore_term();
|
229 | 261 | return EOF;
|
230 | 262 | }
|
231 |
| - |
232 | 263 | strbuf_addch(buf, ch);
|
| 264 | + |
| 265 | + if (ch == '\033' /* ESC */) { |
| 266 | + /* |
| 267 | + * We are most likely looking at an Escape sequence. Let's try |
| 268 | + * to read more bytes, waiting at most half a second, assuming |
| 269 | + * that the sequence is complete if we did not receive any byte |
| 270 | + * within that time. |
| 271 | + * |
| 272 | + * Start by replacing the Escape byte with ^[ */ |
| 273 | + strbuf_splice(buf, buf->len - 1, 1, "^[", 2); |
| 274 | + |
| 275 | + for (;;) { |
| 276 | + struct pollfd pfd = { .fd = 0, .events = POLLIN }; |
| 277 | + |
| 278 | + if (poll(&pfd, 1, 500) < 1) |
| 279 | + break; |
| 280 | + |
| 281 | + ch = getchar(); |
| 282 | + if (ch == EOF) |
| 283 | + return 0; |
| 284 | + strbuf_addch(buf, ch); |
| 285 | + } |
| 286 | + } |
| 287 | + |
233 | 288 | restore_term();
|
234 | 289 | return 0;
|
235 | 290 | }
|
|
0 commit comments