aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-04-22 12:52:48 -0400
committerGitHub <noreply@github.com>2020-04-22 12:52:48 -0400
commit173a143dd04f9ec75355c04be9b0e6353ee9bc03 (patch)
tree3abbee7296ffab6e9e4b40f0d65a23dd9fd4ead7 /lib/std
parent0a2519fafb083e13fb40eac5afcfcb8b741e3438 (diff)
parent155e631aa6f9fabc101abceeeec00b4808a3e4e3 (diff)
downloadzig-173a143dd04f9ec75355c04be9b0e6353ee9bc03.tar.gz
zig-173a143dd04f9ec75355c04be9b0e6353ee9bc03.zip
Merge pull request #5133 from LemonBoy/win-progress
Progressbar for Windows
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/os/windows/kernel32.zig3
-rw-r--r--lib/std/progress.zig56
2 files changed, 52 insertions, 7 deletions
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 8cdf07c1aa..b50143b075 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -83,6 +83,9 @@ pub extern "kernel32" fn GetCommandLineA() callconv(.Stdcall) LPSTR;
pub extern "kernel32" fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: *DWORD) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: *CONSOLE_SCREEN_BUFFER_INFO) callconv(.Stdcall) BOOL;
+pub extern "kernel32" fn FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: TCHAR, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfCharsWritten: LPDWORD) callconv(.Stdcall) BOOL;
+pub extern "kernel32" fn FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfAttrsWritten: LPDWORD) callconv(.Stdcall) BOOL;
+pub extern "kernel32" fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;
diff --git a/lib/std/progress.zig b/lib/std/progress.zig
index a693ec8619..bde67f1a23 100644
--- a/lib/std/progress.zig
+++ b/lib/std/progress.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const windows = std.os.windows;
const testing = std.testing;
const assert = std.debug.assert;
@@ -99,7 +100,12 @@ pub const Progress = struct {
/// API to return Progress rather than accept it as a parameter.
pub fn start(self: *Progress, name: []const u8, estimated_total_items: ?usize) !*Node {
const stderr = std.io.getStdErr();
- self.terminal = if (stderr.supportsAnsiEscapeCodes()) stderr else null;
+ self.terminal = null;
+ if (stderr.supportsAnsiEscapeCodes()) {
+ self.terminal = stderr;
+ } else if (std.builtin.os.tag == .windows and stderr.isTty()) {
+ self.terminal = stderr;
+ }
self.root = Node{
.context = self,
.parent = null,
@@ -129,12 +135,48 @@ pub const Progress = struct {
const prev_columns_written = self.columns_written;
var end: usize = 0;
if (self.columns_written > 0) {
- // restore cursor position
- end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
- self.columns_written = 0;
+ // restore the cursor position by moving the cursor
+ // `columns_written` cells to the left, then clear the rest of the
+ // line
+ if (std.builtin.os.tag != .windows) {
+ end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
+ end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
+ } else {
+ var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
+ if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)
+ unreachable;
+
+ var cursor_pos = windows.COORD{
+ .X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written),
+ .Y = info.dwCursorPosition.Y,
+ };
+
+ if (cursor_pos.X < 0)
+ cursor_pos.X = 0;
- // clear rest of line
- end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
+ const fill_chars = @intCast(windows.DWORD, info.dwSize.X - cursor_pos.X);
+
+ var written: windows.DWORD = undefined;
+ if (windows.kernel32.FillConsoleOutputAttribute(
+ file.handle,
+ info.wAttributes,
+ fill_chars,
+ cursor_pos,
+ &written,
+ ) != windows.TRUE) unreachable;
+ if (windows.kernel32.FillConsoleOutputCharacterA(
+ file.handle,
+ ' ',
+ fill_chars,
+ cursor_pos,
+ &written,
+ ) != windows.TRUE) unreachable;
+
+ if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE)
+ unreachable;
+ }
+
+ self.columns_written = 0;
}
if (!self.done) {
@@ -195,7 +237,7 @@ pub const Progress = struct {
end.* = self.output_buffer.len;
},
}
- const bytes_needed_for_esc_codes_at_end = 11;
+ const bytes_needed_for_esc_codes_at_end = if (std.builtin.os.tag == .windows) 0 else 11;
const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end;
if (end.* > max_end) {
const suffix = "...";