From 1db4041f91f134aef5558a10195633003a5d36c3 Mon Sep 17 00:00:00 2001 From: Thomas Otto Date: Wed, 5 Oct 2022 23:10:19 +0200 Subject: [PATCH 1/2] Fix clippy warnings after rust 1.64 upgrade --- src/features/diff_highlight.rs | 5 +---- src/utils/process.rs | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/features/diff_highlight.rs b/src/features/diff_highlight.rs index fc4544c60..ccc39f9df 100644 --- a/src/features/diff_highlight.rs +++ b/src/features/diff_highlight.rs @@ -7,10 +7,7 @@ pub fn make_feature() -> Vec<(String, OptionValueFunction)> { pub fn _make_feature(bold: bool) -> Vec<(String, OptionValueFunction)> { let mut feature = raw::make_feature(); - feature = feature - .into_iter() - .filter(|(s, _)| s != "keep-plus-minus-markers" && s != "tabs") - .collect(); + feature.retain(|(s, _)| s != "keep-plus-minus-markers" && s != "tabs"); feature.extend(builtin_feature!([ ( "commit-style", diff --git a/src/utils/process.rs b/src/utils/process.rs index 1f24aa028..5c933d54e 100644 --- a/src/utils/process.rs +++ b/src/utils/process.rs @@ -332,14 +332,14 @@ trait ProcessInterface { fn refresh_processes(&mut self); fn parent_process(&mut self, pid: DeltaPid) -> Option<&Self::Out> { - self.refresh_process(pid).then(|| ())?; + self.refresh_process(pid).then_some(())?; let parent_pid = self.process(pid)?.parent()?; - self.refresh_process(parent_pid).then(|| ())?; + self.refresh_process(parent_pid).then_some(())?; self.process(parent_pid) } fn naive_sibling_process(&mut self, pid: DeltaPid) -> Option<&Self::Out> { let sibling_pid = pid - 1; - self.refresh_process(sibling_pid).then(|| ())?; + self.refresh_process(sibling_pid).then_some(())?; self.process(sibling_pid) } fn find_sibling_in_refreshed_processes( From 6c74b4ea2e98188dc336141f2d694e9d2dc03c54 Mon Sep 17 00:00:00 2001 From: Thomas Otto Date: Mon, 10 Oct 2022 21:40:06 +0200 Subject: [PATCH 2/2] Add terminal width fallback via stty if on Windows/MSYS2 Also new workarounds.rs file, and DELTA_NO_WORKAROUNDS env var to disable these. --- src/options/set.rs | 3 +- src/utils/mod.rs | 1 + src/utils/workarounds.rs | 60 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/utils/workarounds.rs diff --git a/src/options/set.rs b/src/options/set.rs index 7cb8b0a7f..88615f7af 100644 --- a/src/options/set.rs +++ b/src/options/set.rs @@ -609,7 +609,8 @@ fn set_widths_and_isatty(opt: &mut cli::Opt) { // If one extra character for e.g. `less --status-column` is required use "-1" // as an argument, also see #41, #10, #115 and #727. - opt.computed.available_terminal_width = term_stdout.size().1 as usize; + opt.computed.available_terminal_width = + crate::utils::workarounds::windows_msys2_width_fix(term_stdout.size(), &term_stdout); let (decorations_width, background_color_extends_to_terminal_width) = match opt.width.as_deref() { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9cd8cfaae..257c7b038 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,3 +5,4 @@ pub mod process; pub mod regex_replacement; pub mod round_char_boundary; pub mod syntect; +pub mod workarounds; diff --git a/src/utils/workarounds.rs b/src/utils/workarounds.rs new file mode 100644 index 000000000..a47a1db83 --- /dev/null +++ b/src/utils/workarounds.rs @@ -0,0 +1,60 @@ +// env var which should disable workarounds +const NO_WORKAROUNDS: &str = "DELTA_NO_WORKAROUNDS"; + +// Work around a bug in the 'console' crate (inherited from 'terminal-size', #25): On Windows +// it can not determine the width of an MSYS2 / MINGW64 terminal (e.g. from Git-Bash) correctly. +// Instead use the usually included stty util from the MSYS2 distribution. +#[cfg(target_os = "windows")] +pub fn windows_msys2_width_fix(height_width: (u16, u16), term_stdout: &console::Term) -> usize { + fn guess_real_width(current_width: u16, term_stdout: &console::Term) -> Option { + use std::process::{Command, Stdio}; + + let term_var = std::env::var("TERM").ok()?; + // More checks before actually calling stty. + if term_var.starts_with("xterm") + && term_stdout.is_term() + && term_stdout.features().is_msys_tty() + { + if std::env::var(NO_WORKAROUNDS).is_ok() { + return Some(current_width); + } + + // stderr/2 is passed to the Command below. + let pseudo_term = "/dev/fd/2"; + + // Read width via stty helper program (e.g. "C:\Program Files\Git\usr\bin\stty.exe") + // which gets both the MSYS2 and cmd.exe width right. + let result = Command::new("stty") + .stderr(Stdio::inherit()) + .arg("-F") + .arg(pseudo_term) + .arg("size") + .output() + .ok()?; + + if result.status.success() { + let size = std::str::from_utf8(&result.stdout).ok()?; + let mut it = size.split_whitespace(); + let _height = it.next()?; + return it.next().map(|width| width.parse().ok())?; + } + } + None + } + + // Calling an external binary is slow, so make sure this is actually necessary. + // The fallback values of 25 lines by 80 columns (sometimes zero indexed) are a good + // indicator. + let (height, width) = height_width; + match (height, width) { + (24..=25, 79..=80) => guess_real_width(width, term_stdout).unwrap_or(width), + _ => width, + } + .into() +} + +#[cfg(not(target_os = "windows"))] +pub fn windows_msys2_width_fix(height_width: (u16, u16), _: &console::Term) -> usize { + let _ = NO_WORKAROUNDS; + height_width.1.into() +}