Skip to content

Commit af924d4

Browse files
committed
Introduce TtyWidth
This commit introduces a `TtyWidth` enum which enables better handling of the tty-width on Windows. Signed-off-by: David Wood <[email protected]>
1 parent 4177f66 commit af924d4

File tree

3 files changed

+51
-36
lines changed

3 files changed

+51
-36
lines changed

src/cargo/core/compiler/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,10 @@ fn add_error_format_and_color(
721721

722722
if nightly_features_allowed() {
723723
let config = cx.bcx.config;
724-
match (config.cli_unstable().terminal_width, config.shell().accurate_err_width()) {
724+
match (
725+
config.cli_unstable().terminal_width,
726+
config.shell().err_width().diagnostic_terminal_width(),
727+
) {
725728
// Terminal width explicitly provided - only useful for testing.
726729
(Some(Some(width)), _) => {
727730
cmd.arg(format!("-Zterminal-width={}", width));

src/cargo/core/shell.rs

+45-33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ use termcolor::{self, Color, ColorSpec, StandardStream, WriteColor};
66

77
use crate::util::errors::CargoResult;
88

9+
pub enum TtyWidth {
10+
NoTty,
11+
Known(usize),
12+
Guess(usize),
13+
}
14+
15+
impl TtyWidth {
16+
/// Returns the width provided with `-Z terminal-width` to rustc to truncate diagnostics with
17+
/// long lines.
18+
pub fn diagnostic_terminal_width(&self) -> Option<usize> {
19+
match *self {
20+
TtyWidth::NoTty | TtyWidth::Guess(_) => None,
21+
TtyWidth::Known(width) => Some(width),
22+
}
23+
}
24+
25+
/// Returns the width used by progress bars for the tty.
26+
pub fn progress_max_width(&self) -> Option<usize> {
27+
match *self {
28+
TtyWidth::NoTty => None,
29+
TtyWidth::Known(width) | TtyWidth::Guess(width) => Some(width),
30+
}
31+
}
32+
}
33+
934
/// The requested verbosity of output.
1035
#[derive(Debug, Clone, Copy, PartialEq)]
1136
pub enum Verbosity {
@@ -125,21 +150,12 @@ impl Shell {
125150
}
126151

127152
/// Returns the width of the terminal in spaces, if any.
128-
pub fn err_width(&self) -> Option<usize> {
153+
pub fn err_width(&self) -> TtyWidth {
129154
match self.output {
130155
ShellOut::Stream {
131156
stderr_tty: true, ..
132157
} => imp::stderr_width(),
133-
_ => None,
134-
}
135-
}
136-
137-
/// Returns the width of the terminal in spaces, if any. Always `None` in Windows.
138-
pub fn accurate_err_width(&self) -> Option<usize> {
139-
if self.is_err_tty() {
140-
imp::accurate_stderr_width()
141-
} else {
142-
None
158+
_ => TtyWidth::NoTty,
143159
}
144160
}
145161

@@ -417,25 +433,21 @@ impl ColorChoice {
417433

418434
#[cfg(unix)]
419435
mod imp {
420-
use super::Shell;
436+
use super::{Shell, TtyWidth};
421437
use std::mem;
422438

423-
pub fn accurate_stderr_width() -> Option<usize> {
424-
stderr_width()
425-
}
426-
427-
pub fn stderr_width() -> Option<usize> {
439+
pub fn stderr_width() -> TtyWidth {
428440
unsafe {
429441
let mut winsize: libc::winsize = mem::zeroed();
430442
// The .into() here is needed for FreeBSD which defines TIOCGWINSZ
431443
// as c_uint but ioctl wants c_ulong.
432444
if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ.into(), &mut winsize) < 0 {
433-
return None;
445+
return TtyWidth::NoTty;
434446
}
435447
if winsize.ws_col > 0 {
436-
Some(winsize.ws_col as usize)
448+
TtyWidth::Known(winsize.ws_col as usize)
437449
} else {
438-
None
450+
TtyWidth::NoTty
439451
}
440452
}
441453
}
@@ -458,18 +470,14 @@ mod imp {
458470
use winapi::um::wincon::*;
459471
use winapi::um::winnt::*;
460472

461-
pub(super) use super::default_err_erase_line as err_erase_line;
462-
463-
pub fn accurate_stderr_width() -> Option<usize> {
464-
None
465-
}
473+
pub(super) use super::{default_err_erase_line as err_erase_line, TtyWidth};
466474

467-
pub fn stderr_width() -> Option<usize> {
475+
pub fn stderr_width() -> TtyWidth {
468476
unsafe {
469477
let stdout = GetStdHandle(STD_ERROR_HANDLE);
470478
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
471479
if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
472-
return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize);
480+
return TtyWidth::Known((csbi.srWindow.Right - csbi.srWindow.Left) as usize);
473481
}
474482

475483
// On mintty/msys/cygwin based terminals, the above fails with
@@ -485,7 +493,7 @@ mod imp {
485493
ptr::null_mut(),
486494
);
487495
if h == INVALID_HANDLE_VALUE {
488-
return None;
496+
return TtyWidth::NoTty;
489497
}
490498

491499
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
@@ -501,17 +509,21 @@ mod imp {
501509
// resize the console correctly, but there's no reasonable way
502510
// to detect which kind of terminal we are running in, or if
503511
// GetConsoleScreenBufferInfo returns accurate information.
504-
return Some(cmp::min(60, width));
512+
return TtyWidth::Guess(cmp::min(60, width));
505513
}
506-
None
514+
515+
TtyWidth::NoTty
507516
}
508517
}
509518
}
510519

511520
#[cfg(windows)]
512521
fn default_err_erase_line(shell: &mut Shell) {
513-
if let Some(max_width) = imp::stderr_width() {
514-
let blank = " ".repeat(max_width);
515-
drop(write!(shell.output.stderr(), "{}\r", blank));
522+
match imp::stderr_width() {
523+
TtyWidth::Known(max_width) | TtyWidth::Guess(max_width) => {
524+
let blank = " ".repeat(max_width);
525+
drop(write!(shell.output.stderr(), "{}\r", blank));
526+
}
527+
_ => (),
516528
}
517529
}

src/cargo/util/progress.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl<'cfg> Progress<'cfg> {
5050
}
5151

5252
Progress {
53-
state: cfg.shell().err_width().map(|n| State {
53+
state: cfg.shell().err_width().progress_max_width().map(|n| State {
5454
config: cfg,
5555
format: Format {
5656
style,
@@ -216,7 +216,7 @@ impl<'cfg> State<'cfg> {
216216
}
217217

218218
fn try_update_max_width(&mut self) {
219-
if let Some(n) = self.config.shell().err_width() {
219+
if let Some(n) = self.config.shell().err_width().progress_max_width() {
220220
self.format.max_width = n;
221221
}
222222
}

0 commit comments

Comments
 (0)