How to send text to GHCi process?

末鹿安然 提交于 2019-12-21 05:11:10

问题


I'm working on Haskell presentation engine Howerpoint. It is running in GHCi. I would like to create a function which would output a statement to current running GHCi session. It must work on Linux and Mac, Windows is not necessary. Function probably will have type

executeStatement :: String -> IO ()

What I tried already:

  • getProcessID and getParentProcessID and then sending something like

    echo 'xxx' > /proc/92856/fd/1
    -bash: /proc/92856/fd/1: No such file or directory
    
  • I also tried runCommand but it executes command in the Bash and not in GHCi so I got error that the command was not found

  • xdotool does not run on mac


回答1:


You could use the ghcid project from hackage to evaluate expressions. They would not be evaluated in the same session as your are currently running, but you can send expressions and read their output in a session nonetheless. Here is an example:

import Language.Haskell.Ghcid

main :: IO ()
main = do 
    (g, _) <- startGhci "ghci" (Just ".") True 
    let executeStatement = exec g
    executeStatement "let x = 33"
    executeStatement "x + 8" >>= print . head
    executeStatement "print x" >>= print . head
    stopGhci g

The output is "41" "33" and g represents a ghci session.

If you really need to execute expressions in an already running ghci instance you can have a look at this function - startGhci and instead of creating a new process you would have to tap into the existing process and then set std_in, std_out and std_err.




回答2:


You could use a terminal multiplexer like tmux to execute ghci in one pane, and from another pane invoke tmux commands that send keystrokes to ghci.

tmux load-buffer lets you load text into a tmux clipboard (using - as the path reads from stdin).

# from within tmux
$ echo foo | tmux load-buffer -
$ tmux show-buffer
foo

tmux paste-buffer lets you paste the contents of a tmux clipboard into a pane:

$ tmux list-panes
0: [127x24] [history 1850/2000, 1343570 bytes] %0
1: [127x24] [history 0/2000, 0 bytes] %2 (active)
$ tmux paste-buffer -t %0

Another option, already mentioned in the comments, is to use the process library to launch a ghci process, and send the commands through piped stardard input.

Here's a small program that uses my process-streaming helper package for process (not really required, you could do the same using process alone). stdin is piped, stdout and stderr inherited:

{-# LANGUAGE OverloadedStrings #-}

import System.Process.Streaming -- from process-streaming
import Pipes (lift,yield) -- from pipes
import Control.Concurrent (threadDelay)

main :: IO ()
main = executeInteractive program (feedProducer (do
    let delay = lift (threadDelay (1000000*6))
    delay
    yield "4 + 3\n"
    delay
    yield "5 + 3\n"))
  where
    program = (shell "ghci"){ std_in = CreatePipe }

The output is:

$ ./Main
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
Prelude> 7
Prelude> 8
Prelude> Leaving GHCi.


来源:https://stackoverflow.com/questions/35331801/how-to-send-text-to-ghci-process

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!