Last active
April 2, 2020 03:27
-
-
Save jorgenpt/9f610a8ddf693775cd8c to your computer and use it in GitHub Desktop.
Text based progress bar for C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace JPT | |
{ | |
class Sample | |
{ | |
static void Main(string[] args) | |
{ | |
var worklist = new List<string>(); | |
using (var reader = new StreamReader("input.txt")) | |
{ | |
while (!reader.EndOfStream) | |
{ | |
var item = reader.ReadLine().Trim(); | |
if (item.Length < 1) | |
continue; | |
worklist.Add(item); | |
} | |
} | |
Console.WriteLine("Doing work:"); | |
using (var progress = new TextProgressBar(worklist.Count)) | |
foreach (var workItem in worklist) | |
{ | |
DoWork(workItem); | |
progress.Increment(); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace JPT | |
{ | |
public class TextProgressBar : IDisposable | |
{ | |
private int _progress; | |
private int _total; | |
private int _width; | |
private int _lastFilledSlots; | |
private int _cursorRow; | |
public TextProgressBar(int total, int width = -1, bool drawImmediately = true) | |
{ | |
_progress = 0; | |
_total = total; | |
if (width < 0) | |
_width = Console.WindowWidth - string.Format("[] {0} of {0}", _total).Length; | |
else | |
_width = width; | |
_lastFilledSlots = -1; | |
_cursorRow = -1; | |
if (drawImmediately) | |
Update(0); | |
} | |
public void Update(int progress) | |
{ | |
_progress = Math.Max(Math.Min(progress, _total), 0); | |
if (_cursorRow < 0) | |
{ | |
_cursorRow = Console.CursorTop; | |
Console.CursorTop++; | |
Console.CursorLeft = 0; | |
} | |
int filledSlots = (int)Math.Floor(_width * ((double)progress) / _total); | |
if (filledSlots != _lastFilledSlots) | |
{ | |
_lastFilledSlots = filledSlots; | |
DrawBar(); | |
} | |
DrawText(); | |
if (Console.CursorTop == _cursorRow) | |
Console.CursorLeft = Console.WindowWidth - 1; | |
} | |
public void ForceDraw() | |
{ | |
DrawBar(); | |
DrawText(); | |
if (Console.CursorTop == _cursorRow) | |
Console.CursorLeft = Console.WindowWidth - 1; | |
} | |
public static TextProgressBar operator ++(TextProgressBar bar) | |
{ | |
bar.Increment(); | |
return bar; | |
} | |
public void Increment() | |
{ | |
Update(_progress + 1); | |
} | |
public void Dispose() | |
{ | |
Update(_total); | |
if (Console.CursorTop == _cursorRow) | |
Console.WriteLine(""); | |
} | |
private void DrawBar() | |
{ | |
using (new ConsoleStateSaver()) | |
{ | |
Console.CursorVisible = false; | |
Console.CursorTop = _cursorRow; | |
// Draw the outline of the progress bar | |
Console.CursorLeft = _width + 1; | |
Console.Write("]"); | |
Console.CursorLeft = 0; | |
Console.Write("["); | |
// Draw progressed part | |
Console.BackgroundColor = ConsoleColor.Green; | |
Console.Write(new String(' ', _lastFilledSlots)); | |
// Draw remaining part | |
Console.BackgroundColor = ConsoleColor.Black; | |
Console.Write(new String(' ', _width - _lastFilledSlots)); | |
} | |
} | |
private void DrawText() | |
{ | |
using (new ConsoleStateSaver()) | |
{ | |
// Write progress text | |
Console.CursorVisible = false; | |
Console.CursorTop = _cursorRow; | |
Console.CursorLeft = _width + 4; | |
Console.Write("{0} of {1}", _progress.ToString().PadLeft(_total.ToString().Length), _total); | |
Console.Write(new String(' ', Console.WindowWidth - Console.CursorLeft)); | |
} | |
} | |
private class ConsoleStateSaver : IDisposable | |
{ | |
ConsoleColor _bgColor; | |
int _cursorTop, _cursorLeft; | |
bool _cursorVisible; | |
public ConsoleStateSaver() | |
{ | |
_bgColor = Console.BackgroundColor; | |
_cursorTop = Console.CursorTop; | |
_cursorLeft = Console.CursorLeft; | |
_cursorVisible = Console.CursorVisible; | |
} | |
public void Dispose() | |
{ | |
RestoreState(); | |
} | |
public void RestoreState() | |
{ | |
Console.BackgroundColor = _bgColor; | |
Console.CursorTop = _cursorTop; | |
Console.CursorLeft = _cursorLeft; | |
Console.CursorVisible = _cursorVisible; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, if user resize console windows, get a ArgumentOutOfRangeException from DrawText().
(Console.WindowWidth - Console.CursorLeft) can´t be negative.