2012-01-21 16 views
10

Qual è il modo più semplice per indicare lo stato di avanzamento del lavoro in console? L'uscita della percentuale sarà sufficiente, la barra di avanzamento non è necessaria.Indicazione di avanzamento semplice nella console

Utilizzare solo print produce un sacco di linee, voglio solo una singola stringa di modifica in un terminale.

+0

è 'cls' permesso di ridisegnare? –

+0

inoltre, puoi semplicemente usare una forma di 'echo' che non stampa l'interruzione di riga, quindi c'era un carattere di controllo' cancella un simbolo di cancellazione ', quindi puoi creare un'animazione rotante (fatta da -/| \) –

+1

Il mio Haskell è a dir poco arrugginito, ma se ricordo male, usare putStr con un \ r alla fine farà un ritorno a capo senza un line feed che dovrebbe permettere di sovrascrivere la linea su cui ti trovi. –

risposta

21

Il modo più semplice sarebbe quello di fare ciò che wget e altri programmi fanno: stampare un ritorno a capo e un codice di cancellazione ANSI prima delle informazioni di avanzamento, restituendo quindi il cursore all'inizio della riga e sostituendo il testo esistente . Per esempio:

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' 

La cosa fondamentale è quello di non stampa un ritorno a capo, in modo che si può tornare al punto di partenza della linea sul prossimo aggiornamento di avanzamento.

Naturalmente, si può solo stampare la percentuale di qui e rilasciare il bar, ma una barra è più fredda :)

+7

Potrebbe essere una buona idea stampare su 'stderr' invece di' stdout'. Si ottiene lo svuotamento automatico ed è possibile utilizzare questo programma in una pipe senza che la barra di avanzamento si avviti. – dflemstr

+0

@dflemstr: buon punto! Ho aggiornato il codice con una soluzione più semplice che stampa su stderr. – ehird

3

Se voglio qualcosa di veramente veloce e sporco, quello che io tendo a fare è semplicemente stampare una sequenza di punti. Ogni volta che c'è stato un progresso "un po 'più", scrivo solo un altro punto (senza newline). Accordo la misura di "un po 'di progresso" in modo che i punti si accendano sulla scala temporale di un punto al secondo. Non molto sofisticato, ma mostra che il programma sta facendo qualcosa.

Se si dispone effettivamente di una sorta di misura di quanti "progressi" totali ci saranno (io spesso no, ma questo è suggerito dalla tua menzione delle percentuali), allora puoi semplicemente dichiarare l'intero programma come X punti e ne stampi uno ogni volta che fai il progresso 1/X.

Problemi correlati