(command_loop_1): Update selected buffer again after read_key_sequence.
[bpt/emacs.git] / lisp / add-log.el
CommitLineData
84fc2cfa
ER
1;;; add-log.el --- change log maintenance commands for Emacs
2
e332f80b 3;; Copyright (C) 1985, 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
84fc2cfa 4
e9571d2a
ER
5;; Keywords: maint
6
84fc2cfa
ER
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
fd7fa35a 11;; the Free Software Foundation; either version 2, or (at your option)
84fc2cfa
ER
12;; any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
b578f267
EN
20;; along with GNU Emacs; see the file COPYING. If not, write to the
21;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22;; Boston, MA 02111-1307, USA.
84fc2cfa 23
e41b2db1
ER
24;;; Commentary:
25
26;; This facility is documented in the Emacs Manual.
27
fd7fa35a 28;;; Code:
84fc2cfa 29
84fc2cfa
ER
30(defvar change-log-default-name nil
31 "*Name of a change log file for \\[add-change-log-entry].")
32
6258d3af
RM
33(defvar add-log-current-defun-function nil
34 "\
35*If non-nil, function to guess name of current function from surrounding text.
36\\[add-change-log-entry] calls this function (if nil, `add-log-current-defun'
37instead) with no arguments. It returns a string or nil if it cannot guess.")
38
29db528b 39;;;###autoload
59ac2ce6 40(defvar add-log-full-name nil
02ec1592
BF
41 "*Full name of user, for inclusion in ChangeLog daily headers.
42This defaults to the value returned by the `user-full-name' function.")
43
29db528b 44;;;###autoload
59ac2ce6 45(defvar add-log-mailing-address nil
02ec1592 46 "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
fb38ca86 47This defaults to the value of `user-mail-address'.")
02ec1592 48
5f562719 49(defvar change-log-font-lock-keywords
5572c1d1
SM
50 '(;;
51 ;; Date lines, new and old styles.
52 ("^\\sw........."
53 (0 font-lock-string-face)
54 ("[A-Z][^\n<]+" nil nil (0 font-lock-reference-face)))
55 ;;
56 ;; File names.
57 ("^\t\\* \\([^ ,:([\n]+\\)"
58 (1 font-lock-function-name-face)
59 ("\\=, \\([^ ,:([\n]+\\)" nil nil (1 font-lock-function-name-face)))
60 ;;
61 ;; Function or variable names.
62 ("(\\([^ ,:\n]+\\)"
63 (1 font-lock-keyword-face)
64 ("\\=, \\([^ ,:\n]+\\)" nil nil (1 font-lock-keyword-face)))
65 ;;
66 ;; Conditionals.
67 ("\\[!?\\([^]\n]+\\)\\]\\(:\\| (\\)" (1 font-lock-variable-name-face))
68 ;;
69 ;; Acknowledgments.
70 ("^\t\\(From\\|Reported by\\)" 1 font-lock-comment-face)
71 )
5f562719
RS
72 "Additional expressions to highlight in Change Log mode.")
73
45c50c5d
KH
74(defvar change-log-mode-map nil
75 "Keymap for Change Log major mode.")
76(if change-log-mode-map
77 nil
78 (setq change-log-mode-map (make-sparse-keymap)))
79
51bd1843
EN
80(defvar change-log-time-zone-rule nil
81 "Time zone used for calculating change log time stamps.
82It takes the same format as the TZ argument of `set-time-zone-rule'.
83If nil, use local time.")
84
85(defun iso8601-time-zone (time)
86 (let* ((utc-offset (or (car (current-time-zone time)) 0))
87 (sign (if (< utc-offset 0) ?- ?+))
88 (sec (abs utc-offset))
89 (ss (% sec 60))
90 (min (/ sec 60))
91 (mm (% min 60))
92 (hh (/ min 60)))
93 (format (cond ((not (zerop ss)) "%c%02d:%02d:%02d")
94 ((not (zerop mm)) "%c%02d:%02d")
95 (t "%c%02d"))
96 sign hh mm ss)))
97
84fc2cfa
ER
98(defun change-log-name ()
99 (or change-log-default-name
8afc29f0 100 (if (eq system-type 'vax-vms)
4a047d23
RS
101 "$CHANGE_LOG$.TXT"
102 "ChangeLog")))
84fc2cfa 103
287d149f 104;;;###autoload
84fc2cfa
ER
105(defun prompt-for-change-log-name ()
106 "Prompt for a change log name."
117aaf60
KH
107 (let* ((default (change-log-name))
108 (name (expand-file-name
109 (read-file-name (format "Log file (default %s): " default)
110 nil default))))
111 ;; Handle something that is syntactically a directory name.
112 ;; Look for ChangeLog or whatever in that directory.
113 (if (string= (file-name-nondirectory name) "")
114 (expand-file-name (file-name-nondirectory default)
115 name)
116 ;; Handle specifying a file that is a directory.
117 (if (file-directory-p name)
118 (expand-file-name (file-name-nondirectory default)
119 (file-name-as-directory name))
120 name))))
84fc2cfa 121
45a13f0d
RM
122;;;###autoload
123(defun find-change-log (&optional file-name)
124 "Find a change log file for \\[add-change-log-entry] and return the name.
a82e2ed5
RS
125
126Optional arg FILE-NAME specifies the file to use.
de98fcaf
RS
127If FILE-NAME is nil, use the value of `change-log-default-name'.
128If 'change-log-default-name' is nil, behave as though it were 'ChangeLog'
129\(or whatever we use on this operating system).
130
131If 'change-log-default-name' contains a leading directory component, then
132simply find it in the current directory. Otherwise, search in the current
133directory and its successive parents for a file so named.
45a13f0d
RM
134
135Once a file is found, `change-log-default-name' is set locally in the
136current buffer to the complete file name."
a82e2ed5
RS
137 ;; If user specified a file name or if this buffer knows which one to use,
138 ;; just use that.
45a13f0d 139 (or file-name
de98fcaf
RS
140 (setq file-name (and change-log-default-name
141 (file-name-directory change-log-default-name)
142 change-log-default-name))
a82e2ed5
RS
143 (progn
144 ;; Chase links in the source file
145 ;; and use the change log in the dir where it points.
146 (setq file-name (or (and buffer-file-name
147 (file-name-directory
148 (file-chase-links buffer-file-name)))
149 default-directory))
150 (if (file-directory-p file-name)
151 (setq file-name (expand-file-name (change-log-name) file-name)))
152 ;; Chase links before visiting the file.
153 ;; This makes it easier to use a single change log file
154 ;; for several related directories.
155 (setq file-name (file-chase-links file-name))
156 (setq file-name (expand-file-name file-name))
157 ;; Move up in the dir hierarchy till we find a change log file.
158 (let ((file1 file-name)
159 parent-dir)
160 (while (and (not (or (get-file-buffer file1) (file-exists-p file1)))
161 (progn (setq parent-dir
162 (file-name-directory
163 (directory-file-name
164 (file-name-directory file1))))
165 ;; Give up if we are already at the root dir.
166 (not (string= (file-name-directory file1)
167 parent-dir))))
168 ;; Move up to the parent dir and try again.
169 (setq file1 (expand-file-name
170 (file-name-nondirectory (change-log-name))
171 parent-dir)))
172 ;; If we found a change log in a parent, use that.
173 (if (or (get-file-buffer file1) (file-exists-p file1))
174 (setq file-name file1)))))
175 ;; Make a local variable in this buffer so we needn't search again.
176 (set (make-local-variable 'change-log-default-name) file-name)
177 file-name)
45a13f0d 178
84fc2cfa 179;;;###autoload
287d149f 180(defun add-change-log-entry (&optional whoami file-name other-window new-entry)
84fc2cfa
ER
181 "Find change log file and add an entry for today.
182Optional arg (interactive prefix) non-nil means prompt for user name and site.
183Second arg is file name of change log. If nil, uses `change-log-default-name'.
287d149f
RM
184Third arg OTHER-WINDOW non-nil means visit in other window.
185Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
51bd1843
EN
186never append to an existing entry. Today's date is calculated according to
187`change-log-time-zone-rule' if non-nil, otherwise in local time."
84fc2cfa
ER
188 (interactive (list current-prefix-arg
189 (prompt-for-change-log-name)))
550d8777
RS
190 (or add-log-full-name
191 (setq add-log-full-name (user-full-name)))
192 (or add-log-mailing-address
193 (setq add-log-mailing-address user-mail-address))
02ec1592
BF
194 (if whoami
195 (progn
196 (setq add-log-full-name (read-input "Full name: " add-log-full-name))
84fc2cfa
ER
197 ;; Note that some sites have room and phone number fields in
198 ;; full name which look silly when inserted. Rather than do
199 ;; anything about that here, let user give prefix argument so that
200 ;; s/he can edit the full name field in prompter if s/he wants.
02ec1592
BF
201 (setq add-log-mailing-address
202 (read-input "Mailing address: " add-log-mailing-address))))
203 (let ((defun (funcall (or add-log-current-defun-function
204 'add-log-current-defun)))
205 paragraph-end entry)
45a13f0d 206
3e1c918b 207 (setq file-name (expand-file-name (find-change-log file-name)))
82f4acaf
RM
208
209 ;; Set ENTRY to the file name to use in the new entry.
210 (and buffer-file-name
211 ;; Never want to add a change log entry for the ChangeLog file itself.
212 (not (string= buffer-file-name file-name))
213 (setq entry (if (string-match
214 (concat "^" (regexp-quote (file-name-directory
215 file-name)))
216 buffer-file-name)
217 (substring buffer-file-name (match-end 0))
218 (file-name-nondirectory buffer-file-name))))
219
84fc2cfa
ER
220 (if (and other-window (not (equal file-name buffer-file-name)))
221 (find-file-other-window file-name)
222 (find-file file-name))
675a998f
RS
223 (or (eq major-mode 'change-log-mode)
224 (change-log-mode))
84fc2cfa
ER
225 (undo-boundary)
226 (goto-char (point-min))
51bd1843
EN
227 (let ((new-entry (concat (if change-log-time-zone-rule
228 (let ((tz (getenv "TZ"))
229 (now (current-time)))
230 (unwind-protect
231 (progn
232 (set-time-zone-rule
233 change-log-time-zone-rule)
234 (concat
235 (format-time-string "%Y-%m-%d " now)
236 (iso8601-time-zone now)))
237 (set-time-zone-rule tz)))
238 (format-time-string "%Y-%m-%d"))
239 " " add-log-full-name
240 " <" add-log-mailing-address ">")))
241 (if (looking-at (regexp-quote new-entry))
242 (forward-line 1)
243 (insert new-entry "\n\n")))
82f4acaf 244
74046d00 245 ;; Search only within the first paragraph.
716a781e
RS
246 (if (looking-at "\n*[^\n* \t]")
247 (skip-chars-forward "\n")
248 (forward-paragraph 1))
82f4acaf 249 (setq paragraph-end (point))
84fc2cfa 250 (goto-char (point-min))
82f4acaf 251
1832dbd1 252 ;; Now insert the new line for this entry.
82f4acaf
RM
253 (cond ((re-search-forward "^\\s *\\*\\s *$" paragraph-end t)
254 ;; Put this file name into the existing empty entry.
255 (if entry
256 (insert entry)))
287d149f 257 ((and (not new-entry)
e172f546
KH
258 (let (case-fold-search)
259 (re-search-forward
260 (concat (regexp-quote (concat "* " entry))
261 ;; Don't accept `foo.bar' when
262 ;; looking for `foo':
263 "\\(\\s \\|[(),:]\\)")
264 paragraph-end t)))
82f4acaf
RM
265 ;; Add to the existing entry for the same file.
266 (re-search-forward "^\\s *$\\|^\\s \\*")
e172f546
KH
267 (goto-char (match-beginning 0))
268 ;; Delete excess empty lines; make just 2.
09b389d0 269 (while (and (not (eobp)) (looking-at "^\\s *$"))
1832dbd1
RS
270 (delete-region (point) (save-excursion (forward-line 1) (point))))
271 (insert "\n\n")
272 (forward-line -2)
dd309224 273 (indent-relative-maybe))
21d7e080 274 (t
dd309224
RM
275 ;; Make a new entry.
276 (forward-line 1)
277 (while (looking-at "\\sW")
278 (forward-line 1))
09b389d0 279 (while (and (not (eobp)) (looking-at "^\\s *$"))
1832dbd1
RS
280 (delete-region (point) (save-excursion (forward-line 1) (point))))
281 (insert "\n\n\n")
282 (forward-line -2)
dd309224
RM
283 (indent-to left-margin)
284 (insert "* " (or entry ""))))
1832dbd1 285 ;; Now insert the function name, if we have one.
21d7e080
ER
286 ;; Point is at the entry for this file,
287 ;; either at the end of the line or at the first blank line.
288 (if defun
289 (progn
dd309224 290 ;; Make it easy to get rid of the function name.
21d7e080 291 (undo-boundary)
dd309224
RM
292 (insert (if (save-excursion
293 (beginning-of-line 1)
294 (looking-at "\\s *$"))
295 ""
296 " ")
297 "(" defun "): "))
1832dbd1 298 ;; No function name, so put in a colon unless we have just a star.
dd309224
RM
299 (if (not (save-excursion
300 (beginning-of-line 1)
301 (looking-at "\\s *\\(\\*\\s *\\)?$")))
1832dbd1 302 (insert ": ")))))
84fc2cfa 303
84fc2cfa
ER
304;;;###autoload
305(defun add-change-log-entry-other-window (&optional whoami file-name)
306 "Find change log file in other window and add an entry for today.
6258d3af
RM
307Optional arg (interactive prefix) non-nil means prompt for user name and site.
308Second arg is file name of change log. \
309If nil, uses `change-log-default-name'."
84fc2cfa
ER
310 (interactive (if current-prefix-arg
311 (list current-prefix-arg
312 (prompt-for-change-log-name))))
313 (add-change-log-entry whoami file-name t))
82f4acaf 314;;;###autoload (define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
84fc2cfa 315
1da56800 316;;;###autoload
21d7e080 317(defun change-log-mode ()
eb8c3be9 318 "Major mode for editing change logs; like Indented Text Mode.
09b389d0 319Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
5516387c
RM
320New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window].
321Each entry behaves as a paragraph, and the entries for one day as a page.
322Runs `change-log-mode-hook'."
21d7e080
ER
323 (interactive)
324 (kill-all-local-variables)
325 (indented-text-mode)
82f4acaf
RM
326 (setq major-mode 'change-log-mode
327 mode-name "Change Log"
328 left-margin 8
4f675a8c 329 fill-column 74
60f10a06
KH
330 indent-tabs-mode t
331 tab-width 8)
45c50c5d 332 (use-local-map change-log-mode-map)
60f10a06
KH
333 (set (make-local-variable 'fill-paragraph-function)
334 'change-log-fill-paragraph)
21d7e080 335 ;; Let each entry behave as one paragraph:
14ee1953
RS
336 ;; We really do want "^" in paragraph-start below: it is only the lines that
337 ;; begin at column 0 (despite the left-margin of 8) that we are looking for.
51bd1843
EN
338 (set (make-local-variable 'paragraph-start) "\\s *$\\|\f\\|^\\<")
339 (set (make-local-variable 'paragraph-separate) "\\s *$\\|\f\\|^\\<")
21d7e080 340 ;; Let all entries for one day behave as one page.
2c91c85c
RS
341 ;; Match null string on the date-line so that the date-line
342 ;; is grouped with what follows.
964141f2 343 (set (make-local-variable 'page-delimiter) "^\\<\\|^\f")
dd309224
RM
344 (set (make-local-variable 'version-control) 'never)
345 (set (make-local-variable 'adaptive-fill-regexp) "\\s *")
4b286eca
SM
346 (set (make-local-variable 'font-lock-defaults)
347 '(change-log-font-lock-keywords t))
21d7e080
ER
348 (run-hooks 'change-log-mode-hook))
349
287d149f
RM
350;; It might be nice to have a general feature to replace this. The idea I
351;; have is a variable giving a regexp matching text which should not be
352;; moved from bol by filling. change-log-mode would set this to "^\\s *\\s(".
353;; But I don't feel up to implementing that today.
354(defun change-log-fill-paragraph (&optional justify)
355 "Fill the paragraph, but preserve open parentheses at beginning of lines.
356Prefix arg means justify as well."
357 (interactive "P")
14ee1953
RS
358 (let ((end (save-excursion (forward-paragraph) (point)))
359 (beg (save-excursion (backward-paragraph)(point)))
360 (paragraph-start (concat paragraph-start "\\|\\s *\\s(")))
361 (fill-region beg end justify)))
287d149f 362\f
21d7e080 363(defvar add-log-current-defun-header-regexp
26add1bf 364 "^\\([A-Z][A-Z_ ]*[A-Z_]\\|[-_a-zA-Z]+\\)[ \t]*[:=]"
21d7e080
ER
365 "*Heuristic regexp used by `add-log-current-defun' for unknown major modes.")
366
e332f80b 367;;;###autoload
21d7e080
ER
368(defun add-log-current-defun ()
369 "Return name of function definition point is in, or nil.
370
63314951 371Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...),
64bd2d51 372Texinfo (@node titles), Perl, and Fortran.
21d7e080
ER
373
374Other modes are handled by a heuristic that looks in the 10K before
375point for uppercase headings starting in the first column or
376identifiers followed by `:' or `=', see variable
377`add-log-current-defun-header-regexp'.
378
379Has a preference of looking backwards."
2cc0b765
RS
380 (condition-case nil
381 (save-excursion
382 (let ((location (point)))
3fec4c1b
RS
383 (cond ((memq major-mode '(emacs-lisp-mode lisp-mode scheme-mode
384 lisp-interaction-mode))
a0151877 385 ;; If we are now precisely at the beginning of a defun,
2cc0b765
RS
386 ;; make sure beginning-of-defun finds that one
387 ;; rather than the previous one.
388 (or (eobp) (forward-char 1))
389 (beginning-of-defun)
390 ;; Make sure we are really inside the defun found, not after it.
947b2743
RS
391 (if (and (looking-at "\\s(")
392 (progn (end-of-defun)
2cc0b765
RS
393 (< location (point)))
394 (progn (forward-sexp -1)
395 (>= location (point))))
396 (progn
0e933219
JB
397 (if (looking-at "\\s(")
398 (forward-char 1))
399 (forward-sexp 1)
a0151877 400 (skip-chars-forward " '")
2cc0b765
RS
401 (buffer-substring (point)
402 (progn (forward-sexp 1) (point))))))
32e986d4 403 ((and (memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
2cc0b765
RS
404 (save-excursion (beginning-of-line)
405 ;; Use eq instead of = here to avoid
406 ;; error when at bob and char-after
407 ;; returns nil.
408 (while (eq (char-after (- (point) 2)) ?\\)
36e6631c 409 (forward-line -1))
2cc0b765
RS
410 (looking-at "[ \t]*#[ \t]*define[ \t]")))
411 ;; Handle a C macro definition.
412 (beginning-of-line)
413 (while (eq (char-after (- (point) 2)) ?\\) ;not =; note above
414 (forward-line -1))
415 (search-forward "define")
416 (skip-chars-forward " \t")
417 (buffer-substring (point)
418 (progn (forward-sexp 1) (point))))
32e986d4 419 ((memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
2cc0b765
RS
420 (beginning-of-line)
421 ;; See if we are in the beginning part of a function,
422 ;; before the open brace. If so, advance forward.
423 (while (not (looking-at "{\\|\\(\\s *$\\)"))
424 (forward-line 1))
425 (or (eobp)
426 (forward-char 1))
427 (beginning-of-defun)
428 (if (progn (end-of-defun)
429 (< location (point)))
430 (progn
431 (backward-sexp 1)
432 (let (beg tem)
fd7fa35a 433
2cc0b765
RS
434 (forward-line -1)
435 ;; Skip back over typedefs of arglist.
436 (while (and (not (bobp))
437 (looking-at "[ \t\n]"))
438 (forward-line -1))
439 ;; See if this is using the DEFUN macro used in Emacs,
440 ;; or the DEFUN macro used by the C library.
441 (if (condition-case nil
442 (and (save-excursion
019644ee
RS
443 (end-of-line)
444 (while (= (preceding-char) ?\\)
445 (end-of-line 2))
2cc0b765
RS
446 (backward-sexp 1)
447 (beginning-of-line)
448 (setq tem (point))
449 (looking-at "DEFUN\\b"))
450 (>= location tem))
451 (error nil))
452 (progn
453 (goto-char tem)
454 (down-list 1)
455 (if (= (char-after (point)) ?\")
456 (progn
457 (forward-sexp 1)
458 (skip-chars-forward " ,")))
459 (buffer-substring (point)
460 (progn (forward-sexp 1) (point))))
32e986d4
RS
461 (if (looking-at "^[+-]")
462 (get-method-definition)
463 ;; Ordinary C function syntax.
464 (setq beg (point))
e172f546
KH
465 (if (and (condition-case nil
466 ;; Protect against "Unbalanced parens" error.
467 (progn
468 (down-list 1) ; into arglist
469 (backward-up-list 1)
470 (skip-chars-backward " \t")
471 t)
472 (error nil))
473 ;; Verify initial pos was after
474 ;; real start of function.
475 (save-excursion
476 (goto-char beg)
477 ;; For this purpose, include the line
478 ;; that has the decl keywords. This
479 ;; may also include some of the
480 ;; comments before the function.
481 (while (and (not (bobp))
482 (save-excursion
483 (forward-line -1)
484 (looking-at "[^\n\f]")))
485 (forward-line -1))
486 (>= location (point)))
32e986d4
RS
487 ;; Consistency check: going down and up
488 ;; shouldn't take us back before BEG.
489 (> (point) beg))
e172f546
KH
490 (let (end middle)
491 ;; Don't include any final newline
492 ;; in the name we use.
493 (if (= (preceding-char) ?\n)
494 (forward-char -1))
495 (setq end (point))
496 (backward-sexp 1)
497 ;; Now find the right beginning of the name.
498 ;; Include certain keywords if they
499 ;; precede the name.
500 (setq middle (point))
501 (forward-word -1)
6dfa1d83
RS
502 ;; Ignore these subparts of a class decl
503 ;; and move back to the class name itself.
504 (while (looking-at "public \\|private ")
505 (skip-chars-backward " \t:")
506 (setq end (point))
507 (backward-sexp 1)
508 (setq middle (point))
509 (forward-word -1))
e172f546
KH
510 (and (bolp)
511 (looking-at "struct \\|union \\|class ")
512 (setq middle (point)))
513 (buffer-substring middle end)))))))))
2cc0b765
RS
514 ((memq major-mode
515 '(TeX-mode plain-TeX-mode LaTeX-mode;; tex-mode.el
516 plain-tex-mode latex-mode;; cmutex.el
517 ))
518 (if (re-search-backward
519 "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" nil t)
520 (progn
521 (goto-char (match-beginning 0))
522 (buffer-substring (1+ (point));; without initial backslash
523 (progn
524 (end-of-line)
525 (point))))))
526 ((eq major-mode 'texinfo-mode)
3071ee28 527 (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
2cc0b765
RS
528 (buffer-substring (match-beginning 1)
529 (match-end 1))))
64bd2d51
RS
530 ((eq major-mode 'perl-mode)
531 (if (re-search-backward "^sub[ \t]+\\([^ \t\n]+\\)" nil t)
532 (buffer-substring (match-beginning 1)
533 (match-end 1))))
a9e2a7f2
RS
534 ((eq major-mode 'fortran-mode)
535 ;; must be inside function body for this to work
536 (beginning-of-fortran-subprogram)
537 (let ((case-fold-search t)) ; case-insensitive
538 ;; search for fortran subprogram start
539 (if (re-search-forward
540 "^[ \t]*\\(program\\|subroutine\\|function\
541\\|[ \ta-z0-9*]*[ \t]+function\\)"
63314951 542 nil t)
a9e2a7f2
RS
543 (progn
544 ;; move to EOL or before first left paren
545 (if (re-search-forward "[(\n]" nil t)
546 (progn (forward-char -1)
547 (skip-chars-backward " \t"))
548 (end-of-line))
549 ;; Use the name preceding that.
550 (buffer-substring (point)
551 (progn (forward-sexp -1)
552 (point)))))))
2cc0b765
RS
553 (t
554 ;; If all else fails, try heuristics
555 (let (case-fold-search)
556 (end-of-line)
557 (if (re-search-backward add-log-current-defun-header-regexp
558 (- (point) 10000)
559 t)
560 (buffer-substring (match-beginning 1)
561 (match-end 1))))))))
562 (error nil)))
ef15f270 563
15319a8f
RS
564(defvar get-method-definition-md)
565
59c1a7de
RS
566;; Subroutine used within get-method-definition.
567;; Add the last match in the buffer to the end of `md',
568;; followed by the string END; move to the end of that match.
569(defun get-method-definition-1 (end)
15319a8f
RS
570 (setq get-method-definition-md
571 (concat get-method-definition-md
572 (buffer-substring (match-beginning 1) (match-end 1))
573 end))
59c1a7de
RS
574 (goto-char (match-end 0)))
575
576;; For objective C, return the method name if we are in a method.
577(defun get-method-definition ()
15319a8f 578 (let ((get-method-definition-md "["))
59c1a7de 579 (save-excursion
f27f16ed 580 (if (re-search-backward "^@implementation\\s-*\\([A-Za-z_]*\\)" nil t)
59c1a7de
RS
581 (get-method-definition-1 " ")))
582 (save-excursion
583 (cond
f27f16ed 584 ((re-search-forward "^\\([-+]\\)[ \t\n\f\r]*\\(([^)]*)\\)?\\s-*" nil t)
59c1a7de
RS
585 (get-method-definition-1 "")
586 (while (not (looking-at "[{;]"))
587 (looking-at
f27f16ed 588 "\\([A-Za-z_]*:?\\)\\s-*\\(([^)]*)\\)?[A-Za-z_]*[ \t\n\f\r]*")
59c1a7de 589 (get-method-definition-1 ""))
15319a8f 590 (concat get-method-definition-md "]"))))))
59c1a7de 591
ef15f270 592
1da56800
RS
593(provide 'add-log)
594
fd7fa35a 595;;; add-log.el ends here