aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/ChangeLog69
-rw-r--r--lisp/Makefile.in2
-rw-r--r--lisp/gnus/ChangeLog5
-rw-r--r--lisp/gnus/gnus-msg.el4
-rw-r--r--lisp/progmodes/octave-inf.el387
-rw-r--r--lisp/progmodes/octave.el (renamed from lisp/progmodes/octave-mod.el)521
-rw-r--r--lisp/progmodes/opascal.el336
-rw-r--r--lisp/textmodes/reftex-parse.el14
-rw-r--r--lisp/textmodes/reftex-vars.el19
-rw-r--r--lisp/textmodes/remember.el6
11 files changed, 613 insertions, 756 deletions
diff --git a/etc/NEWS b/etc/NEWS
index d8f5f68ff99..f6335d314eb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -101,6 +101,12 @@ You can pick the name of the function and the variables with `C-x 4 a'.
101 101
102* Changes in Specialized Modes and Packages in Emacs 24.4 102* Changes in Specialized Modes and Packages in Emacs 24.4
103 103
104** `remember' can now store notes in separates files
105You can use the new function `remember-store-in-files' within the
106`remember-handler-functions' option.
107
108See `remember-data-directory' and `remember-directory-file-name-format'
109for new options related to this function.
104** `ido-decorations' has been slightly extended to give a bit more control. 110** `ido-decorations' has been slightly extended to give a bit more control.
105 111
106** More packages look for ~/.emacs.d/<foo> additionally to ~/.<foo>. 112** More packages look for ~/.emacs.d/<foo> additionally to ~/.<foo>.
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7bce53d7caf..e7c374e1e96 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,72 @@
12013-04-26 Leo Liu <sdl.web@gmail.com>
2
3 * progmodes/octave.el (octave-submit-bug-report): Obsolete.
4 (octave-mode, inferior-octave-mode): Use setq-local.
5 (octave-not-in-string-or-comment-p): Renamed to
6 octave-in-string-or-comment-p.
7 (octave-in-comment-p, octave-in-string-p)
8 (octave-in-string-or-comment-p): Replace defsubst with defun.
9
102013-04-25 Paul Eggert <eggert@cs.ucla.edu>
11
12 * Makefile.in (distclean): Remove $(lisp)/loaddefs.el~.
13
142013-04-25 Bastien Guerry <bzg@gnu.org>
15
16 * textmodes/remember.el (remember-data-directory)
17 (remember-directory-file-name-format): Fix custom types.
18
192013-04-25 Leo Liu <sdl.web@gmail.com>
20
21 * progmodes/octave.el (octave-completion-at-point-function): Make
22 use of inferior octave process.
23 (octave-initialize-completions): Remove.
24 (inferior-octave-completion-table): New function.
25 (inferior-octave-completion-at-point): Use it.
26 (octave-completion-alist): Remove.
27
282013-04-25 Stefan Monnier <monnier@iro.umontreal.ca>
29
30 * progmodes/opascal.el: Use font-lock and syntax-propertize.
31 (opascal-mode-syntax-table): New var.
32 (opascal-literal-kind, opascal-is-literal-end)
33 (opascal-literal-token-at): Rewrite.
34 (opascal--literal-start-re, opascal-font-lock-keywords)
35 (opascal--syntax-propertize): New constants.
36 (opascal-font-lock-defaults): Adjust.
37 (opascal-mode): Use them. Set comment-<foo> variables as well.
38 (delphi-comment-face, opascal-comment-face, delphi-string-face)
39 (opascal-string-face, delphi-keyword-face, opascal-keyword-face)
40 (delphi-other-face, opascal-other-face): Remove face variables.
41 (opascal-save-state): Remove macro.
42 (opascal-fontifying-progress-step): Remove constant.
43 (opascal--ignore-changes): Remove var.
44 (opascal-set-token-property, opascal-parse-next-literal)
45 (opascal-is-stable-literal, opascal-complete-literal)
46 (opascal-is-literal-start, opascal-face-of)
47 (opascal-parse-region, opascal-parse-region-until-stable)
48 (opascal-fontify-region, opascal-after-change)
49 (opascal-debug-show-is-stable, opascal-debug-unparse-buffer)
50 (opascal-debug-parse-region, opascal-debug-parse-window)
51 (opascal-debug-parse-buffer, opascal-debug-fontify-window)
52 (opascal-debug-fontify-buffer): Remove.
53 (opascal-debug-mode-map): Adjust accordingly.
54
552013-04-25 Leo Liu <sdl.web@gmail.com>
56
57 Merge octave-mod.el and octave-inf.el into octave.el with some
58 cleanups.
59 * progmodes/octave.el: New file renamed from octave-mod.el.
60 * progmodes/octave-inf.el: Merged into octave.el.
61 * progmodes/octave-mod.el: Renamed to octave.el.
62
632013-04-25 Tassilo Horn <tsdh@gnu.org>
64
65 * textmodes/reftex-vars.el
66 (reftex-label-ignored-macros-and-environments): New defcustom.
67
68 * textmodes/reftex-parse.el (reftex-parse-from-file): Use it.
69
12013-04-25 Stefan Monnier <monnier@iro.umontreal.ca> 702013-04-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 71
3 * emacs-lisp/smie.el (smie-indent--hanging-p): Don't burp at EOB. 72 * emacs-lisp/smie.el (smie-indent--hanging-p): Don't burp at EOB.
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 1e701df348f..c8707df15df 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -433,7 +433,7 @@ bootstrap-clean:
433 cd $(lisp); rm -f *.elc */*.elc */*/*.elc */*/*/*.elc $(AUTOGENEL) 433 cd $(lisp); rm -f *.elc */*.elc */*/*.elc */*/*/*.elc $(AUTOGENEL)
434 434
435distclean: 435distclean:
436 -rm -f ./Makefile 436 -rm -f ./Makefile $(lisp)/loaddefs.el~
437 437
438maintainer-clean: distclean bootstrap-clean 438maintainer-clean: distclean bootstrap-clean
439 439
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index 4cdc8a103bd..251e5b1f381 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,8 @@
12013-04-25 Andrew Cohen <cohen@bu.edu>
2
3 * gnus-msg.el (gnus-inews-insert-gcc): Re-order conditional to work for
4 string values of 'gcc-self. Thanks to Saroj Thirumalai.
5
12013-04-24 Andrew Cohen <cohen@bu.edu> 62013-04-24 Andrew Cohen <cohen@bu.edu>
2 7
3 * nnir.el (nnir-close-group): Make sure we are in the right group. 8 * nnir.el (nnir-close-group): Make sure we are in the right group.
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index 362dd3ea7f0..fce9a3633c2 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -1719,8 +1719,8 @@ this is a reply."
1719 (group (when group (gnus-group-decoded-name group))) 1719 (group (when group (gnus-group-decoded-name group)))
1720 (var (or gnus-outgoing-message-group gnus-message-archive-group)) 1720 (var (or gnus-outgoing-message-group gnus-message-archive-group))
1721 (gcc-self-val 1721 (gcc-self-val
1722 (and group (gnus-group-find-parameter group 'gcc-self) 1722 (and group (not (gnus-virtual-group-p group))
1723 (not (gnus-virtual-group-p group)))) 1723 (gnus-group-find-parameter group 'gcc-self)))
1724 result 1724 result
1725 (groups 1725 (groups
1726 (cond 1726 (cond
diff --git a/lisp/progmodes/octave-inf.el b/lisp/progmodes/octave-inf.el
deleted file mode 100644
index 4a227db7164..00000000000
--- a/lisp/progmodes/octave-inf.el
+++ /dev/null
@@ -1,387 +0,0 @@
1;;; octave-inf.el --- running Octave as an inferior Emacs process
2
3;; Copyright (C) 1997, 2001-2013 Free Software Foundation, Inc.
4
5;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
6;; John Eaton <jwe@bevo.che.wisc.edu>
7;; Maintainer: FSF
8;; Keywords: languages
9;; Package: octave-mod
10
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software: you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25
26;;; Commentary:
27
28;;; Code:
29
30(require 'octave-mod)
31(require 'comint)
32
33(defgroup octave-inferior nil
34 "Running Octave as an inferior Emacs process."
35 :group 'octave)
36
37(defcustom inferior-octave-program "octave"
38 "Program invoked by `inferior-octave'."
39 :type 'string
40 :group 'octave-inferior)
41
42(defcustom inferior-octave-prompt
43 "\\(^octave\\(\\|.bin\\|.exe\\)\\(-[.0-9]+\\)?\\(:[0-9]+\\)?\\|^debug\\|^\\)>+ "
44 "Regexp to match prompts for the inferior Octave process."
45 :type 'regexp
46 :group 'octave-inferior)
47
48(defcustom inferior-octave-startup-file nil
49 "Name of the inferior Octave startup file.
50The contents of this file are sent to the inferior Octave process on
51startup."
52 :type '(choice (const :tag "None" nil)
53 file)
54 :group 'octave-inferior)
55
56(defcustom inferior-octave-startup-args nil
57 "List of command line arguments for the inferior Octave process.
58For example, for suppressing the startup message and using `traditional'
59mode, set this to (\"-q\" \"--traditional\")."
60 :type '(repeat string)
61 :group 'octave-inferior)
62
63(defvar inferior-octave-mode-map
64 (let ((map (make-sparse-keymap)))
65 (set-keymap-parent map comint-mode-map)
66 (define-key map "\t" 'comint-dynamic-complete)
67 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
68 (define-key map "\C-c\C-l" 'inferior-octave-dynamic-list-input-ring)
69 (define-key map [menu-bar inout list-history]
70 '("List Input History" . inferior-octave-dynamic-list-input-ring))
71 ;; FIXME: free C-h so it can do the describe-prefix-bindings.
72 (define-key map "\C-c\C-h" 'info-lookup-symbol)
73 map)
74 "Keymap used in Inferior Octave mode.")
75
76(defvar inferior-octave-mode-syntax-table
77 (let ((table (make-syntax-table octave-mode-syntax-table)))
78 table)
79 "Syntax table in use in inferior-octave-mode buffers.")
80
81(defcustom inferior-octave-mode-hook nil
82 "Hook to be run when Inferior Octave mode is started."
83 :type 'hook
84 :group 'octave-inferior)
85
86(defvar inferior-octave-font-lock-keywords
87 (list
88 (cons inferior-octave-prompt 'font-lock-type-face))
89 ;; Could certainly do more font locking in inferior Octave ...
90 "Additional expressions to highlight in Inferior Octave mode.")
91
92
93;;; Compatibility functions
94(if (not (fboundp 'comint-line-beginning-position))
95 ;; comint-line-beginning-position is defined in Emacs 21
96 (defun comint-line-beginning-position ()
97 "Returns the buffer position of the beginning of the line, after any prompt.
98The prompt is assumed to be any text at the beginning of the line matching
99the regular expression `comint-prompt-regexp', a buffer local variable."
100 (save-excursion (comint-bol nil) (point))))
101
102
103(defvar inferior-octave-output-list nil)
104(defvar inferior-octave-output-string nil)
105(defvar inferior-octave-receive-in-progress nil)
106
107(defvar inferior-octave-startup-hook nil)
108
109(defvar inferior-octave-complete-impossible nil
110 "Non-nil means that `inferior-octave-complete' is impossible.")
111
112(defvar inferior-octave-has-built-in-variables nil
113 "Non-nil means that Octave has built-in variables.")
114
115(defvar inferior-octave-dynamic-complete-functions
116 '(inferior-octave-completion-at-point comint-filename-completion)
117 "List of functions called to perform completion for inferior Octave.
118This variable is used to initialize `comint-dynamic-complete-functions'
119in the Inferior Octave buffer.")
120
121(defvar info-lookup-mode)
122
123(define-derived-mode inferior-octave-mode comint-mode "Inferior Octave"
124 "Major mode for interacting with an inferior Octave process.
125Runs Octave as a subprocess of Emacs, with Octave I/O through an Emacs
126buffer.
127
128Entry to this mode successively runs the hooks `comint-mode-hook' and
129`inferior-octave-mode-hook'."
130 (setq comint-prompt-regexp inferior-octave-prompt
131 mode-line-process '(":%s")
132 local-abbrev-table octave-abbrev-table)
133
134 (set (make-local-variable 'comment-start) octave-comment-start)
135 (set (make-local-variable 'comment-end) "")
136 (set (make-local-variable 'comment-column) 32)
137 (set (make-local-variable 'comment-start-skip) octave-comment-start-skip)
138
139 (set (make-local-variable 'font-lock-defaults)
140 '(inferior-octave-font-lock-keywords nil nil))
141
142 (set (make-local-variable 'info-lookup-mode) 'octave-mode)
143
144 (setq comint-input-ring-file-name
145 (or (getenv "OCTAVE_HISTFILE") "~/.octave_hist")
146 comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024))
147 (set (make-local-variable 'comint-dynamic-complete-functions)
148 inferior-octave-dynamic-complete-functions)
149 (add-hook 'comint-input-filter-functions
150 'inferior-octave-directory-tracker nil t)
151 (comint-read-input-ring t))
152
153;;;###autoload
154(defun inferior-octave (&optional arg)
155 "Run an inferior Octave process, I/O via `inferior-octave-buffer'.
156This buffer is put in Inferior Octave mode. See `inferior-octave-mode'.
157
158Unless ARG is non-nil, switches to this buffer.
159
160The elements of the list `inferior-octave-startup-args' are sent as
161command line arguments to the inferior Octave process on startup.
162
163Additional commands to be executed on startup can be provided either in
164the file specified by `inferior-octave-startup-file' or by the default
165startup file, `~/.emacs-octave'."
166 (interactive "P")
167 (let ((buffer inferior-octave-buffer))
168 (get-buffer-create buffer)
169 (if (comint-check-proc buffer)
170 ()
171 (with-current-buffer buffer
172 (comint-mode)
173 (inferior-octave-startup)
174 (inferior-octave-mode)))
175 (if (not arg)
176 (pop-to-buffer buffer))))
177
178;;;###autoload
179(defalias 'run-octave 'inferior-octave)
180
181(defun inferior-octave-startup ()
182 "Start an inferior Octave process."
183 (let ((proc (comint-exec-1
184 (substring inferior-octave-buffer 1 -1)
185 inferior-octave-buffer
186 inferior-octave-program
187 (append (list "-i" "--no-line-editing")
188 inferior-octave-startup-args))))
189 (set-process-filter proc 'inferior-octave-output-digest)
190 (setq comint-ptyp process-connection-type
191 inferior-octave-process proc
192 inferior-octave-output-list nil
193 inferior-octave-output-string nil
194 inferior-octave-receive-in-progress t)
195
196 ;; This may look complicated ... However, we need to make sure that
197 ;; we additional startup code only AFTER Octave is ready (otherwise,
198 ;; output may be mixed up). Hence, we need to digest the Octave
199 ;; output to see when it issues a prompt.
200 (while inferior-octave-receive-in-progress
201 (accept-process-output inferior-octave-process))
202 (goto-char (point-max))
203 (set-marker (process-mark proc) (point))
204 (insert-before-markers
205 (concat
206 (if (not (bobp)) " \n")
207 (if inferior-octave-output-list
208 (concat (mapconcat
209 'identity inferior-octave-output-list "\n")
210 "\n"))))
211
212 ;; Find out whether Octave has built-in variables.
213 (inferior-octave-send-list-and-digest
214 (list "exist \"LOADPATH\"\n"))
215 (setq inferior-octave-has-built-in-variables
216 (string-match "101$" (car inferior-octave-output-list)))
217
218 ;; An empty secondary prompt, as e.g. obtained by '--braindead',
219 ;; means trouble.
220 (inferior-octave-send-list-and-digest (list "PS2\n"))
221 (if (string-match "\\(PS2\\|ans\\) = *$" (car inferior-octave-output-list))
222 (inferior-octave-send-list-and-digest
223 (list (if inferior-octave-has-built-in-variables
224 "PS2 = \"> \"\n"
225 "PS2 (\"> \");\n"))))
226
227 ;; O.k., now we are ready for the Inferior Octave startup commands.
228 (let* (commands
229 (program (file-name-nondirectory inferior-octave-program))
230 (file (or inferior-octave-startup-file
231 (concat "~/.emacs-" program))))
232 (setq commands
233 (list "more off;\n"
234 (if (not (string-equal
235 inferior-octave-output-string ">> "))
236 (if inferior-octave-has-built-in-variables
237 "PS1=\"\\\\s> \";\n"
238 "PS1 (\"\\\\s> \");\n"))
239 (if (file-exists-p file)
240 (format "source (\"%s\");\n" file))))
241 (inferior-octave-send-list-and-digest commands))
242 (insert-before-markers
243 (concat
244 (if inferior-octave-output-list
245 (concat (mapconcat
246 'identity inferior-octave-output-list "\n")
247 "\n"))
248 inferior-octave-output-string))
249 ;; Next, we check whether Octave supports `completion_matches' ...
250 (inferior-octave-send-list-and-digest
251 (list "exist \"completion_matches\"\n"))
252 (setq inferior-octave-complete-impossible
253 (not (string-match "5$" (car inferior-octave-output-list))))
254
255 ;; And finally, everything is back to normal.
256 (set-process-filter proc 'inferior-octave-output-filter)
257 (run-hooks 'inferior-octave-startup-hook)
258 (run-hooks 'inferior-octave-startup-hook)
259 ;; Just in case, to be sure a cd in the startup file
260 ;; won't have detrimental effects.
261 (inferior-octave-resync-dirs)))
262
263
264(defun inferior-octave-completion-at-point ()
265 "Return the data to complete the Octave symbol at point."
266 (let* ((end (point))
267 (start
268 (save-excursion
269 (skip-syntax-backward "w_" (comint-line-beginning-position))
270 (point))))
271 (cond ((eq start end) nil)
272 (inferior-octave-complete-impossible
273 (message (concat
274 "Your Octave does not have `completion_matches'. "
275 "Please upgrade to version 2.X."))
276 nil)
277 (t
278 (list
279 start end
280 (completion-table-dynamic
281 (lambda (command)
282 (inferior-octave-send-list-and-digest
283 (list (concat "completion_matches (\"" command "\");\n")))
284 (sort (delete-dups inferior-octave-output-list)
285 'string-lessp))))))))
286
287(define-obsolete-function-alias 'inferior-octave-complete
288 'completion-at-point "24.1")
289
290(defun inferior-octave-dynamic-list-input-ring ()
291 "List the buffer's input history in a help buffer."
292 ;; We cannot use `comint-dynamic-list-input-ring', because it replaces
293 ;; "completion" by "history reference" ...
294 (interactive)
295 (if (or (not (ring-p comint-input-ring))
296 (ring-empty-p comint-input-ring))
297 (message "No history")
298 (let ((history nil)
299 (history-buffer " *Input History*")
300 (index (1- (ring-length comint-input-ring)))
301 (conf (current-window-configuration)))
302 ;; We have to build up a list ourselves from the ring vector.
303 (while (>= index 0)
304 (setq history (cons (ring-ref comint-input-ring index) history)
305 index (1- index)))
306 ;; Change "completion" to "history reference"
307 ;; to make the display accurate.
308 (with-output-to-temp-buffer history-buffer
309 (display-completion-list history)
310 (set-buffer history-buffer))
311 (message "Hit space to flush")
312 (let ((ch (read-event)))
313 (if (eq ch ?\ )
314 (set-window-configuration conf)
315 (setq unread-command-events (list ch)))))))
316
317(defun inferior-octave-strip-ctrl-g (string)
318 "Strip leading `^G' character.
319If STRING starts with a `^G', ring the bell and strip it."
320 (if (string-match "^\a" string)
321 (progn
322 (ding)
323 (setq string (substring string 1))))
324 string)
325
326(defun inferior-octave-output-filter (proc string)
327 "Standard output filter for the inferior Octave process.
328Ring Emacs bell if process output starts with an ASCII bell, and pass
329the rest to `comint-output-filter'."
330 (comint-output-filter proc (inferior-octave-strip-ctrl-g string)))
331
332(defun inferior-octave-output-digest (_proc string)
333 "Special output filter for the inferior Octave process.
334Save all output between newlines into `inferior-octave-output-list', and
335the rest to `inferior-octave-output-string'."
336 (setq string (concat inferior-octave-output-string string))
337 (while (string-match "\n" string)
338 (setq inferior-octave-output-list
339 (append inferior-octave-output-list
340 (list (substring string 0 (match-beginning 0))))
341 string (substring string (match-end 0))))
342 (if (string-match inferior-octave-prompt string)
343 (setq inferior-octave-receive-in-progress nil))
344 (setq inferior-octave-output-string string))
345
346(defun inferior-octave-send-list-and-digest (list)
347 "Send LIST to the inferior Octave process and digest the output.
348The elements of LIST have to be strings and are sent one by one. All
349output is passed to the filter `inferior-octave-output-digest'."
350 (let* ((proc inferior-octave-process)
351 string)
352 (add-function :override (process-filter proc)
353 #'inferior-octave-output-digest)
354 (setq inferior-octave-output-list nil)
355 (unwind-protect
356 (while (setq string (car list))
357 (setq inferior-octave-output-string nil
358 inferior-octave-receive-in-progress t)
359 (comint-send-string proc string)
360 (while inferior-octave-receive-in-progress
361 (accept-process-output proc))
362 (setq list (cdr list)))
363 (remove-function (process-filter proc)
364 #'inferior-octave-output-digest))))
365
366(defun inferior-octave-directory-tracker (string)
367 "Tracks `cd' commands issued to the inferior Octave process.
368Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused."
369 (cond
370 ((string-match "^[ \t]*cd[ \t;]*$" string)
371 (cd "~"))
372 ((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
373 (cd (substring string (match-beginning 1) (match-end 1))))))
374
375(defun inferior-octave-resync-dirs ()
376 "Resync the buffer's idea of the current directory.
377This command queries the inferior Octave process about its current
378directory and makes this the current buffer's default directory."
379 (interactive)
380 (inferior-octave-send-list-and-digest '("disp (pwd ())\n"))
381 (cd (car inferior-octave-output-list)))
382
383;;; provide ourself
384
385(provide 'octave-inf)
386
387;;; octave-inf.el ends here
diff --git a/lisp/progmodes/octave-mod.el b/lisp/progmodes/octave.el
index d161754cad9..640775bfe8b 100644
--- a/lisp/progmodes/octave-mod.el
+++ b/lisp/progmodes/octave.el
@@ -1,4 +1,4 @@
1;;; octave-mod.el --- editing Octave source files under Emacs 1;;; octave.el --- editing octave source files under emacs -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 1997, 2001-2013 Free Software Foundation, Inc. 3;; Copyright (C) 1997, 2001-2013 Free Software Foundation, Inc.
4 4
@@ -24,33 +24,23 @@
24 24
25;;; Commentary: 25;;; Commentary:
26 26
27;; This package provides Emacs support for Octave. 27;; This package provides emacs support for octave. It defines a major
28;; It defines Octave mode, a major mode for editing 28;; mode for editing octave code and contains code for interacting with
29;; Octave code. 29;; an inferior octave process using comint.
30 30
31;; The file octave-inf.el contains code for interacting with an inferior 31;; See the documentation of `octave-mode' and `run-octave' for further
32;; Octave process using comint. 32;; information on usage and customization.
33
34;; See the documentation of `octave-mode' and
35;; `run-octave' for further information on usage and customization.
36 33
37;;; Code: 34;;; Code:
38(require 'custom) 35(require 'comint)
39 36
40(defgroup octave nil 37(defgroup octave nil
41 "Major mode for editing Octave source files." 38 "Editing Octave code."
42 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) 39 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
43 :group 'languages) 40 :group 'languages)
44 41
45(defvar inferior-octave-output-list nil) 42(define-obsolete-function-alias 'octave-submit-bug-report
46(defvar inferior-octave-output-string nil) 43 'report-emacs-bug "24.4")
47(defvar inferior-octave-receive-in-progress nil)
48
49(declare-function inferior-octave-send-list-and-digest "octave-inf" (list))
50
51(defconst octave-maintainer-address
52 "Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>, bug-gnu-emacs@gnu.org"
53 "Current maintainer of the Emacs Octave package.")
54 44
55(define-abbrev-table 'octave-abbrev-table 45(define-abbrev-table 'octave-abbrev-table
56 (mapcar (lambda (e) (append e '(nil 0 t))) 46 (mapcar (lambda (e) (append e '(nil 0 t)))
@@ -84,7 +74,7 @@
84 ("`upc" "unwind_protect_cleanup") 74 ("`upc" "unwind_protect_cleanup")
85 ("`w" "while ()"))) 75 ("`w" "while ()")))
86 "Abbrev table for Octave's reserved words. 76 "Abbrev table for Octave's reserved words.
87Used in `octave-mode' and inferior-octave-mode buffers. 77Used in `octave-mode' and `inferior-octave-mode' buffers.
88All Octave abbrevs start with a grave accent (`)." 78All Octave abbrevs start with a grave accent (`)."
89 :regexp "\\(?:[^`]\\|^\\)\\(\\(?:\\<\\|`\\)\\w+\\)\\W*") 79 :regexp "\\(?:[^`]\\|^\\)\\(\\(?:\\<\\|`\\)\\w+\\)\\W*")
90 80
@@ -156,6 +146,7 @@ All Octave abbrevs start with a grave accent (`)."
156The string `function' and its name are given by the first and third 146The string `function' and its name are given by the first and third
157parenthetical grouping.") 147parenthetical grouping.")
158 148
149
159(defvar octave-font-lock-keywords 150(defvar octave-font-lock-keywords
160 (list 151 (list
161 ;; Fontify all builtin keywords. 152 ;; Fontify all builtin keywords.
@@ -201,12 +192,6 @@ parenthetical grouping.")
201 (put-text-property (match-beginning 1) (match-end 1) 192 (put-text-property (match-beginning 1) (match-end 1)
202 'syntax-table (string-to-syntax "\"'"))))) 193 'syntax-table (string-to-syntax "\"'")))))
203 194
204(defcustom inferior-octave-buffer "*Inferior Octave*"
205 "Name of buffer for running an inferior Octave process."
206 :type 'string
207 :group 'octave-inferior)
208
209(defvar inferior-octave-process nil)
210 195
211(defvar octave-mode-map 196(defvar octave-mode-map
212 (let ((map (make-sparse-keymap))) 197 (let ((map (make-sparse-keymap)))
@@ -344,12 +329,6 @@ newline or semicolon after an else or end keyword."
344 :type 'string 329 :type 'string
345 :group 'octave) 330 :group 'octave)
346 331
347(defvar octave-completion-alist nil
348 "Alist of Octave symbols for completion in Octave mode.
349Each element looks like (VAR . VAR), where the car and cdr are the same
350symbol (an Octave command or variable name).
351Currently, only builtin variables can be completed.")
352
353(defvar octave-mode-imenu-generic-expression 332(defvar octave-mode-imenu-generic-expression
354 (list 333 (list
355 ;; Functions 334 ;; Functions
@@ -605,72 +584,415 @@ including a reproducible test case and send the message."
605 (smie-setup octave-smie-grammar #'octave-smie-rules 584 (smie-setup octave-smie-grammar #'octave-smie-rules
606 :forward-token #'octave-smie-forward-token 585 :forward-token #'octave-smie-forward-token
607 :backward-token #'octave-smie-backward-token) 586 :backward-token #'octave-smie-backward-token)
608 (set (make-local-variable 'smie-indent-basic) 'octave-block-offset) 587 (setq-local smie-indent-basic 'octave-block-offset)
609 588
610 (set (make-local-variable 'smie-blink-matching-triggers) 589 (setq-local smie-blink-matching-triggers
611 (cons ?\; smie-blink-matching-triggers)) 590 (cons ?\; smie-blink-matching-triggers))
612 (unless octave-blink-matching-block 591 (unless octave-blink-matching-block
613 (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local)) 592 (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
614 593
615 (set (make-local-variable 'electric-indent-chars) 594 (setq-local electric-indent-chars
616 (cons ?\; electric-indent-chars)) 595 (cons ?\; electric-indent-chars))
617 ;; IIUC matlab-mode takes the opposite approach: it makes RET insert 596 ;; IIUC matlab-mode takes the opposite approach: it makes RET insert
618 ;; a ";" at those places where it's correct (i.e. outside of parens). 597 ;; a ";" at those places where it's correct (i.e. outside of parens).
619 (set (make-local-variable 'electric-layout-rules) '((?\; . after))) 598 (setq-local electric-layout-rules '((?\; . after)))
620 599
621 (set (make-local-variable 'comment-start) octave-comment-start) 600 (setq-local comment-start octave-comment-start)
622 (set (make-local-variable 'comment-end) "") 601 (setq-local comment-end "")
623 ;; Don't set it here: it's not really a property of the language, 602 ;; Don't set it here: it's not really a property of the language,
624 ;; just a personal preference of the author. 603 ;; just a personal preference of the author.
625 ;; (set (make-local-variable 'comment-column) 32) 604 ;; (setq-local comment-column 32)
626 (set (make-local-variable 'comment-start-skip) "\\s<+\\s-*") 605 (setq-local comment-start-skip "\\s<+\\s-*")
627 (set (make-local-variable 'comment-add) 1) 606 (setq-local comment-add 1)
628 607
629 (set (make-local-variable 'parse-sexp-ignore-comments) t) 608 (setq-local parse-sexp-ignore-comments t)
630 (set (make-local-variable 'paragraph-start) 609 (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter))
631 (concat "\\s-*$\\|" page-delimiter)) 610 (setq-local paragraph-separate paragraph-start)
632 (set (make-local-variable 'paragraph-separate) paragraph-start) 611 (setq-local paragraph-ignore-fill-prefix t)
633 (set (make-local-variable 'paragraph-ignore-fill-prefix) t) 612 (setq-local fill-paragraph-function 'octave-fill-paragraph)
634 (set (make-local-variable 'fill-paragraph-function) 'octave-fill-paragraph)
635 ;; FIXME: Why disable it? 613 ;; FIXME: Why disable it?
636 ;; (set (make-local-variable 'adaptive-fill-regexp) nil) 614 ;; (setq-local adaptive-fill-regexp nil)
637 ;; Again, this is not a property of the language, don't set it here. 615 ;; Again, this is not a property of the language, don't set it here.
638 ;; (set (make-local-variable 'fill-column) 72) 616 ;; (setq fill-column 72)
639 (set (make-local-variable 'normal-auto-fill-function) 'octave-auto-fill) 617 (setq-local normal-auto-fill-function 'octave-auto-fill)
640 618
641 (set (make-local-variable 'font-lock-defaults) 619 (setq font-lock-defaults '(octave-font-lock-keywords))
642 '(octave-font-lock-keywords))
643 620
644 (set (make-local-variable 'syntax-propertize-function) 621 (setq-local syntax-propertize-function #'octave-syntax-propertize-function)
645 #'octave-syntax-propertize-function)
646 622
647 (set (make-local-variable 'imenu-generic-expression) 623 (setq imenu-generic-expression octave-mode-imenu-generic-expression)
648 octave-mode-imenu-generic-expression) 624 (setq imenu-case-fold-search nil)
649 (set (make-local-variable 'imenu-case-fold-search) nil)
650 625
651 (add-hook 'completion-at-point-functions 626 (add-hook 'completion-at-point-functions
652 'octave-completion-at-point-function nil t) 627 'octave-completion-at-point-function nil t)
653 (set (make-local-variable 'beginning-of-defun-function) 628 (setq-local beginning-of-defun-function 'octave-beginning-of-defun)
654 'octave-beginning-of-defun) 629
630 (easy-menu-add octave-mode-menu))
631
632
633(defcustom inferior-octave-program "octave"
634 "Program invoked by `inferior-octave'."
635 :type 'string
636 :group 'octave)
637
638(defcustom inferior-octave-buffer "*Inferior Octave*"
639 "Name of buffer for running an inferior Octave process."
640 :type 'string
641 :group 'octave)
642
643(defcustom inferior-octave-prompt
644 "\\(^octave\\(\\|.bin\\|.exe\\)\\(-[.0-9]+\\)?\\(:[0-9]+\\)?\\|^debug\\|^\\)>+ "
645 "Regexp to match prompts for the inferior Octave process."
646 :type 'regexp
647 :group 'octave)
648
649(defcustom inferior-octave-startup-file nil
650 "Name of the inferior Octave startup file.
651The contents of this file are sent to the inferior Octave process on
652startup."
653 :type '(choice (const :tag "None" nil)
654 file)
655 :group 'octave)
656
657(defcustom inferior-octave-startup-args nil
658 "List of command line arguments for the inferior Octave process.
659For example, for suppressing the startup message and using `traditional'
660mode, set this to (\"-q\" \"--traditional\")."
661 :type '(repeat string)
662 :group 'octave)
663
664(defcustom inferior-octave-mode-hook nil
665 "Hook to be run when Inferior Octave mode is started."
666 :type 'hook
667 :group 'octave)
668
669(defvar inferior-octave-process nil)
670
671(defvar inferior-octave-mode-map
672 (let ((map (make-sparse-keymap)))
673 (set-keymap-parent map comint-mode-map)
674 (define-key map "\t" 'comint-dynamic-complete)
675 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
676 (define-key map "\C-c\C-l" 'inferior-octave-dynamic-list-input-ring)
677 (define-key map [menu-bar inout list-history]
678 '("List Input History" . inferior-octave-dynamic-list-input-ring))
679 map)
680 "Keymap used in Inferior Octave mode.")
681
682(defvar inferior-octave-mode-syntax-table
683 (let ((table (make-syntax-table octave-mode-syntax-table)))
684 table)
685 "Syntax table in use in inferior-octave-mode buffers.")
686
687(defvar inferior-octave-font-lock-keywords
688 (list
689 (cons inferior-octave-prompt 'font-lock-type-face))
690 ;; Could certainly do more font locking in inferior Octave ...
691 "Additional expressions to highlight in Inferior Octave mode.")
692
693
694;;; Compatibility functions
695(if (not (fboundp 'comint-line-beginning-position))
696 ;; comint-line-beginning-position is defined in Emacs 21
697 (defun comint-line-beginning-position ()
698 "Returns the buffer position of the beginning of the line, after any prompt.
699The prompt is assumed to be any text at the beginning of the line matching
700the regular expression `comint-prompt-regexp', a buffer local variable."
701 (save-excursion (comint-bol nil) (point))))
702
703
704(defvar inferior-octave-output-list nil)
705(defvar inferior-octave-output-string nil)
706(defvar inferior-octave-receive-in-progress nil)
707
708(defvar inferior-octave-startup-hook nil)
709
710(defvar inferior-octave-complete-impossible nil
711 "Non-nil means that `inferior-octave-complete' is impossible.")
712
713(defvar inferior-octave-has-built-in-variables nil
714 "Non-nil means that Octave has built-in variables.")
715
716(defvar inferior-octave-dynamic-complete-functions
717 '(inferior-octave-completion-at-point comint-filename-completion)
718 "List of functions called to perform completion for inferior Octave.
719This variable is used to initialize `comint-dynamic-complete-functions'
720in the Inferior Octave buffer.")
721
722(defvar info-lookup-mode)
723
724(define-derived-mode inferior-octave-mode comint-mode "Inferior Octave"
725 "Major mode for interacting with an inferior Octave process.
726Runs Octave as a subprocess of Emacs, with Octave I/O through an Emacs
727buffer.
728
729Entry to this mode successively runs the hooks `comint-mode-hook' and
730`inferior-octave-mode-hook'."
731 (setq comint-prompt-regexp inferior-octave-prompt
732 mode-line-process '(":%s")
733 local-abbrev-table octave-abbrev-table)
734
735 (setq-local comment-start octave-comment-start)
736 (setq-local comment-end "")
737 (setq comment-column 32)
738 (setq-local comment-start-skip octave-comment-start-skip)
739
740 (setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
741
742 (setq info-lookup-mode 'octave-mode)
743
744 (setq comint-input-ring-file-name
745 (or (getenv "OCTAVE_HISTFILE") "~/.octave_hist")
746 comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024))
747 (setq-local comint-dynamic-complete-functions
748 inferior-octave-dynamic-complete-functions)
749 (add-hook 'comint-input-filter-functions
750 'inferior-octave-directory-tracker nil t)
751 (comint-read-input-ring t))
752
753;;;###autoload
754(defun inferior-octave (&optional arg)
755 "Run an inferior Octave process, I/O via `inferior-octave-buffer'.
756This buffer is put in Inferior Octave mode. See `inferior-octave-mode'.
757
758Unless ARG is non-nil, switches to this buffer.
759
760The elements of the list `inferior-octave-startup-args' are sent as
761command line arguments to the inferior Octave process on startup.
762
763Additional commands to be executed on startup can be provided either in
764the file specified by `inferior-octave-startup-file' or by the default
765startup file, `~/.emacs-octave'."
766 (interactive "P")
767 (let ((buffer inferior-octave-buffer))
768 (get-buffer-create buffer)
769 (if (comint-check-proc buffer)
770 ()
771 (with-current-buffer buffer
772 (comint-mode)
773 (inferior-octave-startup)
774 (inferior-octave-mode)))
775 (if (not arg)
776 (pop-to-buffer buffer))))
777
778;;;###autoload
779(defalias 'run-octave 'inferior-octave)
780
781(defun inferior-octave-startup ()
782 "Start an inferior Octave process."
783 (let ((proc (comint-exec-1
784 (substring inferior-octave-buffer 1 -1)
785 inferior-octave-buffer
786 inferior-octave-program
787 (append (list "-i" "--no-line-editing")
788 inferior-octave-startup-args))))
789 (set-process-filter proc 'inferior-octave-output-digest)
790 (setq comint-ptyp process-connection-type
791 inferior-octave-process proc
792 inferior-octave-output-list nil
793 inferior-octave-output-string nil
794 inferior-octave-receive-in-progress t)
795
796 ;; This may look complicated ... However, we need to make sure that
797 ;; we additional startup code only AFTER Octave is ready (otherwise,
798 ;; output may be mixed up). Hence, we need to digest the Octave
799 ;; output to see when it issues a prompt.
800 (while inferior-octave-receive-in-progress
801 (accept-process-output inferior-octave-process))
802 (goto-char (point-max))
803 (set-marker (process-mark proc) (point))
804 (insert-before-markers
805 (concat
806 (if (not (bobp)) " \n")
807 (if inferior-octave-output-list
808 (concat (mapconcat
809 'identity inferior-octave-output-list "\n")
810 "\n"))))
811
812 ;; Find out whether Octave has built-in variables.
813 (inferior-octave-send-list-and-digest
814 (list "exist \"LOADPATH\"\n"))
815 (setq inferior-octave-has-built-in-variables
816 (string-match "101$" (car inferior-octave-output-list)))
817
818 ;; An empty secondary prompt, as e.g. obtained by '--braindead',
819 ;; means trouble.
820 (inferior-octave-send-list-and-digest (list "PS2\n"))
821 (if (string-match "\\(PS2\\|ans\\) = *$" (car inferior-octave-output-list))
822 (inferior-octave-send-list-and-digest
823 (list (if inferior-octave-has-built-in-variables
824 "PS2 = \"> \"\n"
825 "PS2 (\"> \");\n"))))
826
827 ;; O.k., now we are ready for the Inferior Octave startup commands.
828 (let* (commands
829 (program (file-name-nondirectory inferior-octave-program))
830 (file (or inferior-octave-startup-file
831 (concat "~/.emacs-" program))))
832 (setq commands
833 (list "more off;\n"
834 (if (not (string-equal
835 inferior-octave-output-string ">> "))
836 (if inferior-octave-has-built-in-variables
837 "PS1=\"\\\\s> \";\n"
838 "PS1 (\"\\\\s> \");\n"))
839 (if (file-exists-p file)
840 (format "source (\"%s\");\n" file))))
841 (inferior-octave-send-list-and-digest commands))
842 (insert-before-markers
843 (concat
844 (if inferior-octave-output-list
845 (concat (mapconcat
846 'identity inferior-octave-output-list "\n")
847 "\n"))
848 inferior-octave-output-string))
849 ;; Next, we check whether Octave supports `completion_matches' ...
850 (inferior-octave-send-list-and-digest
851 (list "exist \"completion_matches\"\n"))
852 (setq inferior-octave-complete-impossible
853 (not (string-match "5$" (car inferior-octave-output-list))))
854
855 ;; And finally, everything is back to normal.
856 (set-process-filter proc 'inferior-octave-output-filter)
857 (run-hooks 'inferior-octave-startup-hook)
858 (run-hooks 'inferior-octave-startup-hook)
859 ;; Just in case, to be sure a cd in the startup file
860 ;; won't have detrimental effects.
861 (inferior-octave-resync-dirs)))
862
863(defun inferior-octave-completion-table ()
864 (unless inferior-octave-complete-impossible
865 (completion-table-dynamic
866 (lambda (command)
867 (inferior-octave-send-list-and-digest
868 (list (concat "completion_matches (\"" command "\");\n")))
869 (sort (delete-dups inferior-octave-output-list)
870 'string-lessp)))))
871
872(defun inferior-octave-completion-at-point ()
873 "Return the data to complete the Octave symbol at point."
874 (let* ((end (point))
875 (start
876 (save-excursion
877 (skip-syntax-backward "w_" (comint-line-beginning-position))
878 (point))))
879 (cond ((eq start end) nil)
880 (inferior-octave-complete-impossible
881 (message (concat
882 "Your Octave does not have `completion_matches'. "
883 "Please upgrade to version 2.X."))
884 nil)
885 (t (list start end (inferior-octave-completion-table))))))
886
887(define-obsolete-function-alias 'inferior-octave-complete
888 'completion-at-point "24.1")
889
890(defun inferior-octave-dynamic-list-input-ring ()
891 "List the buffer's input history in a help buffer."
892 ;; We cannot use `comint-dynamic-list-input-ring', because it replaces
893 ;; "completion" by "history reference" ...
894 (interactive)
895 (if (or (not (ring-p comint-input-ring))
896 (ring-empty-p comint-input-ring))
897 (message "No history")
898 (let ((history nil)
899 (history-buffer " *Input History*")
900 (index (1- (ring-length comint-input-ring)))
901 (conf (current-window-configuration)))
902 ;; We have to build up a list ourselves from the ring vector.
903 (while (>= index 0)
904 (setq history (cons (ring-ref comint-input-ring index) history)
905 index (1- index)))
906 ;; Change "completion" to "history reference"
907 ;; to make the display accurate.
908 (with-output-to-temp-buffer history-buffer
909 (display-completion-list history)
910 (set-buffer history-buffer))
911 (message "Hit space to flush")
912 (let ((ch (read-event)))
913 (if (eq ch ?\ )
914 (set-window-configuration conf)
915 (setq unread-command-events (list ch)))))))
916
917(defun inferior-octave-strip-ctrl-g (string)
918 "Strip leading `^G' character.
919If STRING starts with a `^G', ring the bell and strip it."
920 (if (string-match "^\a" string)
921 (progn
922 (ding)
923 (setq string (substring string 1))))
924 string)
925
926(defun inferior-octave-output-filter (proc string)
927 "Standard output filter for the inferior Octave process.
928Ring Emacs bell if process output starts with an ASCII bell, and pass
929the rest to `comint-output-filter'."
930 (comint-output-filter proc (inferior-octave-strip-ctrl-g string)))
931
932(defun inferior-octave-output-digest (_proc string)
933 "Special output filter for the inferior Octave process.
934Save all output between newlines into `inferior-octave-output-list', and
935the rest to `inferior-octave-output-string'."
936 (setq string (concat inferior-octave-output-string string))
937 (while (string-match "\n" string)
938 (setq inferior-octave-output-list
939 (append inferior-octave-output-list
940 (list (substring string 0 (match-beginning 0))))
941 string (substring string (match-end 0))))
942 (if (string-match inferior-octave-prompt string)
943 (setq inferior-octave-receive-in-progress nil))
944 (setq inferior-octave-output-string string))
945
946(defun inferior-octave-send-list-and-digest (list)
947 "Send LIST to the inferior Octave process and digest the output.
948The elements of LIST have to be strings and are sent one by one. All
949output is passed to the filter `inferior-octave-output-digest'."
950 (let* ((proc inferior-octave-process)
951 (filter (process-filter proc))
952 string)
953 (set-process-filter proc 'inferior-octave-output-digest)
954 (setq inferior-octave-output-list nil)
955 (unwind-protect
956 (while (setq string (car list))
957 (setq inferior-octave-output-string nil
958 inferior-octave-receive-in-progress t)
959 (comint-send-string proc string)
960 (while inferior-octave-receive-in-progress
961 (accept-process-output proc))
962 (setq list (cdr list)))
963 (set-process-filter proc filter))))
964
965(defun inferior-octave-directory-tracker (string)
966 "Tracks `cd' commands issued to the inferior Octave process.
967Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused."
968 (cond
969 ((string-match "^[ \t]*cd[ \t;]*$" string)
970 (cd "~"))
971 ((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
972 (cd (substring string (match-beginning 1) (match-end 1))))))
973
974(defun inferior-octave-resync-dirs ()
975 "Resync the buffer's idea of the current directory.
976This command queries the inferior Octave process about its current
977directory and makes this the current buffer's default directory."
978 (interactive)
979 (inferior-octave-send-list-and-digest '("disp (pwd ())\n"))
980 (cd (car inferior-octave-output-list)))
655 981
656 (easy-menu-add octave-mode-menu)
657 (octave-initialize-completions))
658 982
659;;; Miscellaneous useful functions 983;;; Miscellaneous useful functions
660 984
661(defsubst octave-in-comment-p () 985(defun octave-in-comment-p ()
662 "Return t if point is inside an Octave comment." 986 "Return non-nil if point is inside an Octave comment."
663 (nth 4 (syntax-ppss))) 987 (nth 4 (syntax-ppss)))
664 988
665(defsubst octave-in-string-p () 989(defun octave-in-string-p ()
666 "Return t if point is inside an Octave string." 990 "Return non-nil if point is inside an Octave string."
667 (nth 3 (syntax-ppss))) 991 (nth 3 (syntax-ppss)))
668 992
669(defsubst octave-not-in-string-or-comment-p () 993(defun octave-in-string-or-comment-p ()
670 "Return t if point is not inside an Octave string or comment." 994 "Return non-nil if point is inside an Octave string or comment."
671 (let ((pps (syntax-ppss))) 995 (nth 8 (syntax-ppss)))
672 (not (or (nth 3 pps) (nth 4 pps)))))
673
674 996
675(defun octave-looking-at-kw (regexp) 997(defun octave-looking-at-kw (regexp)
676 "Like `looking-at', but sets `case-fold-search' nil." 998 "Like `looking-at', but sets `case-fold-search' nil."
@@ -818,8 +1140,8 @@ Returns t unless search stops at the beginning or end of the buffer."
818 (while (and (/= arg 0) 1140 (while (and (/= arg 0)
819 (setq found 1141 (setq found
820 (re-search-backward "\\_<function\\_>" inc))) 1142 (re-search-backward "\\_<function\\_>" inc)))
821 (if (octave-not-in-string-or-comment-p) 1143 (unless (octave-in-string-or-comment-p)
822 (setq arg (- arg inc)))) 1144 (setq arg (- arg inc))))
823 (if found 1145 (if found
824 (progn 1146 (progn
825 (and (< inc 0) (goto-char (match-beginning 0))) 1147 (and (< inc 0) (goto-char (match-beginning 0)))
@@ -959,14 +1281,6 @@ otherwise."
959 1281
960 1282
961;;; Completions 1283;;; Completions
962(defun octave-initialize-completions ()
963 "Create an alist for Octave completions."
964 (if octave-completion-alist
965 ()
966 (setq octave-completion-alist
967 (append octave-reserved-words
968 octave-text-functions
969 octave-variables))))
970 1284
971(defun octave-completion-at-point-function () 1285(defun octave-completion-at-point-function ()
972 "Find the text to complete and the corresponding table." 1286 "Find the text to complete and the corresponding table."
@@ -976,7 +1290,12 @@ otherwise."
976 ;; Extend region past point, if applicable. 1290 ;; Extend region past point, if applicable.
977 (save-excursion (skip-syntax-forward "w_") 1291 (save-excursion (skip-syntax-forward "w_")
978 (setq end (point)))) 1292 (setq end (point))))
979 (list beg end octave-completion-alist))) 1293 (list beg end (or (and inferior-octave-process
1294 (process-live-p inferior-octave-process)
1295 (inferior-octave-completion-table))
1296 (append octave-reserved-words
1297 octave-text-functions
1298 octave-variables)))))
980 1299
981(define-obsolete-function-alias 'octave-complete-symbol 1300(define-obsolete-function-alias 'octave-complete-symbol
982 'completion-at-point "24.1") 1301 'completion-at-point "24.1")
@@ -1002,7 +1321,7 @@ Note that all Octave mode abbrevs start with a grave accent."
1002 "Insert an Octave function skeleton. 1321 "Insert an Octave function skeleton.
1003Prompt for the function's name, arguments and return values (to be 1322Prompt for the function's name, arguments and return values (to be
1004entered without parens)." 1323entered without parens)."
1005 (let* ((defname (substring (buffer-name) 0 -2)) 1324 (let* ((defname (file-name-sans-extension (buffer-name)))
1006 (name (read-string (format "Function name (default %s): " defname) 1325 (name (read-string (format "Function name (default %s): " defname)
1007 nil nil defname)) 1326 nil nil defname))
1008 (args (read-string "Arguments: ")) 1327 (args (read-string "Arguments: "))
@@ -1122,29 +1441,7 @@ code line."
1122 "\n"))) 1441 "\n")))
1123 (mapconcat 'identity inferior-octave-output-list "\n"))) 1442 (mapconcat 'identity inferior-octave-output-list "\n")))
1124 (terpri))) 1443 (terpri)))
1125 1444
1126;;; Bug reporting 1445
1127(defun octave-submit-bug-report () 1446(provide 'octave)
1128 "Submit a bug report on the Emacs Octave package via mail." 1447;;; octave.el ends here
1129 (interactive)
1130 (require 'reporter)
1131 (and
1132 (y-or-n-p "Do you want to submit a bug report? ")
1133 (reporter-submit-bug-report
1134 octave-maintainer-address
1135 (concat "Emacs version " emacs-version)
1136 (list
1137 'octave-blink-matching-block
1138 'octave-block-offset
1139 'octave-comment-char
1140 'octave-continuation-offset
1141 'octave-continuation-string
1142 'octave-send-echo-input
1143 'octave-send-line-auto-forward
1144 'octave-send-show-buffer))))
1145
1146;; provide ourself
1147
1148(provide 'octave-mod)
1149
1150;;; octave-mod.el ends here
diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el
index d87c8f48dcf..e608ea8af0e 100644
--- a/lisp/progmodes/opascal.el
+++ b/lisp/progmodes/opascal.el
@@ -110,29 +110,6 @@ end; end;"
110regardless of where in the line point is when the TAB command is used." 110regardless of where in the line point is when the TAB command is used."
111 :type 'boolean) 111 :type 'boolean)
112 112
113(define-obsolete-variable-alias
114 'delphi-comment-face 'opascal-comment-face "24.4")
115(defcustom opascal-comment-face 'font-lock-comment-face
116 "Face used to color OPascal comments."
117 :type 'face)
118
119(define-obsolete-variable-alias
120 'delphi-string-face 'opascal-string-face "24.4")
121(defcustom opascal-string-face 'font-lock-string-face
122 "Face used to color OPascal strings."
123 :type 'face)
124
125(define-obsolete-variable-alias
126 'delphi-keyword-face 'opascal-keyword-face "24.4")
127(defcustom opascal-keyword-face 'font-lock-keyword-face
128 "Face used to color OPascal keywords."
129 :type 'face)
130
131(define-obsolete-variable-alias 'delphi-other-face 'opascal-other-face "24.4")
132(defcustom opascal-other-face nil
133 "Face used to color everything else."
134 :type '(choice (const :tag "None" nil) face))
135
136(defconst opascal-directives 113(defconst opascal-directives
137 '(absolute abstract assembler automated cdecl default dispid dynamic 114 '(absolute abstract assembler automated cdecl default dispid dynamic
138 export external far forward index inline message name near nodefault 115 export external far forward index inline message name near nodefault
@@ -274,6 +251,21 @@ routine.")
274(defconst opascal-leading-spaces-re (concat "^" opascal-spaces-re)) 251(defconst opascal-leading-spaces-re (concat "^" opascal-spaces-re))
275(defconst opascal-word-chars "a-zA-Z0-9_") 252(defconst opascal-word-chars "a-zA-Z0-9_")
276 253
254(defvar opascal-mode-syntax-table
255 (let ((st (make-syntax-table)))
256 ;; Strings.
257 (modify-syntax-entry ?\" "\"" st)
258 (modify-syntax-entry ?\' "\"" st)
259 ;; Comments.
260 (modify-syntax-entry ?\{ "<" st)
261 (modify-syntax-entry ?\} ">" st)
262 (modify-syntax-entry ?\( "()1" st)
263 (modify-syntax-entry ?\) ")(4" st)
264 (modify-syntax-entry ?* ". 23b" st)
265 (modify-syntax-entry ?/ ". 12c" st)
266 (modify-syntax-entry ?\n "> c" st)
267 st))
268
277(defmacro opascal-save-excursion (&rest forms) 269(defmacro opascal-save-excursion (&rest forms)
278 ;; Executes the forms such that any movements have no effect, including 270 ;; Executes the forms such that any movements have no effect, including
279 ;; searches. 271 ;; searches.
@@ -283,13 +275,6 @@ routine.")
283 (deactivate-mark nil)) 275 (deactivate-mark nil))
284 (progn ,@forms))))) 276 (progn ,@forms)))))
285 277
286(defmacro opascal-save-state (&rest forms)
287 ;; Executes the forms such that any buffer modifications do not have any side
288 ;; effects beyond the buffer's actual content changes.
289 `(let ((opascal--ignore-changes t))
290 (with-silent-modifications
291 ,@forms)))
292
293(defsubst opascal-is (element in-set) 278(defsubst opascal-is (element in-set)
294 ;; If the element is in the set, the element cdr is returned, otherwise nil. 279 ;; If the element is in the set, the element cdr is returned, otherwise nil.
295 (memq element in-set)) 280 (memq element in-set))
@@ -347,13 +332,6 @@ routine.")
347 ;; Returns the column of the point p. 332 ;; Returns the column of the point p.
348 (save-excursion (goto-char p) (current-column))) 333 (save-excursion (goto-char p) (current-column)))
349 334
350(defun opascal-face-of (token-kind)
351 ;; Returns the face property appropriate for the token kind.
352 (cond ((opascal-is token-kind opascal-comments) opascal-comment-face)
353 ((opascal-is token-kind opascal-strings) opascal-string-face)
354 ((opascal-is token-kind opascal-keywords) opascal-keyword-face)
355 (opascal-other-face)))
356
357(defvar opascal-progress-last-reported-point nil 335(defvar opascal-progress-last-reported-point nil
358 "The last point at which progress was reported.") 336 "The last point at which progress was reported.")
359 337
@@ -361,8 +339,6 @@ routine.")
361 "Number of chars to process before the next parsing progress report.") 339 "Number of chars to process before the next parsing progress report.")
362(defconst opascal-scanning-progress-step 2048 340(defconst opascal-scanning-progress-step 2048
363 "Number of chars to process before the next scanning progress report.") 341 "Number of chars to process before the next scanning progress report.")
364(defconst opascal-fontifying-progress-step opascal-scanning-progress-step
365 "Number of chars to process before the next fontification progress report.")
366 342
367(defun opascal-progress-start () 343(defun opascal-progress-start ()
368 ;; Initializes progress reporting. 344 ;; Initializes progress reporting.
@@ -400,22 +376,30 @@ routine.")
400 (goto-char curr-point) 376 (goto-char curr-point)
401 next)) 377 next))
402 378
403(defvar opascal--ignore-changes t 379(defconst opascal--literal-start-re (regexp-opt '("//" "{" "(*" "'" "\"")))
404 "Internal flag to control if the OPascal mode responds to buffer changes.
405Defaults to t in case the `opascal-after-change' function is called on a
406non-OPascal buffer. Set to nil in OPascal buffers. To override, just do:
407 (let ((opascal--ignore-changes t)) ...)")
408
409(defun opascal-set-token-property (from to value)
410 ;; Like `set-text-properties', except we do not consider this to be a buffer
411 ;; modification.
412 (opascal-save-state
413 (put-text-property from to 'token value)))
414 380
415(defun opascal-literal-kind (p) 381(defun opascal-literal-kind (p)
416 ;; Returns the literal kind the point p is in (or nil if not in a literal). 382 ;; Returns the literal kind the point p is in (or nil if not in a literal).
417 (if (and (<= (point-min) p) (<= p (point-max))) 383 (when (and (<= (point-min) p) (<= p (point-max)))
418 (get-text-property p 'token))) 384 (save-excursion
385 (let ((ppss (syntax-ppss p)))
386 ;; We want to return non-nil when right in front
387 ;; of a comment/string.
388 (if (null (nth 8 ppss))
389 (when (looking-at opascal--literal-start-re)
390 (pcase (char-after)
391 (`?/ 'comment-single-line)
392 (`?\{ 'comment-multi-line-1)
393 (`?\( 'comment-multi-line-2)
394 (`?\' 'string)
395 (`?\" 'double-quoted-string)))
396 (if (nth 3 ppss) ;String.
397 (if (eq (nth 3 ppss) ?\")
398 'double-quoted-string 'string)
399 (pcase (nth 7 ppss)
400 (`2 'comment-single-line)
401 (`1 'comment-multi-line-2)
402 (_ 'comment-multi-line-1))))))))
419 403
420(defun opascal-literal-start-pattern (literal-kind) 404(defun opascal-literal-start-pattern (literal-kind)
421 ;; Returns the start pattern of the literal kind. 405 ;; Returns the start pattern of the literal kind.
@@ -446,87 +430,27 @@ non-OPascal buffer. Set to nil in OPascal buffers. To override, just do:
446 (string . "['\n]") 430 (string . "['\n]")
447 (double-quoted-string . "[\"\n]"))))) 431 (double-quoted-string . "[\"\n]")))))
448 432
449(defun opascal-is-literal-start (p)
450 ;; True if the point p is at the start point of a (completed) literal.
451 (let* ((kind (opascal-literal-kind p))
452 (pattern (opascal-literal-start-pattern kind)))
453 (or (null kind) ; Non-literals are considered as start points.
454 (opascal-looking-at-string p pattern))))
455
456(defun opascal-is-literal-end (p) 433(defun opascal-is-literal-end (p)
457 ;; True if the point p is at the end point of a (completed) literal. 434 ;; True if the point p is at the end point of a (completed) literal.
458 (let* ((kind (opascal-literal-kind (1- p))) 435 (save-excursion
459 (pattern (opascal-literal-end-pattern kind))) 436 (and (null (nth 8 (syntax-ppss p)))
460 (or (null kind) ; Non-literals are considered as end points. 437 (nth 8 (syntax-ppss (1- p))))))
461
462 (and (opascal-looking-at-string (- p (length pattern)) pattern)
463 (or (not (opascal-is kind opascal-strings))
464 ;; Special case: string delimiters are start/end ambiguous.
465 ;; We have an end only if there is some string content (at
466 ;; least a starting delimiter).
467 (not (opascal-is-literal-end (1- p)))))
468
469 ;; Special case: strings cannot span lines.
470 (and (opascal-is kind opascal-strings) (eq ?\n (char-after (1- p)))))))
471
472(defun opascal-is-stable-literal (p)
473 ;; True if the point p marks a stable point. That is, a point outside of a
474 ;; literal region, inside of a literal region, or adjacent to completed
475 ;; literal regions.
476 (let ((at-start (opascal-is-literal-start p))
477 (at-end (opascal-is-literal-end p)))
478 (or (>= p (point-max))
479 (and at-start at-end)
480 (and (not at-start) (not at-end)
481 (eq (opascal-literal-kind (1- p)) (opascal-literal-kind p))))))
482
483(defun opascal-complete-literal (literal-kind limit)
484 ;; Continues the search for a literal's true end point and returns the
485 ;; point past the end pattern (if found) or the limit (if not found).
486 (let ((pattern (opascal-literal-stop-pattern literal-kind)))
487 (if (not (stringp pattern))
488 (error "Invalid literal kind %S" literal-kind)
489 ;; Search up to the limit.
490 (re-search-forward pattern limit 'goto-limit-on-fail)
491 (point))))
492
493(defun opascal-parse-next-literal (limit)
494 ;; Searches for the next literal region (i.e. comment or string) and sets the
495 ;; the point to its end (or the limit, if not found). The literal region is
496 ;; marked as such with a text property, to speed up tokenizing during face
497 ;; coloring and indentation scanning.
498 (let ((search-start (point)))
499 (cond ((not (opascal-is-literal-end search-start))
500 ;; We are completing an incomplete literal.
501 (let ((kind (opascal-literal-kind (1- search-start))))
502 (opascal-complete-literal kind limit)
503 (opascal-set-token-property search-start (point) kind)))
504
505 ((re-search-forward
506 "\\(//\\)\\|\\({\\)\\|\\((\\*\\)\\|\\('\\)\\|\\(\"\\)"
507 limit 'goto-limit-on-fail)
508 ;; We found the start of a new literal. Find its end and mark it.
509 (let ((kind (cond ((match-beginning 1) 'comment-single-line)
510 ((match-beginning 2) 'comment-multi-line-1)
511 ((match-beginning 3) 'comment-multi-line-2)
512 ((match-beginning 4) 'string)
513 ((match-beginning 5) 'double-quoted-string)))
514 (start (match-beginning 0)))
515 (opascal-set-token-property search-start start nil)
516 (opascal-complete-literal kind limit)
517 (opascal-set-token-property start (point) kind)))
518
519 ;; Nothing found. Mark it as a non-literal.
520 ((opascal-set-token-property search-start limit nil)))
521 (opascal-step-progress (point) "Parsing" opascal-parsing-progress-step)))
522 438
523(defun opascal-literal-token-at (p) 439(defun opascal-literal-token-at (p)
524 ;; Returns the literal token surrounding the point p, or nil if none. 440 "Return the literal token surrounding the point P, or nil if none."
525 (let ((kind (opascal-literal-kind p))) 441 (save-excursion
526 (when kind 442 (let ((ppss (syntax-ppss p)))
527 (let ((start (previous-single-property-change (1+ p) 'token)) 443 (when (or (nth 8 ppss) (looking-at opascal--literal-start-re))
528 (end (next-single-property-change p 'token))) 444 (let* ((new-start (or (nth 8 ppss) p))
529 (opascal-token-of kind (or start (point-min)) (or end (point-max))))))) 445 (new-end (progn
446 (goto-char new-start)
447 (condition-case nil
448 (if (memq (char-after) '(?\' ?\"))
449 (forward-sexp 1)
450 (forward-comment 1))
451 (scan-error (goto-char (point-max))))
452 (point))))
453 (opascal-token-of (opascal-literal-kind p) new-start new-end))))))
530 454
531(defun opascal-point-token-at (p kind) 455(defun opascal-point-token-at (p kind)
532 ;; Returns the single character token at the point p. 456 ;; Returns the single character token at the point p.
@@ -636,55 +560,6 @@ non-OPascal buffer. Set to nil in OPascal buffers. To override, just do:
636 (opascal-is (opascal-token-kind next-token) '(space newline)))) 560 (opascal-is (opascal-token-kind next-token) '(space newline))))
637 next-token)) 561 next-token))
638 562
639(defun opascal-parse-region (from to)
640 ;; Parses the literal tokens in the region. The point is set to "to".
641 (save-restriction
642 (widen)
643 (goto-char from)
644 (while (< (point) to)
645 (opascal-parse-next-literal to))))
646
647(defun opascal-parse-region-until-stable (from to)
648 ;; Parses at least the literal tokens in the region. After that, parsing
649 ;; continues as long as obsolete literal regions are encountered. The point
650 ;; is set to the encountered stable point.
651 (save-restriction
652 (widen)
653 (opascal-parse-region from to)
654 (while (not (opascal-is-stable-literal (point)))
655 (opascal-parse-next-literal (point-max)))))
656
657(defun opascal-fontify-region (from to &optional verbose)
658 ;; Colors the text in the region according to OPascal rules.
659 (opascal-save-excursion
660 (opascal-save-state
661 (let ((p from)
662 (opascal-verbose verbose)
663 (token nil))
664 (opascal-progress-start)
665 (while (< p to)
666 ;; Color the token and move past it.
667 (setq token (opascal-token-at p))
668 (add-text-properties
669 (opascal-token-start token) (opascal-token-end token)
670 (list 'face (opascal-face-of (opascal-token-kind token)) 'lazy-lock t))
671 (setq p (opascal-token-end token))
672 (opascal-step-progress p "Fontifying" opascal-fontifying-progress-step))
673 (opascal-progress-done)))))
674
675(defun opascal-after-change (change-start change-end _old-length)
676 ;; Called when the buffer has changed. Reparses the changed region.
677 (unless opascal--ignore-changes
678 (let ((opascal--ignore-changes t)) ; Prevent recursive calls.
679 (opascal-save-excursion
680 (opascal-progress-start)
681 ;; Reparse at least from the token previous to the change to the end of
682 ;; line after the change.
683 (opascal-parse-region-until-stable
684 (opascal-token-start (opascal-token-at (1- change-start)))
685 (progn (goto-char change-end) (end-of-line) (point)))
686 (opascal-progress-done)))))
687
688(defun opascal-group-start (from-token) 563(defun opascal-group-start (from-token)
689 ;; Returns the token that denotes the start of the ()/[] group. 564 ;; Returns the token that denotes the start of the ()/[] group.
690 (let ((token (opascal-previous-token from-token)) 565 (let ((token (opascal-previous-token from-token))
@@ -1552,41 +1427,6 @@ If before the indent, the point is moved to the indent."
1552 (interactive "r") 1427 (interactive "r")
1553 (opascal-debug-log "String: %S" (buffer-substring from to))) 1428 (opascal-debug-log "String: %S" (buffer-substring from to)))
1554 1429
1555(defun opascal-debug-show-is-stable ()
1556 (interactive)
1557 (opascal-debug-log "stable: %S prev: %S next: %S"
1558 (opascal-is-stable-literal (point))
1559 (opascal-literal-kind (1- (point)))
1560 (opascal-literal-kind (point))))
1561
1562(defun opascal-debug-unparse-buffer ()
1563 (interactive)
1564 (opascal-set-token-property (point-min) (point-max) nil))
1565
1566(defun opascal-debug-parse-region (from to)
1567 (interactive "r")
1568 (let ((opascal-verbose t))
1569 (opascal-save-excursion
1570 (opascal-progress-start)
1571 (opascal-parse-region from to)
1572 (opascal-progress-done "Parsing done"))))
1573
1574(defun opascal-debug-parse-window ()
1575 (interactive)
1576 (opascal-debug-parse-region (window-start) (window-end)))
1577
1578(defun opascal-debug-parse-buffer ()
1579 (interactive)
1580 (opascal-debug-parse-region (point-min) (point-max)))
1581
1582(defun opascal-debug-fontify-window ()
1583 (interactive)
1584 (opascal-fontify-region (window-start) (window-end) t))
1585
1586(defun opascal-debug-fontify-buffer ()
1587 (interactive)
1588 (opascal-fontify-region (point-min) (point-max) t))
1589
1590(defun opascal-debug-tokenize-region (from to) 1430(defun opascal-debug-tokenize-region (from to)
1591 (interactive) 1431 (interactive)
1592 (opascal-save-excursion 1432 (opascal-save-excursion
@@ -1738,6 +1578,7 @@ An error is raised if not in a comment."
1738 (error "Not in a comment") 1578 (error "Not in a comment")
1739 (let* ((start-comment (opascal-comment-block-start comment)) 1579 (let* ((start-comment (opascal-comment-block-start comment))
1740 (end-comment (opascal-comment-block-end comment)) 1580 (end-comment (opascal-comment-block-end comment))
1581 ;; FIXME: Don't abuse global variables like `comment-end/start'.
1741 (comment-start (opascal-token-start start-comment)) 1582 (comment-start (opascal-token-start start-comment))
1742 (comment-end (opascal-token-end end-comment)) 1583 (comment-end (opascal-token-end end-comment))
1743 (content-start (opascal-comment-content-start start-comment)) 1584 (content-start (opascal-comment-content-start start-comment))
@@ -1805,12 +1646,7 @@ An error is raised if not in a comment."
1805 1646
1806 ;; Restore our position 1647 ;; Restore our position
1807 (goto-char marked-point) 1648 (goto-char marked-point)
1808 (set-marker marked-point nil) 1649 (set-marker marked-point nil)))))))
1809
1810 ;; React to the entire fill change as a whole.
1811 (opascal-progress-start)
1812 (opascal-parse-region comment-start comment-end)
1813 (opascal-progress-done)))))))
1814 1650
1815(defun opascal-new-comment-line () 1651(defun opascal-new-comment-line ()
1816 "If in a // comment, do a newline, indented such that one is still in the 1652 "If in a // comment, do a newline, indented such that one is still in the
@@ -1839,16 +1675,37 @@ comment block. If not in a // comment, just does a normal newline."
1839 (goto-char end) 1675 (goto-char end)
1840 token))) 1676 token)))
1841 1677
1678(defconst opascal-font-lock-keywords
1679 `(("\\_<\\(function\\|pro\\(cedure\\|gram\\)\\)[ \t]+\\([[:alpha:]][[:alnum:]_]*\\)"
1680 (1 font-lock-keyword-face) (3 font-lock-function-name-face))
1681 ,(concat "\\_<" (regexp-opt (mapcar #'symbol-name opascal-keywords))
1682 "\\_>")))
1683
1842(defconst opascal-font-lock-defaults 1684(defconst opascal-font-lock-defaults
1843 '(nil ; We have our own fontify routine, so keywords don't apply. 1685 '(opascal-font-lock-keywords
1844 t ; Syntactic fontification doesn't apply. 1686 nil ; Syntactic fontification does apply.
1845 nil ; Don't care about case since we don't use regexps to find tokens. 1687 nil ; Don't care about case since we don't use regexps to find tokens.
1846 nil ; Syntax alists don't apply. 1688 nil ; Syntax alists don't apply.
1847 nil ; Syntax begin movement doesn't apply 1689 nil ; Syntax begin movement doesn't apply.
1848 (font-lock-fontify-region-function . opascal-fontify-region) 1690 )
1849 (font-lock-verbose . opascal-fontifying-progress-step))
1850 "OPascal mode font-lock defaults. Syntactic fontification is ignored.") 1691 "OPascal mode font-lock defaults. Syntactic fontification is ignored.")
1851 1692
1693(defconst opascal--syntax-propertize
1694 (syntax-propertize-rules
1695 ;; The syntax-table settings are too coarse and end up treating /* and (/
1696 ;; as comment starters. Fix it here by removing the "2" from the syntax
1697 ;; of the second char of such sequences.
1698 ("/\\(\\*\\)" (1 ". 3b"))
1699 ("(\\(\\/\\)" (1 (prog1 ". 1c" (forward-char -1) nil)))
1700 ;; Pascal uses '' and "" rather than \' and \" to escape quotes.
1701 ("''\\|\"\"" (0 (if (save-excursion
1702 (nth 3 (syntax-ppss (match-beginning 0))))
1703 (string-to-syntax ".")
1704 ;; In case of 3 or more quotes in a row, only advance
1705 ;; one quote at a time.
1706 (forward-char -1)
1707 nil)))))
1708
1852(defvar opascal-debug-mode-map 1709(defvar opascal-debug-mode-map
1853 (let ((kmap (make-sparse-keymap))) 1710 (let ((kmap (make-sparse-keymap)))
1854 (dolist (binding '(("n" opascal-debug-goto-next-token) 1711 (dolist (binding '(("n" opascal-debug-goto-next-token)
@@ -1857,14 +1714,7 @@ comment block. If not in a // comment, just does a normal newline."
1857 ("T" opascal-debug-tokenize-buffer) 1714 ("T" opascal-debug-tokenize-buffer)
1858 ("W" opascal-debug-tokenize-window) 1715 ("W" opascal-debug-tokenize-window)
1859 ("g" opascal-debug-goto-point) 1716 ("g" opascal-debug-goto-point)
1860 ("s" opascal-debug-show-current-string) 1717 ("s" opascal-debug-show-current-string)))
1861 ("a" opascal-debug-parse-buffer)
1862 ("w" opascal-debug-parse-window)
1863 ("f" opascal-debug-fontify-window)
1864 ("F" opascal-debug-fontify-buffer)
1865 ("r" opascal-debug-parse-region)
1866 ("c" opascal-debug-unparse-buffer)
1867 ("x" opascal-debug-show-is-stable)))
1868 (define-key kmap (car binding) (cadr binding))) 1718 (define-key kmap (car binding) (cadr binding)))
1869 kmap) 1719 kmap)
1870 "Keystrokes for OPascal mode debug commands.") 1720 "Keystrokes for OPascal mode debug commands.")
@@ -1914,14 +1764,8 @@ Customization:
1914 1764
1915Coloring: 1765Coloring:
1916 1766
1917 `opascal-comment-face' (default font-lock-comment-face)
1918 Face used to color OPascal comments.
1919 `opascal-string-face' (default font-lock-string-face)
1920 Face used to color OPascal strings.
1921 `opascal-keyword-face' (default font-lock-keyword-face) 1767 `opascal-keyword-face' (default font-lock-keyword-face)
1922 Face used to color OPascal keywords. 1768 Face used to color OPascal keywords.
1923 `opascal-other-face' (default nil)
1924 Face used to color everything else.
1925 1769
1926Turning on OPascal mode calls the value of the variable `opascal-mode-hook' 1770Turning on OPascal mode calls the value of the variable `opascal-mode-hook'
1927with no args, if that value is non-nil." 1771with no args, if that value is non-nil."
@@ -1931,21 +1775,13 @@ with no args, if that value is non-nil."
1931 (setq-local comment-indent-function #'opascal-indent-line) 1775 (setq-local comment-indent-function #'opascal-indent-line)
1932 (setq-local case-fold-search t) 1776 (setq-local case-fold-search t)
1933 (setq-local opascal-progress-last-reported-point nil) 1777 (setq-local opascal-progress-last-reported-point nil)
1934 (setq-local opascal--ignore-changes nil)
1935 (setq-local font-lock-defaults opascal-font-lock-defaults) 1778 (setq-local font-lock-defaults opascal-font-lock-defaults)
1936 (setq-local tab-always-indent opascal-tab-always-indents) 1779 (setq-local tab-always-indent opascal-tab-always-indents)
1780 (setq-local syntax-propertize-function opascal--syntax-propertize)
1937 1781
1938 ;; FIXME: Use syntax-propertize-function to tokenize, maybe? 1782 (setq-local comment-start "// ")
1939 1783 (setq-local comment-start-skip "\\(?://\\|(\\*\\|{\\)[ \t]*")
1940 ;; We need to keep track of changes to the buffer to determine if we need 1784 (setq-local comment-end-skip "[ \t]*\\(?:\n\\|\\*)\\|}\\)"))
1941 ;; to retokenize changed text.
1942 (add-hook 'after-change-functions #'opascal-after-change nil t)
1943
1944 (opascal-save-excursion
1945 (let ((opascal-verbose t))
1946 (opascal-progress-start)
1947 (opascal-parse-region (point-min) (point-max))
1948 (opascal-progress-done))))
1949 1785
1950(provide 'opascal) 1786(provide 'opascal)
1951;;; opascal.el ends here 1787;;; opascal.el ends here
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index a86b10e21cc..6bfc70c5d44 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -234,8 +234,18 @@ of master file."
234 234
235 ((match-end 1) 235 ((match-end 1)
236 ;; It is a label 236 ;; It is a label
237 (push (reftex-label-info (reftex-match-string 1) file bound) 237 (when (or (null reftex-label-ignored-macros-and-environments)
238 docstruct)) 238 ;; \label{} defs should always be honored,
239 ;; just no keyval style [label=foo] defs.
240 (string-equal "\label{" (substring (reftex-match-string 0) 0 7))
241 (not (fboundp 'TeX-current-macro))
242 (not (fboundp 'LaTeX-current-environment))
243 (not (or (member (save-match-data (TeX-current-macro))
244 reftex-label-ignored-macros-and-environments)
245 (member (save-match-data (LaTeX-current-environment))
246 reftex-label-ignored-macros-and-environments))))
247 (push (reftex-label-info (reftex-match-string 1) file bound)
248 docstruct)))
239 249
240 ((match-end 3) 250 ((match-end 3)
241 ;; It is a section 251 ;; It is a section
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 7343d86b06f..ab085a3085a 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -885,6 +885,25 @@ effective."
885 :group 'reftex-defining-label-environments 885 :group 'reftex-defining-label-environments
886 :type '(repeat (regexp :tag "Regular Expression"))) 886 :type '(repeat (regexp :tag "Regular Expression")))
887 887
888(defcustom reftex-label-ignored-macros-and-environments nil
889 "List of macros and environments to be ignored when searching for labels.
890The purpose is to ignore environments and macros that use keyval
891style label=foo arguments, but the label has a different meaning
892than a \\label{foo}. Standard \\label{...} definitions are never
893ignored.
894
895E.g., TikZ defines several macros/environments where [label=foo]
896defines the label to be printed at some node or edge, but it's
897not a label used for referencing.
898
899Note that this feature is only supported if you are using AUCTeX
900and the functions `TeX-current-macro' and
901`LaTeX-current-environment' are bound. Also note that this
902feature might slow down the reftex parsing process for large TeX
903files."
904 :group 'reftex-defining-label-environments
905 :type '(repeat string))
906
888(defcustom reftex-label-illegal-re "[^-a-zA-Z0-9_+=:;,.]" 907(defcustom reftex-label-illegal-re "[^-a-zA-Z0-9_+=:;,.]"
889 "Regexp matching characters not valid in labels." 908 "Regexp matching characters not valid in labels."
890 :group 'reftex-making-and-inserting-labels 909 :group 'reftex-making-and-inserting-labels
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index 1286e5d803e..76ffeaf30be 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -432,12 +432,14 @@ If you want to remember a region, supply a universal prefix to
432 432
433(defcustom remember-data-directory "~/remember" 433(defcustom remember-data-directory "~/remember"
434 "The directory in which to store remember data as files." 434 "The directory in which to store remember data as files."
435 :type 'file 435 :type 'directory
436 :version "24.4"
436 :group 'remember) 437 :group 'remember)
437 438
438(defcustom remember-directory-file-name-format "%Y-%m-%d_%T-%z" 439(defcustom remember-directory-file-name-format "%Y-%m-%d_%T-%z"
439 "Format string for the file name in which to store unprocessed data." 440 "Format string for the file name in which to store unprocessed data."
440 :type 'file 441 :type 'string
442 :version "24.4"
441 :group 'remember) 443 :group 'remember)
442 444
443(defun remember-store-in-files () 445(defun remember-store-in-files ()