summaryrefslogtreecommitdiff
path: root/ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el')
-rw-r--r--ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el1935
1 files changed, 0 insertions, 1935 deletions
diff --git a/ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el b/ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el
deleted file mode 100644
index b9a490ffd1..0000000000
--- a/ghc/CONTRIB/haskell-modes/glasgow/original/haskell-mode.el
+++ /dev/null
@@ -1,1935 +0,0 @@
-;; Haskell major mode
-;; (c) Copyright, Richard McPhee et al.
-;; University of Glasgow, February 1993
-
-
-
-;; if .hs is not recognised then put the extension in auto-mode-list
-
-(if (assoc "\\.hs" auto-mode-alist)
- nil
- (nconc auto-mode-alist '(("\\.hs". haskell-mode))))
-
-(if (assoc "\\.hi" auto-mode-alist)
- nil
- (nconc auto-mode-alist '(("\\.hi". haskell-mode))))
-
-(if (assoc "\\.gs" auto-mode-alist)
- nil
- (nconc auto-mode-alist '(("\\.gs". haskell-mode))))
-
-(defvar haskell-mode-syntax-table nil
- "Syntax table for haskell-mode buffers.")
-
-(defvar haskell-mode-abbrev-table nil
- "Abbrev table for haskell-mode buffers.")
-
-(defvar haskell-mode-map (make-sparse-keymap)
- "Keymap for haskell-mode-buffers.")
-
-
-
-;;; Here are the keymaps used in haskell-mode
-
-(define-key haskell-mode-map "\M-;" 'haskell-insert-comment)
-(define-key haskell-mode-map "\C-c=" 'haskell-insert-concat)
-(define-key haskell-mode-map "\C-c;" 'set-haskell-comment-column)
-(define-key haskell-mode-map "\C-c+" 'set-haskell-concat-column)
-(define-key haskell-mode-map "\C-cn" 'set-haskell-indent-offset)
-(define-key haskell-mode-map "\C-cl" 'set-haskell-list-offset)
-(define-key haskell-mode-map "\C-ci" 'set-haskell-if-offset)
-(define-key haskell-mode-map "\C-ce" 'set-haskell-let-offset)
-(define-key haskell-mode-map "\C-cc" 'set-haskell-case-offset)
-(define-key haskell-mode-map "\C-ct" 'set-haskell-then-offset)
-(define-key haskell-mode-map "\C-co" 'set-haskell-comp-offset)
-(define-key haskell-mode-map "\C-cw" 'set-haskell-where-offset)
-(define-key haskell-mode-map "\C-cg" 'goto-line)
-(define-key haskell-mode-map "\C-j" 'haskell-reindent-then-newline-and-indent)
-(define-key haskell-mode-map "\t" 'haskell-indent-line)
-(define-key haskell-mode-map "}" 'electric-haskell-brace)
-(define-key haskell-mode-map "]" 'electric-haskell-brace)
-(define-key haskell-mode-map ")" 'haskell-insert-round-paren)
-(define-key haskell-mode-map "\C-cr" 'haskell-indent-region)
-(define-key haskell-mode-map "\C-cf" 'haskell-further-indent)
-(define-key haskell-mode-map "\C-cb" 'haskell-lesser-indent)
-(define-key haskell-mode-map "\177" 'backward-delete-char-untabify)
-(define-key haskell-mode-map "\M-\C-\177" 'delete-horizontal-space)
-
-(defun haskell-set-local-vars ()
- "Set the local variables for haskell-mode."
- (kill-all-local-variables)
-
- (setq indent-line-function 'haskell-indent-line)
-
- (make-local-variable 'haskell-std-list-indent)
- ;;Non-nil means indent to the offset, 'haskell-list-offset' in a bracket rather than
- ;; moving to the next word afer a function name
- (setq haskell-std-list-indent t)
-
- (make-local-variable 'haskell-nest-ifs)
- ;;Non-nil means that 'if' statements are nested ie. lined up with `if' not `else'.
- (setq haskell-nest-ifs nil)
-
- (make-local-variable 'haskell-align-else-with-then)
- ;;Non-nil means align an `else' under it's corresponding `then'
- (setq haskell-align-else-with-then nil)
-
-
- ;;The local vars for 'where' indentation
-
- (make-local-variable 'haskell-align-where-with-eq)
- ;;Non-nil means align a 'where' under it's corresponding equals sign
- (setq haskell-align-where-with-eq t)
-
- (make-local-variable 'haskell-align-where-after-eq)
- ;;Non-nil means align a 'where' after it's corresponding equals sign
- (setq haskell-align-where-after-eq nil)
-
- (make-local-variable 'haskell-std-indent-where)
- ;;put the 'where' the standard offset ie. 'haskell-indent-offset'
- (setq haskell-std-indent-where nil)
-
-
- (make-local-variable 'haskell-always-fixup-comment-space)
- ;;Non-nil means always insert a (single) space after a comment, even
- ;; if there is more or less than one.
- (setq haskell-always-fixup-comment-space t)
-
-
- (make-local-variable 'haskell-indent-offset)
- ;;Extra indentation for a line continued after a keyword.
- (setq haskell-indent-offset 4)
-
- (make-local-variable 'haskell-list-offset)
- ;;Extra indentation for continuing a list.
- (setq haskell-list-offset 4)
-
- (make-local-variable 'haskell-comp-offset)
- ;;Extra indentation for a list comprehension.
- (setq haskell-comp-offset 4)
-
- (make-local-variable 'haskell-case-offset)
- (setq haskell-case-offset 4)
-
- (make-local-variable 'haskell-where-offset)
- (setq haskell-where-offset 4)
-
- (make-local-variable 'haskell-let-offset)
- (setq haskell-let-offset 4)
-
- (make-local-variable 'haskell-then-offset)
- (setq haskell-then-offset 0)
-
- (make-local-variable 'haskell-if-offset)
- (setq haskell-if-offset 4)
-
- (make-local-variable 'haskell-comment-column)
- (setq haskell-comment-column 35)
-
- (make-local-variable 'haskell-concat-column)
- (setq haskell-concat-column 69)
-
- (make-local-variable 'haskell-where-threshold)
- (setq haskell-where-threshold 35)
-
- (make-local-variable 'line-comment)
- (setq line-comment "-- ")
-
- (make-local-variable 'haskell-indent-style)
- (setq haskell-indent-style "none"))
-
-
-(defun haskell-set-syntax-table ()
- "Set the syntax table for Haskell-mode."
- (setq haskell-mode-syntax-table (make-syntax-table))
- (set-syntax-table haskell-mode-syntax-table)
- (modify-syntax-entry ?\" "\"")
- (modify-syntax-entry ?\\ "\\")
- (modify-syntax-entry ?\' "w")
- (modify-syntax-entry ?_ "w")
- (modify-syntax-entry ?# "_")
- (modify-syntax-entry ?$ "_")
- (modify-syntax-entry ?% "_")
- (modify-syntax-entry ?: "_")
- (modify-syntax-entry ?? "_")
- (modify-syntax-entry ?@ "_")
- (modify-syntax-entry ?! "_")
- (modify-syntax-entry ?^ "_")
- (modify-syntax-entry ?~ "_")
- (modify-syntax-entry ?- "_ 12")
- (modify-syntax-entry ?\n ">")
- (modify-syntax-entry ?{ "(}")
- (modify-syntax-entry ?} "){")
- (set-syntax-table haskell-mode-syntax-table))
-
-
-
-(defun haskell-mode ()
- "Major mode for editing Haskell code.
-Linefeed reindents current line, takes newline and indents.
-Tab indents current line for Haskell code.
-Functions are seperated by blank lines.
-Delete converts tabs to spaces as it moves back.
-\\{haskell-mode-map}
-Variables controlling indentation style:
- haskell-indent-offset
- Standard extra indentation for continuing Haskell
- code under the scope of an expression. The default is 4.
-
- haskell-list-offset
- Extra indentation for indenting in a list. Used if variable
- haskell-std-list-indent is non-nil. The default is 4.
-
- haskell-comp-offset
- Extra indentation for continuing a list comprehension.
- The default is 4.
-
- haskell-case-offset
- Standard extra indentation for continuing Haskell
- code under the scope of an expression. The default is 4.
-
- haskell-where-offset
- Standard extra indentation for continuing Haskell
- code under the scope of a `where'. The default is 4.
-
- haskell-let-offset
- Standard extra indentation for continuing Haskell
- code under the scope of a `let'. The default is 4.
-
- haskell-then-offset
- Standard extra indentation for a `then' beyond
- its corresponding `if'. The default is 0.
-
- haskell-if-offset
- Standard extra indentation for continuing Haskell
- code under the scope of an `if'. The default is 4.
-
- haskell-comment-column
- Column to which line comments `--' will be inserted.
- The default is 35.
-
- haskell-concat-column
- Column to which concatenation operator `++' will be inserted.
- The default is 69.
-
- haskell-where-threshold
- Column beyond which a `where' will be indented to the
- start of a line (to avoid spilling over lines).
- The default is 35.
-
- set-haskell-indent-offset (C-c i)
- Changes the default value of the local variable,
- haskell-indent-offset. May be a number from 0-10.
-
- set-haskell-list-indent (C-c l)
- Change the value of the local variable,
- haskell-list-offset. May be a number from 0-100.
-
- set-haskell-comment-column (C-x ;)
- Changes the value of the local variable,
- haskell-comment-column. May be any number from 0-100."
-
- (interactive)
- (haskell-set-local-vars)
- (haskell-set-syntax-table)
- (use-local-map haskell-mode-map)
- (setq major-mode 'haskell-mode)
- (setq mode-name "Haskell")
- (define-abbrev-table 'haskell-mode-abbrev-table ()))
-
-
-
-
-;;; Returns the indentation column for a comment on this line.
-;;; The point is positioned at the last char of any code on the line.
-
-(defun haskell-comment-indent ()
- "Returns the indentation for a comment on the given line.
-If the line has code on it or the point is not at the beginning of the line,
-then indent to indent-column.
-Otherwise, don't indent."
- (cond ((or (haskell-code-on-linep)
- (not (bolp)))
- ;;There is code before the haskell-comment-column
- ;; or not at the beginning of the line
- ;;Return the largest of
- ;; the current column +1 and the haskell-comment-column
- (max (1+ (current-column))
- haskell-comment-column))
- (t
- ;;Otherwise, return 0
- 0)))
-
-
-
-;;; Returns whether a comment is on the current line
-;;; Search from bol, and beware of "--", {-- etc!
-;;; DOES NOT RECOGNISE {- COMMENTS YET or -- within a string
-
-(defun haskell-comment-on-linep ()
- "Returns the truth value of whether there is a '--' comment on the current line."
- (save-excursion
- (beginning-of-line)
- (looking-at ".*--")))
-
-
-;;; This doesn't account for comments '{-'. Test explicitly if you use this function!
-
-(defun haskell-code-on-linep ()
- "Returns a truth value as to whether there is code on the current line."
- (save-excursion
- (beginning-of-line)
- (not
- ;; Code on line if not looking at a comment directly
- ;; and the line is not blank
- (or
- (looking-at "^[ \t]*--")
- (looking-at "^[ \t]*$")))))
-
-
-;;; Insert a Haskell "--" comment on the current line.
-;;; Move to the comment position if there's already a comment here.
-;;; Otherwise, the comment is inserted either at the comment column
-;;; or one column after the last non-space character, whichever is further
-;;; to the right.
-;;; This function is executed by M-;
-
-(defun haskell-insert-comment ()
- "Inserts a '--' comment on the given line."
- (interactive)
- (cond ((haskell-comment-on-linep)
- ;;There is a comment on the line
- ;;Just reindent existing comment
- (haskell-reindent-comment))
- (t
- (if (haskell-code-on-linep)
- ;;There is code on the line
- ;; and guarenteed that a comment
- ;; does not already exist.
- ;;Move to the last nonspace char
- ;; (there may be spaces after the last char)
- (progn
- (end-of-line)
- (skip-chars-backward " \t")))
- ;;Indent to required level
- ;; and insert the line comment '--'
- (indent-to (haskell-comment-indent))
- (insert line-comment))))
-
-
-;;; Reindents a comment.
-;;; The comment is indented according to the normal rules.
-;;; Skips over ---- and following spaces or tabs
-
-(defun haskell-reindent-comment ()
- "Indents a comment on a line to keep it at haskell-comment-column,
-if possible.
-It is guaranteed that a comment exists on the current line."
- (beginning-of-line)
- ;;Go back to beginning of comment
- (re-search-forward "--")
- (forward-char -2)
- ;;Delete all spaces and reindent to
- ;; the correct location.
- (delete-horizontal-space)
- (indent-to (haskell-comment-indent))
- ;;Move past the comment and insert
- ;; only one space between it and the text.
- ;;Leave point just after comment.
- (skip-chars-forward "- \t")
- (if haskell-always-fixup-comment-space
- (progn
- (fixup-whitespace)
- (forward-char 1))))
-
-
-
-;;; Inserts a haskell concatenation operator, `++', at the
-;;; column dictated by haskell-concat-column
-
-(defun haskell-insert-concat()
- "Inserts a `++' operator on the given line."
- (interactive)
- (end-of-line)
- (skip-chars-backward " \t")
- ;;Indent to required level
- ;; and insert the concat operator `++'
- (indent-to (haskell-concat-indent))
- (insert "++"))
-
-
-
-;;; Returns the indentation column for a concatenation operator on this line.
-;;; The point is positioned at the last char of any code on the line.
-
-(defun haskell-concat-indent ()
- "Returns the indentation for a concat operator on the given line."
- (max (1+ (current-column))
- haskell-concat-column))
-
-
-
-;;; Returns the indentation of the current line of haskell code.
-;;; A blank line has ZERO indentation
-
-(defun haskell-current-indentation ()
- "Returns the indentation for the current haskell line. A blank line has
-indentation zero."
- (save-excursion
- (beginning-of-line)
- (if (looking-at "^[ \t]*$")
- ;;The line is empty
- ;; so the indentation is zero
- 0
- ;;Otherwise find the normal value of indentation
- (current-indentation))))
-
-
-
-;;; Returns the indentation of the previous line of haskell code.
-;;; A blank line has ZERO indentation
-
-(defun haskell-previous-indentation ()
- "Returns the previous line's indentation as Haskell indentation."
- (save-excursion
- (if (not (bobp))
- ;;Not at the start of the buffer
- ;; so get the previous lines indentation
- (progn
- (forward-line -1)
- (haskell-current-indentation))
- ;;We are at the start of buffer
- ;;There is no previous line; Indent is zero
- 0)))
-
-
-
-;;; Move back to the last line which is aligned in the left column.
-;;; Ignores comments and blank lines.
-;;; The point is left at the beginning of the line.
-
-(defun haskell-back-to-zero-indent ()
- "Moves point to last line which has zero as indentation."
- ;;Not at the beginning of buffer.
- ;;Continue to go to the previous line until
- ;; we find a line whose indentation is non-zero.
- ;;Blank lines and lines containing only comments
- ;; are ignored.
- (beginning-of-line)
- (while (and
- (or (not (zerop (haskell-current-indentation)))
- (looking-at "^[ \t]*\\($\\|--\\)"))
- (not (bobp)))
- (haskell-backward-to-noncomment)
- (beginning-of-line)))
-
-
-
-;;; Find the last symbol, usually an equality.
-
-;;; Note: we check for "=" as a complete WORD (and ignore
-;;; comments) when searching for this. Ie. an `=' may be
-;;; surrounded only by a letter, digit, or whitespace .
-;;; Strings are not considered.
-;;; Don't go beyond the first character in the (possibly narrowed) buffer.
-;;; From the beginning of the line,
-;;; find the comment position (or end-of-line)
-;;; search forward to this position, looking for a "where"
-;;; If one's found, then search forward for "\b=\b"
-;;; If there's no equality sign then
-;;; search forward from the start of the line for an equals
-;;; Otherwise we found it.
-;;; If there's no where then search forward for an equals, as above.
-
-(defun haskell-back-to-symbol (exp)
- "Goes backward from point until a symbol, EXP, is found.
-The point is left at the first symbol matching the context
-of the haskell code."
- (let* ((found nil)
- (symbol (concat "[ \ta-z0-9A-Z]" exp "[ \t\na-z0-9A-Z]"))
- eol-limit
- bol-limit
- (zero-indent (save-excursion
- (haskell-back-to-zero-indent)
- (point)))
- (initial-depth (car (parse-partial-sexp
- (point)
- zero-indent))))
-
- (while (and (not found)
- (> (point) zero-indent))
- ;;Not found and point > point min
- ;;Record the limit of search for the beginning and
- ;; end of the line.
- (setq eol-limit (point))
- (beginning-of-line)
- (setq bol-limit (point))
- (goto-char eol-limit)
- (re-search-backward "\\bwhere\\b" bol-limit 't)
- ;;Search back from the end of the line
- ;; to find the most recent 'where'.
-
- (cond ((and (re-search-backward symbol bol-limit 't)
- (= initial-depth
- (car (parse-partial-sexp
- (point)
- zero-indent))))
- ;;Found a symbol sign surrounded by
- ;; a letter, digit or space only, or at the
- ;; beginning of the buffer and they are at
- ;; the same depth level
- (setq found 't))
- ((and (re-search-backward symbol bol-limit 't)
- (zerop
- (car (parse-partial-sexp
- (point)
- zero-indent))))
- ;; Found a symbol and it is not in any parens
- (setq found 't))
- ;;Otherwise, go back a line.
- (t (haskell-backward-to-noncomment))))
- (if found
- (forward-char 1))))
-
-
-;;; Goes back to the last keyword. The point is left at the
-;;; beginning of the keyword.
-;;; The words recognised are:
-;;; `case',`of',`where',`let',`in',`if',`then',`else'
-
-(defun haskell-back-to-keyword ()
- "Goes backward from point until a keyword is found.
-The point is left after the first keyword."
- (let* ((found nil)
- eol-limit
- bol-limit
- (zero-indent (save-excursion
- (haskell-back-to-zero-indent)
- (point)))
- (initial-depth (car (parse-partial-sexp
- (point)
- zero-indent))))
-
- (while (and (not found)
- (>= (point) zero-indent))
- ;;Not found and point > point min
- ;;Go back past any comment.
- ;;Record the limit of search for the beginning and
- ;; end of the line.
- (setq eol-limit (point))
- (beginning-of-line)
- (setq bol-limit (point))
- (goto-char eol-limit)
- (if (and (re-search-backward
- "\\b\\(case\\|of\\|where\\|let\\|in\\|if\\|then\\|else\\)\\b"
- bol-limit 't)
- (= initial-depth
- (car (parse-partial-sexp
- (point)
- zero-indent))))
- ;;Found a keyword and it is at the same level as the initial position
- (progn
- (setq found 't)
- (forward-word 1))
- ;;Otherwise, go back a line.
- (haskell-backward-to-noncomment)))))
-
-
-
-;;; Returns the end of line (point) of the current line, excluding any
-;;; line comments on it.
-
-(defun haskell-eol ()
- "Returns the end (point) of the current line, excluding any line comments."
- (save-excursion
- (end-of-line)
- (let ((eol-limit (point)))
- (beginning-of-line)
- (if (search-forward "--" eol-limit 'move-to-eol)
- ;;Found a '--'
- ;;So move to the beginning of the comment
- ;;If fail then move to end of line
- (forward-char -2)))
- (point)))
-
-
-
-;;; Returns whether or not the current line contains an equality outwith a
-;;; comment. The equality may only be surrounded by a letter, digit or
-;;; whitespace.
-
-(defun haskell-looking-at-eqp ()
- "Returns whether or not the current line contains an equality outwith a
-comment."
- (save-excursion
- (beginning-of-line)
- (re-search-forward "[ \ta-z0-9A-Z]=[ \t\na-z0-9A-Z]" (1+ (haskell-eol)) 't)))
-
-
-;;; This function does not require all keywords, just those which
-;;; may have a bracket before them.
-(defun haskell-looking-at-keywordp ()
- "Returns whether or not there is a keyword after the point outwith a
-comment."
- (save-excursion
- (re-search-forward
- "\\(\\(=>\\|=\\|++\\|->\\|<-\\|::\\)\\|\\b\\(case\\|of\\|if\\|then\\|else\\|let\\|in\\)\\b\\)"
- (haskell-eol) 't)))
-
-
-;;; This function returns whether or not there is a keyword contained in
-;;; the region START END. START < END.
-
-(defun haskell-keyword-in-regionp (start end)
- "Returns whether or not there is a keyword between START and END."
- (save-excursion
- (goto-char start)
- (let ((found nil)
- (eol-limit (haskell-eol)))
- (while (and (not found) (< (point) end))
- (if (> eol-limit end)
- (setq eol-limit end))
- (if (re-search-forward
- "\\b\\(case\\|of\\|if\\|then\\|else\\|let\\|in\\)\\b"
- eol-limit 'move)
- (setq found t)
- ;;Otherwise, have not found a keyword. Now at haskell-eol.
- (if (< (point) end)
- ;;We still have an area to search
- ;; so go forward one line
- (progn
- (beginning-of-line)
- (forward-line 1)
- (setq eol-limit (haskell-eol))))))
- ;;found is `t' or point >= end
- found)))
-
-
-;;; Goes back to the last line which is not entirely commented out.
-;;; The point is left just before the comment.
-
-(defun haskell-backward-to-noncomment ()
- "Sets the point to the last char on the line of Haskell code before a comment."
- (let ((comment 't)
- (limit (point-min)))
- (while (and comment (> (point) limit))
- ;; comment is true and point > limit
- (beginning-of-line)
- (if (< (forward-line -1) 0)
- ;;This was the first line in the buffer
- (setq comment nil)
- ;;Otherwise, this was not the first line
- (if (not (looking-at "^[ \t]*\\($\\|--\\)"))
- ;;There is not a comment at the beginning of the line
- ;; and the line is not blank
- (progn
- ;;The line is either blank or has code on it.
- (setq comment nil)
- (goto-char (haskell-eol))))))
-
- ;;return point
- (point)))
-
-
-
-;;; Indents a region (by applying "tab" to each line).
-;;; The marker upper-marker is set to the end of the region.
-;;; We indent from the beginning of the region to this marker.
-;;; Implements C-c r.
-
-(defun haskell-indent-region ()
- "Indents the region between the point and mark."
- (interactive)
- (let ((lower-limit (min (point) (mark)))
- (upper-limit (max (point) (mark))))
- (indent-region lower-limit upper-limit 'nil)))
-
-
-
-;;; Implements TAB.
-;;; This actually indents a line.
-;;; Eventually it will handle a line split at any point,
-
-(defun haskell-indent-line ()
- "Indent current line as Haskell code.
-Keeps the point at the same position on the line unless the
-point is less then the current indentation, in which case the
-point is moved to the first char."
- (interactive)
- (save-excursion
- (let ((indent (haskell-calculate-indentation)))
- (beginning-of-line)
- (delete-horizontal-space)
- ;;Kill any spaces that may preceed the code
- ;; and reindent to the correct level.
- (indent-to indent)))
- (if (< (current-column) (current-indentation))
- ;;The point is in the indentation
- ;; so move to the first char on the line
- (move-to-column (current-indentation))))
-
-
-
-;;; This is the haskell version of the Emacs function
-;;; reindent-then-newline-and-indent. It was necessary
-;;; to write this because the Emacs version has the
-;;; terrible property of deleting whitespace BEFORE
-;;; reindenting the original line.
-
-(defun haskell-reindent-then-newline-and-indent ()
- "Reidents the current line of Haskell code then takes a
-newline and indents this new line."
- (interactive)
- (skip-chars-backward " \t")
- (haskell-indent-line)
- (newline)
- (delete-horizontal-space)
- (haskell-indent-line))
-
-
-
-;;; Returns whether the first word of the last line with zero indentation
-;;; is the same as the first word of the current line.
-;;; This function is based on the (reasonable?) assumption that
-;;; a function definition occurs on the left hand margin.
-;;; This is not quit reasonable since recusive functions are not
-;;; recognised.
-
-(defun haskell-continued-fn-defp ()
- "Returns whether the first word on the last line with zero indentation
-matches the first word on the current line."
- (save-excursion
- (beginning-of-line)
- (skip-chars-forward " \t")
- ;;Goto the first non space char
- (haskell-word-eq (point)
- (save-excursion
- (forward-line -1)
- (haskell-back-to-zero-indent)
- (point)))))
-
-
-;;; Returns whether two words are the same.
-;;; The beginning of both words are given as their
-;;; respective points in the buffer.
-
-(defun haskell-word-eq (current-pos previous-pos)
- (let ((OK 't))
- (goto-char previous-pos)
- ;;We shall compare the two words starting
- ;; at previous-pos and current-pos.
- (while (and OK (looking-at "\\S-"))
- ;;OK and looking at a word constituent
- (if (eq (char-after current-pos)
- (char-after previous-pos))
- ;;The two chars are the same
- (progn
- ;;Increment the two postions
- ;; and update location of point
- (setq current-pos (1+ current-pos))
- (setq previous-pos (1+ previous-pos))
- (goto-char previous-pos))
- ;;The two chars are different
- ;; so set OK to be false
- (setq OK 'nil)))
-
- ;;Return the value of OK
- OK))
-
-
-
-
-;;; This function returns the column of the last unbalanced
-;;; expression.
-;;; It is called when an keyword is found. The point is
-;;; initially placed before the corresponding keyword.
-;;; The function looks at every word to see if it is a
-;;; `let' or `in'. Each word must be outwith a comment.
-
-(defun haskell-last-unbalanced-key-column (open close)
- "Returns the column of the last unbalanced keyword, open."
- (save-excursion
- (let ((original-pos (point))
- (bol-limit (save-excursion
- (beginning-of-line)
- (setq bol-limit (point))))
- (depth 1))
- (setq open (concat "\\b" open "\\b"))
- (setq close (concat "\\b" close "\\b"))
- (while (and
- (> depth 0)
- (> (point) (point-min)))
- (forward-word -1)
- (if (< (point) bol-limit)
- ;;Moved past the beginning of line limit
- ;; so go back to the previous line past
- ;; any comments.
- (progn
- (goto-char original-pos)
- (haskell-backward-to-noncomment)
- (setq original-pos (point))
- (setq bol-limit (save-excursion
- (beginning-of-line)
- (point))))
- ;;Otherwise, still on the same line
- (if (looking-at open)
- ;;This word is an open keyword
- (setq depth (1- depth))
- ;;Otherwise,
- (if (looking-at close)
- ;;This word is a close keyword
- (setq depth (1+ depth))))))
-
- (if (string= open "\\bif\\b")
- ;;The argument is `if'
- (if (not (save-excursion (skip-chars-backward " \t") (bolp)))
- ;;There is something before the `if'
- (if (and (save-excursion
- (forward-word -1)
- (looking-at "\\belse\\b"))
- (not haskell-nest-ifs))
- ;;There is an `else' before the 'if'
- (forward-word -1))))
-
-
- (current-column))))
-
-
-
-;;; Return the indentation for a line given that we expect a `where'.
-;;; The point lies on the corresponding symbol
-;;; that the `where' scopes over.
-
-(defun haskell-indent-where ()
- "Return the indentation for a line, given that we expect a `where'
-clause."
- (let ((symbol (if (looking-at "=")
- "="
- "->")))
-
- (cond ((or haskell-std-indent-where
- (> (current-column) haskell-where-threshold))
- ;;Set indentation as the sum of the previous
- ;; line's layout column and the standard offset
- ;; (ie. 'haskell-where-offset)
- (save-excursion
- (beginning-of-line)
- (cond ((looking-at (concat "^[ \t]*" symbol))
- ;;The line starts with the symbol
- (setq indent (current-indentation)))
- ((looking-at "^[ \t]*where\\b")
- ;;The line starts with a 'where'
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (+ (current-column) haskell-where-offset)))
- (t
- ;;The line begins on the layout column
- (setq indent (+ (current-indentation)
- haskell-indent-offset))))))
- ((or haskell-align-where-with-eq
- haskell-align-where-after-eq)
- (if (looking-at (concat symbol "[ \t]*$"))
- ;;The symbol is at the end of the line
- (setq indent (+ (current-indentation)
- haskell-where-offset))
- (save-excursion
- ;;Set the indentation as required
- (if haskell-align-where-after-eq
- (skip-chars-forward (concat symbol " \t")))
- (setq indent (current-column))))))))
-
-
-
-;;; Calculates the indentation for the current line.
-;;; When we come here, we are in a line which we want to indent.
-;;; We should leave the point at the same relative position it
-;;; was in before we called the function, that is, if a line
-;;; is already correctly indented, nothing happens!
-
-;;; The main problems are handling "where" definitions
-;;; and the syntax of expressions when these are continued
-;;; over multiple lines (e.g. tuples, lists, or just plain
-;;; bracketed expressions). Watch out for let ... in, too!
-
-;;; For example, think about the following tricky cases:
-
-;;; f x = x + <NL>
-
-;;; f x = [ x + y, <NL>
-
-;;; f x = [ <NL>
-
-;;; f x = [ -- start of a large list
-;;; -- which I'm commenting in as I go
-;;; <TAB>
-
-(defun haskell-calculate-indentation ()
- "Returns the indentation level for the current line of haskell code."
- (save-excursion
- (let ((indent 0)
- (eol-position (point)))
- (beginning-of-line)
- (cond ((bobp)
- ;;We are at the beginning of the buffer so do nothing at all
- (setq indent 0))
-
- ((looking-at "^[ \t]*--")
- ;;There is a comment on the line by itself
- ;;Leave it the way it is
- (setq indent (current-indentation)))
-
- ((looking-at "^[ \t]*\\(data\\|type\\|module\\|import\\|instance\\)\\b")
- ;;There is a 'data', 'type', 'module' or 'import' at start of line
- (setq indent 0))
-
- ((haskell-continued-fn-defp)
- ;;This is clearly same function
- ;; so set indent to be 0
- (setq indent 0))
-
- ((looking-at "^[ \t]*[]}]")
- ;;There is a "]" or "}" at the start of the line
- (let ((state (parse-partial-sexp (match-end 0)
- (save-excursion
- (haskell-back-to-zero-indent)
- (point)))))
- (if (>= (car state) 0)
- ;;Since the point is just after a parenthesis
- ;; it has a match if the depth is >= 0
- (save-excursion
- (goto-char (nth 2 state))
- ;;Move to the match.
- (if (not
- (save-excursion
- (skip-chars-backward " \t")
- (bolp)))
- ;;There is something before the brace.
- (progn
- (let ((initial-pos (point)))
- (forward-word -1)
- (if (not (looking-at
- "\\(let\\|where\\)"))
- ;;The word is not `where' or `let'
- ;; so go back.
- (progn
- (goto-char initial-pos)
- (skip-chars-forward " \t"))))))
- (setq indent (current-column)))
- (setq indent 0))))
-
- ((looking-at "^[ \t]*\\(->\\|=>\\)")
- ;; '->' or '=>' at start of line
- (save-excursion
- (haskell-backward-to-noncomment)
- ;;Go back to previous line
- (let ((eol-limit (point)))
- (beginning-of-line)
- (if (re-search-forward "::" eol-limit 't)
- ;;There is a '::' on this (previous) line
- ;; set indent to be at the start of it
- (setq indent (- (current-column) 2))
- ;;Otherwise copy this (previous) line's indentation
- (setq indent (current-indentation))))))
-
- ((looking-at "^[ \t]*where\\b")
- ;;There is a 'where' at the start of the line
- ;;Look for the equality (which will not
- ;; be on this line).
- (haskell-backward-to-noncomment)
- (goto-char (max (save-excursion
- (haskell-back-to-symbol "=")
- (point))
- (save-excursion
- (haskell-back-to-symbol "->")
- (point))))
- (setq indent (haskell-indent-where)))
-
- ((looking-at "^[ \t]*then\\b")
- ;;The first thing on the line is a `then'
- (setq indent (+ (haskell-last-unbalanced-key-column "if" "then")
- haskell-then-offset)))
-
- ((looking-at "^[ \t]*else\\b")
- ;;The first thing on the line is a `else'
- (if haskell-align-else-with-then
- (setq indent (haskell-last-unbalanced-key-column "then" "else"))
- (setq indent (haskell-last-unbalanced-key-column "if" "else"))))
-
- ((looking-at "^[ \t]*|")
- ;;There is a `|' at beginning of line
- (save-excursion
- (let ((state
- (parse-partial-sexp (save-excursion
- (haskell-back-to-zero-indent)
- (point))
- (point))))
- (if (not (or (nth 3 state) (nth 4 state)))
- ;;Not in a comment or string
- (if (> (car state) 0)
- ;;In an unbalanced parenthesis.
- (progn
- (goto-char (nth 1 state))
- ;;Move to the beginning of the unbalanced parentheses
- (if (and (looking-at "\\[")
- (search-forward "|" (haskell-eol) 't))
- ;;It is a list comprehension
- (setq indent (1- (current-column)))
- (setq indent (+ (current-column)
- haskell-comp-offset))))
- ;;Otherwise, not in an unbalanced parenthesis
- (setq indent (save-excursion
- (haskell-back-to-symbol "=")
- (cond ((not (looking-at "="))
- ;;Did not find an equals
- (+ (haskell-previous-indentation)
- haskell-indent-offset))
- ((save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*data\\b"))
- ;;There is a `data' at beginning
- (setq indent (current-column)))
- ((save-excursion
- (beginning-of-line)
- (search-forward
- "|" (haskell-eol) 't))
- ;;There is a `|' on this line
- ;; so set this to be the indent
- (save-excursion
- (goto-char (match-beginning 0))
- (current-column)))
- (t
- ;;Otherwise, set `=' as indent
- (current-column))))))))))
-
- ((looking-at "^[ \t]*=")
- ;;There is an equals at the start of the line
- ;;Set the indentation to be the previous line's
- ;; indentation plus the standard offset
- (setq indent (+ haskell-indent-offset
- (haskell-previous-indentation))))
-
- ((looking-at "^[ \t]*in\\b")
- ;;The line starts with 'in'
- (beginning-of-line)
- (setq indent (haskell-last-unbalanced-key-column "let" "in")))
-
- ((looking-at "^[ \t]*of\\b")
- ;;The line starts with `of'
- (beginning-of-line)
- (setq indent (haskell-last-unbalanced-key-column "case" "of")))
-
- ((looking-at "^.*::")
- ;;There is a '::' in the line
- ;;There are several possibilities for indentation
- (if (looking-at "[ \t]*::")
- ;;The '::' is the first thing on the line
- ;; so set indent to be the previous line's
- ;; indentation plus the standard offset
- (setq indent (+ (haskell-previous-indentation)
- haskell-indent-offset))
- (save-excursion
- ;;Otherwise, the '::' is contained in the line somewhere
- ;; so use contextual indentation
- (setq indent (haskell-context-indent)))))
-
- (t
- ;;Do not recognise the first word on the line.
- (setq indent (haskell-context-indent))))
-
- indent))) ;return indent as indentation value
-
-
-
-;;; Returns the indentation for the current line by looking at the
-;;; previous line to give clues to the indentation.
-
-(defun haskell-context-indent ()
- "Returns the indentation for the current line by looking at
-the previous line to dictate the indentation."
- (save-excursion
- (let ((original-position (point))
- indent)
- (beginning-of-line)
- (if (bobp)
- ;;At the beginning of the buffer
- (setq indent 0)
- ;;Otherwise, we are not at the beginning of the buffer
- (haskell-backward-to-noncomment)
- (let ((eol-limit (point))
- ;;Record the (upper) limit for any search on this line
- bol-limit
- (paren-indent 'nil))
- ;;`paren-indent' flags whether we are indenting a list or not
- (beginning-of-line)
- (setq bol-limit (point))
- ;;Record the (lower) limit for any search on this line
- (goto-char eol-limit) ;goto the end of the line
- (flag)
- (if (save-excursion
- (goto-char eol-limit)
- (and (re-search-backward
- "[])][^][()]*" bol-limit 't)
- (save-excursion
- (goto-char (match-beginning 0))
- (not (haskell-looking-at-keywordp)))))
-
- ;;There is a close parenthesis at the end of the line
- ;; followed by anything except "(", ")", "[", "]"
- ;; or a keyword
- (progn
- ;;Search back for the close parenthesis
- ;; and move to just after it.
- (re-search-backward "[])]" bol-limit 't)
- (forward-char 1)
- (let ((state
- (parse-partial-sexp (save-excursion
- (haskell-back-to-zero-indent)
- (point))
- (point))))
- (if (not (or (nth 3 state) (nth 4 state)))
- ;;Not in a comment or string
- (if (>= (car state) 0)
- ;;The parenthesis has a match
- (progn
- (goto-char (nth 2 state))
- ;;Move to the beginning of the parentheses
- ;; as this new line will determine
- ;; further indentation
- (if (zerop (car state))
- ;;This paren closes all unbalanced parens
- ;; so move to
- ;; the eol of last line with an equality.
- (progn
- (setq eol-limit (point))
- (goto-char
- (max (save-excursion
- (haskell-back-to-symbol "=")
- (point))
- (save-excursion
- (haskell-back-to-keyword)
- (point))))
- (goto-char eol-limit))
- ;;esle just go to the end of the line
- (goto-char (haskell-eol)))
- (setq paren-indent 't)
- ;;Set 'paren-indent' to true to indicate we
- ;; are indenting a list.
- (setq eol-limit (point))
- (beginning-of-line)
- (setq bol-limit (point))
- ;;Reduce the scope of any later
- ;; indentation to
- ;; exclude the balanced parentheses
- ;; by making this point
- ;; be the eol-limit.
- (goto-char eol-limit)))))))
- (flag)
- ;;This cond expression is structured, to an
- ;; extent, such that the keywords with highest
- ;; indentation precedence come first. Order is important.
- ;;In each condition, the point of match is noted so
- ;; that we can see if this point is in a string.
- (let ((indent-point (point)))
- (cond ((re-search-backward "\\bof\\b" bol-limit 't)
- ;; `of' is contained in previous line
- (setq indent-point (point))
- (if (looking-at "of[ \t]*$")
- ;;`of' at end of line
- (setq indent (+ (haskell-last-unbalanced-key-column
- "case" "of")
- haskell-case-offset))
- ;;Otherwise, `of' is in line
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (current-column))
- (setq indent (list indent))))
-
- ((re-search-backward
- "\\bthen[ \t]*$" bol-limit 't)
- ;;There is a `then' at the end of the line.
- (setq indent-point (point))
- (if haskell-align-else-with-then
- ;;We want to align the `else' (to follow) with the `then'
- (setq indent (+ (current-column)
- haskell-if-offset))
- (setq indent (+ (haskell-last-unbalanced-key-column
- "if" "then")
- haskell-if-offset))))
- ;; This was here but don't know why (setq indent (list indent))))
-
- ((save-excursion
- (and (re-search-backward "\\bif\\b" bol-limit 't)
- (setq indent-point (point))
- (not (re-search-forward "\\bthen\\b" eol-limit 't))))
- ;;There is an `if' on the (previous) line and the line does
- ;; not have a `then' on it.
- (setq indent (+ (haskell-last-unbalanced-key-column
- "if" "then")
- haskell-then-offset)))
-
- ((save-excursion
- (and (re-search-backward "\\bif\\b" bol-limit 't)
- (setq indent-point (point))
- (not (re-search-forward "\\belse\\b" eol-limit 't))))
- ;;There is an `if' on the (previous) line (the line may
- ;; have a `then' on it) and does not have an else on it.
- (if (re-search-backward "\\bthen\\b" bol-limit 't)
- ;;There is a then on the line and it is followed by
- ;; some code.
- (progn
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (current-column)))
- (if haskell-align-else-with-then
- ;;We want to align the `else' with the `then'
- (setq indent (haskell-last-unbalanced-key-column
- "then" "else"))
- (setq indent (haskell-last-unbalanced-key-column
- "if" "else")))))
-
- ((re-search-backward "\\b\\(let\\|in\\)\\b" bol-limit 't)
- ;; 'let' or 'in' is contained in the (previous) line
- (setq indent-point (point))
- (forward-word 1) ;skip past the word
- (skip-chars-forward " \t{")
- (if (looking-at "\\($\\|--\\)")
- ;;looking-at eol or comment
- (progn
- (forward-word -1)
- (setq indent (+ (current-column)
- haskell-let-offset)))
- (setq indent (current-column))))
-
- ((re-search-backward
- "\\belse[ \t]*$" bol-limit 't)
- ;;There is a `else' at end of line
- (setq indent-point (point))
- (save-excursion
- (goto-char eol-limit)
- (forward-word -1)
- (setq indent (+ (current-column)
- haskell-if-offset))))
-
- ((re-search-backward
- "\\belse\\b" bol-limit 't)
- ;;There is a `else' on the line with no if or then
- (setq indent-point (point))
- (save-excursion
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (current-column))))
-
- ((save-excursion
- (beginning-of-line)
- (looking-at
- "^[ \t]*then\\b"))
- ;;There is a 'then' at beginning of line
- (setq indent-point (point))
- (setq indent (current-indentation)))
-
- ((save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*else[ \t]*if\\b"))
- (setq indent-point (point))
- ;;There is an 'else if' at start of (previous) line
- (save-excursion
- (beginning-of-line)
- (if haskell-nest-ifs
- (save-excursion
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (current-column)))
- (skip-chars-forward " \t")
- (setq indent (current-column)))))
-
- ((re-search-backward "\\bcase\\b" bol-limit 't)
- ;;There is a 'case' on the previous line
- ;; so copy this line's indentation and add on
- ;; the offset unless there is not an of.
- (setq indent-point (point))
- (setq indent (+ (current-column)
- haskell-case-offset)))
-
- ((save-excursion
- (beginning-of-line)
- (looking-at "^\\(instance\\|class\\)\\b"))
- ;;This (previous) line has an 'instance' or 'class' at start
- ;; so just set indentation to be this line indentation
- ;; plus the standard offset
- (setq indent-point (point))
- (setq indent (+ (current-indentation)
- haskell-indent-offset)))
-
- ((re-search-backward "where\\b" bol-limit 't)
- ;;There is a 'where' on the (previous) line
- (setq indent-point (point))
- (if (looking-at "where[ \t]*$")
- ;;There is nothing after the 'where'
- ;; so set indent to be this column
- ;; (ie. the column of the 'w')
- ;; plus the standard offset
- (if (save-excursion
- (skip-chars-backward " \t")
- (bolp))
- ;;The 'where' is the only thing on the line.
- (setq indent (+ (current-column)
- haskell-where-offset))
- ;;Otherwise, the 'where' is at the end
- ;; of the line and there is code before it.
- ;;Look before the 'where' for the symbol
- ;; it scopes over.
- (forward-word -1)
- (goto-char (max (save-excursion
- (haskell-back-to-symbol "=")
- (point))
- (save-excursion
- (haskell-back-to-symbol "->")
- (point))))
- (setq indent (haskell-indent-where)))
-
- ;;Otherwise, go past the 'where'
- ;; and goto the last non space character.
- ;;Set this column to be the indentation.
- (forward-word 1)
- (skip-chars-forward " \t")
- (setq indent (current-column))))
-
- ((re-search-backward
- "[ \ta-z0-9A-Z]=[ \t]*$" bol-limit 't)
- ;;There is an equals is at the end of line
- ;; so make the indentation be this line's indentation
- ;; plus the standard offset
- (setq indent-point (point))
- (setq indent (+ (current-indentation)
- haskell-indent-offset)))
-
- ((re-search-backward
- "[ \ta-z0-9A-Z]\\+\\+[ \t]*$" bol-limit 't)
- ;;There is a concat operator at the end of line
- ;; so make the indentation be this line's indentation
- (setq indent-point (point))
- (setq indent (current-indentation)))
-
- ((save-excursion
- (beginning-of-line)
- (looking-at
- "^[ \t]*=[ \ta-z0-9A-Z]"))
- ;;There is an equals is at the beginning of line
- ;; so make the indentation be the previous line's
- ;; indentation unless the previous line's
- ;; indentation is zero.
- (setq indent-point (point))
- (save-excursion
- (haskell-backward-to-noncomment)
- (if (zerop (current-indentation))
- (setq indent (+ (current-indentation)
- haskell-indent-offset))
- (setq indent (haskell-current-indentation)))))
-
- ((re-search-backward "|" bol-limit 't)
- ;;There is an `|' on this line.
- (setq indent-point (point))
- (if (save-excursion
- (goto-char original-position)
- (looking-at "^[ \t]*\\($\\|--\\||\\)"))
- ;;The original line is empty or has a `|' at the
- ;; start. So set indent to be first `|' on this line
- (save-excursion
- (goto-char bol-limit)
- (re-search-forward "|" eol-limit 't)
- (setq indent (1- (current-column))))
- ;;Otherwise set indent to be this (previous) line's
- (setq indent 0)))
-
- ((re-search-backward "->" bol-limit 't)
- ;;There is a `->' in the line.
- ;;This may be from a `case' or a
- ;; type declaration.
- (setq indent-point (point))
- (save-excursion
- (if (re-search-backward "::" bol-limit 't)
- ;;There is a '::' on this line
- (if (looking-at ".*->[ \t]*$")
- ;;The '->' is at the end of line.
- ;;Move past the '::' and any spaces
- ;; and set indent to be this column.
- (progn
- (skip-chars-forward ": \t")
- (setq indent (current-column)))
- ;;Otherwise, the '->' is not at end of line
- ;; so copy the indentation
- (setq indent (haskell-context-indent)))
-
- ;;Otherwise, there is not a
- ;; `::' on this line so copy this
- ;; (previous) indentation.
- (setq indent (haskell-context-indent)))))
-
- ((re-search-backward "::" bol-limit 't)
- ;;There is an '::' on this line.
- ;;We know that the line does not end with '->'.
- (setq indent-point (point))
- (if (looking-at "::[ \t]*$")
- ;;The '::' is at the end of the line
- ;; so set indent to be this line's
- ;; indentation plus the offset.
- (setq indent (+ (current-indentation)
- haskell-indent-offset))
- ;;Otherwise the `::' is in the line
- (setq indent (current-indentation))))
-
- ((re-search-backward
- "\\b\\(import\\|class\\)\\b"
- bol-limit 't)
- ;;There is an `import' or `class' on the line.
- ;;Copy this indentation.
- (setq indent-point (point))
- (setq indent (current-indentation)))
-
- ((or
- (haskell-looking-at-eqp)
- (save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*$")))
- ;;There is an '=' on the line
- ;; or it is blank
- (setq indent-point (point))
- (cond ((save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*data\\b"))
- ;;`data' at start of line
- ;; so expect a `|'
- (haskell-back-to-symbol "=")
- (setq indent (current-column)))
- ((zerop (current-indentation))
- ;;If the indentation is zero, we expect a `where'
- (goto-char eol-limit)
- (haskell-back-to-symbol "=")
- (setq indent (haskell-indent-where)))
- ((looking-at "^[ \t]*=[ \t\na-z0-9A-Z]")
- ;;The equality is the first thing on the line
- ;; so copy the last lines indentation
- (save-excursion
- (haskell-backward-to-noncomment)
- (setq indent (current-indentation))))
- (t
- ;;Otherwise, copy the indentation
- (setq indent (current-indentation)))))
-
- ((save-excursion
- (beginning-of-line)
- (and (zerop (current-indentation))
- (not (looking-at "^[ \t]*$"))))
- ;;The line is not blank and its indentation is zero
- ;;It is a function definition. We know that
- ;; there is not an equals on the line
- (goto-char eol-limit)
- ;;We expect a keyword
- ;; so set indent to be this line's indentation
- ;; plus the offset
- (setq indent-point (point))
- (setq indent (+ (current-indentation)
- haskell-indent-offset)))
-
- ((bobp)
- ;;At the beginning of buffer
- (setq indent 0))
-
- (paren-indent
- ;;We are indenting a list and none
- ;; of the above indentations are applicable
- ;; so copy the indentation of this line
- (setq indent (current-indentation)))
-
- (t
- (save-excursion
- (setq indent (haskell-context-indent)))))
-
- (if (nth 3 (parse-partial-sexp
- (save-excursion
- (goto-char indent-point)
- (haskell-back-to-zero-indent)
- (point))
- (save-excursion
- (goto-char indent-point))))
- ;;The point we determined indentation at is in a
- ;; string so go to this point and go back one line to
- ;; find indentation.
- (setq indent (haskell-context-indent))))
-
-
- ;;HOWEVER, we may have to override any indentation if we are in
- ;; an unbalanced parenthesis (on the original line).
- (flag)
- (save-excursion
- (goto-char original-position)
- (let* ((eq-point (save-excursion
- (haskell-back-to-symbol "=")
- (point)))
- (state (parse-partial-sexp
- eq-point
- (point))))
- (if (> (car state) 0)
- ;;There is an unbalanced parenthesis between
- ;; the function and here.
- (if (not (or (nth 3 state) (nth 4 state)))
- ;;We are not in a string or comment
- ;; so goto the parenthesis
- (progn
- (goto-char (nth 1 state))
- (if (not (haskell-keyword-in-regionp
- (point)
- original-position))
- ;;There is not a keyword after the open
- ;; bracket so we override the indentation
- (progn
- (if (not (looking-at "{"))
- ;;The parenthesis is not a `{'
- (if (or (looking-at "\\[")
- (save-excursion
- (goto-char (haskell-eol))
- (skip-chars-backward " \t")
- (and
- (char-equal (preceding-char) ?,)
- (= (car state)
- (car (parse-partial-sexp
- eq-point
- (point)))))))
- ;;The paren is a square one
- ;; or it is a tuple.
- ;;Don't ignore what is after it.
- (setq indent (haskell-list-align (haskell-eol)))
- ;;Otherwise, ignore what comes after it.
- (setq indent (haskell-list-align (point))))))))))))
- ))
-
- indent)))
-
-
-;;; Inserts the close parenthesis and reindents the line.
-;;; We want to reindent the line if the parenthesis is
-;;; the first character on the line. The parenthesis
-;;; recognised by this function are `]', `}'.
-
-(defun electric-haskell-brace ()
- "Inserts the character `]' or `}' and reindents the current line."
- "Insert character and correct line's indentation."
- (interactive)
- (if (save-excursion
- (skip-chars-backward " \t")
- (bolp))
- ;;The parenthesis is at the beginning of the line.
- (progn
- (insert last-command-char)
- (haskell-indent-line))
- ;;Otherwise it is not at the beginning of line.
- (insert last-command-char))
- ;; Match its beginning.
- (haskell-blink-open))
-
-
-
-
-;;; This function returns the indentation for the next line given
-;;; that it is contained in a bracket or we are extending a functions
-;;; parameters over a line. For the case of being in an unbalanced
-;;; parenthesis list, the point lies on the unbalanced parenthesis.
-;;; The parameter eol-limit is used to delimit the end of the line.
-
-(defun haskell-list-align (eol-limit)
- "Returns the indentation for the next line given that
-the point lies on an unbalanced open parenthesis."
- (save-excursion
- (let ((indent (1+ (current-column))))
- ;;Set indent to be the next char (at least).
-
- (cond ((not
- (looking-at ".[ \t]*\\($\\|--\\)"))
- ;;There is something after the parenthesis
- ;;ie. the line is not empty and ignore comments
- (cond ((save-excursion
- (goto-char eol-limit)
- (skip-chars-backward " \t")
- (and (char-equal (preceding-char) ?,)
- (save-excursion
- (beginning-of-line)
- (not (search-forward "|" eol-limit 't)))))
- ;;This is a normal list since a `,' at end
- ;; and there is no a `|' on the line.
- (forward-char 1)
- (skip-chars-forward " \t")
- (setq indent (current-column)))
-
- ((looking-at "\\[")
- ;;It is a list comp we are looking at
- ;;Goto the bar.
- (forward-char 1)
- (search-forward "|" eol-limit 't)
- (skip-chars-forward " \t")
- (setq indent (current-column)))
-
- ((looking-at ".[ \t]*(")
- ;;We are looking at an open parenthesis
- ;; after this character.
- ;;It must be balanced so
- ;; move to the start of this paren
- ;; and set indent to be here
- (forward-char 1)
- (skip-chars-forward " \t")
- (setq indent (current-column)))
-
- (t
- (forward-word 1)
- ;;We are not looking at another open
- ;; parenthesis, so move forward past the
- ;; (assumed) function name.
- (if (or
- haskell-std-list-indent
- (looking-at"[ \t]*\\($\\|--\\)"))
- ;;There is nothing after the name
- ;; or haskell-std-list-offset is set
- ;; so set indent to be its original
- ;; value plus the offset minus 1
- ;; since we added one on earlier.
- (setq indent
- (+ indent
- (1- haskell-list-offset)))
-
- ;;Otherwise there is something after the
- ;; name, so skip to the first non space
- ;; character.
- (skip-chars-forward " \t")
- (setq indent (current-column)))))))
-
-
- indent)))
-
-
-
-(defun haskell-insert-round-paren ()
- "Inserts a `(' and blinks to its matching parenthesis."
- (interactive)
- (insert last-command-char)
- (haskell-blink-open))
-
-
-
-;;; This function is called when a close parenthesis
-;;; `)', `]', or `}' is typed.
-;;; Blinks the cursor on the corresponding open parnethesis.
-;;; The point lies just after the close parenthesis.
-
-(defun haskell-blink-open ()
- "Blinks the cursor to the matching open parenthesis.
-The point lies just after a parenthesis."
- (let ((state (parse-partial-sexp (point)
- (save-excursion
- (haskell-back-to-zero-indent)
- (point)))))
- (if (and
- (>= (car state) 0)
- (not (or (nth 3 state) (nth 4 state))))
- ;;The parenthesis just inserted has a match
- ;; and is not in a string or a comment
- ;; so blink on its match
- (save-excursion
- (goto-char (nth 2 state))
- (sit-for 1)))))
-
-
-
-;;; This function indents the line expecting the line to be a
-;;; continued function application.
-
-;;; foo a = bar a
-;;; b {haskell-further-indent applied to this line
-;;; indents the line as shown}
-
-;;; The line would look like this if only tab had been applied:
-;;; foo a = bar a
-;;; b
-
-(defun haskell-further-indent ()
- "Indents the line more than the ordinary indentation in order to
-extend function arguments over multiple lines."
- (interactive)
- (let (indent
- (new-point (max (save-excursion
- (haskell-back-to-symbol "=")
- (point))
- (save-excursion
- (haskell-back-to-keyword)
- (point)))))
- (save-excursion
- ;;This may be a continuation of a function
- ;; application so go back to the last '='
- ;; and set indent as designated by the style chosen
- (goto-char new-point)
- (skip-chars-forward "= \t")
- (setq indent (haskell-list-align (haskell-eol))))
- ;;The argument to haskell-list-align is not important here.
- (save-excursion
- (beginning-of-line)
- (delete-horizontal-space)
- (indent-to indent))
- (if (< (current-column) indent)
- (move-to-column indent))))
-
-
-;;; This function indents the current line to the first previous
-;;; indentation value which is less than the current indentation.
-
-(defun haskell-lesser-indent ()
- "Indents the current line to the first previous indentation
-value which is less than the current indentation."
- (interactive)
- (let ((original-indent
- (current-indentation))
- (indent (haskell-context-indent))
- (done nil))
- (save-excursion
- (while (not done)
- (while (and (not (bobp))
- (not (zerop (current-indentation)))
- (>= indent original-indent))
- (haskell-backward-to-noncomment)
- (setq indent (current-indentation)))
- ;;bobp or indent < original-indent
- (if (>= indent original-indent)
- ;;indent is still greater than or equal to original indent
- (progn
- (setq indent 0)
- (setq done t))
- ;;Otherwise, indent is less than orignal indent.
- (forward-line 1)
- (setq indent (haskell-context-indent))
- (if (< indent original-indent)
- ;;The new indent is an improvement
- (setq done t)
- ;;Otherwise, indent is still >= original
- ;; so go back to the line and keep typing.
- (forward-line -1)))))
- (save-excursion
- (beginning-of-line)
- (delete-horizontal-space)
- (indent-to indent))
- (if (< (current-column) indent)
- (move-to-column indent))))
-
-
-
-;;; Here are the functions which change the local variables
-;;; to facilitate tailorability.
-
-(defun default-mode ()
- "Calls the function haskell-mode."
- (interactive)
- (haskell-mode)
- (message haskell-indent-style))
-
-(defun wadler-mode ()
- "Sets defaults according to Dr. Philip L. Wadler's preferences.
- - Aligns `where' clauses with the corresponding equality.
- - Aligns `else' keyword with the corresponding `then'
- - haskell-list-offset 2
- - haskell-indent-offset 8
- - haskell-if-indent 2
- - haskell-comment-column 0
- - haskell-case-offset 2
- - haskell-let-offset 5."
- ;;Preferences:
- ;;'haskell-align-where-with-eq non-nil
- ;;'haskell-list-offset 2
- (interactive)
- (haskell-mode)
- (or haskell-align-where-with-eq
- (progn
- (setq haskell-align-where-with-eq t)
- (setq haskell-std-indent-where nil)))
- (setq haskell-align-else-with-then t)
- (setq haskell-list-offset 2)
- (setq haskell-indent-offset 8)
- (setq haskell-if-offset 2)
- (setq haskell-case-offset 2)
- (setq haskell-let-offset 5)
- (setq haskell-comment-column 0)
- (setq haskell-indent-style "Wadler")
- (message haskell-indent-style))
-
-
-(defun report-mode ()
- "Sets defaults according to the style of the Haskell Report.
- - Aligns `where' clauses after the corresponding equality.
- - Aligns `else' with `then'.
- - haskell-then-offset = 3
- - haskell-where-offset = 0.
- - haskell-case-offset = 5."
- ;;Preferences:
- ;; haskell-align-where-after-eq non-nil
- ;; haskell-then-offset 3
- ;; haskell-where-offset 0
- ;; haskell-case-offset 5
- (interactive)
- (haskell-mode)
- (haskell-align-where-after-eq)
- (or haskell-align-else-with-then
- (haskell-align-else-with-then))
- (setq haskell-then-offset 3)
- (setq haskell-where-offset 0)
- (setq haskell-case-offset 5)
- (setq haskell-indent-style "Report")
- (message haskell-indent-style))
-
-
-(defun haskell-align-where-with-eq ()
- "Sets indentation so that a 'where' clause lines up underneath
-its corresponding equals sign."
- (interactive)
- (or haskell-align-where-with-eq
- (progn
- (setq haskell-align-where-after-eq nil)
- (setq haskell-std-indent-where nil)
- (setq haskell-align-where-with-eq t)
- haskell-align-where-with-eq)))
-
-
-
-(defun haskell-align-where-after-eq ()
- "Sets indentation so that a 'where' clause lines up underneath
-the first nonspace character after its corresponding equals sign."
- (interactive)
- (or haskell-align-where-after-eq
- (progn
- (setq haskell-align-where-with-eq nil)
- (setq haskell-std-indent-where nil)
- (setq haskell-align-where-after-eq t)
- haskell-align-where-after-eq)))
-
-
-(defun haskell-std-indent-where ()
- "Sets indentation so that a `where' clause lines up underneath
-its corresponding equals sign."
- (interactive)
- (or haskell-std-indent-where
- (progn
- (setq haskell-align-where-after-eq nil)
- (setq haskell-align-where-with-eq nil)
- (setq haskell-std-indent-where t)
- haskell-std-indent-where)))
-
-
-(defun haskell-align-else-with-then ()
- "Sets indentation so that an `else' lines up underneath
-it's corresponding `then'."
- (interactive)
- (setq haskell-align-else-with-then
- (not haskell-align-else-with-then))
- (setq haskell-nest-ifs nil))
-
-(defun haskell-nest-ifs ()
- "Sets indentation so that an `if' is lined up
-under an `if' in an `else ."
- (interactive)
- (setq haskell-nest-ifs
- (not haskell-nest-ifs))
- (setq haskell-align-else-with-then nil))
-
-
-(defun haskell-always-fixup-comment-space ()
- "Non-nil means always position one space after a line comment `--',
-when reindenting or inserting a comment,
-whether or not one space exists."
- (setq haskell-always-fixup-comment-space
- (not haskell-always-fixup-comment-space))
- haskell-always-fixup-comment-space)
-
-(defun haskell-indent-style ()
- "Echos the chosen indentation style in the mini-buffer."
- (interactive)
- (message haskell-indent-style))
-
-(defun set-haskell-let-offset (offset)
- "Changes the value of haskell-let-offset, the variable which
-determines extra indentation after a `let' and `in'."
- (interactive "nSet haskell-let-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-let-offset offset)))
-
-(defun set-haskell-if-offset (offset)
- "Changes the value of haskell-let-offset, the variable which
-determines extra indentation after an `if', `then' and `else'."
- (interactive "nSet haskell-if-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-if-offset offset)))
-
-(defun set-haskell-case-offset (offset)
- "Changes the value of haskell-case-offset, the variable which
-determines extra indentation after a `case' and `of'."
- (interactive "nSet haskell-case-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-case-offset offset)))
-
-
-(defun set-haskell-where-offset (offset)
- "Changes the value of haskell-where-offset, the variable which
-determines extra indentation after a line of haskell code."
- (interactive "nSet haskell-where-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-where-offset offset)))
-
-
-(defun set-haskell-indent-offset (offset)
- "Changes the value of haskell-indent-offset, the variable which
-determines extra indentation after a line of haskell code."
- (interactive "nSet haskell-indent-offset to: ")
- (if (and (>= offset 1) (<= offset 10))
- (setq haskell-indent-offset offset)))
-
-
-(defun set-haskell-list-offset (offset)
- "Changes the value of haskell-list-offset, the variable which
-determines extra indentation after a line of haskell code for a list."
- (interactive "nSet haskell-list-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-list-offset offset)))
-
-
-(defun set-haskell-comp-offset (offset)
- "Changes the value of haskell-comp-offset, the variable which
-determines extra indentation after a list comprehension."
- (interactive "nSet haskell-comp-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-comp-offset offset)))
-
-
-(defun set-haskell-then-offset (offset)
- "Changes the value of haskell-then-offset, the variable which
-determines extra indentation for a `then' keyword after an `if'."
- (interactive "nSet haskell-then-offset to: ")
- (if (and (>= offset 0) (<= offset 10))
- (setq haskell-then-offset offset)))
-
-
-(defun set-haskell-comment-column (column)
- "Changes the value of haskell-comment-column, the variable which
-determines where to postition a line comment `--'."
- (interactive "nSet haskell-comment-column to: ")
- (if (and (>= column 0) (<= column 100))
- (setq haskell-comment-column column)))
-
-(defun set-haskell-concat-column (column)
- "Changes the value of haskell-concat-column, the variable which
-determines where to postition a concatenation operator `++'."
- (interactive "nSet haskell-concat-column to: ")
- (if (and (>= column 0) (<= column 100))
- (setq haskell-concat-column column)))
-
-(defun set-haskell-where-threshold (column)
- "Changes the value of haskell-where-threshold, the variable which
-determines when to override positioning a `where' under or after
-its corresponding equality."
- (interactive "nSet haskell-where-threshold to: ")
- (if (and (>= column 0) (<= column 100))
- (setq haskell-where-threshold column)))
-
-(defun flag ()) \ No newline at end of file