mirror of
https://github.com/wez/wezterm.git
synced 2024-12-26 23:04:49 +03:00
record: add support for running on Windows
This commit is contained in:
parent
e535b2d498
commit
4f2539f8e6
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4596,6 +4596,7 @@ dependencies = [
|
|||||||
"wezterm-client",
|
"wezterm-client",
|
||||||
"wezterm-gui-subcommands",
|
"wezterm-gui-subcommands",
|
||||||
"wezterm-term",
|
"wezterm-term",
|
||||||
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -38,3 +38,16 @@ wezterm-term = { path = "../term" }
|
|||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
termios = "0.3"
|
termios = "0.3"
|
||||||
|
|
||||||
|
[target."cfg(windows)".dependencies.winapi]
|
||||||
|
features = [
|
||||||
|
"winbase",
|
||||||
|
"winerror",
|
||||||
|
"winnls",
|
||||||
|
"winuser",
|
||||||
|
"consoleapi",
|
||||||
|
"handleapi",
|
||||||
|
"fileapi",
|
||||||
|
"synchapi",
|
||||||
|
]
|
||||||
|
version = "0.3"
|
||||||
|
@ -8,15 +8,15 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::{BufRead, BufReader, BufWriter, Read, Write};
|
use std::io::{BufRead, BufReader, BufWriter, Read, Write};
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use termios::{cfmakeraw, tcsetattr, Termios, TCSAFLUSH};
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use unix::UnixTty as Tty;
|
use unix::UnixTty as Tty;
|
||||||
use wezterm_term::color::ColorPalette;
|
use wezterm_term::color::ColorPalette;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use win::WinTty as Tty;
|
||||||
|
|
||||||
/// See <https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v2.md>
|
/// See <https://github.com/asciinema/asciinema/blob/develop/doc/asciicast-v2.md>
|
||||||
/// for file format specification
|
/// for file format specification
|
||||||
@ -107,9 +107,123 @@ impl Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod win {
|
||||||
|
use super::*;
|
||||||
|
use filedescriptor::AsRawFileDescriptor;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::os::windows::io::AsRawHandle;
|
||||||
|
use winapi::um::consoleapi::*;
|
||||||
|
use winapi::um::wincon::*;
|
||||||
|
use winapi::um::winnls::CP_UTF8;
|
||||||
|
|
||||||
|
pub struct WinTty {
|
||||||
|
saved_input: u32,
|
||||||
|
saved_output: u32,
|
||||||
|
saved_cp: u32,
|
||||||
|
read: FileDescriptor,
|
||||||
|
write: FileDescriptor,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinTty {
|
||||||
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
|
let read =
|
||||||
|
FileDescriptor::new(OpenOptions::new().read(true).write(true).open("CONIN$")?);
|
||||||
|
let write =
|
||||||
|
FileDescriptor::new(OpenOptions::new().read(true).write(true).open("CONOUT$")?);
|
||||||
|
|
||||||
|
let mut saved_input = 0;
|
||||||
|
let mut saved_output = 0;
|
||||||
|
let saved_cp;
|
||||||
|
unsafe {
|
||||||
|
GetConsoleMode(read.as_raw_file_descriptor(), &mut saved_input);
|
||||||
|
GetConsoleMode(write.as_raw_file_descriptor(), &mut saved_output);
|
||||||
|
saved_cp = GetConsoleOutputCP();
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
saved_input,
|
||||||
|
saved_output,
|
||||||
|
saved_cp,
|
||||||
|
read,
|
||||||
|
write,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_cooked(&mut self) -> anyhow::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
SetConsoleOutputCP(self.saved_cp);
|
||||||
|
SetConsoleMode(self.read.as_raw_handle(), self.saved_input);
|
||||||
|
SetConsoleMode(self.write.as_raw_handle(), self.saved_output);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_raw(&mut self) -> anyhow::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
SetConsoleMode(
|
||||||
|
self.read.as_raw_file_descriptor(),
|
||||||
|
ENABLE_VIRTUAL_TERMINAL_INPUT,
|
||||||
|
);
|
||||||
|
SetConsoleMode(
|
||||||
|
self.write.as_raw_file_descriptor(),
|
||||||
|
ENABLE_PROCESSED_OUTPUT
|
||||||
|
| ENABLE_WRAP_AT_EOL_OUTPUT
|
||||||
|
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
|
| DISABLE_NEWLINE_AUTO_RETURN,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_size(&self) -> anyhow::Result<PtySize> {
|
||||||
|
let mut info: CONSOLE_SCREEN_BUFFER_INFO = unsafe { std::mem::zeroed() };
|
||||||
|
let ok = unsafe {
|
||||||
|
GetConsoleScreenBufferInfo(
|
||||||
|
self.write.as_raw_handle() as *mut _,
|
||||||
|
&mut info as *mut _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ok == 0 {
|
||||||
|
anyhow::bail!(
|
||||||
|
"GetConsoleScreenBufferInfo failed: {}",
|
||||||
|
std::io::Error::last_os_error()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cols = 1 + (info.srWindow.Right - info.srWindow.Left);
|
||||||
|
let rows = 1 + (info.srWindow.Bottom - info.srWindow.Top);
|
||||||
|
|
||||||
|
Ok(PtySize {
|
||||||
|
rows: rows as u16,
|
||||||
|
cols: cols as u16,
|
||||||
|
pixel_width: 0,
|
||||||
|
pixel_height: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reader(&self) -> anyhow::Result<FileDescriptor> {
|
||||||
|
Ok(self.read.try_clone()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_all(&mut self, data: &[u8]) -> anyhow::Result<()> {
|
||||||
|
Ok(self.write.write_all(data)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for WinTty {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.set_cooked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
mod unix {
|
mod unix {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use termios::{cfmakeraw, tcsetattr, Termios, TCSAFLUSH};
|
||||||
|
|
||||||
pub struct UnixTty {
|
pub struct UnixTty {
|
||||||
tty: FileDescriptor,
|
tty: FileDescriptor,
|
||||||
@ -152,7 +266,7 @@ mod unix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size(&self) -> anyhow::Result<PtySize> {
|
pub fn get_size(&self) -> anyhow::Result<PtySize> {
|
||||||
let mut size = MaybeUninit::<libc::winsize>::uninit();
|
let mut size = std::mem::MaybeUninit::<libc::winsize>::uninit();
|
||||||
if unsafe { libc::ioctl(self.tty.as_raw_fd(), libc::TIOCGWINSZ as _, &mut size) } != 0 {
|
if unsafe { libc::ioctl(self.tty.as_raw_fd(), libc::TIOCGWINSZ as _, &mut size) } != 0 {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"failed to ioctl(TIOCGWINSZ): {:#}",
|
"failed to ioctl(TIOCGWINSZ): {:#}",
|
||||||
|
Loading…
Reference in New Issue
Block a user