diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 1dd9c9e48ce..130d986aa5d 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -40,6 +40,7 @@ pub use self::layout::is_bad_artifact_name; use self::output_depinfo::output_depinfo; use self::unit_dependencies::UnitDep; pub use crate::core::compiler::unit::{Unit, UnitInterner}; +use crate::core::features::nightly_features_allowed; use crate::core::manifest::TargetSourcePath; use crate::core::profiles::{Lto, PanicStrategy, Profile}; use crate::core::Feature; @@ -714,6 +715,14 @@ fn add_error_format_and_color( } else { let mut color = true; match cx.bcx.build_config.message_format { + MessageFormat::Human if nightly_features_allowed() => { + if let (Some(width), _) | (_, Some(width)) = ( + cx.bcx.config.cli_unstable().terminal_width, + cx.bcx.config.shell().accurate_err_width(), + ) { + cmd.arg(format!("-Zterminal-width={}", width)); + } + } MessageFormat::Human => (), MessageFormat::Json { ansi, diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index dd24951bbd1..8af4c75ce13 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -337,6 +337,7 @@ pub struct CliUnstable { pub build_std: Option>, pub timings: Option>, pub doctest_xcompile: bool, + pub terminal_width: Option, } impl CliUnstable { @@ -376,6 +377,16 @@ impl CliUnstable { } } + fn parse_usize_opt(value: Option<&str>) -> CargoResult> { + Ok(match value { + Some(value) => match value.parse::() { + Ok(value) => Some(value), + Err(e) => failure::bail!("expected a number, found: {}", e), + }, + None => None, + }) + } + match k { "print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?, "unstable-options" => self.unstable_options = true, @@ -395,6 +406,7 @@ impl CliUnstable { } "timings" => self.timings = Some(parse_timings(v)), "doctest-xcompile" => self.doctest_xcompile = true, + "terminal-width" => self.terminal_width = parse_usize_opt(v)?, _ => failure::bail!("unknown `-Z` flag specified: {}", k), } diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index dfa195943bf..8fefee56bbe 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -136,6 +136,14 @@ impl Shell { } } + /// Returns the width of the terminal in spaces, if any. Always `None` in Windows. + pub fn accurate_err_width(&self) -> Option { + match self.err { + ShellOut::Stream { tty: true, .. } => imp::accurate_stderr_width(), + _ => None, + } + } + /// Returns `true` if stderr is a tty. pub fn is_err_tty(&self) -> bool { match self.err { @@ -383,6 +391,10 @@ mod imp { use super::Shell; + pub fn accurate_stderr_width() -> Option { + stderr_width() + } + pub fn stderr_width() -> Option { unsafe { let mut winsize: libc::winsize = mem::zeroed(); @@ -414,6 +426,10 @@ mod imp { mod imp { pub(super) use super::default_err_erase_line as err_erase_line; + pub fn accurate_stderr_width() -> Option { + None + } + pub fn stderr_width() -> Option { None } @@ -431,6 +447,10 @@ mod imp { pub(super) use super::default_err_erase_line as err_erase_line; + pub fn accurate_stderr_width() -> Option { + None + } + pub fn stderr_width() -> Option { unsafe { let stdout = GetStdHandle(STD_ERROR_HANDLE); diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index aaa4cf79731..c51cc098c2d 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -2,8 +2,8 @@ use cargo::util::paths::dylib_path_envvar; use cargo_test_support::paths::{root, CargoPathExt}; use cargo_test_support::registry::Package; use cargo_test_support::{ - basic_bin_manifest, basic_lib_manifest, basic_manifest, main_file, project, rustc_host, - sleep_ms, symlink_supported, t, Execs, ProjectBuilder, + basic_bin_manifest, basic_lib_manifest, basic_manifest, is_nightly, main_file, project, + rustc_host, sleep_ms, symlink_supported, t, Execs, ProjectBuilder, }; use std::env; use std::fs::{self, File}; @@ -4723,3 +4723,34 @@ d ) .run(); } + +#[cargo_test] +fn simple_terminal_width() { + if !is_nightly() { + // --terminal-width is unstable + return; + } + let p = project() + .file( + "src/lib.rs", + " + fn a() { +/**/ /**/ \ +/**/ /**/ \ +/**/ /**/ \ +/**/ /**/ \ +/**/ /**/ \ +/**/ /**/ \ +/**/ /**/ \ + let _: () = 42; + } + ", + ) + .build(); + + p.cargo("build -Zterminal-width=60") + .masquerade_as_nightly_cargo() + .with_status(101) + .with_stderr_contains("3 | ...t _: () = 42;") + .run(); +}