From b9a26e0e5d1045f5814e3ce6341647c92045e3c3 Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Sat, 5 Feb 2011 11:29:04 -0800 Subject: [PATCH] fancier output --- src/build.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++++++------------ src/build.h | 9 +++++++-- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/build.cc b/src/build.cc index 3e3482c..b380845 100644 --- a/src/build.cc +++ b/src/build.cc @@ -15,6 +15,8 @@ struct BuildStatus { // Returns the time the edge took, in ms. int BuildEdgeFinished(Edge* edge); + void PrintStatus(Edge* edge); + time_t last_update_; int finished_edges_, total_edges_; @@ -22,11 +24,16 @@ struct BuildStatus { RunningEdgeMap running_edges_; BuildConfig::Verbosity verbosity_; + // Whether we can do fancy terminal control codes. + bool smart_terminal_; }; BuildStatus::BuildStatus() : last_update_(time(NULL)), finished_edges_(0), total_edges_(0), - verbosity_(BuildConfig::NORMAL) {} + verbosity_(BuildConfig::NORMAL) { + const char* term = getenv("TERM"); + smart_terminal_ = isatty(1) && term && string(term) != "dumb"; +} void BuildStatus::PlanHasTotalEdges(int total) { total_edges_ = total; @@ -37,13 +44,7 @@ void BuildStatus::BuildEdgeStarted(Edge* edge) { gettimeofday(&now, NULL); running_edges_.insert(make_pair(edge, now)); - string desc = edge->GetDescription(); - if (verbosity_ != BuildConfig::QUIET) { - if (verbosity_ != BuildConfig::VERBOSE && !desc.empty()) - printf("%s\n", desc.c_str()); - else - printf("%s\n", edge->EvaluateCommand().c_str()); - } + PrintStatus(edge); } int BuildStatus::BuildEdgeFinished(Edge* edge) { @@ -51,10 +52,18 @@ int BuildStatus::BuildEdgeFinished(Edge* edge) { gettimeofday(&now, NULL); ++finished_edges_; - if (now.tv_sec - last_update_ > 5) { - printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_, - finished_edges_, total_edges_); - last_update_ = now.tv_sec; + if (verbosity_ != BuildConfig::QUIET) { + if (smart_terminal_ && verbosity_ == BuildConfig::NORMAL) { + PrintStatus(edge); + if (finished_edges_ == total_edges_) + printf("\n"); + } else { + if (now.tv_sec - last_update_ > 5) { + printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_, + finished_edges_, total_edges_); + last_update_ = now.tv_sec; + } + } } RunningEdgeMap::iterator i = running_edges_.find(edge); @@ -66,6 +75,33 @@ int BuildStatus::BuildEdgeFinished(Edge* edge) { return ms; } +void BuildStatus::PrintStatus(Edge* edge) { + switch (verbosity_) { + case BuildConfig::QUIET: + return; + + case BuildConfig::VERBOSE: + printf("%s\n", edge->EvaluateCommand().c_str()); + break; + + default: { + string to_print = edge->GetDescription(); + if (to_print.empty() || verbosity_ == BuildConfig::VERBOSE) + to_print = edge->EvaluateCommand(); + + if (smart_terminal_) { + printf("\r[%d/%d] %s\e[K", finished_edges_, total_edges_, + to_print.c_str()); + fflush(stdout); + } else { + printf("%s\n", to_print.c_str()); + } + } + } +} + +Plan::Plan() : command_edges_(0) {} + bool Plan::AddTarget(Node* node, string* err) { vector stack; return AddSubTarget(node, &stack, err); @@ -93,6 +129,8 @@ bool Plan::AddSubTarget(Node* node, vector* stack, string* err) { if (want_.find(edge) != want_.end()) return true; // We've already enqueued it. want_.insert(edge); + if (!edge->is_phony()) + ++command_edges_; stack->push_back(node); bool awaiting_inputs = false; @@ -302,7 +340,7 @@ bool Builder::Build(string* err) { return true; } - status_->PlanHasTotalEdges(plan_.edge_count()); + status_->PlanHasTotalEdges(plan_.command_edge_count()); while (plan_.more_to_do()) { while (command_runner_->CanRunMore()) { Edge* edge = plan_.FindWork(); diff --git a/src/build.h b/src/build.h index a1d6d4c..618cc28 100644 --- a/src/build.h +++ b/src/build.h @@ -15,6 +15,8 @@ struct State; // Plan stores the state of a build plan: what we intend to build, // which steps we're ready to execute. struct Plan { + Plan(); + // Add a target to our plan (including all its dependencies). // Returns false if we don't need to build this target; may // fill in |err| with an error message if there's a problem. @@ -34,8 +36,8 @@ struct Plan { // tests. void EdgeFinished(Edge* edge); - // Number of edges to run. - int edge_count() const { return want_.size(); } + // Number of edges with commands to run. + int command_edge_count() const { return command_edges_; } private: bool AddSubTarget(Node* node, vector* stack, string* err); @@ -44,6 +46,9 @@ private: set want_; set ready_; + + // Total number of edges that have commands (not phony). + int command_edges_; }; // CommandRunner is an interface that wraps running the build -- 2.7.4