Как я могу отключить readline, чтобы напечатать что-то и затем восстановить это?
Я пытаюсь написать консольный чат-клиент, используя только readline и escape-коды ANSI.
Моя цель - просто позволить терминалу обрабатывать прокрутку и прокрутку истории чата, всегда предоставляя подсказку readline после сообщений для нового ввода.
Я попробовал следующее с моими двумя потоками. Мой поток ввода с консоли делает:
printf("\x1B[s"); // Save cursor position
message = readline("Prompt > ");
И мой поток получения сообщений делает:
message = receive_message(); // Blocks for next message
printf("\x1B[u"); // Restore cursor to before the prompt
printf("\x1B[J"); // Erase readline prompt and input (down to bottom of screen)
printf("%s\n", message); // Print the message (where readline was)
printf("\x1B[s"); // Save new cursor position
rl_forced_update_display(); // Restore readline
Вышеприведенное работает, пока ввод readline не переносится. Когда оно оборачивается, восстановление сохраненной позиции курсора не работает должным образом, кажется, что восстанавливается только горизонтальное положение, а не вертикальное положение.
Как я могу адаптировать вышеуказанный код для работы, даже если строка ввода переносится?
2 ответа
Этот вопрос оказывается гораздо лучшим решением. Я воспроизвел код из приведенного решения, относящегося к ответу на этот вопрос здесь:
message = receive_message();
// Solution
int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;
int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
printf(message);
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
Для полноты входной поток очищается от сохранения курсора и становится простым:
message = readline("Prompt > ");
Я не знаю, как я не видел, прежде чем опубликовать свой вопрос.
Я был вдохновлен тем, как получить ширину терминала в C, чтобы выяснить вручную, завернут ли я или нет.
Теперь я делаю следующее, когда мне нужно что-то напечатать перед приглашением readline:
message = receive_message(); // Blocks for next message
/* Solution */
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // Get terminal dimensions
printf("\r"); // Move cursor to the begining of the line
// Calculate the length of the prompt and cursor position
int readline_length = rl_point + strlen(rl_prompt);
// Integer divide cursor position by the terminal width
int wrapped_lines = readline_length/w.ws_col;
// If there are wraped lines
if (wrapped_lines > 0)
// move the cursor up by that number of lines
printf("\x1B[%dA", wrapped_lines);
printf("\r"); // Move cursor to the beginning of the line
printf("\x1B[J"); // Erase readline prompt and input (down to bottom of screen)
printf("%s\n", message); // Print the message (where readline was)
rl_forced_update_display(); // Restore readline
Для полноты входной поток очищается от сохранения курсора и становится простым:
message = readline("Prompt > ");