2014-09-13 111 views
1

我想用Haskell實現一個簡單的編輯器。Haskell代碼與xterm子進程交互

我的基本想法是打開一個xterm實例,然後發送它編輯器應該顯示的內容(文本+例如着色,光標位置等)。內容可以簡單地在每個關鍵筆畫上重寫。

我設法在一個子進程中打開xterm並讓它顯示一個文件的內容(見下面的代碼);然而,寫入其標準輸入似乎不起作用(我沒有得到任何錯誤,但文本也沒有在xterm窗口中顯示)。然後,我嘗試運行簡單的shell命令,如lscat - 通過這些流,通過流進行交互確實可行。

問題:我的Haskell進程如何與創建的xterm實例交互?

import System.IO 
import System.Process    

main = do 
    (Just hin, Just hout, Just herr, jHandle) <- 
     createProcess (proc "xterm" ["-e", "tail", "-f", "foo.txt"]) 
      { cwd = Just "." 
      , std_in = CreatePipe 
      , std_out = CreatePipe 
      , std_err = CreatePipe 
      } 
    hPutStrLn hin "This should be printed to xterm" 
    waitForProcess jHandle 

回答

1

不像catgrep,讀,從xterm寫作不是從通常的標準流來完成。您需要打開僞終端(使用System.Posix.Terminal中的函數),通過參數-S將從屬部分掛接到xterm,然後從主部分讀取/寫入。

關於-S說法,在xterm手冊頁說:

此選項允許的xterm被用作用於現有程序的輸入和輸出通道和在專門的應用程序,有時使用。選項值指定在從屬模式下使用的僞終端名稱的最後幾個字母,以及繼承的文件描述符的編號。如果該選項包含一個「/」字符,該字符將從文件描述符分隔用於僞終端名稱的字符。

更多信息herehere

一些示例代碼:

import Control.Monad 
import Control.Applicative 
import System.IO 
import System.FilePath 
import System.Posix.Terminal 
import System.Posix.Types 
import System.Posix.IO 
import System.Process 

main :: IO() 
main = do 
    ([email protected](Fd mfd),[email protected](Fd sfd)) <- openPseudoTerminal 
    -- deactivating echo seems to be neccessary 
    slaveattr <- flip withoutMode EnableEcho <$> getTerminalAttributes slave 
    setTerminalAttributes slave slaveattr Immediately 
    sname <- getSlaveTerminalName master 
    let sbasename = takeFileName sname 
     sargs = "-S" ++ sbasename ++ "/" ++ show sfd 
    (Just _, Just _, Just _, _) <- createProcess $ 
       (proc "xterm" [sargs] ) { cwd = Just "." 
             , std_in = CreatePipe 
             , std_out = CreatePipe 
             , std_err = CreatePipe 
             } 
    h <- fdToHandle master 
    hSetBuffering h NoBuffering 
    -- read and print the initial line sent by xterm 
    hGetLine h >>= putStrLn 
    hPutStrLn h "this should appear in the xterm" 
    -- this should appear both in console and xterm 
    forever $ hGetChar h >>= \c -> (putChar c >> hPutChar h c)