2010-02-25 53 views
29

當您運行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 

這是怎麼acccomplished?它是否使用ncurses或更簡單的東西,如退格字符和常規字符輸出的組合?

我特別感興趣的是如何從Ruby完成這種控制檯輸出。

編輯

我原來的問題是回答。但這是一個附錄。例如,當您使用MPlayer時,它不僅會更新一行以顯示當前進度,還會更新之前的一行(例如,當您按暫停時)。

===== PAUSE ===== 
A: 79.9 (01:19.9) of 4718.0 (1:18:38.0) 0.3% 

你會如何更新兩行輸出?

+1

也看看http://stackoverflow.com/questions/613305/infinite-yields-from-an-iterator – vladr 2010-02-28 03:03:14

+0

這個問題和相關的答案正是什麼使堆棧溢出很大。謝謝他們。 – num1 2011-03-21 07:18:50

回答

36

使用回車。 '\ r'通常應該可以工作。

+9

這是一個例子:'10.times {| i | STDOUT.write「\ r#{i}」;睡1}' – 2010-02-25 18:38:41

+0

謝謝。但爲什麼在Unix中\ r有這樣的效果? – dan 2010-02-25 18:42:10

+1

@dan:或許這有一個答案:http://en.wikipedia.org/wiki/Carriage_return – 2010-02-25 18:59:29

0

Ruby有許多curses librbaries。我相信rbbcurse是維護最好的。

7

git/progress.c

... 
     eol = done ? done : " \r"; 
... 
       fprintf(stderr, "...%s", ..., eol); 
       fflush(stderr); 

GIT中簡單地發出一個回車和無線饋電,其中所述終端解釋爲「移動到第一列」。

4

您必須使用其他方法(如Curses)才能更新兩行代碼。

ablogaboutcode.com | web.archive.org

......還有......

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html

+0

到博客文章的鏈接已經死了。請將您的鏈接包裝到網絡檔案中。 – Overbryd 2016-11-23 12:33:49

+1

@Overbryd,它還沒死。但其行爲不可預測。 – 2016-11-23 13:20:44

+0

很酷,非常感謝。真的需要那篇文章。 – Overbryd 2016-11-24 14:43:09

1

我寫的小類多輸出更新:

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方法。