1 ;;; Haskell mode for emacs (c) Simon Marlow 11/1/92
3 ;;; To: partain@dcs.gla.ac.uk
4 ;;; Subject: Haskell mode for emacs
5 ;;; Date: Mon, 14 Dec 92 17:41:56 +0000
6 ;;; From: Simon Marlow <simonm@dcs.gla.ac.uk>
8 ;;; ... What it buys you: very little actually, but the nice things are
10 ;;; (i) Pressing line feed indents the next line according to the
12 ;;; (ii) Pressing Meta-; gives you a comment on the current line,
13 ;;; (iii) For literate scripts, pressing line feed gives you a bird
14 ;;; track on the next line if there was one on the previous
15 ;;; line, and does the indentation
16 ;;; (iv) For literate scripts, pressing Meta-Tab toggles a bird track
17 ;;; on or off at the beginning of the current line,
18 ;;; (v) There's a function for toggling bird tracks on all lines in a
20 ;;; (vi) Emacs says "Haskell" or "Literate Haskell" in the mode line :-)
22 ;;; You'll have to make the necessary changes in .emacs to load in the
23 ;;; library automatically (you probably know what to do). ...
25 (defvar haskell-mode-map ()
26 "Keymap used in Haskell mode.")
28 (defvar haskell-literate-mode-map ()
29 "Keymap used in Haskell literate script mode.")
31 (defvar haskell-mode-syntax-table ()
32 "Syntax table for haskell mode.")
36 (setq haskell-mode-map (make-sparse-keymap))
37 (define-key haskell-mode-map "\C-j" 'haskell-newline-and-indent))
39 (if haskell-literate-mode-map
41 (setq haskell-literate-mode-map (make-sparse-keymap))
42 (define-key haskell-literate-mode-map "\C-j" 'haskell-literate-newline-and-indent)
43 (define-key haskell-literate-mode-map "\M-\C-i" 'haskell-literate-toggle-bird-track-line))
45 (if haskell-mode-syntax-table
48 (setq haskell-mode-syntax-table (make-syntax-table))
50 (modify-syntax-entry i "." haskell-mode-syntax-table)
53 (modify-syntax-entry i "_" haskell-mode-syntax-table)
56 (modify-syntax-entry i "." haskell-mode-syntax-table)
59 (modify-syntax-entry i "w" haskell-mode-syntax-table)
62 (modify-syntax-entry i "." haskell-mode-syntax-table)
65 (modify-syntax-entry i "w" haskell-mode-syntax-table)
68 (modify-syntax-entry i "." haskell-mode-syntax-table)
70 (modify-syntax-entry ? " " haskell-mode-syntax-table)
71 (modify-syntax-entry ?\t " " haskell-mode-syntax-table)
72 (modify-syntax-entry ?\n ">" haskell-mode-syntax-table)
73 (modify-syntax-entry ?\f ">" haskell-mode-syntax-table)
74 (modify-syntax-entry ?\" "\"" haskell-mode-syntax-table)
75 (modify-syntax-entry ?\' "w" haskell-mode-syntax-table)
76 (modify-syntax-entry ?_ "w" haskell-mode-syntax-table)
77 (modify-syntax-entry ?\\ "." haskell-mode-syntax-table)
78 (modify-syntax-entry ?\( "()" haskell-mode-syntax-table)
79 (modify-syntax-entry ?\) ")(" haskell-mode-syntax-table)
80 (modify-syntax-entry ?\[ "(]" haskell-mode-syntax-table)
81 (modify-syntax-entry ?\] ")[" haskell-mode-syntax-table)
82 (modify-syntax-entry ?{ "(}1" haskell-mode-syntax-table)
83 (modify-syntax-entry ?} "){4" haskell-mode-syntax-table)
84 (modify-syntax-entry ?- "_ 123" haskell-mode-syntax-table)
87 (defun haskell-vars ()
88 (kill-all-local-variables)
89 (make-local-variable 'paragraph-start)
90 (setq paragraph-start (concat "^$\\|" page-delimiter))
91 (make-local-variable 'paragraph-separate)
92 (setq paragraph-separate paragraph-start)
93 (make-local-variable 'comment-start)
94 (setq comment-start "--")
95 (make-local-variable 'comment-start-skip)
96 (setq comment-start-skip "--[^a-zA-Z0-9]*")
97 (make-local-variable 'comment-column)
98 (setq comment-column 40)
99 (make-local-variable 'comment-indent-hook)
100 (setq comment-indent-hook 'haskell-comment-indent))
102 (defun haskell-mode ()
103 "Major mode for editing Haskell programs.
104 Blank lines separate paragraphs, Comments start with '--'.
105 Use Linefeed to do a newline and indent to the level of the previous line.
106 Tab simply inserts a TAB character.
107 Entry to this mode calls the value of haskell-mode-hook if non-nil."
110 (setq major-mode 'haskell-mode)
111 (setq mode-name "Haskell")
112 (use-local-map haskell-mode-map)
113 (set-syntax-table haskell-mode-syntax-table)
114 (run-hooks 'haskell-mode-hook))
116 (defun haskell-literate-mode ()
117 "Major mode for editing haskell programs in literate script form.
118 Linefeed produces a newline, indented maybe with a bird track on it.
119 M-TAB toggles the state of the bird track on the current-line.
120 Entry to this mode calls haskell-mode-hook and haskell-literate-mode-hook."
123 (setq major-mode 'haskell-literate-mode)
124 (setq mode-name "Literate Haskell")
125 (use-local-map haskell-literate-mode-map)
126 (set-syntax-table haskell-mode-syntax-table)
127 (run-hooks 'haskell-mode-hook)
128 (run-hooks 'haskell-literate-mode-hook))
130 ;; Find the indentation level for a comment..
131 (defun haskell-comment-indent ()
132 (skip-chars-backward " \t")
133 ;; if the line is blank, put the comment at the beginning,
134 ;; else at comment-column
135 (if (bolp) 0 (max (1+ (current-column)) comment-column)))
137 ;; Newline, and indent according to the previous line's indentation.
138 ;; Don't forget to use 'indent-tabs-mode' if you require tabs to be used
140 (defun haskell-newline-and-indent ()
146 (back-to-indentation)
147 (setq c (if (eolp) 0 (current-column))))
148 (indent-to c))) ;ident new line to this level
150 ;;; Functions for literate scripts
152 ;; Newline and maybe add a bird track, indent
153 (defun haskell-literate-newline-and-indent ()
156 (let ((bird-track nil) (indent-column 0))
159 (if (= (following-char) ?>) (setq bird-track t))
160 (skip-chars-forward "^ \t")
161 (skip-chars-forward " \t")
162 (setq indent-column (if (eolp) 0 (current-column))))
163 (if bird-track (insert-char ?> 1))
164 (indent-to indent-column)))
166 ;; Toggle bird-track ][
167 (defun haskell-literate-toggle-bird-track-line ()
171 (if (= (following-char) ? )
172 (progn (delete-char 1) (insert-char ?> 1))
173 (if (= (following-char) ?>)
174 (progn (delete-char 1) (insert-char ? 1))
175 (progn (insert-char ?> 1) (insert-char ? 1))))))
177 (defun haskell-literate-toggle-bird-track-region (start end)
181 (while (<= (point) end)
183 (haskell-literate-toggle-bird-track-line)