6adc7441eda9175b2cdea6d32b4c1e33066d7f04
[ghc-hetmet.git] / ghc / CONTRIB / haskell-modes / simonm / real / haskell.el
1 ;;; Haskell mode for emacs (c) Simon Marlow 11/1/92
2
3 (defvar haskell-mode-map ()
4   "Keymap used in Haskell mode.")
5
6 (defvar haskell-literate-mode-map ()
7   "Keymap used in Haskell literate script mode.")
8
9 (defvar haskell-mode-syntax-table ()
10   "Syntax table for haskell mode.")
11
12 (if haskell-mode-map
13     ()
14   (setq haskell-mode-map (make-sparse-keymap))
15   (define-key haskell-mode-map "\C-j" 'haskell-newline-and-indent))
16
17 (if haskell-literate-mode-map
18     ()
19   (setq haskell-literate-mode-map (make-sparse-keymap))
20   (define-key haskell-literate-mode-map "\C-j" 
21     'haskell-literate-newline-and-indent)
22   (define-key haskell-literate-mode-map "\M-\C-i" 
23     'haskell-literate-toggle-bird-track-line)
24   (define-key haskell-literate-mode-map "\M-m" 
25     'haskell-literate-back-to-indentation))
26
27
28 (if haskell-mode-syntax-table
29     ()
30   (let ((i 0))
31     (setq haskell-mode-syntax-table (make-syntax-table))
32 ;    (while (< i ?0)
33 ;      (modify-syntax-entry i "." haskell-mode-syntax-table)
34 ;      (setq i (1+ i)))
35 ;    (while (< i (1+ ?9))
36 ;      (modify-syntax-entry i "_" haskell-mode-syntax-table)
37 ;      (setq i (1+ i)))
38 ;    (while (< i ?A)
39 ;      (modify-syntax-entry i "." haskell-mode-syntax-table)
40 ;      (setq i (1+ i)))
41 ;    (while (< i (1+ ?Z))
42 ;      (modify-syntax-entry i "w" haskell-mode-syntax-table)
43 ;      (setq i (1+ i)))
44 ;    (while (< i ?a)
45 ;      (modify-syntax-entry i "." haskell-mode-syntax-table)
46 ;      (setq i (1+ i)))
47 ;    (while (< i (1+ ?z))
48 ;      (modify-syntax-entry i "w" haskell-mode-syntax-table)
49 ;      (setq i (1+ i)))
50 ;    (while (< i 128)
51 ;      (modify-syntax-entry i "." haskell-mode-syntax-table)
52 ;      (setq i (1+ i)))
53     (modify-syntax-entry ?   " " haskell-mode-syntax-table)
54     (modify-syntax-entry ?\t " " haskell-mode-syntax-table)
55     (modify-syntax-entry ?\f "> b"    haskell-mode-syntax-table)
56     (modify-syntax-entry ?\n "> b"    haskell-mode-syntax-table)
57     (modify-syntax-entry ?\" "\"" haskell-mode-syntax-table)
58     (modify-syntax-entry ?\' "w" haskell-mode-syntax-table)
59     (modify-syntax-entry ?_  "w" haskell-mode-syntax-table)
60     (modify-syntax-entry ?\\ "." haskell-mode-syntax-table)
61     (modify-syntax-entry ?\( "()" haskell-mode-syntax-table)
62     (modify-syntax-entry ?\) ")(" haskell-mode-syntax-table)
63     (modify-syntax-entry ?\[ "(]" haskell-mode-syntax-table)
64     (modify-syntax-entry ?\] ")[" haskell-mode-syntax-table)
65     (modify-syntax-entry ?{  "(}1" haskell-mode-syntax-table)
66     (modify-syntax-entry ?}  "){4" haskell-mode-syntax-table)
67     (modify-syntax-entry ?-  ". 12b" haskell-mode-syntax-table)
68     ))
69
70 (defun haskell-vars ()
71   (kill-all-local-variables)
72   (make-local-variable 'paragraph-start)
73   (setq paragraph-start (concat "^$\\|" page-delimiter))
74   (make-local-variable 'paragraph-separate)
75   (setq paragraph-separate paragraph-start)
76   (make-local-variable 'comment-start)
77   (setq comment-start "--")
78   (make-local-variable 'comment-start-skip)
79   (setq comment-start-skip "--[^a-zA-Z0-9]*")
80   (make-local-variable 'comment-column)
81   (setq comment-column 40)
82   (make-local-variable 'comment-indent-function)
83   (setq comment-indent-function 'haskell-comment-indent)
84   )
85
86 (defun haskell-mode ()
87   "Major mode for editing Haskell programs.
88 Blank lines separate paragraphs, Comments start with '--'. 
89 Use Linefeed to do a newline and indent to the level of the previous line.
90 Tab simply inserts a TAB character.
91 Entry to this mode calls the value of haskell-mode-hook if non-nil."
92   (interactive)
93   (haskell-vars)
94   (setq major-mode 'haskell-mode)
95   (setq mode-name "Haskell")
96   (use-local-map haskell-mode-map)
97   (set-syntax-table haskell-mode-syntax-table)
98   (run-hooks 'haskell-mode-hook))
99
100 (defun haskell-literate-mode ()
101   "Major mode for editing haskell programs in literate script form.
102 Linefeed produces a newline, indented maybe with a bird track on it.
103 M-TAB toggles the state of the bird track on the current-line.
104 Entry to this mode calls haskell-mode-hook and haskell-literate-mode-hook."
105   (interactive)
106   (haskell-vars)
107   (make-local-variable 'font-lock-keywords)
108   (setq font-lock-keywords haskell-literate-font-lock-keywords)
109   (setq major-mode 'haskell-literate-mode)
110   (setq mode-name "Literate Haskell")
111   (use-local-map haskell-literate-mode-map)
112   (set-syntax-table haskell-mode-syntax-table)
113   (run-hooks 'haskell-mode-hook)
114   (run-hooks 'haskell-literate-mode-hook))
115
116 ;; Find the indentation level for a comment..
117 (defun haskell-comment-indent ()
118   (skip-chars-backward " \t")
119   ;; if the line is blank, put the comment at the beginning,
120   ;; else at comment-column
121   (if (bolp) 0 (max (1+ (current-column)) comment-column)))
122
123 ;; Newline, and indent according to the previous line's indentation.
124 ;; Don't forget to use 'indent-tabs-mode' if you require tabs to be used
125 ;; for indentation.
126 (defun haskell-newline-and-indent ()
127   (interactive)
128   (newline)
129   (let ((c 0))
130     (save-excursion
131       (forward-line -1)
132       (back-to-indentation)
133       (setq c (if (eolp) 0 (current-column))))
134     (indent-to c)))                     ;ident new line to this level
135
136 ;;; Functions for literate scripts
137
138 ;; Newline and maybe add a bird track, indent
139 (defun haskell-literate-newline-and-indent ()
140   (interactive)
141   (newline)
142   (let ((bird-track nil) (indent-column 0))
143     (save-excursion
144       (forward-line -1)
145       (if (= (following-char) ?>) (setq bird-track t))
146       (skip-chars-forward "^ \t")
147       (skip-chars-forward " \t")
148       (setq indent-column (if (eolp) 0 (current-column))))
149     (if bird-track (insert-char ?> 1))
150     (indent-to indent-column)))
151
152 ;; Toggle bird-track ][ 
153 (defun haskell-literate-toggle-bird-track-line ()
154   (interactive)
155   (save-excursion
156     (beginning-of-line)
157     (if (= (following-char) ? )
158         (progn (delete-char 1) (insert-char ?> 1))
159       (if (= (following-char) ?>)
160           (progn (delete-char 1) (insert-char ?  1))
161         (progn (insert-char ?> 1) (insert-char ?  1))))))
162
163 (defun haskell-literate-toggle-bird-track-region (start end)
164   (interactive "r") 
165   (save-excursion 
166     (goto-char start) 
167     (while (<= (point) end) 
168       (beginning-of-line)
169       (haskell-literate-toggle-bird-track-line)
170       (forward-line 1))))
171
172 (defun haskell-literate-back-to-indentation ()
173   (interactive)
174   (beginning-of-line)
175   (if (= (following-char) ?>) 
176       (forward-char 1))
177   (skip-chars-forward " \t"))
178
179
180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181 ;;;
182 ;;; keywords for jwz's font-look-mode (lemacs 19)
183 ;;;
184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
185
186 (defvar haskell-literate-font-lock-keywords ()
187   "Font definitions for Literate Haskell files.")
188
189 (setq haskell-literate-font-lock-keywords
190       (list
191        '("^[^>\n].*$" . font-lock-comment-face)
192        (concat "\\b\\("
193                (mapconcat 'identity 
194                           '("case" "class" "data" "default" "deriving" "else" 
195                             "hiding" "if" "import" "in" "infix" "infixl" 
196                             "infixr" "instance" "interface" "let" "module" 
197                             "of" "renaming" "then" "to" "type" "where")
198                           "\\|")
199                "\\)\\b")
200 ;       '("(\\|)\\|\\[\\|\\]\\|,\\|[\\\\!$#^%&*@~?=-+<>.:]+" . font-lock-function-name-face)
201        ))
202