Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple progress indication in console

What is the easiest way to indicate the work progress in console? Outputting the percentage will be enough, progress bar is not necessary.

Using just print will produce lot's of lines, I want just a single changing string in a terminal.

like image 784
Yrogirg Avatar asked Jan 21 '12 14:01

Yrogirg


People also ask

What progress bar does Pip use?

pip , the package installer for Python, merged a code change to deprecate its former progress rendering method in favor of using rich, a Python library for rich text and formatting.


2 Answers

The simplest way would be to do what wget and other programs do: printing out a carriage return and an ANSI erase-line code before the progress information, thus returning the cursor to the start of the line and replacing the existing text. For example:

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'

The key thing here is to not print a newline, so that you can return to the start of the line on the next progress update.

Of course, you could just print out the percentage here and drop the bar, but a bar is cooler :)

like image 78
ehird Avatar answered Nov 15 '22 22:11

ehird


If I want something really quick and dirty, what I tend to do is just print a sequence of dots. Every time there's been "a bit more" progress I just write another dot (with no newline). I tune the measure of "a bit of progress" so that the dots come on about the time scale of a dot per second. Not very sophisticated, but it shows the program is doing something.

If you actually have some sort of measure of how much total "progress" there will be (I often don't, but this is suggested by your mention of percentages), then you can just declare the whole program to be X dots, and print one every time you make 1/X progress.

like image 22
Ben Avatar answered Nov 15 '22 22:11

Ben