如何可靠地确定Handle是否是Haskell中的终端?

时间:2017-09-12 09:13:50

标签: haskell ghc

我正在使用System.IO.hIsTerminalDevice来确定Handle是否是终端并在这种情况下应用着色。我注意到,在使用CreatePipe作为新进程stdin和stdout的流分支进程时,此函数返回True,这似乎是错误的答案:管道不应被视为终端。我试图查看System.IOSystem.POSIX.IO源代码的问题,但最终会导致C pipe函数无法使用。

有没有更好的方法来判断句柄是否是终端?或者我做错了什么?

更新

以下是两个应该暴露我观察到的行为的程序:

import           Control.Monad
import           System.IO
import           System.Process

main = do
  (in_, Just out, Just err, h) <-  createProcess $ (proc "./test2" [])
                                   { std_in = CreatePipe
                                   , std_err = CreatePipe
                                   , std_out = CreatePipe }
  dump out
  where
    dump h = forever $ do
      ln <- hGetLine h
      putStrLn ln

然后`test2:

import           System.IO

main = do
  print =<< hIsTerminalDevice stderr
  print =<< hIsTerminalDevice stdout
  print =<< hIsTerminalDevice stdin

然后运行第一个程序:

$ ./test
False
False
False

我知道发生了什么:我所要求的不是程序本身,而是 docker容器!我明确添加-t参数,为容器分配tty ......

1 个答案:

答案 0 :(得分:3)

您是否有一个最小的例子来说明问题?以下程序打印&#34; False&#34;两次,提示使用CreatePipe创建的句柄被错误标识为终端设备:

import System.Process
import System.IO

main = do (Just in_, Just out, err, h) <-
            createProcess $ (shell "cat") { std_in = CreatePipe,
                                            std_out = CreatePipe }
          print =<< hIsTerminalDevice in_
          print =<< hIsTerminalDevice out