Commit 9319ceff authored by Jezza's avatar Jezza

Add basic windows support.

Construct the window's tty handle and set the necessary console modes.
parent ce6b43d0
Pipeline #2277 passed with stages
in 3 minutes and 56 seconds
target
Cargo.lock
.idea
\ No newline at end of file
......@@ -12,9 +12,15 @@ exclude = ["target", "CHANGELOG.md", "image.png", "Cargo.lock"]
[dependencies]
numtoa = { version = "0.1.0", features = ["std"]}
[target.'cfg(not(target_os = "redox"))'.dependencies]
[target.'cfg(all(not(target_os = "redox"), not(windows)))'.dependencies]
libc = "0.2.8"
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = "0.1"
redox_termios = "0.1"
redox_termios = "0.1"
[target.'cfg(windows)'.dependencies]
[dependencies.winapi]
version = "0.3.6"
features = ["winbase", "wincon", "processenv", "consoleapi", "handleapi"]
extern crate termion;
use std::fs;
use std::{fs, io};
fn main() {
if termion::is_tty(&fs::File::create("/dev/stdout").unwrap()) {
#[cfg(not(windows))]
let stream = fs::File::create("/dev/stdout").unwrap();
#[cfg(windows)]
let stream = io::stdin();
if termion::is_tty(&stream) {
println!("This is a TTY!");
} else {
println!("This is not a TTY :(");
......
......@@ -24,7 +24,7 @@ pub fn async_stdin_until(delimiter: u8) -> AsyncReader {
}
});
AsyncReader { recv: recv }
AsyncReader { recv }
}
/// Construct an asynchronous handle to the TTY standard input.
......
This diff is collapsed.
......@@ -21,6 +21,10 @@ mod sys;
#[path="sys/unix/mod.rs"]
mod sys;
#[cfg(windows)]
#[path="sys/windows/mod.rs"]
mod sys;
pub use sys::size::terminal_size;
pub use sys::tty::{is_tty, get_tty};
......
......@@ -95,7 +95,7 @@ impl<W: Write> IntoRawMode for W {
set_terminal_attr(&ios)?;
Ok(RawTerminal {
prev_ios: prev_ios,
prev_ios,
output: self,
})
}
......
use std::{env, fs, io};
use std::{env, fs, io::{self, Read}};
use std::os::unix::io::AsRawFd;
use super::syscall;
......@@ -16,7 +16,7 @@ pub fn is_tty<T: AsRawFd>(stream: &T) -> bool {
/// Get the TTY device.
///
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
pub fn get_tty() -> io::Result<fs::File> {
pub fn get_tty() -> io::Result<impl Read> {
let tty = try!(env::var("TTY").map_err(|x| io::Error::new(io::ErrorKind::NotFound, x)));
fs::OpenOptions::new().read(true).write(true).open(tty)
}
use std::{fs, io};
use std::{fs, io::{self, Read}};
use std::os::unix::io::AsRawFd;
use super::libc;
......@@ -12,6 +12,6 @@ pub fn is_tty<T: AsRawFd>(stream: &T) -> bool {
/// Get the TTY device.
///
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
pub fn get_tty() -> io::Result<fs::File> {
pub fn get_tty() -> io::Result<impl Read> {
fs::OpenOptions::new().read(true).write(true).open("/dev/tty")
}
use std::{io, mem};
use super::{DWORD, Termios};
use super::winapi::um::{consoleapi, handleapi, processenv, winbase, wincon};
pub fn get_terminal_attr() -> io::Result<Termios> {
let input_mode = get_console_mode(winbase::STD_INPUT_HANDLE)?;
let output_mode = get_console_mode(winbase::STD_OUTPUT_HANDLE)?;
Ok(Termios(input_mode, output_mode))
}
pub fn set_terminal_attr(termios: &Termios) -> io::Result<()> {
set_console_mode(winbase::STD_INPUT_HANDLE, termios.0)?;
set_console_mode(winbase::STD_OUTPUT_HANDLE, termios.1)?;
Ok(())
}
fn get_console_mode(handle: DWORD) -> io::Result<DWORD> {
unsafe {
let handle = processenv::GetStdHandle(handle);
if handle == handleapi::INVALID_HANDLE_VALUE {
return Err(io::Error::last_os_error());
}
let mut mode: DWORD = mem::zeroed();
consoleapi::GetConsoleMode(handle, &mut mode);
Ok(mode)
}
}
fn set_console_mode(handle: DWORD, mode: DWORD) -> io::Result<()> {
unsafe {
let handle = processenv::GetStdHandle(handle);
if handle == handleapi::INVALID_HANDLE_VALUE {
return Err(io::Error::last_os_error());
}
let check = consoleapi::SetConsoleMode(handle, mode);
if check != 1 {
return Err(io::Error::last_os_error());
}
Ok(())
}
}
pub fn raw_terminal_attr(termios: &mut Termios) {
termios.0 = wincon::ENABLE_VIRTUAL_TERMINAL_INPUT;
termios.1 = wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING
| wincon::ENABLE_PROCESSED_OUTPUT
| wincon::DISABLE_NEWLINE_AUTO_RETURN;
}
extern crate winapi;
use self::winapi::shared::minwindef::DWORD;
#[derive(Clone, Copy, Debug)]
pub struct Termios(DWORD, DWORD);
pub mod attr;
pub mod size;
pub mod tty;
\ No newline at end of file
use std::{io, mem};
use super::winapi::um::{processenv, winbase, wincon};
/// Get the size of the terminal.
pub fn terminal_size() -> io::Result<(u16, u16)> {
unsafe {
let output_handle = processenv::GetStdHandle(winbase::STD_OUTPUT_HANDLE);
let mut screen_info: wincon::CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
wincon::GetConsoleScreenBufferInfo(output_handle, &mut screen_info);
let columns = screen_info.srWindow.Right - screen_info.srWindow.Left + 1;
let rows = screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1;
Ok((columns as u16, rows as u16))
}
}
use std::{fs, io::{self, Read}};
use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle};
/// Is this stream a TTY?
pub fn is_tty<T: AsRawHandle>(stream: &T) -> bool {
// @MAYBE Jezza - 17 Dec. 2018: Is this the correct implementation?
// I just check against this program's stdin handle, and if they're the same, then the given
// must be a tty for something... I guess...
stream.as_raw_handle() == io::stdin().as_raw_handle()
}
/// Get the TTY device.
///
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
pub fn get_tty() -> io::Result<impl Read> {
Ok(io::stdin())
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment