1use crate::utils::module::{export_default, ModuleInfo};
4use rquickjs::{
5 module::{Declarations, Exports, ModuleDef},
6 prelude::Func,
7 Ctx, Result,
8};
9
10fn isatty(fd: i32) -> bool {
11 unsafe { libc::isatty(fd) != 0 }
12}
13
14pub struct TtyModule;
15
16impl ModuleDef for TtyModule {
17 fn declare(declare: &Declarations<'_>) -> Result<()> {
18 declare.declare("isatty")?;
19 declare.declare("default")?;
20 Ok(())
21 }
22
23 fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> {
24 export_default(ctx, exports, |default| {
25 default.set("isatty", Func::from(isatty))?;
26 Ok(())
27 })
28 }
29}
30
31impl From<TtyModule> for ModuleInfo<TtyModule> {
32 fn from(val: TtyModule) -> Self {
33 ModuleInfo {
34 name: "tty",
35 module: val,
36 }
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use crate::tty::TtyModule;
43 use crate::test::{call_test, test_async_with, ModuleEvaluator};
44 use std::io::{stderr, stdin, stdout, IsTerminal};
45
46 #[tokio::test]
47 async fn test_isatty() {
48 test_async_with(|ctx| {
49 Box::pin(async move {
50 ModuleEvaluator::eval_rust::<TtyModule>(ctx.clone(), "tty")
51 .await
52 .unwrap();
53
54 let module = ModuleEvaluator::eval_js(
55 ctx.clone(),
56 "test",
57 r#"
58 import { isatty } from 'tty';
59
60 export async function test() {
61 return new Array(3).fill(0).map((_, i) => +isatty(i)).join('')
62 }
63 "#,
64 )
65 .await
66 .unwrap();
67 let expect = [
68 stdin().is_terminal(),
69 stdout().is_terminal(),
70 stderr().is_terminal(),
71 ]
72 .map(|i| (i as u8).to_string())
73 .join("");
74 let result = call_test::<String, _>(&ctx, &module, ()).await;
75 assert_eq!(result, expect);
76 })
77 })
78 .await;
79 }
80}