X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2FCONTRIB%2Fhaskell-modes%2Fglasgow%2Foriginal%2Fhaskell-mode.el;fp=ghc%2FCONTRIB%2Fhaskell-modes%2Fglasgow%2Foriginal%2Fhaskell-mode.el;h=0000000000000000000000000000000000000000;hb=1fb1ab5d53a09607e7f6d2450806760688396387;hp=b9a490ffd14af118ede1126d187151ca6b92b39d;hpb=fa6fb09e2e4e6918eebc79ed187f32c88817c9db;p=ghc-hetmet.git 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 b9a490f..0000000 --- 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 + - -;;; f x = [ x + y, - -;;; f x = [ - -;;; f x = [ -- start of a large list -;;; -- which I'm commenting in as I go -;;; - -(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