8000 Add terminal width fallback via stty if on windows/MSYS2 by th1000s · Pull Request #1030 · dandavison/delta · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add terminal width fallback via stty if on windows/MSYS2 #1030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/features/diff_highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion src/options/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
1 change: 1 addition & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod process;
pub mod regex_replacement;
pub mod round_char_boundary;
pub mod syntect;
pub mod workarounds;
6 changes: 3 additions & 3 deletions src/utils/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F, T>(
Expand Down
60 changes: 60 additions & 0 deletions src/utils/workarounds.rs
8000
Original file line number Diff line number Diff line change
@@ -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<u16> {
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;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so this const &str does not trigger an unused variable warning in the non-windows case.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah of course, thanks.

height_width.1.into()
}
0