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)
|
project(indica VERSION 1.0.0 LANGUAGES CXX)
|
||||||
option(INDICA_BUILD_TESTS OFF)
|
option(INDICA_BUILD_TESTS OFF)
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
add_library(indica INTERFACE)
|
add_library(indica INTERFACE)
|
||||||
add_library(indica::indica ALIAS indica)
|
add_library(indica::indica ALIAS indica)
|
||||||
|
|
||||||
@@ -11,10 +14,20 @@ target_compile_features(indica INTERFACE cxx_std_11)
|
|||||||
target_include_directories(indica INTERFACE
|
target_include_directories(indica INTERFACE
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>)
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>)
|
||||||
|
target_link_libraries(indica INTERFACE Threads::Threads)
|
||||||
|
|
||||||
install(TARGETS indica EXPORT indicaConfig)
|
configure_package_config_file(indicaConfig.cmake.in
|
||||||
install(EXPORT indicaConfig
|
${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::
|
NAMESPACE indica::
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/indica)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/indica)
|
||||||
install(FILES ${CMAKE_CURRENT_LIST_DIR}/include/indica.hpp
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/indicaConfig.cmake
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/indica)
|
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.
|
||||||
70
README.md
70
README.md
@@ -127,19 +127,28 @@ int main() {
|
|||||||
bar.set_foreground_color(indicators::Color::GREEN);
|
bar.set_foreground_color(indicators::Color::GREEN);
|
||||||
|
|
||||||
// Update bar state
|
// Update bar state
|
||||||
size_t i = 0;
|
|
||||||
while (i < 101) {
|
bar.set_progress(10); // 10% done
|
||||||
bar.set_progress(i);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
// do some work
|
||||||
i += 10;
|
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;
|
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
|
## Multi-threaded Example
|
||||||
|
|
||||||
```cpp
|
```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
|
# 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.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <indicators/color.hpp>
|
#include <indicators/color.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -104,7 +105,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t current() {
|
size_t current() {
|
||||||
std::unique_lock<std::mutex> lock{_mutex};
|
|
||||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
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.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <indicators/color.hpp>
|
#include <indicators/color.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -79,7 +80,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t current() {
|
size_t current() {
|
||||||
std::unique_lock<std::mutex> lock{_mutex};
|
|
||||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
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