mirror of
https://github.com/p-ranav/indicators.git
synced 2025-12-16 04:18:51 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2edbccce9c | ||
|
|
e6ae6c5513 | ||
|
|
1c2e7d5bd1 | ||
|
|
b6d0ec0ee0 | ||
|
|
cb879b5eb1 | ||
|
|
25001ceb1f | ||
|
|
21391f3ca0 | ||
|
|
55f9eb7c67 | ||
|
|
a516957135 | ||
|
|
56489bf37a | ||
|
|
8f903b9741 | ||
|
|
a938eb8f4c | ||
|
|
9e088af612 | ||
|
|
a41c7c118e | ||
|
|
cde4dbd83c | ||
|
|
6f69ca5246 | ||
|
|
d3ef0b0209 | ||
|
|
3012fa78cf |
@@ -2,8 +2,11 @@ cmake_minimum_required(VERSION 3.8)
|
||||
project(indica VERSION 1.0.0 LANGUAGES CXX)
|
||||
option(INDICA_BUILD_TESTS OFF)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_library(indica INTERFACE)
|
||||
add_library(indica::indica ALIAS indica)
|
||||
|
||||
@@ -11,10 +14,20 @@ target_compile_features(indica INTERFACE cxx_std_11)
|
||||
target_include_directories(indica INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>)
|
||||
target_link_libraries(indica INTERFACE Threads::Threads)
|
||||
|
||||
install(TARGETS indica EXPORT indicaConfig)
|
||||
install(EXPORT indicaConfig
|
||||
configure_package_config_file(indicaConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/indicaConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/indica)
|
||||
|
||||
install(TARGETS indica EXPORT indicaTargets)
|
||||
install(EXPORT indicaTargets
|
||||
FILE indicaTargets.cmake
|
||||
NAMESPACE indica::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/indica)
|
||||
install(FILES ${CMAKE_CURRENT_LIST_DIR}/include/indica.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/indica)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/indicaConfig.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/indica)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/indicators
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
USE_SOURCE_PERMISSIONS
|
||||
PATTERN "*.hpp")
|
||||
|
||||
31
LICENSE.termcolor
Normal file
31
LICENSE.termcolor
Normal file
@@ -0,0 +1,31 @@
|
||||
Copyright (c) 2013, Ihor Kalnytskyi.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms of the software as well
|
||||
as documentation, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
68
README.md
68
README.md
@@ -127,19 +127,28 @@ int main() {
|
||||
bar.set_foreground_color(indicators::Color::GREEN);
|
||||
|
||||
// Update bar state
|
||||
size_t i = 0;
|
||||
while (i < 101) {
|
||||
bar.set_progress(i);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
i += 10;
|
||||
}
|
||||
|
||||
bar.set_progress(10); // 10% done
|
||||
|
||||
// do some work
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
bar.set_progress(30); // 30% done
|
||||
|
||||
// do some more work
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
||||
|
||||
bar.set_progress(65); // 65% done
|
||||
|
||||
// do final bit of work
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
|
||||
bar.set_progress(100); // all done
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The above code will print a progress bar that goes from 0 to 100% at the rate of 10% every 100 ms.
|
||||
|
||||
## Multi-threaded Example
|
||||
|
||||
```cpp
|
||||
@@ -208,7 +217,48 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
For more examples, checkout the examples in the `samples/` directory.
|
||||
# Smooth Block Progress Bar
|
||||
|
||||
Are you in need of a smooth block progress bar using [unicode block elements](https://en.wikipedia.org/wiki/Block_Elements)? Use `BlockProgressBar` instead of `ProgressBar`. Thanks to [this blog post](https://mike42.me/blog/2018-06-make-better-cli-progress-bars-with-unicode-block-characters) for making `BlockProgressBar` an easy addition to the library.
|
||||
|
||||
<p align="center">
|
||||
<img height="70" src="img/block_progress_bar.gif"/>
|
||||
</p>
|
||||
|
||||
```cpp
|
||||
#include <indicators/block_progress_bar.hpp>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
int main() {
|
||||
|
||||
// Hide cursor
|
||||
std::cout << "\e[?25l";
|
||||
|
||||
indicators::BlockProgressBar bar;
|
||||
|
||||
// Configure the bar
|
||||
bar.set_bar_width(80);
|
||||
bar.start_bar_with("[");
|
||||
bar.end_bar_with("]");
|
||||
bar.set_foreground_color(indicators::Color::WHITE);
|
||||
|
||||
// Update bar state
|
||||
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 cursor
|
||||
std::cout << "\e[?25h";
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
# Progress Spinner
|
||||
|
||||
|
||||
BIN
img/block_progress_bar.gif
Normal file
BIN
img/block_progress_bar.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
183
include/indicators/block_progress_bar.hpp
Normal file
183
include/indicators/block_progress_bar.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
Activity Indicators for Modern C++
|
||||
https://github.com/p-ranav/indicators
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <indicators/color.hpp>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
namespace indicators {
|
||||
|
||||
class BlockProgressBar {
|
||||
public:
|
||||
void set_foreground_color(Color color) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_foreground_color = color;
|
||||
}
|
||||
|
||||
void set_bar_width(size_t bar_width) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_bar_width = bar_width;
|
||||
}
|
||||
|
||||
void start_bar_with(const std::string &start) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_start = start;
|
||||
}
|
||||
|
||||
void end_bar_with(const std::string &end) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_end = end;
|
||||
}
|
||||
|
||||
void set_prefix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_prefix_text = text;
|
||||
}
|
||||
|
||||
void set_postfix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_postfix_text = text;
|
||||
if (_postfix_text.length() > _max_postfix_text_length)
|
||||
_max_postfix_text_length = _postfix_text.length();
|
||||
}
|
||||
|
||||
void show_percentage() { _show_percentage = true; }
|
||||
|
||||
void hide_percentage() { _show_percentage = false; }
|
||||
|
||||
void set_progress(float value) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress = value;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
void tick() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress += 1;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
size_t current() {
|
||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
||||
}
|
||||
|
||||
bool is_completed() const { return _completed; }
|
||||
|
||||
void mark_as_completed() {
|
||||
_completed = true;
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
private:
|
||||
float _progress{0.0};
|
||||
size_t _bar_width{100};
|
||||
std::string _prefix_text{""};
|
||||
std::string _start{"["};
|
||||
std::string _fill{"█"};
|
||||
std::string _lead{" "};
|
||||
std::string _remainder{" "};
|
||||
std::string _end{"]"};
|
||||
std::string _postfix_text{""};
|
||||
std::atomic<size_t> _max_postfix_text_length{0};
|
||||
std::atomic<bool> _completed{false};
|
||||
std::atomic<bool> _show_percentage{true};
|
||||
std::mutex _mutex;
|
||||
Color _foreground_color;
|
||||
|
||||
void _print_progress() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
std::cout << termcolor::bold;
|
||||
switch (_foreground_color) {
|
||||
case Color::GREY:
|
||||
std::cout << termcolor::grey;
|
||||
break;
|
||||
case Color::RED:
|
||||
std::cout << termcolor::red;
|
||||
break;
|
||||
case Color::GREEN:
|
||||
std::cout << termcolor::green;
|
||||
break;
|
||||
case Color::YELLOW:
|
||||
std::cout << termcolor::yellow;
|
||||
break;
|
||||
case Color::BLUE:
|
||||
std::cout << termcolor::blue;
|
||||
break;
|
||||
case Color::MAGENTA:
|
||||
std::cout << termcolor::magenta;
|
||||
break;
|
||||
case Color::CYAN:
|
||||
std::cout << termcolor::cyan;
|
||||
break;
|
||||
case Color::WHITE:
|
||||
std::cout << termcolor::white;
|
||||
break;
|
||||
}
|
||||
std::cout << _prefix_text;
|
||||
std::cout << _start;
|
||||
|
||||
std::vector<std::string> lead_characters{" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"};
|
||||
auto progress = std::min(1.0f, std::max(0.0f, _progress / 100.0f));
|
||||
auto whole_width = std::floor(progress * _bar_width);
|
||||
auto remainder_width = fmod((progress * _bar_width), 1.0f);
|
||||
auto part_width = std::floor(remainder_width * lead_characters.size());
|
||||
_lead = lead_characters[part_width];
|
||||
if ((_bar_width - whole_width - 1) < 0)
|
||||
_lead = "";
|
||||
for (size_t i = 0; i < whole_width; ++i)
|
||||
std::cout << _fill;
|
||||
std::cout << _lead;
|
||||
for (size_t i = 0; i < (_bar_width - whole_width - 1); ++i)
|
||||
std::cout << " ";
|
||||
|
||||
std::cout << _end;
|
||||
if (_show_percentage) {
|
||||
std::cout << " " << std::min(static_cast<size_t>(_progress), size_t(100)) << "%";
|
||||
}
|
||||
if (_max_postfix_text_length == 0)
|
||||
_max_postfix_text_length = 10;
|
||||
std::cout << " " << _postfix_text << std::string(_max_postfix_text_length, ' ') << "\r";
|
||||
std::cout.flush();
|
||||
if (_progress > 100.0) {
|
||||
_completed = true;
|
||||
}
|
||||
if (_completed)
|
||||
std::cout << termcolor::reset << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace indicators
|
||||
@@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <indicators/color.hpp>
|
||||
#include <iostream>
|
||||
@@ -104,7 +105,6 @@ public:
|
||||
}
|
||||
|
||||
size_t current() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <indicators/color.hpp>
|
||||
#include <iostream>
|
||||
@@ -79,7 +80,6 @@ public:
|
||||
}
|
||||
|
||||
size_t current() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
||||
}
|
||||
|
||||
|
||||
9
indicaConfig.cmake.in
Normal file
9
indicaConfig.cmake.in
Normal file
@@ -0,0 +1,9 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency(Threads)
|
||||
|
||||
if (NOT TARGET indica::indica)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/indicaTargets.cmake)
|
||||
endif ()
|
||||
32
samples/block_progress_bar.cpp
Normal file
32
samples/block_progress_bar.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <indicators/block_progress_bar.hpp>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
int main() {
|
||||
|
||||
// Hide cursor
|
||||
std::cout << "\e[?25l";
|
||||
|
||||
indicators::BlockProgressBar bar;
|
||||
|
||||
// Configure the bar
|
||||
bar.set_bar_width(80);
|
||||
bar.start_bar_with("[");
|
||||
bar.end_bar_with("]");
|
||||
bar.set_foreground_color(indicators::Color::WHITE);
|
||||
|
||||
// Update bar state
|
||||
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 cursor
|
||||
std::cout << "\e[?25h";
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user