На самом деле ответ был немного сложнее простого форматирования.
Каждый символ, отправленный процессом на терминал, можно рассматривать как переход в конечном автомате (FSM). Состояние этого FSM примерно соответствует отображаемому предложению и положению курсора, но есть много других переменных, таких как размеры терминала, текущая вводимая последовательность управления *, режим терминала (например, режим VI / классическая консоль BASH), и т.п.
Хорошую реализацию этого FSM можно увидеть в исходном коде pexpect. .
Чтобы ответить на мой вопрос, не существует базовой «функции» Unix, которая может форматировать строку в соответствии с тем, что отображается в терминале, поскольку такая функция специфична для терминала, который отображает вывод процесса, и вы бы придется переписать полный терминал, чтобы обрабатывать все возможные символы и управляющие последовательности.
Однако мы можем реализовать простой пример сами. Нам нужно определить FSM с начальным состоянием:
- отображаемая строка: "" (пустая строка)
- положение курсора: 0
и переходы (ввод символов):
- любой буквенно-цифровой символ/символ пробела: заменяет символ в позиции курсора на себя (или добавляет, если его нет) и увеличивает позицию курсора
\x08
шестнадцатеричный код: уменьшает позицию курсора
и подайте ему строку.
Python-решение
def decode(input_string):
# Initial state
# String is stored as a list because
# python forbids the modification of
# a string
displayed_string = []
cursor_position = 0
# Loop on our input (transitions sequence)
for character in input_string:
# Alphanumeric transition
if str.isalnum(character) or str.isspace(character):
# Add the character to the string
displayed_string[cursor_position:cursor_position+1] = character
# Move the cursor forward
cursor_position += 1
# Backward transition
elif character == "\x08":
# Move the cursor backward
cursor_position -= 1
else:
print("{} is not handled by this function".format(repr(character)))
# We transform our "list" string back to a real string
return "".join(displayed_string)
И пример
>>> decode("test\x08 \x08")
tes
Примечание о последовательностях управления
Управляющая последовательность ANSI представляет собой набор символов, которые действуют как переход в состояние (отображение/курсор/режим терминала/...) терминала. Это можно рассматривать как уточнение нашего состояния FSM и переходов с большим количеством подсостояний и подпереходов.
Например: когда вы нажимаете клавишу UP в классическом терминале Unix (например, VT100), вы фактически вводите управляющую последовательность: ESC 0 A
, где ESC
— шестнадцатеричный код \x1b
. ESC
переходит в режим ESCAPE и возвращается в нормальный режим после A.
Некоторые процессы интерпретируют эту последовательность как перемещение вертикальной позиции курсора (VI), другие — как движение назад по истории (BASH): это полностью зависит от программы, которая обрабатывает ввод.
Тем не менее, та же самая последовательность может использоваться для процесса вывода, но она, скорее всего, будет перемещать курсор вверх по экрану: это зависит от реализации терминала.
Хороший список управляющих последовательностей ANSI доступен здесь.
person
Perceval W
schedule
28.04.2017
'\r'
(т. е. возврат каретки), а затем написать предыдущую строку, но я думаю, это будет неудобно. - person Wayne Werner   schedule 12.04.2016