问题
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
andgetParentProcessID
and then sending something likeecho '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 foundxdotool
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