#python #bash #readline
#python #bash #строка чтения
Вопрос:
У меня есть скрипт на python, который принимает, управляет stdin, stdout и stderr любого приложения и позволяет корректно вставлять строку чтения. Подумайте о любом приложении, которое имеет много консольных выходных данных, но также принимает команды из stdin.
В любом случае, мой скрипт использует эти две функции:
def blank_current_readline():
# Next line said to be reasonably portable for various Unixes
(rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))
text_len = len(readline.get_line_buffer()) 2
# ANSI escape sequences (All VT100 except ESC[0G)
sys.stdout.write('x1b[2K') # Clear current line
sys.stdout.write('x1b[1Ax1b[2K'*(text_len/cols)) # Move cursor up and clear line
sys.stdout.write('x1b[0G') # Move to start of line
def print_line(line):
global cmd_state
blank_current_readline()
print line,
sys.stdout.write(cmd_state["prompt"] readline.get_line_buffer())
sys.stdout.flush()
При обработке стандартного вывода я вызываю print_line() . Это очищает все, что пользователь может вводить, печатает строку, а затем восстанавливает введенный пользователем текст. Все это происходит незаметно для пользователя.
Проблема возникает, когда курсор не находится в конце любого ввода, который вводит пользователь. Когда курсор находится в середине теста и печатается строка, курсор автоматически помещается в конец ввода. Чтобы решить эту проблему, я хочу сделать что-то подобное в print_line:
def print_line(line):
global cmd_state
cursorPos = getCurrentCursorPos() #Doesn't exist
blank_current_readline()
print line,
sys.stdout.write(cmd_state["prompt"] readline.get_line_buffer())
sys.stdout.setCurrentCursorPos(cursorPos) #Doesn't exist
sys.stdout.flush()
Редактировать: чтобы попытаться визуализировать то, что я написал:
Терминал выглядит следующим образом:
----------------------------------------------
| |
| |
| <scolling command output here> |
| |
| <scolling command output here> |
| |
|: <user inputted text here> |
----------------------------------------------
Таким образом, выходной текст постоянно прокручивается по мере поступления новых журналов. В то же время пользователь в данный момент редактирует и пишет новую команду, которая будет вставлена после нажатия enter. Итак, это похоже на консоль python, но вывод всегда добавляется.
Ответ №1:
Могу ли я предложить Python curses?
Вот основные практические рекомендации
Модуль curses предоставляет интерфейс к библиотеке curses, фактическому стандарту для переносимой расширенной обработки терминалов.
Хотя curses наиболее широко используется в среде Unix, доступны версии для DOS, OS / 2 и, возможно, других систем. Этот модуль расширения разработан для соответствия API ncurses, библиотеки curses с открытым исходным кодом, размещенной в Linux и вариантах BSD Unix.
В качестве альтернативы
Я нашел терминальный контроллер здесь: использование terminfo для портативного цветового вывода и управления курсором. Он выглядит более переносимым, чем можно было бы предположить по имени сайта (macOS упоминается в комментариях, хотя и с изменениями).
Вот пример использования, отображающий индикатор выполнения:
class ProgressBar:
"""
A 3-line progress bar, which looks like::
Header
20% [===========----------------------------------]
progress message
The progress bar is colored, if the terminal supports color
output; and adjusts to the width of the terminal.
"""
BAR = '=%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}n'
HEADER = '${BOLD}${CYAN}%s${NORMAL}nn'
def __init__(self, term, header):
self.term = term
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
raise ValueError("Terminal isn't capable enough -- you "
"should use a simpler progress dispaly.")
self.width = self.term.COLS or 75
self.bar = term.render(self.BAR)
self.header = self.term.render(self.HEADER % header.center(self.width))
self.cleared = 1 #: true if we haven't drawn the bar yet.
self.update(0, '')
def update(self, percent, message):
if self.cleared:
sys.stdout.write(self.header)
self.cleared = 0
n = int((self.width-10)*percent)
sys.stdout.write(
self.term.BOL self.term.UP self.term.CLEAR_EOL
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n)))
self.term.CLEAR_EOL message.center(self.width))
def clear(self):
if not self.cleared:
sys.stdout.write(self.term.BOL self.term.CLEAR_EOL
self.term.UP self.term.CLEAR_EOL
self.term.UP self.term.CLEAR_EOL)
self.cleared = 1
Комментарии:
1. Я снова займусь проклятиями, это показалось мне излишеством для моего использования.
2. @Jim: хорошо, найден и добавлен альтернативный вариант, который выглядит довольно легким
3. Хотя это выглядит довольно круто, моя проблема заключается не в чистом форматировании выходных данных, а в индексе курсора после вывода. В приведенном выше примере не учитывается, что пользователь редактирует встроенную команду во время одновременного создания выходных данных.
4. @Jim: Я полагаю, вы пропустили тот факт, что он может отправлять курсор вверх, вниз, BOL, EOL и т. Д.? Конечно, вам пришлось бы написать свои собственные процедуры ввода. Образец — это всего лишь образец. (Лично я бы предпочел проклятия. Есть готовые панели и виджеты.)