Как направить gnu readline от stdout - PullRequest
2 голосов
/ 25 марта 2019

Итак, я хотел создать программу, которая принимает ввод от stdin через перенаправление или интерактивный ввод. getline может обеспечить чтение в обратном направлении, но я хотел бы иметь все приятные функции readline для интерактивного ввода. Цель программы - манипулировать текстом через язык и выводить результаты на стандартный вывод (аналогично тому, что делает sed). Проблема в том, что я не могу сделать my_prog > output.txt с readline, потому что все, что было введено в readline, вывод readline попадает в этот файл, и я даже не вижу его. В настоящее время у меня есть обходной путь, когда я просто отправляю вывод readline в stderr, используя rl_outstream. Это дает мне поведение, которое я ищу, но похоже на хак, когда, возможно, есть более простое решение. Хороший пример того, что я ищу, это то, что делает Python.

python > output.txt
>>> print 'hello'
>>> exit()
cat output.txt
hello

Вот код, демонстрирующий, что я делаю ...

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "readline/readline.h"

int main(int argc, char** argv)
{
    char* from_stdin = malloc(512);
    char* line = NULL;

    rl_outstream = stderr;

    if(isatty(STDIN_FILENO)) {
        do {
            line = readline("");
            if(line) {
                strcat(from_stdin, line);
                strcat(from_stdin, "\n");
            } else {
                break;
            }
        } while(1);
    } else {
        size_t n = 0;
        while(getline(&line, &n, stdin) != -1)
            strcat(from_stdin, line);
    }
    puts(from_stdin);
}

Патч для принятого решения:

--rl_outstream = stderr;
++FILE* more_hacky = fopen("/dev/tty", "w");
++rl_outstream = more_hacky;

Я согласен с тем, что он более хакерский. Вероятно, я оставлю свой код как есть, но это сделает stderr более «чистым» для ошибок, если я выберу.

1 Ответ

2 голосов
/ 25 марта 2019

Для чего бы то ни было, CPython использует , использует STDERR_FILENO в качестве дескриптора выходного файла для Readline, если !isatty(STDOUT_FILENO) факт, который вы можете проверить с помощью strace и т. П.

Без перенаправления мы получаем

% strace -o strace.out python3 && grep '>>>' strace.out
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
write(1, ">>> ", 4)                     = 4

и с перенаправлением

% strace -o strace.out python3 > python.out && grep '>>>' strace.out
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
write(2, ">>> ", 4)                     = 4

Альтернативой может быть открытие /dev/tty для выходного потока, но я чувствую, что , что было бы больше, а не меньше, хаки.

...