Project Icon

indicators

C++进度条和加载动画库

indicators是一个C++库,提供线程安全的进度条和加载动画。支持多种进度条样式,包括基本、不确定、方块、多进度和动态进度条。该库为头文件式,使用简便,并可自定义Unicode、颜色和字体等选项。适用于需在命令行界面显示进度的C++应用。

codacy license version

亮点

  • 线程安全的进度条和加载动画
  • 仅头文件库。获取include/indicators的副本。
  • 单头文件版本在single_include/indicators中。
  • 上述GIF的源代码可以在这里找到
  • MIT许可证

目录

基本进度条

要在应用程序中引入进度条,请包含indicators/progress_bar.hpp并创建一个ProgressBar对象。以下是进度条的一般结构:

{前缀} {开始} {填充} {引导} {剩余} {结束} {百分比} [{已用时间}<{剩余时间}] {后缀}
         ^^^^^^^^^^^^^ 条宽 ^^^^^^^^^^^^^^^   

ProgressBar中的进度量以size_t类型维护,范围为[0, 100]。当进度达到100时,进度完成。

从应用程序级代码,有两种方法可以更新这个进度:

使用bar.tick()更新进度

你可以使用bar.tick()更新进度条,它每次将进度增加恰好1%

#include <indicators/progress_bar.hpp>
#include <thread>
#include <chrono>

