Difference between revisions of "Haskell mode for Emacs"
Jump to navigation
Jump to search
BrettGiles (talk | contribs) (HaWiki conversion / add XEmacs fixes) |
m |
||
(103 intermediate revisions by 30 users not shown) | |||
Line 1: | Line 1: | ||
+ | #REDIRECT[[Emacs]] |
||
− | haskell-mode is a major mode for Emacs and XEmacs specifically for writing Haskell code. You can get HaskellMode from the web page: http://www.haskell.org/haskell-mode/ or on Debian you can type <code>apt-get install haskell-mode</code>. |
||
− | ==Tips and use== |
||
− | Handy keybindings in haskell-mode. See the documentation <code>C-h m</code> for more information: |
||
− | *<code>C-c C-=</code> inserts an = sign and lines up type signatures and other pattern matches nicely. |
||
− | *<code>C-c C-|</code> inserts a guard |
||
− | *<code>C-c C-o</code> inserts a guard <hask>| otherwise =</hask> and lines up existing guards |
||
− | *<code>C-c C-w</code> inserts a where keyword |
||
+ | [[Category: Pages to be removed]] |
||
− | Here's an example for <code>C-c C-=</code>. Put your cursor after myInt and hit <code>C-c C-=</code> |
||
− | <haskell> |
||
− | blah :: Int -> Int |
||
− | blah myInt |
||
− | </haskell> |
||
− | note how the function signature is reindented to match the column of the = sign. |
||
− | <haskell> |
||
− | blah :: Int -> Int |
||
− | blah myInt = |
||
− | </haskell> |
||
− | |||
− | You can also use Haskell-Mode to load Emacs buffers with Haskell code in either Hugs or GHC. To load something in Hugs or ghci, type <code>C-c C-l</code> to load the file. |
||
− | |||
− | If you have imenu (standard in Emacs and available as a package in XEmacs), you can use <code>M-x imenu</code> to jump to any definition in the file. A good keybinding for it is: |
||
− | <pre-lisp> |
||
− | (global-set-key [(control meta down-mouse-3)] 'imenu) |
||
− | </pre-lisp> |
||
− | If you don't have imenu but have func-menu you can do |
||
− | <pre-lisp> |
||
− | (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan) |
||
− | </pre-lisp> |
||
− | after which some keybindings will be available, such as: |
||
− | *<code>C-c l</code> fume-list-functions - quickly jump to a function definition in this file. |
||
− | |||
− | == Questions == |
||
− | * haddock integration with haskell-doc.el ? |
||
− | |||
− | == Bugs == |
||
− | * Debian maintains a list of bugs for haskell-mode [http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=haskell-mode here]. |
||
− | * haskell-mode does not check for unsent input at a ghci prompt before sending a <code>:load myfilename</code> command to ghci. |
||
− | |||
− | On some the linux systems with XEmacs, admittedly, only verified on Ubuntu and Debian), there is a system function missing that interferes with automatic indenting. Secondly, there seems to be an issue with setting the <code-lisp>haskell-default-face</code-lisp> to <code-lisp>nil</code-lisp>. |
||
− | |||
− | ===line-end-position=== |
||
− | |||
− | To fix this, find where the haskell mode package is installed on your system. (Usually <code>/usr/share/emacs/site-lisp/haskell-mode</code>). Edit the file <code>haskell-indent.el</code> and add the lines: |
||
− | <pre-lisp> |
||
− | (eval-and-compile |
||
− | |||
− | ;; If `line-end-position' isn't available provide one. |
||
− | (unless (fboundp 'line-end-position) |
||
− | (defun line-end-position (&optional n) |
||
− | "Return the `point' of the end of the current line." |
||
− | (save-excursion |
||
− | (end-of-line n) |
||
− | (point))))) |
||
− | </pre-lisp> |
||
− | right after the comments at the top. That should fix the issue. |
||
− | |||
− | ===haskell-default-face=== |
||
− | |||
− | This one shows up when typing in code (at various spots - most often when typing a qualified function, such as <hask>List.map</hask>.) |
||
− | |||
− | To fix this one, edit the file <code>haskell-font-lock.el</code>. Look for the line that says: |
||
− | <pre-lisp> |
||
− | (defvar haskell-default-face nil) |
||
− | </pre-lisp> |
||
− | and change this to |
||
− | <pre-lisp> |
||
− | (defvar haskell-default-face 'default) |
||
− | </pre-lisp> |
||
− | In my version, this is line 168. |
||
− | |||
− | Then, look for the line that says: |
||
− | <pre-lisp> |
||
− | (,qvarid 0 haskell-default-face) |
||
− | </pre-lisp> |
||
− | and change it to |
||
− | <pre-lisp> |
||
− | (,qvarid 0 (symbol-value 'haskell-default-face)) |
||
− | </pre-lisp> |
||
− | |||
− | For me, this is line 326 of the file. |
||
− | YMMV - hope this helps. |
||
− | |||
− | |||
− | |||
− | |||
− | == Tricks and Tweaks == |
||
− | |||
− | === Automatic Unit Testing === |
||
− | Here's a cute trick I've evolved: |
||
− | |||
− | I'm a great fan of [[unit test first]], as described by eXtremeProgramming on TheOriginalWiki. |
||
− | |||
− | With the code below, I can press F12 and immediately run all of my unit tests, and immediately see whether they all passed or not. |
||
− | I've put all of my unit tests into their own file with a main function that runs the tests and gives an exitcode according to the test results. I've specified that the compile-command for that file compiles and runs the file. |
||
− | |||
− | This elisp code will run the <code>compile</code> command from the F12 key in emacs. The output will popup a new window twelve lines tall. If the compilation is successful (exitcode zero) the window goes away. If the exitcode is 1 or greater, the window stays so you can see the output. |
||
− | <pre-lisp> |
||
− | (require 'compile) |
||
− | |||
− | ;; this means hitting the compile button always saves the buffer |
||
− | ;; having to separately hit C-x C-s is a waste of time |
||
− | (setq mode-compile-always-save-buffer-p t) |
||
− | ;; make the compile window stick at 12 lines tall |
||
− | (setq compilation-window-height 12) |
||
− | |||
− | ;; from enberg on #emacs |
||
− | ;; if the compilation has a zero exit code, |
||
− | ;; the windows disappears after two seconds |
||
− | ;; otherwise it stays |
||
− | (setq compilation-finish-function |
||
− | (lambda (buf str) |
||
− | (unless (string-match "exited abnormally" str) |
||
− | ;;no errors, make the compilation window go away in a few seconds |
||
− | (run-at-time |
||
− | "2 sec" nil 'delete-windows-on |
||
− | (get-buffer-create "*compilation*")) |
||
− | (message "No Compilation Errors!")))) |
||
− | |||
− | |||
− | ;; one-button testing, tada! |
||
− | (global-set-key [f12] 'compile) |
||
− | </pre-lisp> |
||
− | |||
− | |||
− | This Haskell code has some Emacs local variable settings at the bottom specifying what the compile-command should be for this buffer. |
||
− | <haskell> |
||
− | import HUnit |
||
− | import System |
||
− | |||
− | myTestList = |
||
− | TestList [ |
||
− | "add numbers" ~: 5 ~=? (3 + 2) |
||
− | ,"add numbers" ~: 5 ~=? (3 + 3) |
||
− | ] |
||
− | |||
− | h = runTestTT myTestList |
||
− | |||
− | main = do c <- h |
||
− | putStr $ show c |
||
− | let errs = errors c |
||
− | fails = failures c |
||
− | System.exitWith (codeGet errs fails) |
||
− | |||
− | codeGet errs fails |
||
− | | fails > 0 = ExitFailure 2 |
||
− | | errs > 0 = ExitFailure 1 |
||
− | | otherwise = ExitSuccess |
||
− | |||
− | -- Local Variables: |
||
− | -- compile-command: "ghc --make -o Test_Demo -i/home/shae/src/haskell/libraries/ HUnitDemo.hs && ./Test_Demo" |
||
− | -- End: |
||
− | </haskell> |
||
− | |||
− | |||
− | If you have any questions, ideas, or suggestions for this code, the maintainer would love to hear them. |
||
− | |||
− | [[Category:Development tools]] |
Latest revision as of 06:27, 8 June 2023
Redirect to: