2012-01-21 16 views
10

¿Cuál es la forma más fácil de indicar el progreso de trabajo en la consola? La salida del porcentaje será suficiente, la barra de progreso no es necesaria.Indicación de progreso simple en la consola

El uso de solo print producirá lotes de líneas, solo quiero una única cadena de cambio en un terminal.

+0

¿se permite volver a dibujar 'cls'? –

+0

también, puede usar alguna forma de 'echo' que no imprime salto de línea, por lo tanto, había un carácter de control' back one symbol erase', por lo que puede hacer una animación rotativa (hecha de -/| \) –

+1

Mi Haskell está algo oxidado, por decir lo menos, pero si mal no recuerdo, si usas putStr con un \ r, harás un retorno de carro sin un salto de línea que te permita sobrescribir la línea en la que estás. –

Respuesta

21

La manera más simple sería hacer lo que hacen wget y otros programas: imprimir un retorno de carro y un código de borrado ANSI antes de la información de progreso, volviendo el cursor al inicio de la línea y reemplazando el texto existente . Por ejemplo:

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 clave aquí es que no impresión de una nueva línea, para que pueda volver al principio de la línea en la siguiente actualización del progreso.

Por supuesto, usted podría imprimir el porcentaje aquí y deje caer la barra, pero hay un bar es más fresco :)

+7

Puede ser una buena idea imprimir en 'stderr' en lugar de' stdout'. Obtiene un enjuague automático, y es posible usar este programa en una tubería sin que la barra de progreso se enrosque. – dflemstr

+0

@dflemstr: ¡Buen punto! Actualicé el código con una solución más simple que imprime en stderr. – ehird

3

Si quiero algo realmente rápido y sucio, lo que tiendo a hacer es imprimir una secuencia de puntos Cada vez que ha habido un progreso "un poco más", simplemente escribo otro punto (sin nueva línea). Ajusto la medida de "un poco de progreso" para que aparezcan los puntos sobre la escala de tiempo de un punto por segundo. No es muy sofisticado, pero muestra que el programa está haciendo algo.

Si realmente tiene algún tipo de medida de la cantidad total de "progreso" que habrá (a menudo no, pero esto es sugerido por su mención de porcentajes), entonces puede declarar que todo el programa es X puntos, e imprima uno cada vez que haga un progreso de 1/X.

Cuestiones relacionadas