mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Introduce TtyWidth
This commit introduces a `TtyWidth` enum which enables better handling of the tty-width on Windows. Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
4177f66fd2
commit
af924d4ecf
@ -721,7 +721,10 @@ fn add_error_format_and_color(
|
|||||||
|
|
||||||
if nightly_features_allowed() {
|
if nightly_features_allowed() {
|
||||||
let config = cx.bcx.config;
|
let config = cx.bcx.config;
|
||||||
match (config.cli_unstable().terminal_width, config.shell().accurate_err_width()) {
|
match (
|
||||||
|
config.cli_unstable().terminal_width,
|
||||||
|
config.shell().err_width().diagnostic_terminal_width(),
|
||||||
|
) {
|
||||||
// Terminal width explicitly provided - only useful for testing.
|
// Terminal width explicitly provided - only useful for testing.
|
||||||
(Some(Some(width)), _) => {
|
(Some(Some(width)), _) => {
|
||||||
cmd.arg(format!("-Zterminal-width={}", width));
|
cmd.arg(format!("-Zterminal-width={}", width));
|
||||||
|
@ -6,6 +6,31 @@ use termcolor::{self, Color, ColorSpec, StandardStream, WriteColor};
|
|||||||
|
|
||||||
use crate::util::errors::CargoResult;
|
use crate::util::errors::CargoResult;
|
||||||
|
|
||||||
|
pub enum TtyWidth {
|
||||||
|
NoTty,
|
||||||
|
Known(usize),
|
||||||
|
Guess(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TtyWidth {
|
||||||
|
/// Returns the width provided with `-Z terminal-width` to rustc to truncate diagnostics with
|
||||||
|
/// long lines.
|
||||||
|
pub fn diagnostic_terminal_width(&self) -> Option<usize> {
|
||||||
|
match *self {
|
||||||
|
TtyWidth::NoTty | TtyWidth::Guess(_) => None,
|
||||||
|
TtyWidth::Known(width) => Some(width),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the width used by progress bars for the tty.
|
||||||
|
pub fn progress_max_width(&self) -> Option<usize> {
|
||||||
|
match *self {
|
||||||
|
TtyWidth::NoTty => None,
|
||||||
|
TtyWidth::Known(width) | TtyWidth::Guess(width) => Some(width),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The requested verbosity of output.
|
/// The requested verbosity of output.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Verbosity {
|
pub enum Verbosity {
|
||||||
@ -125,21 +150,12 @@ impl Shell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the width of the terminal in spaces, if any.
|
/// Returns the width of the terminal in spaces, if any.
|
||||||
pub fn err_width(&self) -> Option<usize> {
|
pub fn err_width(&self) -> TtyWidth {
|
||||||
match self.output {
|
match self.output {
|
||||||
ShellOut::Stream {
|
ShellOut::Stream {
|
||||||
stderr_tty: true, ..
|
stderr_tty: true, ..
|
||||||
} => imp::stderr_width(),
|
} => imp::stderr_width(),
|
||||||
_ => None,
|
_ => TtyWidth::NoTty,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the width of the terminal in spaces, if any. Always `None` in Windows.
|
|
||||||
pub fn accurate_err_width(&self) -> Option<usize> {
|
|
||||||
if self.is_err_tty() {
|
|
||||||
imp::accurate_stderr_width()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,25 +433,21 @@ impl ColorChoice {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::Shell;
|
use super::{Shell, TtyWidth};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
pub fn accurate_stderr_width() -> Option<usize> {
|
pub fn stderr_width() -> TtyWidth {
|
||||||
stderr_width()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stderr_width() -> Option<usize> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut winsize: libc::winsize = mem::zeroed();
|
let mut winsize: libc::winsize = mem::zeroed();
|
||||||
// The .into() here is needed for FreeBSD which defines TIOCGWINSZ
|
// The .into() here is needed for FreeBSD which defines TIOCGWINSZ
|
||||||
// as c_uint but ioctl wants c_ulong.
|
// as c_uint but ioctl wants c_ulong.
|
||||||
if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ.into(), &mut winsize) < 0 {
|
if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ.into(), &mut winsize) < 0 {
|
||||||
return None;
|
return TtyWidth::NoTty;
|
||||||
}
|
}
|
||||||
if winsize.ws_col > 0 {
|
if winsize.ws_col > 0 {
|
||||||
Some(winsize.ws_col as usize)
|
TtyWidth::Known(winsize.ws_col as usize)
|
||||||
} else {
|
} else {
|
||||||
None
|
TtyWidth::NoTty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,18 +470,14 @@ mod imp {
|
|||||||
use winapi::um::wincon::*;
|
use winapi::um::wincon::*;
|
||||||
use winapi::um::winnt::*;
|
use winapi::um::winnt::*;
|
||||||
|
|
||||||
pub(super) use super::default_err_erase_line as err_erase_line;
|
pub(super) use super::{default_err_erase_line as err_erase_line, TtyWidth};
|
||||||
|
|
||||||
pub fn accurate_stderr_width() -> Option<usize> {
|
pub fn stderr_width() -> TtyWidth {
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stderr_width() -> Option<usize> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let stdout = GetStdHandle(STD_ERROR_HANDLE);
|
let stdout = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
|
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
|
||||||
if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
|
if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
|
||||||
return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize);
|
return TtyWidth::Known((csbi.srWindow.Right - csbi.srWindow.Left) as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On mintty/msys/cygwin based terminals, the above fails with
|
// On mintty/msys/cygwin based terminals, the above fails with
|
||||||
@ -485,7 +493,7 @@ mod imp {
|
|||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
);
|
);
|
||||||
if h == INVALID_HANDLE_VALUE {
|
if h == INVALID_HANDLE_VALUE {
|
||||||
return None;
|
return TtyWidth::NoTty;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
|
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
|
||||||
@ -501,17 +509,21 @@ mod imp {
|
|||||||
// resize the console correctly, but there's no reasonable way
|
// resize the console correctly, but there's no reasonable way
|
||||||
// to detect which kind of terminal we are running in, or if
|
// to detect which kind of terminal we are running in, or if
|
||||||
// GetConsoleScreenBufferInfo returns accurate information.
|
// GetConsoleScreenBufferInfo returns accurate information.
|
||||||
return Some(cmp::min(60, width));
|
return TtyWidth::Guess(cmp::min(60, width));
|
||||||
}
|
}
|
||||||
None
|
|
||||||
|
TtyWidth::NoTty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn default_err_erase_line(shell: &mut Shell) {
|
fn default_err_erase_line(shell: &mut Shell) {
|
||||||
if let Some(max_width) = imp::stderr_width() {
|
match imp::stderr_width() {
|
||||||
|
TtyWidth::Known(max_width) | TtyWidth::Guess(max_width) => {
|
||||||
let blank = " ".repeat(max_width);
|
let blank = " ".repeat(max_width);
|
||||||
drop(write!(shell.output.stderr(), "{}\r", blank));
|
drop(write!(shell.output.stderr(), "{}\r", blank));
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ impl<'cfg> Progress<'cfg> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Progress {
|
Progress {
|
||||||
state: cfg.shell().err_width().map(|n| State {
|
state: cfg.shell().err_width().progress_max_width().map(|n| State {
|
||||||
config: cfg,
|
config: cfg,
|
||||||
format: Format {
|
format: Format {
|
||||||
style,
|
style,
|
||||||
@ -216,7 +216,7 @@ impl<'cfg> State<'cfg> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn try_update_max_width(&mut self) {
|
fn try_update_max_width(&mut self) {
|
||||||
if let Some(n) = self.config.shell().err_width() {
|
if let Some(n) = self.config.shell().err_width().progress_max_width() {
|
||||||
self.format.max_width = n;
|
self.format.max_width = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user