2012-01-21 31 views
10

什麼是指示在控制檯的工作進展情況的最簡單的方法?輸出百分比就足夠了,進度條不是必需的。簡單進度指示

只需使用print會產生線很多的,我想只是一個終端一個變化的字符串。

+0

是'cls'允許重繪? –

+0

也,你可能只需要使用某種形式的'echo'不打印線斷裂,從而出現'回一個符號erase'控制字符,這樣就可以使一個旋轉的動畫(從製造 -/| \) –

+1

我的Haskell是那種生疏,至少可以說,但如果我沒有記錯,使用putStr用\ r在年底會做不換行應該讓你覆蓋你就行了回車。 –

回答

21

最簡單的方法是做什麼wget和其他程序一樣:打印出的進展信息之前回車和ANSI擦除行代碼,從而光標回到行的開始,並替換現有文本。例如:

import Control.Monad 
import Control.Concurrent 
import System.IO 
import Text.Printf 

putProgress :: String -> IO() 
putProgress s = hPutStr stderr $ "\r\ESC[K" ++ s 

drawProgressBar :: Int -> Rational -> String 
drawProgressBar width progress = 
    "[" ++ replicate bars '=' ++ replicate spaces ' ' ++ "]" 
    where bars = round (progress * fromIntegral width) 
     spaces = width - bars 

drawPercentage :: Rational -> String 
drawPercentage progress = printf "%3d%%" (truncate (progress * 100) :: Int) 

main :: IO() 
main = do 
    forM_ [0..10] $ \i -> do 
    let progress = fromIntegral i/10 
    putProgress $ drawProgressBar 40 progress ++ " " ++ drawPercentage progress 
    threadDelay 250000 
    putProgress "All done." 
    hPutChar stderr '\n' 

這裏的關鍵就是要打印換行,這樣就可以返回到下一個進度更新該行的開始。

當然,你可能只是在這裏打印出來的百分比和丟棄的酒吧,但酒吧是冷卻器:)

+7

打印到「stderr」而不是「stdout」可能是一個好主意。您可以自動沖洗,並且可以在不使用進度條的情況下在管道中使用此程序。 – dflemstr

+0

@dflemstr:好點!我用更簡單的打印到stderr的解決方案更新了代碼。 – ehird

3

如果我想獲得真正的快速和骯髒的,我傾向於做的僅僅是打印序列的點。每次有「更多」的進展,我只寫一個點(沒有換行符)。我調整了「一點點進步」的措施,以便點對每秒點的時間尺度。不是很複雜,但它表明該程序正在做一些事情。

如果你實際上有某種程度的總體「進步」會有多少(我經常不會這樣做,但是這是你提到的百分比所提示的),那麼你可以聲明整個程序是X點,並在每次進行1/X時進行打印。