How do I use getContents to take input from the command line? - haskell

My program allows the user to specify a file which is read as input, however this is optional. If the user does not specify a file, I'd like to read input in from the command line.
I have this so far:
main :: IO()
main = do
(opts, mbArgs) <- parseCmdLine
input <-
case mbArgs of
Nothing -> getContents
Just file -> readFile file
This doesn't seem to be working. When a user doesn't stipulate a file, they are able to enter input, but there seems to be no way of terminating so that the program can then work on that input.
I thought that you had to press Ctrl+D, but that doesn't do anything.
Thanks for any help.

In a typical Unix-like terminal (such as Cygwin, at least in Cygwin's rxvt; not sure about the Windows Command Prompt), a Ctrl+D only sends EOF when you're at the start of a line. If you hit Enter and then Ctrl+D, it should work. If you want to send EOF without a newline, hit Ctrl+D twice in a row.
If it's not that, then there's presumably some other problem with your terminal; the code looks fine.

I'm going to write hammar's comment as an answer.
For me on windows, hitting ctrl+Z crtl+Z enter worked.

Related

Haskell does not return from getLine

For some reason, Haskell on my machine does never return from any getLine call. For instance, I tried to run the following code straight from Learn You a Haskell for Great Good:
main = do
putStrLn "Hello, what's your name?"
name <- getLine
putStrLn ("Hey " ++ name ++ ", you rock!")
When I run it, the first line is printed, and I see my input when I type a name, however when I press Enter the program just blocks there and never prints the final line.
How should I fix this?
edit: I am running it from the Sublime IDE, maybe that has something to do with it
After doing a quick search on how Sublime runs programs, I found a youtube video (edit: and this SO post) which says that Sublime's "run program" functionality can only show output and isn't capable of reading input.
So it looks like you'll have to run your program from the command line or from within GHCi using :main. The latter might be the most convenient as Sublime actually supports a GHCi tab, so you can still do everything from within Sublime.
This seems to be a limitation in Sublime's Build command (assuming that this is what you're using).
Sublime executes the script using runhaskell, but apparently, it doesn't capture STDIN (which makes kind of sense - build results are usually read-only and not an interactive session).
Workaround: run your script from the command line with
runhaskell script.hs
and everything works as expected

Use stdin from within R studio

When I try the following:
f<-file("stdin")
lines<-readLines(f)
from within R-studio on Ubuntu I can input text but unable to terminate it. Ctr+C/D, random hitting keyboard won't help. It simply hangs
I only found the followin so far
How to input EOF in stdin in R?
but no help there - had to kill R-studio.
Anybody have explanation what is wrong?
Presumably, Rstudio is redirecting stdin, so that it cannot be properly accessed as "stdin" or "/dev/stdin" any longer. However, stdin() still works.
I was still unable to actually type Ctrl+D. But it is possible to read a fixed number of lines:
> a <- readLines(stdin(), n=2)
Hello
World
> a
[1] "Hello" "World"
I've also discovered a hack that may help for interactive debugging. Let's say, you have at most 10 lines in your manual examples. Then you can do
> a <- readLines(stdin(), n=10)
abc
def
ghi
# and now just keep pressing ENTER
...
> a <- a[a != ""]
> a
[1] "abc" "def" "ghi"
If you run the same code in an environment where Ctrl+D is available, it also properly terminates the input.
Caveats: but stdin() does not work with Rscript: you'd have to switch back to file("stdin"). Furthermore, in some environments, if you use readLines with n=1 to read the file line-by-line, you may end up reopening the file and getting the first line every time. It seems that putting everything into a file and reading the whole file at once with e.g. read.table is a much more robust way of developing with Rstudio.

File list by ls are misaligned

I catted a binary file and hit Ctrl-Z to stop it. Now ls results are misaligned. What did it happen and how could I have them listed correctly again ?
Type reset to reset your terminal, and press Enter. Then maybe press Ctrl+L to clear the screen. You should be back to normal.
Oh and by the way, that binary cat you ran, when you pressed Ctrl-Z that just suspended it, it's probably still running. Run jobs to see the list of jobs, and if it's there, say job number 2, do kill %2 (or whichever job number).
When you catted the binary file, your terminal probably inadvertently interpreted some of its data as control sequences and tried to execute them, screwing its properties and state.
You can either kill the terminal altogether (quit it if you're in a GUI, or relog if you're on a tty), or use another control sequence to reset the terminal. echo -e \\033c should do the trick. Some systems also have a reset builtin/command, which accomplishes the same thing.

Linux command line issue with prompt

I started to manage a new server based on CentOS. I wanted to change the prompt, so I wrote the following command :
PS1="\e[0;36m[`pwd`]\$\e[m "
It worked perfectly. But since I got an annoying issue. When I write something quite long, or displays an older command that is quite long using up arrow, or paste it, and then click on "home" to get to the top of the line, the cursor stops within the command, 10 characters ahead of the prompt. For example, lets say I write this :
[/]$ git log --pretty=oneline
And then click on home button, the cursor will stop on the "p" letter, after "--". And if I try to move with left key to get on top of the line, it does that annoying bip saying "you are already there, mate"...
Now, lets say I wrote
ls
and right after
git log --pretty=oneline
If I go up two times, the prompt displays this :
[/]$ git log --ls
And if I keep going up the "git log --" never goes away. Now if I press enter, it will still launch the ls command without any problem. Seems like it's just a display issue. But still, that confuse me all the time...
Thanks ahead for your help !
Use \w to print the working directory in your shell prompt, rather than trying to embed a command.
You also need to escape the escape sequences so that bash doesn't attempt to count them as printed characters. This is done by enclosing them with \[ and \].
So you should end up with something like:
PS1="\[\e[0;36m\][\w]\$\[\e[m\]"
Your prompt is also very compact, you may want to stick some spaces in it. The key is that you have used the brackets to escape the non-printable characters.
You can find a complete list of these substitutions in the PROMPTING section of the bash man page.

How to make getch() accept taking an enter hit (\n)?

I made a touch typing console program in C++.
It reads the text from a file and load it to the screen.
User must enter the right letter in order for him to proceed to the next letter.
My only Problem is with the '\n',
so if I had something like this in the text file (the file I'm reading from):
"
hello
dude
Sup
"
After the user enters "hello",
he should press enter right?
But whenever he presses enter, getch() takes him back to the beginning for the current line.
How can I fix this?
I'm reading the whole file and storing it to a string, like this:
void getTextFromFile()
{
text.assign(istreambuf_iterator<char>(fin), istreambuf_iterator<char>());
}
First of all, getch() is deprecated (just an FYI if you start having more problems with it). From my understanding you're trying to accept character input 1 char at a time. If you're using getch() for the '\n' enter press you should be fine. If not please explain more.
I just tried a quick experiment. Apparently getch() (which, as reagan says, is deprecated; use _getch() instead) returns '\r', not '\n', when you press Enter.
With your current program, try typing Ctrl-J instead of Enter; that should give you a '\n' result from getch().
And for future reference, you should show us the actual code that calls getch(). I have no idea how the currentLetter = getch(); that you mentioned in a comment relates to the code in the question.

Resources