2014-09-13 2 views
1

Я хочу реализовать простой редактор с Haskell.Код Haskell для взаимодействия с xterm-subprocess

Моей основной идеей было открыть экземпляр xterm, а затем отправить его содержимое, которое должен отображать редактор (текст +, например, раскраска, позиция курсора и т. Д.). Затем содержимое может быть просто переписано при каждом нажатии клавиши.

Мне удалось открыть xterm в подпроцессе и позволить ему отображать содержимое файла (см. Код ниже); однако запись на его stdin не работает (я не получаю никаких ошибок, но текст также не отображается в окне xterm). Затем я попытался запустить простые команды оболочки, такие как ls или cat - с ними взаимодействие через потоки действительно работает.

Вопрос: Как мой процесс 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

В отличии от cat и grep, чтения и записи из xterm не делается из обычных стандартных потоков. Вам нужно открыть псевдотерминал (используя функции от System.Posix.Terminal), подключить подчиненную часть к xterm с помощью аргумента -S, а затем прочитать/записать из основной части.

О -S аргумента Xterm страница руководство говорит:

Эта опция позволяет Xterm быть использована в качестве входного и выходного канала для существующей программы и иногда используется в специализированных приложениях. Значение параметра указывает последние несколько букв имени псевдотерминала для использования в ведомом режиме, а также количество наследуемого файлового дескриптора. Если опция содержит символ «/», это ограничивает символы, используемые для псевдотерминального имени из дескриптора файла.

Дополнительная информация here и here.

Некоторые примеры кода:

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) 

 Смежные вопросы

  • Нет связанных вопросов^_^