I'm trying to write a urlview clone in Haskell. The program reads a message (piped via STDIN), extracts all URLs and asks the user to select one of them.
After reading the message, STDIN obviously reaches EOF. In Python, I reset STDIN like this
message = sys.stdin.read()
sys.stdin = open('/dev/tty')
selected_index = raw_input('Which URL to open? ')
How would I achieve the same in Haskell?
You cannot change the stdin
handle in Haskell. In Python, the sys.stdin
variable only points to a handle, so when you replace it with a new file handle, the old stdin
handle still remains, but the sys.stdin
variable now contains the file handle.
Since the System.IO.stdin
handle is immutable in Haskell (as are so many other variables, or should I say values), you cannot do the same thing in Haskell.
What you can do is to open the /dev/tty
file with a new handle, and use that handle to read from the terminal. You can use all of the same operations on any handle as you can on stdin
. Simply import System.IO
, and every time you would otherwise use foo ...
to get some input, instead use hFoo handle ...
. For instance, to read a line from the terminal, use this code:
import System.IO
-- ...
newstdin <- openFile "/dev/tty" ReadMode
-- Instead of normal getLine; just prepend "h" and pass the handle
line <- hGetLine newstdin
Don't forget to close your new handle with a call to hClose
!
As far as I know there is no way to "re-assign" the built-in stdin
in Haskell, but you can otherwise open a new handle to /dev/tty
. A direct translation of your Python code would be something like
import System.IO
main = do
message <- getContents
tty <- openFile "/dev/tty" ReadMode
putStr "Which URL to open? "
url <- hGetLine tty
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With