vfs: add is_terminal()
This commit is contained in:
parent
8dbbc07ff6
commit
4acb148d0e
@ -93,12 +93,6 @@ impl CharFile {
|
|||||||
self.device.0.read_nonblocking(buf)
|
self.device.0.read_nonblocking(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if self.read {
|
|
||||||
// self.device.0.read(buf)
|
|
||||||
// } else {
|
|
||||||
// Err(Error::InvalidOperation)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
if !self.write {
|
if !self.write {
|
||||||
@ -111,10 +105,8 @@ impl CharFile {
|
|||||||
self.device.0.write_nonblocking(buf)
|
self.device.0.write_nonblocking(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if self.write {
|
|
||||||
// self.device.0.write(buf)
|
pub fn is_terminal(&self) -> bool {
|
||||||
// } else {
|
self.device.0.is_terminal()
|
||||||
// Err(Error::ReadOnly)
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -341,6 +341,14 @@ impl File {
|
|||||||
|
|
||||||
/// Performs a device-specific request
|
/// Performs a device-specific request
|
||||||
pub fn device_request(&self, req: &mut DeviceRequest) -> Result<(), Error> {
|
pub fn device_request(&self, req: &mut DeviceRequest) -> Result<(), Error> {
|
||||||
|
match req {
|
||||||
|
DeviceRequest::IsTerminal(value) => {
|
||||||
|
*value = self.is_terminal();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::Char(f) => f.device.device_request(req),
|
Self::Char(f) => f.device.device_request(req),
|
||||||
Self::Block(f) => f.device.device_request(req),
|
Self::Block(f) => f.device.device_request(req),
|
||||||
@ -375,6 +383,14 @@ impl File {
|
|||||||
_ => Err(Error::InvalidOperation),
|
_ => Err(Error::InvalidOperation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_terminal(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Char(dev) => dev.is_terminal(),
|
||||||
|
Self::PtySlave(_) | Self::PtyMaster(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PageProvider for File {
|
impl PageProvider for File {
|
||||||
|
@ -29,6 +29,8 @@ pub enum DeviceRequest {
|
|||||||
GetTerminalSize(MaybeUninit<terminal::TerminalSize>),
|
GetTerminalSize(MaybeUninit<terminal::TerminalSize>),
|
||||||
/// Sets a foreground process group ID for the terminal
|
/// Sets a foreground process group ID for the terminal
|
||||||
SetTerminalGroup(ProcessGroupId),
|
SetTerminalGroup(ProcessGroupId),
|
||||||
|
/// Returns `true` if a file/device is a terminal
|
||||||
|
IsTerminal(bool),
|
||||||
|
|
||||||
/// "Acquires" ownership of the device, preventing others from accessing it
|
/// "Acquires" ownership of the device, preventing others from accessing it
|
||||||
AcquireDevice,
|
AcquireDevice,
|
||||||
|
@ -28,7 +28,7 @@ pub use abi::io::{
|
|||||||
FileType, OpenOptions, PipeOptions, RawFd, SeekFrom, TimerOptions,
|
FileType, OpenOptions, PipeOptions, RawFd, SeekFrom, TimerOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
use abi::{error::Error, process::ProcessOption, util::FixedString};
|
use abi::{error::Error, io::DeviceRequest, process::ProcessOption, util::FixedString};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
|
||||||
pub fn current_directory<T, F: FnOnce(&str) -> T>(mapper: F) -> Result<T, Error> {
|
pub fn current_directory<T, F: FnOnce(&str) -> T>(mapper: F) -> Result<T, Error> {
|
||||||
@ -50,3 +50,12 @@ pub fn set_current_directory(path: &str) -> Result<(), Error> {
|
|||||||
unsafe { crate::sys::set_process_option(&mut option) }?;
|
unsafe { crate::sys::set_process_option(&mut option) }?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_terminal(f: RawFd) -> bool {
|
||||||
|
let mut option = DeviceRequest::IsTerminal(false);
|
||||||
|
let res = unsafe { crate::sys::device_request(f, &mut option) };
|
||||||
|
match (res, option) {
|
||||||
|
(Ok(()), DeviceRequest::IsTerminal(true)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
io::{self, Read, Stdin},
|
io::{self, Read},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::TermInput;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
pub enum TermKey {
|
pub enum TermKey {
|
||||||
Char(char),
|
Char(char),
|
||||||
@ -23,7 +25,7 @@ pub trait ReadChar {
|
|||||||
fn read_char(&mut self) -> Result<char, InputError>;
|
fn read_char(&mut self) -> Result<char, InputError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadChar for Stdin {
|
impl ReadChar for TermInput {
|
||||||
fn read_char(&mut self) -> Result<char, InputError> {
|
fn read_char(&mut self) -> Result<char, InputError> {
|
||||||
let mut buf = [0; 4];
|
let mut buf = [0; 4];
|
||||||
self.read_exact(&mut buf[..1])
|
self.read_exact(&mut buf[..1])
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os, rustc_private))]
|
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os, rustc_private))]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt, fs::File, io::{self, stdin, stdout, IsTerminal, Read, Stdin, Stdout, Write}, os::fd::{AsRawFd, RawFd}
|
||||||
io::{self, stdin, stdout, Stdin, Stdout, Write},
|
|
||||||
os::fd::{AsRawFd, RawFd},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::{input::ReadChar, sys::RawMode};
|
pub use self::{input::ReadChar, sys::RawMode};
|
||||||
@ -43,8 +41,31 @@ pub trait RawTerminal {
|
|||||||
fn raw_size(&self) -> io::Result<(usize, usize)>;
|
fn raw_size(&self) -> io::Result<(usize, usize)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TermInput {
|
||||||
|
Stdin(Stdin),
|
||||||
|
File(File)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for TermInput {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
Self::Stdin(stdin) => stdin.read(buf),
|
||||||
|
Self::File(file) => file.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for TermInput {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
match self {
|
||||||
|
Self::Stdin(stdin) => stdin.as_raw_fd(),
|
||||||
|
Self::File(file) => file.as_raw_fd(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Term {
|
pub struct Term {
|
||||||
stdin: Stdin,
|
stdin: TermInput,
|
||||||
stdout: Stdout,
|
stdout: Stdout,
|
||||||
raw: RawMode,
|
raw: RawMode,
|
||||||
}
|
}
|
||||||
@ -134,9 +155,8 @@ impl RawTerminal for Stdout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Term {
|
impl Term {
|
||||||
pub fn is_tty() -> bool {
|
pub fn stdin_is_tty() -> bool {
|
||||||
// TODO
|
stdin().is_terminal()
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn input_fd(&self) -> RawFd {
|
pub fn input_fd(&self) -> RawFd {
|
||||||
@ -145,6 +165,12 @@ impl Term {
|
|||||||
|
|
||||||
pub fn open() -> Result<Self, Error> {
|
pub fn open() -> Result<Self, Error> {
|
||||||
let stdin = stdin();
|
let stdin = stdin();
|
||||||
|
let stdin = if stdin.is_terminal() {
|
||||||
|
TermInput::Stdin(stdin)
|
||||||
|
} else {
|
||||||
|
let file = File::open("/dev/tty")?;
|
||||||
|
TermInput::File(file)
|
||||||
|
};
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
|
|
||||||
// Set stdin to raw mode
|
// Set stdin to raw mode
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{self, Stdin, Stdout},
|
io::{self, Stdout},
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
os::yggdrasil::io::{
|
os::{fd::AsRawFd, yggdrasil::io::{
|
||||||
device::{DeviceRequest, FdDeviceRequest},
|
device::{DeviceRequest, FdDeviceRequest},
|
||||||
terminal::{update_terminal_options, TerminalOptions},
|
terminal::{update_terminal_options, TerminalOptions},
|
||||||
},
|
}},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RawMode(TerminalOptions);
|
pub struct RawMode(TerminalOptions);
|
||||||
@ -13,15 +13,15 @@ impl RawMode {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// May leave the terminal in broken state, unsafe.
|
/// May leave the terminal in broken state, unsafe.
|
||||||
pub unsafe fn enter(stdin: &Stdin) -> io::Result<Self> {
|
pub unsafe fn enter<F: AsRawFd>(stdin: &F) -> io::Result<Self> {
|
||||||
update_terminal_options(stdin, |_| TerminalOptions::raw_input()).map(RawMode)
|
update_terminal_options(stdin.as_raw_fd(), |_| TerminalOptions::raw_input()).map(RawMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// May leave the terminal in broken state, unsafe.
|
/// May leave the terminal in broken state, unsafe.
|
||||||
pub unsafe fn leave(&self, stdin: &Stdin) {
|
pub unsafe fn leave<F: AsRawFd>(&self, stdin: &F) {
|
||||||
update_terminal_options(stdin, |_| self.0).ok();
|
update_terminal_options(stdin.as_raw_fd(), |_| self.0).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Term::is_tty() {
|
if !Term::stdin_is_tty() {
|
||||||
eprintln!("Not a tty");
|
eprintln!("Not a tty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Write},
|
fmt::{self, Write},
|
||||||
io,
|
io,
|
||||||
|
process::ExitCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
@ -160,9 +161,15 @@ struct Args {
|
|||||||
filename: String,
|
filename: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> ExitCode {
|
||||||
// TODO check if running in a terminal
|
// TODO check if running in a terminal
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let view = View::open(&args.filename, !args.no_bar).unwrap();
|
let view = View::open(&args.filename, !args.no_bar).unwrap();
|
||||||
view.run()
|
match view.run() {
|
||||||
|
Ok(()) => ExitCode::SUCCESS,
|
||||||
|
Err(error) => {
|
||||||
|
yggdrasil_rt::debug_trace!("view: {error}");
|
||||||
|
ExitCode::FAILURE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user