|
|
(94 intermediate revisions by 29 users not shown) |
Line 1: |
Line 1: |
| 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>. However, the released version (2.1) and the Debian package are both very old (Nov 2005).
| | #REDIRECT[[Emacs]] |
|
| |
|
| ==Obtaining the CVS version==
| | [[Category: Pages to be removed]] |
| | |
| <code>cvs -d :pserver:anoncvs@cvs.haskell.org:/cvs login # password 'cvs' </code>
| |
| | |
| <code>cvs -d :pserver:anoncvs@cvs.haskell.org:/cvs co fptools/CONTRIB/haskell-modes/emacs</code>
| |
| | |
| ==Minimal Setup==
| |
| | |
| Insert in your ~/.emacs or appropriate file:
| |
| | |
| <code>
| |
| (add-to-list 'load-path "path/to/haskell-mode")
| |
| </code>
| |
| | |
| <code>(load "haskell-site-file")</code>
| |
| | |
| <code>(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) </code>
| |
| | |
| <code>(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
| |
| </code>
| |
| | |
| <code>;; enable auto-mode selection:</code>
| |
| | |
| <code>(add-to-list 'auto-mode-alist '("\\.hs\\'" . 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
| |
| *<code>C-c C-.</code> aligns code over a region in a "sensible" fashion.
| |
| | |
| 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 could also achieve the same effect by selecting the region and typing <code>C-c C-.</code>
| |
| | |
| 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. Then, you can go on to type <code>C-c C-r</code> to reload the current module when you have made a change.
| |
| | |
| 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.
| |
| | |
| ===Xemacs===
| |
| 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.
| |
| | |
| === Hoogle lookup ===
| |
| This code adds hoogle lookup for emacs mode. If the current line contains a type signature, it is hoogled. Otherwise, the word at point is hoogled.
| |
| <pre-lisp>
| |
| (defun haskell-hoogle (query)
| |
| "Hoogle search for QUERY via browse-url"
| |
| (browse-url (concat "http://www.haskell.org/hoogle/?q=" query)))
| |
| | |
| (defun haskell-hoogle-point ()
| |
| "If point is at a type, hoogle for it. Else, hoogle for the word at point."
| |
| (interactive)
| |
| (if (save-excursion
| |
| (beginning-of-line)
| |
| (looking-at ".+::\\(.+\\)"))
| |
| (haskell-hoogle (match-string 1))
| |
| (haskell-hoogle (haskell-doc-get-current-word))))
| |
| | |
| (add-hook 'haskell-mode-hook
| |
| (lambda ()
| |
| (local-set-key (kbd "C-c C-d h") 'haskell-hoogle-point)))
| |
| | |
| </pre-lisp>
| |
| | |
| === Using Rectangular region commands ===
| |
| | |
| Emacs has a set of commands which operate on the region as if it were rectangular. This turns out to be extremely useful when dealing with whitespace sensitive languages.
| |
| | |
| <code>C-x r o</code> is "Open Rectangle". It will shift any text within the rectangle to the right side.
| |
| | |
| <code>C-x r d</code> is "Delete Rectangle". It will delete the contents of the rectangle and move anything on the right over.
| |
| | |
| <code>C-x r x</code> is "Copy Rectangle to Register". It will prompt you for a register number so it can save it for later.
| |
| | |
| <code>C-x r g</code> is "Insert register". This will insert the contents of the given register, overwriting whatever happens to be within the target rectangle.
| |
| | |
| As with all Emacs modifier combos, you can type <code>C-x r C-h</code> to find out what keys are bound beginning with the <code>C-x r</code> prefix.
| |
| | |
| === Aligning Code ===
| |
| | |
| Emacs22 has a neat tool called: align-regexp. Select a region you want to align text within, M-x align-regexp, and type a regexp representing the alignment delimiter.
| |
| | |
| For example, I often line up my Haddock comments:
| |
| | |
| <haskell>
| |
| f :: a -- ^ does a
| |
| -> Foo b -- ^ and b
| |
| -> c -- ^ to c
| |
| </haskell>
| |
| | |
| Select the region, and let the regexp be: <code>--</code>
| |
| | |
| <haskell>
| |
| f :: a -- ^ does a
| |
| -> Foo b -- ^ and b
| |
| -> c -- ^ to c
| |
| </haskell>
| |
| | |
| Of course, this works for just about anything. Personally, I've globally bound it to <code>C-x a r</code>:
| |
| | |
| <code>(global-set-key (kbd "C-x a r") 'align-regexp)</code>.
| |
| | |
| [[Category:Development tools]]
| |