| ... | @@ -22,6 +22,10 @@ const Progress = @This(); | ... | @@ -22,6 +22,10 @@ const Progress = @This(); |
| 22 | /// not print on update() | 22 | /// not print on update() |
| 23 | terminal: ?std.fs.File = undefined, | 23 | terminal: ?std.fs.File = undefined, |
| 24 | | 24 | |
| | 25 | /// Is this a windows API terminal (note: this is not the same as being run on windows |
| | 26 | /// because other terminals exist like MSYS/git-bash) |
| | 27 | is_windows_terminal: bool = false, |
| | 28 | |
| 25 | /// Whether the terminal supports ANSI escape codes. | 29 | /// Whether the terminal supports ANSI escape codes. |
| 26 | supports_ansi_escape_codes: bool = false, | 30 | supports_ansi_escape_codes: bool = false, |
| 27 | | 31 | |
| ... | @@ -143,6 +147,7 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* | ... | @@ -143,6 +147,7 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* |
| 143 | self.terminal = stderr; | 147 | self.terminal = stderr; |
| 144 | self.supports_ansi_escape_codes = true; | 148 | self.supports_ansi_escape_codes = true; |
| 145 | } else if (std.builtin.os.tag == .windows and stderr.isTty()) { | 149 | } else if (std.builtin.os.tag == .windows and stderr.isTty()) { |
| | 150 | self.is_windows_terminal = true; |
| 146 | self.terminal = stderr; | 151 | self.terminal = stderr; |
| 147 | } else if (std.builtin.os.tag != .windows) { | 152 | } else if (std.builtin.os.tag != .windows) { |
| 148 | // we are in a "dumb" terminal like in acme or writing to a file | 153 | // we are in a "dumb" terminal like in acme or writing to a file |
| ... | @@ -192,8 +197,9 @@ const DECRC = "\x1b8"; | ... | @@ -192,8 +197,9 @@ const DECRC = "\x1b8"; |
| 192 | // supported by some terminals (eg. Terminal.app). | 197 | // supported by some terminals (eg. Terminal.app). |
| 193 | | 198 | |
| 194 | fn refreshWithHeldLock(self: *Progress) void { | 199 | fn refreshWithHeldLock(self: *Progress) void { |
| 195 | const is_dumb = !self.supports_ansi_escape_codes and !(std.builtin.os.tag == .windows); | 200 | const is_dumb = !self.supports_ansi_escape_codes and !self.is_windows_terminal; |
| 196 | if (is_dumb and self.dont_print_on_dumb) return; | 201 | if (is_dumb and self.dont_print_on_dumb) return; |
| | 202 | |
| 197 | const file = self.terminal orelse return; | 203 | const file = self.terminal orelse return; |
| 198 | | 204 | |
| 199 | var end: usize = 0; | 205 | var end: usize = 0; |
| ... | @@ -206,6 +212,8 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -206,6 +212,8 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 206 | std.mem.copy(u8, self.output_buffer[end..], seq_before); | 212 | std.mem.copy(u8, self.output_buffer[end..], seq_before); |
| 207 | end += seq_before.len; | 213 | end += seq_before.len; |
| 208 | } else if (std.builtin.os.tag == .windows) winapi: { | 214 | } else if (std.builtin.os.tag == .windows) winapi: { |
| | 215 | std.debug.assert(self.is_windows_terminal); |
| | 216 | |
| 209 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | 217 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; |
| 210 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) | 218 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) |
| 211 | unreachable; | 219 | unreachable; |
| ... | @@ -282,7 +290,7 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -282,7 +290,7 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 282 | const seq_after = DECRC; | 290 | const seq_after = DECRC; |
| 283 | std.mem.copy(u8, self.output_buffer[end..], seq_after); | 291 | std.mem.copy(u8, self.output_buffer[end..], seq_after); |
| 284 | end += seq_after.len; | 292 | end += seq_after.len; |
| 285 | } else if (std.builtin.os.tag != .windows) { | 293 | } else if (!self.is_windows_terminal) { |
| 286 | self.output_buffer[end] = '\n'; | 294 | self.output_buffer[end] = '\n'; |
| 287 | end += 1; | 295 | end += 1; |
| 288 | } | 296 | } |
| ... | @@ -293,8 +301,10 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -293,8 +301,10 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 293 | }; | 301 | }; |
| 294 | | 302 | |
| 295 | if (std.builtin.os.tag == .windows) { | 303 | if (std.builtin.os.tag == .windows) { |
| 296 | if (windows.kernel32.SetConsoleCursorPosition(file.handle, saved_cursor_pos) != windows.TRUE) | 304 | if (self.is_windows_terminal) { |
| 297 | unreachable; | 305 | const res = windows.kernel32.SetConsoleCursorPosition(file.handle, saved_cursor_pos); |
| | 306 | std.debug.assert(res == windows.TRUE); |
| | 307 | } |
| 298 | } | 308 | } |
| 299 | | 309 | |
| 300 | self.prev_refresh_timestamp = self.timer.read(); | 310 | self.prev_refresh_timestamp = self.timer.read(); |
| ... | @@ -318,7 +328,7 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any | ... | @@ -318,7 +328,7 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any |
| 318 | end.* = self.output_buffer.len; | 328 | end.* = self.output_buffer.len; |
| 319 | }, | 329 | }, |
| 320 | } | 330 | } |
| 321 | const bytes_needed_for_esc_codes_at_end = if (std.builtin.os.tag == .windows) 0 else 11; | 331 | const bytes_needed_for_esc_codes_at_end: u8 = if (self.is_windows_terminal) 0 else 11; |
| 322 | const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end; | 332 | const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end; |
| 323 | if (end.* > max_end) { | 333 | if (end.* > max_end) { |
| 324 | const suffix = "... "; | 334 | const suffix = "... "; |