Отображение стандартного фонового процесса в определенном месте терминала

8

У меня есть команда, которую я запускаю каждый раз, когда открывается новый терминал или производится новый вход в систему.

Эта программа производит вывод (цветной), который должен располагаться перед командной строкой. Запуск может занять несколько секунд, что не позволит мне использовать терминал до тех пор (если он не работает в фоновом режиме).

Учитывая, что у zsh есть несколько продвинутых способов перерисовки терминала без залипания существующего текста, я хотел бы знать, как я могу выполнить эту команду так, чтобы мне не приходилось ждать ее завершения, прежде чем я смогу использовать терминал, но это как только он заканчивает работу, он печатает вывод, как если бы он не был фоновым.

На практике я хотел бы что-то, что может сделать:

Command output:
... (running on background)
me@computer: somecommand
me@computer: someothercommand

и как только команда завершится, я получу:

Command output:
 * Output foo
 * Multiple lines bar
 * and some yada
me@computer: somecommand
me@computer: someothercommand

Я попытался поместить процесс в фоновом режиме при запуске, но затем он не отображает вывод чисто. Я получаю что-то вроде:

Command output:
[2] 32207
me@computer: somecommand
me@computer: someother * Output foo
 * Multiple lines bar
 * and some yada
[2]  + done       command
me@computer: someothercommand

Так это возможно? Если нет с zsh, есть ли какое-нибудь решение, которое могло бы это сделать?

Любые указатели или информация приветствуются.

unode
источник
Это невозможно, если программа работает непосредственно в терминале, потому что есть только одна позиция курсора и zsh, и программа будет конкурировать за это. Вы можете сделать что-то с zpty: запустить команду на терминале, созданном zsh, с выводом, передаваемым на реальный терминал под контролем zsh.
Жиль "ТАК - перестань быть злым"
@ Жиль Не могли бы вы подробнее рассказать об использовании zpty? Я знаю, что вы не можете иметь две программы, пишущие на один и тот же терминал, без какой-либо конкуренции за курсор. Мой вопрос связан с тем, что zsh уже переписывает приглашение в некоторых конфигурациях. Очевидно, что этой программе придется записывать данные во временный буфер в памяти, который затем будет «напечатан» в определенном месте после завершения команды. Все последние под контролем зш.
unode
@ Жиль: может быть, это стоит настоящего ответа?
Стефан Гименес
@ StéphaneGimenez Конечно, это так. Я не знаю, как сделать это без какого-либо исследования, и у меня нет времени для этого исследования прямо сейчас.
Жиль "ТАК - перестань быть злым"
Идея заключалась бы в том, чтобы сделать это с screenпомощью сценария запуска, который разделяет экран и запускает длинный бегун в верхней части и обычную командную строку в нижней части.
Васкес

Ответы:

5

Это простое решение, если вы готовы принять вывод чуть выше текущей строки приглашения.

TRAPUSR1 () { zle -I; unfunction TRAPUSR1 }  # invalidate prompt on signal USR1

bufferout () {
    local buffer
    while read -r line; do                   # buffer lines from stdin
        buffer="$buffer$line\n"
    done
    print -rn -- $terminfo[dl1]              # delete current line
    print -rn -- $terminfo[cr]               # move cursor to BOL
    printf "$buffer"                         # print buffer
    kill -USR1 $$                            # send USR1 when we're done
}

unsetopt monitor                             # don't monitor this job
./testout |& bufferout & disown              # bg and disown to suppress notification
setopt monitor                               # restore job monitoring

Когда работа завершена, текущий быстрый и входной буфер будет удален и полнота данной команды stdoutи stderrбудет распечатан.

С этим модулем вы можете получить гораздо больше фантазии, чем с этим zsh/curses, но я сомневаюсь, что это даст преимущество, достаточно значительное, чтобы заслужить усилия.

user112553
источник
Это работает. Но насколько сложно было бы запретить оболочке печатать pid процесса при отправке в фоновый режим и сообщение «выполнено» после завершения? (Я имею в виду временно отключить эту функцию). Кроме того, перед тем, как поместить вывод в терминал, насколько сложно будет очистить существующую строку или строки подсказки?
unode
Я думаю, что у меня может быть какая-то другая конфигурация переписывания подсказок, которая конфликтует с удалением начальной подсказки. Мой не уходит, как только команда заканчивается. Я также все еще получаю PID процессов при отправке в фоновый режим, но строка "done" исчезла. В любом случае я принимаю ваш ответ, так как он довольно близок к тому, что я имел в виду. Спасибо.
unode
Я использую xterm, и у меня включен модуль VCS и некоторые другие настройки для приглашения. Я не пробовал, но я уверен, что это связано с этим. Некоторое время назад я пытался использовать средство оповещения о режиме vi, подобное этому ( stackoverflow.com/a/3791786/125801 ), и когда оно было активным, я потерял некоторые из своих пользовательских настроек подсказок. Это не имеет большого значения, на данный момент я доволен решением. Я попытаюсь очистить мой запрос на днях и проверим, появляются ли еще идентификаторы PID.
unode
Zsh-4.3.10, после отключения практически всех настроек, я больше не получаю приглашение (то есть оно правильно удалено), но я все еще получаю PID процессов в фоновом режиме, как [1] 27911 27912в одной строке, так и в первой строке Терминал.
unode
Могу ли я снова проголосовать? :) Это прекрасно сейчас! Огромное спасибо.
unode