Search code examples
haskellemacsghci

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.


Solution

  • 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)))