Skip to content

Commit

Permalink
fix(cli): dev command stderr text overflow on Windows, closes #3995 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Apr 29, 2022
1 parent cf22f4c commit 094534d
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .changes/cli-fix-overflow-windows.md
@@ -0,0 +1,6 @@
---
"cli.rs": patch
"cli.js": patch
---

Fixes text overflow on `tauri dev` on Windows.
4 changes: 2 additions & 2 deletions examples/api/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/api/src-tauri/Cargo.toml
Expand Up @@ -12,7 +12,7 @@ tauri-build = { path = "../../../core/tauri-build", features = ["isolation"] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = [ "derive" ] }
tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "http-multipart", "icon-ico", "icon-png", "isolation", "macos-private-api", "reqwest-client", "system-tray", "updater", "global-shortcut"] }
tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "global-shortcut", "http-multipart", "icon-ico", "icon-png", "isolation", "macos-private-api", "reqwest-client", "system-tray", "updater"] }
tiny_http = "0.11"

[features]
Expand Down
1 change: 1 addition & 0 deletions tooling/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion tooling/cli/Cargo.toml
Expand Up @@ -52,7 +52,6 @@ os_info = "3.2"
semver = "1.0"
regex = "1.5.5"
lazy_static = "1"
libc = "0.2"
terminal_size = "0.1"
unicode-width = "0.1"
tempfile = "3"
Expand All @@ -67,10 +66,14 @@ ctrlc = "3.2"

[target."cfg(windows)".dependencies]
encode_unicode = "0.3"
winapi = { version = "0.3", features = ["handleapi", "processenv", "winbase", "wincon", "winnt"] }

[target."cfg(target_os = \"linux\")".build-dependencies]
heck = "0.4"

[target."cfg(unix)".dependencies]
libc = "0.2"

[build-dependencies]
tauri-utils = { version = "1.0.0-rc.0", features = [ "schema", "isolation" ], path = "../../core/tauri-utils" }
schemars = { version = "0.8", features = [ "url" ] }
Expand Down
107 changes: 95 additions & 12 deletions tooling/cli/src/dev.rs
Expand Up @@ -23,7 +23,7 @@ use std::{
env::set_current_dir,
ffi::OsStr,
fs::FileType,
io::BufReader,
io::{BufReader, Write},
path::{Path, PathBuf},
process::{exit, Command},
sync::{
Expand Down Expand Up @@ -320,7 +320,6 @@ fn lookup<F: FnMut(FileType, PathBuf)>(dir: &Path, mut f: F) {
default_gitignore.push(".gitignore");
if !default_gitignore.exists() {
if let Ok(mut file) = std::fs::File::create(default_gitignore.clone()) {
use std::io::Write;
let _ = file.write_all(TAURI_DEV_WATCHER_GITIGNORE);
}
}
Expand Down Expand Up @@ -422,7 +421,7 @@ fn kill_before_dev_process() {

if !kill_children_script_path.exists() {
if let Ok(mut file) = std::fs::File::create(&kill_children_script_path) {
use std::{io::Write, os::unix::fs::PermissionsExt};
use std::os::unix::fs::PermissionsExt;
let _ = file.write_all(KILL_CHILDREN_SCRIPT);
let mut permissions = file.metadata().unwrap().permissions();
permissions.set_mode(0o770);
Expand All @@ -448,9 +447,15 @@ fn start_app(
command
.env(
"CARGO_TERM_PROGRESS_WIDTH",
terminal_size::terminal_size()
.map(|(w, _)| w.0)
.unwrap_or(80)
terminal::stderr_width()
.map(|width| {
if cfg!(windows) {
std::cmp::min(60, width)
} else {
width
}
})
.unwrap_or(if cfg!(windows) { 60 } else { 80 })
.to_string(),
)
.env("CARGO_TERM_PROGRESS_WHEN", "always");
Expand Down Expand Up @@ -506,19 +511,18 @@ fn start_app(
std::thread::spawn(move || {
let mut buf = Vec::new();
let mut lines = stderr_lines_.lock().unwrap();
let mut io_stderr = std::io::stderr();
loop {
buf.clear();
match tauri_utils::io::read_line(&mut stderr, &mut buf) {
Ok(s) if s == 0 => break,
_ => (),
}
let line = String::from_utf8_lossy(&buf).into_owned();
if line.ends_with('\r') {
eprint!("{}", line);
} else {
eprintln!("{}", line);
let _ = io_stderr.write_all(&buf);
if !buf.ends_with(&[b'\r']) {
let _ = io_stderr.write_all(b"\n");
}
lines.push(line);
lines.push(String::from_utf8_lossy(&buf).into_owned());
}
});

Expand Down Expand Up @@ -554,3 +558,82 @@ fn start_app(

Ok(child_arc)
}

// taken from https://github.com/rust-lang/cargo/blob/78b10d4e611ab0721fc3aeaf0edd5dd8f4fdc372/src/cargo/core/shell.rs#L514
#[cfg(unix)]
mod terminal {
use std::mem;

pub fn stderr_width() -> Option<usize> {
unsafe {
let mut winsize: libc::winsize = mem::zeroed();
// The .into() here is needed for FreeBSD which defines TIOCGWINSZ
// as c_uint but ioctl wants c_ulong.
#[allow(clippy::useless_conversion)]
if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ.into(), &mut winsize) < 0 {
return None;
}
if winsize.ws_col > 0 {
Some(winsize.ws_col as usize)
} else {
None
}
}
}
}

// taken from https://github.com/rust-lang/cargo/blob/78b10d4e611ab0721fc3aeaf0edd5dd8f4fdc372/src/cargo/core/shell.rs#L543
#[cfg(windows)]
mod terminal {
use std::{cmp, mem, ptr};
use winapi::um::fileapi::*;
use winapi::um::handleapi::*;
use winapi::um::processenv::*;
use winapi::um::winbase::*;
use winapi::um::wincon::*;
use winapi::um::winnt::*;

pub fn stderr_width() -> Option<usize> {
unsafe {
let stdout = GetStdHandle(STD_ERROR_HANDLE);
let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize);
}

// On mintty/msys/cygwin based terminals, the above fails with
// INVALID_HANDLE_VALUE. Use an alternate method which works
// in that case as well.
let h = CreateFileA(
"CONOUT$\0".as_ptr() as *const CHAR,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
ptr::null_mut(),
OPEN_EXISTING,
0,
ptr::null_mut(),
);
if h == INVALID_HANDLE_VALUE {
return None;
}

let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
let rc = GetConsoleScreenBufferInfo(h, &mut csbi);
CloseHandle(h);
if rc != 0 {
let width = (csbi.srWindow.Right - csbi.srWindow.Left) as usize;
// Unfortunately cygwin/mintty does not set the size of the
// backing console to match the actual window size. This
// always reports a size of 80 or 120 (not sure what
// determines that). Use a conservative max of 60 which should
// work in most circumstances. ConEmu does some magic to
// resize the console correctly, but there's no reasonable way
// to detect which kind of terminal we are running in, or if
// GetConsoleScreenBufferInfo returns accurate information.
return Some(cmp::min(60, width));
}

None
}
}
}

0 comments on commit 094534d

Please sign in to comment.