Initial Commit
[packages] / xemacs-packages / ilisp / ilisp-mov.el
1 ;;; -*- Mode: Emacs-Lisp -*-
2
3 ;;; ilisp-mov.el --
4 ;;;
5 ;;; This file is part of ILISP.
6 ;;; Please refer to the file COPYING for copyrights and licensing
7 ;;; information.
8 ;;; Please refer to the file ACKNOWLEGDEMENTS for an (incomplete) list
9 ;;; of present and past contributors.
10 ;;;
11 ;;; $Id: ilisp-mov.el,v 1.3 2001-07-02 09:40:47 youngs Exp $
12
13
14 ;;;%%Movement
15 (defun bol-ilisp (arg)
16   "Goes to the beginning of line, then skips past the prompt, if any.
17 If a prefix argument is given (\\[universal-argument]), then no prompt skip 
18 -- go straight to column 0.
19
20 The prompt skip is done by skipping text matching the regular expression
21 comint-prompt-regexp or ilisp-other-prompt, both buffer local variables."
22   (interactive "P")
23   (beginning-of-line)
24   (if (null arg) 
25       (or (comint-skip-prompt)
26           (if ilisp-other-prompt
27               (let ((comint-prompt-regexp ilisp-other-prompt))
28                 (comint-skip-prompt))))))
29
30 ;;;
31 (defun beginning-of-defun-lisp (&optional stay)
32   "Go to the next left paren that starts at the left margin or after a
33 prompt in an ILISP buffer.  If optional STAY, then do not move to
34 prior defun if at the start of one in an ilisp mode."
35   (interactive)
36   (if (memq major-mode ilisp-modes)
37       (let ((point (point)))
38         (if (and (not stay) (= point (lisp-input-start)))
39             (progn (forward-line -1) (lisp-input-start))))
40       (beginning-of-defun)))
41
42 ;;;
43 (defun end-of-defun-lisp ()
44   "Go to the next left paren that starts at the left margin or after a
45 prompt in an ILISP buffer and go to the end of the expression."
46   (interactive)
47   (let ((point (point)))
48     (if (memq major-mode ilisp-modes)
49         (beginning-of-defun-lisp t)
50         (if (or (lisp-in-string)
51                 (progn (beginning-of-line)
52                        (re-search-forward "^[ \t\n]*[^; \t\n]" nil t)
53                        (back-to-indentation)
54                        (not (bolp))))
55             (beginning-of-defun-lisp t)))
56     (lisp-end-defun-text t)
57     (if (= point (point))               ;Already at end so move to next end
58         (progn
59           (if (memq major-mode ilisp-modes)
60               (re-search-forward comint-prompt-regexp (point-max) t)
61               (lisp-skip (point-max)))
62           (if (not (or (eobp)
63                        (= (char-after (point)) ?\n)))
64               (lisp-end-defun-text t))))))
65
66 ;;;
67 (defun lisp-defun-begin ()
68   "Go to the start of the containing defun and return point."
69   (let (begin)
70     (if (memq major-mode ilisp-modes)
71         (lisp-input-start)
72         (if (or (eobp) (not (and (bolp) (= (char-after (point)) ?\())))
73             (beginning-of-defun))
74         (point))))
75
76 ;;;
77 (defun lisp-defun-end (&optional no-errorp at-beginp)
78   "Go to the end of the containing defun and return point or nil if
79 there is no end."
80   (if (not at-beginp) (lisp-defun-begin))
81   (condition-case ()
82       (progn
83         (lisp-skip (point-max))         ;To skip comments on defun-end
84         (forward-sexp)
85         (point))
86     (error (if no-errorp nil (error "Unbalanced parentheses")))))
87
88 ;;;
89 (defun lisp-find-next-start ()
90   "Find the start of the next line at the left margin that starts with
91 a character besides whitespace, a \) or ;;; and return the
92 point."
93   (if (eobp)
94       (point-max)
95       (save-excursion
96         (forward-char)
97         (if (re-search-forward "^\\(\\(;;;\\)\\|\\([^ \t\n\);]\\)\\)" nil t)
98             (match-beginning 0)
99             (point-max)))))
100
101 ;;;
102 (defun lisp-end-defun-text (&optional at-start)
103   "Go the end of the text associated with the current defun and return
104 point.  The end is the last character before whitespace leading to
105 a left paren or ;;; at the left margin unless it is in a string."
106   (if (not at-start) (lisp-defun-begin))
107   (let ((point (point))
108         (boundary (lisp-find-next-start))
109         (final (save-excursion
110                  (condition-case ()
111                      (progn (forward-sexp) (point))
112                    (error (point-max))))))
113     ;; Find the next line starting at the left margin and then check
114     ;; to see if it is in a string. 
115     (while (progn
116              (skip-chars-forward "^\"" boundary) ;To the next string
117              (if (= (point) boundary)   
118                  nil                    ;No quote found and at limit
119                  (let ((string-boundary ;Start of next defun
120                         (save-excursion
121                           (if (re-search-forward "^\(\\|^;;;" nil t)
122                               (match-beginning 0)
123                               (point-max)))))
124                    (if (condition-case ()
125                            (progn (forward-sexp) t)
126                          (error (goto-char string-boundary) nil))
127                        (if (>= (point) boundary)
128                            ;; Boundary was in string
129                            (if (> (point) string-boundary)
130                                (progn   ;String ended in next defun
131                                  (goto-char string-boundary)
132                                  nil)
133                                (if (> (setq boundary
134                                             (lisp-find-next-start))
135                                       final)
136                                    ;; Normal defun
137                                    (progn (goto-char final) nil)
138                                    t))
139                            t)
140                        ;; Unclosed string
141                        nil)))))
142     (re-search-backward  "^[^; \t\n]\\|^[^;\n][ \t]*[^ \t\n]" point t)
143     (end-of-line)
144     (skip-chars-backward " \t")
145     (if (< (point) point)
146         (goto-char point)
147         (if (save-excursion
148               (let ((point (point)))
149                 (beginning-of-line)
150                 (if comment-start (search-forward comment-start point t))))
151             (progn (next-line 1) (indent-line-ilisp)))
152         (point))))
153
154 ;;;
155 (defun lisp-in-comment (test)
156   "Return T if you are in a comment."
157   (beginning-of-line)
158   (and (looking-at test)
159        (not (= (match-end 0)
160                (progn (end-of-line) (point))))))
161
162 ;;;
163 (defun lisp-in-string (&optional begin end)
164   "Return the string region that immediately follows/precedes point or
165 that contains point in optional region BEGIN to END.  If point is in
166 region, T will be returned as well."
167   (save-excursion
168     (if (not begin)
169         (save-excursion
170           (setq end (lisp-end-defun-text)
171                 begin (lisp-defun-begin))))
172     (let* ((point (progn (skip-chars-forward " \t") (point)))
173            (done nil))
174       (goto-char begin)
175       (while (and (< (point) end) (not done))
176         (skip-chars-forward "^\"" end)
177         (setq begin (point))
178         (if (< begin end)
179             (if (and (not (bobp)) (= (char-after (1- begin)) ??))
180                 (forward-char)
181                 (if (condition-case () (progn (forward-sexp) (<= (point) end))
182                       (error nil))
183                     (progn              ;After string
184                       (skip-chars-forward " \t")
185                       (if (or (= begin point) (= point (point)))
186                           (setq done (list begin (point) nil))
187                           (if (and (< begin point) (< point (point)))
188                               (setq done (list begin (point) t)))))
189                     ;; In string at end of buffer
190                     (setq done (list begin end t))))))
191       done)))