3

In contrast to the information in "learn you a haskell", on my windows system, ghci translates CTRL-D to EOT, not EOF.

Thus, when I do something like:

input <- getContents
doSomething input

, where doSomething is a function which consumes the input.
Doing that, I have to press CTRL-Z to end my input text, which makes sense since getContents is intended for process piping...

But if I repeat the above steps a second time, it fails because stdin is closed.

So, while browsing System.IO, I could not find an alternative to getContents, which would react on EOT.

Do I have to write such a function myself or is it to be found in another package, maybe?

Btw, the version of GHCI, I use is 8.2.2.
Also, I do not want single line processing. I am aware of getLine but it is not what I want in this case.

BitTickler
  • 10,905
  • 5
  • 32
  • 53
  • Not as far as I'm aware. What you're asking for is sufficiently weird (in that I've never seen a program act this way) that it's not really something that fits in a standard library. Lots of older command line applications used a single `.` on one line as a multiline text terminator, so you could do _that_ if you really wanted to. – Cubic May 20 '19 at 11:40
  • @Cubic Not that weird obviously as "Learn you a haskell for the greater good" web site shows examples (which do not work) and given that you still have to type ``:{`` etc. for multiline input in ghci instead of simply typing away until ``CTRL-D``. In the meantime I looked at github for the source of ``getContents`` and see that it is mapped to ``primGetContents``. Any idea where I can find the source code for that? – BitTickler May 20 '19 at 11:44
  • I think this is a valid question, just ran into the same problem. On the python command line, calling `sys.stdin.read()` just works. I assume the problem is with GHCI substituting EOT for EOF, which may be to work around `getContents` semi-closing the handle on EOF, compare https://stackoverflow.com/questions/12119420/haskell-ghci-using-eof-character-on-stdin-with-getcontents. – robx Dec 01 '19 at 13:21

1 Answers1

2

Here is the function I was looking for:

getContentsEOT :: IO String
getContentsEOT = 
    getChar >>= \c -> 
        if c == '\EOT' 
            then return "" 
            else getContentsEOT >>= \s -> 
                return (c:s)
BitTickler
  • 10,905
  • 5
  • 32
  • 53