nu_plugin_plot icon indicating copy to clipboard operation
nu_plugin_plot copied to clipboard

Terminal size issues

Open Euphrasiologist opened this issue 2 years ago • 2 comments

As nu_plugin is communicating over the stdout, the terminal_size crate doesn't work in its current implementation. It's ideal to use this crate as it's actively supported, and what the rest of nushell uses.

@fdncred has suggested this from discord:

fn terminal_size() -> Option<(Width, Height)> {
    use windows_sys::Win32::System::Console::{GetStdHandle, STD_ERROR_HANDLE};
    let handle = unsafe { GetStdHandle(STD_ERROR_HANDLE) as RawHandle };
    terminal_size_using_handle(handle)
}

Or something similar. To think about!

Euphrasiologist avatar Jan 11 '23 18:01 Euphrasiologist

The only real downside to this is you have to have a dependency on windows-sys (i think that's the crate terminal-size uses). But if you were including terminal-size, you'd have that dependency anyway. But if you decide to forward, I'd do something similar to what the term-size crate does, but in terminal-size syntax.

This is the term-size syntax. It should be easy-ish to retrofit for terminal-size I think.

  if unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &mut console_data) } != 0 ||
        unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_INPUT_HANDLE), &mut console_data) } != 0 ||
        unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &mut console_data) } != 0 {
        Some(((console_data.srWindow.Right - console_data.srWindow.Left + 1) as usize,
                (console_data.srWindow.Bottom - console_data.srWindow.Top + 1) as usize))
    } else {
        None
    }

fdncred avatar Jan 11 '23 19:01 fdncred

I just fought this issue with my nu_plugin_dbg and came up with this solution.

#[cfg(not(windows))]
fn termsize() -> usize {
    use std::os::fd::AsRawFd;

    // because STDOUT is redirected we need to use STDERR descriptor
    let (cols, _) = match terminal_size::terminal_size_using_fd(std::io::stderr().as_raw_fd()) {
        Some((w, h)) => (w.0, h.0),
        None => (0, 0),
    };

    cols as usize
}

#[cfg(windows)]
fn termsize() -> usize {
    use std::os::windows::io::RawHandle;
    use windows_sys::Win32::System::Console::{GetStdHandle, STD_ERROR_HANDLE};

    let stderr = unsafe { GetStdHandle(STD_ERROR_HANDLE) } as RawHandle;

    // because STDOUT is redirected we need to use STDERR descriptor
    let (cols, _) = match terminal_size::terminal_size_using_handle(stderr) {
        Some((w, h)) => (w.0, h.0),
        None => (0, 0),
    };

    cols as usize
}

fdncred avatar Feb 09 '23 14:02 fdncred