1212#include < filesystem>
1313#include < fstream>
1414#include < future>
15+ #include < map>
16+ #include < mutex>
1517#include < regex>
1618#include < string>
1719#include < thread>
@@ -469,36 +471,79 @@ std::pair<long, std::vector<char>> common_remote_get_content(const std::string &
469471
470472#elif defined(LLAMA_USE_HTTPLIB)
471473
472- static bool is_output_a_tty () {
474+ class ProgressBar {
475+ static inline std::mutex mutex;
476+ static inline std::map<const ProgressBar *, int > lines;
477+ static inline int max_line = 0 ;
478+
479+ static void cleanup (const ProgressBar * line) {
480+ lines.erase (line);
481+ if (lines.empty ()) {
482+ max_line = 0 ;
483+ }
484+ }
485+
486+ static bool is_output_a_tty () {
473487#if defined(_WIN32)
474- return _isatty (_fileno (stdout));
488+ return _isatty (_fileno (stdout));
475489#else
476- return isatty (1 );
490+ return isatty (1 );
477491#endif
478- }
492+ }
479493
480- static void print_progress (size_t current, size_t total) {
481- if (!is_output_a_tty ()) {
482- return ;
494+ public:
495+ ProgressBar () = default ;
496+
497+ ~ProgressBar () {
498+ std::lock_guard<std::mutex> lock (mutex);
499+ cleanup (this );
483500 }
484501
485- if (!total) {
486- return ;
502+ void update (size_t current, size_t total) {
503+ if (!is_output_a_tty ()) {
504+ return ;
505+ }
506+
507+ if (!total) {
508+ return ;
509+ }
510+
511+ std::lock_guard<std::mutex> lock (mutex);
512+
513+ if (lines.find (this ) == lines.end ()) {
514+ lines[this ] = max_line++;
515+ std::cout << " \n " ;
516+ }
517+ int lines_up = max_line - lines[this ];
518+
519+ size_t width = 50 ;
520+ size_t pct = (100 * current) / total;
521+ size_t pos = (width * current) / total;
522+
523+ std::cout << " \033 [s" ;
524+
525+ if (lines_up > 0 ) {
526+ std::cout << " \033 [" << lines_up << " A" ;
527+ }
528+ std::cout << " \033 [2K\r ["
529+ << std::string (pos, ' =' )
530+ << (pos < width ? " >" : " " )
531+ << std::string (width - pos, ' ' )
532+ << " ] " << std::setw (3 ) << pct << " % ("
533+ << current / (1024 * 1024 ) << " MB / "
534+ << total / (1024 * 1024 ) << " MB) "
535+ << " \033 [u" ;
536+
537+ std::cout.flush ();
538+
539+ if (current == total) {
540+ cleanup (this );
541+ }
487542 }
488543
489- size_t width = 50 ;
490- size_t pct = (100 * current) / total;
491- size_t pos = (width * current) / total;
492-
493- std::cout << " ["
494- << std::string (pos, ' =' )
495- << (pos < width ? " >" : " " )
496- << std::string (width - pos, ' ' )
497- << " ] " << std::setw (3 ) << pct << " % ("
498- << current / (1024 * 1024 ) << " MB / "
499- << total / (1024 * 1024 ) << " MB)\r " ;
500- std::cout.flush ();
501- }
544+ ProgressBar (const ProgressBar &) = delete ;
545+ ProgressBar & operator =(const ProgressBar &) = delete ;
546+ };
502547
503548static bool common_pull_file (httplib::Client & cli,
504549 const std::string & resolve_path,
@@ -520,6 +565,7 @@ static bool common_pull_file(httplib::Client & cli,
520565 const char * func = __func__; // avoid __func__ inside a lambda
521566 size_t downloaded = existing_size;
522567 size_t progress_step = 0 ;
568+ ProgressBar bar;
523569
524570 auto res = cli.Get (resolve_path, headers,
525571 [&](const httplib::Response &response) {
@@ -551,16 +597,14 @@ static bool common_pull_file(httplib::Client & cli,
551597 progress_step += len;
552598
553599 if (progress_step >= total_size / 1000 || downloaded == total_size) {
554- print_progress (downloaded, total_size);
600+ bar. update (downloaded, total_size);
555601 progress_step = 0 ;
556602 }
557603 return true ;
558604 },
559605 nullptr
560606 );
561607
562- std::cout << " \n " ;
563-
564608 if (!res) {
565609 LOG_ERR (" %s: error during download. Status: %d\n " , __func__, res ? res->status : -1 );
566610 return false ;
0 commit comments