Я использую (отлично) readline
(версия 6.3, режим по умолчанию [не vi]) из моей собственной программы, работающей в окне Терминала (на ПК). Возникает проблема, когда предыдущий вывод не завершается символом новой строки при вызове readline ()
.
#include <stdio.h>
#include <readline/readline.h>
void main(void)
{
// Previous output from some other part of application
// which *may* have output stuff *not* terminated with a '\n'
printf("Hello ");
fflush(stdout);
char *in = readline("OK> ");
}
Итак, строка выглядит так:
Hello OK> <caret here>
Если вы введете небольшое количество символов (до 5?), А затем, скажем, Ctrl + U
(могут быть другие), чтобы удалить введенные данные, пока все кажется хорошо --- readline ()
перемещает курсор обратно сразу после его собственного приглашения. Однако попробуйте ввести, скажем:
123456 <Ctrl+U>
Теперь он удаляет обратно в Hello
, оставляя в строке только Hell
, за которым следует курсор.
Мне нужно одно из двух возможных решений:
Это действительно похоже на ошибку, теперь, когда я понял, это зависит от того, сколько символов набрано в строке, где ошибка. Какие-нибудь исправления / обходные пути?
В качестве альтернативы, могу ли я сделать вызов библиотеки readline
, который сообщит мне, в какой позиции / столбце находится курсор, прежде чем я вызову readline ()
? Тогда, по крайней мере, я смог бы распознать тот факт, что я нахожусь в конце существующей строки, и вывести \ n
, чтобы сначала позиционировать себя в начале новой строки.
PS
Можно ли здесь спросить о программировании readline
под Ubuntu, или мне следует публиковать сообщения на stackoverflow.com ?
Оказывается, что readline
не может распознать, не запускается ли это в столбце № 1, и, таким образом, мешайте себе портить предыдущий вывод на строке.
единственный способ иметь дело с этим состоит в том, чтобы распознать стартовый столбец самостоятельно и переместиться в запуск следующей строки вниз, если текущая позиция не столбец № 1. Затем это будет всегда начинать с крайнего левого столбца, не производя ненужную новую строку, когда это уже будет в столбце № 1.
, Мы можем сделать это для стандарта "Терминал", потому что это понимает escape-последовательность ANSI для запросов текущей строки & столбец терминала. Запрос отправляется через символы в stdout
, и ответ читается через символы, которые терминал вставляет в stdin
. Мы должны поместить терминал в "необработанный" режим ввода так, чтобы символы ответа могли быть сразу считаны и не были отражены.
, Таким образом, вот код:
rl_prep_terminal(1); // put the terminal into "raw" mode
fputs("\033[6n", stdout); // <ESC>[6n is ANSI sequence to query terminal position
int row, col; // terminal will reply with <ESC>[<row>;<col>R
fscanf(stdin, "\033[%d;%dR", &row, &col);
rl_deprep_terminal(); // restore terminal "cooked" mode
if (col > 1) // if beyond the first column...
fputc('\n', stdout); // output '\n' to move to start of next line
in = readline(prompt); // now we can invoke readline() with our prompt
[Stackoverflow был бы более соответствующим местом для такого вопроса о программировании]
, Это не ошибка, но ожидаемое поведение. readline не знает о том, что было записано на терминале ранее и в том, какое положение он пишет. Думайте "основной последовательный терминал". Кроме того, другие фоновые процессы (о котором не знает Ваша программа) могут также записать в терминал.
Так, readline предполагает, что начинает писать в начале терминальной строки. Когда Вы, Ctrl-U (отбрасывание строки Unix), readline возвращается, где это думает, что Вы запустили к символам текста, т.е. сразу после его подсказки. Ваша подсказка "хорошо>" является четырьмя символами долго, таким образом, readline помещают каре в 5-е место и стирают строку, покидая просто "Ад".
обходное решение могло быть должно пропустить строку прежде, чем назвать readline или начать Вашу подсказку с символа CR (т.е. \r
), который вызовет подсказку в начале строки, перезаписывая "Привет" (но более длинный текст был бы только частично перезаписан).
[обновление]
Что касается того, почему иногда Ctrl-U стирает просто последние введенные символы и иногда он стирает (почти) целую строку, это - readline оптимизация.
readline может испустить две различных последовательности символов для стирания целого входа:
<BS>
(клавиша Backspace) + < управляющая последовательность для стирания целого line> (например, ANSI <ESC> [ K
), где n является количеством символов, введенных до сих пор. <CR>
+ m Г — < управляющая последовательность для перемещения курсора в right> (например, ANSI <ESC> [ C
) + < управляющая последовательность для стирания целого line> где m является продолжительностью подсказки. readline выбирают самое короткое, которое зависит от количества введенного wrt символов продолжительность Вашей подсказки.