콘솔 프로그레스 바

내 이 세상 도처에서 쉴 곳을 찾아보았으나, 마침내 찾아낸, 컴퓨터가 있는 구석방보다 나은 곳은 없더라.

콘솔 프로그레스 바

콘솔에서 프로그레스 바를 그릴 때 요령은 행을 바꾸지 않고 같은 행에 텍스트를 계속 갱신하는 것이다. 프로그레스 바와 진행률을 제외하면 다른 텍스트는 바뀌지 않을 것이므로 \r로 커서를 행의 처음으로 옮긴 후 새로운 텍스트로 덮어쓰면 프로그레스바가 깜박거리지 않을 것이다.

두 개 이상의 프로그레스 바를 그리려면 어떻게 해야 할까? 커서를 위로 옮길 수도 있어야 하므로 \r 만으로는 안 되고, ANSI 이스케이프 코드를 써야 한다. ANSI 이스케이프 코드를 사용하면 콘솔 화면에서 커서를 이동하거나 출력 글자의 색상을 바꿀 수 있다.

\r을 이용해 콘솔에 프로그레스 바를 출력하는 간단한 프로그램을 작성했다. 프로그레스 바를 그리는 부분은 그냥 \r를 썼고, ANSI 이스케이프 코드를 이용해 커서를 숨기고 글자 색상을 바꾸었다.

use std::{thread, time};
use std::io::{Write, stdout};

fn main() {
  let complete_char = "=";
  let pause_time = time::Duration::from_millis(50);

  println!("Start:");
  print!("\u{001b}[?25l");      // hide cursor
  print!("\u{001b}[34m");       // change text color to yellow
  for _i in 1..=100 {
    let complete = complete_char.repeat(_i/2);
    print!("\rProgress: |{:-<50}| {:3}%", complete, _i);

    stdout().flush().unwrap();
    thread::sleep(pause_time);
  }

  print!("\u{001b}[0m");        // reset color
  println!("\nFinished.");
  print!("\u{001b}[?25h");      // show cursor
}

여기서는 프로그레스 바를 그릴 때는 러스트의 포매팅 기능을 사용했지만, 다른 방법을 사용해도 된다. 프로그레스 바를 업데이트한 다음 버퍼를 flush 해야 화면이 바로바로 갱신된다.

프로그래밍 언어별로 콘솔에서 프로그레스 바를 표시하게 해 주는 라이브러리가 이미 개발되어 있다. 프로그레스 바 모양을 쉽게 바꿀 수 있고 사용하기 편리한 프로그래밍 인터페이스도 제공한다. 콘솔에 프로그레스 바를 그릴 일이 있다면 아마도 라이브러리를 사용하는 편이 나을 것이다.

참고