| 295 | } |
| 296 | |
| 297 | BAN::Optional<BAN::String> Input::get_input(BAN::Optional<BAN::StringView> custom_prompt) |
| 298 | { |
| 299 | tcsetattr(0, TCSANOW, &s_raw_termios); |
| 300 | BAN::ScopeGuard _([] { tcsetattr(0, TCSANOW, &s_original_termios); }); |
| 301 | |
| 302 | BAN::String ps1_prompt; |
| 303 | if (!custom_prompt.has_value()) |
| 304 | ps1_prompt = parse_ps1_prompt(); |
| 305 | |
| 306 | const auto print_prompt = |
| 307 | [&]() |
| 308 | { |
| 309 | if (custom_prompt.has_value()) |
| 310 | printf("%.*s", (int)custom_prompt->size(), custom_prompt->data()); |
| 311 | else |
| 312 | printf("%.*s", (int)ps1_prompt.size(), ps1_prompt.data()); |
| 313 | }; |
| 314 | const auto prompt_length = |
| 315 | [&]() -> int |
| 316 | { |
| 317 | if (custom_prompt.has_value()) |
| 318 | return custom_prompt->size(); |
| 319 | return character_length(ps1_prompt); |
| 320 | }; |
| 321 | |
| 322 | print_prompt(); |
| 323 | fflush(stdout); |
| 324 | |
| 325 | while (true) |
| 326 | { |
| 327 | int chi = getchar(); |
| 328 | if (chi == EOF) |
| 329 | { |
| 330 | if (errno != EINTR) |
| 331 | { |
| 332 | perror("getchar"); |
| 333 | exit(1); |
| 334 | } |
| 335 | |
| 336 | clearerr(stdin); |
| 337 | m_buffers = s_history; |
| 338 | MUST(m_buffers.emplace_back(""_sv)); |
| 339 | m_buffer_index = m_buffers.size() - 1; |
| 340 | m_buffer_col = 0; |
| 341 | putchar('\n'); |
| 342 | print_prompt(); |
| 343 | fflush(stdout); |
| 344 | continue; |
| 345 | } |
| 346 | |
| 347 | uint8_t ch = chi; |
| 348 | if (ch != '\t') |
| 349 | { |
| 350 | m_tab_completions.clear(); |
| 351 | m_tab_index.clear(); |
| 352 | } |
| 353 | |
| 354 | if (m_waiting_utf8 > 0) |
no test coverage detected