Permalink
Browse files

[win32] Overprint the previous line if we're attached to a console

  • Loading branch information...
sgraham committed Feb 27, 2012
1 parent eab83e9 commit 7b3d8c8e903b848c6018eb60f26986714ce85720
Showing with 38 additions and 5 deletions.
  1. +38 −5 src/build.cc
View
@@ -61,6 +61,10 @@ struct BuildStatus {
/// Whether we can do fancy terminal control codes.
bool smart_terminal_;
+
+#ifdef _WIN32
+ HANDLE console_;
+#endif
};
BuildStatus::BuildStatus(const BuildConfig& config)
@@ -73,12 +77,14 @@ BuildStatus::BuildStatus(const BuildConfig& config)
const char* term = getenv("TERM");
smart_terminal_ = isatty(1) && term && string(term) != "dumb";
#else
- smart_terminal_ = false;
// Disable output buffer. It'd be nice to use line buffering but
// MSDN says: "For some systems, [_IOLBF] provides line
// buffering. However, for Win32, the behavior is the same as _IOFBF
// - Full Buffering."
setvbuf(stdout, NULL, _IONBF, 0);
+ console_ = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ smart_terminal_ = GetConsoleScreenBufferInfo(console_, &csbi);
#endif
// Don't do anything fancy in verbose mode.
@@ -174,13 +180,24 @@ void BuildStatus::PrintStatus(Edge* edge) {
if (to_print.empty() || force_full_command)
to_print = edge->EvaluateCommand();
- if (smart_terminal_)
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(console_, &csbi);
+#endif
+
+ if (smart_terminal_) {
+#ifndef _WIN32
printf("\r"); // Print over previous line, if any.
+#else
+ csbi.dwCursorPosition.X = 0;
+ SetConsoleCursorPosition(console_, csbi.dwCursorPosition);
+#endif
+ }
int progress_chars = printf("[%d/%d] ", started_edges_, total_edges_);
-#ifndef _WIN32
if (smart_terminal_ && !force_full_command) {
+#ifndef _WIN32
// Limit output to width of the terminal if provided so we don't cause
// line-wrapping.
winsize size;
@@ -193,17 +210,33 @@ void BuildStatus::PrintStatus(Edge* edge) {
+ to_print.substr(to_print.size() - elide_size, elide_size);
}
}
- }
#else
- NINJA_UNUSED_ARG(progress_chars);
+ const int kMargin = progress_chars + 3; // Space for [xx/yy] and "...".
+ // Don't use the full width or console with move to next line.
+ size_t width = static_cast<size_t>(csbi.dwSize.X) - 1;
+ if (to_print.size() + kMargin > width) {
+ int elide_size = (width - kMargin) / 2;
+ to_print = to_print.substr(0, elide_size)
+ + "..."
+ + to_print.substr(to_print.size() - elide_size, elide_size);
+ }
#endif
+ }
printf("%s", to_print.c_str());
if (smart_terminal_ && !force_full_command) {
+#ifndef _WIN32
printf("\x1B[K"); // Clear to end of line.
fflush(stdout);
have_blank_line_ = false;
+#else
+ // Clear to end of line.
+ GetConsoleScreenBufferInfo(console_, &csbi);
+ int num_spaces = csbi.dwSize.X - 1 - csbi.dwCursorPosition.X;
+ printf("%*s", num_spaces, "");
+ have_blank_line_ = false;
+#endif
} else {
printf("\n");
}

2 comments on commit 7b3d8c8

Contributor

syntheticpp replied Mar 25, 2012

Most MS tools always print the processed file, so even with this patch the output doesn't look like on Linux.

for instance:
[350/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudio10IA64Generator.cxx.obj
cmGlobalVisualStudio10IA64Generator.cxx
[351/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudio11Win64Generator.cxx.obj
cmGlobalVisualStudio11Win64Generator.cxx
[352/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudio10Win64Generator.cxx.obj
cmGlobalVisualStudio10Win64Generator.cxx
[353/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudio11Generator.cxx.obj
cmGlobalVisualStudio11Generator.cxx
[354/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmVisualStudio10TargetGenerator.cxx.obj
cmVisualStudio10TargetGenerator.cxx
[355/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalWatcomWMakeGenerator.cxx.obj
cmGlobalWatcomWMakeGenerator.cxx
[356/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudio10Generator.cxx.obj
cmGlobalVisualStudio10Generator.cxx
[357/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmIDEOptions.cxx.obj
cmIDEOptions.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmWin32ProcessExecution.cxx.obj
cmWin32ProcessExecution.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmLocalVisualStudioGenerator.cxx.obj
cmLocalVisualStudioGenerator.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmGlobalVisualStudioGenerator.cxx.obj
cmGlobalVisualStudioGenerator.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmNinjaTargetGenerator.cxx.obj
cmNinjaTargetGenerator.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmLocalNinjaGenerator.cxx.obj
cmLocalNinjaGenerator.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmLocalVisualStudio7Generator.cxx.obj
cmLocalVisualStudio7Generator.cxx
[358/431] Building CXX object Source\CMakeFiles\CMakeLib.dir\cmNinjaUtilityTargetGenerator.cxx.obj
cmNinjaUtilityTargetGenerator.cxx

Or have I missed a cl option?

Collaborator

evmar replied Apr 5, 2012

scottmg, what do you think?

Please sign in to comment.