Repository: kkawakam/rustyline (language: rust)

Issue:
Send prompt to stdout even if stdin is not a tty or check TERM also on Windows
This issue arises from the investigation in https://github.com/mthom/scryer-prolog/issues/2694. There is a comment at the end explaining my conclusions but I will re-word it here below.

I was having issues calling Scryer Prolog from emacs. Scryer Prolog uses rustyline for the repl, and it will print a prompt on the repl (`?- `). The emacs package `ediprolog` expects that prompt for running.

On Linux, the emacs shell `eshell` is identified by rustyline as an unsupported terminal, as it sets `TERM=dumb`. There `rustyline` [flushes the prompt to stdout](https://github.com/kkawakam/rustyline/blob/5b92355961718474fb67a84ae1520cbd75368f3d/src/lib.rs#L653-L660).

On Windows, the emacs shell `eshell` also sets `TERM=dumb` but this is not checked (it is said that [checking `TERM` on Windows is a no-op](https://github.com/kkawakam/rustyline/blob/5b92355961718474fb67a84ae1520cbd75368f3d/src/tty/windows.rs#L722-L725), not sure why) so it falls into [the third case of `readline_with`](https://github.com/kkawakam/rustyline/blob/5b92355961718474fb67a84ae1520cbd75368f3d/src/lib.rs#L673-L677) which does not flush the prompt.

I think at least with MSYS2 and others it is becoming more common for Windows applications to use things like `TERM=dumb` so I guess the check for "unsupported terminals" could be run also on Windows?


Discussion / hints:
For [is_unsupported](https://github.com/kkawakam/rustyline/blob/5b92355961718474fb67a84ae1520cbd75368f3d/src/tty/windows.rs#L722-L725), we need to check the behavior of other similar libraries but your proposal seems right.
For MSYS2, see #401.
Both [replxx](https://github.com/AmokHuginnsson/replxx/blob/1f149bfe20bf6e49c1afd4154eaf0032c8c2fda2/src/replxx_impl.cxx#L638) and [isocline](https://github.com/daanx/isocline/blob/c9310ae58941559d761fe5d2dd2713d245f18da6/src/isocline.c#L538) seem to behave like you suggested: no distinction between unix and windows.

Fix patch:
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index d4bceb6c2..abc02ccec 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -1,5 +1,8 @@
 //! This module implements and describes common TTY methods & traits
 
+/// Unsupported Terminals that don't support RAW mode
+const UNSUPPORTED_TERM: [&str; 3] = ["dumb", "cons25", "emacs"];
+
 use crate::config::{Behavior, BellStyle, ColorMode, Config};
 use crate::highlight::Highlighter;
 use crate::keys::KeyEvent;
@@ -200,6 +203,22 @@ pub trait Term {
     fn set_cursor_visibility(&mut self, visible: bool) -> Result<Option<Self::CursorGuard>>;
 }
 
+/// Check TERM environment variable to see if current term is in our
+/// unsupported list
+fn is_unsupported_term() -> bool {
+    match std::env::var("TERM") {
+        Ok(term) => {
+            for iter in &UNSUPPORTED_TERM {
+                if (*iter).eq_ignore_ascii_case(&term) {
+                    return true;
+                }
+            }
+            false
+        }
+        Err(_) => false,
+    }
+}
+
 // If on Windows platform import Windows TTY module
 // and re-export into mod.rs scope
 #[cfg(all(windows, not(target_arch = "wasm32")))]
@@ -218,3 +237,15 @@ pub use self::unix::*;
 mod test;
 #[cfg(any(test, target_arch = "wasm32"))]
 pub use self::test::*;
+
+#[cfg(test)]
+mod test_ {
+    #[test]
+    fn test_unsupported_term() {
+        std::env::set_var("TERM", "xterm");
+        assert!(!super::is_unsupported_term());
+
+        std::env::set_var("TERM", "dumb");
+        assert!(super::is_unsupported_term());
+    }
+}
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 0ef853921..1c25bbb07 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -34,9 +34,6 @@ use crate::layout::{Layout, Position, Unit};
 use crate::line_buffer::LineBuffer;
 use crate::{error, Cmd, ReadlineError, Result};
 
-/// Unsupported Terminals that don't support RAW mode
-const UNSUPPORTED_TERM: [&str; 3] = ["dumb", "cons25", "emacs"];
-
 const BRACKETED_PASTE_ON: &str = "\x1b[?2004h";
 const BRACKETED_PASTE_OFF: &str = "\x1b[?2004l";
 
@@ -70,22 +67,6 @@ fn get_win_size(fd: RawFd) -> (Unit, Unit) {
     }
 }
 
-/// Check TERM environment variable to see if current term is in our
-/// unsupported list
-fn is_unsupported_term() -> bool {
-    match std::env::var("TERM") {
-        Ok(term) => {
-            for iter in &UNSUPPORTED_TERM {
-                if (*iter).eq_ignore_ascii_case(&term) {
-                    return true;
-                }
-            }
-            false
-        }
-        Err(_) => false,
-    }
-}
-
 /// Return whether or not STDIN, STDOUT or STDERR is a TTY
 fn is_a_tty(fd: RawFd) -> bool {
     isatty(fd).unwrap_or(false)
@@ -1357,7 +1338,7 @@ impl Term for PosixTerminal {
                     false,
                 )
             };
-        let unsupported = is_unsupported_term();
+        let unsupported = super::is_unsupported_term();
         let sigwinch = if !unsupported && is_in_a_tty && is_out_a_tty {
             Some(SigWinCh::install_sigwinch_handler()?)
         } else {
@@ -1686,15 +1667,6 @@ mod test {
         assert_eq!(0, pos.row);
     }
 
-    #[test]
-    fn test_unsupported_term() {
-        std::env::set_var("TERM", "xterm");
-        assert!(!super::is_unsupported_term());
-
-        std::env::set_var("TERM", "dumb");
-        assert!(super::is_unsupported_term());
-    }
-
     #[test]
     fn test_send() {
         fn assert_send<T: Send>() {}
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index 1d843f8ef..dc714031e 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -718,9 +718,8 @@ impl Term for Console {
         })
     }
 
-    /// Checking for an unsupported TERM in windows is a no-op
     fn is_unsupported(&self) -> bool {
-        false
+        super::is_unsupported_term()
     }
 
     fn is_input_tty(&self) -> bool {


Test patch: