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 :)
è 'cls' permesso di ridisegnare? –
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 -/| \) –
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. –