Initial Commit
[packages] / xemacs-packages / haskell-mode / haskell-simple-indent.el
1 ;;; haskell-simple-indent.el --- Simple indentation module for Haskell Mode
2
3 ;; Copyright (C) 1998 Heribert Schuetz, Graeme E Moss
4
5 ;; Authors:
6 ;;   1998 Heribert Schuetz <Heribert.Schuetz@informatik.uni-muenchen.de> and
7 ;;        Graeme E Moss <gem@cs.york.ac.uk>
8 ;; Keywords: indentation files Haskell
9 ;; Version: 1.0
10 ;; URL: http://www.cs.york.ac.uk/~gem/haskell-mode/simple-indent.html
11
12 ;; This file is not part of GNU Emacs.
13
14 ;; This file is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; any later version.
18
19 ;; This file is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
28
29 \f
30 ;;; Commentary:
31
32 ;; Purpose:
33 ;;
34 ;; To support simple indentation of Haskell scripts.
35 ;;
36 ;;
37 ;; Installation:
38 ;; 
39 ;; To bind TAB to the indentation command for all Haskell buffers, add
40 ;; this to .emacs:
41 ;;
42 ;;    (add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)
43 ;;
44 ;; Otherwise, call `turn-on-haskell-simple-indent'.
45 ;;
46 ;;
47 ;; Customisation:
48 ;;
49 ;; None supported.
50 ;;
51 ;;
52 ;; History:
53 ;;
54 ;; If you have any problems or suggestions, after consulting the list
55 ;; below, email gem@cs.york.ac.uk quoting the version of you are
56 ;; using, the version of Emacs you are using, and a small example of
57 ;; the problem or suggestion.
58 ;;
59 ;; Version 1.0:
60 ;;   Brought over from Haskell mode v1.1.
61 ;;
62 ;; Present Limitations/Future Work (contributions are most welcome!):
63 ;;
64 ;; (None so far.)
65
66 ;;; Code:
67
68 ;; All functions/variables start with
69 ;; `(turn-(on/off)-)haskell-simple-indent'.
70
71 ;; Version.
72 (defconst haskell-simple-indent-version "1.2"
73   "`haskell-simple-indent' version number.")
74 (defun haskell-simple-indent-version ()
75   "Echo the current version of `haskell-simple-indent' in the minibuffer."
76   (interactive)
77   (message "Using haskell-simple-indent version %s"
78            haskell-simple-indent-version))
79
80 ;; Partly stolen from `indent-relative' in indent.el:
81 (defun haskell-simple-indent ()
82   "Space out to under next visible indent point.
83 Indent points are positions of non-whitespace following whitespace in
84 lines preceeding point.  A position is visible if it is to the left of
85 the first non-whitespace of every nonblank line between the position and
86 the current line.  If there is no visible indent point beyond the current
87 column, `tab-to-tab-stop' is done instead."
88   (interactive)
89   (let* ((start-column (current-column))
90          (invisible-from nil)           ; `nil' means infinity here
91          (indent
92           (catch 'haskell-simple-indent-break
93             (save-excursion
94               (while (progn (beginning-of-line)
95                             (not (bobp)))
96                 (forward-line -1)
97                 (if (not (looking-at "[ \t]*\n"))
98                     (let ((this-indentation (current-indentation)))
99                       (if (or (not invisible-from)
100                               (< this-indentation invisible-from))
101                           (if (> this-indentation start-column)
102                               (setq invisible-from this-indentation)
103                             ;; XEmacs: no `line-beginning-position' in < 21.5
104                             (let ((end (point-at-bol 2)))
105                               (move-to-column start-column)
106                               ;; Is start-column inside a tab on this line?
107                               (if (> (current-column) start-column)
108                                   (backward-char 1))
109                               (or (looking-at "[ \t]")
110                                   (skip-chars-forward "^ \t" end))
111                               (skip-chars-forward " \t" end)
112                               (let ((col (current-column)))
113                                 (throw 'haskell-simple-indent-break
114                                        (if (or (= (point) end)
115                                                (and invisible-from
116                                                     (> col invisible-from)))
117                                            invisible-from
118                                          col)))))))))))))
119     (if indent
120         (let ((opoint (point-marker)))
121           (indent-line-to indent)
122           (if (> opoint (point))
123               (goto-char opoint))
124           (set-marker opoint nil))
125       (tab-to-tab-stop))))
126
127 (defvar haskell-simple-indent-old)
128
129 ;; The main functions.
130 (defun turn-on-haskell-simple-indent ()
131   "Set `indent-line-function' to a simple indentation function.
132 TAB will now move the cursor to the next indent point in the previous
133 nonblank line.  An indent point is a non-whitespace character following
134 whitespace.
135
136 Runs `haskell-simple-indent-hook'.
137
138 Use `haskell-simple-indent-version' to find out what version this is."
139   (interactive)
140   (set (make-local-variable 'haskell-simple-indent-old) indent-line-function)
141   (set (make-local-variable 'indent-line-function) 'haskell-simple-indent)
142   (run-hooks 'haskell-simple-indent-hook))
143
144 (defun turn-off-haskell-simple-indent ()
145   "Return `indent-line-function' to original value.
146 I.e. the value before `turn-on-haskell-simple-indent' was called."
147   (interactive)
148   (when (local-variable-p 'haskell-simple-indent-old)
149     (setq indent-line-function haskell-simple-indent-old)
150     (kill-local-variable 'haskell-simple-indent-old)))
151
152 ;; Provide ourselves:
153
154 (provide 'haskell-simple-indent)
155
156 ;;; haskell-simple-indent.el ends here