Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 747
Ian Kelling Avatar asked Nov 03 '12 21:11

Ian Kelling


People also ask

How do I load a Haskell file into Ghci?

Open a command window and navigate to the directory where you want to keep your Haskell source files. Run Haskell by typing ghci or ghci MyFile. hs. (The "i" in "GHCi" stands for "interactive", as opposed to compiling and producing an executable file.)

How do I exit Haskell?

You can also quit by typing control-D at the prompt. Attempts to reload the current target set (see :load ) if any of the modules in the set, or any dependent module, has changed.

What does variable not in scope mean in Haskell?

(When GHC complains that a variable or function is "not in scope," it simply means that it has not yet seen a definition of it yet. As was mentioned before, GHC requires that variables and functions be defined before they are used.)


1 Answers

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)))
like image 141
Tikhon Jelvis Avatar answered Nov 15 '22 05:11

Tikhon Jelvis