int main() {
  using namespace indicators;
  ProgressBar bar{
    option::BarWidth{50},
    option::Start{"["},
    option::Fill{"="},
    option::Lead{">"},
    option::Remainder{" "},
    option::End{"]"},
    option::PostfixText{"正在提取归档"},
    option::ForegroundColor{Color::green},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };
  
  // 更新进度条状态
  while (true) {
    bar.tick();
    if (bar.is_completed())
      break;
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  return 0;
}

上述代码将打印一个进度条,每100毫秒增加1%,从0%到100%。

使用bar.set_progress(value)更新进度

如果你希望以离散步骤控制进度条的进度,可以考虑使用bar.set_progress(value)。例如:

#include <chrono>
#include <indicators/cursor_control.hpp>
#include <indicators/progress_bar.hpp>
#include <thread>

int main() {
  using namespace indicators;

  // 隐藏光标
  show_console_cursor(false);

  ProgressBar bar{
    option::BarWidth{50},
    option::Start{"["},
    option::Fill{"■"},
    option::Lead{"■"},
    option::Remainder{"-"},
    option::End{" ]"},
    option::PostfixText{"正在加载依赖项 1/4"},
    option::ForegroundColor{Color::cyan},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };

  // 更新进度条状态
  bar.set_progress(10); // 完成10%

  // 执行一些工作
  std::this_thread::sleep_for(std::chrono::milliseconds(800));

  bar.set_option(option::PostfixText{"正在加载依赖项 2/4"});  

  bar.set_progress(30); // 完成30%

  // 执行更多工作
  std::this_thread::sleep_for(std::chrono::milliseconds(700));

  bar.set_option(option::PostfixText{"正在加载依赖项 3/4"});  

  bar.set_progress(65); // 完成65%

  // 执行最后一部分工作
  std::this_thread::sleep_for(std::chrono::milliseconds(900));

  bar.set_option(option::PostfixText{"依赖项已加载!"});

  bar.set_progress(100); // 全部完成

  // 显示光标
  show_console_cursor(true);

  return 0;
}

显示已用时间/剩余时间

indicators中的所有进度条和加载动画都支持显示已用时间和剩余时间。受Python的tqdm模块启发,这个计时器的格式是[{已用时间}<{剩余时间}]

#include <chrono>
#include <indicators/cursor_control.hpp>
#include <indicators/progress_bar.hpp>
#include <thread>

int main() {
  using namespace indicators;

  // 隐藏光标
  show_console_cursor(false);

  indicators::ProgressBar bar{
    option::BarWidth{50},
    option::Start{" ["},
    option::Fill{"█"},
    option::Lead{"█"},
    option::Remainder{"-"},
    option::End{"]"},
    option::PrefixText{"训练注视网络 👀"},
    option::ForegroundColor{Color::yellow},
    option::ShowElapsedTime{true},
    option::ShowRemainingTime{true},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };

  // 更新进度条状态
  while (true) {
    bar.tick();
    if (bar.is_completed())
      break;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  }

  // 显示光标
  show_console_cursor(true);

  return 0;
}

不确定进度条

你可能有一个需要进度条但最大进度未知的用例,例如,你正在从一个没有公布总字节数的远程服务器下载内容。

在这种情况下使用indicators::IndeterminateProgressBarIndeterminateProgressBar类似于常规进度条,只是要达到的总进度是未知的。这种进度条的tick可以无限运行。

当你知道进度完成时,只需调用bar.mark_as_completed()

#include <chrono>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <indicators/termcolor.hpp>
#include <thread>

int main() {
  indicators::IndeterminateProgressBar bar{
      indicators::option::BarWidth{40},
      indicators::option::Start{"["},
      indicators::option::Fill{"·"},
      indicators::option::Lead{"<==>"},
      indicators::option::End{"]"},
      indicators::option::PostfixText{"检查更新"},
      indicators::option::ForegroundColor{indicators::Color::yellow},
      indicators::option::FontStyles{
          std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
  };

  indicators::show_console_cursor(false);

  auto job = [&bar]() {
    std::this_thread::sleep_for(std::chrono::milliseconds(10000));
    bar.mark_as_completed();
    std::cout << termcolor::bold << termcolor::green 
        << "系统已是最新版本!\n" << termcolor::reset;
  };
  std::thread job_completion_thread(job);

  // 更新进度条状态
  while (!bar.is_completed()) {
    bar.tick();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  job_completion_thread.join();
  
  indicators::show_console_cursor(true);  
  return 0;
}

块进度条

你是否需要使用Unicode块元素的平滑块进度条?使用BlockProgressBar而不是ProgressBar。感谢这篇博客文章使BlockProgressBar成为该库的一个简单添加。

#include <indicators/block_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>
#include <chrono>

int main() {

  using namespace indicators;

  // 隐藏光标
  show_console_cursor(false);

  BlockProgressBar bar{
    option::BarWidth{80},
    option::Start{"["},
    option::End{"]"},
    option::ForegroundColor{Color::white}  ,
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };
  
  // 更新进度条状态
  auto progress = 0.0f;
  while (true) {
    bar.set_progress(progress);
    progress += 0.25f;
    if (bar.is_completed())
      break;
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
  }

  // 显示光标
  show_console_cursor(true);

  return 0;
}

多重进度

indicators支持使用MultiProgress类模板管理多个进度条。

template <typename Indicator, size_t count> class MultiProgress是一个类模板,它持有多个进度条的引用,并提供一个安全的接口来更新每个进度条的状态。MultiProgress适用于ProgressBarBlockProgressBar类。

如果你在编译时知道要管理的进度条数量,请使用此类。

以下是一个管理三个ProgressBar对象的MultiProgress对象的示例。

#include <indicators/multi_progress.hpp>
#include <indicators/progress_bar.hpp>

int main() {
  using namespace indicators;
  // 配置第一个进度条
  ProgressBar bar1{
    option::BarWidth{50},
    option::Start{"["},
    option::Fill{"■"},
    option::Lead{"■"},
    option::Remainder{" "},
    option::End{" ]"},
    option::ForegroundColor{Color::yellow},
    option::ShowElapsedTime{true},
    option::ShowRemainingTime{true},
    option::PrefixText{"进度条 #1 "},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };

  // 配置第二个进度条
ProgressBar bar2{
    option::BarWidth{50},
    option::Start{"["},
    option::Fill{"="},
    option::Lead{">"},
    option::Remainder{" "},
    option::End{" ]"},
    option::ForegroundColor{Color::cyan},
    option::ShowElapsedTime{true},
    option::ShowRemainingTime{true},
    option::PrefixText{"进度条 #2 "},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};

// 配置第三个进度条
indicators::ProgressBar bar3{
    option::BarWidth{50},
    option::Start{"["},
    option::Fill{"#"},
    option::Lead{"#"},
    option::Remainder{" "},
    option::End{" ]"},
    option::ForegroundColor{Color::red},
    option::ShowElapsedTime{true},
    option::ShowRemainingTime{true},
    option::PrefixText{"进度条 #3 "},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};

// 构造 MultiProgress 对象
indicators::MultiProgress<indicators::ProgressBar, 3> bars(bar1, bar2, bar3);

std::cout << "多个进度条:\n";

auto job1 = [&bars]() {
    while (true) {
        bars.tick<0>();
        if (bars.is_completed<0>())
            break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
};

auto job2 = [&bars]() {
    while (true) {
        bars.tick<1>();
        if (bars.is_completed<1>())
            break;
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
};

auto job3 = [&bars]() {
    while (true) {
        bars.tick<2>();
        if (bars.is_completed<2>())
            break;
        std::this_thread::sleep_for(std::chrono::milliseconds(60));
    }
};

std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);

first_job.join();
second_job.join();
third_job.join();

return 0;
}

DynamicProgress

DynamicProgress 是一个容器类,类似于 MultiProgress,用于管理多个进度条。顾名思义,使用 DynamicProgress,您可以动态添加新的进度条。

要添加新的进度条,调用 bars.push_back(new_bar)。这个调用将返回追加的条的索引。然后您可以使用索引运算符引用这个条,例如 bars[4].set_progress(55)

如果您在编译时不知道进度条的数量,请使用这个类。

下面是一个 DynamicProgress 对象的示例,它管理六个 ProgressBar 对象。其中三个条是动态添加的。

#include <indicators/dynamic_progress.hpp>
#include <indicators/progress_bar.hpp>
using namespace indicators;

int main() {

  auto bar1 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::red},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"5c90d4a2d1a8: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  auto bar2 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::yellow},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"22337bfd13a9: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  auto bar3 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::green},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"10f26c680a34: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  auto bar4 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::white},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"6364e0d7a283: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  auto bar5 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::blue},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"ff1356ba118b: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  auto bar6 = std::make_unique<ProgressBar>(option::BarWidth{50},
                   option::ForegroundColor{Color::cyan},
                   option::ShowElapsedTime{true},
                   option::ShowRemainingTime{true},
                   option::PrefixText{"5a17453338b4: 下载中 "},
                   indicators::option::FontStyles{
                       std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});

  std::cout << termcolor::bold << termcolor::white << "拉取镜像 foo:bar/baz\n";

  // 构造包含3个进度条。我们稍后会再添加3个
  DynamicProgress<ProgressBar> bars(bar1, bar2, bar3);

  // 完成时不隐藏进度条
  bars.set_option(option::HideBarWhenComplete{false});

  std::thread fourth_job, fifth_job, sixth_job;

  auto job4 = [&bars](size_t i) {
    while (true) {
      bars[i].tick();
      if (bars[i].is_completed()) {
        bars[i].set_option(option::PrefixText{"6364e0d7a283: 拉取完成 "});
        bars[i].mark_as_completed();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
  };

  auto job5 = [&bars](size_t i) {
    while (true) {
      bars[i].tick();
      if (bars[i].is_completed()) {
        bars[i].set_option(option::PrefixText{"ff1356ba118b: 拉取完成 "});
        bars[i].mark_as_completed();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
  };

  auto job6 = [&bars](size_t i) {
    while (true) {
      bars[i].tick();
      if (bars[i].is_completed()) {
        bars[i].set_option(option::PrefixText{"5a17453338b4: 拉取完成 "});
        bars[i].mark_as_completed();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(40));
    }
  };

  auto job1 = [&bars, &bar6, &sixth_job, &job6]() {
    while (true) {
      bars[0].tick();
      if (bars[0].is_completed()) {
        bars[0].set_option(option::PrefixText{"5c90d4a2d1a8: 拉取完成 "});
        // bar1 完成,添加 bar6
        auto i = bars.push_back(std::move(bar6));
        sixth_job = std::thread(job6, i);
        sixth_job.join();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(140));
    }
  };

  auto job2 = [&bars, &bar5, &fifth_job, &job5]() {
    while (true) {
      bars[1].tick();
      if (bars[1].is_completed()) {
        bars[1].set_option(option::PrefixText{"22337bfd13a9: 拉取完成 "});
        // bar2 完成,添加 bar5
        auto i = bars.push_back(std::move(bar5));
        fifth_job = std::thread(job5, i);
        fifth_job.join();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
  };

  auto job3 = [&bars, &bar4, &fourth_job, &job4]() {
    while (true) {
      bars[2].tick();
      if (bars[2].is_completed()) {
        bars[2].set_option(option::PrefixText{"10f26c680a34: 拉取完成 "});
        // bar3 完成,添加 bar4
        auto i = bars.push_back(std::move(bar4));
        fourth_job = std::thread(job4, i);
        fourth_job.join();
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
  };

  std::thread first_job(job1);
  std::thread second_job(job2);
  std::thread third_job(job3);

  third_job.join();
  second_job.join();
  first_job.join();

  std::cout << termcolor::bold << termcolor::green << "✔ 下载完成镜像 foo/bar:baz" << std::endl;
  std::cout << termcolor::reset;

  return 0;
}

在上面的代码中,注意选项 bars.set_option(option::HideBarWhenComplete{true});。是的,您可以通过将此选项设置为 true 来在进度条完成时隐藏它们。如果这样做,上面的例子将看起来像这样:

进度旋转器

要在应用程序中引入进度旋转器,包含 indicators/progress_spinner.hpp 并创建一个 ProgressSpinner 对象。以下是进度旋转器的一般结构:

{前缀} {旋转器} {百分比} [{已用时间}<{剩余时间}] {后缀}

ProgressSpinner 有一个字符串向量:spinner_states。每次更新时,旋转器将从这个序列中选择下一个字符串打印到控制台。旋转器状态可以类似于进度条进行更新:使用 tick()set_progress(value)

#include <indicators/progress_spinner.hpp>

int main() {
  using namespace indicators;
  indicators::ProgressSpinner spinner{
    option::PostfixText{"正在检查凭证"},
    option::ForegroundColor{Color::yellow},
    option::SpinnerStates{std::vector<std::string>{"⠈", "⠐", "⠠", "⢀", "⡀", "⠄", "⠂", "⠁"}},
    option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
  };
 
  // 更新旋转器状态
  auto job = [&spinner]() {
    while (true) {
      if (spinner.is_completed()) {
        spinner.set_option(option::ForegroundColor{Color::green});
        spinner.set_option(option::PrefixText{"✔"});
        spinner.set_option(option::ShowSpinner{false});
        spinner.set_option(option::ShowPercentage{false});
        spinner.set_option(option::PostfixText{"已认证!"});
        spinner.mark_as_completed();	
        break;
      } else
        spinner.tick();
      std::this_thread::sleep_for(std::chrono::milliseconds(40));
    }
  };
  std::thread thread(job);
  thread.join();  

  return 0;
}

递减进度

indicators 允许您轻松控制进度方向,即递增或递减进度,使用 option::ProgressType。要编程一个倒计时进度条,使用 option::ProgressType::decremental

#include <chrono>
#include <indicators/progress_bar.hpp>
#include <thread>
using namespace indicators;

int main() {

  ProgressBar bar{option::BarWidth{50},
                  option::ProgressType{ProgressType::decremental},
                  option::Start{"["},
                  option::Fill{"■"},
                  option::Lead{"■"},
                  option::Remainder{"-"},
                  option::End{"]"},
                  option::PostfixText{"正在还原系统恢复"},
                  option::ForegroundColor{Color::yellow},
                  option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}};

  // 更新进度条状态
  while (true) {
    bar.tick();
    if (bar.is_completed())
      break;
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  std::cout << termcolor::bold << termcolor::white
            << "任务成功失败\n" << termcolor::reset;

  return 0;
}

使用可迭代对象

如果您想使用进度条来指示在迭代可迭代对象(例如数字列表)时的进度,可以通过使用 option::MaxProgress 来实现:

#include <chrono>
#include <indicators/block_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>

int main() {

  // 隐藏光标
  indicators::show_console_cursor(false);

  // 随机数字列表
  std::vector<size_t> numbers;
  for (size_t i = 0; i < 1259438; ++i) {
      numbers.push_back(i);
  }

  using namespace indicators;
  BlockProgressBar bar{
    option::BarWidth{80},
    option::ForegroundColor{Color::white},
    option::FontStyles{
          std::vector<FontStyle>{FontStyle::bold}},
    option::MaxProgress{numbers.size()}
  };

  std::cout << "迭代数字列表(大小 = "
            << numbers.size() << ")\n";

  std::vector<size_t> result;
  for (size_t i = 0; i < numbers.size(); ++i) {

    // 执行一些计算
    result.push_back(numbers[i] * numbers[i]);

    // 显示迭代作为后缀文本
    bar.set_option(option::PostfixText{
      std::to_string(i) + "/" + std::to_string(numbers.size())
    });

    // 更新进度条
    bar.tick();
  }

  bar.mark_as_completed();

  // 显示光标
  indicators::show_console_cursor(true);

  return 0;
}

Unicode 支持

indicators 支持进度条中的多字节 Unicode 字符。

如果设置了 option::BarWidth,库会尽量遵守这个设置。在填充进度条时,如果下一个 Fill 字符串的显示宽度会超过进度条宽度,那么库会用 ' ' 空格字符填充进度条的剩余部分。

以下是一些进度条的示例,每个进度条的宽度为 50,显示不同的 Unicode 字符:

#include <chrono>
#include <indicators/progress_bar.hpp>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>

int main() {

    indicators::show_console_cursor(false);

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    {
        // 普通 ASCII
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"="},
            indicators::option::Lead{">"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"普通 ASCII"},
            indicators::option::ForegroundColor{indicators::Color::green},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    {
        // Unicode
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"驚くばかり"},
            indicators::option::Lead{">"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"日语"},
            indicators::option::ForegroundColor{indicators::Color::yellow},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    {
        // 俄语
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"Потрясающие"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"俄语"},
            indicators::option::ForegroundColor{indicators::Color::red},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    {
        // 希腊语
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"Φοβερός"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"希腊语"},
            indicators::option::ForegroundColor{indicators::Color::cyan},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    {
        // 中文
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"太棒了"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"中文"},
            indicators::option::ForegroundColor{indicators::Color::green},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }        
    }

    {
        // 表情符号
        indicators::ProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"🔥"},
            indicators::option::Lead{"🔥"},
            indicators::option::Remainder{" "},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"表情符号"},
            indicators::option::ForegroundColor{indicators::Color::white},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        // 更新进度条状态
        while (true) {
            bar.tick();
            if (bar.is_completed())
            break;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    {
        // 不确定进度条
        indicators::IndeterminateProgressBar bar{
            indicators::option::BarWidth{50},
            indicators::option::Start{"["},
            indicators::option::Fill{"✯"},
            indicators::option::Lead{"載入中"},
            indicators::option::End{" ]"},
            indicators::option::PostfixText{"加载进度条"},
            indicators::option::ForegroundColor{indicators::Color::yellow},
            indicators::option::FontStyles{
                std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
        };

        auto job = [&bar]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(10000));
            bar.mark_as_completed();
        };
        std::thread job_completion_thread(job);

        // 更新进度条状态
        while (!bar.is_completed()) {
            bar.tick();
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }

        job_completion_thread.join();
    }

    indicators::show_console_cursor(true);

  return 0;
}

构建示例

git clone https://github.com/p-ranav/indicators
cd indicators
mkdir build && cd build
cmake -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
make

WinLibs + MinGW

对于 Windows,如果你像我一样使用 WinLibs,cmake 命令会像这样:

foo@bar:~$ mkdir build && cd build
foo@bar:~$ cmake -G "MinGW Makefiles" -DCMAKE_CXX_COMPILER="C:/WinLibs/mingw64/bin/g++.exe" -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
foo@bar:~$ make -j4

生成单头文件

python3 utils/amalgamate/amalgamate.py -c single_include.json -s .

贡献

欢迎贡献,请查看 CONTRIBUTING.md 文档以获取更多信息。

许可

该项目使用 MIT 许可证。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号