Ответ 1
Использовать возврат каретки. '\ r' обычно должен работать.
При запуске git clone
он обновляет ход выполнения. Например, процент полученных объектов изменяется на месте.
[email protected]:~/cloj/src$ git clone git://git.boinkor.net/slime.git
Initialized empty Git repository in /home/user/cloj/src/slime/.git/
remote: Counting objects: 15936, done.
remote: Compressing objects: 100% (5500/5500), done.
Receiving objects: 28% (4547/15936), 3.16 MiB | 165 KiB/s
Как это происходит? Использует ли он ncurses или что-то еще более простое, например, какую-то комбинацию символов backspace и обычного символьного вывода?
Меня особенно интересует, как этот консольный вывод может быть выполнен с Ruby.
ИЗМЕНИТЬ
Отвечает мой первоначальный вопрос. Но здесь добавление. Например, когда вы используете MPlayer, он не только обновляет строку, чтобы показывать текущий прогресс, но также и предыдущую строку (например, когда вы нажимаете паузу).
===== PAUSE =====
A: 79.9 (01:19.9) of 4718.0 ( 1:18:38.0) 0.3%
Как бы вы обновили две строки вывода на месте?
Использовать возврат каретки. '\ r' обычно должен работать.
...
eol = done ? done : " \r";
...
fprintf(stderr, "...%s", ..., eol);
fflush(stderr);
Git просто испускает возврат каретки и нет строки, которую терминал интерпретирует как "перемещение в первый столбец".
Вам понадобится использовать другой метод (например, Curses) для обновления двух строк на месте.
ablogaboutcode.com | web.archive.org
... и...
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html
Я написал небольшой класс для многострочного обновления:
class ConsoleReset
# Unix
# Contains a string to clear the line in the shell
CLR = "\e[0K"
# ANSI escape sequence for hiding terminal cursor
ESC_CURS_INVIS = "\e[?25l"
# ANSI escape sequence for showing terminal cursor
ESC_CURS_VIS = "\e[?25h"
# ANSI escape sequence for clearing line in terminal
ESC_R_AND_CLR = "\r#{CLR}"
# ANSI escape sequence for going up a line in terminal
ESC_UP_A_LINE = "\e[1A"
def initialize
@first_call = true
end
def reset_line(text = '')
# Initialise ANSI escape string
escape = ""
# The number of lines the previous message spanned
lines = text.strip.lines.count - 1
# Clear and go up a line
lines.times { escape += "#{ESC_R_AND_CLR}#{ESC_UP_A_LINE}" }
# Clear the line that is to be printed on
# escape += "#{ESC_R_AND_CLR}"
# Console is clear, we can print!
STDOUT.print escape if [email protected]_call
@first_call = false
print text
end
def hide_cursor
STDOUT.print(ESC_CURS_INVIS)
end
def show_cursor
STDOUT.print(ESC_CURS_VIS)
end
def test
hide_cursor
5.times do |i|
line = ['===========================================']
(1..10).each do |num|
line << ["#{num}:\t#{rand_num}"]
end
line << ['===========================================']
line = line.join("\n")
reset_line(line)
sleep 1
end
show_cursor
puts ''
end
private
def rand_num
rand(10 ** rand(10))
end
end
Вдохновленный prydonius/spinning_cursor
. См. Метод test
, например, использование.
Для Ruby существует ряд проклятий librbaries. Я считаю, что rbbcurse наиболее поддерживается.