[project @ 1996-01-11 14:06:51 by partain]
[ghc-hetmet.git] / ghc / CONTRIB / haskell-modes / chalmers / sof / haskell-mode.el
diff --git a/ghc/CONTRIB/haskell-modes/chalmers/sof/haskell-mode.el b/ghc/CONTRIB/haskell-modes/chalmers/sof/haskell-mode.el
new file mode 100644 (file)
index 0000000..25a4324
--- /dev/null
@@ -0,0 +1,825 @@
+;; haskell-mode.el. Major mode for editing Haskell.
+;; Copyright (C) 1989, Free Software Foundation, Inc., Lars Bo Nielsen
+;; and Lennart Augustsson
+;; modified by Peter Thiemann, March 1994
+
+;; This file is not officially part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Haskell Mode. A major mode for editing and running Haskell. (Version 0.0)
+;; =================================================================
+;;
+;; This is a mode for editing and running Haskell.
+;; It is very much based on the sml mode for GNU Emacs. It
+;; features:
+;;
+;;      - Inferior shell running Haskell. No need to leave emacs, just
+;;        keep right on editing while Haskell runs in another window.
+;;
+;;      - Automatic "load file" in inferior shell. Send regions of code
+;;        to the Haskell program.
+;;
+;;
+;; 1. HOW TO USE THE Haskell-MODE
+;; ==========================
+;;
+;; Here is a short introduction to the mode.
+;;
+;; 1.1 GETTING STARTED
+;; -------------------
+;;
+;; If you are an experienced user of Emacs, just skip this section.
+;;
+;; To use the haskell-mode, insert this in your "~/.emacs" file (Or ask your
+;; emacs-administrator to help you.):
+;;
+;;    (setq auto-mode-alist (cons '("\\.hs$" . haskell-mode) (cons '("\\.lhs$" . haskell-mode)
+;;                           auto-mode-alist)))
+;;    (autoload 'haskell-mode "haskell-mode" "Major mode for editing Haskell." t)
+;;
+;; Now every time a file with the extension `.hs' or `.lhs' is found, it is
+;; automatically started up in haskell-mode.
+;;
+;; You will also have to specify the path to this file, so you will have
+;; to add this as well:
+;;
+;;    (setq load-path (cons "/usr/me/emacs" load-path))
+;;
+;; where "/usr/me/emacs" is the directory where this file is.
+;;
+;; You may also want to compile the this file (M-x byte-compile-file)
+;; for speed.
+;;
+;; You are now ready to start using haskell-mode. If you have tried other
+;; language modes (like lisp-mode or C-mode), you should have no
+;; problems. There are only a few extra functions in this mode.
+;;
+;; 1.2. EDITING COMMANDS.
+;; ----------------------
+;;
+;; The following editing and inferior-shell commands can ONLY be issued
+;; from within a buffer in haskell-mode.
+;;
+;; LFD (haskell-newline-and-indent).  
+;;     This is probably the function you will be using the most (press
+;;     CTRL while you press Return, press C-j or press Newline). It
+;;     makes a new line and performs indentation based on the last 
+;;     preceding non-comment line.
+;;
+;; M-; (indent-for-comment).
+;;     Like in other language modes, this command will give you a comment
+;;     at the of the current line. The column where the comment starts is
+;;     determined by the variable comment-column (default: 40).
+;;    
+;; C-c C-v (haskell-mode-version). 
+;;     Get the version of the haskell-mode.
+;;
+;;
+;; 1.3. COMMANDS RELATED TO THE INFERIOR SHELL
+;; -------------------------------------------
+;;
+;; C-c C-s (haskell-pop-to-shell).
+;;     This command starts up an inferior shell running haskell. If the shell
+;;     is running, it will just pop up the shell window.
+;;
+;; C-c C-u (haskell-save-buffer-use-file).
+;;     This command will save the current buffer and send a "load file",
+;;     where file is the file visited by the current buffer, to the
+;;     inferior shell running haskell.
+;;
+;; C-c C-f (haskell-run-on-file).
+;;     Will send a "load file" to the inferior shell running haskell,
+;;     prompting you for the file name.
+;;    
+;; C-c C-r (haskell-send-region). 
+;;     Will send region, from point to mark, to the inferior shell
+;;     running haskell.
+;;
+;; C-c C-b (haskell-send-buffer). 
+;;     Will send whole buffer to inferior shell running haskell.
+;;
+;; 2. INDENTATION
+;; ================
+;; 
+;; The first indentation command (using C-j or TAB) on a given line
+;; indents like the last preceding non-comment line. The next TAB
+;; indents to the indentation of the innermost enclosing scope. Further
+;; TABs get you to further enclosing scopes. After indentation has
+;; reached the first column, the process restarts using the indentation
+;; of the preceding non-comment line, again.
+;;
+;; 3. INFERIOR SHELL.
+;; ==================
+;;
+;; The mode for Standard ML also contains a mode for an inferior shell
+;; running haskell. The mode is the same as the shell-mode, with just one
+;; extra command.
+;;
+;; 3.1. INFERIOR SHELL COMMANDS
+;; ----------------------------
+;;
+;; C-c C-f (haskell-run-on-file).  Send a `load file' to the process running
+;; haskell.
+;;
+;; 3.2. CONSTANTS CONTROLLING THE INFERIOR SHELL MODE
+;; --------------------------------------------------
+;;
+;; Because haskell is called differently on various machines, and the
+;; haskell-systems have their own command for reading in a file, a set of
+;; constants controls the behavior of the inferior shell running haskell (to
+;; change these constants: See CUSTOMIZING YOUR Haskell-MODE below).
+;;
+;; haskell-prog-name (default "hbi").
+;;     This constant is a string, containing the command to invoke
+;;     Standard ML on your system. 
+;;
+;; haskell-use-right-delim (default "\"")
+;; haskell-use-left-delim  (default "\"")
+;;     The left and right delimiter used by your version of haskell, for
+;;     `use file-name'.
+;;
+;; haskell-process-name (default "Haskell"). 
+;;     The name of the process running haskell. (This will be the name
+;;     appearing on the mode line of the buffer)
+;;
+;; NOTE: The haskell-mode functions: haskell-send-buffer, haskell-send-function and
+;; haskell-send-region, creates temporary files (I could not figure out how
+;; to send large amounts of data to a process). These files will be
+;; removed when you leave emacs.
+;;
+;; 4. FONTIFICATION
+;;
+;; There is support for Jamie Zawinski's font-lock-mode through the
+;; variable "haskell-font-lock-keywords".
+;;
+;; 5. CUSTOMIZING YOUR Haskell-MODE
+;; ============================
+;;
+;; If you have to change some of the constants, you will have to add a
+;; `hook' to the haskell-mode. Insert this in your "~/.emacs" file.
+;;
+;;    (setq haskell-mode-hook 'my-haskell-constants)
+;;
+;; Your function "my-haskell-constants" will then be executed every time
+;; "haskell-mode" is invoked.  Now you only have to write the emacs-lisp
+;; function "my-haskell-constants", and put it in your "~/.emacs" file.
+;;
+;; Say you are running a version of haskell that uses the syntax `load
+;; ["file"]', is invoked by the command "OurHaskell" and you don't want the
+;; indentation algorithm to indent according to open parenthesis, your
+;; function should look like this:
+;;
+;;    (defun my-haskell-constants ()
+;;       (setq haskell-prog-name "OurHaskell")
+;;       (setq haskell-use-left-delim "[\"")
+;;       (setq haskell-use-right-delim "\"]")
+;;       (setq haskell-paren-lookback nil))
+;;
+;; The haskell-shell also runs a `hook' (haskell-shell-hook) when it is invoked.
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;
+;; ORIGINAL AUTHOR
+;;         Lars Bo Nielsen
+;;         Aalborg University
+;;         Computer Science Dept.
+;;         9000 Aalborg
+;;         Denmark
+;;
+;;         lbn@iesd.dk
+;;         or: ...!mcvax!diku!iesd!lbn
+;;         or: mcvax!diku!iesd!lbn@uunet.uu.net
+;;
+;; MODIFIED FOR Haskell BY
+;;        Lennart Augustsson
+;;        indentation stuff by Peter Thiemann
+;;
+;;
+;; Please let me know if you come up with any ideas, bugs, or fixes.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst haskell-mode-version-string
+  "HASKELL-MODE, Version 0.2, PJT indentation")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; CONSTANTS CONTROLLING THE MODE.
+;;;
+;;; These are the constants you might want to change
+;;; 
+
+;; The command used to start up the haskell-program.
+(defconst haskell-prog-name "hbi" "*Name of program to run as haskell.")
+
+;; The left delimmitter for `load file'
+(defconst haskell-use-left-delim "\""
+  "*The left delimiter for the filename when using \"load\".")
+
+;; The right delimmitter for `load file'
+(defconst haskell-use-right-delim "\""
+  "*The right delimiter for the filename when using \"load\".")
+
+;; A regular expression matching the prompt pattern in the inferior
+;; shell
+(defconst haskell-shell-prompt-pattern "^> *"
+  "*The prompt pattern for the inferion shell running haskell.")
+
+;; The template used for temporary files, created when a region is
+;; send to the inferior process running haskell.
+(defconst haskell-tmp-template "/tmp/haskell.tmp."
+  "*Template for the temporary file, created by haskell-simulate-send-region.")
+
+;; The name of the process running haskell (This will also be the name of
+;; the buffer).
+(defconst haskell-process-name "Haskell" "*The name of the Haskell-process")
+
+;;;
+;;; END OF CONSTANTS CONTROLLING THE MODE.
+;;;
+;;; If you change anything below, you are on your own.
+;;; 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defvar haskell-mode-syntax-table nil "The syntax table used in haskell-mode.")
+
+(defvar haskell-mode-map nil "The mode map used in haskell-mode.")
+
+(defvar haskell-mode-abbrev-table nil "The abbrev-table used in haskell-mode.")
+
+(defvar haskell-old-kill-emacs-hook nil "Old value of kill-emacs-hook")
+
+(defun haskell-mode ()
+  "Major mode for editing Haskell code.
+Tab indents for Haskell code.
+Comments are delimited with --
+Paragraphs are separated by blank lines only.
+Delete converts tabs to spaces as it moves back.
+
+Key bindings:
+=============
+
+\\[haskell-pop-to-shell]\t  Pop to the haskell window.
+\\[haskell-save-buffer-use-file]\t  Save the buffer, and send a \"load file\".
+\\[haskell-send-region]\t  Send region (point and mark) to haskell.
+\\[haskell-run-on-file]\t  Send a \"load file\" to haskell.
+\\[haskell-send-buffer]\t  Send whole buffer to haskell.
+\\[haskell-mode-version]\t  Get the version of haskell-mode.
+\\[haskell-evaluate-expression]\t  Prompt for an expression and evalute it.
+
+
+Mode map
+========
+\\{haskell-mode-map}
+Runs haskell-mode-hook if non nil."
+  (interactive)
+  (kill-all-local-variables)
+  (if haskell-mode-map
+      ()
+    (setq haskell-mode-map (make-sparse-keymap))
+    (define-key haskell-mode-map "\C-c\C-v" 'haskell-mode-version)
+    (define-key haskell-mode-map "\C-c\C-u" 'haskell-save-buffer-use-file)
+    (define-key haskell-mode-map "\C-c\C-s" 'haskell-pop-to-shell)
+    (define-key haskell-mode-map "\C-c\C-r" 'haskell-send-region)
+    (define-key haskell-mode-map "\C-c\C-m" 'haskell-region)
+    (define-key haskell-mode-map "\C-c\C-f" 'haskell-run-on-file)
+    (define-key haskell-mode-map "\C-c\C-b" 'haskell-send-buffer)
+    (define-key haskell-mode-map "\C-c\C-l" 'comment-line)
+    (define-key haskell-mode-map "\C-ce"    'haskell-evaluate-expression)
+;    (define-key haskell-mode-map "\C-j"     'haskell-newline-and-indent)
+    (define-key haskell-mode-map [S-tab]    'tab-to-tab-stop)
+    (define-key haskell-mode-map "\177"     'backward-delete-char-untabify))
+  (use-local-map haskell-mode-map)
+  (setq major-mode 'haskell-mode)
+  (setq mode-name "Haskell")
+  (define-abbrev-table 'haskell-mode-abbrev-table ())
+  (setq local-abbrev-table haskell-mode-abbrev-table)
+  (if haskell-mode-syntax-table
+      ()
+    (setq haskell-mode-syntax-table (make-syntax-table))
+    (modify-syntax-entry ?{  "(}1"    haskell-mode-syntax-table)
+    (modify-syntax-entry ?}  "){4"    haskell-mode-syntax-table)
+; partain: out
+;    (modify-syntax-entry ?-  "_ 2356" haskell-mode-syntax-table)
+;    (modify-syntax-entry ?\f "> b"    haskell-mode-syntax-table)
+;    (modify-syntax-entry ?\n "> b"    haskell-mode-syntax-table)
+; partain: end out
+; partain: in
+    (modify-syntax-entry ?-  "_ 23" haskell-mode-syntax-table)
+;    (modify-syntax-entry ?\f "> b"    haskell-mode-syntax-table)
+;    (modify-syntax-entry ?\n "> b"    haskell-mode-syntax-table)
+; partain: end in
+    (modify-syntax-entry ?\\ "\\"     haskell-mode-syntax-table)
+    (modify-syntax-entry ?*  "_"      haskell-mode-syntax-table)
+    (modify-syntax-entry ?_  "_"      haskell-mode-syntax-table)
+    (modify-syntax-entry ?'  "_"      haskell-mode-syntax-table)
+    (modify-syntax-entry ?:  "_"      haskell-mode-syntax-table)
+    (modify-syntax-entry ?|  "."      haskell-mode-syntax-table)
+    )
+  (set-syntax-table haskell-mode-syntax-table)
+  (make-local-variable 'require-final-newline) ; Always put a new-line
+  (setq require-final-newline t)       ; in the end of file
+;  (make-local-variable 'change-major-mode-hook)
+;  (setq change-major-mode-hook nil)
+;  (make-local-variable 'indent-line-function)
+;  (setq indent-line-function 'haskell-indent-line)
+  (make-local-variable 'comment-start)
+  (setq comment-start "-- ")
+;  (setq comment-start "{- ")
+  (make-local-variable 'comment-end)
+  (setq comment-end "")
+;  (setq comment-end " -}")
+  (make-local-variable 'comment-column)
+  (setq comment-column 60)             ; Start of comment in this column
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "{-+ *\\|--+ *") ; This matches a start of comment
+  (make-local-variable 'comment-multi-line)
+  (setq comment-multi-line nil)
+;  (make-local-variable 'comment-indent-function)
+;  (setq comment-indent-function 'haskell-comment-indent)
+  ;;
+  ;; Adding these will fool the matching of parens. I really don't
+  ;; know why. It would be nice to have comments treated as
+  ;; white-space
+  ;; 
+  ;; (make-local-variable 'parse-sexp-ignore-comments)
+  ;; (setq parse-sexp-ignore-comments t)
+  ;; 
+  (run-hooks 'haskell-mode-hook))              ; Run the hook
+
+(defun haskell-mode-version ()
+  (interactive)
+  (message haskell-mode-version-string))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; INDENTATION
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; some variables for later use
+
+(defvar haskell-open-comment "{-")
+(defvar haskell-close-comment "-}")
+(defvar haskell-indentation-counter 0
+  "count repeated invocations of indent-for-tab-command")
+(defvar haskell-literate-flag nil
+  "used to guide literate/illiterate behavior, set automagically")
+
+(defun haskell-newline-and-indent ()
+  (interactive)
+  (setq haskell-literate-flag
+       (save-excursion
+         (beginning-of-line)
+         (= (following-char) ?>)))
+  (newline)
+  (if haskell-literate-flag (insert ">"))
+  (haskell-indent-line))
+
+(defun haskell-indent-line ()
+  "Indent current line of ordinary or literate Haskell code."
+  (interactive)
+  (let ((indent (haskell-calculate-indentation-pjt-2)))
+    (if (/= (current-indentation) indent)
+       (let ((beg (progn
+                    (beginning-of-line)
+                    (if (= (following-char) ?>) (forward-char 1)) ;LITERATE
+                    (point))))
+         (skip-chars-forward "\t ")
+         (delete-region beg (point))
+         (indent-to indent))
+      ;; If point is before indentation, move point to indentation
+      (if (< (current-column) (current-indentation))
+         (skip-chars-forward "\t ")))))
+
+(defun haskell-calculate-indentation ()
+  (save-excursion
+    (let ((col (current-column)))
+      (while (and (not (bobp))                 ;skip over empty and comment-only lines
+                 (= col (current-column)))
+       (previous-line 1)
+       (beginning-of-line)                     ; Go to first non whitespace
+       (if (= (following-char) ?>)             ;LITERATE
+           (forward-char 1)
+         (if haskell-literate-flag             ;ignore illiterate lines
+             (end-of-line)))
+       (skip-chars-forward "\t ")              ; on the line.
+       (setq col (current-column))
+       (search-forward-regexp (concat haskell-open-comment "\\|--\\|\n") nil 0)
+       (goto-char (match-beginning 0)))
+      (search-backward-regexp "\\b\\(where\\|let\\|of\\|in\\)\\b\\|\n" nil 0)
+      (if (looking-at "\n")
+         ()
+       (setq col (current-column))
+       (forward-word 1)
+       (skip-chars-forward "\t ")
+       (if (looking-at "\\w")
+           (setq col (current-column))
+         (setq col (+ 2 col))))
+      col)))
+
+(defun haskell-calculate-indentation-pjt-2 ()
+  "Calculate indentation for Haskell program code, versatile version"
+  (save-excursion
+    (if (eq last-command 'haskell-indentation)
+       (setq haskell-indentation-counter (1+ haskell-indentation-counter))
+      (setq haskell-indentation-counter -1))
+    (setq this-command 'haskell-indentation)
+    (let* ((simple-indent (haskell-calculate-indentation))
+          (count haskell-indentation-counter)
+          (min-indent simple-indent)   ; minimum indentation found in a non-comment line
+          (last-indent simple-indent)  ; indentation of the following non-comment line
+          (return-indent nil)          ; computed indentation
+          (comment-depth 0))
+      (previous-line 1)
+      (if (< haskell-indentation-counter 0) ; 1st tab gives simple indentation
+         (setq return-indent simple-indent))
+      (while (not return-indent)
+       (if (search-backward-regexp "\\b\\(where\\|let\\|of\\)\\b\\|\n\\|{-\\|-}" nil t 1)
+           (cond
+            ((looking-at haskell-open-comment)
+             (setq comment-depth (1- comment-depth)))
+            ((looking-at haskell-close-comment)
+             (setq comment-depth (1+ comment-depth)))
+            ((= 0 comment-depth)
+             (cond
+              ((looking-at "\n")
+               (save-excursion
+                 (forward-char 1)
+                 (if (= (following-char) ?>)
+                     (forward-char 1)
+                   (if haskell-literate-flag
+                       (end-of-line))) ;LITERATE: ignore lines w/o >
+                 (skip-chars-forward "\t ")
+                 (if (looking-at (concat haskell-open-comment "\\|--\\|\n"))
+                     ()
+                   (setq last-indent (current-column))
+                   (if (< last-indent min-indent)
+                       (setq min-indent last-indent)))))
+              (t                       ; looking at a keyword
+               (save-excursion
+                 (forward-word 1)
+                 (skip-chars-forward " \t")
+                 (if (and haskell-literate-flag ;LITERATE: ignore lines w/o >
+                          (save-excursion
+                            (beginning-of-line)
+                            (/= (following-char) ?>)))
+                     (end-of-line))
+                 (if (looking-at (concat haskell-open-comment "\\|--\\|\n"))
+                     ()
+                   (setq last-indent (current-column)))
+                 (if (<= last-indent min-indent)
+                     (if (> count 0)
+                         (setq count (1- count))
+                       (setq return-indent last-indent)))
+                 (if (< last-indent min-indent)
+                     (setq min-indent last-indent)))))))
+         (setq return-indent simple-indent)
+         (setq haskell-indentation-counter -1)))
+      return-indent)))
+
+(defun haskell-skip-nested-comment ()
+  ;; point looks at opening {-, move over closing -}
+  ;; todo: specify what happens on failure, bounds check ...
+  (forward-char 2)
+  (let ((comment-depth 1))
+    (while (> comment-depth 0)
+      (search-forward-regexp "{-\\|-}")
+      (goto-char (match-beginning 0))
+      (setq comment-depth
+           (if (= (following-char) 123) ; code for opening brace
+               (1+ comment-depth)
+             (1- comment-depth)))
+      (goto-char (match-end 0)))))
+
+
+;;;seemingly obsolete functions
+(defun haskell-inside-of-inline-comment ()
+  (let ((bolp (save-excursion
+              (beginning-of-line)
+              (point))))
+    (search-backward comment-start bolp t 1)))
+
+(defun haskell-inside-of-nested-comment ()
+  (save-excursion
+    (let ((count 0))
+      (while
+         (search-backward-regexp "\\({-\\|-}\\)" 0 t 1)
+       (if (haskell-inside-of-inline-comment)
+           ()
+         (if (looking-at haskell-open-comment)
+             (setq count (1+ count))
+           (setq count (1- count)))))
+      (> count 0))))
+
+(defun haskell-inside-of-comment ()
+  (or (haskell-inside-of-inline-comment)
+      (haskell-inside-of-nested-comment)))
+
+;;;stolen from sml-mode.el
+(defun haskell-comment-indent ()
+  "Compute indentation for Haskell comments"
+  (if (looking-at "^--")
+      0
+    (save-excursion
+      (skip-chars-backward " \t")
+      (max (1+ (current-column))
+          comment-column))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; INFERIOR SHELL
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar haskell-shell-map nil "The mode map for haskell-shell.")
+
+(defun haskell-shell ()
+  "Inferior shell invoking Haskell.
+It is not possible to have more than one shell running Haskell.
+Like the shell mode with the additional command:
+
+\\[haskell-run-on-file]\t Runs haskell on the file.
+\\{haskell-shell-map}
+Variables controlling the mode:
+
+haskell-prog-name (default \"hbi\")
+    The string used to invoke the haskell program.
+
+haskell-use-right-delim (default \"\\\"\")
+haskell-use-left-delim  (default \"\\\"\")
+    The left and right delimiter used by your version of haskell, for
+    \"load file-name\".
+
+haskell-process-name (default \"Haskell\")
+    The name of the process running haskell.
+
+haskell-shell-prompt-pattern (default \"^> *\")
+    The prompt pattern.
+
+Runs haskell-shell-hook if not nil."
+  (interactive)
+  (if (not (process-status haskell-process-name))
+      (save-excursion                  ; Process is not running
+       (message "Starting Haskell...") ; start up a new process
+       (require 'shell)
+       (set-buffer (make-comint haskell-process-name haskell-prog-name))
+       (erase-buffer)                  ; Erase the buffer if a previous
+       (if haskell-shell-map           ; process died in there
+           ()
+         (setq haskell-shell-map (copy-keymap shell-mode-map))
+         (define-key haskell-shell-map "\C-c\C-f" 'haskell-run-on-file))
+       (use-local-map haskell-shell-map)
+       (make-local-variable 'shell-prompt-pattern)
+       (setq shell-prompt-pattern haskell-shell-prompt-pattern)
+       (setq major-mode 'haskell-shell)
+       (setq mode-name "Haskell Shell")
+       (setq mode-line-format 
+             "-----Emacs: %17b   %M   %[(%m: %s)%]----%3p--%-")
+       (set-process-filter (get-process haskell-process-name) 'haskell-process-filter)
+       (message "Starting Haskell...done.")
+       (run-hooks 'haskell-shell-hook))))
+
+(defun haskell-process-filter (proc str)
+  (let ((cur (current-buffer))
+       (pop-up-windows t))
+    (pop-to-buffer (concat "*" haskell-process-name "*"))
+    (goto-char (point-max))
+    (if (string= str "\b\b\b  \b\b\b")
+       (backward-delete-char 4)
+      (insert str))
+    (set-marker (process-mark proc) (point-max))
+    (pop-to-buffer cur)))
+
+(defun haskell-pop-to-shell ()
+  (interactive)
+  (haskell-shell)
+  (pop-to-buffer (concat "*" haskell-process-name "*")))
+
+(defun haskell-run-on-file (fil)
+  (interactive "FRun Haskell on : ")
+  (haskell-shell)
+  (save-some-buffers)
+  (process-send-string haskell-process-name
+              (concat "load " haskell-use-left-delim (expand-file-name fil)
+                      haskell-use-right-delim ";\n")))
+
+(defun haskell-save-buffer-use-file ()
+  "Save the buffer, and send a `use file' to the inferior shell
+running Haskell."
+  (interactive)
+  (let (file)
+    (if (setq file (buffer-file-name)) ; Is the buffer associated
+       (progn                          ; with file ?
+         (save-buffer)
+         (haskell-shell)
+         (process-send-string haskell-process-name
+                      (concat "load " haskell-use-left-delim
+                              (expand-file-name file)
+                              haskell-use-right-delim ";\n")))
+      (error "Buffer not associated with file."))))
+
+(defvar haskell-tmp-files-list nil
+  "List of all temporary files created by haskell-simulate-send-region.
+Each element in the list is a list with the format:
+
+      (\"tmp-filename\"  buffer  start-line)")
+
+(defvar haskell-simulate-send-region-called-p nil
+  "Has haskell-simulate-send-region been called previously.")
+
+(defun haskell-make-temp-name (pre)
+  (concat (make-temp-name pre) ".m"))
+
+(defun haskell-simulate-send-region (point1 point2)
+  "Simulate send region. As send-region only can handle what ever the
+system sets as the default, we have to make a temporary file.
+Updates the list of temporary files (haskell-tmp-files-list)."
+  (let ((file (expand-file-name (haskell-make-temp-name haskell-tmp-template))))
+    ;; Remove temporary files when we leave emacs
+    (if (not haskell-simulate-send-region-called-p)
+       (progn
+         (setq haskell-old-kill-emacs-hook kill-emacs-hook)
+         (setq kill-emacs-hook 'haskell-remove-tmp-files)
+         (setq haskell-simulate-send-region-called-p t)))
+    (save-excursion
+      (goto-char point1)
+      (setq haskell-tmp-files-list
+           (cons (list file
+                       (current-buffer)
+                       (save-excursion ; Calculate line no.
+                         (beginning-of-line)
+                         (1+ (count-lines 1 (point)))))
+                 haskell-tmp-files-list)))
+    (write-region point1 point2 file nil 'dummy)
+    (haskell-shell)
+    (message "Using temporary file: %s" file)
+    (process-send-string
+     haskell-process-name
+     ;; string to send: load file;
+     (concat "load " haskell-use-left-delim file haskell-use-right-delim ";\n"))))
+
+(defun haskell-remove-tmp-files ()
+  "Remove the temporary files, created by haskell-simulate-send-region, if
+they still exist. Only files recorded in haskell-tmp-files-list are removed."
+  (message "Removing temporary files created by haskell-mode...")
+  (while haskell-tmp-files-list
+    (condition-case ()
+       (delete-file (car (car haskell-tmp-files-list)))
+      (error ()))
+    (setq haskell-tmp-files-list (cdr haskell-tmp-files-list)))
+  (message "Removing temporary files created by haskell-mode...done.")
+  (run-hooks 'haskell-old-kill-emacs-hook))
+
+(defun haskell-send-region ()
+  "Send region."
+  (interactive)
+  (let (start end)
+    (save-excursion
+      (setq end (point))
+      (exchange-point-and-mark)
+      (setq start (point)))
+    (haskell-simulate-send-region start end)))
+
+(defun haskell-send-buffer ()
+  "Send the buffer."
+  (interactive)
+  (haskell-simulate-send-region (point-min) (point-max)))
+
+(defun haskell-evaluate-expression (h-expr)
+  "Prompt for and evaluate an expression"
+  (interactive "sExpression: ")
+  (let ((str (concat h-expr ";\n"))
+       (buf (current-buffer)))
+    (haskell-pop-to-shell)
+    (insert str)
+    (process-send-string haskell-process-name str)
+    (pop-to-buffer buf)))
+
+
+;;
+;; font-lock-mode patterns, based on specs. in an earlier version
+;; of haskell-mode.el
+;; (these patterns have only been tested with 19.30)
+
+(defconst haskell-font-lock-keywords nil
+ "Conservative highlighting of a Haskell buffer
+(using font-lock.)")
+
+(let ((haskell-id "[a-z_][a-zA-Z0-9_'#]+")
+      (haskell-reserved-ids
+          (concat "\\b\\(" 
+                   (mapconcat 
+                      'identity
+                      '("case"    "class"     "data"
+                        "default" "deriving"  "else"
+                        "hiding"  "if" "import"   "in"
+                        "instance" "interface" "let"
+                        "module" "of"   "renaming"
+                        "then"  "to" "type" "where" "infix[rl]?")
+                       "\\|")
+                  "\\)[ \t\n:,]"))
+       (haskell-basic-types 
+          (concat "\\b\\("
+                   (mapconcat 'identity
+                             '("Bool" "()" "String" "Char" "Int"
+                               "Integer" "Float" "Double" "Ratio"
+                               "Assoc" "Rational" "Array")
+                             "\\|")
+                  "\\)\\b"))
+       (haskell-prelude-classes
+          (concat "\\b\\("
+                   (mapconcat 'identity
+                             '("Eq" "Ord" "Text" "Num" "Real" "Fractional" 
+                                 "Integral"   "RealFrac" "Floating" "RealFloat"
+                                "Complex" "Ix" "Enum"
+                                ;; ghc-isms
+                                "_CCallable" "_CReturnable")
+                             "\\|")
+                  "\\)\\b"))
+       (haskell-reserved-ops 
+          (mapconcat 'identity
+                     '("\\.\\."  "::"
+                       "=>" "/=" "@"
+                       "<-" "->")
+                     "\\|"))
+       (glasgow-haskell-ops
+          (concat "\\b\\(" 
+                   (mapconcat 
+                     'identity
+                     '(">>"    ">>="  "thenPrimIO"
+                       "seqPrimIO" "returnPrimIO" 
+                       "return" "_ccall_" "_casm_"
+                       "thenST" "seqST" "returnST"
+                       "thenStrictlyST" "seqStrictlyST" "returnStrictlyST"
+                       "unsafeInterleavePrimIO" "unsafePerformIO")
+                     "\\|")
+                  "\\)\\b"))
+       (glasgow-haskell-types
+          (concat "\\b\\(" 
+                   (mapconcat 
+                     'identity
+                     '("IO"    "PrimIO"  "_?ST"
+                       "_Word" "_Addr"   "_?MVar"
+                       "_?IVar" "_RealWorld"
+                       "_?MutableByteArray"
+                       "_?ByteArray")
+                     "\\|")
+                  "\\)\\b")))
+      (setq haskell-font-lock-keywords
+       (list
+         '("--.*$" . font-lock-comment-face)
+        (list "[ \t\n]*\\([A-Za-z[(_][]A-Za-z0-9_$', ~@|:[)(#]*[ \t\n]*\\)=" 1 font-lock-function-name-face)
+        (list (concat "^>?[ \t\n]*\\(" haskell-id "\\)[ \t]*::") 1 'font-lock-function-name-face)
+         (list haskell-reserved-ids    0 'font-lock-function-name-face)
+         (list glasgow-haskell-ops     0 'font-lock-function-name-face)
+         (list glasgow-haskell-types   0 'font-lock-type-face)
+        (list haskell-basic-types     0 'font-lock-type-face)
+        (list haskell-prelude-classes 0 'font-lock-type-face)
+        (list "^[ \t\n]*\\([A-Za-z[(_][]A-Za-z0-9_$', @:[)(#]*[ \t\n]*\\)->" 1 font-lock-variable-name-face)
+        )))
+
+;;
+;; To enable font-lock-mode for Haskell buffers, add something
+;; like this to your ~/.emacs
+
+;(cond (window-system
+;  (require 'font-lock)
+;  (add-hook 'haskell-mode-hook
+;    '(lambda () (make-local-variable 'font-lock-defaults)
+;              (make-local-variable 'font-lock-mode-hook) ; don't affect other buffers      
+;              (setq font-lock-mode-hook nil)
+;              (add-hook 'font-lock-mode-hook 
+;                   '(lambda ()
+;                        (setq font-lock-keywords haskell-font-lock-keywords)))
+;              (font-lock-mode 1))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; END OF Haskell-MODE
+;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(provide 'haskell-mode)