Expand/Shrink

progress

Definition: progress(string msg="", object args={})
Description: A simple console-based progress indicator.
pwa/p2js: Does nothing(ish). The browser does not update the display while JavaScript is still running (and it is quite adamant about that), hence all updates would be delayed until the program had finished, making this kind of approach worthless. However, rather than force you to put an "if platform()!=JS then" around every call, the (fake-ish) version in p2js.js simply does nothing, unless the last character of msg is '\n' (see examples below), in which case it behaves as/invokes printf(1,msg,args).
Comments: For gui apps (including the browser) see (eg) gProgressBar() or gLabel() or even (my personal pet favourite) gSetAttribute(dlg,"TITLE",msg).
[See demo\rosetta\VoronoiDiagram.exw for a good (and interruptable) example of the latter, just maximise the window and/or press '+' a few times to see it in action.]

Display (eg) 1%, 2%, ... 100% on the console while working, overwriting each time, and clearing it away once done.

If args is not {} then msg = sprintf(msg,args) is performed automatically for you.
Obviously, to display "1%".."100%" when args is not {}, you would need "%%", or better yet "%d%%".

Note a '\r' at the end of msg is critical to overwriting/clearing output, one will be provided if required, but '\n' at the end (and mid-msg) prevents (future) overwriting.

A final progress("") should be performed to clean up the display (the "" is now optional), or, as in the examples below, a progress(""); puts/printf(1,m); pair can be combined into one progress() call, as long as that m ends with a '\n'. That cleans up the display, by overwriting it with the minimum number of spaces (a previously saved length) and then a \r to put the cursor back in column 1, before displaying that m as normal.

If used correctly, adds progress messages to a console app, but does not change the final output.
Correct use requires the cursor be on a blank line in column 1 while displaying progress messages.
Example 1:
-- displays Working... (100%) .. (0%)
constant N = 100
for i=N to 0 by -1 do
    -- (by -1 to test that trailing "))" does NOT appear,
    --  that is, when a message is shorter than previous)
    progress("Working... (%d%%)\r",{(i/N)*100})
    sleep(0.1+(i=N or i=0)) -- (1.1 first/last, 0.1 rest)
end for
--progress("") -- (clears away the last one)
--puts(1,"\ndone\n")
progress("\ndone\n") -- equivalent to above two lines
{} = wait_key()

The parenthesis around (i/N) is strictly speaking unnecessary, but reinforces intent.
Example 2:
-- displays fourth|seventh|tenth of ten
atom t1 = time()+1
for i=1 to 10 do
    if time()>t1 then
        progress("Working... (%s of ten)\r",{ordinal(i)})
        t1 = time()+1
    end if
    sleep(0.4)
end for
--progress("") -- (clears away the last one)
--puts(1,"\ndone\n")
progress("\ndone\n") -- equivalent to above two lines
{} = wait_key()

Obviously the time()>t1 avoids unnecessary displays and is certainly noticeably faster than calling progress() thousands of times a second.
Providing you have that kind of rate limiting in place for any messages, even a long-running program should be slowed down by less than 0.01s.
aside: ?{i,time()-t1} would show {{1,-1},{2|5|8,-.6},{3|6|9,-.2},{4|7|10,+.2(show/reset)}}, hence it shows 4th/7th/10th (and not 4th/8th[/12th]).
Implementation: See builtins\progress.e (an autoinclude) for details of the actual implementation.
See Also: sprintf, sleep, time, ordinal