How to switch to Haskell Interactive and reload last line in emacs? - haskell

Is there a command available to load the the current buffer to the haskell process and execute the previous line I introduced in the ghci?
I am trying to make a function for this, but I get "Unexpected response from haskell process." because of this line: haskell-interactive-mode-history-previous
(defun reload-haskell-last-line () (interactive)
"blablabla"
(haskell-process-load-file)
(haskell-interactive-switch)
(haskell-interactive-mode-history-previous)
(haskell-interactive-mode-return)
)
This can be super handy for developing.
If this is not the right way, what do you usually use?
Atom haskell-ide repl has a similar feature, that I would like to replicate in emacs

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

Function to evaluate haskell in ghci while editing source file using Emacs

I'm editing a haskell source file. I want to run my main function in my inferior-haskell buffer (already opened in a different frame) and continue editing my source file. To do this, I do
C-c C-l, change frame, main<ret>, change back to original frame
This seems quite inefficient. I'd like an emacs function/key that does it one shot.
There is actually a function to do this already defined in inf-haskell.el: inferior-haskell-load-and-run. This loads your current file and runs :main.
You can bind it to a key in Haskell mode by adding a hook:
(defun my-haskell-mode-hook ()
(local-set-key (kbd "C-x C-r") 'inferior-haskell-load-and-run))
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
However, playing around with this for a bit, it seems to have an odd issue on my computer: sometimes, when it pops to the *haskell* buffer, it doesn't move the point to the end. I find this rather annoying. You can easily fix it by moving the point to the end yourself:
(defun my-haskell-load-and-run ()
"Loads and runs the current Haskell file."
(interactive)
(inferior-haskell-load-and-run inferior-haskell-run-command)
(sleep-for 0 100)
(end-of-buffer))
I believe the sleep-for is necessary because the Haskell command is run asynchronously and takes a little bit of time to return. This whole thing is something of a hack, but it seems to work.
Also, you might want to customize exactly what the inferior-haskell-run-command is. By default, it's :main. However, for me, I think just main would be better because main is affected by :set args ... where :main isn't.
If you want to stay in your current Haskell buffer, you can just do this:
(defun my-haskell-load-and-run ()
"Loads and runs the current Haskell file."
(interactive)
(let ((start-buffer (current-buffer)))
(inferior-haskell-load-and-run inferior-haskell-run-command)
(sleep-for 0 100)
(end-of-buffer)
(pop-to-buffer start-buffer)))
To use interactive-haskell-mode, I found a similar setting than the other answer:
(defun my-haskell-load-and-run ()
"Loads and runs the current Haskell file main function."
(interactive)
(haskell-process-load-file)
(haskell-interactive-mode-run-expr "main"))
(defun my-haskell-mode-hook ()
(local-set-key (kbd "C-x C-r") 'my-haskell-load-and-run))
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
But I have a small issue with it, it always jumps to the end of the source buffer... which can be annoying.

Evaluate buffer in ghci or hugs via Emacs

Using sml-mode in Emacs I have been able to send my buffer contents directly to an inferior SML process using C-c C-b. Now I want to do the same thing only with Haskell. Haskell-mode does not seem to support this, so I'm wondering: What is the right way to go about this with Emacs and Haskell?
While learning SML I've been using C-c C-b almost non-stop to easily evaluate my program as I go, instantly seeing the results of assigning values etc. But if I use C-c C-l in haskell-mode on a saved file containing two lines, let foo = "foo" and let bar = "bar" - I get "parse error (possibly incorrect indentation)"
I think you are making a common rookie mistake, confusing what you can write inside the repl of ghci and what you write in a haskell source file.
All sml interpreters are made in such a way that you can write any top level declaration into the repl, or put in other words: anything you can write in an sml file, you can write into the sml interpreter. Thus you are allowed to write val foo = "bar" into a file and use C-c C-b to load the file and you are allowed to just put in val foo = "bar" into the interpreter.
On the other hand, because of how haskell work, you can write let foo = 42 into ghci, however it is not a valid top level declaration and thus this can't be in a haskell source file (by it self). On the other hand you can have id n = n in a haskell source file and use C-c C-l to load the file, however you can't write this directly into ghci (you will get an error: :1:6: parse error on input '='). The reason for this is that the repl in ghci runs in the IO monad, and thus what ever you write into ghci must be done using the do notation. I can only recommend that you read Interactive evaluation at the prompt from the Using GHCi user guide.
C-c C-b in sml-mode is the exact same thing as C-c C-l in haskell-mode, well atleast conceptually. I don't know that much about the internals of haskell-mode, but in sml-mode C-c C-b executes some sml code in the interpreter, normally the use(...) function. In haskell-mode it seems to just excute the :load "..." ghci command
You can't do that with ghci (or hugs) for the simple reason that you can't write top-level definitions in ghci (or hugs). So even if you manually pasted your file's contents into ghci, all you'd get would be a syntax error.
So loading a file using C-c C-l is the best you can do.

Emacs hangs in haskell-mode with inferior-haskell-load-file call

When in a Haskell file, I use C-c C-l to run the command inferior-haskell-load-file which is intended to load the current file into the GHCI interpreter but Emacs just hangs until I hit C-g. Anyone know how I can get this to work?
GNU Emacs 23.3.1 (x86_64-pc-linux-gnu, GTK+ Version 2.24.5) of 2011-08-14 on allspice, modified by Debian
Using haskell-mode version v2.7.0
inferior-haskell-mode does some parsing based upon the expected ghci prompt. As such, if you change the prompt in a .ghci file, then it can't detect it.
For more information, see where haskell-ghci.el sets the comint-prompt-regexp value to determine what a prompt is.
;; GHCi prompt should be of the form `ModuleName> '.
(setq comint-prompt-regexp
"^\\*?[[:upper:]][\\._[:alnum:]]*\\( \\*?[[:upper:]][\\._[:alnum:]]*\\)*> ")
If you want to keep the setting in your .ghci file, then it may be possible to customise this settings.
Old question, but as I just ran into this today, I wanted to share how to actually customize comint-prompt-regexp since I had to figure it out.
This customization will recognize λ> prompts, or actually any single character before >), but it doesn't break the existing regex. In your .emacs:
(load-library "inf-haskell")
(defun my-inf-haskell-hook ()
(setq comint-prompt-regexp
(concat comint-prompt-regexp "\\|^.> ")))
(add-to-list 'inferior-haskell-mode-hook 'my-inf-haskell-hook)
You can add more dots to "\\|^.> " to recognize a longer prompt, but I wanted to keep it fixed-length for simplicity.
I had a similar problem caused by GHCi reporting some kind of error on startup, causing the Emacs haskell mode to wait for the GHCi prompt indefinitely (GHCi didn't show the standard prompt (Prelude>), but rather just showed >). You can try running GHCi externally and see if it reports any errors.
I got the same error message when I tried to use stack with emacs. For me, adding this line to my .emacs/init.el resolved the problem:
(setq haskell-program-name "stack ghci")

Node.js REPL continuation lines

When working with the node.js repl, is there a way to quit a continuation line that node is being over zealous with?
For example:
$ node
> {- -}
...
And pretty much everything you can type then gives you another continuation line. Ctrl+D quits the whole repl.
Obviously I don't want to go around typing {- -} all the time, but I do find I often type something erroneous when I'm using the repl to experiment. Then I have to quit the repl, and loose all the bits in memory.
You can also type:
.break
Type
.help
for more REPL options... the .clear command may also be useful because it breaks and clears the local context, in case you want to save yourself the trouble of exiting and restarting the repl.
Sorry - I really should experiment more and Google less.
The answer (at least on Ubuntu) is Ctrl+C.
Ctrl+C first quits any continuation. Then if you hit it again prints
(^C again to quit)
Then quits, as it says.
In the interest of making this question more useful, just tested this and the same thing works in Python's repl, Guile. But doesn't work in Rhino, where it quits the repl entirely.

Resources