aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes
diff options
context:
space:
mode:
authorTom Tromey2013-06-03 12:25:05 -0600
committerTom Tromey2013-06-03 12:25:05 -0600
commit68359abba96d7ec4db8aab3d3dd9cf1105c3bab5 (patch)
tree862703e7e1a1888170136a8296a5750d6b2ae2eb /lisp/progmodes
parentcbcba8ce7f980b01c18c0fd561ef6687b1361507 (diff)
parente2d8a6f0a229b4ebe26484b892ec4f14888f58b6 (diff)
downloademacs-68359abba96d7ec4db8aab3d3dd9cf1105c3bab5.tar.gz
emacs-68359abba96d7ec4db8aab3d3dd9cf1105c3bab5.zip
merge from trunk; clean up some issues
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/ada-mode.el146
-rw-r--r--lisp/progmodes/autoconf.el19
-rw-r--r--lisp/progmodes/cc-bytecomp.el16
-rw-r--r--lisp/progmodes/cc-cmds.el1
-rw-r--r--lisp/progmodes/cc-defs.el16
-rw-r--r--lisp/progmodes/cc-engine.el136
-rw-r--r--lisp/progmodes/cc-fonts.el3
-rw-r--r--lisp/progmodes/cc-langs.el4
-rw-r--r--lisp/progmodes/cc-menus.el159
-rw-r--r--lisp/progmodes/cc-mode.el33
-rw-r--r--lisp/progmodes/cc-vars.el59
-rw-r--r--lisp/progmodes/cfengine.el30
-rw-r--r--lisp/progmodes/compile.el18
-rw-r--r--lisp/progmodes/cperl-mode.el16
-rw-r--r--lisp/progmodes/cpp.el7
-rw-r--r--lisp/progmodes/f90.el495
-rw-r--r--lisp/progmodes/flymake.el91
-rw-r--r--lisp/progmodes/gdb-mi.el303
-rw-r--r--lisp/progmodes/grep.el4
-rw-r--r--lisp/progmodes/gud.el110
-rw-r--r--lisp/progmodes/idlw-help.el9
-rw-r--r--lisp/progmodes/idlwave.el92
-rw-r--r--lisp/progmodes/js.el17
-rw-r--r--lisp/progmodes/ld-script.el10
-rw-r--r--lisp/progmodes/m4-mode.el49
-rw-r--r--lisp/progmodes/make-mode.el2
-rw-r--r--lisp/progmodes/meta-mode.el1
-rw-r--r--lisp/progmodes/octave-inf.el386
-rw-r--r--lisp/progmodes/octave-mod.el1152
-rw-r--r--lisp/progmodes/octave.el1732
-rw-r--r--lisp/progmodes/opascal.el345
-rw-r--r--lisp/progmodes/pascal.el86
-rw-r--r--lisp/progmodes/perl-mode.el50
-rw-r--r--lisp/progmodes/prolog.el27
-rw-r--r--lisp/progmodes/python.el358
-rw-r--r--lisp/progmodes/ruby-mode.el351
-rw-r--r--lisp/progmodes/sh-script.el27
-rw-r--r--lisp/progmodes/sql.el65
-rw-r--r--lisp/progmodes/subword.el129
-rw-r--r--lisp/progmodes/tcl.el2
-rw-r--r--lisp/progmodes/vera-mode.el7
-rw-r--r--lisp/progmodes/verilog-mode.el54
-rw-r--r--lisp/progmodes/vhdl-mode.el971
-rw-r--r--lisp/progmodes/which-func.el4
-rw-r--r--lisp/progmodes/xscheme.el39
45 files changed, 4428 insertions, 3203 deletions
diff --git a/lisp/progmodes/ada-mode.el b/lisp/progmodes/ada-mode.el
index 3709aa26bbe..805444d08b9 100644
--- a/lisp/progmodes/ada-mode.el
+++ b/lisp/progmodes/ada-mode.el
@@ -457,15 +457,8 @@ The extensions should include a `.' if needed.")
457(defvar ada-mode-extra-prefix "\C-c\C-q" 457(defvar ada-mode-extra-prefix "\C-c\C-q"
458 "Prefix key to access `ada-mode-extra-map' functions.") 458 "Prefix key to access `ada-mode-extra-map' functions.")
459 459
460(defvar ada-mode-abbrev-table nil 460(define-abbrev-table 'ada-mode-abbrev-table ()
461 "Local abbrev table for Ada mode.") 461 "Local abbrev table for Ada mode.")
462(define-abbrev-table 'ada-mode-abbrev-table ())
463
464(defvar ada-mode-syntax-table nil
465 "Syntax table to be used for editing Ada source code.")
466
467(defvar ada-mode-symbol-syntax-table nil
468 "Syntax table for Ada, where `_' is a word constituent.")
469 462
470(eval-when-compile 463(eval-when-compile
471 ;; These values are used in eval-when-compile expressions. 464 ;; These values are used in eval-when-compile expressions.
@@ -845,61 +838,58 @@ the 4 file locations can be clicked on and jumped to."
845;; better is available on XEmacs. 838;; better is available on XEmacs.
846;;------------------------------------------------------------------------- 839;;-------------------------------------------------------------------------
847 840
848(defun ada-create-syntax-table () 841(defvar ada-mode-syntax-table
849 "Create the two syntax tables use in the Ada mode. 842 (let ((st (make-syntax-table)))
850The standard table declares `_' as a symbol constituent, the second one 843 ;; Define string brackets (`%' is alternative string bracket, but
851declares it as a word constituent." 844 ;; almost never used as such and throws font-lock and indentation
852 (interactive) 845 ;; off the track.)
853 (setq ada-mode-syntax-table (make-syntax-table)) 846 (modify-syntax-entry ?% "$" st)
854 847 (modify-syntax-entry ?\" "\"" st)
855 ;; define string brackets (`%' is alternative string bracket, but 848
856 ;; almost never used as such and throws font-lock and indentation 849 (modify-syntax-entry ?: "." st)
857 ;; off the track.) 850 (modify-syntax-entry ?\; "." st)
858 (modify-syntax-entry ?% "$" ada-mode-syntax-table) 851 (modify-syntax-entry ?& "." st)
859 (modify-syntax-entry ?\" "\"" ada-mode-syntax-table) 852 (modify-syntax-entry ?\| "." st)
860 853 (modify-syntax-entry ?+ "." st)
861 (modify-syntax-entry ?: "." ada-mode-syntax-table) 854 (modify-syntax-entry ?* "." st)
862 (modify-syntax-entry ?\; "." ada-mode-syntax-table) 855 (modify-syntax-entry ?/ "." st)
863 (modify-syntax-entry ?& "." ada-mode-syntax-table) 856 (modify-syntax-entry ?= "." st)
864 (modify-syntax-entry ?\| "." ada-mode-syntax-table) 857 (modify-syntax-entry ?< "." st)
865 (modify-syntax-entry ?+ "." ada-mode-syntax-table) 858 (modify-syntax-entry ?> "." st)
866 (modify-syntax-entry ?* "." ada-mode-syntax-table) 859 (modify-syntax-entry ?$ "." st)
867 (modify-syntax-entry ?/ "." ada-mode-syntax-table) 860 (modify-syntax-entry ?\[ "." st)
868 (modify-syntax-entry ?= "." ada-mode-syntax-table) 861 (modify-syntax-entry ?\] "." st)
869 (modify-syntax-entry ?< "." ada-mode-syntax-table) 862 (modify-syntax-entry ?\{ "." st)
870 (modify-syntax-entry ?> "." ada-mode-syntax-table) 863 (modify-syntax-entry ?\} "." st)
871 (modify-syntax-entry ?$ "." ada-mode-syntax-table) 864 (modify-syntax-entry ?. "." st)
872 (modify-syntax-entry ?\[ "." ada-mode-syntax-table) 865 (modify-syntax-entry ?\\ "." st)
873 (modify-syntax-entry ?\] "." ada-mode-syntax-table) 866 (modify-syntax-entry ?\' "." st)
874 (modify-syntax-entry ?\{ "." ada-mode-syntax-table) 867
875 (modify-syntax-entry ?\} "." ada-mode-syntax-table) 868 ;; A single hyphen is punctuation, but a double hyphen starts a comment.
876 (modify-syntax-entry ?. "." ada-mode-syntax-table) 869 (modify-syntax-entry ?- ". 12" st)
877 (modify-syntax-entry ?\\ "." ada-mode-syntax-table) 870
878 (modify-syntax-entry ?\' "." ada-mode-syntax-table) 871 ;; See the comment above on grammar related function for the special
879 872 ;; setup for '#'.
880 ;; a single hyphen is punctuation, but a double hyphen starts a comment 873 (modify-syntax-entry ?# (if (featurep 'xemacs) "<" "$") st)
881 (modify-syntax-entry ?- ". 12" ada-mode-syntax-table) 874
882 875 ;; And \f and \n end a comment.
883 ;; See the comment above on grammar related function for the special 876 (modify-syntax-entry ?\f "> " st)
884 ;; setup for '#'. 877 (modify-syntax-entry ?\n "> " st)
885 (if (featurep 'xemacs) 878
886 (modify-syntax-entry ?# "<" ada-mode-syntax-table) 879 ;; Define what belongs in Ada symbols.
887 (modify-syntax-entry ?# "$" ada-mode-syntax-table)) 880 (modify-syntax-entry ?_ "_" st)
888 881
889 ;; and \f and \n end a comment 882 ;; Define parentheses to match.
890 (modify-syntax-entry ?\f "> " ada-mode-syntax-table) 883 (modify-syntax-entry ?\( "()" st)
891 (modify-syntax-entry ?\n "> " ada-mode-syntax-table) 884 (modify-syntax-entry ?\) ")(" st)
892 885 st)
893 ;; define what belongs in Ada symbols 886 "Syntax table to be used for editing Ada source code.")
894 (modify-syntax-entry ?_ "_" ada-mode-syntax-table) 887
895 888(defvar ada-mode-symbol-syntax-table
896 ;; define parentheses to match 889 (let ((st (make-syntax-table ada-mode-syntax-table)))
897 (modify-syntax-entry ?\( "()" ada-mode-syntax-table) 890 (modify-syntax-entry ?_ "w" st)
898 (modify-syntax-entry ?\) ")(" ada-mode-syntax-table) 891 st)
899 892 "Syntax table for Ada, where `_' is a word constituent.")
900 (setq ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
901 (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
902 )
903 893
904;; Support of special characters in XEmacs (see the comments at the beginning 894;; Support of special characters in XEmacs (see the comments at the beginning
905;; of the section on Grammar related functions). 895;; of the section on Grammar related functions).
@@ -1293,7 +1283,7 @@ the file name."
1293 (if ada-popup-key 1283 (if ada-popup-key
1294 (define-key ada-mode-map ada-popup-key 'ada-popup-menu)) 1284 (define-key ada-mode-map ada-popup-key 'ada-popup-menu))
1295 1285
1296 ;; Support for Abbreviations (the user still need to "M-x abbrev-mode" 1286 ;; Support for Abbreviations (the user still needs to "M-x abbrev-mode").
1297 (setq local-abbrev-table ada-mode-abbrev-table) 1287 (setq local-abbrev-table ada-mode-abbrev-table)
1298 1288
1299 ;; Support for which-function mode 1289 ;; Support for which-function mode
@@ -1625,9 +1615,8 @@ ARG is the prefix the user entered with \\[universal-argument]."
1625 (let ((lastk last-command-event)) 1615 (let ((lastk last-command-event))
1626 1616
1627 (with-syntax-table ada-mode-symbol-syntax-table 1617 (with-syntax-table ada-mode-symbol-syntax-table
1628 (cond ((or (eq lastk ?\n) 1618 (cond ((memq lastk '(?\n ?\r))
1629 (eq lastk ?\r)) 1619 ;; Horrible kludge.
1630 ;; horrible kludge
1631 (insert " ") 1620 (insert " ")
1632 (ada-adjust-case) 1621 (ada-adjust-case)
1633 ;; horrible dekludge 1622 ;; horrible dekludge
@@ -1706,9 +1695,7 @@ ARG is ignored, and is there for compatibility with `capitalize-word' only."
1706 (interactive) 1695 (interactive)
1707 (let ((end (save-excursion (skip-syntax-forward "w") (point))) 1696 (let ((end (save-excursion (skip-syntax-forward "w") (point)))
1708 (begin (save-excursion (skip-syntax-backward "w") (point)))) 1697 (begin (save-excursion (skip-syntax-backward "w") (point))))
1709 (modify-syntax-entry ?_ "_") 1698 (capitalize-region begin end)))
1710 (capitalize-region begin end)
1711 (modify-syntax-entry ?_ "w")))
1712 1699
1713(defun ada-adjust-case-region (from to) 1700(defun ada-adjust-case-region (from to)
1714 "Adjust the case of all words in the region between FROM and TO. 1701 "Adjust the case of all words in the region between FROM and TO.
@@ -2165,7 +2152,7 @@ and the offset."
2165 (unwind-protect 2152 (unwind-protect
2166 (with-syntax-table ada-mode-symbol-syntax-table 2153 (with-syntax-table ada-mode-symbol-syntax-table
2167 2154
2168 ;; This need to be done here so that the advice is not always 2155 ;; This needs to be done here so that the advice is not always
2169 ;; activated (this might interact badly with other modes) 2156 ;; activated (this might interact badly with other modes)
2170 (if (featurep 'xemacs) 2157 (if (featurep 'xemacs)
2171 (ad-activate 'parse-partial-sexp t)) 2158 (ad-activate 'parse-partial-sexp t))
@@ -3419,27 +3406,23 @@ Stop the search at LIMIT."
3419If BACKWARD is non-nil, jump to the beginning of the previous word. 3406If BACKWARD is non-nil, jump to the beginning of the previous word.
3420Return the new position of point or nil if not found." 3407Return the new position of point or nil if not found."
3421 (let ((match-cons nil) 3408 (let ((match-cons nil)
3422 (orgpoint (point)) 3409 (orgpoint (point)))
3423 (old-syntax (char-to-string (char-syntax ?_))))
3424 (modify-syntax-entry ?_ "w")
3425 (unless backward 3410 (unless backward
3426 (skip-syntax-forward "w")) 3411 (skip-syntax-forward "w_"))
3427 (if (setq match-cons 3412 (if (setq match-cons
3428 (ada-search-ignore-string-comment "\\w" backward nil t)) 3413 (ada-search-ignore-string-comment "\\sw\\|\\s_" backward nil t))
3429 ;; 3414 ;;
3430 ;; move to the beginning of the word found 3415 ;; move to the beginning of the word found
3431 ;; 3416 ;;
3432 (progn 3417 (progn
3433 (goto-char (car match-cons)) 3418 (goto-char (car match-cons))
3434 (skip-syntax-backward "w") 3419 (skip-syntax-backward "w_")
3435 (point)) 3420 (point))
3436 ;; 3421 ;;
3437 ;; if not found, restore old position of point 3422 ;; if not found, restore old position of point
3438 ;; 3423 ;;
3439 (goto-char orgpoint) 3424 (goto-char orgpoint)
3440 'nil) 3425 'nil)))
3441 (modify-syntax-entry ?_ old-syntax))
3442 )
3443 3426
3444 3427
3445(defun ada-check-matching-start (keyword) 3428(defun ada-check-matching-start (keyword)
@@ -5431,9 +5414,6 @@ This function typically is to be hooked into `ff-file-created-hook'."
5431(ada-create-keymap) 5414(ada-create-keymap)
5432(ada-create-menu) 5415(ada-create-menu)
5433 5416
5434;; Create the syntax tables, but do not activate them
5435(ada-create-syntax-table)
5436
5437;; Add the default extensions (and set up speedbar) 5417;; Add the default extensions (and set up speedbar)
5438(ada-add-extensions ".ads" ".adb") 5418(ada-add-extensions ".ads" ".adb")
5439;; This two files are generated by GNAT when running with -gnatD 5419;; This two files are generated by GNAT when running with -gnatD
diff --git a/lisp/progmodes/autoconf.el b/lisp/progmodes/autoconf.el
index 8a99ad6e1b3..e6eaea985af 100644
--- a/lisp/progmodes/autoconf.el
+++ b/lisp/progmodes/autoconf.el
@@ -41,10 +41,10 @@
41 "Hook run by `autoconf-mode'.") 41 "Hook run by `autoconf-mode'.")
42 42
43(defconst autoconf-definition-regexp 43(defconst autoconf-definition-regexp
44 "A\\(?:H_TEMPLATE\\|C_\\(?:SUBST\\|DEFINE\\(?:_UNQUOTED\\)?\\)\\)(\\[*\\(\\sw+\\)\\]*") 44 "A\\(?:H_TEMPLATE\\|C_\\(?:SUBST\\|DEFINE\\(?:_UNQUOTED\\)?\\)\\)(\\[*\\(\\(?:\\sw\\|\\s_\\)+\\)\\]*")
45 45
46(defvar autoconf-font-lock-keywords 46(defvar autoconf-font-lock-keywords
47 `(("\\_<A[CHMS]_\\sw+" . font-lock-keyword-face) 47 `(("\\_<A[CHMS]_\\(?:\\sw\\|\\s_\\)+" . font-lock-keyword-face)
48 (,autoconf-definition-regexp 48 (,autoconf-definition-regexp
49 1 font-lock-function-name-face) 49 1 font-lock-function-name-face)
50 ;; Are any other M4 keywords really appropriate for configure.ac, 50 ;; Are any other M4 keywords really appropriate for configure.ac,
@@ -67,13 +67,11 @@
67This version looks back for an AC_DEFINE or AC_SUBST. It will stop 67This version looks back for an AC_DEFINE or AC_SUBST. It will stop
68searching backwards at another AC_... command." 68searching backwards at another AC_... command."
69 (save-excursion 69 (save-excursion
70 (with-syntax-table (copy-syntax-table autoconf-mode-syntax-table) 70 (skip-syntax-forward "w_" (line-end-position))
71 (modify-syntax-entry ?_ "w") 71 (if (re-search-backward autoconf-definition-regexp
72 (skip-syntax-forward "w" (line-end-position)) 72 (save-excursion (beginning-of-defun) (point))
73 (if (re-search-backward autoconf-definition-regexp 73 t)
74 (save-excursion (beginning-of-defun) (point)) 74 (match-string-no-properties 1))))
75 t)
76 (match-string-no-properties 1)))))
77 75
78;;;###autoload 76;;;###autoload
79(define-derived-mode autoconf-mode prog-mode "Autoconf" 77(define-derived-mode autoconf-mode prog-mode "Autoconf"
@@ -85,9 +83,8 @@ searching backwards at another AC_... command."
85 (setq-local syntax-propertize-function 83 (setq-local syntax-propertize-function
86 (syntax-propertize-rules ("\\<dnl\\>" (0 "<")))) 84 (syntax-propertize-rules ("\\<dnl\\>" (0 "<"))))
87 (setq-local font-lock-defaults 85 (setq-local font-lock-defaults
88 `(autoconf-font-lock-keywords nil nil (("_" . "w")))) 86 `(autoconf-font-lock-keywords nil nil))
89 (setq-local imenu-generic-expression autoconf-imenu-generic-expression) 87 (setq-local imenu-generic-expression autoconf-imenu-generic-expression)
90 (setq-local imenu-syntax-alist '(("_" . "w")))
91 (setq-local indent-line-function #'indent-relative) 88 (setq-local indent-line-function #'indent-relative)
92 (setq-local add-log-current-defun-function 89 (setq-local add-log-current-defun-function
93 #'autoconf-current-defun-function)) 90 #'autoconf-current-defun-function))
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el
index e41455f7883..337a5292417 100644
--- a/lisp/progmodes/cc-bytecomp.el
+++ b/lisp/progmodes/cc-bytecomp.el
@@ -232,6 +232,9 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere"))
232 (cc-bytecomp-setup-environment) 232 (cc-bytecomp-setup-environment)
233 t)))) 233 t))))
234 234
235(defvar cc-bytecomp-noruntime-functions nil
236 "Saved value of `byte-compile-noruntime-functions'.")
237
235(defmacro cc-require (cc-part) 238(defmacro cc-require (cc-part)
236 "Force loading of the corresponding .el file in the current directory 239 "Force loading of the corresponding .el file in the current directory
237during compilation, but compile in a `require'. Don't use within 240during compilation, but compile in a `require'. Don't use within
@@ -240,7 +243,16 @@ during compilation, but compile in a `require'. Don't use within
240Having cyclic cc-require's will result in infinite recursion. That's 243Having cyclic cc-require's will result in infinite recursion. That's
241somewhat intentional." 244somewhat intentional."
242 `(progn 245 `(progn
243 (eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part))) 246 (eval-when-compile
247 (setq cc-bytecomp-noruntime-functions byte-compile-noruntime-functions)
248 (cc-bytecomp-load (symbol-name ,cc-part)))
249 ;; Hack to suppress spurious "might not be defined at runtime" warnings.
250 ;; The basic issue is that
251 ;; (eval-when-compile (require 'foo))
252 ;; (require 'foo)
253 ;; produces bogus noruntime warnings about functions from foo.
254 (eval-when-compile
255 (setq byte-compile-noruntime-functions cc-bytecomp-noruntime-functions))
244 (require ,cc-part))) 256 (require ,cc-part)))
245 257
246(defmacro cc-provide (feature) 258(defmacro cc-provide (feature)
@@ -266,7 +278,7 @@ somewhat intentional."
266during compilation, but do a compile time `require' otherwise. Don't 278during compilation, but do a compile time `require' otherwise. Don't
267use within `eval-when-compile'." 279use within `eval-when-compile'."
268 `(eval-when-compile 280 `(eval-when-compile
269 (if (and (featurep 'cc-bytecomp) 281 (if (and (fboundp 'cc-bytecomp-is-compiling)
270 (cc-bytecomp-is-compiling)) 282 (cc-bytecomp-is-compiling))
271 (if (or (not load-in-progress) 283 (if (or (not load-in-progress)
272 (not (featurep ,cc-part))) 284 (not (featurep ,cc-part)))
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 0bb804799dc..dc6ed1348d1 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -45,7 +45,6 @@
45(cc-require 'cc-engine) 45(cc-require 'cc-engine)
46 46
47;; Silence the compiler. 47;; Silence the compiler.
48(cc-bytecomp-defun delete-forward-p) ; XEmacs
49(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge 48(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge
50 ; which looks at this. 49 ; which looks at this.
51 50
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 48236c2dca2..b90a01dcb3b 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -48,16 +48,12 @@
48 48
49;; Silence the compiler. 49;; Silence the compiler.
50(cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el 50(cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el
51(cc-bytecomp-defun buffer-syntactic-context-depth) ; XEmacs
52(cc-bytecomp-defun region-active-p) ; XEmacs 51(cc-bytecomp-defun region-active-p) ; XEmacs
53(cc-bytecomp-defvar zmacs-region-stays) ; XEmacs
54(cc-bytecomp-defvar zmacs-regions) ; XEmacs
55(cc-bytecomp-defvar mark-active) ; Emacs 52(cc-bytecomp-defvar mark-active) ; Emacs
56(cc-bytecomp-defvar deactivate-mark) ; Emacs 53(cc-bytecomp-defvar deactivate-mark) ; Emacs
57(cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs 54(cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs
58(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs 55(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs
59(cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21 56(cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21
60(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs
61(cc-bytecomp-defun string-to-syntax) ; Emacs 21 57(cc-bytecomp-defun string-to-syntax) ; Emacs 21
62 58
63 59
@@ -93,7 +89,7 @@
93 89
94;;; Variables also used at compile time. 90;;; Variables also used at compile time.
95 91
96(defconst c-version "5.32.4" 92(defconst c-version "5.32.5"
97 "CC Mode version number.") 93 "CC Mode version number.")
98 94
99(defconst c-version-sym (intern c-version)) 95(defconst c-version-sym (intern c-version))
@@ -334,6 +330,8 @@ to it is returned. This function does not modify the point or the mark."
334(defmacro c-region-is-active-p () 330(defmacro c-region-is-active-p ()
335 ;; Return t when the region is active. The determination of region 331 ;; Return t when the region is active. The determination of region
336 ;; activeness is different in both Emacs and XEmacs. 332 ;; activeness is different in both Emacs and XEmacs.
333 ;; FIXME? Emacs has region-active-p since 23.1, so maybe this test
334 ;; should be updated.
337 (if (cc-bytecomp-boundp 'mark-active) 335 (if (cc-bytecomp-boundp 'mark-active)
338 ;; Emacs. 336 ;; Emacs.
339 'mark-active 337 'mark-active
@@ -343,7 +341,7 @@ to it is returned. This function does not modify the point or the mark."
343(defmacro c-set-region-active (activate) 341(defmacro c-set-region-active (activate)
344 ;; Activate the region if ACTIVE is non-nil, deactivate it 342 ;; Activate the region if ACTIVE is non-nil, deactivate it
345 ;; otherwise. Covers the differences between Emacs and XEmacs. 343 ;; otherwise. Covers the differences between Emacs and XEmacs.
346 (if (cc-bytecomp-fboundp 'zmacs-activate-region) 344 (if (fboundp 'zmacs-activate-region)
347 ;; XEmacs. 345 ;; XEmacs.
348 `(if ,activate 346 `(if ,activate
349 (zmacs-activate-region) 347 (zmacs-activate-region)
@@ -707,9 +705,9 @@ be after it."
707 ;; `c-parse-state'. 705 ;; `c-parse-state'.
708 706
709 `(progn 707 `(progn
710 (if (and ,(cc-bytecomp-fboundp 'buffer-syntactic-context-depth) 708 (if (and ,(fboundp 'buffer-syntactic-context-depth)
711 c-enable-xemacs-performance-kludge-p) 709 c-enable-xemacs-performance-kludge-p)
712 ,(when (cc-bytecomp-fboundp 'buffer-syntactic-context-depth) 710 ,(when (fboundp 'buffer-syntactic-context-depth)
713 ;; XEmacs only. This can improve the performance of 711 ;; XEmacs only. This can improve the performance of
714 ;; c-parse-state to between 3 and 60 times faster when 712 ;; c-parse-state to between 3 and 60 times faster when
715 ;; braces are hung. It can also degrade performance by 713 ;; braces are hung. It can also degrade performance by
@@ -1606,7 +1604,7 @@ non-nil, a caret is prepended to invert the set."
1606 (let ((buf (generate-new-buffer " test")) 1604 (let ((buf (generate-new-buffer " test"))
1607 parse-sexp-lookup-properties 1605 parse-sexp-lookup-properties
1608 parse-sexp-ignore-comments 1606 parse-sexp-ignore-comments
1609 lookup-syntax-properties) 1607 lookup-syntax-properties) ; XEmacs
1610 (with-current-buffer buf 1608 (with-current-buffer buf
1611 (set-syntax-table (make-syntax-table)) 1609 (set-syntax-table (make-syntax-table))
1612 1610
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 368b1fc50dc..b0c0bfd7bde 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -147,9 +147,6 @@
147(cc-require-when-compile 'cc-langs) 147(cc-require-when-compile 'cc-langs)
148(cc-require 'cc-vars) 148(cc-require 'cc-vars)
149 149
150;; Silence the compiler.
151(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
152
153 150
154;; Make declarations for all the `c-lang-defvar' variables in cc-langs. 151;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
155 152
@@ -2180,32 +2177,45 @@ comment at the start of cc-engine.el for more info."
2180;; reduced by buffer changes, and increased by invocations of 2177;; reduced by buffer changes, and increased by invocations of
2181;; `c-state-literal-at'. FIXME!!! 2178;; `c-state-literal-at'. FIXME!!!
2182 2179
2183(defsubst c-state-pp-to-literal (from to) 2180(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter)
2184 ;; Do a parse-partial-sexp from FROM to TO, returning either 2181 ;; Do a parse-partial-sexp from FROM to TO, returning either
2185 ;; (STATE TYPE (BEG . END)) if TO is in a literal; or 2182 ;; (STATE TYPE (BEG . END)) if TO is in a literal; or
2186 ;; (STATE) otherwise, 2183 ;; (STATE) otherwise,
2187 ;; where STATE is the parsing state at TO, TYPE is the type of the literal 2184 ;; where STATE is the parsing state at TO, TYPE is the type of the literal
2188 ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal. 2185 ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
2189 ;; 2186 ;;
2187 ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
2188 ;; comment opener, this is recognized as being in a comment literal.
2189 ;;
2190 ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), 2190 ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote),
2191 ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of 2191 ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
2192 ;; STATE are valid. 2192 ;; STATE are valid.
2193 (save-excursion 2193 (save-excursion
2194 (let ((s (parse-partial-sexp from to)) 2194 (let ((s (parse-partial-sexp from to))
2195 ty) 2195 ty co-st)
2196 (when (or (nth 3 s) (nth 4 s)) ; in a string or comment 2196 (cond
2197 ((or (nth 3 s) (nth 4 s)) ; in a string or comment
2197 (setq ty (cond 2198 (setq ty (cond
2198 ((nth 3 s) 'string) 2199 ((nth 3 s) 'string)
2199 ((eq (nth 7 s) t) 'c++) 2200 ((nth 7 s) 'c++)
2200 (t 'c))) 2201 (t 'c)))
2201 (parse-partial-sexp (point) (point-max) 2202 (parse-partial-sexp (point) (point-max)
2202 nil ; TARGETDEPTH 2203 nil ; TARGETDEPTH
2203 nil ; STOPBEFORE 2204 nil ; STOPBEFORE
2204 s ; OLDSTATE 2205 s ; OLDSTATE
2205 'syntax-table)) ; stop at end of literal 2206 'syntax-table) ; stop at end of literal
2206 (if ty 2207 `(,s ,ty (,(nth 8 s) . ,(point))))
2207 `(,s ,ty (,(nth 8 s) . ,(point))) 2208
2208 `(,s))))) 2209 ((and (not not-in-delimiter) ; inside a comment starter
2210 (not (bobp))
2211 (progn (backward-char)
2212 (looking-at c-comment-start-regexp)))
2213 (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
2214 co-st (point))
2215 (forward-comment 1)
2216 `(,s ,ty (,co-st . ,(point))))
2217
2218 (t `(,s))))))
2209 2219
2210(defun c-state-safe-place (here) 2220(defun c-state-safe-place (here)
2211 ;; Return a buffer position before HERE which is "safe", i.e. outside any 2221 ;; Return a buffer position before HERE which is "safe", i.e. outside any
@@ -3143,10 +3153,13 @@ comment at the start of cc-engine.el for more info."
3143 ;; This function is called from c-after-change. 3153 ;; This function is called from c-after-change.
3144 3154
3145 ;; The caches of non-literals: 3155 ;; The caches of non-literals:
3146 (if (< here c-state-nonlit-pos-cache-limit) 3156 ;; Note that we use "<=" for the possibility of the second char of a two-char
3147 (setq c-state-nonlit-pos-cache-limit here)) 3157 ;; comment opener being typed; this would invalidate any cache position at
3148 (if (< here c-state-semi-nonlit-pos-cache-limit) 3158 ;; HERE.
3149 (setq c-state-semi-nonlit-pos-cache-limit here)) 3159 (if (<= here c-state-nonlit-pos-cache-limit)
3160 (setq c-state-nonlit-pos-cache-limit (1- here)))
3161 (if (<= here c-state-semi-nonlit-pos-cache-limit)
3162 (setq c-state-semi-nonlit-pos-cache-limit (1- here)))
3150 3163
3151 ;; `c-state-cache': 3164 ;; `c-state-cache':
3152 ;; Case 1: if `here' is in a literal containing point-min, everything 3165 ;; Case 1: if `here' is in a literal containing point-min, everything
@@ -4444,19 +4457,12 @@ comment at the start of cc-engine.el for more info."
4444 (lim (or lim (c-state-semi-safe-place pos))) 4457 (lim (or lim (c-state-semi-safe-place pos)))
4445 (pp-to-lit (save-restriction 4458 (pp-to-lit (save-restriction
4446 (widen) 4459 (widen)
4447 (c-state-pp-to-literal lim pos))) 4460 (c-state-pp-to-literal lim pos not-in-delimiter)))
4448 (state (car pp-to-lit)) 4461 (state (car pp-to-lit))
4449 (lit-limits (car (cddr pp-to-lit)))) 4462 (lit-limits (car (cddr pp-to-lit))))
4450 4463
4451 (cond 4464 (cond
4452 (lit-limits) 4465 (lit-limits)
4453 ((and (not not-in-delimiter)
4454 (not (elt state 5))
4455 (eq (char-before) ?/)
4456 (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter. 2008-09-28.
4457 ;; We're standing in a comment starter.
4458 (backward-char 1)
4459 (cons (point) (progn (c-forward-single-comment) (point))))
4460 4466
4461 (near 4467 (near
4462 (goto-char pos) 4468 (goto-char pos)
@@ -6466,6 +6472,52 @@ comment at the start of cc-engine.el for more info."
6466 (c-go-list-forward) 6472 (c-go-list-forward)
6467 t))) 6473 t)))
6468 6474
6475(defun c-back-over-member-initializers ()
6476 ;; Test whether we are in a C++ member initializer list, and if so, go back
6477 ;; to the introducing ":", returning the position of the opening paren of
6478 ;; the function's arglist. Otherwise return nil, leaving point unchanged.
6479 (let ((here (point))
6480 (paren-state (c-parse-state))
6481 res)
6482
6483 (setq res
6484 (catch 'done
6485 (if (not (c-at-toplevel-p))
6486 (progn
6487 (while (not (c-at-toplevel-p))
6488 (goto-char (c-pull-open-brace paren-state)))
6489 (c-backward-syntactic-ws)
6490 (when (not (c-simple-skip-symbol-backward))
6491 (throw 'done nil))
6492 (c-backward-syntactic-ws))
6493 (c-backward-syntactic-ws)
6494 (when (memq (char-before) '(?\) ?}))
6495 (when (not (c-go-list-backward))
6496 (throw 'done nil))
6497 (c-backward-syntactic-ws))
6498 (when (c-simple-skip-symbol-backward)
6499 (c-backward-syntactic-ws)))
6500
6501 (while (eq (char-before) ?,)
6502 (backward-char)
6503 (c-backward-syntactic-ws)
6504
6505 (when (not (memq (char-before) '(?\) ?})))
6506 (throw 'done nil))
6507 (when (not (c-go-list-backward))
6508 (throw 'done nil))
6509 (c-backward-syntactic-ws)
6510 (when (not (c-simple-skip-symbol-backward))
6511 (throw 'done nil))
6512 (c-backward-syntactic-ws))
6513
6514 (and
6515 (eq (char-before) ?:)
6516 (c-just-after-func-arglist-p))))
6517
6518 (or res (goto-char here))
6519 res))
6520
6469 6521
6470;; Handling of large scale constructs like statements and declarations. 6522;; Handling of large scale constructs like statements and declarations.
6471 6523
@@ -9668,18 +9720,13 @@ comment at the start of cc-engine.el for more info."
9668 ;; 2007-11-09) 9720 ;; 2007-11-09)
9669 )))) 9721 ))))
9670 9722
9671 ;; CASE 5B: After a function header but before the body (or 9723 ;; CASE 5R: Member init list. (Used to be part of CASE 5B.1)
9672 ;; the ending semicolon if there's no body). 9724 ;; Note there is no limit on the backward search here, since member
9725 ;; init lists can, in practice, be very large.
9673 ((save-excursion 9726 ((save-excursion
9674 (when (setq placeholder (c-just-after-func-arglist-p 9727 (when (setq placeholder (c-back-over-member-initializers))
9675 (max lim (c-determine-limit 500))))
9676 (setq tmp-pos (point)))) 9728 (setq tmp-pos (point))))
9677 (cond 9729 (if (= (c-point 'bosws) (1+ tmp-pos))
9678
9679 ;; CASE 5B.1: Member init list.
9680 ((eq (char-after tmp-pos) ?:)
9681 (if (or (>= tmp-pos indent-point)
9682 (= (c-point 'bosws) (1+ tmp-pos)))
9683 (progn 9730 (progn
9684 ;; There is no preceding member init clause. 9731 ;; There is no preceding member init clause.
9685 ;; Indent relative to the beginning of indentation 9732 ;; Indent relative to the beginning of indentation
@@ -9692,6 +9739,23 @@ comment at the start of cc-engine.el for more info."
9692 (c-forward-syntactic-ws) 9739 (c-forward-syntactic-ws)
9693 (c-add-syntax 'member-init-cont (point)))) 9740 (c-add-syntax 'member-init-cont (point))))
9694 9741
9742 ;; CASE 5B: After a function header but before the body (or
9743 ;; the ending semicolon if there's no body).
9744 ((save-excursion
9745 (when (setq placeholder (c-just-after-func-arglist-p
9746 (max lim (c-determine-limit 500))))
9747 (setq tmp-pos (point))))
9748 (cond
9749
9750 ;; CASE 5B.1: Member init list.
9751 ((eq (char-after tmp-pos) ?:)
9752 ;; There is no preceding member init clause.
9753 ;; Indent relative to the beginning of indentation
9754 ;; for the topmost-intro line that contains the
9755 ;; prototype's open paren.
9756 (goto-char placeholder)
9757 (c-add-syntax 'member-init-intro (c-point 'boi)))
9758
9695 ;; CASE 5B.2: K&R arg decl intro 9759 ;; CASE 5B.2: K&R arg decl intro
9696 ((and c-recognize-knr-p 9760 ((and c-recognize-knr-p
9697 (c-in-knr-argdecl lim)) 9761 (c-in-knr-argdecl lim))
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index f6c47f5bb4d..6a4bfd9e875 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -176,7 +176,6 @@
176 'font-lock-negation-char-face)) 176 'font-lock-negation-char-face))
177 177
178(cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs. 178(cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs.
179(cc-bytecomp-defun face-property-instance) ; Only in XEmacs.
180 179
181(defun c-make-inverse-face (oldface newface) 180(defun c-make-inverse-face (oldface newface)
182 ;; Emacs and XEmacs have completely different face manipulation 181 ;; Emacs and XEmacs have completely different face manipulation
@@ -2486,7 +2485,7 @@ need for `pike-font-lock-extra-types'.")
2486 (setq comment-beg nil)) 2485 (setq comment-beg nil))
2487 (setq region-beg comment-beg)) 2486 (setq region-beg comment-beg))
2488 2487
2489 (if (eq (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7) t) 2488 (if (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7)
2490 ;; Collect a sequence of doc style line comments. 2489 ;; Collect a sequence of doc style line comments.
2491 (progn 2490 (progn
2492 (goto-char comment-beg) 2491 (goto-char comment-beg)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index ba9c42e4c89..af52ad53aad 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -812,8 +812,8 @@ Assumed to not contain any submatches or \\| operators."
812(c-lang-defconst c-anchored-cpp-prefix 812(c-lang-defconst c-anchored-cpp-prefix
813 "Regexp matching the prefix of a cpp directive anchored to BOL, 813 "Regexp matching the prefix of a cpp directive anchored to BOL,
814in the languages that have a macro preprocessor." 814in the languages that have a macro preprocessor."
815 t (if (c-lang-const c-opt-cpp-prefix) 815 t "^\\s *\\(#\\)\\s *"
816 (concat "^" (c-lang-const c-opt-cpp-prefix)))) 816 (java awk) nil)
817(c-lang-defvar c-anchored-cpp-prefix (c-lang-const c-anchored-cpp-prefix)) 817(c-lang-defvar c-anchored-cpp-prefix (c-lang-const c-anchored-cpp-prefix))
818 818
819(c-lang-defconst c-opt-cpp-start 819(c-lang-defconst c-opt-cpp-start
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el
index a06eaf566d8..067a4df13dd 100644
--- a/lisp/progmodes/cc-menus.el
+++ b/lisp/progmodes/cc-menus.el
@@ -161,49 +161,132 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
161 cc-imenu-c++-generic-expression 161 cc-imenu-c++-generic-expression
162 "Imenu generic expression for C mode. See `imenu-generic-expression'.") 162 "Imenu generic expression for C mode. See `imenu-generic-expression'.")
163 163
164(defvar cc-imenu-java-generic-expression 164
165;; Auxiliary regexps for Java try to match their trailing whitespace where
166;; appropriate, but _not_ starting whitespace.
167
168(defconst cc-imenu-java-ellipsis-regexp
169 (concat
170 "\\.\\{3\\}"
171 "[ \t\n\r]*"))
172
173(defun cc-imenu-java-build-type-args-regex (depth)
174 "Builds regexp for type arguments list with DEPTH allowed
175nested angle brackets constructs."
176 (if (> depth 0)
177 (concat "<"
178 "[][.," c-alnum "_? \t\n\r]+"
179 (if (> depth 1)
180 "\\(")
181 (cc-imenu-java-build-type-args-regex (1- depth))
182 (if (> depth 1)
183 (concat "[][.," c-alnum "_? \t\n\r]*"
184 "\\)*"))
185 ">")))
186
187(defconst cc-imenu-java-type-spec-regexp
188 (concat
189 ;; zero or more identifiers followed by a dot
190 "\\("
191 "[" c-alpha "_][" c-alnum "_]*\\."
192 "\\)*"
193 ;; a single mandatory identifier without a dot
194 "[" c-alpha "_][" c-alnum "_]*"
195 ;; then choice:
196 "\\("
197 ;; (option 1) type arguments list which _may_ be followed with brackets
198 ;; and/or spaces, then optional variable arity
199 "[ \t\n\r]*"
200 (cc-imenu-java-build-type-args-regex 3)
201 "[][ \t\n\r]*"
202 "\\(" cc-imenu-java-ellipsis-regexp "\\)?"
203 "\\|"
204 ;; (option 2) just brackets and/or spaces (there should be at least one),
205 ;; then optional variable arity
206 "[][ \t\n\r]+"
207 "\\(" cc-imenu-java-ellipsis-regexp "\\)?"
208 "\\|"
209 ;; (option 3) just variable arity
210 cc-imenu-java-ellipsis-regexp
211 "\\)"))
212
213(defconst cc-imenu-java-comment-regexp
214 (concat
215 "/"
216 "\\("
217 ;; a traditional comment
218 "\\*"
219 "\\("
220 "[^*]"
221 "\\|"
222 "\\*+[^/*]"
223 "\\)*"
224 "\\*+/"
225 "\\|"
226 ;; an end-of-line comment
227 "/[^\n\r]*[\n\r]"
228 "\\)"
229 "[ \t\n\r]*"
230 ))
231
232;; Comments are allowed before the argument, after any of the
233;; modifiers and after the identifier.
234(defconst cc-imenu-java-method-arg-regexp
235 (concat
236 "\\(" cc-imenu-java-comment-regexp "\\)*"
237 ;; optional modifiers
238 "\\("
239 ;; a modifier is either an annotation or "final"
240 "\\("
241 "@[" c-alpha "_]"
242 "[" c-alnum "._]*"
243 ;; TODO support element-value pairs!
244 "\\|"
245 "final"
246 "\\)"
247 ;; a modifier ends with comments and/or ws
248 "\\("
249 "\\(" cc-imenu-java-comment-regexp "\\)+"
250 "\\|"
251 "[ \t\n\r]+"
252 "\\(" cc-imenu-java-comment-regexp "\\)*"
253 "\\)"
254 "\\)*"
255 ;; type spec
256 cc-imenu-java-type-spec-regexp
257 ;; identifier
258 "[" c-alpha "_]"
259 "[" c-alnum "_]*"
260 ;; optional comments and/or ws
261 "[ \t\n\r]*"
262 "\\(" cc-imenu-java-comment-regexp "\\)*"
263 ))
264
265(defconst cc-imenu-java-generic-expression
165 `((nil 266 `((nil
166 ,(concat 267 ,(concat
167 "[" c-alpha "_][\]\[." c-alnum "_<> ]+[ \t\n\r]+" ; type spec 268 cc-imenu-java-type-spec-regexp
168 "\\([" c-alpha "_][" c-alnum "_]*\\)" ; method name 269 "\\(" ; method name which gets captured
270 ; into index
271 "[" c-alpha "_]"
272 "[" c-alnum "_]*"
273 "\\)"
169 "[ \t\n\r]*" 274 "[ \t\n\r]*"
170 ;; An argument list htat is either empty or contains any number 275 ;; An argument list that contains zero or more arguments.
171 ;; of arguments. An argument is any number of annotations 276 (concat
172 ;; followed by a type spec followed by a word. A word is an 277 "("
173 ;; identifier. A type spec is an identifier, possibly followed 278 "[ \t\n\r]*"
174 ;; by < typespec > possibly followed by []. 279 "\\("
175 (concat "(" 280 "\\(" cc-imenu-java-method-arg-regexp ",[ \t\n\r]*\\)*"
176 "\\(" 281 cc-imenu-java-method-arg-regexp
177 "[ \t\n\r]*" 282 "\\)?"
178 "\\(" 283 ")"
179 "@" 284 "[.,_" c-alnum " \t\n\r]*" ; throws etc.
180 "[" c-alpha "_]" 285 "{"
181 "[" c-alnum "._]""*" 286 )) 7))
182 "[ \t\n\r]+"
183 "\\)*"
184 "\\("
185 "[" c-alpha "_]"
186 "[\]\[" c-alnum "_.]*"
187 "\\("
188
189 "<"
190 "[ \t\n\r]*"
191 "[\]\[.," c-alnum "_<> \t\n\r]*"
192 ">"
193 "\\)?"
194 "\\(\\[\\]\\)?"
195 "[ \t\n\r]+"
196 "\\)"
197 "[" c-alpha "_]"
198 "[" c-alnum "_]*"
199 "[ \t\n\r,]*"
200 "\\)*"
201 ")"
202 "[.," c-alnum " \t\n\r]*"
203 "{"
204 )) 1))
205 "Imenu generic expression for Java mode. See `imenu-generic-expression'.") 287 "Imenu generic expression for Java mode. See `imenu-generic-expression'.")
206 288
289
207;; Internal variables 290;; Internal variables
208(defvar cc-imenu-objc-generic-expression-noreturn-index nil) 291(defvar cc-imenu-objc-generic-expression-noreturn-index nil)
209(defvar cc-imenu-objc-generic-expression-general-func-index nil) 292(defvar cc-imenu-objc-generic-expression-general-func-index nil)
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 3c3a5766582..36c9f72fa18 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -86,8 +86,8 @@
86 (load "cc-bytecomp" nil t))) 86 (load "cc-bytecomp" nil t)))
87 87
88(cc-require 'cc-defs) 88(cc-require 'cc-defs)
89(cc-require-when-compile 'cc-langs)
90(cc-require 'cc-vars) 89(cc-require 'cc-vars)
90(cc-require-when-compile 'cc-langs)
91(cc-require 'cc-engine) 91(cc-require 'cc-engine)
92(cc-require 'cc-styles) 92(cc-require 'cc-styles)
93(cc-require 'cc-cmds) 93(cc-require 'cc-cmds)
@@ -97,7 +97,6 @@
97 97
98;; Silence the compiler. 98;; Silence the compiler.
99(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs 99(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
100(cc-bytecomp-defun set-keymap-parents) ; XEmacs
101(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1 100(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1
102 101
103;; We set these variables during mode init, yet we don't require 102;; We set these variables during mode init, yet we don't require
@@ -212,7 +211,7 @@ control). See \"cc-mode.el\" for more info."
212 ((cc-bytecomp-fboundp 'set-keymap-parent) 211 ((cc-bytecomp-fboundp 'set-keymap-parent)
213 (set-keymap-parent map c-mode-base-map)) 212 (set-keymap-parent map c-mode-base-map))
214 ;; XEmacs 213 ;; XEmacs
215 ((cc-bytecomp-fboundp 'set-keymap-parents) 214 ((fboundp 'set-keymap-parents)
216 (set-keymap-parents map c-mode-base-map)) 215 (set-keymap-parents map c-mode-base-map))
217 ;; incompatible 216 ;; incompatible
218 (t (error "CC Mode is incompatible with this version of Emacs"))) 217 (t (error "CC Mode is incompatible with this version of Emacs")))
@@ -936,7 +935,8 @@ Note that the style variables are always made local to the buffer."
936 935
937 ;; Add needed properties to each CPP construct in the region. 936 ;; Add needed properties to each CPP construct in the region.
938 (goto-char c-new-BEG) 937 (goto-char c-new-BEG)
939 (let ((pps-position c-new-BEG) pps-state mbeg) 938 (skip-chars-backward " \t")
939 (let ((pps-position (point)) pps-state mbeg)
940 (while (and (< (point) c-new-END) 940 (while (and (< (point) c-new-END)
941 (search-forward-regexp c-anchored-cpp-prefix c-new-END t)) 941 (search-forward-regexp c-anchored-cpp-prefix c-new-END t))
942 ;; If we've found a "#" inside a string/comment, ignore it. 942 ;; If we've found a "#" inside a string/comment, ignore it.
@@ -945,14 +945,12 @@ Note that the style variables are always made local to the buffer."
945 pps-position (point)) 945 pps-position (point))
946 (unless (or (nth 3 pps-state) ; in a string? 946 (unless (or (nth 3 pps-state) ; in a string?
947 (nth 4 pps-state)) ; in a comment? 947 (nth 4 pps-state)) ; in a comment?
948 (goto-char (match-beginning 0)) 948 (goto-char (match-beginning 1))
949 (setq mbeg (point)) 949 (setq mbeg (point))
950 (if (> (c-syntactic-end-of-macro) mbeg) 950 (if (> (c-syntactic-end-of-macro) mbeg)
951 (progn 951 (progn
952 (c-neutralize-CPP-line mbeg (point)) 952 (c-neutralize-CPP-line mbeg (point))
953 (c-set-cpp-delimiters mbeg (point)) 953 (c-set-cpp-delimiters mbeg (point)))
954 ;(setq pps-position (point))
955 )
956 (forward-line)) ; no infinite loop with, e.g., "#//" 954 (forward-line)) ; no infinite loop with, e.g., "#//"
957 ))))) 955 )))))
958 956
@@ -1060,7 +1058,7 @@ Note that the style variables are always made local to the buffer."
1060 ;; This calls the language variable c-before-font-lock-functions, if non nil. 1058 ;; This calls the language variable c-before-font-lock-functions, if non nil.
1061 ;; This typically sets `syntax-table' properties. 1059 ;; This typically sets `syntax-table' properties.
1062 1060
1063 (c-save-buffer-state () 1061 (c-save-buffer-state (case-fold-search)
1064 ;; When `combine-after-change-calls' is used we might get calls 1062 ;; When `combine-after-change-calls' is used we might get calls
1065 ;; with regions outside the current narrowing. This has been 1063 ;; with regions outside the current narrowing. This has been
1066 ;; observed in Emacs 20.7. 1064 ;; observed in Emacs 20.7.
@@ -1078,12 +1076,13 @@ Note that the style variables are always made local to the buffer."
1078 (setq beg end))) 1076 (setq beg end)))
1079 1077
1080 ;; C-y is capable of spuriously converting category properties 1078 ;; C-y is capable of spuriously converting category properties
1081 ;; c-</>-as-paren-syntax into hard syntax-table properties. Remove 1079 ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
1082 ;; these when it happens. 1080 ;; properties. Remove these when it happens.
1083 (c-clear-char-property-with-value beg end 'syntax-table 1081 (c-clear-char-property-with-value beg end 'syntax-table
1084 c-<-as-paren-syntax) 1082 c-<-as-paren-syntax)
1085 (c-clear-char-property-with-value beg end 'syntax-table 1083 (c-clear-char-property-with-value beg end 'syntax-table
1086 c->-as-paren-syntax) 1084 c->-as-paren-syntax)
1085 (c-clear-char-property-with-value beg end 'syntax-table nil)
1087 1086
1088 (c-trim-found-types beg end old-len) ; maybe we don't need all of these. 1087 (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
1089 (c-invalidate-sws-region-after beg end) 1088 (c-invalidate-sws-region-after beg end)
@@ -1161,9 +1160,6 @@ Note that the style variables are always made local to the buffer."
1161 ;; `c-set-fl-decl-start' for the detailed functionality. 1160 ;; `c-set-fl-decl-start' for the detailed functionality.
1162 (cons (c-set-fl-decl-start beg) end)) 1161 (cons (c-set-fl-decl-start beg) end))
1163 1162
1164(defvar c-standard-font-lock-fontify-region-function nil
1165 "Standard value of `font-lock-fontify-region-function'")
1166
1167(defun c-font-lock-fontify-region (beg end &optional verbose) 1163(defun c-font-lock-fontify-region (beg end &optional verbose)
1168 ;; Effectively advice around `font-lock-fontify-region' which extends the 1164 ;; Effectively advice around `font-lock-fontify-region' which extends the
1169 ;; region (BEG END), for example, to avoid context fontification chopping 1165 ;; region (BEG END), for example, to avoid context fontification chopping
@@ -1188,17 +1184,14 @@ Note that the style variables are always made local to the buffer."
1188 (setq new-region (funcall fn new-beg new-end)) 1184 (setq new-region (funcall fn new-beg new-end))
1189 (setq new-beg (car new-region) new-end (cdr new-region))) 1185 (setq new-beg (car new-region) new-end (cdr new-region)))
1190 c-before-context-fontification-functions)))) 1186 c-before-context-fontification-functions))))
1191 (funcall c-standard-font-lock-fontify-region-function 1187 (funcall (default-value 'font-lock-fontify-region-function)
1192 new-beg new-end verbose))) 1188 new-beg new-end verbose)))
1193 1189
1194(defun c-after-font-lock-init () 1190(defun c-after-font-lock-init ()
1195 ;; Put on `font-lock-mode-hook'. This function ensures our after-change 1191 ;; Put on `font-lock-mode-hook'. This function ensures our after-change
1196 ;; function will get executed before the font-lock one. Amongst other 1192 ;; function will get executed before the font-lock one.
1197 ;; things.
1198 (remove-hook 'after-change-functions 'c-after-change t) 1193 (remove-hook 'after-change-functions 'c-after-change t)
1199 (add-hook 'after-change-functions 'c-after-change nil t) 1194 (add-hook 'after-change-functions 'c-after-change nil t))
1200 (setq c-standard-font-lock-fontify-region-function
1201 (default-value 'font-lock-fontify-region-function)))
1202 1195
1203(defun c-font-lock-init () 1196(defun c-font-lock-init ()
1204 "Set up the font-lock variables for using the font-lock support in CC Mode. 1197 "Set up the font-lock variables for using the font-lock support in CC Mode.
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 66ff217c73e..c89402c63a3 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -42,23 +42,25 @@
42 42
43(cc-require 'cc-defs) 43(cc-require 'cc-defs)
44 44
45;; Silence the compiler.
46(cc-bytecomp-defun get-char-table) ; XEmacs
47
48(cc-eval-when-compile 45(cc-eval-when-compile
49 (require 'custom) 46 (require 'custom)
50 (require 'widget)) 47 (require 'widget))
51 48
52;;; Helpers 49;;; Helpers
53 50
54;; This widget exists in newer versions of the Custom library 51
55(or (get 'other 'widget-type) 52;; Emacs has 'other since at least version 21.1.
56 (define-widget 'other 'sexp 53;; FIXME this is probably broken, since the widget is defined
57 "Matches everything, but doesn't let the user edit the value. 54;; in wid-edit, which this file does not load. So we will always
55;; define the widget, even when we don't need to.
56(when (featurep 'xemacs)
57 (or (get 'other 'widget-type)
58 (define-widget 'other 'sexp
59 "Matches everything, but doesn't let the user edit the value.
58Useful as last item in a `choice' widget." 60Useful as last item in a `choice' widget."
59 :tag "Other" 61 :tag "Other"
60 :format "%t%n" 62 :format "%t%n"
61 :value 'other)) 63 :value 'other)))
62 64
63;; The next defun will supersede c-const-symbol. 65;; The next defun will supersede c-const-symbol.
64(eval-and-compile 66(eval-and-compile
@@ -1622,11 +1624,30 @@ names)."))
1622) 1624)
1623(make-variable-buffer-local 'c-macro-with-semi-re) 1625(make-variable-buffer-local 'c-macro-with-semi-re)
1624 1626
1627(defvar c-macro-names-with-semicolon
1628 '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS")
1629 "List of #defined symbols whose expansion ends with a semicolon.
1630Alternatively it can be a string, a regular expression which
1631matches all such symbols.
1632
1633The \"symbols\" must be syntactically valid identifiers in the
1634target language \(C, C++, Objective C), or \(as the case may be)
1635the regular expression must match only valid identifiers.
1636
1637If you change this variable's value, call the function
1638`c-make-macros-with-semi-re' to set the necessary internal
1639variables.
1640
1641Note that currently \(2008-11-04) this variable is a prototype,
1642and is likely to disappear or change its form soon.")
1643(make-variable-buffer-local 'c-macro-names-with-semicolon)
1644
1625(defun c-make-macro-with-semi-re () 1645(defun c-make-macro-with-semi-re ()
1626 ;; Convert `c-macro-names-with-semicolon' into the regexp 1646 ;; Convert `c-macro-names-with-semicolon' into the regexp
1627 ;; `c-macro-with-semi-re' (or just copy it if it's already a re). 1647 ;; `c-macro-with-semi-re' (or just copy it if it's already a re).
1628 (setq c-macro-with-semi-re 1648 (setq c-macro-with-semi-re
1629 (and 1649 (and
1650 (boundp 'c-opt-cpp-macro-define)
1630 c-opt-cpp-macro-define 1651 c-opt-cpp-macro-define
1631 (cond 1652 (cond
1632 ((stringp c-macro-names-with-semicolon) 1653 ((stringp c-macro-names-with-semicolon)
@@ -1643,24 +1664,6 @@ names)."))
1643c-macro-names-with-semicolon: %s" 1664c-macro-names-with-semicolon: %s"
1644 c-macro-names-with-semicolon)))))) 1665 c-macro-names-with-semicolon))))))
1645 1666
1646(defvar c-macro-names-with-semicolon
1647 '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS")
1648 "List of #defined symbols whose expansion ends with a semicolon.
1649Alternatively it can be a string, a regular expression which
1650matches all such symbols.
1651
1652The \"symbols\" must be syntactically valid identifiers in the
1653target language \(C, C++, Objective C), or \(as the case may be)
1654the regular expression must match only valid identifiers.
1655
1656If you change this variable's value, call the function
1657`c-make-macros-with-semi-re' to set the necessary internal
1658variables.
1659
1660Note that currently \(2008-11-04) this variable is a prototype,
1661and is likely to disappear or change its form soon.")
1662(make-variable-buffer-local 'c-macro-names-with-semicolon)
1663
1664(defvar c-file-style nil 1667(defvar c-file-style nil
1665 "Variable interface for setting style via File Local Variables. 1668 "Variable interface for setting style via File Local Variables.
1666In a file's Local Variable section, you can set this variable to a 1669In a file's Local Variable section, you can set this variable to a
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 74b81b0cd01..11eb0eeaf49 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -30,11 +30,13 @@
30;; The CFEngine 3.x support doesn't have Imenu support but patches are 30;; The CFEngine 3.x support doesn't have Imenu support but patches are
31;; welcome. 31;; welcome.
32 32
33;; By default, CFEngine 3.x syntax is used.
34
33;; You can set it up so either `cfengine2-mode' (2.x and earlier) or 35;; You can set it up so either `cfengine2-mode' (2.x and earlier) or
34;; `cfengine3-mode' (3.x) will be picked, depending on the buffer 36;; `cfengine3-mode' (3.x) will be picked, depending on the buffer
35;; contents: 37;; contents:
36 38
37;; (add-to-list 'auto-mode-alist '("\\.cf\\'" . cfengine-mode)) 39;; (add-to-list 'auto-mode-alist '("\\.cf\\'" . cfengine-auto-mode))
38 40
39;; OR you can choose to always use a specific version, if you prefer 41;; OR you can choose to always use a specific version, if you prefer
40;; it: 42;; it:
@@ -181,7 +183,7 @@ This includes those for cfservd as well as cfagent.")
181 ("$(\\([[:alnum:]_]+\\))" 1 font-lock-variable-name-face) 183 ("$(\\([[:alnum:]_]+\\))" 1 font-lock-variable-name-face)
182 ("${\\([[:alnum:]_]+\\)}" 1 font-lock-variable-name-face) 184 ("${\\([[:alnum:]_]+\\)}" 1 font-lock-variable-name-face)
183 ;; Variable definitions. 185 ;; Variable definitions.
184 ("\\<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1 font-lock-variable-name-face) 186 ("\\_<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1 font-lock-variable-name-face)
185 ;; File, acl &c in group: { token ... } 187 ;; File, acl &c in group: { token ... }
186 ("{[ \t]*\\([^ \t\n]+\\)" 1 font-lock-constant-face))) 188 ("{[ \t]*\\([^ \t\n]+\\)" 1 font-lock-constant-face)))
187 189
@@ -189,9 +191,9 @@ This includes those for cfservd as well as cfagent.")
189 `( 191 `(
190 ;; Defuns. This happens early so they don't get caught by looser 192 ;; Defuns. This happens early so they don't get caught by looser
191 ;; patterns. 193 ;; patterns.
192 (,(concat "\\<" cfengine3-defuns-regex "\\>" 194 (,(concat "\\_<" cfengine3-defuns-regex "\\_>"
193 "[ \t]+\\<\\([[:alnum:]_.:]+\\)\\>" 195 "[ \t]+\\_<\\([[:alnum:]_.:]+\\)\\_>"
194 "[ \t]+\\<\\([[:alnum:]_.:]+\\)" 196 "[ \t]+\\_<\\([[:alnum:]_.:]+\\)"
195 ;; Optional parentheses with variable names inside. 197 ;; Optional parentheses with variable names inside.
196 "\\(?:(\\([^)]*\\))\\)?") 198 "\\(?:(\\([^)]*\\))\\)?")
197 (1 font-lock-builtin-face) 199 (1 font-lock-builtin-face)
@@ -212,10 +214,10 @@ This includes those for cfservd as well as cfagent.")
212 ("[@$]{\\([[:alnum:]_.:]+\\)}" 1 font-lock-variable-name-face) 214 ("[@$]{\\([[:alnum:]_.:]+\\)}" 1 font-lock-variable-name-face)
213 215
214 ;; Variable definitions. 216 ;; Variable definitions.
215 ("\\<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1 font-lock-variable-name-face) 217 ("\\_<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1 font-lock-variable-name-face)
216 218
217 ;; Variable types. 219 ;; Variable types.
218 (,(concat "\\<" (eval-when-compile (regexp-opt cfengine3-vartypes t)) "\\>") 220 (,(concat "\\_<" (eval-when-compile (regexp-opt cfengine3-vartypes t)) "\\_>")
219 1 font-lock-type-face))) 221 1 font-lock-type-face)))
220 222
221(defvar cfengine2-imenu-expression 223(defvar cfengine2-imenu-expression
@@ -223,9 +225,9 @@ This includes those for cfservd as well as cfagent.")
223 (regexp-opt cfengine2-actions t)) 225 (regexp-opt cfengine2-actions t))
224 ":[^:]") 226 ":[^:]")
225 1) 227 1)
226 ("Variables/classes" "\\<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1) 228 ("Variables/classes" "\\_<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1)
227 ("Variables/classes" "\\<define=\\([[:alnum:]_]+\\)" 1) 229 ("Variables/classes" "\\_<define=\\([[:alnum:]_]+\\)" 1)
228 ("Variables/classes" "\\<DefineClass\\>[ \t]+\\([[:alnum:]_]+\\)" 1)) 230 ("Variables/classes" "\\_<DefineClass\\>[ \t]+\\([[:alnum:]_]+\\)" 1))
229 "`imenu-generic-expression' for CFEngine mode.") 231 "`imenu-generic-expression' for CFEngine mode.")
230 232
231(defun cfengine2-outline-level () 233(defun cfengine2-outline-level ()
@@ -338,7 +340,7 @@ Intended as the value of `indent-line-function'."
338Treats body/bundle blocks as defuns." 340Treats body/bundle blocks as defuns."
339 (unless (<= (current-column) (current-indentation)) 341 (unless (<= (current-column) (current-indentation))
340 (end-of-line)) 342 (end-of-line))
341 (if (re-search-backward (concat "^[ \t]*" cfengine3-defuns-regex "\\>") nil t) 343 (if (re-search-backward (concat "^[ \t]*" cfengine3-defuns-regex "\\_>") nil t)
342 (beginning-of-line) 344 (beginning-of-line)
343 (goto-char (point-min))) 345 (goto-char (point-min)))
344 t) 346 t)
@@ -347,7 +349,7 @@ Treats body/bundle blocks as defuns."
347 "`end-of-defun' function for Cfengine 3 mode. 349 "`end-of-defun' function for Cfengine 3 mode.
348Treats body/bundle blocks as defuns." 350Treats body/bundle blocks as defuns."
349 (end-of-line) 351 (end-of-line)
350 (if (re-search-forward (concat "^[ \t]*" cfengine3-defuns-regex "\\>") nil t) 352 (if (re-search-forward (concat "^[ \t]*" cfengine3-defuns-regex "\\_>") nil t)
351 (beginning-of-line) 353 (beginning-of-line)
352 (goto-char (point-max))) 354 (goto-char (point-max)))
353 t) 355 t)
@@ -366,7 +368,7 @@ Intended as the value of `indent-line-function'."
366 368
367 (cond 369 (cond
368 ;; Body/bundle blocks start at 0. 370 ;; Body/bundle blocks start at 0.
369 ((looking-at (concat cfengine3-defuns-regex "\\>")) 371 ((looking-at (concat cfengine3-defuns-regex "\\_>"))
370 (indent-line-to 0)) 372 (indent-line-to 0))
371 ;; Categories are indented one step. 373 ;; Categories are indented one step.
372 ((looking-at (concat cfengine3-category-regex "[ \t]*\\(#.*\\)*$")) 374 ((looking-at (concat cfengine3-category-regex "[ \t]*\\(#.*\\)*$"))
@@ -583,7 +585,7 @@ on the buffer contents"
583 (save-restriction 585 (save-restriction
584 (goto-char (point-min)) 586 (goto-char (point-min))
585 (while (not (or (eobp) v3)) 587 (while (not (or (eobp) v3))
586 (setq v3 (looking-at (concat cfengine3-defuns-regex "\\>"))) 588 (setq v3 (looking-at (concat cfengine3-defuns-regex "\\_>")))
587 (forward-line))) 589 (forward-line)))
588 (if v3 (cfengine3-mode) (cfengine2-mode)))) 590 (if v3 (cfengine3-mode) (cfengine2-mode))))
589 591
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 9e9e2f0b090..d6f136ec92d 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1814,6 +1814,7 @@ Returns the compilation buffer created."
1814 (define-key map [follow-link] 'mouse-face) 1814 (define-key map [follow-link] 'mouse-face)
1815 (define-key map "\C-c\C-c" 'compile-goto-error) 1815 (define-key map "\C-c\C-c" 'compile-goto-error)
1816 (define-key map "\C-m" 'compile-goto-error) 1816 (define-key map "\C-m" 'compile-goto-error)
1817 (define-key map "\C-o" 'compilation-display-error)
1817 (define-key map "\C-c\C-k" 'kill-compilation) 1818 (define-key map "\C-c\C-k" 'kill-compilation)
1818 (define-key map "\M-n" 'compilation-next-error) 1819 (define-key map "\M-n" 'compilation-next-error)
1819 (define-key map "\M-p" 'compilation-previous-error) 1820 (define-key map "\M-p" 'compilation-previous-error)
@@ -1858,6 +1859,7 @@ Returns the compilation buffer created."
1858 (define-key map [follow-link] 'mouse-face) 1859 (define-key map [follow-link] 'mouse-face)
1859 (define-key map "\C-c\C-c" 'compile-goto-error) 1860 (define-key map "\C-c\C-c" 'compile-goto-error)
1860 (define-key map "\C-m" 'compile-goto-error) 1861 (define-key map "\C-m" 'compile-goto-error)
1862 (define-key map "\C-o" 'compilation-display-error)
1861 (define-key map "\C-c\C-k" 'kill-compilation) 1863 (define-key map "\C-c\C-k" 'kill-compilation)
1862 (define-key map "\M-n" 'compilation-next-error) 1864 (define-key map "\M-n" 'compilation-next-error)
1863 (define-key map "\M-p" 'compilation-previous-error) 1865 (define-key map "\M-p" 'compilation-previous-error)
@@ -2299,6 +2301,12 @@ Prefix arg N says how many files to move backwards (or forwards, if negative)."
2299 (interactive "p") 2301 (interactive "p")
2300 (compilation-next-file (- n))) 2302 (compilation-next-file (- n)))
2301 2303
2304(defun compilation-display-error ()
2305 "Display the source for current error in another window."
2306 (interactive)
2307 (setq compilation-current-error (point))
2308 (next-error-no-select 0))
2309
2302(defun kill-compilation () 2310(defun kill-compilation ()
2303 "Kill the process made by the \\[compile] or \\[grep] commands." 2311 "Kill the process made by the \\[compile] or \\[grep] commands."
2304 (interactive) 2312 (interactive)
@@ -2374,10 +2382,12 @@ This is the value of `next-error-function' in Compilation buffers."
2374 ;; (setq timestamp compilation-buffer-modtime))) 2382 ;; (setq timestamp compilation-buffer-modtime)))
2375 ) 2383 )
2376 (with-current-buffer 2384 (with-current-buffer
2377 (compilation-find-file 2385 (apply #'compilation-find-file
2378 marker 2386 marker
2379 (caar (compilation--loc->file-struct loc)) 2387 (caar (compilation--loc->file-struct loc))
2380 (cadr (car (compilation--loc->file-struct loc)))) 2388 (cadr (car (compilation--loc->file-struct loc)))
2389 (compilation--file-struct->formats
2390 (compilation--loc->file-struct loc)))
2381 (let ((screen-columns 2391 (let ((screen-columns
2382 ;; Obey the compilation-error-screen-columns of the target 2392 ;; Obey the compilation-error-screen-columns of the target
2383 ;; buffer if its major mode set it buffer-locally. 2393 ;; buffer if its major mode set it buffer-locally.
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index e8678fe6281..910e7c49d2a 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -565,6 +565,7 @@ If nil, the value of `cperl-indent-level' will be used."
565 "*Non-nil means that the _ (underline) should be treated as word char." 565 "*Non-nil means that the _ (underline) should be treated as word char."
566 :type 'boolean 566 :type 'boolean
567 :group 'cperl) 567 :group 'cperl)
568(make-obsolete-variable 'cperl-under-as-char 'superword-mode "24.4")
568 569
569(defcustom cperl-extra-perl-args "" 570(defcustom cperl-extra-perl-args ""
570 "*Extra arguments to use when starting Perl. 571 "*Extra arguments to use when starting Perl.
@@ -1905,7 +1906,7 @@ or as help on variables `cperl-tips', `cperl-problems',
1905 (and (boundp 'msb-menu-cond) 1906 (and (boundp 'msb-menu-cond)
1906 (not cperl-msb-fixed) 1907 (not cperl-msb-fixed)
1907 (cperl-msb-fix)) 1908 (cperl-msb-fix))
1908 (if (featurep 'easymenu) 1909 (if (fboundp 'easy-menu-add)
1909 (easy-menu-add cperl-menu)) ; A NOP in Emacs. 1910 (easy-menu-add cperl-menu)) ; A NOP in Emacs.
1910 (run-mode-hooks 'cperl-mode-hook) 1911 (run-mode-hooks 'cperl-mode-hook)
1911 (if cperl-hook-after-change 1912 (if cperl-hook-after-change
@@ -6529,6 +6530,9 @@ side-effect of memorizing only. Examples in `cperl-style-examples'."
6529 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc"))) 6530 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
6530 (eval '(mode-compile)))) ; Avoid a warning 6531 (eval '(mode-compile)))) ; Avoid a warning
6531 6532
6533(declare-function Info-find-node "info"
6534 (filename nodename &optional no-going-back))
6535
6532(defun cperl-info-buffer (type) 6536(defun cperl-info-buffer (type)
6533 ;; Returns buffer with documentation. Creates if missing. 6537 ;; Returns buffer with documentation. Creates if missing.
6534 ;; If TYPE, this vars buffer. 6538 ;; If TYPE, this vars buffer.
@@ -6667,10 +6671,13 @@ Customized by setting variables `cperl-shrink-wrap-info-frame',
6667 (buffer-substring 6671 (buffer-substring
6668 (match-beginning 1) (match-end 1))) 6672 (match-beginning 1) (match-end 1)))
6669 6673
6674(declare-function imenu-choose-buffer-index "imenu" (&optional prompt alist))
6675
6670(defun cperl-imenu-on-info () 6676(defun cperl-imenu-on-info ()
6671 "Shows imenu for Perl Info Buffer. 6677 "Shows imenu for Perl Info Buffer.
6672Opens Perl Info buffer if needed." 6678Opens Perl Info buffer if needed."
6673 (interactive) 6679 (interactive)
6680 (require 'imenu)
6674 (let* ((buffer (current-buffer)) 6681 (let* ((buffer (current-buffer))
6675 imenu-create-index-function 6682 imenu-create-index-function
6676 imenu-prev-index-position-function 6683 imenu-prev-index-position-function
@@ -7130,6 +7137,10 @@ Use as
7130(defvar cperl-hierarchy '(() ()) 7137(defvar cperl-hierarchy '(() ())
7131 "Global hierarchy of classes.") 7138 "Global hierarchy of classes.")
7132 7139
7140;; Follows call to (autoloaded) visit-tags-table.
7141(declare-function file-of-tag "etags" (&optional relative))
7142(declare-function etags-snarf-tag "etags" (&optional use-explicit))
7143
7133(defun cperl-tags-hier-fill () 7144(defun cperl-tags-hier-fill ()
7134 ;; Suppose we are in a tag table cooked by cperl. 7145 ;; Suppose we are in a tag table cooked by cperl.
7135 (goto-char 1) 7146 (goto-char 1)
@@ -7173,6 +7184,7 @@ Use as
7173 (end-of-line)))) 7184 (end-of-line))))
7174 7185
7175(declare-function x-popup-menu "menu.c" (position menu)) 7186(declare-function x-popup-menu "menu.c" (position menu))
7187(declare-function etags-goto-tag-location "etags" (tag-info))
7176 7188
7177(defun cperl-tags-hier-init (&optional update) 7189(defun cperl-tags-hier-init (&optional update)
7178 "Show hierarchical menu of classes and methods. 7190 "Show hierarchical menu of classes and methods.
@@ -8516,6 +8528,8 @@ the appropriate statement modifier."
8516 ;;(error "Not at `if', `unless', `while', `until', `for' or `foreach'") 8528 ;;(error "Not at `if', `unless', `while', `until', `for' or `foreach'")
8517 (cperl-invert-if-unless-modifiers))) 8529 (cperl-invert-if-unless-modifiers)))
8518 8530
8531(declare-function Man-getpage-in-background "man" (topic))
8532
8519;;; By Anthony Foiani <afoiani@uswest.com> 8533;;; By Anthony Foiani <afoiani@uswest.com>
8520;;; Getting help on modules in C-h f ? 8534;;; Getting help on modules in C-h f ?
8521;;; This is a modified version of `man'. 8535;;; This is a modified version of `man'.
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index 674d98b8dc3..d332d8bff31 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -136,13 +136,18 @@ Each entry is a list with the following elements:
136 ("true" . t) 136 ("true" . t)
137 ("both" . both))) 137 ("both" . both)))
138 138
139;; FIXME Gets clobbered by cpp-choose-face, so why is even it a defcustom?
139(defcustom cpp-face-default-list nil 140(defcustom cpp-face-default-list nil
140 "Alist of faces you can choose from for cpp conditionals. 141 "Alist of faces you can choose from for cpp conditionals.
141Each element has the form (STRING . FACE), where STRING 142Each element has the form (STRING . FACE), where STRING
142serves as a name (for `cpp-highlight-buffer' only) 143serves as a name (for `cpp-highlight-buffer' only)
143and FACE is either a face (a symbol) 144and FACE is either a face (a symbol)
144or a cons cell (background-color . COLOR)." 145or a cons cell (background-color . COLOR)."
145 :type '(repeat (cons string (choice face (cons (const background-color) string)))) 146 :type '(alist :key-type (string :tag "Name")
147 :value-type (choice face
148 (const invisible)
149 (cons (const background-color)
150 (string :tag "Color"))))
146 :group 'cpp) 151 :group 'cpp)
147 152
148(defcustom cpp-face-light-name-list 153(defcustom cpp-face-light-name-list
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index dba1d6a2f9b..9bde2900a67 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -247,15 +247,36 @@
247 247
248(defcustom f90-smart-end 'blink 248(defcustom f90-smart-end 'blink
249 "Qualification of END statements according to the matching block start. 249 "Qualification of END statements according to the matching block start.
250For example, the END that closes an IF block is changed to END 250For example, change the END that closes an IF block to END IF.
251IF. If the block has a label, this is added as well. Allowed 251If the block has a label, add it as well (unless `f90-smart-end-names'
252values are 'blink, 'no-blink, and nil. If nil, nothing is done. 252says not to). Allowed values are `blink', `no-blink', and nil. If nil,
253The other two settings have the same effect, but 'blink 253nothing is done. The other two settings have the same effect, but `blink'
254additionally blinks the cursor to the start of the block." 254additionally blinks the cursor to the start of the block."
255 :type '(choice (const blink) (const no-blink) (const nil)) 255 :type '(choice (const blink) (const no-blink) (const nil))
256 :safe (lambda (value) (memq value '(blink no-blink nil))) 256 :safe (lambda (value) (memq value '(blink no-blink nil)))
257 :group 'f90) 257 :group 'f90)
258 258
259;; Optional: program, module, type, function, subroutine
260;; Not optional: block data?, forall, if, select case/type, associate, do,
261;; where, interface, critical
262;; No labels: enum
263(defcustom f90-smart-end-names t
264 "Whether completion of END statements should insert optional block names.
265For example, when closing a \"PROGRAM PROGNAME\" block, \"PROGNAME\" is
266optional in the \"END PROGRAM\" statement. The same is true for modules,
267functions, subroutines, and types. Some people prefer to omit the name
268from the END statement, since it makes it easier to change the name.
269
270This does not apply to named DO, IF, etc. blocks. If such blocks
271start with a label, they must end with one.
272
273If an end statement has a name that does not match the start, it is always
274corrected, regardless of the value of this variable."
275 :type 'boolean
276 :safe 'booleanp
277 :group 'f90
278 :version "24.4")
279
259(defcustom f90-break-delimiters "[-+\\*/><=,% \t]" 280(defcustom f90-break-delimiters "[-+\\*/><=,% \t]"
260 "Regexp matching delimiter characters at which lines may be broken. 281 "Regexp matching delimiter characters at which lines may be broken.
261There are some common two-character tokens where one or more of 282There are some common two-character tokens where one or more of
@@ -298,55 +319,61 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
298;; User options end here. 319;; User options end here.
299 320
300(defconst f90-keywords-re 321(defconst f90-keywords-re
301 (regexp-opt '("allocatable" "allocate" "assign" "assignment" "backspace" 322 (concat
302 "block" "call" "case" "character" "close" "common" "complex" 323 "\\_<"
303 "contains" "continue" "cycle" "data" "deallocate" 324 (regexp-opt '("allocatable" "allocate" "assign" "assignment" "backspace"
304 "dimension" "do" "double" "else" "elseif" "elsewhere" "end" 325 "block" "call" "case" "character" "close" "common" "complex"
305 "enddo" "endfile" "endif" "entry" "equivalence" "exit" 326 "contains" "continue" "cycle" "data" "deallocate"
306 "external" "forall" "format" "function" "goto" "if" 327 "dimension" "do" "double" "else" "elseif" "elsewhere" "end"
307 "implicit" "include" "inquire" "integer" "intent" 328 "enddo" "endfile" "endif" "entry" "equivalence" "exit"
308 "interface" "intrinsic" "logical" "module" "namelist" "none" 329 "external" "forall" "format" "function" "goto" "if"
309 "nullify" "only" "open" "operator" "optional" "parameter" 330 "implicit" "include" "inquire" "integer" "intent"
310 "pause" "pointer" "precision" "print" "private" "procedure" 331 "interface" "intrinsic" "logical" "module" "namelist" "none"
311 "program" "public" "read" "real" "recursive" "result" "return" 332 "nullify" "only" "open" "operator" "optional" "parameter"
312 "rewind" "save" "select" "sequence" "stop" "subroutine" 333 "pause" "pointer" "precision" "print" "private" "procedure"
313 "target" "then" "type" "use" "where" "while" "write" 334 "program" "public" "read" "real" "recursive" "result" "return"
314 ;; F95 keywords. 335 "rewind" "save" "select" "sequence" "stop" "subroutine"
315 "elemental" "pure" 336 "target" "then" "type" "use" "where" "while" "write"
316 ;; F2003 337 ;; F95 keywords.
317 "abstract" "associate" "asynchronous" "bind" "class" 338 "elemental" "pure"
318 "deferred" "enum" "enumerator" "extends" "extends_type_of" 339 ;; F2003
319 "final" "generic" "import" "non_intrinsic" "non_overridable" 340 "abstract" "associate" "asynchronous" "bind" "class"
320 "nopass" "pass" "protected" "same_type_as" "value" "volatile" 341 "deferred" "enum" "enumerator" "extends" "extends_type_of"
321 ;; F2008. 342 "final" "generic" "import" "non_intrinsic" "non_overridable"
322 "contiguous" "submodule" "concurrent" "codimension" 343 "nopass" "pass" "protected" "same_type_as" "value" "volatile"
323 "sync all" "sync memory" "critical" "image_index" 344 ;; F2008.
324 ) 'words) 345 "contiguous" "submodule" "concurrent" "codimension"
346 "sync all" "sync memory" "critical" "image_index"
347 ))
348 "\\_>")
325 "Regexp used by the function `f90-change-keywords'.") 349 "Regexp used by the function `f90-change-keywords'.")
326 350
327(defconst f90-keywords-level-3-re 351(defconst f90-keywords-level-3-re
328 (regexp-opt 352 (concat
329 '("allocatable" "allocate" "assign" "assignment" "backspace" 353 "\\_<"
330 "close" "deallocate" "dimension" "endfile" "entry" "equivalence" 354 (regexp-opt
331 "external" "inquire" "intent" "intrinsic" "nullify" "only" "open" 355 '("allocatable" "allocate" "assign" "assignment" "backspace"
332 ;; FIXME operator and assignment should be F2003 procedures? 356 "close" "deallocate" "dimension" "endfile" "entry" "equivalence"
333 "operator" "optional" "parameter" "pause" "pointer" "print" "private" 357 "external" "inquire" "intent" "intrinsic" "nullify" "only" "open"
334 "public" "read" "recursive" "result" "rewind" "save" "select" 358 ;; FIXME operator and assignment should be F2003 procedures?
335 "sequence" "target" "write" 359 "operator" "optional" "parameter" "pause" "pointer" "print" "private"
336 ;; F95 keywords. 360 "public" "read" "recursive" "result" "rewind" "save" "select"
337 "elemental" "pure" 361 "sequence" "target" "write"
338 ;; F2003. asynchronous separate. 362 ;; F95 keywords.
339 "abstract" "deferred" "import" "final" "non_intrinsic" "non_overridable" 363 "elemental" "pure"
340 "nopass" "pass" "protected" "value" "volatile" 364 ;; F2003. asynchronous separate.
341 ;; F2008. 365 "abstract" "deferred" "import" "final" "non_intrinsic" "non_overridable"
342 ;; "concurrent" is only in the sense of "do [,] concurrent", but given 366 "nopass" "pass" "protected" "value" "volatile"
343 ;; the [,] it's simpler to just do every instance (cf "do while"). 367 ;; F2008.
344 "contiguous" "concurrent" "codimension" "sync all" "sync memory" 368 ;; "concurrent" is only in the sense of "do [,] concurrent", but given
345 ) 'words) 369 ;; the [,] it's simpler to just do every instance (cf "do while").
370 "contiguous" "concurrent" "codimension" "sync all" "sync memory"
371 ))
372 "\\_>")
346 "Keyword-regexp for font-lock level >= 3.") 373 "Keyword-regexp for font-lock level >= 3.")
347 374
348(defconst f90-procedures-re 375(defconst f90-procedures-re
349 (concat "\\<" 376 (concat "\\_<"
350 (regexp-opt 377 (regexp-opt
351 '("abs" "achar" "acos" "adjustl" "adjustr" "aimag" "aint" 378 '("abs" "achar" "acos" "adjustl" "adjustr" "aimag" "aint"
352 "all" "allocated" "anint" "any" "asin" "associated" 379 "all" "allocated" "anint" "any" "asin" "associated"
@@ -407,61 +434,67 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
407 "Regexp matching intrinsic operators.") 434 "Regexp matching intrinsic operators.")
408 435
409(defconst f90-hpf-keywords-re 436(defconst f90-hpf-keywords-re
410 (regexp-opt 437 (concat
411 ;; Intrinsic procedures. 438 "\\_<"
412 '("all_prefix" "all_scatter" "all_suffix" "any_prefix" 439 (regexp-opt
413 "any_scatter" "any_suffix" "copy_prefix" "copy_scatter" 440 ;; Intrinsic procedures.
414 "copy_suffix" "count_prefix" "count_scatter" "count_suffix" 441 '("all_prefix" "all_scatter" "all_suffix" "any_prefix"
415 "grade_down" "grade_up" 442 "any_scatter" "any_suffix" "copy_prefix" "copy_scatter"
416 "hpf_alignment" "hpf_distribution" "hpf_template" "iall" "iall_prefix" 443 "copy_suffix" "count_prefix" "count_scatter" "count_suffix"
417 "iall_scatter" "iall_suffix" "iany" "iany_prefix" "iany_scatter" 444 "grade_down" "grade_up"
418 "iany_suffix" "ilen" "iparity" "iparity_prefix" 445 "hpf_alignment" "hpf_distribution" "hpf_template" "iall" "iall_prefix"
419 "iparity_scatter" "iparity_suffix" "leadz" "maxval_prefix" 446 "iall_scatter" "iall_suffix" "iany" "iany_prefix" "iany_scatter"
420 "maxval_scatter" "maxval_suffix" "minval_prefix" "minval_scatter" 447 "iany_suffix" "ilen" "iparity" "iparity_prefix"
421 "minval_suffix" "number_of_processors" "parity" 448 "iparity_scatter" "iparity_suffix" "leadz" "maxval_prefix"
422 "parity_prefix" "parity_scatter" "parity_suffix" "popcnt" "poppar" 449 "maxval_scatter" "maxval_suffix" "minval_prefix" "minval_scatter"
423 "processors_shape" "product_prefix" "product_scatter" 450 "minval_suffix" "number_of_processors" "parity"
424 "product_suffix" "sum_prefix" "sum_scatter" "sum_suffix" 451 "parity_prefix" "parity_scatter" "parity_suffix" "popcnt" "poppar"
425 ;; Directives. 452 "processors_shape" "product_prefix" "product_scatter"
426 "align" "distribute" "dynamic" "independent" "inherit" "processors" 453 "product_suffix" "sum_prefix" "sum_scatter" "sum_suffix"
427 "realign" "redistribute" "template" 454 ;; Directives.
428 ;; Keywords. 455 "align" "distribute" "dynamic" "independent" "inherit" "processors"
429 "block" "cyclic" "extrinsic" "new" "onto" "pure" "with") 'words) 456 "realign" "redistribute" "template"
457 ;; Keywords.
458 "block" "cyclic" "extrinsic" "new" "onto" "pure" "with"))
459 "\\_>")
430 "Regexp for all HPF keywords, procedures and directives.") 460 "Regexp for all HPF keywords, procedures and directives.")
431 461
432(defconst f90-constants-re 462(defconst f90-constants-re
433 (regexp-opt '( ;; F2003 iso_fortran_env constants. 463 (concat
434 "iso_fortran_env" 464 "\\_<"
435 "input_unit" "output_unit" "error_unit" 465 (regexp-opt '( ;; F2003 iso_fortran_env constants.
436 "iostat_end" "iostat_eor" 466 "iso_fortran_env"
437 "numeric_storage_size" "character_storage_size" 467 "input_unit" "output_unit" "error_unit"
438 "file_storage_size" 468 "iostat_end" "iostat_eor"
439 ;; F2003 iso_c_binding constants. 469 "numeric_storage_size" "character_storage_size"
440 "iso_c_binding" 470 "file_storage_size"
441 "c_int" "c_short" "c_long" "c_long_long" "c_signed_char" 471 ;; F2003 iso_c_binding constants.
442 "c_size_t" 472 "iso_c_binding"
443 "c_int8_t" "c_int16_t" "c_int32_t" "c_int64_t" 473 "c_int" "c_short" "c_long" "c_long_long" "c_signed_char"
444 "c_int_least8_t" "c_int_least16_t" "c_int_least32_t" 474 "c_size_t"
445 "c_int_least64_t" 475 "c_int8_t" "c_int16_t" "c_int32_t" "c_int64_t"
446 "c_int_fast8_t" "c_int_fast16_t" "c_int_fast32_t" 476 "c_int_least8_t" "c_int_least16_t" "c_int_least32_t"
447 "c_int_fast64_t" 477 "c_int_least64_t"
448 "c_intmax_t" "c_intptr_t" 478 "c_int_fast8_t" "c_int_fast16_t" "c_int_fast32_t"
449 "c_float" "c_double" "c_long_double" 479 "c_int_fast64_t"
450 "c_float_complex" "c_double_complex" "c_long_double_complex" 480 "c_intmax_t" "c_intptr_t"
451 "c_bool" "c_char" 481 "c_float" "c_double" "c_long_double"
452 "c_null_char" "c_alert" "c_backspace" "c_form_feed" 482 "c_float_complex" "c_double_complex" "c_long_double_complex"
453 "c_new_line" "c_carriage_return" "c_horizontal_tab" 483 "c_bool" "c_char"
454 "c_vertical_tab" 484 "c_null_char" "c_alert" "c_backspace" "c_form_feed"
455 "c_ptr" "c_funptr" "c_null_ptr" "c_null_funptr" 485 "c_new_line" "c_carriage_return" "c_horizontal_tab"
456 "ieee_exceptions" 486 "c_vertical_tab"
457 "ieee_arithmetic" 487 "c_ptr" "c_funptr" "c_null_ptr" "c_null_funptr"
458 "ieee_features" 488 "ieee_exceptions"
459 ;; F2008 iso_fortran_env constants. 489 "ieee_arithmetic"
460 "character_kinds" "int8" "int16" "int32" "int64" 490 "ieee_features"
461 "integer_kinds" "iostat_inquire_internal_unit" 491 ;; F2008 iso_fortran_env constants.
462 "logical_kinds" "real_kinds" "real32" "real64" "real128" 492 "character_kinds" "int8" "int16" "int32" "int64"
463 "lock_type" "atomic_int_kind" "atomic_logical_kind" 493 "integer_kinds" "iostat_inquire_internal_unit"
464 ) 'words) 494 "logical_kinds" "real_kinds" "real32" "real64" "real128"
495 "lock_type" "atomic_int_kind" "atomic_logical_kind"
496 ))
497 "\\_>")
465 "Regexp for Fortran intrinsic constants.") 498 "Regexp for Fortran intrinsic constants.")
466 499
467;; cf f90-looking-at-type-like. 500;; cf f90-looking-at-type-like.
@@ -470,16 +503,16 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
470Set the match data so that subexpression 1,2 are the TYPE, and 503Set the match data so that subexpression 1,2 are the TYPE, and
471type-name parts, respectively." 504type-name parts, respectively."
472 (let (found l) 505 (let (found l)
473 (while (and (re-search-forward "\\<\\(\\(?:end[ \t]*\\)?type\\)\\>[ \t]*" 506 (while (and (re-search-forward "\\_<\\(\\(?:end[ \t]*\\)?type\\)\\_>[ \t]*"
474 limit t) 507 limit t)
475 (not (setq found 508 (not (setq found
476 (progn 509 (progn
477 (setq l (match-data)) 510 (setq l (match-data))
478 (unless (looking-at "\\(is\\>\\|(\\)") 511 (unless (looking-at "\\(is\\_>\\|(\\)")
479 (when (if (looking-at "\\(\\sw+\\)") 512 (when (if (looking-at "\\(\\(?:\\sw\\|\\s_\\)+\\)")
480 (goto-char (match-end 0)) 513 (goto-char (match-end 0))
481 (re-search-forward 514 (re-search-forward
482 "[ \t]*::[ \t]*\\(\\sw+\\)" 515 "[ \t]*::[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)"
483 (line-end-position) t)) 516 (line-end-position) t))
484 ;; 0 is wrong, but we don't use it. 517 ;; 0 is wrong, but we don't use it.
485 (set-match-data 518 (set-match-data
@@ -491,33 +524,33 @@ type-name parts, respectively."
491(defvar f90-font-lock-keywords-1 524(defvar f90-font-lock-keywords-1
492 (list 525 (list
493 ;; Special highlighting of "module procedure". 526 ;; Special highlighting of "module procedure".
494 '("\\<\\(module[ \t]*procedure\\)\\>\\([^()\n]*::\\)?[ \t]*\\([^&!\n]*\\)" 527 '("\\_<\\(module[ \t]*procedure\\)\\_>\\([^()\n]*::\\)?[ \t]*\\([^&!\n]*\\)"
495 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) 528 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
496 ;; Highlight definition of derived type. 529 ;; Highlight definition of derived type.
497;;; '("\\<\\(\\(?:end[ \t]*\\)?type\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)" 530;;; '("\\_<\\(\\(?:end[ \t]*\\)?type\\)\\_>\\([^()\n]*::\\)?[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)"
498;;; (1 font-lock-keyword-face) (3 font-lock-function-name-face)) 531;;; (1 font-lock-keyword-face) (3 font-lock-function-name-face))
499 '(f90-typedef-matcher 532 '(f90-typedef-matcher
500 (1 font-lock-keyword-face) (2 font-lock-function-name-face)) 533 (1 font-lock-keyword-face) (2 font-lock-function-name-face))
501 ;; F2003. Prevent operators being highlighted as functions. 534 ;; F2003. Prevent operators being highlighted as functions.
502 '("\\<\\(\\(?:end[ \t]*\\)?interface[ \t]*\\(?:assignment\\|operator\\|\ 535 '("\\_<\\(\\(?:end[ \t]*\\)?interface[ \t]*\\(?:assignment\\|operator\\|\
503read\\|write\\)\\)[ \t]*(" (1 font-lock-keyword-face t)) 536read\\|write\\)\\)[ \t]*(" (1 font-lock-keyword-face t))
504 ;; Other functions and declarations. Named interfaces = F2003. 537 ;; Other functions and declarations. Named interfaces = F2003.
505 ;; F2008: end submodule submodule_name. 538 ;; F2008: end submodule submodule_name.
506 '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|\\(?:sub\\)?module\\|\ 539 '("\\_<\\(\\(?:end[ \t]*\\)?\\(program\\|\\(?:sub\\)?module\\|\
507function\\|associate\\|subroutine\\|interface\\)\\|use\\|call\\)\ 540function\\|associate\\|subroutine\\|interface\\)\\|use\\|call\\)\
508\\>[ \t]*\\(\\sw+\\)?" 541\\_>[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
509 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) 542 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
510 ;; F2008: submodule (parent_name) submodule_name. 543 ;; F2008: submodule (parent_name) submodule_name.
511 '("\\<\\(submodule\\)\\>[ \t]*([^)\n]+)[ \t]*\\(\\sw+\\)?" 544 '("\\_<\\(submodule\\)\\_>[ \t]*([^)\n]+)[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
512 (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t)) 545 (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
513 ;; F2003. 546 ;; F2003.
514 '("\\<\\(use\\)[ \t]*,[ \t]*\\(\\(?:non_\\)?intrinsic\\)[ \t]*::[ \t]*\ 547 '("\\_<\\(use\\)[ \t]*,[ \t]*\\(\\(?:non_\\)?intrinsic\\)[ \t]*::[ \t]*\
515\\(\\sw+\\)" 548\\(\\(?:\\sw\\|\\s_\\)+\\)"
516 (1 font-lock-keyword-face) (2 font-lock-keyword-face) 549 (1 font-lock-keyword-face) (2 font-lock-keyword-face)
517 (3 font-lock-function-name-face)) 550 (3 font-lock-function-name-face))
518 "\\<\\(\\(end[ \t]*\\)?block[ \t]*data\\|contains\\)\\>" 551 "\\_<\\(\\(end[ \t]*\\)?block[ \t]*data\\|contains\\)\\_>"
519 ;; "abstract interface" is F2003. 552 ;; "abstract interface" is F2003.
520 '("\\<abstract[ \t]*interface\\>" (0 font-lock-keyword-face t))) 553 '("\\_<abstract[ \t]*interface\\_>" (0 font-lock-keyword-face t)))
521 "This does fairly subdued highlighting of comments and function calls.") 554 "This does fairly subdued highlighting of comments and function calls.")
522 555
523;; NB not explicitly handling this, yet it seems to work. 556;; NB not explicitly handling this, yet it seems to work.
@@ -529,7 +562,7 @@ and variable-name parts, respectively."
529 ;; Matcher functions must return nil only when there are no more 562 ;; Matcher functions must return nil only when there are no more
530 ;; matches within the search range. 563 ;; matches within the search range.
531 (let (found l) 564 (let (found l)
532 (while (and (re-search-forward "\\<\\(type\\|class\\)[ \t]*(" limit t) 565 (while (and (re-search-forward "\\_<\\(type\\|class\\)[ \t]*(" limit t)
533 (not 566 (not
534 (setq found 567 (setq found
535 (condition-case nil 568 (condition-case nil
@@ -544,7 +577,7 @@ and variable-name parts, respectively."
544 (when 577 (when
545 (re-search-forward 578 (re-search-forward
546 ;; type (foo) bar, qux 579 ;; type (foo) bar, qux
547 (if (looking-at "\\sw+") 580 (if (looking-at "\\(?:\\sw\\|\\s_\\)+")
548 "\\([^&!\n]+\\)" 581 "\\([^&!\n]+\\)"
549 ;; type (foo), stuff :: bar, qux 582 ;; type (foo), stuff :: bar, qux
550 "::[ \t]*\\([^&!\n]+\\)") 583 "::[ \t]*\\([^&!\n]+\\)")
@@ -587,53 +620,53 @@ enumerator\\|generic\\|procedure\\|logical\\|double[ \t]*precision\\)\
587 ;; integer( kind=1 ) function foo() 620 ;; integer( kind=1 ) function foo()
588 ;; thanks to the happy accident described above. 621 ;; thanks to the happy accident described above.
589 ;; Not anchored, so don't need to worry about "pure" etc. 622 ;; Not anchored, so don't need to worry about "pure" etc.
590 '("\\<\\(\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\ 623 '("\\_<\\(\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
591logical\\|double[ \t]*precision\\|\ 624logical\\|double[ \t]*precision\\|\
592\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)[ \t]*\\)\ 625\\(?:type\\|class\\)[ \t]*([ \t]*\\(?:\\sw\\|\\s_\\)+[ \t]*)\\)[ \t]*\\)\
593\\(function\\)\\>[ \t]*\\(\\sw+\\)[ \t]*\\(([^&!\n]*)\\)" 626\\(function\\)\\_>[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*\\(([^&!\n]*)\\)"
594 (1 font-lock-type-face t) (4 font-lock-keyword-face t) 627 (1 font-lock-type-face t) (4 font-lock-keyword-face t)
595 (5 font-lock-function-name-face t) (6 'default t)) 628 (5 font-lock-function-name-face t) (6 'default t))
596 ;; enum (F2003; must be followed by ", bind(C)"). 629 ;; enum (F2003; must be followed by ", bind(C)").
597 '("\\<\\(enum\\)[ \t]*," (1 font-lock-keyword-face)) 630 '("\\_<\\(enum\\)[ \t]*," (1 font-lock-keyword-face))
598 ;; end do, enum (F2003), if, select, where, and forall constructs. 631 ;; end do, enum (F2003), if, select, where, and forall constructs.
599 ;; block, critical (F2008). 632 ;; block, critical (F2008).
600 ;; Note that "block data" may get somewhat mixed up with F2008 blocks, 633 ;; Note that "block data" may get somewhat mixed up with F2008 blocks,
601 ;; but since the former is obsolete I'm not going to worry about it. 634 ;; but since the former is obsolete I'm not going to worry about it.
602 '("\\<\\(end[ \t]*\\(do\\|if\\|enum\\|select\\|forall\\|where\\|\ 635 '("\\_<\\(end[ \t]*\\(do\\|if\\|enum\\|select\\|forall\\|where\\|\
603block\\|critical\\)\\)\\>\ 636block\\|critical\\)\\)\\_>\
604\\([ \t]+\\(\\sw+\\)\\)?" 637\\([ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\)?"
605 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t)) 638 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t))
606 '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|\ 639 '("^[ \t0-9]*\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|\
607do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\ 640do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\
608forall\\|block\\|critical\\)\\)\\>" 641forall\\|block\\|critical\\)\\)\\_>"
609 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face)) 642 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face))
610 ;; Implicit declaration. 643 ;; Implicit declaration.
611 '("\\<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\ 644 '("\\_<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\
612\\|enumerator\\|procedure\\|\ 645\\|enumerator\\|procedure\\|\
613logical\\|double[ \t]*precision\\|type[ \t]*(\\sw+)\\|none\\)[ \t]*" 646logical\\|double[ \t]*precision\\|type[ \t]*(\\(?:\\sw\\|\\s_\\)+)\\|none\\)[ \t]*"
614 (1 font-lock-keyword-face) (2 font-lock-type-face)) 647 (1 font-lock-keyword-face) (2 font-lock-type-face))
615 '("\\<\\(namelist\\|common\\)[ \t]*\/\\(\\sw+\\)?\/" 648 '("\\_<\\(namelist\\|common\\)[ \t]*\/\\(\\(?:\\sw\\|\\s_\\)+\\)?\/"
616 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) 649 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
617 "\\<else\\([ \t]*if\\|where\\)?\\>" 650 "\\_<else\\([ \t]*if\\|where\\)?\\_>"
618 '("\\(&\\)[ \t]*\\(!\\|$\\)" (1 font-lock-keyword-face)) 651 '("\\(&\\)[ \t]*\\(!\\|$\\)" (1 font-lock-keyword-face))
619 "\\<\\(then\\|continue\\|format\\|include\\|stop\\|return\\)\\>" 652 "\\_<\\(then\\|continue\\|format\\|include\\|stop\\|return\\)\\_>"
620 '("\\<\\(exit\\|cycle\\)[ \t]*\\(\\sw+\\)?\\>" 653 '("\\_<\\(exit\\|cycle\\)[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?\\_>"
621 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) 654 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
622 '("\\<\\(case\\)[ \t]*\\(default\\|(\\)" . 1) 655 '("\\_<\\(case\\)[ \t]*\\(default\\|(\\)" . 1)
623 ;; F2003 "class default". 656 ;; F2003 "class default".
624 '("\\<\\(class\\)[ \t]*default" . 1) 657 '("\\_<\\(class\\)[ \t]*default" . 1)
625 ;; F2003 "type is" in a "select type" block. 658 ;; F2003 "type is" in a "select type" block.
626 '("\\<\\(\\(type\\|class\\)[ \t]*is\\)[ \t]*(" (1 font-lock-keyword-face t)) 659 '("\\_<\\(\\(type\\|class\\)[ \t]*is\\)[ \t]*(" (1 font-lock-keyword-face t))
627 '("\\<\\(do\\|go[ \t]*to\\)\\>[ \t]*\\([0-9]+\\)" 660 '("\\_<\\(do\\|go[ \t]*to\\)\\_>[ \t]*\\([0-9]+\\)"
628 (1 font-lock-keyword-face) (2 font-lock-constant-face)) 661 (1 font-lock-keyword-face) (2 font-lock-constant-face))
629 ;; Line numbers (lines whose first character after number is letter). 662 ;; Line numbers (lines whose first character after number is letter).
630 '("^[ \t]*\\([0-9]+\\)[ \t]*[a-z]+" (1 font-lock-constant-face t)) 663 '("^[ \t]*\\([0-9]+\\)[ \t]*[a-z]+" (1 font-lock-constant-face t))
631 ;; Override eg for "#include". 664 ;; Override eg for "#include".
632 '("^#[ \t]*\\w+" (0 font-lock-preprocessor-face t) 665 '("^#[ \t]*\\(?:\\sw\\|\\s_\\)+" (0 font-lock-preprocessor-face t)
633 ("\\<defined\\>" nil nil (0 font-lock-preprocessor-face))) 666 ("\\_<defined\\_>" nil nil (0 font-lock-preprocessor-face)))
634 '("^#" ("\\(&&\\|||\\)" nil nil (0 font-lock-constant-face t))) 667 '("^#" ("\\(&&\\|||\\)" nil nil (0 font-lock-constant-face t)))
635 '("^#[ \t]*define[ \t]+\\(\\w+\\)(" (1 font-lock-function-name-face)) 668 '("^#[ \t]*define[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)(" (1 font-lock-function-name-face))
636 '("^#[ \t]*define[ \t]+\\(\\w+\\)" (1 font-lock-variable-name-face)) 669 '("^#[ \t]*define[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face))
637 '("^#[ \t]*include[ \t]+\\(<.+>\\)" (1 font-lock-string-face)))) 670 '("^#[ \t]*include[ \t]+\\(<.+>\\)" (1 font-lock-string-face))))
638 "Highlights declarations, do-loops and other constructs.") 671 "Highlights declarations, do-loops and other constructs.")
639 672
@@ -645,9 +678,9 @@ logical\\|double[ \t]*precision\\|type[ \t]*(\\sw+)\\|none\\)[ \t]*"
645 ;; FIXME why isn't this font-lock-builtin-face, which 678 ;; FIXME why isn't this font-lock-builtin-face, which
646 ;; otherwise we hardly use, as in fortran.el? 679 ;; otherwise we hardly use, as in fortran.el?
647 (list f90-procedures-re '(1 font-lock-keyword-face keep)) 680 (list f90-procedures-re '(1 font-lock-keyword-face keep))
648 "\\<real\\>" ; avoid overwriting real defs 681 "\\_<real\\_>" ; avoid overwriting real defs
649 ;; As an attribute, but not as an optional argument. 682 ;; As an attribute, but not as an optional argument.
650 '("\\<\\(asynchronous\\)[ \t]*[^=]" . 1))) 683 '("\\_<\\(asynchronous\\)[ \t]*[^=]" . 1)))
651 "Highlights all F90 keywords and intrinsic procedures.") 684 "Highlights all F90 keywords and intrinsic procedures.")
652 685
653(defvar f90-font-lock-keywords-4 686(defvar f90-font-lock-keywords-4
@@ -666,8 +699,7 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
666 (let ((table (make-syntax-table))) 699 (let ((table (make-syntax-table)))
667 (modify-syntax-entry ?\! "<" table) ; begin comment 700 (modify-syntax-entry ?\! "<" table) ; begin comment
668 (modify-syntax-entry ?\n ">" table) ; end comment 701 (modify-syntax-entry ?\n ">" table) ; end comment
669 ;; FIXME: This goes against the convention: it should be "_". 702 (modify-syntax-entry ?_ "_" table) ; underscore in names
670 (modify-syntax-entry ?_ "w" table) ; underscore in names
671 (modify-syntax-entry ?\' "\"" table) ; string quote 703 (modify-syntax-entry ?\' "\"" table) ; string quote
672 (modify-syntax-entry ?\" "\"" table) ; string quote 704 (modify-syntax-entry ?\" "\"" table) ; string quote
673 ;; FIXME: We used to set ` to word syntax for the benefit of abbrevs, but 705 ;; FIXME: We used to set ` to word syntax for the benefit of abbrevs, but
@@ -822,14 +854,14 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
822 854
823;; Regexps for finding program structures. 855;; Regexps for finding program structures.
824(defconst f90-blocks-re 856(defconst f90-blocks-re
825 (concat "\\(block[ \t]*data\\|" 857 (concat "\\(\\(?:block[ \t]*data\\|"
826 (regexp-opt '("do" "if" "interface" "function" "module" "program" 858 (regexp-opt '("do" "if" "interface" "function" "module" "program"
827 "select" "subroutine" "type" "where" "forall" 859 "select" "subroutine" "type" "where" "forall"
828 ;; F2003. 860 ;; F2003.
829 "enum" "associate" 861 "enum" "associate"
830 ;; F2008. 862 ;; F2008.
831 "submodule" "block" "critical")) 863 "submodule" "block" "critical"))
832 "\\)\\>") 864 "\\)\\_>\\)")
833 "Regexp potentially indicating a \"block\" of F90 code.") 865 "Regexp potentially indicating a \"block\" of F90 code.")
834 866
835(defconst f90-program-block-re 867(defconst f90-program-block-re
@@ -845,15 +877,15 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
845(defconst f90-end-if-re 877(defconst f90-end-if-re
846 (concat "end[ \t]*" 878 (concat "end[ \t]*"
847 (regexp-opt '("if" "select" "where" "forall") 'paren) 879 (regexp-opt '("if" "select" "where" "forall") 'paren)
848 "\\>") 880 "\\_>")
849 "Regexp matching the end of an IF, SELECT, WHERE, FORALL block.") 881 "Regexp matching the end of an IF, SELECT, WHERE, FORALL block.")
850 882
851(defconst f90-end-type-re 883(defconst f90-end-type-re
852 "end[ \t]*\\(type\\|enum\\|interface\\|block[ \t]*data\\)\\>" 884 "end[ \t]*\\(type\\|enum\\|interface\\|block[ \t]*data\\)\\_>"
853 "Regexp matching the end of a TYPE, ENUM, INTERFACE, BLOCK DATA section.") 885 "Regexp matching the end of a TYPE, ENUM, INTERFACE, BLOCK DATA section.")
854 886
855(defconst f90-end-associate-re 887(defconst f90-end-associate-re
856 "end[ \t]*associate\\>" 888 "end[ \t]*associate\\_>"
857 "Regexp matching the end of an ASSOCIATE block.") 889 "Regexp matching the end of an ASSOCIATE block.")
858 890
859;; This is for a TYPE block, not a variable of derived TYPE. 891;; This is for a TYPE block, not a variable of derived TYPE.
@@ -864,12 +896,12 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
864 ;; type, stuff :: word 896 ;; type, stuff :: word
865 ;; type, bind(c) :: word 897 ;; type, bind(c) :: word
866 ;; NOT "type (" 898 ;; NOT "type ("
867 "\\<\\(type\\)\\>\\(?:\\(?:[^()\n]*\\|\ 899 "\\_<\\(type\\)\\_>\\(?:\\(?:[^()\n]*\\|\
868.*,[ \t]*bind[ \t]*([ \t]*c[ \t]*)[ \t]*\\)::\\)?[ \t]*\\(\\sw+\\)" 900.*,[ \t]*bind[ \t]*([ \t]*c[ \t]*)[ \t]*\\)::\\)?[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)"
869 "Regexp matching the definition of a derived type.") 901 "Regexp matching the definition of a derived type.")
870 902
871(defconst f90-typeis-re 903(defconst f90-typeis-re
872 "\\<\\(class\\|type\\)[ \t]*is[ \t]*(" 904 "\\_<\\(class\\|type\\)[ \t]*is[ \t]*("
873 "Regexp matching a CLASS/TYPE IS statement.") 905 "Regexp matching a CLASS/TYPE IS statement.")
874 906
875(defconst f90-no-break-re 907(defconst f90-no-break-re
@@ -888,12 +920,12 @@ allowed. This minor issue currently only affects \"(/\" and \"/)\".")
888 920
889;; Hideshow support. 921;; Hideshow support.
890(defconst f90-end-block-re 922(defconst f90-end-block-re
891 (concat "^[ \t0-9]*\\<end[ \t]*" 923 (concat "^[ \t0-9]*\\_<end[ \t]*"
892 (regexp-opt '("do" "if" "forall" "function" "interface" 924 (regexp-opt '("do" "if" "forall" "function" "interface"
893 "module" "program" "select" "subroutine" 925 "module" "program" "select" "subroutine"
894 "type" "where" "enum" "associate" "submodule" 926 "type" "where" "enum" "associate" "submodule"
895 "block" "critical") t) 927 "block" "critical") t)
896 "\\>") 928 "\\_>")
897 "Regexp matching the end of an F90 \"block\", from the line start. 929 "Regexp matching the end of an F90 \"block\", from the line start.
898Used in the F90 entry in `hs-special-modes-alist'.") 930Used in the F90 entry in `hs-special-modes-alist'.")
899 931
@@ -903,11 +935,11 @@ Used in the F90 entry in `hs-special-modes-alist'.")
903 (concat 935 (concat
904 "^[ \t0-9]*" ; statement number 936 "^[ \t0-9]*" ; statement number
905 "\\(\\(" 937 "\\(\\("
906 "\\(\\sw+[ \t]*:[ \t]*\\)?" ; structure label 938 "\\(\\(?:\\sw\\|\\s_\\)+[ \t]*:[ \t]*\\)?" ; structure label
907 "\\(do\\|select[ \t]*\\(case\\|type\\)\\|" 939 "\\(do\\|select[ \t]*\\(case\\|type\\)\\|"
908 ;; See comments in fortran-start-block-re for the problems of IF. 940 ;; See comments in fortran-start-block-re for the problems of IF.
909 "if[ \t]*(\\(.*\\|" 941 "if[ \t]*(\\(.*\\|"
910 ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|" 942 ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\_>\\)\\)\\)\\_<then\\|"
911 ;; Distinguish WHERE block from isolated WHERE. 943 ;; Distinguish WHERE block from isolated WHERE.
912 "\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)" 944 "\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)"
913 "\\|" 945 "\\|"
@@ -917,7 +949,7 @@ Used in the F90 entry in `hs-special-modes-alist'.")
917 "type[ \t,]\\(" 949 "type[ \t,]\\("
918 "[^i(!\n\"\& \t]\\|" ; not-i( 950 "[^i(!\n\"\& \t]\\|" ; not-i(
919 "i[^s!\n\"\& \t]\\|" ; i not-s 951 "i[^s!\n\"\& \t]\\|" ; i not-s
920 "is\\sw\\)\\|" 952 "is\\(?:\\sw\\|\\s_\\)\\)\\|"
921 ;; "abstract interface" is F2003; "submodule" is F2008. 953 ;; "abstract interface" is F2003; "submodule" is F2008.
922 "program\\|\\(?:abstract[ \t]*\\)?interface\\|\\(?:sub\\)?module\\|" 954 "program\\|\\(?:abstract[ \t]*\\)?interface\\|\\(?:sub\\)?module\\|"
923 ;; "enum", but not "enumerator". 955 ;; "enum", but not "enumerator".
@@ -945,10 +977,10 @@ Set subexpression 1 in the match-data to the name of the type."
945 (not (setq found 977 (not (setq found
946 (save-excursion 978 (save-excursion
947 (goto-char (match-end 0)) 979 (goto-char (match-end 0))
948 (unless (looking-at "\\(is\\>\\|(\\)") 980 (unless (looking-at "\\(is\\_>\\|(\\)")
949 (or (looking-at "\\(\\sw+\\)") 981 (or (looking-at "\\(\\(?:\\sw\\|\\s_\\)+\\)")
950 (re-search-forward 982 (re-search-forward
951 "[ \t]*::[ \t]*\\(\\sw+\\)" 983 "[ \t]*::[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)"
952 (line-end-position) t)))))))) 984 (line-end-position) t))))))))
953 found)) 985 found))
954 986
@@ -957,36 +989,35 @@ Set subexpression 1 in the match-data to the name of the type."
957 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]") 989 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]")
958 ;; (not-ib "[^i(!\n\"\& \t]") (not-s "[^s!\n\"\& \t]") 990 ;; (not-ib "[^i(!\n\"\& \t]") (not-s "[^s!\n\"\& \t]")
959 ) 991 )
960 (list 992 `((nil "^[ \t0-9]*program[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)" 1)
961 '(nil "^[ \t0-9]*program[ \t]+\\(\\sw+\\)" 1) 993 ("Submodules" "^[ \t0-9]*submodule[ \t]*([^)\n]+)[ \t]*\
962 '("Submodules" "^[ \t0-9]*submodule[ \t]*([^)\n]+)[ \t]*\ 994\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*\\(!\\|$\\)" 1)
963\\(\\sw+\\)[ \t]*\\(!\\|$\\)" 1) 995 ("Modules" "^[ \t0-9]*module[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*\\(!\\|$\\)" 1)
964 '("Modules" "^[ \t0-9]*module[ \t]+\\(\\sw+\\)[ \t]*\\(!\\|$\\)" 1) 996 ("Types" f90-imenu-type-matcher 1)
965 (list "Types" 'f90-imenu-type-matcher 1) 997 ;; Does not handle: "type[, stuff] :: foo".
966 ;; Does not handle: "type[, stuff] :: foo". 998 ;;(format "^[ \t0-9]*type[ \t]+\\(\\(%s\\|i%s\\|is\\(?:\\sw\\|\\s_\\)\\)\\(?:\\sw\\|\\s_\\)*\\)"
967;;; (format "^[ \t0-9]*type[ \t]+\\(\\(%s\\|i%s\\|is\\sw\\)\\sw*\\)" 999 ;; not-ib not-s)
968;;; not-ib not-s) 1000 ;;1)
969;;; 1) 1001 ;; Can't get the subexpression numbers to match in the two branches.
970 ;; Can't get the subexpression numbers to match in the two branches. 1002 ;; FIXME: Now with \(?N:..\) we can get the numbers to match!
971;;; (format "^[ \t0-9]*type\\([ \t]*,.*\\(::\\)[ \t]*\\(\\sw+\\)\\|[ \t]+\\(\\(%s\\|i%s\\|is\\sw\\)\\sw*\\)\\)" not-ib not-s) 1003 ;;(format "^[ \t0-9]*type\\([ \t]*,.*\\(::\\)[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)\\|[ \t]+\\(\\(%s\\|i%s\\|is\\(?:\\sw\\|\\s_\\)\\)\\(?:\\sw\\|\\s_\\)*\\)\\)" not-ib not-s)
972;;; 3) 1004 ;;3)
973 (list 1005 ("Procedures"
974 "Procedures" 1006 ,(concat
975 (concat 1007 "^[ \t0-9]*"
976 "^[ \t0-9]*" 1008 "\\("
977 "\\(" 1009 ;; At least three non-space characters before function/subroutine.
978 ;; At least three non-space characters before function/subroutine. 1010 ;; Check that the last three non-space characters do not spell E N D.
979 ;; Check that the last three non-space characters do not spell E N D. 1011 "[^!\"\&\n]*\\("
980 "[^!\"\&\n]*\\(" 1012 not-e good-char good-char "\\|"
981 not-e good-char good-char "\\|" 1013 good-char not-n good-char "\\|"
982 good-char not-n good-char "\\|" 1014 good-char good-char not-d "\\)"
983 good-char good-char not-d "\\)" 1015 "\\|"
984 "\\|" 1016 ;; Less than three non-space characters before function/subroutine.
985 ;; Less than three non-space characters before function/subroutine. 1017 good-char "?" good-char "?"
986 good-char "?" good-char "?" 1018 "\\)"
987 "\\)" 1019 "[ \t]*\\(function\\|subroutine\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)")
988 "[ \t]*\\(function\\|subroutine\\)[ \t]+\\(\\sw+\\)") 1020 4)))
989 4)))
990 "Value for `imenu-generic-expression' in F90 mode.") 1021 "Value for `imenu-generic-expression' in F90 mode.")
991 1022
992(defun f90-add-imenu-menu () 1023(defun f90-add-imenu-menu ()
@@ -1119,11 +1150,11 @@ Variables controlling indentation style and extra features:
1119 Automatic insertion of \& at beginning of continuation lines (default t). 1150 Automatic insertion of \& at beginning of continuation lines (default t).
1120`f90-smart-end' 1151`f90-smart-end'
1121 From an END statement, check and fill the end using matching block start. 1152 From an END statement, check and fill the end using matching block start.
1122 Allowed values are 'blink, 'no-blink, and nil, which determine 1153 Allowed values are `blink', `no-blink', and nil, which determine
1123 whether to blink the matching beginning (default 'blink). 1154 whether to blink the matching beginning (default `blink').
1124`f90-auto-keyword-case' 1155`f90-auto-keyword-case'
1125 Automatic change of case of keywords (default nil). 1156 Automatic change of case of keywords (default nil).
1126 The possibilities are 'downcase-word, 'upcase-word, 'capitalize-word. 1157 The possibilities are `downcase-word', `upcase-word', `capitalize-word'.
1127`f90-leave-line-no' 1158`f90-leave-line-no'
1128 Do not left-justify line numbers (default nil). 1159 Do not left-justify line numbers (default nil).
1129 1160
@@ -1235,13 +1266,13 @@ whitespace, if any."
1235(defsubst f90-looking-at-do () 1266(defsubst f90-looking-at-do ()
1236 "Return (\"do\" NAME) if a do statement starts after point. 1267 "Return (\"do\" NAME) if a do statement starts after point.
1237NAME is nil if the statement has no label." 1268NAME is nil if the statement has no label."
1238 (if (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\\(do\\)\\>") 1269 (if (looking-at "\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:\\)?[ \t]*\\(do\\)\\_>")
1239 (list (match-string 3) (match-string 2)))) 1270 (list (match-string 3) (match-string 2))))
1240 1271
1241(defsubst f90-looking-at-select-case () 1272(defsubst f90-looking-at-select-case ()
1242 "Return (\"select\" NAME) if a select statement starts after point. 1273 "Return (\"select\" NAME) if a select statement starts after point.
1243NAME is nil if the statement has no label." 1274NAME is nil if the statement has no label."
1244 (if (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\ 1275 (if (looking-at "\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:\\)?[ \t]*\
1245\\(select\\)[ \t]*\\(case\\|type\\)[ \t]*(") 1276\\(select\\)[ \t]*\\(case\\|type\\)[ \t]*(")
1246 (list (match-string 3) (match-string 2)))) 1277 (list (match-string 3) (match-string 2))))
1247 1278
@@ -1249,50 +1280,50 @@ NAME is nil if the statement has no label."
1249 "Return (\"if\" NAME) if an if () then statement starts after point. 1280 "Return (\"if\" NAME) if an if () then statement starts after point.
1250NAME is nil if the statement has no label." 1281NAME is nil if the statement has no label."
1251 (save-excursion 1282 (save-excursion
1252 (when (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\\(if\\)\\>") 1283 (when (looking-at "\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:\\)?[ \t]*\\(if\\)\\_>")
1253 (let ((struct (match-string 3)) 1284 (let ((struct (match-string 3))
1254 (label (match-string 2)) 1285 (label (match-string 2))
1255 (pos (scan-lists (point) 1 0))) 1286 (pos (scan-lists (point) 1 0)))
1256 (and pos (goto-char pos)) 1287 (and pos (goto-char pos))
1257 (skip-chars-forward " \t") 1288 (skip-chars-forward " \t")
1258 (if (or (looking-at "then\\>") 1289 (if (or (looking-at "then\\_>")
1259 (when (f90-line-continued) 1290 (when (f90-line-continued)
1260 (f90-next-statement) 1291 (f90-next-statement)
1261 (skip-chars-forward " \t0-9&") 1292 (skip-chars-forward " \t0-9&")
1262 (looking-at "then\\>"))) 1293 (looking-at "then\\_>")))
1263 (list struct label)))))) 1294 (list struct label))))))
1264 1295
1265;; FIXME label? 1296;; FIXME label?
1266(defsubst f90-looking-at-associate () 1297(defsubst f90-looking-at-associate ()
1267 "Return (\"associate\") if an associate block starts after point." 1298 "Return (\"associate\") if an associate block starts after point."
1268 (if (looking-at "\\<\\(associate\\)[ \t]*(") 1299 (if (looking-at "\\_<\\(associate\\)[ \t]*(")
1269 (list (match-string 1)))) 1300 (list (match-string 1))))
1270 1301
1271(defsubst f90-looking-at-critical () 1302(defsubst f90-looking-at-critical ()
1272 "Return (KIND NAME) if a critical or block block starts after point." 1303 "Return (KIND NAME) if a critical or block block starts after point."
1273 (if (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\\(critical\\|block\\)\\>") 1304 (if (looking-at "\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:\\)?[ \t]*\\(critical\\|block\\)\\_>")
1274 (let ((struct (match-string 3)) 1305 (let ((struct (match-string 3))
1275 (label (match-string 2))) 1306 (label (match-string 2)))
1276 (if (or (not (string-equal "block" struct)) 1307 (if (or (not (string-equal "block" struct))
1277 (save-excursion 1308 (save-excursion
1278 (skip-chars-forward " \t") 1309 (skip-chars-forward " \t")
1279 (not (looking-at "data\\>")))) 1310 (not (looking-at "data\\_>"))))
1280 (list struct label))))) 1311 (list struct label)))))
1281 1312
1282(defsubst f90-looking-at-end-critical () 1313(defsubst f90-looking-at-end-critical ()
1283 "Return non-nil if a critical or block block ends after point." 1314 "Return non-nil if a critical or block block ends after point."
1284 (if (looking-at "end[ \t]*\\(critical\\|block\\)\\>") 1315 (if (looking-at "end[ \t]*\\(critical\\|block\\)\\_>")
1285 (or (not (string-equal "block" (match-string 1))) 1316 (or (not (string-equal "block" (match-string 1)))
1286 (save-excursion 1317 (save-excursion
1287 (skip-chars-forward " \t") 1318 (skip-chars-forward " \t")
1288 (not (looking-at "data\\>")))))) 1319 (not (looking-at "data\\_>"))))))
1289 1320
1290(defsubst f90-looking-at-where-or-forall () 1321(defsubst f90-looking-at-where-or-forall ()
1291 "Return (KIND NAME) if a where or forall block starts after point. 1322 "Return (KIND NAME) if a where or forall block starts after point.
1292NAME is nil if the statement has no label." 1323NAME is nil if the statement has no label."
1293 (save-excursion 1324 (save-excursion
1294 (when (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\ 1325 (when (looking-at "\\(\\(\\(?:\\sw\\|\\s_\\)+\\)[ \t]*:\\)?[ \t]*\
1295\\(where\\|forall\\)\\>") 1326\\(where\\|forall\\)\\_>")
1296 (let ((struct (match-string 3)) 1327 (let ((struct (match-string 3))
1297 (label (match-string 2)) 1328 (label (match-string 2))
1298 (pos (scan-lists (point) 1 0))) 1329 (pos (scan-lists (point) 1 0)))
@@ -1305,43 +1336,43 @@ NAME is nil if the statement has no label."
1305NAME is non-nil only for type and certain interfaces." 1336NAME is non-nil only for type and certain interfaces."
1306 (cond 1337 (cond
1307 ((save-excursion 1338 ((save-excursion
1308 (and (looking-at "\\<type\\>[ \t]*") 1339 (and (looking-at "\\_<type\\_>[ \t]*")
1309 (goto-char (match-end 0)) 1340 (goto-char (match-end 0))
1310 (not (looking-at "\\(is\\>\\|(\\)")) 1341 (not (looking-at "\\(is\\_>\\|(\\)"))
1311 (or (looking-at "\\(\\sw+\\)") 1342 (or (looking-at "\\(\\(?:\\sw\\|\\s_\\)+\\)")
1312 (re-search-forward "[ \t]*::[ \t]*\\(\\sw+\\)" 1343 (re-search-forward "[ \t]*::[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)"
1313 (line-end-position) t)))) 1344 (line-end-position) t))))
1314 (list "type" (match-string 1))) 1345 (list "type" (match-string 1)))
1315;;; ((and (not (looking-at f90-typeis-re)) 1346;;; ((and (not (looking-at f90-typeis-re))
1316;;; (looking-at f90-type-def-re)) 1347;;; (looking-at f90-type-def-re))
1317;;; (list (match-string 1) (match-string 2))) 1348;;; (list (match-string 1) (match-string 2)))
1318 ((looking-at "\\<\\(interface\\)\\>[ \t]*") 1349 ((looking-at "\\_<\\(interface\\)\\_>[ \t]*")
1319 (list (match-string 1) 1350 (list (match-string 1)
1320 (save-excursion 1351 (save-excursion
1321 (goto-char (match-end 0)) 1352 (goto-char (match-end 0))
1322 (if (or (looking-at "\\(operator\\|assignment\\|read\\|\ 1353 (if (or (looking-at "\\(operator\\|assignment\\|read\\|\
1323write\\)[ \t]*([^)\n]*)") 1354write\\)[ \t]*([^)\n]*)")
1324 (looking-at "\\sw+")) 1355 (looking-at "\\(?:\\sw\\|\\s_\\)+"))
1325 (match-string 0))))) 1356 (match-string 0)))))
1326 ((looking-at "\\(enum\\|block[ \t]*data\\)\\>") 1357 ((looking-at "\\(enum\\|block[ \t]*data\\)\\_>")
1327 (list (match-string 1) nil)) 1358 (list (match-string 1) nil))
1328 ((looking-at "abstract[ \t]*\\(interface\\)\\>") 1359 ((looking-at "abstract[ \t]*\\(interface\\)\\_>")
1329 (list (match-string 1) nil)))) 1360 (list (match-string 1) nil))))
1330 1361
1331(defsubst f90-looking-at-program-block-start () 1362(defsubst f90-looking-at-program-block-start ()
1332 "Return (KIND NAME) if a program block with name NAME starts after point." 1363 "Return (KIND NAME) if a program block with name NAME starts after point."
1333;;;NAME is nil for an un-named main PROGRAM block." 1364;;;NAME is nil for an un-named main PROGRAM block."
1334 (cond 1365 (cond
1335 ((looking-at "\\(program\\)[ \t]+\\(\\sw+\\)\\>") 1366 ((looking-at "\\(program\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
1336 (list (match-string 1) (match-string 2))) 1367 (list (match-string 1) (match-string 2)))
1337 ((and (not (looking-at "module[ \t]*procedure\\>")) 1368 ((and (not (looking-at "module[ \t]*procedure\\_>"))
1338 (looking-at "\\(module\\)[ \t]+\\(\\sw+\\)\\>")) 1369 (looking-at "\\(module\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>"))
1339 (list (match-string 1) (match-string 2))) 1370 (list (match-string 1) (match-string 2)))
1340 ((looking-at "\\(submodule\\)[ \t]*([^)\n]+)[ \t]*\\(\\sw+\\)\\>") 1371 ((looking-at "\\(submodule\\)[ \t]*([^)\n]+)[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
1341 (list (match-string 1) (match-string 2))) 1372 (list (match-string 1) (match-string 2)))
1342 ((and (not (looking-at "end[ \t]*\\(function\\|subroutine\\)")) 1373 ((and (not (looking-at "end[ \t]*\\(function\\|subroutine\\)"))
1343 (looking-at "[^!'\"\&\n]*\\(function\\|subroutine\\)[ \t]+\ 1374 (looking-at "[^!'\"\&\n]*\\(function\\|subroutine\\)[ \t]+\
1344\\(\\sw+\\)")) 1375\\(\\(?:\\sw\\|\\s_\\)+\\)"))
1345 (list (match-string 1) (match-string 2))))) 1376 (list (match-string 1) (match-string 2)))))
1346;; Following will match an un-named main program block; however 1377;; Following will match an un-named main program block; however
1347;; one needs to check if there is an actual PROGRAM statement after 1378;; one needs to check if there is an actual PROGRAM statement after
@@ -1357,7 +1388,7 @@ write\\)[ \t]*([^)\n]*)")
1357\\(?:assignment\\|operator\\|read\\|write\\)[ \t]*([^)\n]*)\\)") 1388\\(?:assignment\\|operator\\|read\\|write\\)[ \t]*([^)\n]*)\\)")
1358 (list (match-string 1) (match-string 2))) 1389 (list (match-string 1) (match-string 2)))
1359 ((looking-at (concat "end[ \t]*" f90-blocks-re 1390 ((looking-at (concat "end[ \t]*" f90-blocks-re
1360 "?\\([ \t]+\\(\\sw+\\)\\)?\\>")) 1391 "?\\([ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\)?\\_>"))
1361 (list (match-string 1) (match-string 3))))) 1392 (list (match-string 1) (match-string 3)))))
1362 1393
1363(defsubst f90-comment-indent () 1394(defsubst f90-comment-indent ()
@@ -1414,10 +1445,10 @@ if all else fails."
1414 (not (or (looking-at "end") 1445 (not (or (looking-at "end")
1415 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\ 1446 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\
1416\\|select[ \t]*\\(case\\|type\\)\\|case\\|where\\|forall\\|\ 1447\\|select[ \t]*\\(case\\|type\\)\\|case\\|where\\|forall\\|\
1417block\\|critical\\)\\>") 1448block\\|critical\\)\\_>")
1418 (looking-at "\\(program\\|\\(?:sub\\)?module\\|\ 1449 (looking-at "\\(program\\|\\(?:sub\\)?module\\|\
1419\\(?:abstract[ \t]*\\)?interface\\|block[ \t]*data\\)\\>") 1450\\(?:abstract[ \t]*\\)?interface\\|block[ \t]*data\\)\\_>")
1420 (looking-at "\\(contains\\|\\sw+[ \t]*:\\)") 1451 (looking-at "\\(contains\\|\\(?:\\sw\\|\\s_\\)+[ \t]*:\\)")
1421 (looking-at f90-type-def-re) 1452 (looking-at f90-type-def-re)
1422 (re-search-forward "\\(function\\|subroutine\\)" 1453 (re-search-forward "\\(function\\|subroutine\\)"
1423 (line-end-position) t))))) 1454 (line-end-position) t)))))
@@ -1483,7 +1514,7 @@ Does not check type and subprogram indentation."
1483 (setq icol (- icol f90-associate-indent))) 1514 (setq icol (- icol f90-associate-indent)))
1484 ((f90-looking-at-end-critical) 1515 ((f90-looking-at-end-critical)
1485 (setq icol (- icol f90-critical-indent))) 1516 (setq icol (- icol f90-critical-indent)))
1486 ((looking-at "end[ \t]*do\\>") 1517 ((looking-at "end[ \t]*do\\_>")
1487 (setq icol (- icol f90-do-indent)))) 1518 (setq icol (- icol f90-do-indent))))
1488 (end-of-line)) 1519 (end-of-line))
1489 icol))) 1520 icol)))
@@ -1550,7 +1581,7 @@ Does not check type and subprogram indentation."
1550 (cond ((or (looking-at f90-else-like-re) 1581 (cond ((or (looking-at f90-else-like-re)
1551 (looking-at f90-end-if-re)) 1582 (looking-at f90-end-if-re))
1552 (setq icol (- icol f90-if-indent))) 1583 (setq icol (- icol f90-if-indent)))
1553 ((looking-at "end[ \t]*do\\>") 1584 ((looking-at "end[ \t]*do\\_>")
1554 (setq icol (- icol f90-do-indent))) 1585 (setq icol (- icol f90-do-indent)))
1555 ((looking-at f90-end-type-re) 1586 ((looking-at f90-end-type-re)
1556 (setq icol (- icol f90-type-indent))) 1587 (setq icol (- icol f90-type-indent)))
@@ -1671,7 +1702,7 @@ Interactively, pushes mark before moving point."
1671 (setq start-list (cons start-this start-list) ; not add-to-list! 1702 (setq start-list (cons start-this start-list) ; not add-to-list!
1672 count (1+ count))) 1703 count (1+ count)))
1673 ((looking-at (concat "end[ \t]*" f90-blocks-re 1704 ((looking-at (concat "end[ \t]*" f90-blocks-re
1674 "[ \t]*\\(\\sw+\\)?")) 1705 "[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"))
1675 (setq end-type (match-string 1) 1706 (setq end-type (match-string 1)
1676 end-label (match-string 2) 1707 end-label (match-string 2)
1677 count (1- count)) 1708 count (1- count))
@@ -1716,7 +1747,7 @@ Interactively, pushes mark before moving point."
1716 (skip-chars-forward " \t0-9") 1747 (skip-chars-forward " \t0-9")
1717 (cond ((or (f90-in-string) (f90-in-comment))) 1748 (cond ((or (f90-in-string) (f90-in-comment)))
1718 ((looking-at (concat "end[ \t]*" f90-blocks-re 1749 ((looking-at (concat "end[ \t]*" f90-blocks-re
1719 "[ \t]*\\(\\sw+\\)?")) 1750 "[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"))
1720 (setq end-list (cons (list (match-string 1) (match-string 2)) 1751 (setq end-list (cons (list (match-string 1) (match-string 2))
1721 end-list) 1752 end-list)
1722 count (1+ count))) 1753 count (1+ count)))
@@ -1962,7 +1993,7 @@ If run in the middle of a line, the line is not broken."
1962 (car end-struct) (cadr end-struct)))) 1993 (car end-struct) (cadr end-struct))))
1963 (setq ind-b 1994 (setq ind-b
1964 (cond ((looking-at f90-end-if-re) f90-if-indent) 1995 (cond ((looking-at f90-end-if-re) f90-if-indent)
1965 ((looking-at "end[ \t]*do\\>") f90-do-indent) 1996 ((looking-at "end[ \t]*do\\_>") f90-do-indent)
1966 ((looking-at f90-end-type-re) f90-type-indent) 1997 ((looking-at f90-end-type-re) f90-type-indent)
1967 ((looking-at f90-end-associate-re) 1998 ((looking-at f90-end-associate-re)
1968 f90-associate-indent) 1999 f90-associate-indent)
@@ -2108,12 +2139,19 @@ Like `join-line', but handles F90 syntax."
2108 (zmacs-deactivate-region) 2139 (zmacs-deactivate-region)
2109 (deactivate-mark)))) 2140 (deactivate-mark))))
2110 2141
2142(defconst f90-end-block-optional-name
2143 '("program" "module" "subroutine" "function" "type")
2144 "Block types where including the name in the end statement is optional.")
2145
2111(defun f90-block-match (beg-block beg-name end-block end-name) 2146(defun f90-block-match (beg-block beg-name end-block end-name)
2112 "Match end-struct with beg-struct and complete end-block if possible. 2147 "Match end-struct with beg-struct and complete end-block if possible.
2113BEG-BLOCK is the type of block as indicated at the start (e.g., do). 2148BEG-BLOCK is the type of block as indicated at the start (e.g., do).
2114BEG-NAME is the block start name (may be nil). 2149BEG-NAME is the block start name (may be nil).
2115END-BLOCK is the type of block as indicated at the end (may be nil). 2150END-BLOCK is the type of block as indicated at the end (may be nil).
2116END-NAME is the block end name (may be nil). 2151END-NAME is the block end name (may be nil).
2152If the block type matches `f90-end-block-optional-name', do not add
2153an end name if `f90-smart-end-names' is nil, but always update an
2154incorrect end name if there already was one.
2117Leave point at the end of line." 2155Leave point at the end of line."
2118 ;; Hack to deal with the case when this is called from 2156 ;; Hack to deal with the case when this is called from
2119 ;; f90-indent-region on a program block without an explicit PROGRAM 2157 ;; f90-indent-region on a program block without an explicit PROGRAM
@@ -2133,8 +2171,11 @@ Leave point at the end of line."
2133 (if (f90-equal-symbols beg-name end-name) 2171 (if (f90-equal-symbols beg-name end-name)
2134 (and end-name (search-forward end-name)) 2172 (and end-name (search-forward end-name))
2135 (cond ((and beg-name (not end-name)) 2173 (cond ((and beg-name (not end-name))
2136 (message "Inserting %s." beg-name) 2174 (unless (and (not f90-smart-end-names)
2137 (insert (concat " " beg-name))) 2175 (member-ignore-case beg-block
2176 f90-end-block-optional-name))
2177 (message "Inserting %s." beg-name)
2178 (insert (concat " " beg-name))))
2138 ((and beg-name end-name) 2179 ((and beg-name end-name)
2139 (message "Replacing %s with %s." end-name beg-name) 2180 (message "Replacing %s with %s." end-name beg-name)
2140 (search-forward end-name) 2181 (search-forward end-name)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 0f92df95a9d..99b48e8d0db 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1,4 +1,4 @@
1;;; flymake.el -- a universal on-the-fly syntax checker 1;;; flymake.el --- a universal on-the-fly syntax checker
2 2
3;; Copyright (C) 2003-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2003-2013 Free Software Foundation, Inc.
4 4
@@ -68,6 +68,9 @@
68 68
69;;;; [[ cross-emacs compatibility routines 69;;;; [[ cross-emacs compatibility routines
70(defsubst flymake-makehash (&optional test) 70(defsubst flymake-makehash (&optional test)
71 "Create and return a new hash table using TEST to compare keys.
72It uses the function `make-hash-table' to make a hash-table if
73you use GNU Emacs, otherwise it uses `makehash'."
71 (if (fboundp 'make-hash-table) 74 (if (fboundp 'make-hash-table)
72 (if test (make-hash-table :test test) (make-hash-table)) 75 (if test (make-hash-table :test test) (make-hash-table))
73 (with-no-warnings 76 (with-no-warnings
@@ -106,10 +109,12 @@ Zero-length substrings at the beginning and end of the list are omitted."
106 (lambda () temporary-file-directory))) 109 (lambda () temporary-file-directory)))
107 110
108(defun flymake-posn-at-point-as-event (&optional position window dx dy) 111(defun flymake-posn-at-point-as-event (&optional position window dx dy)
109 "Return pixel position of top left corner of glyph at POSITION, 112 "Return pixel position of top left corner of glyph at POSITION.
110relative to top left corner of WINDOW, as a mouse-1 click 113
111event (identical to the event that would be triggered by clicking 114The position is relative to top left corner of WINDOW, as a
112mouse button 1 at the top left corner of the glyph). 115mouse-1 click event (identical to the event that would be
116triggered by clicking mouse button 1 at the top left corner of
117the glyph).
113 118
114POSITION and WINDOW default to the position of point in the 119POSITION and WINDOW default to the position of point in the
115selected window. 120selected window.
@@ -164,7 +169,9 @@ See `x-popup-menu' for the menu specifier format."
164 169
165(if (featurep 'xemacs) (progn 170(if (featurep 'xemacs) (progn
166 171
167(defun flymake-nop ()) 172(defun flymake-nop ()
173 "Do nothing."
174 nil)
168 175
169(defun flymake-make-xemacs-menu (menu-data) 176(defun flymake-make-xemacs-menu (menu-data)
170 "Return a menu specifier using MENU-DATA." 177 "Return a menu specifier using MENU-DATA."
@@ -187,6 +194,7 @@ See `x-popup-menu' for the menu specifier format."
187 (count-lines (window-start) (point)))) 194 (count-lines (window-start) (point))))
188 195
189(defun flymake-selected-frame () 196(defun flymake-selected-frame ()
197 "Return the frame that is now selected."
190 (if (fboundp 'window-edges) 198 (if (fboundp 'window-edges)
191 (selected-frame) 199 (selected-frame)
192 (selected-window))) 200 (selected-window)))
@@ -217,31 +225,41 @@ See `x-popup-menu' for the menu specifier format."
217 :group 'flymake 225 :group 'flymake
218 :type 'integer) 226 :type 'integer)
219 227
228
229;; (defcustom flymake-log-file-name "~/flymake.log"
230;; "Where to put the flymake log if logging is enabled.
231;;
232;; See `flymake-log-level' if you want to control what is logged."
233;; :group 'flymake
234;; :type 'string)
235
220(defun flymake-log (level text &rest args) 236(defun flymake-log (level text &rest args)
221 "Log a message at level LEVEL. 237 "Log a message at level LEVEL.
222If LEVEL is higher than `flymake-log-level', the message is 238If LEVEL is higher than `flymake-log-level', the message is
223ignored. Otherwise, it is printed using `message'. 239ignored. Otherwise, it is printed using `message'.
224TEXT is a format control string, and the remaining arguments ARGS 240TEXT is a format control string, and the remaining arguments ARGS
225are the string substitutions (see `format')." 241are the string substitutions (see the function `format')."
226 (if (<= level flymake-log-level) 242 (if (<= level flymake-log-level)
227 (let* ((msg (apply 'format text args))) 243 (let* ((msg (apply 'format text args)))
228 (message "%s" msg) 244 (message "%s" msg)
229 ;;(with-temp-buffer 245 ;;(with-temp-buffer
230 ;; (insert msg) 246 ;; (insert msg)
231 ;; (insert "\n") 247 ;; (insert "\n")
232 ;; (flymake-save-buffer-in-file "d:/flymake.log" t) ; make log file name customizable 248 ;; (flymake-save-buffer-in-file "~/flymake.log") ; make log file name customizable
233 ;;) 249 ;;)
234 ))) 250 )))
235 251
236(defun flymake-ins-after (list pos val) 252(defun flymake-ins-after (list pos val)
237 "Insert VAL into LIST after position POS." 253 "Insert VAL into LIST after position POS.
238 (let ((tmp (copy-sequence list))) ; (???) 254POS counts from zero."
255 (let ((tmp (copy-sequence list)))
239 (setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp))) 256 (setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp)))
240 tmp)) 257 tmp))
241 258
242(defun flymake-set-at (list pos val) 259(defun flymake-set-at (list pos val)
243 "Set VAL at position POS in LIST." 260 "Set VAL at position POS in LIST.
244 (let ((tmp (copy-sequence list))) ; (???) 261POS counts from zero."
262 (let ((tmp (copy-sequence list)))
245 (setcar (nthcdr pos tmp) val) 263 (setcar (nthcdr pos tmp) val)
246 tmp)) 264 tmp))
247 265
@@ -249,7 +267,6 @@ are the string substitutions (see `format')."
249 "List of currently active flymake processes.") 267 "List of currently active flymake processes.")
250 268
251(defvar flymake-output-residual nil) 269(defvar flymake-output-residual nil)
252
253(make-variable-buffer-local 'flymake-output-residual) 270(make-variable-buffer-local 'flymake-output-residual)
254 271
255(defgroup flymake nil 272(defgroup flymake nil
@@ -257,6 +274,13 @@ are the string substitutions (see `format')."
257 :version "23.1" 274 :version "23.1"
258 :group 'tools) 275 :group 'tools)
259 276
277(defcustom flymake-xml-program
278 (if (executable-find "xmlstarlet") "xmlstarlet" "xml")
279 "Program to use for XML validation."
280 :type 'file
281 :group 'flymake
282 :version "24.4")
283
260(defcustom flymake-allowed-file-name-masks 284(defcustom flymake-allowed-file-name-masks
261 '(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'" flymake-simple-make-init) 285 '(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'" flymake-simple-make-init)
262 ("\\.xml\\'" flymake-xml-init) 286 ("\\.xml\\'" flymake-xml-init)
@@ -279,16 +303,31 @@ are the string substitutions (see `format')."
279 ;; ("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2 )) 303 ;; ("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2 ))
280 ;; ("\\.tex\\'" 1) 304 ;; ("\\.tex\\'" 1)
281 ) 305 )
282 "Files syntax checking is allowed for." 306 "Files syntax checking is allowed for.
307This is an alist with elements of the form:
308 REGEXP INIT [CLEANUP [NAME]]
309REGEXP is a regular expression that matches a file name.
310INIT is the init function to use.
311CLEANUP is the cleanup function to use, default `flymake-simple-cleanup'.
312NAME is the file name function to use, default `flymake-get-real-file-name'."
283 :group 'flymake 313 :group 'flymake
284 :type '(repeat (string symbol symbol symbol))) 314 :type '(alist :key-type (regexp :tag "File regexp")
315 :value-type
316 (list :tag "Handler functions"
317 (function :tag "Init function")
318 (choice :tag "Cleanup function"
319 (const :tag "flymake-simple-cleanup" nil)
320 function)
321 (choice :tag "Name function"
322 (const :tag "flymake-get-real-file-name" nil)
323 function))))
285 324
286(defun flymake-get-file-name-mode-and-masks (file-name) 325(defun flymake-get-file-name-mode-and-masks (file-name)
287 "Return the corresponding entry from `flymake-allowed-file-name-masks'." 326 "Return the corresponding entry from `flymake-allowed-file-name-masks'."
288 (unless (stringp file-name) 327 (unless (stringp file-name)
289 (error "Invalid file-name")) 328 (error "Invalid file-name"))
290 (let ((fnm flymake-allowed-file-name-masks) 329 (let ((fnm flymake-allowed-file-name-masks)
291 (mode-and-masks nil)) 330 (mode-and-masks nil))
292 (while (and (not mode-and-masks) fnm) 331 (while (and (not mode-and-masks) fnm)
293 (if (string-match (car (car fnm)) file-name) 332 (if (string-match (car (car fnm)) file-name)
294 (setq mode-and-masks (cdr (car fnm)))) 333 (setq mode-and-masks (cdr (car fnm))))
@@ -314,18 +353,22 @@ Return nil if we cannot, non-nil if we can."
314 'flymake-simple-cleanup)) 353 'flymake-simple-cleanup))
315 354
316(defun flymake-get-real-file-name-function (file-name) 355(defun flymake-get-real-file-name-function (file-name)
317 (or (nth 2 (flymake-get-file-name-mode-and-masks file-name)) 356 (or (nth 4 (flymake-get-file-name-mode-and-masks file-name))
318 'flymake-get-real-file-name)) 357 'flymake-get-real-file-name))
319 358
320(defvar flymake-find-buildfile-cache (flymake-makehash 'equal)) 359(defvar flymake-find-buildfile-cache (flymake-makehash 'equal))
321 360
322(defun flymake-get-buildfile-from-cache (dir-name) 361(defun flymake-get-buildfile-from-cache (dir-name)
362 "Look up DIR-NAME in cache and return its associated value.
363If DIR-NAME is not found, return nil."
323 (gethash dir-name flymake-find-buildfile-cache)) 364 (gethash dir-name flymake-find-buildfile-cache))
324 365
325(defun flymake-add-buildfile-to-cache (dir-name buildfile) 366(defun flymake-add-buildfile-to-cache (dir-name buildfile)
367 "Associate DIR-NAME with BUILDFILE in the buildfile cache."
326 (puthash dir-name buildfile flymake-find-buildfile-cache)) 368 (puthash dir-name buildfile flymake-find-buildfile-cache))
327 369
328(defun flymake-clear-buildfile-cache () 370(defun flymake-clear-buildfile-cache ()
371 "Clear the buildfile cache."
329 (clrhash flymake-find-buildfile-cache)) 372 (clrhash flymake-find-buildfile-cache))
330 373
331(defun flymake-find-buildfile (buildfile-name source-dir-name) 374(defun flymake-find-buildfile (buildfile-name source-dir-name)
@@ -372,9 +415,11 @@ Return t if so, nil if not."
372 415
373(defun flymake-find-possible-master-files (file-name master-file-dirs masks) 416(defun flymake-find-possible-master-files (file-name master-file-dirs masks)
374 "Find (by name and location) all possible master files. 417 "Find (by name and location) all possible master files.
375Master files include .cpp and .c for .h. Files are searched for 418
376starting from the .h directory and max max-level parent dirs. 419Name is specified by FILE-NAME and location is specified by
377File contents are not checked." 420MASTER-FILE-DIRS. Master files include .cpp and .c for .h.
421Files are searched for starting from the .h directory and max
422max-level parent dirs. File contents are not checked."
378 (let* ((dirs master-file-dirs) 423 (let* ((dirs master-file-dirs)
379 (files nil) 424 (files nil)
380 (done nil)) 425 (done nil))
@@ -571,6 +616,8 @@ Find master file, patch and save it."
571 nil)))) 616 nil))))
572 617
573(defun flymake-save-buffer-in-file (file-name) 618(defun flymake-save-buffer-in-file (file-name)
619 "Save the entire buffer contents into file FILE-NAME.
620Create parent directories as needed."
574 (make-directory (file-name-directory file-name) 1) 621 (make-directory (file-name-directory file-name) 1)
575 (write-region nil nil file-name nil 566) 622 (write-region nil nil file-name nil 566)
576 (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name)) 623 (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name))
@@ -1837,7 +1884,9 @@ Use CREATE-TEMP-F for creating temp copy."
1837 1884
1838;;;; xml-specific init-cleanup routines 1885;;;; xml-specific init-cleanup routines
1839(defun flymake-xml-init () 1886(defun flymake-xml-init ()
1840 (list "xml" (list "val" (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace)))) 1887 (list flymake-xml-program
1888 (list "val" (flymake-init-create-temp-buffer-copy
1889 'flymake-create-temp-inplace))))
1841 1890
1842(provide 'flymake) 1891(provide 'flymake)
1843 1892
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 8ba2822c3a3..0b52302a98d 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -91,7 +91,7 @@
91(require 'gud) 91(require 'gud)
92(require 'json) 92(require 'json)
93(require 'bindat) 93(require 'bindat)
94(eval-when-compile (require 'cl-lib)) 94(require 'cl-lib)
95 95
96(declare-function speedbar-change-initial-expansion-list 96(declare-function speedbar-change-initial-expansion-list
97 "speedbar" (new-default)) 97 "speedbar" (new-default))
@@ -206,8 +206,8 @@ Only used for files that Emacs can't find.")
206(defvar gdb-last-command nil) 206(defvar gdb-last-command nil)
207(defvar gdb-prompt-name nil) 207(defvar gdb-prompt-name nil)
208(defvar gdb-token-number 0) 208(defvar gdb-token-number 0)
209(defvar gdb-handler-alist '()) 209(defvar gdb-handler-list '()
210(defvar gdb-handler-number nil) 210 "List of gdb-handler keeping track of all pending GDB commands.")
211(defvar gdb-source-file-list nil 211(defvar gdb-source-file-list nil
212 "List of source files for the current executable.") 212 "List of source files for the current executable.")
213(defvar gdb-first-done-or-error t) 213(defvar gdb-first-done-or-error t)
@@ -242,33 +242,114 @@ Possible values are these symbols:
242 disposition of output generated by commands that 242 disposition of output generated by commands that
243 gdb mode sends to gdb on its own behalf.") 243 gdb mode sends to gdb on its own behalf.")
244 244
245;; Pending triggers prevent congestion: Emacs won't send two similar 245(defcustom gdb-discard-unordered-replies t
246;; consecutive requests. 246 "Non-nil means discard any out-of-order GDB replies.
247 247This protects against lost GDB replies, assuming that GDB always
248(defvar gdb-pending-triggers '() 248replies in the same order as Emacs sends commands. When receiving a
249 "A list of trigger functions which have not yet been handled. 249reply with a given token-number, assume any pending messages with a
250 250lower token-number are out-of-order."
251Elements are either function names or pairs (buffer . function)") 251 :type 'boolean
252 252 :group 'gud
253(defmacro gdb-add-pending (item) 253 :version "24.4")
254 `(push ,item gdb-pending-triggers)) 254
255(defmacro gdb-pending-p (item) 255(cl-defstruct gdb-handler
256 `(member ,item gdb-pending-triggers)) 256 "Data required to handle the reply of a command sent to GDB."
257(defmacro gdb-delete-pending (item) 257 ;; Prefix of the command sent to GDB. The GDB reply for this command
258 `(setq gdb-pending-triggers 258 ;; will be prefixed with this same TOKEN-NUMBER
259 (delete ,item gdb-pending-triggers))) 259 (token-number nil :read-only t)
260 ;; Callback to invoke when the reply is received from GDB
261 (function nil :read-only t)
262 ;; PENDING-TRIGGER is used to prevent congestion: Emacs won't send
263 ;; two requests with the same PENDING-TRIGGER until a reply is received
264 ;; for the first one."
265 (pending-trigger nil))
266
267(defun gdb-add-handler (token-number handler-function &optional pending-trigger)
268 "Insert a new GDB command handler in `gdb-handler-list'.
269Handlers are used to keep track of the commands sent to GDB
270and to handle the replies received.
271Upon reception of a reply prefixed with TOKEN-NUMBER,
272invoke the callback HANDLER-FUNCTION.
273If PENDING-TRIGGER is specified, no new GDB commands will be
274sent with this same PENDING-TRIGGER until a reply is received
275for this handler."
276
277 (push (make-gdb-handler :token-number token-number
278 :function handler-function
279 :pending-trigger pending-trigger)
280 gdb-handler-list))
281
282(defun gdb-delete-handler (token-number)
283 "Remove the handler TOKEN-NUMBER from `gdb-handler-list'.
284Additionally, if `gdb-discard-unordered-replies' is non-nil,
285discard all handlers having a token number less than TOKEN-NUMBER."
286 (if gdb-discard-unordered-replies
287
288 (setq gdb-handler-list
289 (cl-delete-if
290 (lambda (handler)
291 "Discard any HANDLER with a token number `<=' than TOKEN-NUMBER."
292 (when (< (gdb-handler-token-number handler) token-number)
293 (message (format
294 "WARNING! Discarding GDB handler with token #%d\n"
295 (gdb-handler-token-number handler))))
296 (<= (gdb-handler-token-number handler) token-number))
297 gdb-handler-list))
298
299 (setq gdb-handler-list
300 (cl-delete-if
301 (lambda (handler)
302 "Discard any HANDLER with a token number `eq' to TOKEN-NUMBER."
303 (eq (gdb-handler-token-number handler) token-number))
304 gdb-handler-list))))
305
306(defun gdb-get-handler-function (token-number)
307 "Return the function callback registered with the handler TOKEN-NUMBER."
308 (gdb-handler-function
309 (cl-find-if (lambda (handler) (eq (gdb-handler-token-number handler)
310 token-number))
311 gdb-handler-list)))
312
313
314(defun gdb-pending-handler-p (pending-trigger)
315 "Return non-nil if a command handler is pending with trigger PENDING-TRIGGER."
316 (cl-find-if (lambda (handler) (eq (gdb-handler-pending-trigger handler)
317 pending-trigger))
318 gdb-handler-list))
319
320
321(defun gdb-handle-reply (token-number)
322 "Handle the GDB reply TOKEN-NUMBER.
323This invokes the handler registered with this token number
324in `gdb-handler-list' and clears all pending handlers invalidated
325by the reception of this reply."
326 (let ((handler-function (gdb-get-handler-function token-number)))
327 (when handler-function
328 (funcall handler-function)
329 (gdb-delete-handler token-number))))
330
331(defun gdb-remove-all-pending-triggers ()
332 "Remove all pending triggers from gdb-handler-list.
333The handlers are left in gdb-handler-list so that replies received
334from GDB could still be handled. However, removing the pending triggers
335allows Emacs to send new commands even if replies of previous commands
336were not yet received."
337 (dolist (handler gdb-handler-list)
338 (setf (gdb-handler-pending-trigger handler) nil)))
260 339
261(defmacro gdb-wait-for-pending (&rest body) 340(defmacro gdb-wait-for-pending (&rest body)
262 "Wait until `gdb-pending-triggers' is empty and evaluate FORM. 341 "Wait for all pending GDB commands to finish and evaluate BODY.
263 342
264This function checks `gdb-pending-triggers' value every 343This function checks every 0.5 seconds if there are any pending
265`gdb-wait-for-pending' seconds." 344triggers in `gdb-handler-list'."
266 (run-with-timer 345 `(run-with-timer
267 0.5 nil 346 0.5 nil
268 `(lambda () 347 '(lambda ()
269 (if (not gdb-pending-triggers) 348 (if (not (cl-find-if (lambda (handler)
270 (progn ,@body) 349 (gdb-handler-pending-trigger handler))
271 (gdb-wait-for-pending ,@body))))) 350 gdb-handler-list))
351 (progn ,@body)
352 (gdb-wait-for-pending ,@body)))))
272 353
273;; Publish-subscribe 354;; Publish-subscribe
274 355
@@ -574,21 +655,20 @@ NOARG must be t when this macro is used outside `gud-def'"
574 (concat (gdb-gud-context-command ,cmd1 ,noall) " " ,cmd2) 655 (concat (gdb-gud-context-command ,cmd1 ,noall) " " ,cmd2)
575 ,(when (not noarg) 'arg))) 656 ,(when (not noarg) 'arg)))
576 657
577(defun gdb--check-interpreter (proc string) 658(defun gdb--check-interpreter (filter proc string)
578 (unless (zerop (length string)) 659 (unless (zerop (length string))
579 (let ((filter (process-get proc 'gud-normal-filter))) 660 (remove-function (process-filter proc) #'gdb--check-interpreter)
580 (set-process-filter proc filter) 661 (unless (memq (aref string 0) '(?^ ?~ ?@ ?& ?* ?=))
581 (unless (memq (aref string 0) '(?^ ?~ ?@ ?& ?* ?=)) 662 ;; Apparently we're not running with -i=mi.
582 ;; Apparently we're not running with -i=mi. 663 (let ((msg "Error: you did not specify -i=mi on GDB's command line!"))
583 (let ((msg "Error: you did not specify -i=mi on GDB's command line!")) 664 (message msg)
584 (message msg) 665 (setq string (concat (propertize msg 'font-lock-face 'error)
585 (setq string (concat (propertize msg 'font-lock-face 'error) 666 "\n" string)))
586 "\n" string))) 667 ;; Use the old gud-gbd filter, not because it works, but because it
587 ;; Use the old gud-gbd filter, not because it works, but because it 668 ;; will properly display GDB's answers rather than hanging waiting for
588 ;; will properly display GDB's answers rather than hanging waiting for 669 ;; answers that aren't coming.
589 ;; answers that aren't coming. 670 (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter))
590 (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter)) 671 (funcall filter proc string)))
591 (funcall filter proc string))))
592 672
593(defvar gdb-control-level 0) 673(defvar gdb-control-level 0)
594 674
@@ -662,8 +742,7 @@ detailed description of this mode.
662 ;; Setup a temporary process filter to warn when GDB was not started 742 ;; Setup a temporary process filter to warn when GDB was not started
663 ;; with -i=mi. 743 ;; with -i=mi.
664 (let ((proc (get-buffer-process gud-comint-buffer))) 744 (let ((proc (get-buffer-process gud-comint-buffer)))
665 (process-put proc 'gud-normal-filter (process-filter proc)) 745 (add-function :around (process-filter proc) #'gdb--check-interpreter))
666 (set-process-filter proc #'gdb--check-interpreter))
667 746
668 (set (make-local-variable 'gud-minor-mode) 'gdbmi) 747 (set (make-local-variable 'gud-minor-mode) 'gdbmi)
669 (set (make-local-variable 'gdb-control-level) 0) 748 (set (make-local-variable 'gdb-control-level) 0)
@@ -822,14 +901,12 @@ detailed description of this mode.
822 gdb-frame-number nil 901 gdb-frame-number nil
823 gdb-thread-number nil 902 gdb-thread-number nil
824 gdb-var-list nil 903 gdb-var-list nil
825 gdb-pending-triggers nil
826 gdb-output-sink 'user 904 gdb-output-sink 'user
827 gdb-location-alist nil 905 gdb-location-alist nil
828 gdb-source-file-list nil 906 gdb-source-file-list nil
829 gdb-last-command nil 907 gdb-last-command nil
830 gdb-token-number 0 908 gdb-token-number 0
831 gdb-handler-alist '() 909 gdb-handler-list '()
832 gdb-handler-number nil
833 gdb-prompt-name nil 910 gdb-prompt-name nil
834 gdb-first-done-or-error t 911 gdb-first-done-or-error t
835 gdb-buffer-fringe-width (car (window-fringes)) 912 gdb-buffer-fringe-width (car (window-fringes))
@@ -1109,17 +1186,15 @@ With arg, enter name of variable to be watched in the minibuffer."
1109 (message-box "No symbol \"%s\" in current context." expr)))) 1186 (message-box "No symbol \"%s\" in current context." expr))))
1110 1187
1111(defun gdb-speedbar-update () 1188(defun gdb-speedbar-update ()
1112 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame) 1189 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
1113 (not (gdb-pending-p 'gdb-speedbar-timer)))
1114 ;; Dummy command to update speedbar even when idle. 1190 ;; Dummy command to update speedbar even when idle.
1115 (gdb-input "-environment-pwd" 'gdb-speedbar-timer-fn) 1191 (gdb-input "-environment-pwd"
1116 ;; Keep gdb-pending-triggers non-nil till end. 1192 'gdb-speedbar-timer-fn
1117 (gdb-add-pending 'gdb-speedbar-timer))) 1193 'gdb-speedbar-update)))
1118 1194
1119(defun gdb-speedbar-timer-fn () 1195(defun gdb-speedbar-timer-fn ()
1120 (if gdb-speedbar-auto-raise 1196 (if gdb-speedbar-auto-raise
1121 (raise-frame speedbar-frame)) 1197 (raise-frame speedbar-frame))
1122 (gdb-delete-pending 'gdb-speedbar-timer)
1123 (speedbar-timer-fn)) 1198 (speedbar-timer-fn))
1124 1199
1125(defun gdb-var-evaluate-expression-handler (varnum changed) 1200(defun gdb-var-evaluate-expression-handler (varnum changed)
@@ -1209,9 +1284,9 @@ With arg, enter name of variable to be watched in the minibuffer."
1209 1284
1210 ; Uses "-var-update --all-values". Needs GDB 6.4 onwards. 1285 ; Uses "-var-update --all-values". Needs GDB 6.4 onwards.
1211(defun gdb-var-update () 1286(defun gdb-var-update ()
1212 (if (not (gdb-pending-p 'gdb-var-update)) 1287 (gdb-input "-var-update --all-values *"
1213 (gdb-input "-var-update --all-values *" 'gdb-var-update-handler)) 1288 'gdb-var-update-handler
1214 (gdb-add-pending 'gdb-var-update)) 1289 'gdb-var-update))
1215 1290
1216(defun gdb-var-update-handler () 1291(defun gdb-var-update-handler ()
1217 (let ((changelist (bindat-get-field (gdb-json-partial-output) 'changelist))) 1292 (let ((changelist (bindat-get-field (gdb-json-partial-output) 'changelist)))
@@ -1274,8 +1349,6 @@ With arg, enter name of variable to be watched in the minibuffer."
1274 (push var1 var-list)) 1349 (push var1 var-list))
1275 (setq var1 (pop temp-var-list))) 1350 (setq var1 (pop temp-var-list)))
1276 (setq gdb-var-list (nreverse var-list)))))))) 1351 (setq gdb-var-list (nreverse var-list))))))))
1277 (setq gdb-pending-triggers
1278 (delq 'gdb-var-update gdb-pending-triggers))
1279 (gdb-speedbar-update)) 1352 (gdb-speedbar-update))
1280 1353
1281(defun gdb-speedbar-expand-node (text token indent) 1354(defun gdb-speedbar-expand-node (text token indent)
@@ -1729,18 +1802,25 @@ All embedded quotes, newlines, and backslashes are preceded with a backslash."
1729 (setq string (replace-regexp-in-string "\n" "\\n" string t t)) 1802 (setq string (replace-regexp-in-string "\n" "\\n" string t t))
1730 (concat "\"" string "\"")) 1803 (concat "\"" string "\""))
1731 1804
1732(defun gdb-input (command handler-function) 1805(defun gdb-input (command handler-function &optional trigger-name)
1733 "Send COMMAND to GDB via the MI interface. 1806 "Send COMMAND to GDB via the MI interface.
1734Run the function HANDLER-FUNCTION, with no arguments, once the command is 1807Run the function HANDLER-FUNCTION, with no arguments, once the command is
1735complete." 1808complete. Do not send COMMAND to GDB if TRIGGER-NAME is non-nil and
1736 (if gdb-enable-debug (push (list 'send-item command handler-function) 1809Emacs is still waiting for a reply from another command previously
1737 gdb-debug-log)) 1810sent with the same TRIGGER-NAME."
1738 (setq gdb-token-number (1+ gdb-token-number)) 1811 (when (or (not trigger-name)
1739 (setq command (concat (number-to-string gdb-token-number) command)) 1812 (not (gdb-pending-handler-p trigger-name)))
1740 (push (cons gdb-token-number handler-function) gdb-handler-alist) 1813 (setq gdb-token-number (1+ gdb-token-number))
1741 (if gdbmi-debug-mode (message "gdb-input: %s" command)) 1814 (setq command (concat (number-to-string gdb-token-number) command))
1742 (process-send-string (get-buffer-process gud-comint-buffer) 1815
1743 (concat command "\n"))) 1816 (if gdb-enable-debug (push (list 'send-item command handler-function)
1817 gdb-debug-log))
1818
1819 (gdb-add-handler gdb-token-number handler-function trigger-name)
1820
1821 (if gdbmi-debug-mode (message "gdb-input: %s" command))
1822 (process-send-string (get-buffer-process gud-comint-buffer)
1823 (concat command "\n"))))
1744 1824
1745;; NOFRAME is used for gud execution control commands 1825;; NOFRAME is used for gud execution control commands
1746(defun gdb-current-context-command (command) 1826(defun gdb-current-context-command (command)
@@ -1776,7 +1856,7 @@ If `gdb-thread-number' is nil, just wrap NAME in asterisks."
1776(defun gdb-resync() 1856(defun gdb-resync()
1777 (setq gud-running nil) 1857 (setq gud-running nil)
1778 (setq gdb-output-sink 'user) 1858 (setq gdb-output-sink 'user)
1779 (setq gdb-pending-triggers nil)) 1859 (gdb-remove-all-pending-triggers))
1780 1860
1781(defun gdb-update (&optional no-proc) 1861(defun gdb-update (&optional no-proc)
1782 "Update buffers showing status of debug session. 1862 "Update buffers showing status of debug session.
@@ -2149,19 +2229,23 @@ the end of the current result or async record is reached."
2149 ;; Search the data stream for the end of the current record: 2229 ;; Search the data stream for the end of the current record:
2150 (let* ((newline-pos (string-match "\n" gud-marker-acc gdbmi-bnf-offset)) 2230 (let* ((newline-pos (string-match "\n" gud-marker-acc gdbmi-bnf-offset))
2151 (is-progressive (equal (cdr class-command) 'progressive)) 2231 (is-progressive (equal (cdr class-command) 'progressive))
2152 (is-complete (not (null newline-pos))) 2232 (is-complete (not (null newline-pos)))
2153 result-str) 2233 result-str)
2234
2235 (when gdbmi-debug-mode
2236 (message "gdbmi-bnf-incomplete-record-result: %s"
2237 (substring gud-marker-acc gdbmi-bnf-offset newline-pos)))
2154 2238
2155 ;; Update the gdbmi-bnf-offset only if the current chunk of data can 2239 ;; Update the gdbmi-bnf-offset only if the current chunk of data can
2156 ;; be processed by the class-command handler: 2240 ;; be processed by the class-command handler:
2157 (when (or is-complete is-progressive) 2241 (when (or is-complete is-progressive)
2158 (setq result-str 2242 (setq result-str
2159 (substring gud-marker-acc gdbmi-bnf-offset newline-pos)) 2243 (substring gud-marker-acc gdbmi-bnf-offset newline-pos))
2160 (setq gdbmi-bnf-offset (+ 1 newline-pos)))
2161 2244
2162 (if gdbmi-debug-mode 2245 ;; Move gdbmi-bnf-offset past the end of the chunk.
2163 (message "gdbmi-bnf-incomplete-record-result: %s" 2246 (setq gdbmi-bnf-offset (+ gdbmi-bnf-offset (length result-str)))
2164 (substring gud-marker-acc gdbmi-bnf-offset newline-pos))) 2247 (when newline-pos
2248 (setq gdbmi-bnf-offset (1+ gdbmi-bnf-offset))))
2165 2249
2166 ;; Update the parsing state before invoking the handler in class-command 2250 ;; Update the parsing state before invoking the handler in class-command
2167 ;; to make sure it's not left in an invalid state if the handler was 2251 ;; to make sure it's not left in an invalid state if the handler was
@@ -2253,9 +2337,9 @@ Unset `gdb-thread-number' if current thread exited and update threads list."
2253 (if (string= gdb-thread-number thread-id) 2337 (if (string= gdb-thread-number thread-id)
2254 (gdb-setq-thread-number nil)) 2338 (gdb-setq-thread-number nil))
2255 ;; When we continue current thread and it quickly exits, 2339 ;; When we continue current thread and it quickly exits,
2256 ;; gdb-pending-triggers left after gdb-running disallow us to 2340 ;; the pending triggers in gdb-handler-list left after gdb-running
2257 ;; properly call -thread-info without --thread option. Thus we 2341 ;; disallow us to properly call -thread-info without --thread option.
2258 ;; need to use gdb-wait-for-pending. 2342 ;; Thus we need to use gdb-wait-for-pending.
2259 (gdb-wait-for-pending 2343 (gdb-wait-for-pending
2260 (gdb-emit-signal gdb-buf-publisher 'update-threads)))) 2344 (gdb-emit-signal gdb-buf-publisher 'update-threads))))
2261 2345
@@ -2270,9 +2354,10 @@ Sets `gdb-thread-number' to new id."
2270 ;; by `=thread-selected` notification. `^done` causes `gdb-update` 2354 ;; by `=thread-selected` notification. `^done` causes `gdb-update`
2271 ;; as usually. Things happen to fast and second call (from 2355 ;; as usually. Things happen to fast and second call (from
2272 ;; gdb-thread-selected handler) gets cut off by our beloved 2356 ;; gdb-thread-selected handler) gets cut off by our beloved
2273 ;; gdb-pending-triggers. 2357 ;; pending triggers.
2274 ;; Solution is `gdb-wait-for-pending` macro: it guarantees that its 2358 ;; Solution is `gdb-wait-for-pending' macro: it guarantees that its
2275 ;; body will get executed when `gdb-pending-triggers` is empty. 2359 ;; body will get executed when `gdb-handler-list' if free of
2360 ;; pending triggers.
2276 (gdb-wait-for-pending 2361 (gdb-wait-for-pending
2277 (gdb-update)))) 2362 (gdb-update))))
2278 2363
@@ -2291,8 +2376,7 @@ Sets `gdb-thread-number' to new id."
2291 (propertize gdb-inferior-status 'face font-lock-type-face)) 2376 (propertize gdb-inferior-status 'face font-lock-type-face))
2292 (when (not gdb-non-stop) 2377 (when (not gdb-non-stop)
2293 (setq gud-running t)) 2378 (setq gud-running t))
2294 (setq gdb-active-process t) 2379 (setq gdb-active-process t))
2295 (gdb-emit-signal gdb-buf-publisher 'update-threads))
2296 2380
2297(defun gdb-starting (_output-field _result) 2381(defun gdb-starting (_output-field _result)
2298 ;; CLI commands don't emit ^running at the moment so use gdb-running too. 2382 ;; CLI commands don't emit ^running at the moment so use gdb-running too.
@@ -2300,11 +2384,7 @@ Sets `gdb-thread-number' to new id."
2300 (gdb-force-mode-line-update 2384 (gdb-force-mode-line-update
2301 (propertize gdb-inferior-status 'face font-lock-type-face)) 2385 (propertize gdb-inferior-status 'face font-lock-type-face))
2302 (setq gdb-active-process t) 2386 (setq gdb-active-process t)
2303 (setq gud-running t) 2387 (setq gud-running t))
2304 ;; GDB doesn't seem to respond to -thread-info before first stop or
2305 ;; thread exit (even in non-stop mode), so this is useless.
2306 ;; Behavior may change in the future.
2307 (gdb-emit-signal gdb-buf-publisher 'update-threads))
2308 2388
2309;; -break-insert -t didn't give a reason before gdb 6.9 2389;; -break-insert -t didn't give a reason before gdb 6.9
2310 2390
@@ -2436,10 +2516,7 @@ current thread and update GDB buffers."
2436 (when (and token-number is-complete) 2516 (when (and token-number is-complete)
2437 (with-current-buffer 2517 (with-current-buffer
2438 (gdb-get-buffer-create 'gdb-partial-output-buffer) 2518 (gdb-get-buffer-create 'gdb-partial-output-buffer)
2439 (funcall 2519 (gdb-handle-reply (string-to-number token-number))))
2440 (cdr (assoc (string-to-number token-number) gdb-handler-alist))))
2441 (setq gdb-handler-alist
2442 (assq-delete-all token-number gdb-handler-alist)))
2443 2520
2444 (when is-complete 2521 (when is-complete
2445 (gdb-clear-partial-output)))) 2522 (gdb-clear-partial-output))))
@@ -2657,27 +2734,23 @@ trigger argument when describing buffer types with
2657 (when 2734 (when
2658 (or (not ,signal-list) 2735 (or (not ,signal-list)
2659 (memq signal ,signal-list)) 2736 (memq signal ,signal-list))
2660 (when (not (gdb-pending-p 2737 (gdb-input ,gdb-command
2661 (cons (current-buffer) ',trigger-name))) 2738 (gdb-bind-function-to-buffer ',handler-name (current-buffer))
2662 (gdb-input ,gdb-command 2739 (cons (current-buffer) ',trigger-name)))))
2663 (gdb-bind-function-to-buffer ',handler-name (current-buffer)))
2664 (gdb-add-pending (cons (current-buffer) ',trigger-name))))))
2665 2740
2666;; Used by disassembly buffer only, the rest use 2741;; Used by disassembly buffer only, the rest use
2667;; def-gdb-trigger-and-handler 2742;; def-gdb-trigger-and-handler
2668(defmacro def-gdb-auto-update-handler (handler-name trigger-name custom-defun 2743(defmacro def-gdb-auto-update-handler (handler-name custom-defun
2669 &optional nopreserve) 2744 &optional nopreserve)
2670 "Define a handler HANDLER-NAME for TRIGGER-NAME with CUSTOM-DEFUN. 2745 "Define a handler HANDLER-NAME calling CUSTOM-DEFUN.
2671 2746
2672Handlers are normally called from the buffers they put output in. 2747Handlers are normally called from the buffers they put output in.
2673 2748
2674Delete ((current-buffer) . TRIGGER-NAME) from 2749Erase current buffer and evaluate CUSTOM-DEFUN.
2675`gdb-pending-triggers', erase current buffer and evaluate 2750Then call `gdb-update-buffer-name'.
2676CUSTOM-DEFUN. Then `gdb-update-buffer-name' is called.
2677 2751
2678If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." 2752If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN."
2679 `(defun ,handler-name () 2753 `(defun ,handler-name ()
2680 (gdb-delete-pending (cons (current-buffer) ',trigger-name))
2681 (let* ((inhibit-read-only t) 2754 (let* ((inhibit-read-only t)
2682 ,@(unless nopreserve 2755 ,@(unless nopreserve
2683 '((window (get-buffer-window (current-buffer) 0)) 2756 '((window (get-buffer-window (current-buffer) 0))
@@ -2705,7 +2778,7 @@ See `def-gdb-auto-update-handler'."
2705 ,gdb-command 2778 ,gdb-command
2706 ,handler-name ,signal-list) 2779 ,handler-name ,signal-list)
2707 (def-gdb-auto-update-handler ,handler-name 2780 (def-gdb-auto-update-handler ,handler-name
2708 ,trigger-name ,custom-defun))) 2781 ,custom-defun)))
2709 2782
2710 2783
2711 2784
@@ -3622,7 +3695,6 @@ DOC is an optional documentation string."
3622 3695
3623(def-gdb-auto-update-handler 3696(def-gdb-auto-update-handler
3624 gdb-disassembly-handler 3697 gdb-disassembly-handler
3625 gdb-invalidate-disassembly
3626 gdb-disassembly-handler-custom 3698 gdb-disassembly-handler-custom
3627 t) 3699 t)
3628 3700
@@ -4114,21 +4186,19 @@ member."
4114 4186
4115;; Needs GDB 6.4 onwards (used to fail with no stack). 4187;; Needs GDB 6.4 onwards (used to fail with no stack).
4116(defun gdb-get-changed-registers () 4188(defun gdb-get-changed-registers ()
4117 (when (and (gdb-get-buffer 'gdb-registers-buffer) 4189 (when (gdb-get-buffer 'gdb-registers-buffer)
4118 (not (gdb-pending-p 'gdb-get-changed-registers)))
4119 (gdb-input "-data-list-changed-registers" 4190 (gdb-input "-data-list-changed-registers"
4120 'gdb-changed-registers-handler) 4191 'gdb-changed-registers-handler
4121 (gdb-add-pending 'gdb-get-changed-registers))) 4192 'gdb-get-changed-registers)))
4122 4193
4123(defun gdb-changed-registers-handler () 4194(defun gdb-changed-registers-handler ()
4124 (gdb-delete-pending 'gdb-get-changed-registers)
4125 (setq gdb-changed-registers nil) 4195 (setq gdb-changed-registers nil)
4126 (dolist (register-number 4196 (dolist (register-number
4127 (bindat-get-field (gdb-json-partial-output) 'changed-registers)) 4197 (bindat-get-field (gdb-json-partial-output) 'changed-registers))
4128 (push register-number gdb-changed-registers))) 4198 (push register-number gdb-changed-registers)))
4129 4199
4130(defun gdb-register-names-handler () 4200(defun gdb-register-names-handler ()
4131 ;; Don't use gdb-pending-triggers because this handler is called 4201 ;; Don't use pending triggers because this handler is called
4132 ;; only once (in gdb-init-1) 4202 ;; only once (in gdb-init-1)
4133 (setq gdb-register-names nil) 4203 (setq gdb-register-names nil)
4134 (dolist (register-name 4204 (dolist (register-name
@@ -4152,16 +4222,13 @@ is set in them."
4152(defun gdb-get-main-selected-frame () 4222(defun gdb-get-main-selected-frame ()
4153 "Trigger for `gdb-frame-handler' which uses main current thread. 4223 "Trigger for `gdb-frame-handler' which uses main current thread.
4154Called from `gdb-update'." 4224Called from `gdb-update'."
4155 (if (not (gdb-pending-p 'gdb-get-main-selected-frame)) 4225 (gdb-input (gdb-current-context-command "-stack-info-frame")
4156 (progn 4226 'gdb-frame-handler
4157 (gdb-input (gdb-current-context-command "-stack-info-frame") 4227 'gdb-get-main-selected-frame))
4158 'gdb-frame-handler)
4159 (gdb-add-pending 'gdb-get-main-selected-frame))))
4160 4228
4161(defun gdb-frame-handler () 4229(defun gdb-frame-handler ()
4162 "Set `gdb-selected-frame' and `gdb-selected-file' to show 4230 "Set `gdb-selected-frame' and `gdb-selected-file' to show
4163overlay arrow in source buffer." 4231overlay arrow in source buffer."
4164 (gdb-delete-pending 'gdb-get-main-selected-frame)
4165 (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame))) 4232 (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame)))
4166 (when frame 4233 (when frame
4167 (setq gdb-selected-frame (bindat-get-field frame 'func)) 4234 (setq gdb-selected-frame (bindat-get-field frame 'func))
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 1e152c6d751..46af51e1f97 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -410,7 +410,9 @@ Notice that using \\[next-error] or \\[compile-goto-error] modifies
410 (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t) 410 (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
411 (1 grep-error-face) 411 (1 grep-error-face)
412 (2 grep-error-face nil t)) 412 (2 grep-error-face nil t))
413 ("^.+?-[0-9]+-.*\n" (0 grep-context-face))) 413 ;; "filename-linenumber-" format is used for context lines in GNU grep,
414 ;; "filename=linenumber=" for lines with function names in "git grep -p".
415 ("^.+?[-=][0-9]+[-=].*\n" (0 grep-context-face)))
414 "Additional things to highlight in grep output. 416 "Additional things to highlight in grep output.
415This gets tacked on the end of the generated expressions.") 417This gets tacked on the end of the generated expressions.")
416 418
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index d339495d76a..c549d9eedef 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -46,11 +46,8 @@
46(defvar gdb-show-changed-values) 46(defvar gdb-show-changed-values)
47(defvar gdb-source-window) 47(defvar gdb-source-window)
48(defvar gdb-var-list) 48(defvar gdb-var-list)
49(defvar gdb-speedbar-auto-raise)
50(defvar gud-tooltip-mode)
51(defvar hl-line-mode) 49(defvar hl-line-mode)
52(defvar hl-line-sticky-flag) 50(defvar hl-line-sticky-flag)
53(defvar tool-bar-map)
54 51
55 52
56;; ====================================================================== 53;; ======================================================================
@@ -416,7 +413,7 @@ we're in the GUD buffer)."
416 413
417;; ====================================================================== 414;; ======================================================================
418;; speedbar support functions and variables. 415;; speedbar support functions and variables.
419(eval-when-compile (require 'speedbar)) ;For speedbar-with-attached-buffer. 416(eval-when-compile (require 'dframe)) ; for dframe-with-attached-buffer
420 417
421(defvar gud-last-speedbar-stackframe nil 418(defvar gud-last-speedbar-stackframe nil
422 "Description of the currently displayed GUD stack. 419 "Description of the currently displayed GUD stack.
@@ -425,19 +422,24 @@ The value t means that there is no stack, and we are in display-file mode.")
425(defvar gud-speedbar-key-map nil 422(defvar gud-speedbar-key-map nil
426 "Keymap used when in the buffers display mode.") 423 "Keymap used when in the buffers display mode.")
427 424
425;; At runtime, will be pulled in as a require of speedbar.
426(declare-function dframe-message "dframe" (fmt &rest args))
427
428(defun gud-speedbar-item-info () 428(defun gud-speedbar-item-info ()
429 "Display the data type of the watch expression element." 429 "Display the data type of the watch expression element."
430 (let ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list))) 430 (let ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list)))
431 (if (nth 7 var) 431 (if (nth 7 var)
432 (speedbar-message "%s: %s" (nth 7 var) (nth 3 var)) 432 (dframe-message "%s: %s" (nth 7 var) (nth 3 var))
433 (speedbar-message "%s" (nth 3 var))))) 433 (dframe-message "%s" (nth 3 var)))))
434
435(declare-function speedbar-make-specialized-keymap "speedbar" ())
436(declare-function speedbar-add-expansion-list "speedbar" (new-list))
437(defvar speedbar-mode-functions-list)
434 438
435(defun gud-install-speedbar-variables () 439(defun gud-install-speedbar-variables ()
436 "Install those variables used by speedbar to enhance gud/gdb." 440 "Install those variables used by speedbar to enhance gud/gdb."
437 (if gud-speedbar-key-map 441 (unless gud-speedbar-key-map
438 nil
439 (setq gud-speedbar-key-map (speedbar-make-specialized-keymap)) 442 (setq gud-speedbar-key-map (speedbar-make-specialized-keymap))
440
441 (define-key gud-speedbar-key-map "j" 'speedbar-edit-line) 443 (define-key gud-speedbar-key-map "j" 'speedbar-edit-line)
442 (define-key gud-speedbar-key-map "e" 'speedbar-edit-line) 444 (define-key gud-speedbar-key-map "e" 'speedbar-edit-line)
443 (define-key gud-speedbar-key-map "\C-m" 'speedbar-edit-line) 445 (define-key gud-speedbar-key-map "\C-m" 'speedbar-edit-line)
@@ -486,6 +488,13 @@ The value t means that there is no stack, and we are in display-file mode.")
486DIRECTORY and ZERO are not used, but are required by the caller." 488DIRECTORY and ZERO are not used, but are required by the caller."
487 (gud-speedbar-buttons gud-comint-buffer)) 489 (gud-speedbar-buttons gud-comint-buffer))
488 490
491(declare-function speedbar-make-tag-line "speedbar"
492 (type char func data tag tfunc tdata tface depth))
493(declare-function speedbar-remove-localized-speedbar-support "speedbar"
494 (buffer))
495(declare-function speedbar-insert-button "speedbar"
496 (text face mouse function &optional token prevline))
497
489(defun gud-speedbar-buttons (buffer) 498(defun gud-speedbar-buttons (buffer)
490 "Create a speedbar display based on the current state of GUD. 499 "Create a speedbar display based on the current state of GUD.
491If the GUD BUFFER is not running a supported debugger, then turn 500If the GUD BUFFER is not running a supported debugger, then turn
@@ -707,6 +716,16 @@ The option \"--fullname\" must be included in this value."
707(defvar gud-filter-pending-text nil 716(defvar gud-filter-pending-text nil
708 "Non-nil means this is text that has been saved for later in `gud-filter'.") 717 "Non-nil means this is text that has been saved for later in `gud-filter'.")
709 718
719;; One of the nice features of GDB is its impressive support for
720;; context-sensitive command completion. We preserve that feature
721;; in the GUD buffer by using a GDB command designed just for Emacs.
722
723(defvar gud-gdb-completion-function nil
724 "Completion function for GDB commands.
725It receives two arguments: COMMAND, the prefix for which we seek
726completion; and CONTEXT, the text before COMMAND on the line.
727It should return a list of completion strings.")
728
710;; If in gdb mode, gdb-mi is loaded. 729;; If in gdb mode, gdb-mi is loaded.
711(declare-function gdb-restore-windows "gdb-mi" ()) 730(declare-function gdb-restore-windows "gdb-mi" ())
712 731
@@ -767,16 +786,6 @@ directory and source-file directory for your debugger."
767 (setq gud-filter-pending-text nil) 786 (setq gud-filter-pending-text nil)
768 (run-hooks 'gud-gdb-mode-hook)) 787 (run-hooks 'gud-gdb-mode-hook))
769 788
770;; One of the nice features of GDB is its impressive support for
771;; context-sensitive command completion. We preserve that feature
772;; in the GUD buffer by using a GDB command designed just for Emacs.
773
774(defvar gud-gdb-completion-function nil
775 "Completion function for GDB commands.
776It receives two arguments: COMMAND, the prefix for which we seek
777completion; and CONTEXT, the text before COMMAND on the line.
778It should return a list of completion strings.")
779
780;; The completion process filter indicates when it is finished. 789;; The completion process filter indicates when it is finished.
781(defvar gud-gdb-fetch-lines-in-progress) 790(defvar gud-gdb-fetch-lines-in-progress)
782 791
@@ -884,9 +893,14 @@ It is passed through `gud-gdb-marker-filter' before we look at it."
884 893
885;; gdb speedbar functions 894;; gdb speedbar functions
886 895
896;; Part of the macro expansion of dframe-with-attached-buffer.
897;; At runtime, will be pulled in as a require of speedbar.
898(declare-function dframe-select-attached-frame "dframe" (&optional frame))
899(declare-function dframe-maybee-jump-to-attached-frame "dframe" ())
900
887(defun gud-gdb-goto-stackframe (_text token _indent) 901(defun gud-gdb-goto-stackframe (_text token _indent)
888 "Goto the stackframe described by TEXT, TOKEN, and INDENT." 902 "Goto the stackframe described by TEXT, TOKEN, and INDENT."
889 (speedbar-with-attached-buffer 903 (dframe-with-attached-buffer
890 (gud-basic-call (concat "server frame " (nth 1 token))) 904 (gud-basic-call (concat "server frame " (nth 1 token)))
891 (sit-for 1))) 905 (sit-for 1)))
892 906
@@ -1487,14 +1501,38 @@ into one that invokes an Emacs-enabled debugging session.
1487 (let ((output "")) 1501 (let ((output ""))
1488 1502
1489 ;; Process all the complete markers in this chunk. 1503 ;; Process all the complete markers in this chunk.
1490 (while (string-match "\032\032\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\):.*\n" 1504 ;;
1491 gud-marker-acc) 1505 ;; Here I match the string coming out of perldb.
1506 ;; The strings can look like any of
1507 ;;
1508 ;; "\032\032/tmp/tst.pl:6:0\n"
1509 ;; "\032\032(eval 5)[/tmp/tst.pl:6]:3:0\n"
1510 ;; "\032\032(eval 17)[Basic/Core/Core.pm.PL (i.e. PDL::Core.pm):2931]:1:0\n"
1511 ;;
1512 ;; From those I want the filename and the line number. First I look for
1513 ;; the eval case. If that doesn't match, I look for the "normal" case.
1514 (while
1515 (string-match
1516 (eval-when-compile
1517 (let ((file-re "\\(?:[a-zA-Z]:\\)?[^:\n]*"))
1518 (concat "\032\032\\(?:"
1519 (concat
1520 "(eval [0-9]+)\\["
1521 "\\(" file-re "\\)" ; Filename.
1522 "\\(?: (i\\.e\\. [^)]*)\\)?"
1523 ":\\([0-9]*\\)\\]") ; Line number.
1524 "\\|"
1525 (concat
1526 "\\(?1:" file-re "\\)" ; Filename.
1527 ":\\(?2:[0-9]*\\)") ; Line number.
1528 "\\):.*\n")))
1529 gud-marker-acc)
1492 (setq 1530 (setq
1493 1531
1494 ;; Extract the frame position from the marker. 1532 ;; Extract the frame position from the marker.
1495 gud-last-frame 1533 gud-last-frame
1496 (cons (match-string 1 gud-marker-acc) 1534 (cons (match-string 1 gud-marker-acc)
1497 (string-to-number (match-string 3 gud-marker-acc))) 1535 (string-to-number (match-string 2 gud-marker-acc)))
1498 1536
1499 ;; Append any text before the marker to the output we're going 1537 ;; Append any text before the marker to the output we're going
1500 ;; to return - we don't include the marker in this text. 1538 ;; to return - we don't include the marker in this text.
@@ -2612,6 +2650,8 @@ It is saved for when this flag is not set.")
2612(add-to-list 'overlay-arrow-variable-list 'gud-overlay-arrow-position) 2650(add-to-list 'overlay-arrow-variable-list 'gud-overlay-arrow-position)
2613 2651
2614(declare-function gdb-reset "gdb-mi" ()) 2652(declare-function gdb-reset "gdb-mi" ())
2653(declare-function speedbar-change-initial-expansion-list "speedbar" (new))
2654(defvar speedbar-previously-used-expansion-list-name)
2615 2655
2616(defun gud-sentinel (proc msg) 2656(defun gud-sentinel (proc msg)
2617 (cond ((null (buffer-name (process-buffer proc))) 2657 (cond ((null (buffer-name (process-buffer proc)))
@@ -2619,7 +2659,7 @@ It is saved for when this flag is not set.")
2619 ;; Stop displaying an arrow in a source file. 2659 ;; Stop displaying an arrow in a source file.
2620 (setq gud-overlay-arrow-position nil) 2660 (setq gud-overlay-arrow-position nil)
2621 (set-process-buffer proc nil) 2661 (set-process-buffer proc nil)
2622 (if (and (boundp 'speedbar-frame) 2662 (if (and (boundp 'speedbar-initial-expansion-list-name)
2623 (string-equal speedbar-initial-expansion-list-name "GUD")) 2663 (string-equal speedbar-initial-expansion-list-name "GUD"))
2624 (speedbar-change-initial-expansion-list 2664 (speedbar-change-initial-expansion-list
2625 speedbar-previously-used-expansion-list-name)) 2665 speedbar-previously-used-expansion-list-name))
@@ -3312,6 +3352,9 @@ only tooltips in the buffer containing the overlay arrow."
3312 :group 'gud 3352 :group 'gud
3313 :group 'tooltip) 3353 :group 'tooltip)
3314 3354
3355(make-obsolete-variable 'gud-tooltip-echo-area
3356 "disable Tooltip mode instead" "24.4" 'set)
3357
3315;;; Reacting on mouse movements 3358;;; Reacting on mouse movements
3316 3359
3317(defun gud-tooltip-change-major-mode () 3360(defun gud-tooltip-change-major-mode ()
@@ -3363,9 +3406,6 @@ ACTIVATEP non-nil means activate mouse motion events."
3363 3406
3364;;; Tips for `gud' 3407;;; Tips for `gud'
3365 3408
3366(defvar gud-tooltip-original-filter nil
3367 "Process filter to restore after GUD output has been received.")
3368
3369(defvar gud-tooltip-dereference nil 3409(defvar gud-tooltip-dereference nil
3370 "Non-nil means print expressions with a `*' in front of them. 3410 "Non-nil means print expressions with a `*' in front of them.
3371For C this would dereference a pointer expression.") 3411For C this would dereference a pointer expression.")
@@ -3396,12 +3436,13 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference."
3396; the tooltip incompletely and spill over into the gud buffer. 3436; the tooltip incompletely and spill over into the gud buffer.
3397; Switching the process-filter creates timing problems and 3437; Switching the process-filter creates timing problems and
3398; it may be difficult to do better. Using GDB/MI as in 3438; it may be difficult to do better. Using GDB/MI as in
3399; gdb-mi.el gets round this problem. 3439; gdb-mi.el gets around this problem.
3400(defun gud-tooltip-process-output (process output) 3440(defun gud-tooltip-process-output (process output)
3401 "Process debugger output and show it in a tooltip window." 3441 "Process debugger output and show it in a tooltip window."
3402 (set-process-filter process gud-tooltip-original-filter) 3442 (remove-function (process-filter process) #'gud-tooltip-process-output)
3403 (tooltip-show (tooltip-strip-prompt process output) 3443 (tooltip-show (tooltip-strip-prompt process output)
3404 (or gud-tooltip-echo-area tooltip-use-echo-area))) 3444 (or gud-tooltip-echo-area tooltip-use-echo-area
3445 (not tooltip-mode))))
3405 3446
3406(defun gud-tooltip-print-command (expr) 3447(defun gud-tooltip-print-command (expr)
3407 "Return a suitable command to print the expression EXPR." 3448 "Return a suitable command to print the expression EXPR."
@@ -3411,7 +3452,7 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference."
3411 ((or `xdb `pdb) (concat "p " expr)) 3452 ((or `xdb `pdb) (concat "p " expr))
3412 (`sdb (concat expr "/")))) 3453 (`sdb (concat expr "/"))))
3413 3454
3414(declare-function gdb-input "gdb-mi" (command handler)) 3455(declare-function gdb-input "gdb-mi" (command handler &optional trigger))
3415(declare-function tooltip-expr-to-print "tooltip" (event)) 3456(declare-function tooltip-expr-to-print "tooltip" (event))
3416(declare-function tooltip-event-buffer "tooltip" (event)) 3457(declare-function tooltip-event-buffer "tooltip" (event))
3417 3458
@@ -3444,7 +3485,8 @@ This function must return nil if it doesn't handle EVENT."
3444 (unless (null define-elt) 3485 (unless (null define-elt)
3445 (tooltip-show 3486 (tooltip-show
3446 (cdr define-elt) 3487 (cdr define-elt)
3447 (or gud-tooltip-echo-area tooltip-use-echo-area)) 3488 (or gud-tooltip-echo-area tooltip-use-echo-area
3489 (not tooltip-mode)))
3448 expr)))) 3490 expr))))
3449 (when gud-tooltip-dereference 3491 (when gud-tooltip-dereference
3450 (setq expr (concat "*" expr))) 3492 (setq expr (concat "*" expr)))
@@ -3466,8 +3508,8 @@ so they have been disabled."))
3466 (gdb-input 3508 (gdb-input
3467 (concat cmd "\n") 3509 (concat cmd "\n")
3468 `(lambda () (gdb-tooltip-print ,expr)))) 3510 `(lambda () (gdb-tooltip-print ,expr))))
3469 (setq gud-tooltip-original-filter (process-filter process)) 3511 (add-function :override (process-filter process)
3470 (set-process-filter process 'gud-tooltip-process-output) 3512 #'gud-tooltip-process-output)
3471 (gud-basic-call cmd)) 3513 (gud-basic-call cmd))
3472 expr)))))))) 3514 expr))))))))
3473 3515
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
index 749b0b65576..7060cae5080 100644
--- a/lisp/progmodes/idlw-help.el
+++ b/lisp/progmodes/idlw-help.el
@@ -90,16 +90,15 @@ Defaults to `browse-url-browser-function', which see."
90(defcustom idlwave-help-browser-generic-program browse-url-generic-program 90(defcustom idlwave-help-browser-generic-program browse-url-generic-program
91 "Program to run if using `browse-url-generic-program'." 91 "Program to run if using `browse-url-generic-program'."
92 :group 'idlwave-online-help 92 :group 'idlwave-online-help
93 :type 'string) 93 :type '(choice (const nil) string))
94
95(defvar browse-url-generic-args)
96 94
95;; AFAICS, never used since it was introduced in 2004.
97(defcustom idlwave-help-browser-generic-args 96(defcustom idlwave-help-browser-generic-args
98 (if (boundp 'browse-url-generic-args) 97 (if (boundp 'browse-url-generic-args)
99 browse-url-generic-args "") 98 browse-url-generic-args "")
100 "Program args to use if using `browse-url-generic-program'." 99 "Program args to use if using `browse-url-generic-program'."
101 :group 'idlwave-online-help 100 :group 'idlwave-online-help
102 :type 'string) 101 :type '(repeat string))
103 102
104(defcustom idlwave-help-browser-is-local nil 103(defcustom idlwave-help-browser-is-local nil
105 "Whether the browser will display locally in an Emacs window. 104 "Whether the browser will display locally in an Emacs window.
@@ -1179,7 +1178,7 @@ Useful when source code is displayed as help. See the option
1179 (if (featurep 'font-lock) 1178 (if (featurep 'font-lock)
1180 (let ((major-mode 'idlwave-mode) 1179 (let ((major-mode 'idlwave-mode)
1181 (font-lock-verbose 1180 (font-lock-verbose
1182 (if (interactive-p) font-lock-verbose nil)) 1181 (if (called-interactively-p 'interactive) font-lock-verbose nil))
1183 (syntax-table (syntax-table))) 1182 (syntax-table (syntax-table)))
1184 (unwind-protect 1183 (unwind-protect
1185 (progn 1184 (progn
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index aeaf1acb2ac..ba9a632b949 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -5078,11 +5078,14 @@ Cache to disk for quick recovery."
5078 ;; The sequence here is important because earlier definitions shadow 5078 ;; The sequence here is important because earlier definitions shadow
5079 ;; later ones. We assume that if things in the buffers are newer 5079 ;; later ones. We assume that if things in the buffers are newer
5080 ;; then in the shell of the system, they are meant to be different. 5080 ;; then in the shell of the system, they are meant to be different.
5081 (setcdr idlwave-last-system-routine-info-cons-cell 5081 (let ((temp (append idlwave-buffer-routines
5082 (append idlwave-buffer-routines 5082 idlwave-compiled-routines
5083 idlwave-compiled-routines 5083 idlwave-library-catalog-routines
5084 idlwave-library-catalog-routines 5084 idlwave-user-catalog-routines)))
5085 idlwave-user-catalog-routines)) 5085 ;; Not actually used for anything?
5086 (if idlwave-last-system-routine-info-cons-cell
5087 (setcdr idlwave-last-system-routine-info-cons-cell temp)
5088 (setq idlwave-last-system-routine-info-cons-cell (cons temp nil))))
5086 (setq idlwave-class-alist nil) 5089 (setq idlwave-class-alist nil)
5087 5090
5088 ;; Give a message with information about the number of routines we have. 5091 ;; Give a message with information about the number of routines we have.
@@ -5481,30 +5484,21 @@ directories and save the routine info.
5481 (message "Creating user catalog file...") 5484 (message "Creating user catalog file...")
5482 (kill-buffer "*idlwave-scan.pro*") 5485 (kill-buffer "*idlwave-scan.pro*")
5483 (kill-buffer (get-buffer-create "*IDLWAVE Widget*")) 5486 (kill-buffer (get-buffer-create "*IDLWAVE Widget*"))
5484 (let ((font-lock-maximum-size 0) 5487 (with-temp-buffer
5485 (auto-mode-alist nil)) 5488 (insert ";; IDLWAVE user catalog file\n")
5486 (find-file idlwave-user-catalog-file)) 5489 (insert (format ";; Created %s\n\n" (current-time-string)))
5487 (if (and (boundp 'font-lock-mode) 5490
5488 font-lock-mode) 5491 ;; Define the routine info list
5489 (font-lock-mode 0)) 5492 (insert "\n(setq idlwave-user-catalog-routines\n '(")
5490 (erase-buffer) 5493 (let ((standard-output (current-buffer)))
5491 (insert ";; IDLWAVE user catalog file\n") 5494 (mapc (lambda (x)
5492 (insert (format ";; Created %s\n\n" (current-time-string))) 5495 (insert "\n ")
5493 5496 (prin1 x)
5494 ;; Define the routine info list 5497 (goto-char (point-max)))
5495 (insert "\n(setq idlwave-user-catalog-routines\n '(") 5498 idlwave-user-catalog-routines))
5496 (let ((standard-output (current-buffer))) 5499 (insert (format "))\n\n;;; %s ends here\n"
5497 (mapc (lambda (x) 5500 (file-name-nondirectory idlwave-user-catalog-file)))
5498 (insert "\n ") 5501 (write-region nil nil idlwave-user-catalog-file)))
5499 (prin1 x)
5500 (goto-char (point-max)))
5501 idlwave-user-catalog-routines))
5502 (insert (format "))\n\n;;; %s ends here\n"
5503 (file-name-nondirectory idlwave-user-catalog-file)))
5504 (goto-char (point-min))
5505 ;; Save the buffer
5506 (save-buffer 0)
5507 (kill-buffer (current-buffer)))
5508 (message "Creating user catalog file...done") 5502 (message "Creating user catalog file...done")
5509 (message "Info for %d routines saved in %s" 5503 (message "Info for %d routines saved in %s"
5510 (length idlwave-user-catalog-routines) 5504 (length idlwave-user-catalog-routines)
@@ -5522,31 +5516,23 @@ directories and save the routine info.
5522(defun idlwave-write-paths () 5516(defun idlwave-write-paths ()
5523 (interactive) 5517 (interactive)
5524 (when (and idlwave-path-alist idlwave-system-directory) 5518 (when (and idlwave-path-alist idlwave-system-directory)
5525 (let ((font-lock-maximum-size 0) 5519 (with-temp-buffer
5526 (auto-mode-alist nil)) 5520 (insert ";; IDLWAVE paths\n")
5527 (find-file idlwave-path-file)) 5521 (insert (format ";; Created %s\n\n" (current-time-string)))
5528 (if (and (boundp 'font-lock-mode)
5529 font-lock-mode)
5530 (font-lock-mode 0))
5531 (erase-buffer)
5532 (insert ";; IDLWAVE paths\n")
5533 (insert (format ";; Created %s\n\n" (current-time-string)))
5534 ;; Define the variable which knows the value of "!DIR" 5522 ;; Define the variable which knows the value of "!DIR"
5535 (insert (format "\n(setq idlwave-system-directory \"%s\")\n" 5523 (insert (format "\n(setq idlwave-system-directory \"%s\")\n"
5536 idlwave-system-directory)) 5524 idlwave-system-directory))
5537 5525
5538 ;; Define the variable which contains a list of all scanned directories 5526 ;; Define the variable which contains a list of all scanned directories
5539 (insert "\n(setq idlwave-path-alist\n '(") 5527 (insert "\n(setq idlwave-path-alist\n '(")
5540 (let ((standard-output (current-buffer))) 5528 (let ((standard-output (current-buffer)))
5541 (mapc (lambda (x) 5529 (mapc (lambda (x)
5542 (insert "\n ") 5530 (insert "\n ")
5543 (prin1 x) 5531 (prin1 x)
5544 (goto-char (point-max))) 5532 (goto-char (point-max)))
5545 idlwave-path-alist)) 5533 idlwave-path-alist))
5546 (insert "))\n") 5534 (insert "))\n")
5547 (save-buffer 0) 5535 (write-region nil nil idlwave-path-file))))
5548 (kill-buffer (current-buffer))))
5549
5550 5536
5551(defun idlwave-expand-path (path &optional default-dir) 5537(defun idlwave-expand-path (path &optional default-dir)
5552 ;; Expand parts of path starting with '+' recursively into directory list. 5538 ;; Expand parts of path starting with '+' recursively into directory list.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 2ea78fc321c..28ee859f9db 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -55,7 +55,6 @@
55 55
56(eval-when-compile 56(eval-when-compile
57 (require 'cl-lib) 57 (require 'cl-lib)
58 (require 'comint)
59 (require 'ido)) 58 (require 'ido))
60 59
61(defvar inferior-moz-buffer) 60(defvar inferior-moz-buffer)
@@ -2217,6 +2216,9 @@ marker."
2217 2216
2218(defvar find-tag-marker-ring) ; etags 2217(defvar find-tag-marker-ring) ; etags
2219 2218
2219;; etags loads ring.
2220(declare-function ring-insert "ring" (ring item))
2221
2220(defun js-find-symbol (&optional arg) 2222(defun js-find-symbol (&optional arg)
2221 "Read a JavaScript symbol and jump to it. 2223 "Read a JavaScript symbol and jump to it.
2222With a prefix argument, restrict symbols to those from the 2224With a prefix argument, restrict symbols to those from the
@@ -2639,6 +2641,11 @@ with `js--js-encode-value'."
2639 ;; order to catch a prompt that's only partially arrived 2641 ;; order to catch a prompt that's only partially arrived
2640 (save-excursion (forward-line 0) (point)))) 2642 (save-excursion (forward-line 0) (point))))
2641 2643
2644;; Presumably "inferior-moz-process" loads comint.
2645(declare-function comint-send-string "comint" (process string))
2646(declare-function comint-send-input "comint"
2647 (&optional no-newline artificial))
2648
2642(defun js--js-enter-repl () 2649(defun js--js-enter-repl ()
2643 (inferior-moz-process) ; called for side-effect 2650 (inferior-moz-process) ; called for side-effect
2644 (with-current-buffer inferior-moz-buffer 2651 (with-current-buffer inferior-moz-buffer
@@ -2697,6 +2704,10 @@ with `js--js-encode-value'."
2697(defsubst js--js-true (value) 2704(defsubst js--js-true (value)
2698 (not (js--js-not value))) 2705 (not (js--js-not value)))
2699 2706
2707;; The somewhat complex code layout confuses the byte-compiler into
2708;; thinking this function "might not be defined at runtime".
2709(declare-function js--optimize-arglist "js" (arglist))
2710
2700(eval-and-compile 2711(eval-and-compile
2701 (defun js--optimize-arglist (arglist) 2712 (defun js--optimize-arglist (arglist)
2702 "Convert immediate js< and js! references to deferred ones." 2713 "Convert immediate js< and js! references to deferred ones."
@@ -2824,6 +2835,8 @@ If nil, the whole Array is treated as a JS symbol.")
2824 (`error (signal 'js-js-error (list (cl-second result)))) 2835 (`error (signal 'js-js-error (list (cl-second result))))
2825 (x (error "Unmatched case in js--js-decode-retval: %S" x)))) 2836 (x (error "Unmatched case in js--js-decode-retval: %S" x))))
2826 2837
2838(defvar comint-last-input-end)
2839
2827(defun js--js-funcall (function &rest arguments) 2840(defun js--js-funcall (function &rest arguments)
2828 "Call the Mozilla function FUNCTION with arguments ARGUMENTS. 2841 "Call the Mozilla function FUNCTION with arguments ARGUMENTS.
2829If function is a string, look it up as a property on the global 2842If function is a string, look it up as a property on the global
@@ -2996,6 +3009,8 @@ left-to-right."
2996 3009
2997(defvar js-read-tab-history nil) 3010(defvar js-read-tab-history nil)
2998 3011
3012(declare-function ido-chop "ido" (items elem))
3013
2999(defun js--read-tab (prompt) 3014(defun js--read-tab (prompt)
3000 "Read a Mozilla tab with prompt PROMPT. 3015 "Read a Mozilla tab with prompt PROMPT.
3001Return a cons of (TYPE . OBJECT). TYPE is either 'window or 3016Return a cons of (TYPE . OBJECT). TYPE is either 'window or
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index 34d1525bbab..ffb425ee1e9 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -48,7 +48,7 @@
48 (modify-syntax-entry ?\) ")(" st) 48 (modify-syntax-entry ?\) ")(" st)
49 (modify-syntax-entry ?\[ "(]" st) 49 (modify-syntax-entry ?\[ "(]" st)
50 (modify-syntax-entry ?\] ")[" st) 50 (modify-syntax-entry ?\] ")[" st)
51 (modify-syntax-entry ?_ "w" st) 51 (modify-syntax-entry ?_ "_" st)
52 (modify-syntax-entry ?. "_" st) 52 (modify-syntax-entry ?. "_" st)
53 (modify-syntax-entry ?\\ "\\" st) 53 (modify-syntax-entry ?\\ "\\" st)
54 (modify-syntax-entry ?: "." st) 54 (modify-syntax-entry ?: "." st)
@@ -154,10 +154,10 @@
154 154
155(defvar ld-script-font-lock-keywords 155(defvar ld-script-font-lock-keywords
156 (append 156 (append
157 `((,(regexp-opt ld-script-keywords 'words) 157 `((,(concat "\\_<" (regexp-opt ld-script-keywords) "\\_>")
158 1 font-lock-keyword-face) 158 0 font-lock-keyword-face)
159 (,(regexp-opt ld-script-builtins 'words) 159 (,(concat "\\_<" (regexp-opt ld-script-builtins) "\\_>")
160 1 font-lock-builtin-face) 160 0 font-lock-builtin-face)
161 ;; 3.6.7 Output Section Discarding 161 ;; 3.6.7 Output Section Discarding
162 ;; 3.6.4.1 Input Section Basics 162 ;; 3.6.4.1 Input Section Basics
163 ;; 3.6.8.7 Output Section Phdr 163 ;; 3.6.8.7 Output Section Phdr
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index 0641fc776de..4ba2ae1ded9 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -45,15 +45,10 @@
45 :prefix "m4-" 45 :prefix "m4-"
46 :group 'languages) 46 :group 'languages)
47 47
48(defcustom m4-program 48(defcustom m4-program "m4"
49 (cond 49 "File name of the m4 executable.
50 ((file-exists-p "/usr/local/bin/m4") "/usr/local/bin/m4") 50If m4 is not in your PATH, set this to an absolute file name."
51 ((file-exists-p "/usr/bin/m4") "/usr/bin/m4") 51 :version "24.4"
52 ((file-exists-p "/bin/m4") "/bin/m4")
53 ((file-exists-p "/usr/ccs/bin/m4") "/usr/ccs/bin/m4")
54 ( t "m4")
55 )
56 "File name of the m4 executable."
57 :type 'file 52 :type 'file
58 :group 'm4) 53 :group 'm4)
59 54
@@ -85,19 +80,24 @@
85 :group 'm4) 80 :group 'm4)
86 81
87;;this may still need some work 82;;this may still need some work
88(defvar m4-mode-syntax-table nil 83(defvar m4-mode-syntax-table
84 (let ((table (make-syntax-table)))
85 (modify-syntax-entry ?` "('" table)
86 (modify-syntax-entry ?' ")`" table)
87 (modify-syntax-entry ?# "<\n" table)
88 (modify-syntax-entry ?\n ">#" table)
89 (modify-syntax-entry ?{ "_" table)
90 (modify-syntax-entry ?} "_" table)
91 ;; FIXME: This symbol syntax for underscore looks OK on its own, but it's
92 ;; odd that it should have the same syntax as { and } are these really
93 ;; valid in m4 symbols?
94 (modify-syntax-entry ?_ "_" table)
95 ;; FIXME: These three chars with word syntax look wrong.
96 (modify-syntax-entry ?* "w" table)
97 (modify-syntax-entry ?\" "w" table)
98 (modify-syntax-entry ?\" "w" table)
99 table)
89 "Syntax table used while in `m4-mode'.") 100 "Syntax table used while in `m4-mode'.")
90(setq m4-mode-syntax-table (make-syntax-table))
91(modify-syntax-entry ?` "('" m4-mode-syntax-table)
92(modify-syntax-entry ?' ")`" m4-mode-syntax-table)
93(modify-syntax-entry ?# "<\n" m4-mode-syntax-table)
94(modify-syntax-entry ?\n ">#" m4-mode-syntax-table)
95(modify-syntax-entry ?{ "_" m4-mode-syntax-table)
96(modify-syntax-entry ?} "_" m4-mode-syntax-table)
97(modify-syntax-entry ?* "w" m4-mode-syntax-table)
98(modify-syntax-entry ?_ "w" m4-mode-syntax-table)
99(modify-syntax-entry ?\" "w" m4-mode-syntax-table)
100(modify-syntax-entry ?\" "w" m4-mode-syntax-table)
101 101
102(defvar m4-mode-map 102(defvar m4-mode-map
103 (let ((map (make-sparse-keymap)) 103 (let ((map (make-sparse-keymap))
@@ -117,12 +117,6 @@
117 :help "Send contents of the current region to m4")) 117 :help "Send contents of the current region to m4"))
118 map)) 118 map))
119 119
120(defvar m4-mode-abbrev-table nil
121 "Abbrev table used while in `m4-mode'.")
122
123(unless m4-mode-abbrev-table
124 (define-abbrev-table 'm4-mode-abbrev-table ()))
125
126(defun m4-m4-buffer () 120(defun m4-m4-buffer ()
127 "Send contents of the current buffer to m4." 121 "Send contents of the current buffer to m4."
128 (interactive) 122 (interactive)
@@ -151,7 +145,6 @@
151;;;###autoload 145;;;###autoload
152(define-derived-mode m4-mode prog-mode "m4" 146(define-derived-mode m4-mode prog-mode "m4"
153 "A major mode to edit m4 macro files." 147 "A major mode to edit m4 macro files."
154 :abbrev-table m4-mode-abbrev-table
155 (setq-local comment-start "#") 148 (setq-local comment-start "#")
156 (setq-local parse-sexp-ignore-comments t) 149 (setq-local parse-sexp-ignore-comments t)
157 (setq-local add-log-current-defun-function #'m4-current-defun-name) 150 (setq-local add-log-current-defun-function #'m4-current-defun-name)
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 20673866bc4..3069c790e1c 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -241,7 +241,7 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
241 "List of special targets. 241 "List of special targets.
242You will be offered to complete on one of those in the minibuffer whenever 242You will be offered to complete on one of those in the minibuffer whenever
243you enter a \".\" at the beginning of a line in `makefile-mode'." 243you enter a \".\" at the beginning of a line in `makefile-mode'."
244 :type '(repeat (list string)) 244 :type '(repeat string)
245 :group 'makefile) 245 :group 'makefile)
246(put 'makefile-special-targets-list 'risky-local-variable t) 246(put 'makefile-special-targets-list 'risky-local-variable t)
247 247
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index b090435ac9b..6a150667f19 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -794,6 +794,7 @@ The environment marked is the one that contains point or follows point."
794 794
795(defvar meta-common-mode-syntax-table 795(defvar meta-common-mode-syntax-table
796 (let ((st (make-syntax-table))) 796 (let ((st (make-syntax-table)))
797 ;; FIXME: This goes against the convention!
797 ;; underscores are word constituents 798 ;; underscores are word constituents
798 (modify-syntax-entry ?_ "w" st) 799 (modify-syntax-entry ?_ "w" st)
799 ;; miscellaneous non-word symbols 800 ;; miscellaneous non-word symbols
diff --git a/lisp/progmodes/octave-inf.el b/lisp/progmodes/octave-inf.el
deleted file mode 100644
index de7ca32befe..00000000000
--- a/lisp/progmodes/octave-inf.el
+++ /dev/null
@@ -1,386 +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 (filter (process-filter proc))
352 string)
353 (set-process-filter proc '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 (set-process-filter proc filter))))
364
365(defun inferior-octave-directory-tracker (string)
366 "Tracks `cd' commands issued to the inferior Octave process.
367Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused."
368 (cond
369 ((string-match "^[ \t]*cd[ \t;]*$" string)
370 (cd "~"))
371 ((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
372 (cd (substring string (match-beginning 1) (match-end 1))))))
373
374(defun inferior-octave-resync-dirs ()
375 "Resync the buffer's idea of the current directory.
376This command queries the inferior Octave process about its current
377directory and makes this the current buffer's default directory."
378 (interactive)
379 (inferior-octave-send-list-and-digest '("disp (pwd ())\n"))
380 (cd (car inferior-octave-output-list)))
381
382;;; provide ourself
383
384(provide 'octave-inf)
385
386;;; octave-inf.el ends here
diff --git a/lisp/progmodes/octave-mod.el b/lisp/progmodes/octave-mod.el
deleted file mode 100644
index 806afe5a537..00000000000
--- a/lisp/progmodes/octave-mod.el
+++ /dev/null
@@ -1,1152 +0,0 @@
1;;; octave-mod.el --- editing Octave source files under Emacs
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@octave.org>
7;; Maintainer: FSF
8;; Keywords: languages
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;; This package provides Emacs support for Octave.
28;; It defines Octave mode, a major mode for editing
29;; Octave code.
30
31;; The file octave-inf.el contains code for interacting with an inferior
32;; Octave process using comint.
33
34;; See the documentation of `octave-mode' and
35;; `run-octave' for further information on usage and customization.
36
37;;; Code:
38(require 'custom)
39
40(defgroup octave nil
41 "Major mode for editing Octave source files."
42 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
43 :group 'languages)
44
45(defvar inferior-octave-output-list nil)
46(defvar inferior-octave-output-string nil)
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
55(define-abbrev-table 'octave-abbrev-table
56 (mapcar (lambda (e) (append e '(nil 0 t)))
57 '(("`a" "all_va_args")
58 ("`b" "break")
59 ("`cs" "case")
60 ("`ca" "catch")
61 ("`c" "continue")
62 ("`el" "else")
63 ("`eli" "elseif")
64 ("`et" "end_try_catch")
65 ("`eu" "end_unwind_protect")
66 ("`ef" "endfor")
67 ("`efu" "endfunction")
68 ("`ei" "endif")
69 ("`es" "endswitch")
70 ("`ew" "endwhile")
71 ("`f" "for")
72 ("`fu" "function")
73 ("`gl" "global")
74 ("`gp" "gplot")
75 ("`gs" "gsplot")
76 ("`if" "if ()")
77 ("`o" "otherwise")
78 ("`rp" "replot")
79 ("`r" "return")
80 ("`s" "switch")
81 ("`t" "try")
82 ("`u" "until ()")
83 ("`up" "unwind_protect")
84 ("`upc" "unwind_protect_cleanup")
85 ("`w" "while ()")))
86 "Abbrev table for Octave's reserved words.
87Used in `octave-mode' and inferior-octave-mode buffers.
88All Octave abbrevs start with a grave accent (`)."
89 :regexp "\\(?:[^`]\\|^\\)\\(\\(?:\\<\\|`\\)\\w+\\)\\W*")
90
91(defvar octave-comment-char ?#
92 "Character to start an Octave comment.")
93(defvar octave-comment-start
94 (string octave-comment-char ?\s)
95 "String to insert to start a new Octave in-line comment.")
96(defvar octave-comment-start-skip "\\s<+\\s-*"
97 "Regexp to match the start of an Octave comment up to its body.")
98
99(defvar octave-begin-keywords
100 '("do" "for" "function" "if" "switch" "try" "unwind_protect" "while"))
101(defvar octave-else-keywords
102 '("case" "catch" "else" "elseif" "otherwise" "unwind_protect_cleanup"))
103(defvar octave-end-keywords
104 '("endfor" "endfunction" "endif" "endswitch" "end_try_catch"
105 "end_unwind_protect" "endwhile" "until" "end"))
106
107(defvar octave-reserved-words
108 (append octave-begin-keywords
109 octave-else-keywords
110 octave-end-keywords
111 '("break" "continue" "end" "global" "persistent" "return"))
112 "Reserved words in Octave.")
113
114(defvar octave-text-functions
115 '("casesen" "cd" "chdir" "clear" "diary" "dir" "document" "echo"
116 "edit_history" "format" "help" "history" "hold"
117 "load" "ls" "more" "run_history" "save" "type"
118 "which" "who" "whos")
119 "Text functions in Octave.")
120
121(defvar octave-variables
122 '("DEFAULT_EXEC_PATH" "DEFAULT_LOADPATH"
123 "EDITOR" "EXEC_PATH" "F_DUPFD" "F_GETFD" "F_GETFL" "F_SETFD"
124 "F_SETFL" "I" "IMAGE_PATH" "Inf" "J"
125 "NaN" "OCTAVE_VERSION" "O_APPEND" "O_CREAT" "O_EXCL"
126 "O_NONBLOCK" "O_RDONLY" "O_RDWR" "O_TRUNC" "O_WRONLY" "PAGER" "PS1"
127 "PS2" "PS4" "PWD" "SEEK_CUR" "SEEK_END" "SEEK_SET" "__F_DUPFD__"
128 "__F_GETFD__" "__F_GETFL__" "__F_SETFD__" "__F_SETFL__" "__I__"
129 "__Inf__" "__J__" "__NaN__" "__OCTAVE_VERSION__" "__O_APPEND__"
130 "__O_CREAT__" "__O_EXCL__" "__O_NONBLOCK__" "__O_RDONLY__"
131 "__O_RDWR__" "__O_TRUNC__" "__O_WRONLY__" "__PWD__" "__SEEK_CUR__"
132 "__SEEK_END__" "__SEEK_SET__" "__argv__" "__e__" "__eps__"
133 "__i__" "__inf__" "__j__" "__nan__" "__pi__"
134 "__program_invocation_name__" "__program_name__" "__realmax__"
135 "__realmin__" "__stderr__" "__stdin__" "__stdout__" "ans" "argv"
136 "beep_on_error" "completion_append_char"
137 "crash_dumps_octave_core" "default_save_format"
138 "e" "echo_executing_commands" "eps"
139 "error_text" "gnuplot_binary" "history_file"
140 "history_size" "ignore_function_time_stamp"
141 "inf" "nan" "nargin" "output_max_field_width" "output_precision"
142 "page_output_immediately" "page_screen_output" "pi"
143 "print_answer_id_name" "print_empty_dimensions"
144 "program_invocation_name" "program_name"
145 "realmax" "realmin" "return_last_computed_value" "save_precision"
146 "saving_history" "sighup_dumps_octave_core" "sigterm_dumps_octave_core"
147 "silent_functions" "split_long_rows" "stderr" "stdin" "stdout"
148 "string_fill_char" "struct_levels_to_print"
149 "suppress_verbose_help_message")
150 "Builtin variables in Octave.")
151
152(defvar octave-function-header-regexp
153 (concat "^\\s-*\\_<\\(function\\)\\_>"
154 "\\([^=;\n]*=[ \t]*\\|[ \t]*\\)\\(\\(?:\\w\\|\\s_\\)+\\)\\_>")
155 "Regexp to match an Octave function header.
156The string `function' and its name are given by the first and third
157parenthetical grouping.")
158
159(defvar octave-font-lock-keywords
160 (list
161 ;; Fontify all builtin keywords.
162 (cons (concat "\\_<\\("
163 (regexp-opt (append octave-reserved-words
164 octave-text-functions))
165 "\\)\\_>")
166 'font-lock-keyword-face)
167 ;; Fontify all builtin operators.
168 (cons "\\(&\\||\\|<=\\|>=\\|==\\|<\\|>\\|!=\\|!\\)"
169 (if (boundp 'font-lock-builtin-face)
170 'font-lock-builtin-face
171 'font-lock-preprocessor-face))
172 ;; Fontify all builtin variables.
173 (cons (concat "\\_<" (regexp-opt octave-variables) "\\_>")
174 'font-lock-variable-name-face)
175 ;; Fontify all function declarations.
176 (list octave-function-header-regexp
177 '(1 font-lock-keyword-face)
178 '(3 font-lock-function-name-face nil t)))
179 "Additional Octave expressions to highlight.")
180
181(defun octave-syntax-propertize-function (start end)
182 (goto-char start)
183 (octave-syntax-propertize-sqs end)
184 (funcall (syntax-propertize-rules
185 ;; Try to distinguish the string-quotes from the transpose-quotes.
186 ("[[({,; ]\\('\\)"
187 (1 (prog1 "\"'" (octave-syntax-propertize-sqs end)))))
188 (point) end))
189
190(defun octave-syntax-propertize-sqs (end)
191 "Propertize the content/end of single-quote strings."
192 (when (eq (nth 3 (syntax-ppss)) ?\')
193 ;; A '..' string.
194 (when (re-search-forward
195 "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)\\($\\|[^']\\)" end 'move)
196 (goto-char (match-beginning 2))
197 (when (eq (char-before (match-beginning 1)) ?\\)
198 ;; Backslash cannot escape a single quote.
199 (put-text-property (1- (match-beginning 1)) (match-beginning 1)
200 'syntax-table (string-to-syntax ".")))
201 (put-text-property (match-beginning 1) (match-end 1)
202 'syntax-table (string-to-syntax "\"'")))))
203
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
211(defvar octave-mode-map
212 (let ((map (make-sparse-keymap)))
213 (define-key map "`" 'octave-abbrev-start)
214 (define-key map "\e\n" 'octave-indent-new-comment-line)
215 (define-key map "\M-\C-q" 'octave-indent-defun)
216 (define-key map "\C-c\C-b" 'octave-submit-bug-report)
217 (define-key map "\C-c\C-p" 'octave-previous-code-line)
218 (define-key map "\C-c\C-n" 'octave-next-code-line)
219 (define-key map "\C-c\C-a" 'octave-beginning-of-line)
220 (define-key map "\C-c\C-e" 'octave-end-of-line)
221 (define-key map [remap down-list] 'smie-down-list)
222 (define-key map "\C-c\M-\C-h" 'octave-mark-block)
223 (define-key map "\C-c]" 'smie-close-block)
224 (define-key map "\C-c/" 'smie-close-block)
225 (define-key map "\C-c\C-f" 'octave-insert-defun)
226 ;; FIXME: free C-h so it can do the describe-prefix-bindings.
227 (define-key map "\C-c\C-h" 'info-lookup-symbol)
228 (define-key map "\C-c\C-il" 'octave-send-line)
229 (define-key map "\C-c\C-ib" 'octave-send-block)
230 (define-key map "\C-c\C-if" 'octave-send-defun)
231 (define-key map "\C-c\C-ir" 'octave-send-region)
232 (define-key map "\C-c\C-is" 'octave-show-process-buffer)
233 (define-key map "\C-c\C-ih" 'octave-hide-process-buffer)
234 (define-key map "\C-c\C-ik" 'octave-kill-process)
235 (define-key map "\C-c\C-i\C-l" 'octave-send-line)
236 (define-key map "\C-c\C-i\C-b" 'octave-send-block)
237 (define-key map "\C-c\C-i\C-f" 'octave-send-defun)
238 (define-key map "\C-c\C-i\C-r" 'octave-send-region)
239 (define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
240 ;; FIXME: free C-h so it can do the describe-prefix-bindings.
241 (define-key map "\C-c\C-i\C-h" 'octave-hide-process-buffer)
242 (define-key map "\C-c\C-i\C-k" 'octave-kill-process)
243 map)
244 "Keymap used in Octave mode.")
245
246
247
248(easy-menu-define octave-mode-menu octave-mode-map
249 "Menu for Octave mode."
250 '("Octave"
251 ("Lines"
252 ["Previous Code Line" octave-previous-code-line t]
253 ["Next Code Line" octave-next-code-line t]
254 ["Begin of Continuation" octave-beginning-of-line t]
255 ["End of Continuation" octave-end-of-line t]
256 ["Split Line at Point" octave-indent-new-comment-line t])
257 ("Blocks"
258 ["Mark Block" octave-mark-block t]
259 ["Close Block" smie-close-block t])
260 ("Functions"
261 ["Indent Function" octave-indent-defun t]
262 ["Insert Function" octave-insert-defun t])
263 "-"
264 ("Debug"
265 ["Send Current Line" octave-send-line t]
266 ["Send Current Block" octave-send-block t]
267 ["Send Current Function" octave-send-defun t]
268 ["Send Region" octave-send-region t]
269 ["Show Process Buffer" octave-show-process-buffer t]
270 ["Hide Process Buffer" octave-hide-process-buffer t]
271 ["Kill Process" octave-kill-process t])
272 "-"
273 ["Indent Line" indent-according-to-mode t]
274 ["Complete Symbol" completion-at-point t]
275 "-"
276 ["Toggle Abbrev Mode" abbrev-mode
277 :style toggle :selected abbrev-mode]
278 ["Toggle Auto-Fill Mode" auto-fill-mode
279 :style toggle :selected auto-fill-function]
280 "-"
281 ["Submit Bug Report" octave-submit-bug-report t]
282 "-"
283 ["Describe Octave Mode" describe-mode t]
284 ["Lookup Octave Index" info-lookup-symbol t]))
285
286(defvar octave-mode-syntax-table
287 (let ((table (make-syntax-table)))
288 (modify-syntax-entry ?\r " " table)
289 (modify-syntax-entry ?+ "." table)
290 (modify-syntax-entry ?- "." table)
291 (modify-syntax-entry ?= "." table)
292 (modify-syntax-entry ?* "." table)
293 (modify-syntax-entry ?/ "." table)
294 (modify-syntax-entry ?> "." table)
295 (modify-syntax-entry ?< "." table)
296 (modify-syntax-entry ?& "." table)
297 (modify-syntax-entry ?| "." table)
298 (modify-syntax-entry ?! "." table)
299 (modify-syntax-entry ?\\ "\\" table)
300 (modify-syntax-entry ?\' "." table)
301 ;; Was "w" for abbrevs, but now that it's not necessary any more,
302 (modify-syntax-entry ?\` "." table)
303 (modify-syntax-entry ?\" "\"" table)
304 (modify-syntax-entry ?. "_" table)
305 (modify-syntax-entry ?_ "_" table)
306 ;; The "b" flag only applies to the second letter of the comstart
307 ;; and the first letter of the comend, i.e. the "4b" below is ineffective.
308 ;; If we try to put `b' on the single-line comments, we get a similar
309 ;; problem where the % and # chars appear as first chars of the 2-char
310 ;; comend, so the multi-line ender is also turned into style-b.
311 ;; So we need the new "c" comment style.
312 (modify-syntax-entry ?\% "< 13" table)
313 (modify-syntax-entry ?\# "< 13" table)
314 (modify-syntax-entry ?\{ "(} 2c" table)
315 (modify-syntax-entry ?\} "){ 4c" table)
316 (modify-syntax-entry ?\n ">" table)
317 table)
318 "Syntax table in use in `octave-mode' buffers.")
319
320(defcustom octave-blink-matching-block t
321 "Control the blinking of matching Octave block keywords.
322Non-nil means show matching begin of block when inserting a space,
323newline or semicolon after an else or end keyword."
324 :type 'boolean
325 :group 'octave)
326
327(defcustom octave-block-offset 2
328 "Extra indentation applied to statements in Octave block structures."
329 :type 'integer
330 :group 'octave)
331
332(defvar octave-block-comment-start
333 (concat (make-string 2 octave-comment-char) " ")
334 "String to insert to start a new Octave comment on an empty line.")
335
336(defcustom octave-continuation-offset 4
337 "Extra indentation applied to Octave continuation lines."
338 :type 'integer
339 :group 'octave)
340(eval-and-compile
341 (defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
342(defvar octave-continuation-regexp
343 (concat "[^#%\n]*\\(" octave-continuation-marker-regexp
344 "\\)\\s-*\\(\\s<.*\\)?$"))
345(defcustom octave-continuation-string "\\"
346 "Character string used for Octave continuation lines. Normally \\."
347 :type 'string
348 :group 'octave)
349
350(defvar octave-completion-alist nil
351 "Alist of Octave symbols for completion in Octave mode.
352Each element looks like (VAR . VAR), where the car and cdr are the same
353symbol (an Octave command or variable name).
354Currently, only builtin variables can be completed.")
355
356(defvar octave-mode-imenu-generic-expression
357 (list
358 ;; Functions
359 (list nil octave-function-header-regexp 3))
360 "Imenu expression for Octave mode. See `imenu-generic-expression'.")
361
362(defcustom octave-mode-hook nil
363 "Hook to be run when Octave mode is started."
364 :type 'hook
365 :group 'octave)
366
367(defcustom octave-send-show-buffer t
368 "Non-nil means display `inferior-octave-buffer' after sending to it."
369 :type 'boolean
370 :group 'octave)
371(defcustom octave-send-line-auto-forward t
372 "Control auto-forward after sending to the inferior Octave process.
373Non-nil means always go to the next Octave code line after sending."
374 :type 'boolean
375 :group 'octave)
376(defcustom octave-send-echo-input t
377 "Non-nil means echo input sent to the inferior Octave process."
378 :type 'boolean
379 :group 'octave)
380
381
382;;; SMIE indentation
383
384(require 'smie)
385
386(defconst octave-operator-table
387 '((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
388 (right "=" "+=" "-=" "*=" "/=")
389 (assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
390 (assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
391 (nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
392 (nonassoc ":") ;No idea what this is.
393 (assoc "+" "-")
394 (assoc "*" "/" "\\" ".\\" ".*" "./")
395 (nonassoc "'" ".'")
396 (nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
397 (right "^" "**" ".^" ".**")
398 ;; It's not really an operator, but for indentation purposes it
399 ;; could be convenient to treat it as one.
400 (assoc "...")))
401
402(defconst octave-smie-bnf-table
403 '((atom)
404 ;; We can't distinguish the first element in a sequence with
405 ;; precedence grammars, so we can't distinguish the condition
406 ;; if the `if' from the subsequent body, for example.
407 ;; This has to be done later in the indentation rules.
408 (exp (exp "\n" exp)
409 ;; We need to mention at least one of the operators in this part
410 ;; of the grammar: if the BNF and the operator table have
411 ;; no overlap, SMIE can't know how they relate.
412 (exp ";" exp)
413 ("try" exp "catch" exp "end_try_catch")
414 ("try" exp "catch" exp "end")
415 ("unwind_protect" exp
416 "unwind_protect_cleanup" exp "end_unwind_protect")
417 ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
418 ("for" exp "endfor")
419 ("for" exp "end")
420 ("do" exp "until" atom)
421 ("while" exp "endwhile")
422 ("while" exp "end")
423 ("if" exp "endif")
424 ("if" exp "else" exp "endif")
425 ("if" exp "elseif" exp "else" exp "endif")
426 ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
427 ("if" exp "elseif" exp "elseif" exp "else" exp "end")
428 ("switch" exp "case" exp "endswitch")
429 ("switch" exp "case" exp "otherwise" exp "endswitch")
430 ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
431 ("switch" exp "case" exp "case" exp "otherwise" exp "end")
432 ("function" exp "endfunction")
433 ("function" exp "end"))
434 ;; (fundesc (atom "=" atom))
435 ))
436
437(defconst octave-smie-grammar
438 (smie-prec2->grammar
439 (smie-merge-prec2s
440 (smie-bnf->prec2 octave-smie-bnf-table
441 '((assoc "\n" ";")))
442
443 (smie-precs->prec2 octave-operator-table))))
444
445;; Tokenizing needs to be refined so that ";;" is treated as two
446;; tokens and also so as to recognize the \n separator (and
447;; corresponding continuation lines).
448
449(defconst octave-operator-regexp
450 (regexp-opt (apply 'append (mapcar 'cdr octave-operator-table))))
451
452(defun octave-smie-backward-token ()
453 (let ((pos (point)))
454 (forward-comment (- (point)))
455 (cond
456 ((and (not (eq (char-before) ?\;)) ;Coalesce ";" and "\n".
457 (> pos (line-end-position))
458 (if (looking-back octave-continuation-marker-regexp (- (point) 3))
459 (progn
460 (goto-char (match-beginning 0))
461 (forward-comment (- (point)))
462 nil)
463 t)
464 ;; Ignore it if it's within parentheses.
465 (let ((ppss (syntax-ppss)))
466 (not (and (nth 1 ppss)
467 (eq ?\( (char-after (nth 1 ppss)))))))
468 (skip-chars-forward " \t")
469 ;; Why bother distinguishing \n and ;?
470 ";") ;;"\n"
471 ((and (looking-back octave-operator-regexp (- (point) 3) 'greedy)
472 ;; Don't mistake a string quote for a transpose.
473 (not (looking-back "\\s\"" (1- (point)))))
474 (goto-char (match-beginning 0))
475 (match-string-no-properties 0))
476 (t
477 (smie-default-backward-token)))))
478
479(defun octave-smie-forward-token ()
480 (skip-chars-forward " \t")
481 (when (looking-at (eval-when-compile
482 (concat "\\(" octave-continuation-marker-regexp
483 "\\)[ \t]*\\($\\|[%#]\\)")))
484 (goto-char (match-end 1))
485 (forward-comment 1))
486 (cond
487 ((and (looking-at "$\\|[%#]")
488 ;; Ignore it if it's within parentheses.
489 (prog1 (let ((ppss (syntax-ppss)))
490 (not (and (nth 1 ppss)
491 (eq ?\( (char-after (nth 1 ppss))))))
492 (forward-comment (point-max))))
493 ;; Why bother distinguishing \n and ;?
494 ";") ;;"\n"
495 ((looking-at ";[ \t]*\\($\\|[%#]\\)")
496 ;; Combine the ; with the subsequent \n.
497 (goto-char (match-beginning 1))
498 (forward-comment 1)
499 ";")
500 ((and (looking-at octave-operator-regexp)
501 ;; Don't mistake a string quote for a transpose.
502 (not (looking-at "\\s\"")))
503 (goto-char (match-end 0))
504 (match-string-no-properties 0))
505 (t
506 (smie-default-forward-token))))
507
508(defun octave-smie-rules (kind token)
509 (pcase (cons kind token)
510 ;; We could set smie-indent-basic instead, but that would have two
511 ;; disadvantages:
512 ;; - changes to octave-block-offset wouldn't take effect immediately.
513 ;; - edebug wouldn't show the use of this variable.
514 (`(:elem . basic) octave-block-offset)
515 ;; Since "case" is in the same BNF rules as switch..end, SMIE by default
516 ;; aligns it with "switch".
517 (`(:before . "case") (if (not (smie-rule-sibling-p)) octave-block-offset))
518 (`(:after . ";")
519 (if (smie-rule-parent-p "function" "if" "while" "else" "elseif" "for"
520 "otherwise" "case" "try" "catch" "unwind_protect"
521 "unwind_protect_cleanup")
522 (smie-rule-parent octave-block-offset)
523 ;; For (invalid) code between switch and case.
524 ;; (if (smie-parent-p "switch") 4)
525 0))))
526
527(defvar electric-layout-rules)
528
529;;;###autoload
530(define-derived-mode octave-mode prog-mode "Octave"
531 "Major mode for editing Octave code.
532
533This mode makes it easier to write Octave code by helping with
534indentation, doing some of the typing for you (with Abbrev mode) and by
535showing keywords, comments, strings, etc. in different faces (with
536Font Lock mode on terminals that support it).
537
538Octave itself is a high-level language, primarily intended for numerical
539computations. It provides a convenient command line interface for
540solving linear and nonlinear problems numerically. Function definitions
541can also be stored in files, and it can be used in a batch mode (which
542is why you need this mode!).
543
544The latest released version of Octave is always available via anonymous
545ftp from ftp.octave.org in the directory `/pub/octave'. Complete
546source and binaries for several popular systems are available.
547
548Type \\[list-abbrevs] to display the built-in abbrevs for Octave keywords.
549
550Keybindings
551===========
552
553\\{octave-mode-map}
554
555Variables you can use to customize Octave mode
556==============================================
557
558`octave-blink-matching-block'
559 Non-nil means show matching begin of block when inserting a space,
560 newline or semicolon after an else or end keyword. Default is t.
561
562`octave-block-offset'
563 Extra indentation applied to statements in block structures.
564 Default is 2.
565
566`octave-continuation-offset'
567 Extra indentation applied to Octave continuation lines.
568 Default is 4.
569
570`octave-continuation-string'
571 String used for Octave continuation lines.
572 Default is a backslash.
573
574`octave-send-echo-input'
575 Non-nil means always display `inferior-octave-buffer' after sending a
576 command to the inferior Octave process.
577
578`octave-send-line-auto-forward'
579 Non-nil means always go to the next unsent line of Octave code after
580 sending a line to the inferior Octave process.
581
582`octave-send-echo-input'
583 Non-nil means echo input sent to the inferior Octave process.
584
585Turning on Octave mode runs the hook `octave-mode-hook'.
586
587To begin using this mode for all `.m' files that you edit, add the
588following lines to your init file:
589
590 (add-to-list 'auto-mode-alist '(\"\\\\.m\\\\'\" . octave-mode))
591
592To automatically turn on the abbrev and auto-fill features,
593add the following lines to your init file as well:
594
595 (add-hook 'octave-mode-hook
596 (lambda ()
597 (abbrev-mode 1)
598 (auto-fill-mode 1)))
599
600To submit a problem report, enter \\[octave-submit-bug-report] from \
601an Octave mode buffer.
602This automatically sets up a mail buffer with version information
603already added. You just need to add a description of the problem,
604including a reproducible test case and send the message."
605 (setq local-abbrev-table octave-abbrev-table)
606
607 (smie-setup octave-smie-grammar #'octave-smie-rules
608 :forward-token #'octave-smie-forward-token
609 :backward-token #'octave-smie-backward-token)
610 (set (make-local-variable 'smie-indent-basic) 'octave-block-offset)
611
612 (set (make-local-variable 'smie-blink-matching-triggers)
613 (cons ?\; smie-blink-matching-triggers))
614 (unless octave-blink-matching-block
615 (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
616
617 (set (make-local-variable 'electric-indent-chars)
618 (cons ?\; electric-indent-chars))
619 ;; IIUC matlab-mode takes the opposite approach: it makes RET insert
620 ;; a ";" at those places where it's correct (i.e. outside of parens).
621 (set (make-local-variable 'electric-layout-rules) '((?\; . after)))
622
623 (set (make-local-variable 'comment-start) octave-comment-start)
624 (set (make-local-variable 'comment-end) "")
625 ;; Don't set it here: it's not really a property of the language,
626 ;; just a personal preference of the author.
627 ;; (set (make-local-variable 'comment-column) 32)
628 (set (make-local-variable 'comment-start-skip) "\\s<+\\s-*")
629 (set (make-local-variable 'comment-add) 1)
630
631 (set (make-local-variable 'parse-sexp-ignore-comments) t)
632 (set (make-local-variable 'paragraph-start)
633 (concat "\\s-*$\\|" page-delimiter))
634 (set (make-local-variable 'paragraph-separate) paragraph-start)
635 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
636 (set (make-local-variable 'fill-paragraph-function) 'octave-fill-paragraph)
637 ;; FIXME: Why disable it?
638 ;; (set (make-local-variable 'adaptive-fill-regexp) nil)
639 ;; Again, this is not a property of the language, don't set it here.
640 ;; (set (make-local-variable 'fill-column) 72)
641 (set (make-local-variable 'normal-auto-fill-function) 'octave-auto-fill)
642
643 (set (make-local-variable 'font-lock-defaults)
644 '(octave-font-lock-keywords))
645
646 (set (make-local-variable 'syntax-propertize-function)
647 #'octave-syntax-propertize-function)
648
649 (set (make-local-variable 'imenu-generic-expression)
650 octave-mode-imenu-generic-expression)
651 (set (make-local-variable 'imenu-case-fold-search) nil)
652
653 (add-hook 'completion-at-point-functions
654 'octave-completion-at-point-function nil t)
655 (set (make-local-variable 'beginning-of-defun-function)
656 'octave-beginning-of-defun)
657
658 (easy-menu-add octave-mode-menu)
659 (octave-initialize-completions))
660
661;;; Miscellaneous useful functions
662
663(defsubst octave-in-comment-p ()
664 "Return t if point is inside an Octave comment."
665 (nth 4 (syntax-ppss)))
666
667(defsubst octave-in-string-p ()
668 "Return t if point is inside an Octave string."
669 (nth 3 (syntax-ppss)))
670
671(defsubst octave-not-in-string-or-comment-p ()
672 "Return t if point is not inside an Octave string or comment."
673 (let ((pps (syntax-ppss)))
674 (not (or (nth 3 pps) (nth 4 pps)))))
675
676
677(defun octave-looking-at-kw (regexp)
678 "Like `looking-at', but sets `case-fold-search' nil."
679 (let ((case-fold-search nil))
680 (looking-at regexp)))
681
682(defun octave-maybe-insert-continuation-string ()
683 (if (or (octave-in-comment-p)
684 (save-excursion
685 (beginning-of-line)
686 (looking-at octave-continuation-regexp)))
687 nil
688 (delete-horizontal-space)
689 (insert (concat " " octave-continuation-string))))
690
691;;; Indentation
692
693(defun octave-indent-new-comment-line ()
694 "Break Octave line at point, continuing comment if within one.
695If within code, insert `octave-continuation-string' before breaking the
696line. If within a string, signal an error.
697The new line is properly indented."
698 (interactive)
699 (delete-horizontal-space)
700 (cond
701 ((octave-in-comment-p)
702 (indent-new-comment-line))
703 ((octave-in-string-p)
704 (error "Cannot split a code line inside a string"))
705 (t
706 (insert (concat " " octave-continuation-string))
707 (reindent-then-newline-and-indent))))
708
709(defun octave-indent-defun ()
710 "Properly indent the Octave function which contains point."
711 (interactive)
712 (save-excursion
713 (mark-defun)
714 (message "Indenting function...")
715 (indent-region (point) (mark) nil))
716 (message "Indenting function...done."))
717
718
719;;; Motion
720(defun octave-next-code-line (&optional arg)
721 "Move ARG lines of Octave code forward (backward if ARG is negative).
722Skips past all empty and comment lines. Default for ARG is 1.
723
724On success, return 0. Otherwise, go as far as possible and return -1."
725 (interactive "p")
726 (or arg (setq arg 1))
727 (beginning-of-line)
728 (let ((n 0)
729 (inc (if (> arg 0) 1 -1)))
730 (while (and (/= arg 0) (= n 0))
731 (setq n (forward-line inc))
732 (while (and (= n 0)
733 (looking-at "\\s-*\\($\\|\\s<\\)"))
734 (setq n (forward-line inc)))
735 (setq arg (- arg inc)))
736 n))
737
738(defun octave-previous-code-line (&optional arg)
739 "Move ARG lines of Octave code backward (forward if ARG is negative).
740Skips past all empty and comment lines. Default for ARG is 1.
741
742On success, return 0. Otherwise, go as far as possible and return -1."
743 (interactive "p")
744 (or arg (setq arg 1))
745 (octave-next-code-line (- arg)))
746
747(defun octave-beginning-of-line ()
748 "Move point to beginning of current Octave line.
749If on an empty or comment line, go to the beginning of that line.
750Otherwise, move backward to the beginning of the first Octave code line
751which is not inside a continuation statement, i.e., which does not
752follow a code line ending in `...' or `\\', or is inside an open
753parenthesis list."
754 (interactive)
755 (beginning-of-line)
756 (if (not (looking-at "\\s-*\\($\\|\\s<\\)"))
757 (while (or (condition-case nil
758 (progn
759 (up-list -1)
760 (beginning-of-line)
761 t)
762 (error nil))
763 (and (or (looking-at "\\s-*\\($\\|\\s<\\)")
764 (save-excursion
765 (if (zerop (octave-previous-code-line))
766 (looking-at octave-continuation-regexp))))
767 (zerop (forward-line -1)))))))
768
769(defun octave-end-of-line ()
770 "Move point to end of current Octave line.
771If on an empty or comment line, go to the end of that line.
772Otherwise, move forward to the end of the first Octave code line which
773does not end in `...' or `\\' or is inside an open parenthesis list."
774 (interactive)
775 (end-of-line)
776 (if (save-excursion
777 (beginning-of-line)
778 (looking-at "\\s-*\\($\\|\\s<\\)"))
779 ()
780 (while (or (condition-case nil
781 (progn
782 (up-list 1)
783 (end-of-line)
784 t)
785 (error nil))
786 (and (save-excursion
787 (beginning-of-line)
788 (or (looking-at "\\s-*\\($\\|\\s<\\)")
789 (looking-at octave-continuation-regexp)))
790 (zerop (forward-line 1)))))
791 (end-of-line)))
792
793(defun octave-mark-block ()
794 "Put point at the beginning of this Octave block, mark at the end.
795The block marked is the one that contains point or follows point."
796 (interactive)
797 (if (and (looking-at "\\sw\\|\\s_")
798 (looking-back "\\sw\\|\\s_" (1- (point))))
799 (skip-syntax-forward "w_"))
800 (unless (or (looking-at "\\s(")
801 (save-excursion
802 (let* ((token (funcall smie-forward-token-function))
803 (level (assoc token smie-grammar)))
804 (and level (not (numberp (cadr level)))))))
805 (backward-up-list 1))
806 (mark-sexp))
807
808(defun octave-beginning-of-defun (&optional arg)
809 "Move backward to the beginning of an Octave function.
810With positive ARG, do it that many times. Negative argument -N means
811move forward to Nth following beginning of a function.
812Returns t unless search stops at the beginning or end of the buffer."
813 (let* ((arg (or arg 1))
814 (inc (if (> arg 0) 1 -1))
815 (found nil)
816 (case-fold-search nil))
817 (and (not (eobp))
818 (not (and (> arg 0) (looking-at "\\_<function\\_>")))
819 (skip-syntax-forward "w"))
820 (while (and (/= arg 0)
821 (setq found
822 (re-search-backward "\\_<function\\_>" inc)))
823 (if (octave-not-in-string-or-comment-p)
824 (setq arg (- arg inc))))
825 (if found
826 (progn
827 (and (< inc 0) (goto-char (match-beginning 0)))
828 t))))
829
830
831;;; Filling
832(defun octave-auto-fill ()
833 "Perform auto-fill in Octave mode.
834Returns nil if no feasible place to break the line could be found, and t
835otherwise."
836 (let (fc give-up)
837 (if (or (null (setq fc (current-fill-column)))
838 (save-excursion
839 (beginning-of-line)
840 (and auto-fill-inhibit-regexp
841 (octave-looking-at-kw auto-fill-inhibit-regexp))))
842 nil ; Can't do anything
843 (if (and (not (octave-in-comment-p))
844 (> (current-column) fc))
845 (setq fc (- fc (+ (length octave-continuation-string) 1))))
846 (while (and (not give-up) (> (current-column) fc))
847 (let* ((opoint (point))
848 (fpoint
849 (save-excursion
850 (move-to-column (+ fc 1))
851 (skip-chars-backward "^ \t\n")
852 ;; If we're at the beginning of the line, break after
853 ;; the first word
854 (if (bolp)
855 (re-search-forward "[ \t]" opoint t))
856 ;; If we're in a comment line, don't break after the
857 ;; comment chars
858 (if (save-excursion
859 (skip-syntax-backward " <")
860 (bolp))
861 (re-search-forward "[ \t]" (line-end-position)
862 'move))
863 ;; If we're not in a comment line and just ahead the
864 ;; continuation string, don't break here.
865 (if (and (not (octave-in-comment-p))
866 (looking-at
867 (concat "\\s-*"
868 (regexp-quote
869 octave-continuation-string)
870 "\\s-*$")))
871 (end-of-line))
872 (skip-chars-backward " \t")
873 (point))))
874 (if (save-excursion
875 (goto-char fpoint)
876 (not (or (bolp) (eolp))))
877 (let ((prev-column (current-column)))
878 (if (save-excursion
879 (skip-chars-backward " \t")
880 (= (point) fpoint))
881 (progn
882 (octave-maybe-insert-continuation-string)
883 (indent-new-comment-line t))
884 (save-excursion
885 (goto-char fpoint)
886 (octave-maybe-insert-continuation-string)
887 (indent-new-comment-line t)))
888 (if (>= (current-column) prev-column)
889 (setq give-up t)))
890 (setq give-up t))))
891 (not give-up))))
892
893(defun octave-fill-paragraph (&optional _arg)
894 "Fill paragraph of Octave code, handling Octave comments."
895 ;; FIXME: difference with generic fill-paragraph:
896 ;; - code lines are only split, never joined.
897 ;; - \n that end comments are never removed.
898 ;; - insert continuation marker when splitting code lines.
899 (interactive "P")
900 (save-excursion
901 (let ((end (progn (forward-paragraph) (copy-marker (point) t)))
902 (beg (progn
903 (forward-paragraph -1)
904 (skip-chars-forward " \t\n")
905 (beginning-of-line)
906 (point)))
907 (cfc (current-fill-column))
908 comment-prefix)
909 (goto-char beg)
910 (while (< (point) end)
911 (condition-case nil
912 (indent-according-to-mode)
913 (error nil))
914 (move-to-column cfc)
915 ;; First check whether we need to combine non-empty comment lines
916 (if (and (< (current-column) cfc)
917 (octave-in-comment-p)
918 (not (save-excursion
919 (beginning-of-line)
920 (looking-at "^\\s-*\\s<+\\s-*$"))))
921 ;; This is a nonempty comment line which does not extend
922 ;; past the fill column. If it is followed by a nonempty
923 ;; comment line with the same comment prefix, try to
924 ;; combine them, and repeat this until either we reach the
925 ;; fill-column or there is nothing more to combine.
926 (progn
927 ;; Get the comment prefix
928 (save-excursion
929 (beginning-of-line)
930 (while (and (re-search-forward "\\s<+")
931 (not (octave-in-comment-p))))
932 (setq comment-prefix (match-string 0)))
933 ;; And keep combining ...
934 (while (and (< (current-column) cfc)
935 (save-excursion
936 (forward-line 1)
937 (and (looking-at
938 (concat "^\\s-*"
939 comment-prefix
940 "\\S<"))
941 (not (looking-at
942 (concat "^\\s-*"
943 comment-prefix
944 "\\s-*$"))))))
945 (delete-char 1)
946 (re-search-forward comment-prefix)
947 (delete-region (match-beginning 0) (match-end 0))
948 (fixup-whitespace)
949 (move-to-column cfc))))
950 ;; We might also try to combine continued code lines> Perhaps
951 ;; some other time ...
952 (skip-chars-forward "^ \t\n")
953 (delete-horizontal-space)
954 (if (or (< (current-column) cfc)
955 (and (= (current-column) cfc) (eolp)))
956 (forward-line 1)
957 (if (not (eolp)) (insert " "))
958 (or (octave-auto-fill)
959 (forward-line 1))))
960 t)))
961
962
963;;; Completions
964(defun octave-initialize-completions ()
965 "Create an alist for Octave completions."
966 (if octave-completion-alist
967 ()
968 (setq octave-completion-alist
969 (append octave-reserved-words
970 octave-text-functions
971 octave-variables))))
972
973(defun octave-completion-at-point-function ()
974 "Find the text to complete and the corresponding table."
975 (let* ((beg (save-excursion (skip-syntax-backward "w_") (point)))
976 (end (point)))
977 (if (< beg (point))
978 ;; Extend region past point, if applicable.
979 (save-excursion (skip-syntax-forward "w_")
980 (setq end (point))))
981 (list beg end octave-completion-alist)))
982
983(define-obsolete-function-alias 'octave-complete-symbol
984 'completion-at-point "24.1")
985
986;;; Electric characters && friends
987
988(defun octave-abbrev-start ()
989 "Start entering an Octave abbreviation.
990If Abbrev mode is turned on, typing ` (grave accent) followed by ? or
991\\[help-command] lists all Octave abbrevs. Any other key combination is
992executed normally.
993Note that all Octave mode abbrevs start with a grave accent."
994 (interactive)
995 (self-insert-command 1)
996 (when abbrev-mode
997 (set-temporary-overlay-map
998 (let ((map (make-sparse-keymap)))
999 (define-key map [??] 'list-abbrevs)
1000 (define-key map (vector help-char) 'list-abbrevs)
1001 map))))
1002
1003(define-skeleton octave-insert-defun
1004 "Insert an Octave function skeleton.
1005Prompt for the function's name, arguments and return values (to be
1006entered without parens)."
1007 (let* ((defname (substring (buffer-name) 0 -2))
1008 (name (read-string (format "Function name (default %s): " defname)
1009 nil nil defname))
1010 (args (read-string "Arguments: "))
1011 (vals (read-string "Return values: ")))
1012 (format "%s%s (%s)"
1013 (cond
1014 ((string-equal vals "") vals)
1015 ((string-match "[ ,]" vals) (concat "[" vals "] = "))
1016 (t (concat vals " = ")))
1017 name
1018 args))
1019 \n "function " > str \n \n
1020 octave-block-comment-start "usage: " str \n
1021 octave-block-comment-start \n octave-block-comment-start
1022 \n _ \n
1023 "endfunction" > \n)
1024
1025;;; Communication with the inferior Octave process
1026(defun octave-kill-process ()
1027 "Kill inferior Octave process and its buffer."
1028 (interactive)
1029 (if inferior-octave-process
1030 (progn
1031 (process-send-string inferior-octave-process "quit;\n")
1032 (accept-process-output inferior-octave-process)))
1033 (if inferior-octave-buffer
1034 (kill-buffer inferior-octave-buffer)))
1035
1036(defun octave-show-process-buffer ()
1037 "Make sure that `inferior-octave-buffer' is displayed."
1038 (interactive)
1039 (if (get-buffer inferior-octave-buffer)
1040 (display-buffer inferior-octave-buffer)
1041 (message "No buffer named %s" inferior-octave-buffer)))
1042
1043(defun octave-hide-process-buffer ()
1044 "Delete all windows that display `inferior-octave-buffer'."
1045 (interactive)
1046 (if (get-buffer inferior-octave-buffer)
1047 (delete-windows-on inferior-octave-buffer)
1048 (message "No buffer named %s" inferior-octave-buffer)))
1049
1050(defun octave-send-region (beg end)
1051 "Send current region to the inferior Octave process."
1052 (interactive "r")
1053 (inferior-octave t)
1054 (let ((proc inferior-octave-process)
1055 (string (buffer-substring-no-properties beg end))
1056 line)
1057 (with-current-buffer inferior-octave-buffer
1058 (setq inferior-octave-output-list nil)
1059 (while (not (string-equal string ""))
1060 (if (string-match "\n" string)
1061 (setq line (substring string 0 (match-beginning 0))
1062 string (substring string (match-end 0)))
1063 (setq line string string ""))
1064 (setq inferior-octave-receive-in-progress t)
1065 (inferior-octave-send-list-and-digest (list (concat line "\n")))
1066 (while inferior-octave-receive-in-progress
1067 (accept-process-output proc))
1068 (insert-before-markers
1069 (mapconcat 'identity
1070 (append
1071 (if octave-send-echo-input (list line) (list ""))
1072 (mapcar 'inferior-octave-strip-ctrl-g
1073 inferior-octave-output-list)
1074 (list inferior-octave-output-string))
1075 "\n")))))
1076 (if octave-send-show-buffer
1077 (display-buffer inferior-octave-buffer)))
1078
1079(defun octave-send-block ()
1080 "Send current Octave block to the inferior Octave process."
1081 (interactive)
1082 (save-excursion
1083 (octave-mark-block)
1084 (octave-send-region (point) (mark))))
1085
1086(defun octave-send-defun ()
1087 "Send current Octave function to the inferior Octave process."
1088 (interactive)
1089 (save-excursion
1090 (mark-defun)
1091 (octave-send-region (point) (mark))))
1092
1093(defun octave-send-line (&optional arg)
1094 "Send current Octave code line to the inferior Octave process.
1095With positive prefix ARG, send that many lines.
1096If `octave-send-line-auto-forward' is non-nil, go to the next unsent
1097code line."
1098 (interactive "P")
1099 (or arg (setq arg 1))
1100 (if (> arg 0)
1101 (let (beg end)
1102 (beginning-of-line)
1103 (setq beg (point))
1104 (octave-next-code-line (- arg 1))
1105 (end-of-line)
1106 (setq end (point))
1107 (if octave-send-line-auto-forward
1108 (octave-next-code-line 1))
1109 (octave-send-region beg end))))
1110
1111(defun octave-eval-print-last-sexp ()
1112 "Evaluate Octave sexp before point and print value into current buffer."
1113 (interactive)
1114 (inferior-octave t)
1115 (let ((standard-output (current-buffer))
1116 (print-escape-newlines nil)
1117 (opoint (point)))
1118 (terpri)
1119 (prin1
1120 (save-excursion
1121 (forward-sexp -1)
1122 (inferior-octave-send-list-and-digest
1123 (list (concat (buffer-substring-no-properties (point) opoint)
1124 "\n")))
1125 (mapconcat 'identity inferior-octave-output-list "\n")))
1126 (terpri)))
1127
1128;;; Bug reporting
1129(defun octave-submit-bug-report ()
1130 "Submit a bug report on the Emacs Octave package via mail."
1131 (interactive)
1132 (require 'reporter)
1133 (and
1134 (y-or-n-p "Do you want to submit a bug report? ")
1135 (reporter-submit-bug-report
1136 octave-maintainer-address
1137 (concat "Emacs version " emacs-version)
1138 (list
1139 'octave-blink-matching-block
1140 'octave-block-offset
1141 'octave-comment-char
1142 'octave-continuation-offset
1143 'octave-continuation-string
1144 'octave-send-echo-input
1145 'octave-send-line-auto-forward
1146 'octave-send-show-buffer))))
1147
1148;; provide ourself
1149
1150(provide 'octave-mod)
1151
1152;;; octave-mod.el ends here
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
new file mode 100644
index 00000000000..c6e19fe3a15
--- /dev/null
+++ b/lisp/progmodes/octave.el
@@ -0,0 +1,1732 @@
1;;; octave.el --- editing octave source files under emacs -*- lexical-binding: t; -*-
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@octave.org>
7;; Maintainer: FSF
8;; Keywords: languages
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;; This package provides emacs support for Octave. It defines a major
28;; mode for editing Octave code and contains code for interacting with
29;; an inferior Octave process using comint.
30
31;; See the documentation of `octave-mode' and `run-octave' for further
32;; information on usage and customization.
33
34;;; Code:
35(require 'comint)
36
37;;; For emacs < 24.3.
38(require 'newcomment)
39(eval-and-compile
40 (unless (fboundp 'user-error)
41 (defalias 'user-error 'error))
42 (unless (fboundp 'delete-consecutive-dups)
43 (defalias 'delete-consecutive-dups 'delete-dups)))
44(eval-when-compile
45 (unless (fboundp 'setq-local)
46 (defmacro setq-local (var val)
47 "Set variable VAR to value VAL in current buffer."
48 (list 'set (list 'make-local-variable (list 'quote var)) val))))
49
50(defgroup octave nil
51 "Editing Octave code."
52 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
53 :group 'languages)
54
55(define-obsolete-function-alias 'octave-submit-bug-report
56 'report-emacs-bug "24.4")
57
58(define-abbrev-table 'octave-abbrev-table nil
59 "Abbrev table for Octave's reserved words.
60Used in `octave-mode' and `inferior-octave-mode' buffers.")
61
62(defvar octave-comment-char ?#
63 "Character to start an Octave comment.")
64
65(defvar octave-comment-start (char-to-string octave-comment-char)
66 "Octave-specific `comment-start' (which see).")
67
68(defvar octave-comment-start-skip "\\(^\\|\\S<\\)\\(?:%!\\|\\s<+\\)\\s-*"
69 "Octave-specific `comment-start-skip' (which see).")
70
71(defvar octave-begin-keywords
72 '("classdef" "do" "enumeration" "events" "for" "function" "if" "methods"
73 "parfor" "properties" "switch" "try" "unwind_protect" "while"))
74
75(defvar octave-else-keywords
76 '("case" "catch" "else" "elseif" "otherwise" "unwind_protect_cleanup"))
77
78(defvar octave-end-keywords
79 '("endclassdef" "endenumeration" "endevents" "endfor" "endfunction" "endif"
80 "endmethods" "endparfor" "endproperties" "endswitch" "end_try_catch"
81 "end_unwind_protect" "endwhile" "until" "end"))
82
83(defvar octave-reserved-words
84 (append octave-begin-keywords
85 octave-else-keywords
86 octave-end-keywords
87 '("break" "continue" "global" "persistent" "return"))
88 "Reserved words in Octave.")
89
90(defvar octave-function-header-regexp
91 (concat "^\\s-*\\_<\\(function\\)\\_>"
92 "\\([^=;\n]*=[ \t]*\\|[ \t]*\\)\\(\\(?:\\w\\|\\s_\\)+\\)\\_>")
93 "Regexp to match an Octave function header.
94The string `function' and its name are given by the first and third
95parenthetical grouping.")
96
97
98(defvar octave-mode-map
99 (let ((map (make-sparse-keymap)))
100 (define-key map "\M-." 'octave-find-definition)
101 (define-key map "\M-\C-j" 'octave-indent-new-comment-line)
102 (define-key map "\C-c\C-p" 'octave-previous-code-line)
103 (define-key map "\C-c\C-n" 'octave-next-code-line)
104 (define-key map "\C-c\C-a" 'octave-beginning-of-line)
105 (define-key map "\C-c\C-e" 'octave-end-of-line)
106 (define-key map [remap down-list] 'smie-down-list)
107 (define-key map "\C-c\M-\C-h" 'octave-mark-block)
108 (define-key map "\C-c]" 'smie-close-block)
109 (define-key map "\C-c/" 'smie-close-block)
110 (define-key map "\C-c;" 'octave-update-function-file-comment)
111 (define-key map "\C-hd" 'octave-help)
112 (define-key map "\C-c\C-f" 'octave-insert-defun)
113 (define-key map "\C-c\C-il" 'octave-send-line)
114 (define-key map "\C-c\C-ib" 'octave-send-block)
115 (define-key map "\C-c\C-if" 'octave-send-defun)
116 (define-key map "\C-c\C-ir" 'octave-send-region)
117 (define-key map "\C-c\C-is" 'octave-show-process-buffer)
118 (define-key map "\C-c\C-iq" 'octave-hide-process-buffer)
119 (define-key map "\C-c\C-ik" 'octave-kill-process)
120 (define-key map "\C-c\C-i\C-l" 'octave-send-line)
121 (define-key map "\C-c\C-i\C-b" 'octave-send-block)
122 (define-key map "\C-c\C-i\C-f" 'octave-send-defun)
123 (define-key map "\C-c\C-i\C-r" 'octave-send-region)
124 (define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
125 (define-key map "\C-c\C-i\C-q" 'octave-hide-process-buffer)
126 (define-key map "\C-c\C-i\C-k" 'octave-kill-process)
127 map)
128 "Keymap used in Octave mode.")
129
130
131
132(easy-menu-define octave-mode-menu octave-mode-map
133 "Menu for Octave mode."
134 '("Octave"
135 ["Split Line at Point" octave-indent-new-comment-line t]
136 ["Previous Code Line" octave-previous-code-line t]
137 ["Next Code Line" octave-next-code-line t]
138 ["Begin of Line" octave-beginning-of-line t]
139 ["End of Line" octave-end-of-line t]
140 ["Mark Block" octave-mark-block t]
141 ["Close Block" smie-close-block t]
142 "---"
143 ["Start Octave Process" run-octave t]
144 ["Documentation Lookup" info-lookup-symbol t]
145 ["Help on Function" octave-help t]
146 ["Find Function Definition" octave-find-definition t]
147 ["Insert Function" octave-insert-defun t]
148 ["Update Function File Comment" octave-update-function-file-comment t]
149 "---"
150 ["Function Syntax Hints" (call-interactively
151 (if (fboundp 'eldoc-post-insert-mode)
152 'eldoc-post-insert-mode
153 'eldoc-mode))
154 :style toggle :selected (or eldoc-post-insert-mode eldoc-mode)
155 :help "Display function signatures after typing `SPC' or `('"]
156 ["Delimiter Matching" smie-highlight-matching-block-mode
157 :style toggle :selected smie-highlight-matching-block-mode
158 :help "Highlight matched pairs such as `if ... end'"
159 :visible (fboundp 'smie-highlight-matching-block-mode)]
160 ["Auto Fill" auto-fill-mode
161 :style toggle :selected auto-fill-function
162 :help "Automatic line breaking"]
163 ["Electric Layout" electric-layout-mode
164 :style toggle :selected electric-layout-mode
165 :help "Automatically insert newlines around some chars"]
166 "---"
167 ("Debug"
168 ["Send Current Line" octave-send-line t]
169 ["Send Current Block" octave-send-block t]
170 ["Send Current Function" octave-send-defun t]
171 ["Send Region" octave-send-region t]
172 ["Show Process Buffer" octave-show-process-buffer t]
173 ["Hide Process Buffer" octave-hide-process-buffer t]
174 ["Kill Process" octave-kill-process t])
175 "---"
176 ["Customize Octave" (customize-group 'octave) t]
177 ["Submit Bug Report" report-emacs-bug t]))
178
179(defvar octave-mode-syntax-table
180 (let ((table (make-syntax-table)))
181 (modify-syntax-entry ?\r " " table)
182 (modify-syntax-entry ?+ "." table)
183 (modify-syntax-entry ?- "." table)
184 (modify-syntax-entry ?= "." table)
185 (modify-syntax-entry ?* "." table)
186 (modify-syntax-entry ?/ "." table)
187 (modify-syntax-entry ?> "." table)
188 (modify-syntax-entry ?< "." table)
189 (modify-syntax-entry ?& "." table)
190 (modify-syntax-entry ?| "." table)
191 (modify-syntax-entry ?! "." table)
192 (modify-syntax-entry ?\\ "." table)
193 (modify-syntax-entry ?\' "." table)
194 (modify-syntax-entry ?\` "." table)
195 (modify-syntax-entry ?. "." table)
196 (modify-syntax-entry ?\" "\"" table)
197 (modify-syntax-entry ?_ "_" table)
198 ;; The "b" flag only applies to the second letter of the comstart
199 ;; and the first letter of the comend, i.e. the "4b" below is ineffective.
200 ;; If we try to put `b' on the single-line comments, we get a similar
201 ;; problem where the % and # chars appear as first chars of the 2-char
202 ;; comend, so the multi-line ender is also turned into style-b.
203 ;; So we need the new "c" comment style.
204 (modify-syntax-entry ?\% "< 13" table)
205 (modify-syntax-entry ?\# "< 13" table)
206 (modify-syntax-entry ?\{ "(} 2c" table)
207 (modify-syntax-entry ?\} "){ 4c" table)
208 (modify-syntax-entry ?\n ">" table)
209 table)
210 "Syntax table in use in `octave-mode' buffers.")
211
212(defcustom octave-font-lock-texinfo-comment t
213 "Control whether to highlight the texinfo comment block."
214 :type 'boolean
215 :group 'octave
216 :version "24.4")
217
218(defcustom octave-blink-matching-block t
219 "Control the blinking of matching Octave block keywords.
220Non-nil means show matching begin of block when inserting a space,
221newline or semicolon after an else or end keyword."
222 :type 'boolean
223 :group 'octave)
224
225(defcustom octave-block-offset 2
226 "Extra indentation applied to statements in Octave block structures."
227 :type 'integer
228 :group 'octave)
229
230(defvar octave-block-comment-start
231 (concat (make-string 2 octave-comment-char) " ")
232 "String to insert to start a new Octave comment on an empty line.")
233
234(defcustom octave-continuation-offset 4
235 "Extra indentation applied to Octave continuation lines."
236 :type 'integer
237 :group 'octave)
238
239(eval-and-compile
240 (defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
241
242(defvar octave-continuation-regexp
243 (concat "[^#%\n]*\\(" octave-continuation-marker-regexp
244 "\\)\\s-*\\(\\s<.*\\)?$"))
245
246;; Char \ is considered a bad decision for continuing a line.
247(defconst octave-continuation-string "..."
248 "Character string used for Octave continuation lines.")
249
250(defvar octave-mode-imenu-generic-expression
251 (list
252 ;; Functions
253 (list nil octave-function-header-regexp 3))
254 "Imenu expression for Octave mode. See `imenu-generic-expression'.")
255
256(defcustom octave-mode-hook nil
257 "Hook to be run when Octave mode is started."
258 :type 'hook
259 :group 'octave)
260
261(defcustom octave-send-show-buffer t
262 "Non-nil means display `inferior-octave-buffer' after sending to it."
263 :type 'boolean
264 :group 'octave)
265
266(defcustom octave-send-line-auto-forward t
267 "Control auto-forward after sending to the inferior Octave process.
268Non-nil means always go to the next Octave code line after sending."
269 :type 'boolean
270 :group 'octave)
271
272(defcustom octave-send-echo-input t
273 "Non-nil means echo input sent to the inferior Octave process."
274 :type 'boolean
275 :group 'octave)
276
277
278;;; SMIE indentation
279
280(require 'smie)
281
282;; Use '__operators__' in Octave REPL to get a full list.
283(defconst octave-operator-table
284 '((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
285 (right "=" "+=" "-=" "*=" "/=")
286 (assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
287 (assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
288 (nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
289 (nonassoc ":") ;No idea what this is.
290 (assoc "+" "-")
291 (assoc "*" "/" "\\" ".\\" ".*" "./")
292 (nonassoc "'" ".'")
293 (nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
294 (right "^" "**" ".^" ".**")
295 ;; It's not really an operator, but for indentation purposes it
296 ;; could be convenient to treat it as one.
297 (assoc "...")))
298
299(defconst octave-smie-bnf-table
300 '((atom)
301 ;; We can't distinguish the first element in a sequence with
302 ;; precedence grammars, so we can't distinguish the condition
303 ;; if the `if' from the subsequent body, for example.
304 ;; This has to be done later in the indentation rules.
305 (exp (exp "\n" exp)
306 ;; We need to mention at least one of the operators in this part
307 ;; of the grammar: if the BNF and the operator table have
308 ;; no overlap, SMIE can't know how they relate.
309 (exp ";" exp)
310 ("try" exp "catch" exp "end_try_catch")
311 ("try" exp "catch" exp "end")
312 ("unwind_protect" exp
313 "unwind_protect_cleanup" exp "end_unwind_protect")
314 ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
315 ("for" exp "endfor")
316 ("for" exp "end")
317 ("parfor" exp "endparfor")
318 ("parfor" exp "end")
319 ("do" exp "until" atom)
320 ("while" exp "endwhile")
321 ("while" exp "end")
322 ("if" exp "endif")
323 ("if" exp "else" exp "endif")
324 ("if" exp "elseif" exp "else" exp "endif")
325 ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
326 ("if" exp "elseif" exp "elseif" exp "else" exp "end")
327 ("switch" exp "case" exp "endswitch")
328 ("switch" exp "case" exp "otherwise" exp "endswitch")
329 ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
330 ("switch" exp "case" exp "case" exp "otherwise" exp "end")
331 ("function" exp "endfunction")
332 ("function" exp "end")
333 ("enumeration" exp "endenumeration")
334 ("enumeration" exp "end")
335 ("events" exp "endevents")
336 ("events" exp "end")
337 ("methods" exp "endmethods")
338 ("methods" exp "end")
339 ("properties" exp "endproperties")
340 ("properties" exp "end")
341 ("classdef" exp "endclassdef")
342 ("classdef" exp "end"))
343 ;; (fundesc (atom "=" atom))
344 ))
345
346(defconst octave-smie-grammar
347 (smie-prec2->grammar
348 (smie-merge-prec2s
349 (smie-bnf->prec2 octave-smie-bnf-table
350 '((assoc "\n" ";")))
351
352 (smie-precs->prec2 octave-operator-table))))
353
354;; Tokenizing needs to be refined so that ";;" is treated as two
355;; tokens and also so as to recognize the \n separator (and
356;; corresponding continuation lines).
357
358(defconst octave-operator-regexp
359 (regexp-opt (apply 'append (mapcar 'cdr octave-operator-table))))
360
361(defun octave-smie-backward-token ()
362 (let ((pos (point)))
363 (forward-comment (- (point)))
364 (cond
365 ((and (not (eq (char-before) ?\;)) ;Coalesce ";" and "\n".
366 (> pos (line-end-position))
367 (if (looking-back octave-continuation-marker-regexp (- (point) 3))
368 (progn
369 (goto-char (match-beginning 0))
370 (forward-comment (- (point)))
371 nil)
372 t)
373 ;; Ignore it if it's within parentheses.
374 (let ((ppss (syntax-ppss)))
375 (not (and (nth 1 ppss)
376 (eq ?\( (char-after (nth 1 ppss)))))))
377 (skip-chars-forward " \t")
378 ;; Why bother distinguishing \n and ;?
379 ";") ;;"\n"
380 ((and (looking-back octave-operator-regexp (- (point) 3) 'greedy)
381 ;; Don't mistake a string quote for a transpose.
382 (not (looking-back "\\s\"" (1- (point)))))
383 (goto-char (match-beginning 0))
384 (match-string-no-properties 0))
385 (t
386 (smie-default-backward-token)))))
387
388(defun octave-smie-forward-token ()
389 (skip-chars-forward " \t")
390 (when (looking-at (eval-when-compile
391 (concat "\\(" octave-continuation-marker-regexp
392 "\\)[ \t]*\\($\\|[%#]\\)")))
393 (goto-char (match-end 1))
394 (forward-comment 1))
395 (cond
396 ((and (looking-at "[%#\n]")
397 (not (or (save-excursion (skip-chars-backward " \t")
398 ;; Only add implicit ; when needed.
399 (or (bolp) (eq (char-before) ?\;)))
400 ;; Ignore it if it's within parentheses.
401 (let ((ppss (syntax-ppss)))
402 (and (nth 1 ppss)
403 (eq ?\( (char-after (nth 1 ppss))))))))
404 (if (eolp) (forward-char 1) (forward-comment 1))
405 ;; Why bother distinguishing \n and ;?
406 ";") ;;"\n"
407 ((progn (forward-comment (point-max)) nil))
408 ((looking-at ";[ \t]*\\($\\|[%#]\\)")
409 ;; Combine the ; with the subsequent \n.
410 (goto-char (match-beginning 1))
411 (forward-comment 1)
412 ";")
413 ((and (looking-at octave-operator-regexp)
414 ;; Don't mistake a string quote for a transpose.
415 (not (looking-at "\\s\"")))
416 (goto-char (match-end 0))
417 (match-string-no-properties 0))
418 (t
419 (smie-default-forward-token))))
420
421(defun octave-smie-rules (kind token)
422 (pcase (cons kind token)
423 ;; We could set smie-indent-basic instead, but that would have two
424 ;; disadvantages:
425 ;; - changes to octave-block-offset wouldn't take effect immediately.
426 ;; - edebug wouldn't show the use of this variable.
427 (`(:elem . basic) octave-block-offset)
428 ;; Since "case" is in the same BNF rules as switch..end, SMIE by default
429 ;; aligns it with "switch".
430 (`(:before . "case") (if (not (smie-rule-sibling-p)) octave-block-offset))
431 (`(:after . ";")
432 (if (smie-rule-parent-p "classdef" "events" "enumeration" "function" "if"
433 "while" "else" "elseif" "for" "parfor"
434 "properties" "methods" "otherwise" "case"
435 "try" "catch" "unwind_protect"
436 "unwind_protect_cleanup")
437 (smie-rule-parent octave-block-offset)
438 ;; For (invalid) code between switch and case.
439 ;; (if (smie-parent-p "switch") 4)
440 nil))))
441
442(defun octave-indent-comment ()
443 "A function for `smie-indent-functions' (which see)."
444 (save-excursion
445 (back-to-indentation)
446 (cond
447 ((octave-in-string-or-comment-p) nil)
448 ((looking-at-p "\\(\\s<\\)\\1\\{2,\\}")
449 0)
450 ;; Exclude %{, %} and %!.
451 ((and (looking-at-p "\\s<\\(?:[^{}!]\\|$\\)")
452 (not (looking-at-p "\\(\\s<\\)\\1")))
453 (comment-choose-indent)))))
454
455
456(defvar octave-font-lock-keywords
457 (list
458 ;; Fontify all builtin keywords.
459 (cons (concat "\\_<\\("
460 (regexp-opt octave-reserved-words)
461 "\\)\\_>")
462 'font-lock-keyword-face)
463 ;; Note: 'end' also serves as the last index in an indexing expression.
464 ;; Ref: http://www.mathworks.com/help/matlab/ref/end.html
465 (list (lambda (limit)
466 (while (re-search-forward "\\_<end\\_>" limit 'move)
467 (let ((beg (match-beginning 0))
468 (end (match-end 0)))
469 (unless (octave-in-string-or-comment-p)
470 (condition-case nil
471 (progn
472 (goto-char beg)
473 (backward-up-list)
474 (when (memq (char-after) '(?\( ?\[ ?\{))
475 (put-text-property beg end 'face nil))
476 (goto-char end))
477 (error (goto-char end))))))
478 nil))
479 ;; Fontify all operators.
480 (cons octave-operator-regexp 'font-lock-builtin-face)
481 ;; Fontify all function declarations.
482 (list octave-function-header-regexp
483 '(1 font-lock-keyword-face)
484 '(3 font-lock-function-name-face nil t)))
485 "Additional Octave expressions to highlight.")
486
487(defun octave-syntax-propertize-function (start end)
488 (goto-char start)
489 (octave-syntax-propertize-sqs end)
490 (funcall (syntax-propertize-rules
491 ("\\\\" (0 (when (eq (nth 3 (save-excursion
492 (syntax-ppss (match-beginning 0))))
493 ?\")
494 (string-to-syntax "\\"))))
495 ;; Try to distinguish the string-quotes from the transpose-quotes.
496 ("\\(?:^\\|[[({,; ]\\)\\('\\)"
497 (1 (prog1 "\"'" (octave-syntax-propertize-sqs end)))))
498 (point) end))
499
500(defun octave-syntax-propertize-sqs (end)
501 "Propertize the content/end of single-quote strings."
502 (when (eq (nth 3 (syntax-ppss)) ?\')
503 ;; A '..' string.
504 (when (re-search-forward
505 "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)\\($\\|[^']\\)" end 'move)
506 (goto-char (match-beginning 2))
507 (when (eq (char-before (match-beginning 1)) ?\\)
508 ;; Backslash cannot escape a single quote.
509 (put-text-property (1- (match-beginning 1)) (match-beginning 1)
510 'syntax-table (string-to-syntax ".")))
511 (put-text-property (match-beginning 1) (match-end 1)
512 'syntax-table (string-to-syntax "\"'")))))
513
514(defvar electric-layout-rules)
515
516;;;###autoload
517(define-derived-mode octave-mode prog-mode "Octave"
518 "Major mode for editing Octave code.
519
520Octave is a high-level language, primarily intended for numerical
521computations. It provides a convenient command line interface
522for solving linear and nonlinear problems numerically. Function
523definitions can also be stored in files and used in batch mode."
524 :abbrev-table octave-abbrev-table
525
526 (smie-setup octave-smie-grammar #'octave-smie-rules
527 :forward-token #'octave-smie-forward-token
528 :backward-token #'octave-smie-backward-token)
529 (setq-local smie-indent-basic 'octave-block-offset)
530 (add-hook 'smie-indent-functions #'octave-indent-comment nil t)
531
532 (setq-local smie-blink-matching-triggers
533 (cons ?\; smie-blink-matching-triggers))
534 (unless octave-blink-matching-block
535 (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
536
537 (setq-local electric-indent-chars
538 (cons ?\; electric-indent-chars))
539 ;; IIUC matlab-mode takes the opposite approach: it makes RET insert
540 ;; a ";" at those places where it's correct (i.e. outside of parens).
541 (setq-local electric-layout-rules '((?\; . after)))
542
543 (setq-local comment-start octave-comment-start)
544 (setq-local comment-end "")
545 (setq-local comment-start-skip octave-comment-start-skip)
546 (setq-local comment-add 1)
547
548 (setq-local parse-sexp-ignore-comments t)
549 (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter))
550 (setq-local paragraph-separate paragraph-start)
551 (setq-local paragraph-ignore-fill-prefix t)
552 (setq-local fill-paragraph-function 'octave-fill-paragraph)
553
554 (setq-local fill-nobreak-predicate
555 (lambda () (eq (octave-in-string-p) ?')))
556 (add-function :around (local 'comment-line-break-function)
557 #'octave--indent-new-comment-line)
558
559 (setq font-lock-defaults '(octave-font-lock-keywords))
560
561 (setq-local syntax-propertize-function #'octave-syntax-propertize-function)
562
563 (setq-local imenu-generic-expression octave-mode-imenu-generic-expression)
564 (setq-local imenu-case-fold-search nil)
565
566 (add-hook 'completion-at-point-functions 'octave-completion-at-point nil t)
567 (add-hook 'before-save-hook 'octave-sync-function-file-names nil t)
568 (setq-local beginning-of-defun-function 'octave-beginning-of-defun)
569 (and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment))
570 (setq-local eldoc-documentation-function 'octave-eldoc-function)
571
572 (easy-menu-add octave-mode-menu))
573
574
575(defcustom inferior-octave-program "octave"
576 "Program invoked by `inferior-octave'."
577 :type 'string
578 :group 'octave)
579
580(defcustom inferior-octave-buffer "*Inferior Octave*"
581 "Name of buffer for running an inferior Octave process."
582 :type 'string
583 :group 'octave)
584
585(defcustom inferior-octave-prompt
586 "\\(^octave\\(\\|.bin\\|.exe\\)\\(-[.0-9]+\\)?\\(:[0-9]+\\)?\\|^debug\\|^\\)>+ "
587 "Regexp to match prompts for the inferior Octave process."
588 :type 'regexp
589 :group 'octave)
590
591(defcustom inferior-octave-prompt-read-only comint-prompt-read-only
592 "If non-nil, the Octave prompt is read only.
593See `comint-prompt-read-only' for details."
594 :type 'boolean
595 :group 'octave
596 :version "24.4")
597
598(defcustom inferior-octave-startup-file
599 (convert-standard-filename
600 (concat "~/.emacs-" (file-name-nondirectory inferior-octave-program)))
601 "Name of the inferior Octave startup file.
602The contents of this file are sent to the inferior Octave process on
603startup."
604 :type '(choice (const :tag "None" nil) file)
605 :group 'octave
606 :version "24.4")
607
608(defcustom inferior-octave-startup-args nil
609 "List of command line arguments for the inferior Octave process.
610For example, for suppressing the startup message and using `traditional'
611mode, set this to (\"-q\" \"--traditional\")."
612 :type '(repeat string)
613 :group 'octave)
614
615(defcustom inferior-octave-mode-hook nil
616 "Hook to be run when Inferior Octave mode is started."
617 :type 'hook
618 :group 'octave)
619
620(defvar inferior-octave-process nil)
621
622(defvar inferior-octave-mode-map
623 (let ((map (make-sparse-keymap)))
624 (set-keymap-parent map comint-mode-map)
625 (define-key map "\M-." 'octave-find-definition)
626 (define-key map "\t" 'completion-at-point)
627 (define-key map "\C-hd" 'octave-help)
628 ;; Same as in `shell-mode'.
629 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
630 (define-key map "\C-c\C-l" 'inferior-octave-dynamic-list-input-ring)
631 (define-key map [menu-bar inout list-history]
632 '("List Input History" . inferior-octave-dynamic-list-input-ring))
633 map)
634 "Keymap used in Inferior Octave mode.")
635
636(defvar inferior-octave-mode-syntax-table
637 (let ((table (make-syntax-table octave-mode-syntax-table)))
638 table)
639 "Syntax table in use in inferior-octave-mode buffers.")
640
641(defvar inferior-octave-font-lock-keywords
642 (list
643 (cons inferior-octave-prompt 'font-lock-type-face))
644 ;; Could certainly do more font locking in inferior Octave ...
645 "Additional expressions to highlight in Inferior Octave mode.")
646
647(defvar inferior-octave-output-list nil)
648(defvar inferior-octave-output-string nil)
649(defvar inferior-octave-receive-in-progress nil)
650
651(define-obsolete-variable-alias 'inferior-octave-startup-hook
652 'inferior-octave-mode-hook "24.4")
653
654(defvar inferior-octave-dynamic-complete-functions
655 '(inferior-octave-completion-at-point comint-filename-completion)
656 "List of functions called to perform completion for inferior Octave.
657This variable is used to initialize `comint-dynamic-complete-functions'
658in the Inferior Octave buffer.")
659
660(defvar info-lookup-mode)
661
662(define-derived-mode inferior-octave-mode comint-mode "Inferior Octave"
663 "Major mode for interacting with an inferior Octave process."
664 :abbrev-table octave-abbrev-table
665 (setq comint-prompt-regexp inferior-octave-prompt)
666
667 (setq-local comment-start octave-comment-start)
668 (setq-local comment-end "")
669 (setq comment-column 32)
670 (setq-local comment-start-skip octave-comment-start-skip)
671
672 (setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
673
674 (setq-local info-lookup-mode 'octave-mode)
675 (setq-local eldoc-documentation-function 'octave-eldoc-function)
676
677 (setq comint-input-ring-file-name
678 (or (getenv "OCTAVE_HISTFILE") "~/.octave_hist")
679 comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024))
680 (setq-local comint-dynamic-complete-functions
681 inferior-octave-dynamic-complete-functions)
682 (setq-local comint-prompt-read-only inferior-octave-prompt-read-only)
683 (add-hook 'comint-input-filter-functions
684 'inferior-octave-directory-tracker nil t)
685 ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
686 (add-hook 'window-configuration-change-hook
687 'inferior-octave-track-window-width-change nil t)
688 (comint-read-input-ring t))
689
690;;;###autoload
691(defun inferior-octave (&optional arg)
692 "Run an inferior Octave process, I/O via `inferior-octave-buffer'.
693This buffer is put in Inferior Octave mode. See `inferior-octave-mode'.
694
695Unless ARG is non-nil, switches to this buffer.
696
697The elements of the list `inferior-octave-startup-args' are sent as
698command line arguments to the inferior Octave process on startup.
699
700Additional commands to be executed on startup can be provided either in
701the file specified by `inferior-octave-startup-file' or by the default
702startup file, `~/.emacs-octave'."
703 (interactive "P")
704 (let ((buffer (get-buffer-create inferior-octave-buffer)))
705 (unless arg
706 (pop-to-buffer buffer))
707 (unless (comint-check-proc buffer)
708 (with-current-buffer buffer
709 (inferior-octave-startup)
710 (inferior-octave-mode)))
711 buffer))
712
713;;;###autoload
714(defalias 'run-octave 'inferior-octave)
715
716(defun inferior-octave-startup ()
717 "Start an inferior Octave process."
718 (let ((proc (comint-exec-1
719 (substring inferior-octave-buffer 1 -1)
720 inferior-octave-buffer
721 inferior-octave-program
722 (append (list "-i" "--no-line-editing")
723 ;; --no-gui is introduced in Octave > 3.7
724 (when (zerop (process-file inferior-octave-program
725 nil nil nil
726 "--no-gui" "--help"))
727 (list "--no-gui"))
728 inferior-octave-startup-args))))
729 (set-process-filter proc 'inferior-octave-output-digest)
730 (setq inferior-octave-process proc
731 inferior-octave-output-list nil
732 inferior-octave-output-string nil
733 inferior-octave-receive-in-progress t)
734
735 ;; This may look complicated ... However, we need to make sure that
736 ;; we additional startup code only AFTER Octave is ready (otherwise,
737 ;; output may be mixed up). Hence, we need to digest the Octave
738 ;; output to see when it issues a prompt.
739 (while inferior-octave-receive-in-progress
740 (or (process-live-p inferior-octave-process)
741 (error "Process `%s' died" inferior-octave-process))
742 (accept-process-output inferior-octave-process))
743 (goto-char (point-max))
744 (set-marker (process-mark proc) (point))
745 (insert-before-markers
746 (concat
747 (if (not (bobp)) " \n")
748 (if inferior-octave-output-list
749 (concat (mapconcat
750 'identity inferior-octave-output-list "\n")
751 "\n"))))
752
753 ;; An empty secondary prompt, as e.g. obtained by '--braindead',
754 ;; means trouble.
755 (inferior-octave-send-list-and-digest (list "PS2\n"))
756 (when (string-match "\\(PS2\\|ans\\) = *$"
757 (car inferior-octave-output-list))
758 (inferior-octave-send-list-and-digest (list "PS2 (\"> \");\n")))
759
760 (inferior-octave-send-list-and-digest
761 (list "disp(getenv(\"OCTAVE_SRCDIR\"))\n"))
762 (process-put proc 'octave-srcdir
763 (unless (equal (car inferior-octave-output-list) "")
764 (car inferior-octave-output-list)))
765
766 ;; O.K., now we are ready for the Inferior Octave startup commands.
767 (inferior-octave-send-list-and-digest
768 (list "more off;\n"
769 (unless (equal inferior-octave-output-string ">> ")
770 "PS1 (\"\\\\s> \");\n")
771 (when (and inferior-octave-startup-file
772 (file-exists-p inferior-octave-startup-file))
773 (format "source (\"%s\");\n" inferior-octave-startup-file))))
774 (when inferior-octave-output-list
775 (insert-before-markers
776 (mapconcat 'identity inferior-octave-output-list "\n")))
777
778 ;; And finally, everything is back to normal.
779 (set-process-filter proc 'comint-output-filter)
780 ;; Just in case, to be sure a cd in the startup file
781 ;; won't have detrimental effects.
782 (inferior-octave-resync-dirs)
783 ;; Generate a proper prompt, which is critical to
784 ;; `comint-history-isearch-backward-regexp'. Bug#14433.
785 (comint-send-string proc "\n")))
786
787(defvar inferior-octave-completion-table
788 ;;
789 ;; Use cache to avoid repetitive computation of completions due to
790 ;; bug#11906 - http://debbugs.gnu.org/11906 - which may cause
791 ;; noticeable delay. CACHE: (CMD TIME VALUE).
792 (let ((cache))
793 (completion-table-dynamic
794 (lambda (command)
795 (unless (and (equal (car cache) command)
796 (< (float-time) (+ 5 (cadr cache))))
797 (inferior-octave-send-list-and-digest
798 (list (concat "completion_matches (\"" command "\");\n")))
799 (setq cache (list command (float-time)
800 (delete-consecutive-dups
801 (sort inferior-octave-output-list 'string-lessp)))))
802 (car (cddr cache))))))
803
804(defun inferior-octave-completion-at-point ()
805 "Return the data to complete the Octave symbol at point."
806 ;; http://debbugs.gnu.org/14300
807 (let* ((filecomp (string-match-p
808 "/" (or (comint--match-partial-filename) "")))
809 (end (point))
810 (start
811 (unless filecomp
812 (save-excursion
813 (skip-syntax-backward "w_" (comint-line-beginning-position))
814 (point)))))
815 (when (and start (> end start))
816 (list start end (completion-table-in-turn
817 inferior-octave-completion-table
818 'comint-completion-file-name-table)))))
819
820(define-obsolete-function-alias 'inferior-octave-complete
821 'completion-at-point "24.1")
822
823(defun inferior-octave-dynamic-list-input-ring ()
824 "List the buffer's input history in a help buffer."
825 ;; We cannot use `comint-dynamic-list-input-ring', because it replaces
826 ;; "completion" by "history reference" ...
827 (interactive)
828 (if (or (not (ring-p comint-input-ring))
829 (ring-empty-p comint-input-ring))
830 (message "No history")
831 (let ((history nil)
832 (history-buffer " *Input History*")
833 (index (1- (ring-length comint-input-ring)))
834 (conf (current-window-configuration)))
835 ;; We have to build up a list ourselves from the ring vector.
836 (while (>= index 0)
837 (setq history (cons (ring-ref comint-input-ring index) history)
838 index (1- index)))
839 ;; Change "completion" to "history reference"
840 ;; to make the display accurate.
841 (with-output-to-temp-buffer history-buffer
842 (display-completion-list history)
843 (set-buffer history-buffer))
844 (message "Hit space to flush")
845 (let ((ch (read-event)))
846 (if (eq ch ?\ )
847 (set-window-configuration conf)
848 (setq unread-command-events (list ch)))))))
849
850(defun inferior-octave-output-digest (_proc string)
851 "Special output filter for the inferior Octave process.
852Save all output between newlines into `inferior-octave-output-list', and
853the rest to `inferior-octave-output-string'."
854 (setq string (concat inferior-octave-output-string string))
855 (while (string-match "\n" string)
856 (setq inferior-octave-output-list
857 (append inferior-octave-output-list
858 (list (substring string 0 (match-beginning 0))))
859 string (substring string (match-end 0))))
860 (if (string-match inferior-octave-prompt string)
861 (setq inferior-octave-receive-in-progress nil))
862 (setq inferior-octave-output-string string))
863
864(defun inferior-octave-check-process ()
865 (or (and inferior-octave-process
866 (process-live-p inferior-octave-process))
867 (error (substitute-command-keys
868 "No inferior octave process running. Type \\[run-octave]"))))
869
870(defun inferior-octave-send-list-and-digest (list)
871 "Send LIST to the inferior Octave process and digest the output.
872The elements of LIST have to be strings and are sent one by one. All
873output is passed to the filter `inferior-octave-output-digest'."
874 (inferior-octave-check-process)
875 (let* ((proc inferior-octave-process)
876 (filter (process-filter proc))
877 string)
878 (set-process-filter proc 'inferior-octave-output-digest)
879 (setq inferior-octave-output-list nil)
880 (unwind-protect
881 (while (setq string (car list))
882 (setq inferior-octave-output-string nil
883 inferior-octave-receive-in-progress t)
884 (comint-send-string proc string)
885 (while inferior-octave-receive-in-progress
886 (accept-process-output proc))
887 (setq list (cdr list)))
888 (set-process-filter proc filter))))
889
890(defvar inferior-octave-directory-tracker-resync nil)
891(make-variable-buffer-local 'inferior-octave-directory-tracker-resync)
892
893(defun inferior-octave-directory-tracker (string)
894 "Tracks `cd' commands issued to the inferior Octave process.
895Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused."
896 (when inferior-octave-directory-tracker-resync
897 (setq inferior-octave-directory-tracker-resync nil)
898 (inferior-octave-resync-dirs))
899 (cond
900 ((string-match "^[ \t]*cd[ \t;]*$" string)
901 (cd "~"))
902 ((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
903 (condition-case err
904 (cd (match-string 1 string))
905 (error (setq inferior-octave-directory-tracker-resync t)
906 (message "%s: `%s'"
907 (error-message-string err)
908 (match-string 1 string)))))))
909
910(defun inferior-octave-resync-dirs ()
911 "Resync the buffer's idea of the current directory.
912This command queries the inferior Octave process about its current
913directory and makes this the current buffer's default directory."
914 (interactive)
915 (inferior-octave-send-list-and-digest '("disp (pwd ())\n"))
916 (cd (car inferior-octave-output-list)))
917
918(defcustom inferior-octave-minimal-columns 80
919 "The minimal column width for the inferior Octave process."
920 :type 'integer
921 :group 'octave
922 :version "24.4")
923
924(defvar inferior-octave-last-column-width nil)
925
926(defun inferior-octave-track-window-width-change ()
927 ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
928 (let ((width (max inferior-octave-minimal-columns (window-width))))
929 (unless (eq inferior-octave-last-column-width width)
930 (setq-local inferior-octave-last-column-width width)
931 (when (and inferior-octave-process
932 (process-live-p inferior-octave-process))
933 (inferior-octave-send-list-and-digest
934 (list (format "putenv(\"COLUMNS\", \"%s\");\n" width)))))))
935
936
937;;; Miscellaneous useful functions
938
939(defun octave-in-comment-p ()
940 "Return non-nil if point is inside an Octave comment."
941 (nth 4 (syntax-ppss)))
942
943(defun octave-in-string-p ()
944 "Return non-nil if point is inside an Octave string."
945 (nth 3 (syntax-ppss)))
946
947(defun octave-in-string-or-comment-p ()
948 "Return non-nil if point is inside an Octave string or comment."
949 (nth 8 (syntax-ppss)))
950
951(defun octave-looking-at-kw (regexp)
952 "Like `looking-at', but sets `case-fold-search' nil."
953 (let ((case-fold-search nil))
954 (looking-at regexp)))
955
956(defun octave-maybe-insert-continuation-string ()
957 (if (or (octave-in-comment-p)
958 (save-excursion
959 (beginning-of-line)
960 (looking-at octave-continuation-regexp)))
961 nil
962 (delete-horizontal-space)
963 (insert (concat " " octave-continuation-string))))
964
965(defun octave-completing-read ()
966 (let ((def (or (thing-at-point 'symbol)
967 (save-excursion
968 (skip-syntax-backward "-(")
969 (thing-at-point 'symbol)))))
970 (completing-read
971 (format (if def "Function (default %s): "
972 "Function: ") def)
973 inferior-octave-completion-table
974 nil nil nil nil def)))
975
976(defun octave-goto-function-definition (fn)
977 "Go to the function definition of FN in current buffer."
978 (goto-char (point-min))
979 (let ((search
980 (lambda (re sub)
981 (let (done)
982 (while (and (not done) (re-search-forward re nil t))
983 (when (and (equal (match-string sub) fn)
984 (not (nth 8 (syntax-ppss))))
985 (setq done t)))
986 (or done (goto-char (point-min)))))))
987 (pcase (file-name-extension (buffer-file-name))
988 (`"cc" (funcall search
989 "\\_<DEFUN\\(?:_DLD\\)?\\s-*(\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)" 1))
990 (t (funcall search octave-function-header-regexp 3)))))
991
992(defun octave-function-file-p ()
993 "Return non-nil if the first token is \"function\".
994The value is (START END NAME-START NAME-END) of the function."
995 (save-excursion
996 (goto-char (point-min))
997 (when (equal (funcall smie-forward-token-function) "function")
998 (forward-word -1)
999 (let* ((start (point))
1000 (end (progn (forward-sexp 1) (point)))
1001 (name (when (progn
1002 (goto-char start)
1003 (re-search-forward octave-function-header-regexp
1004 end t))
1005 (list (match-beginning 3) (match-end 3)))))
1006 (cons start (cons end name))))))
1007
1008;; Like forward-comment but stop at non-comment blank
1009(defun octave-skip-comment-forward (limit)
1010 (let ((ppss (syntax-ppss)))
1011 (if (nth 4 ppss)
1012 (goto-char (nth 8 ppss))
1013 (goto-char (or (comment-search-forward limit t) (point)))))
1014 (while (and (< (point) limit) (looking-at-p "\\s<"))
1015 (forward-comment 1)))
1016
1017;;; First non-copyright comment block
1018(defun octave-function-file-comment ()
1019 "Beginning and end positions of the function file comment."
1020 (save-excursion
1021 (goto-char (point-min))
1022 ;; Copyright block: octave/libinterp/parse-tree/lex.ll around line 1634
1023 (while (save-excursion
1024 (when (comment-search-forward (point-max) t)
1025 (when (eq (char-after) ?\{) ; case of block comment
1026 (forward-char 1))
1027 (skip-syntax-forward "-")
1028 (let ((case-fold-search t))
1029 (looking-at-p "\\(?:copyright\\|author\\)\\_>"))))
1030 (octave-skip-comment-forward (point-max)))
1031 (let ((beg (comment-search-forward (point-max) t)))
1032 (when beg
1033 (goto-char beg)
1034 (octave-skip-comment-forward (point-max))
1035 (list beg (point))))))
1036
1037(defun octave-sync-function-file-names ()
1038 "Ensure function name agree with function file name.
1039See Info node `(octave)Function Files'."
1040 (interactive)
1041 (when buffer-file-name
1042 (pcase-let ((`(,start ,_end ,name-start ,name-end)
1043 (octave-function-file-p)))
1044 (when (and start name-start)
1045 (let* ((func (buffer-substring name-start name-end))
1046 (file (file-name-sans-extension
1047 (file-name-nondirectory buffer-file-name)))
1048 (help-form (format "\
1049a: Use function name `%s'
1050b: Use file name `%s'
1051q: Don't fix\n" func file))
1052 (c (unless (equal file func)
1053 (save-window-excursion
1054 (help-form-show)
1055 (read-char-choice
1056 "Which name to use? (a/b/q) " '(?a ?b ?q))))))
1057 (pcase c
1058 (`?a (let ((newname (expand-file-name
1059 (concat func (file-name-extension
1060 buffer-file-name t)))))
1061 (when (or (not (file-exists-p newname))
1062 (yes-or-no-p
1063 (format "Target file %s exists; proceed? " newname)))
1064 (when (file-exists-p buffer-file-name)
1065 (rename-file buffer-file-name newname t))
1066 (set-visited-file-name newname))))
1067 (`?b (save-excursion
1068 (goto-char name-start)
1069 (delete-region name-start name-end)
1070 (insert file)))))))))
1071
1072(defun octave-update-function-file-comment (beg end)
1073 "Query replace function names in function file comment."
1074 (interactive
1075 (progn
1076 (barf-if-buffer-read-only)
1077 (if (use-region-p)
1078 (list (region-beginning) (region-end))
1079 (or (octave-function-file-comment)
1080 (error "No function file comment found")))))
1081 (save-excursion
1082 (let* ((bounds (or (octave-function-file-p)
1083 (error "Not in a function file buffer")))
1084 (func (if (cddr bounds)
1085 (apply #'buffer-substring (cddr bounds))
1086 (error "Function name not found")))
1087 (old-func (progn
1088 (goto-char beg)
1089 (when (re-search-forward
1090 "[=}]\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>"
1091 (min (line-end-position 4) end)
1092 t)
1093 (match-string 1))))
1094 (old-func (read-string (format (if old-func
1095 "Name to replace (default %s): "
1096 "Name to replace: ")
1097 old-func)
1098 nil nil old-func)))
1099 (if (and func old-func (not (equal func old-func)))
1100 (perform-replace old-func func 'query
1101 nil 'delimited nil nil beg end)
1102 (message "Function names match")))))
1103
1104(defface octave-function-comment-block
1105 '((t (:inherit font-lock-doc-face)))
1106 "Face used to highlight function comment block."
1107 :group 'octave)
1108
1109(eval-when-compile (require 'texinfo))
1110
1111(defun octave-font-lock-texinfo-comment ()
1112 (let ((kws
1113 (eval-when-compile
1114 (delq nil (mapcar
1115 (lambda (kw)
1116 (if (numberp (nth 1 kw))
1117 `(,(nth 0 kw) ,(nth 1 kw) ,(nth 2 kw) prepend)
1118 (message "Ignoring Texinfo highlight: %S" kw)))
1119 texinfo-font-lock-keywords)))))
1120 (font-lock-add-keywords
1121 nil
1122 `((,(lambda (limit)
1123 (while (and (< (point) limit)
1124 (search-forward "-*- texinfo -*-" limit t)
1125 (octave-in-comment-p))
1126 (let ((beg (nth 8 (syntax-ppss)))
1127 (end (progn
1128 (octave-skip-comment-forward (point-max))
1129 (point))))
1130 (put-text-property beg end 'font-lock-multiline t)
1131 (font-lock-prepend-text-property
1132 beg end 'face 'octave-function-comment-block)
1133 (dolist (kw kws)
1134 (goto-char beg)
1135 (while (re-search-forward (car kw) end 'move)
1136 (font-lock-apply-highlight (cdr kw))))))
1137 nil)))
1138 'append)))
1139
1140
1141;;; Indentation
1142
1143(defun octave-indent-new-comment-line (&optional soft)
1144 ;; FIXME: C-M-j should probably be bound globally to a function like
1145 ;; this one.
1146 "Break Octave line at point, continuing comment if within one.
1147Insert `octave-continuation-string' before breaking the line
1148unless inside a list. Signal an error if within a single-quoted
1149string."
1150 (interactive)
1151 (funcall comment-line-break-function soft))
1152
1153(defun octave--indent-new-comment-line (orig &rest args)
1154 (cond
1155 ((octave-in-comment-p) nil)
1156 ((eq (octave-in-string-p) ?')
1157 (error "Cannot split a single-quoted string"))
1158 ((eq (octave-in-string-p) ?\")
1159 (insert octave-continuation-string))
1160 (t
1161 (delete-horizontal-space)
1162 (unless (and (cadr (syntax-ppss))
1163 (eq (char-after (cadr (syntax-ppss))) ?\())
1164 (insert " " octave-continuation-string))))
1165 (apply orig args)
1166 (indent-according-to-mode))
1167
1168(define-obsolete-function-alias
1169 'octave-indent-defun 'prog-indent-sexp "24.4")
1170
1171
1172;;; Motion
1173(defun octave-next-code-line (&optional arg)
1174 "Move ARG lines of Octave code forward (backward if ARG is negative).
1175Skips past all empty and comment lines. Default for ARG is 1.
1176
1177On success, return 0. Otherwise, go as far as possible and return -1."
1178 (interactive "p")
1179 (or arg (setq arg 1))
1180 (beginning-of-line)
1181 (let ((n 0)
1182 (inc (if (> arg 0) 1 -1)))
1183 (while (and (/= arg 0) (= n 0))
1184 (setq n (forward-line inc))
1185 (while (and (= n 0)
1186 (looking-at "\\s-*\\($\\|\\s<\\)"))
1187 (setq n (forward-line inc)))
1188 (setq arg (- arg inc)))
1189 n))
1190
1191(defun octave-previous-code-line (&optional arg)
1192 "Move ARG lines of Octave code backward (forward if ARG is negative).
1193Skips past all empty and comment lines. Default for ARG is 1.
1194
1195On success, return 0. Otherwise, go as far as possible and return -1."
1196 (interactive "p")
1197 (or arg (setq arg 1))
1198 (octave-next-code-line (- arg)))
1199
1200(defun octave-beginning-of-line ()
1201 "Move point to beginning of current Octave line.
1202If on an empty or comment line, go to the beginning of that line.
1203Otherwise, move backward to the beginning of the first Octave code line
1204which is not inside a continuation statement, i.e., which does not
1205follow a code line ending with `...' or is inside an open
1206parenthesis list."
1207 (interactive)
1208 (beginning-of-line)
1209 (unless (looking-at "\\s-*\\($\\|\\s<\\)")
1210 (while (or (when (cadr (syntax-ppss))
1211 (goto-char (cadr (syntax-ppss)))
1212 (beginning-of-line)
1213 t)
1214 (and (or (looking-at "\\s-*\\($\\|\\s<\\)")
1215 (save-excursion
1216 (if (zerop (octave-previous-code-line))
1217 (looking-at octave-continuation-regexp))))
1218 (zerop (forward-line -1)))))))
1219
1220(defun octave-end-of-line ()
1221 "Move point to end of current Octave line.
1222If on an empty or comment line, go to the end of that line.
1223Otherwise, move forward to the end of the first Octave code line which
1224does not end with `...' or is inside an open parenthesis list."
1225 (interactive)
1226 (end-of-line)
1227 (unless (save-excursion
1228 (beginning-of-line)
1229 (looking-at "\\s-*\\($\\|\\s<\\)"))
1230 (while (or (when (cadr (syntax-ppss))
1231 (condition-case nil
1232 (progn
1233 (up-list 1)
1234 (end-of-line)
1235 t)
1236 (error nil)))
1237 (and (save-excursion
1238 (beginning-of-line)
1239 (or (looking-at "\\s-*\\($\\|\\s<\\)")
1240 (looking-at octave-continuation-regexp)))
1241 (zerop (forward-line 1)))))
1242 (end-of-line)))
1243
1244(defun octave-mark-block ()
1245 "Put point at the beginning of this Octave block, mark at the end.
1246The block marked is the one that contains point or follows point."
1247 (interactive)
1248 (if (and (looking-at "\\sw\\|\\s_")
1249 (looking-back "\\sw\\|\\s_" (1- (point))))
1250 (skip-syntax-forward "w_"))
1251 (unless (or (looking-at "\\s(")
1252 (save-excursion
1253 (let* ((token (funcall smie-forward-token-function))
1254 (level (assoc token smie-grammar)))
1255 (and level (not (numberp (cadr level)))))))
1256 (backward-up-list 1))
1257 (mark-sexp))
1258
1259(defun octave-beginning-of-defun (&optional arg)
1260 "Octave-specific `beginning-of-defun-function' (which see)."
1261 (or arg (setq arg 1))
1262 ;; Move out of strings or comments.
1263 (when (octave-in-string-or-comment-p)
1264 (goto-char (octave-in-string-or-comment-p)))
1265 (letrec ((orig (point))
1266 (toplevel (lambda (pos)
1267 (condition-case nil
1268 (progn
1269 (backward-up-list 1)
1270 (funcall toplevel (point)))
1271 (scan-error pos)))))
1272 (goto-char (funcall toplevel (point)))
1273 (when (and (> arg 0) (/= orig (point)))
1274 (setq arg (1- arg)))
1275 (forward-sexp (- arg))
1276 (and (< arg 0) (forward-sexp -1))
1277 (/= orig (point))))
1278
1279(defun octave-fill-paragraph (&optional _arg)
1280 "Fill paragraph of Octave code, handling Octave comments."
1281 ;; FIXME: difference with generic fill-paragraph:
1282 ;; - code lines are only split, never joined.
1283 ;; - \n that end comments are never removed.
1284 ;; - insert continuation marker when splitting code lines.
1285 (interactive "P")
1286 (save-excursion
1287 (let ((end (progn (forward-paragraph) (copy-marker (point) t)))
1288 (beg (progn
1289 (forward-paragraph -1)
1290 (skip-chars-forward " \t\n")
1291 (beginning-of-line)
1292 (point)))
1293 (cfc (current-fill-column))
1294 comment-prefix)
1295 (goto-char beg)
1296 (while (< (point) end)
1297 (condition-case nil
1298 (indent-according-to-mode)
1299 (error nil))
1300 (move-to-column cfc)
1301 ;; First check whether we need to combine non-empty comment lines
1302 (if (and (< (current-column) cfc)
1303 (octave-in-comment-p)
1304 (not (save-excursion
1305 (beginning-of-line)
1306 (looking-at "^\\s-*\\s<+\\s-*$"))))
1307 ;; This is a nonempty comment line which does not extend
1308 ;; past the fill column. If it is followed by a nonempty
1309 ;; comment line with the same comment prefix, try to
1310 ;; combine them, and repeat this until either we reach the
1311 ;; fill-column or there is nothing more to combine.
1312 (progn
1313 ;; Get the comment prefix
1314 (save-excursion
1315 (beginning-of-line)
1316 (while (and (re-search-forward "\\s<+")
1317 (not (octave-in-comment-p))))
1318 (setq comment-prefix (match-string 0)))
1319 ;; And keep combining ...
1320 (while (and (< (current-column) cfc)
1321 (save-excursion
1322 (forward-line 1)
1323 (and (looking-at
1324 (concat "^\\s-*"
1325 comment-prefix
1326 "\\S<"))
1327 (not (looking-at
1328 (concat "^\\s-*"
1329 comment-prefix
1330 "\\s-*$"))))))
1331 (delete-char 1)
1332 (re-search-forward comment-prefix)
1333 (delete-region (match-beginning 0) (match-end 0))
1334 (fixup-whitespace)
1335 (move-to-column cfc))))
1336 ;; We might also try to combine continued code lines> Perhaps
1337 ;; some other time ...
1338 (skip-chars-forward "^ \t\n")
1339 (delete-horizontal-space)
1340 (if (or (< (current-column) cfc)
1341 (and (= (current-column) cfc) (eolp)))
1342 (forward-line 1)
1343 (if (not (eolp)) (insert " "))
1344 (or (funcall normal-auto-fill-function)
1345 (forward-line 1))))
1346 t)))
1347
1348;;; Completions
1349
1350(defun octave-completion-at-point ()
1351 "Find the text to complete and the corresponding table."
1352 (let* ((beg (save-excursion (skip-syntax-backward "w_") (point)))
1353 (end (point)))
1354 (if (< beg (point))
1355 ;; Extend region past point, if applicable.
1356 (save-excursion (skip-syntax-forward "w_")
1357 (setq end (point))))
1358 (when (> end beg)
1359 (list beg end (or (and inferior-octave-process
1360 (process-live-p inferior-octave-process)
1361 inferior-octave-completion-table)
1362 octave-reserved-words)))))
1363
1364(define-obsolete-function-alias 'octave-complete-symbol
1365 'completion-at-point "24.1")
1366
1367;;; Electric characters && friends
1368(define-skeleton octave-insert-defun
1369 "Insert an Octave function skeleton.
1370Prompt for the function's name, arguments and return values (to be
1371entered without parens)."
1372 (let* ((defname (file-name-sans-extension (buffer-name)))
1373 (name (read-string (format "Function name (default %s): " defname)
1374 nil nil defname))
1375 (args (read-string "Arguments: "))
1376 (vals (read-string "Return values: ")))
1377 (format "%s%s (%s)"
1378 (cond
1379 ((string-equal vals "") vals)
1380 ((string-match "[ ,]" vals) (concat "[" vals "] = "))
1381 (t (concat vals " = ")))
1382 name
1383 args))
1384 \n octave-block-comment-start "usage: " str \n
1385 octave-block-comment-start '(delete-horizontal-space) \n
1386 octave-block-comment-start '(delete-horizontal-space) \n
1387 "function " > str \n
1388 _ \n
1389 "endfunction" > \n)
1390
1391;;; Communication with the inferior Octave process
1392(defun octave-kill-process ()
1393 "Kill inferior Octave process and its buffer."
1394 (interactive)
1395 (if inferior-octave-process
1396 (progn
1397 (process-send-string inferior-octave-process "quit;\n")
1398 (accept-process-output inferior-octave-process)))
1399 (if inferior-octave-buffer
1400 (kill-buffer inferior-octave-buffer)))
1401
1402(defun octave-show-process-buffer ()
1403 "Make sure that `inferior-octave-buffer' is displayed."
1404 (interactive)
1405 (if (get-buffer inferior-octave-buffer)
1406 (display-buffer inferior-octave-buffer)
1407 (message "No buffer named %s" inferior-octave-buffer)))
1408
1409(defun octave-hide-process-buffer ()
1410 "Delete all windows that display `inferior-octave-buffer'."
1411 (interactive)
1412 (if (get-buffer inferior-octave-buffer)
1413 (delete-windows-on inferior-octave-buffer)
1414 (message "No buffer named %s" inferior-octave-buffer)))
1415
1416(defun octave-send-region (beg end)
1417 "Send current region to the inferior Octave process."
1418 (interactive "r")
1419 (inferior-octave t)
1420 (let ((proc inferior-octave-process)
1421 (string (buffer-substring-no-properties beg end))
1422 line)
1423 (with-current-buffer inferior-octave-buffer
1424 (setq inferior-octave-output-list nil)
1425 (while (not (string-equal string ""))
1426 (if (string-match "\n" string)
1427 (setq line (substring string 0 (match-beginning 0))
1428 string (substring string (match-end 0)))
1429 (setq line string string ""))
1430 (setq inferior-octave-receive-in-progress t)
1431 (inferior-octave-send-list-and-digest (list (concat line "\n")))
1432 (while inferior-octave-receive-in-progress
1433 (accept-process-output proc))
1434 (insert-before-markers
1435 (mapconcat 'identity
1436 (append
1437 (if octave-send-echo-input (list line) (list ""))
1438 inferior-octave-output-list
1439 (list inferior-octave-output-string))
1440 "\n")))))
1441 (if octave-send-show-buffer
1442 (display-buffer inferior-octave-buffer)))
1443
1444(defun octave-send-block ()
1445 "Send current Octave block to the inferior Octave process."
1446 (interactive)
1447 (save-excursion
1448 (octave-mark-block)
1449 (octave-send-region (point) (mark))))
1450
1451(defun octave-send-defun ()
1452 "Send current Octave function to the inferior Octave process."
1453 (interactive)
1454 (save-excursion
1455 (mark-defun)
1456 (octave-send-region (point) (mark))))
1457
1458(defun octave-send-line (&optional arg)
1459 "Send current Octave code line to the inferior Octave process.
1460With positive prefix ARG, send that many lines.
1461If `octave-send-line-auto-forward' is non-nil, go to the next unsent
1462code line."
1463 (interactive "P")
1464 (or arg (setq arg 1))
1465 (if (> arg 0)
1466 (let (beg end)
1467 (beginning-of-line)
1468 (setq beg (point))
1469 (octave-next-code-line (- arg 1))
1470 (end-of-line)
1471 (setq end (point))
1472 (if octave-send-line-auto-forward
1473 (octave-next-code-line 1))
1474 (octave-send-region beg end))))
1475
1476(defun octave-eval-print-last-sexp ()
1477 "Evaluate Octave sexp before point and print value into current buffer."
1478 (interactive)
1479 (inferior-octave t)
1480 (let ((standard-output (current-buffer))
1481 (print-escape-newlines nil)
1482 (opoint (point)))
1483 (terpri)
1484 (prin1
1485 (save-excursion
1486 (forward-sexp -1)
1487 (inferior-octave-send-list-and-digest
1488 (list (concat (buffer-substring-no-properties (point) opoint)
1489 "\n")))
1490 (mapconcat 'identity inferior-octave-output-list "\n")))
1491 (terpri)))
1492
1493
1494
1495(defcustom octave-eldoc-message-style 'auto
1496 "Octave eldoc message style: auto, oneline, multiline."
1497 :type '(choice (const :tag "Automatic" auto)
1498 (const :tag "One Line" oneline)
1499 (const :tag "Multi Line" multiline))
1500 :group 'octave
1501 :version "24.4")
1502
1503;; (FN SIGNATURE1 SIGNATURE2 ...)
1504(defvar octave-eldoc-cache nil)
1505
1506(defun octave-eldoc-function-signatures (fn)
1507 (unless (equal fn (car octave-eldoc-cache))
1508 (inferior-octave-send-list-and-digest
1509 (list (format "\
1510if ismember(exist(\"%s\"), [2 3 5 103]) print_usage(\"%s\") endif\n"
1511 fn fn)))
1512 (let (result)
1513 (dolist (line inferior-octave-output-list)
1514 (when (string-match
1515 "\\s-*\\(?:--[^:]+\\|usage\\):\\s-*\\(.*\\)$"
1516 line)
1517 (push (match-string 1 line) result)))
1518 (setq octave-eldoc-cache
1519 (cons (substring-no-properties fn)
1520 (nreverse result)))))
1521 (cdr octave-eldoc-cache))
1522
1523(defun octave-eldoc-function ()
1524 "A function for `eldoc-documentation-function' (which see)."
1525 (when (and inferior-octave-process
1526 (process-live-p inferior-octave-process))
1527 (let* ((ppss (syntax-ppss))
1528 (paren-pos (cadr ppss))
1529 (fn (save-excursion
1530 (if (and paren-pos
1531 ;; PAREN-POS must be after the prompt
1532 (>= paren-pos
1533 (if (eq (get-buffer-process (current-buffer))
1534 inferior-octave-process)
1535 (process-mark inferior-octave-process)
1536 (point-min)))
1537 (or (not (eq (get-buffer-process (current-buffer))
1538 inferior-octave-process))
1539 (< (process-mark inferior-octave-process)
1540 paren-pos))
1541 (eq (char-after paren-pos) ?\())
1542 (goto-char paren-pos)
1543 (setq paren-pos nil))
1544 (when (or (< (skip-syntax-backward "-") 0) paren-pos)
1545 (thing-at-point 'symbol))))
1546 (sigs (and fn (octave-eldoc-function-signatures fn)))
1547 (oneline (mapconcat 'identity sigs
1548 (propertize " | " 'face 'warning)))
1549 (multiline (mapconcat (lambda (s) (concat "-- " s)) sigs "\n")))
1550 ;;
1551 ;; Return the value according to style.
1552 (pcase octave-eldoc-message-style
1553 (`auto (if (< (length oneline) (window-width (minibuffer-window)))
1554 oneline
1555 multiline))
1556 (`oneline oneline)
1557 (`multiline multiline)))))
1558
1559(defcustom octave-help-buffer "*Octave Help*"
1560 "Buffer name for `octave-help'."
1561 :type 'string
1562 :group 'octave
1563 :version "24.4")
1564
1565(define-button-type 'octave-help-file
1566 'follow-link t
1567 'action #'help-button-action
1568 'help-function 'octave-find-definition)
1569
1570(define-button-type 'octave-help-function
1571 'follow-link t
1572 'action (lambda (b)
1573 (octave-help
1574 (buffer-substring (button-start b) (button-end b)))))
1575
1576(defvar octave-help-mode-map
1577 (let ((map (make-sparse-keymap)))
1578 (define-key map "\M-." 'octave-find-definition)
1579 (define-key map "\C-hd" 'octave-help)
1580 map))
1581
1582(define-derived-mode octave-help-mode help-mode "OctHelp"
1583 "Major mode for displaying Octave documentation."
1584 :abbrev-table nil
1585 :syntax-table octave-mode-syntax-table
1586 (eval-and-compile (require 'help-mode))
1587 ;; Mostly stolen from `help-make-xrefs'.
1588 (let ((inhibit-read-only t))
1589 (setq-local info-lookup-mode 'octave-mode)
1590 ;; Delete extraneous newlines at the end of the docstring
1591 (goto-char (point-max))
1592 (while (and (not (bobp)) (bolp))
1593 (delete-char -1))
1594 (insert "\n")
1595 (when (or help-xref-stack help-xref-forward-stack)
1596 (insert "\n"))
1597 (when help-xref-stack
1598 (help-insert-xref-button help-back-label 'help-back
1599 (current-buffer)))
1600 (when help-xref-forward-stack
1601 (when help-xref-stack
1602 (insert "\t"))
1603 (help-insert-xref-button help-forward-label 'help-forward
1604 (current-buffer)))
1605 (when (or help-xref-stack help-xref-forward-stack)
1606 (insert "\n"))))
1607
1608(defvar octave-help-mode-finish-hook nil
1609 "Octave specific hook for `temp-buffer-show-hook'.")
1610
1611(defun octave-help-mode-finish ()
1612 (when (eq major-mode 'octave-help-mode)
1613 (run-hooks 'octave-help-mode-finish-hook)))
1614
1615(add-hook 'temp-buffer-show-hook 'octave-help-mode-finish)
1616
1617(defun octave-help (fn)
1618 "Display the documentation of FN."
1619 (interactive (list (octave-completing-read)))
1620 (inferior-octave-send-list-and-digest
1621 (list (format "help \"%s\"\n" fn)))
1622 (let ((lines inferior-octave-output-list)
1623 (inhibit-read-only t))
1624 (when (string-match "error: \\(.*\\)$" (car lines))
1625 (error "%s" (match-string 1 (car lines))))
1626 (with-help-window octave-help-buffer
1627 (princ (mapconcat 'identity lines "\n"))
1628 (with-current-buffer octave-help-buffer
1629 ;; Bound to t so that `help-buffer' returns current buffer for
1630 ;; `help-setup-xref'.
1631 (let ((help-xref-following t))
1632 (help-setup-xref (list 'octave-help fn)
1633 (called-interactively-p 'interactive)))
1634 ;; Note: can be turned off by suppress_verbose_help_message.
1635 ;;
1636 ;; Remove boring trailing text: Additional help for built-in functions
1637 ;; and operators ...
1638 (goto-char (point-max))
1639 (when (search-backward "\n\n\n" nil t)
1640 (goto-char (match-beginning 0))
1641 (delete-region (point) (point-max)))
1642 ;; File name highlight
1643 (goto-char (point-min))
1644 (when (re-search-forward "from the file \\(.*\\)$"
1645 (line-end-position)
1646 t)
1647 (let* ((file (match-string 1))
1648 (dir (file-name-directory
1649 (directory-file-name (file-name-directory file)))))
1650 (replace-match "" nil nil nil 1)
1651 (insert "`")
1652 ;; Include the parent directory which may be regarded as
1653 ;; the category for the FN.
1654 (help-insert-xref-button (file-relative-name file dir)
1655 'octave-help-file fn)
1656 (insert "'")))
1657 ;; Make 'See also' clickable
1658 (with-syntax-table octave-mode-syntax-table
1659 (when (re-search-forward "^\\s-*See also:" nil t)
1660 (let ((end (save-excursion (re-search-forward "^\\s-*$" nil t))))
1661 (while (re-search-forward "\\_<\\(?:\\sw\\|\\s_\\)+\\_>" end t)
1662 (make-text-button (match-beginning 0) (match-end 0)
1663 :type 'octave-help-function)))))
1664 (octave-help-mode)))))
1665
1666(defcustom octave-source-directories nil
1667 "A list of directories for Octave sources.
1668If the environment variable OCTAVE_SRCDIR is set, it is searched first."
1669 :type '(repeat directory)
1670 :group 'octave
1671 :version "24.4")
1672
1673(defun octave-source-directories ()
1674 (let ((srcdir (or (and inferior-octave-process
1675 (process-get inferior-octave-process 'octave-srcdir))
1676 (getenv "OCTAVE_SRCDIR"))))
1677 (if srcdir
1678 (cons srcdir octave-source-directories)
1679 octave-source-directories)))
1680
1681(defvar octave-find-definition-filename-function
1682 #'octave-find-definition-default-filename)
1683
1684(defun octave-find-definition-default-filename (name)
1685 "Default value for `octave-find-definition-filename-function'."
1686 (pcase (file-name-extension name)
1687 (`"oct"
1688 (octave-find-definition-default-filename
1689 (concat "libinterp/dldfcn/"
1690 (file-name-sans-extension (file-name-nondirectory name))
1691 ".cc")))
1692 (`"cc"
1693 (let ((file (or (locate-file name (octave-source-directories))
1694 (locate-file (file-name-nondirectory name)
1695 (octave-source-directories)))))
1696 (or (and file (file-exists-p file))
1697 (error "File `%s' not found" name))
1698 file))
1699 (`"mex"
1700 (if (yes-or-no-p (format "File `%s' may be binary; open? "
1701 (file-name-nondirectory name)))
1702 name
1703 (user-error "Aborted")))
1704 (t name)))
1705
1706(defvar find-tag-marker-ring)
1707
1708(defun octave-find-definition (fn)
1709 "Find the definition of FN.
1710Functions implemented in C++ can be found if
1711`octave-source-directories' is set correctly."
1712 (interactive (list (octave-completing-read)))
1713 (inferior-octave-send-list-and-digest
1714 ;; help NAME is more verbose
1715 (list (format "\
1716if iskeyword(\"%s\") disp(\"`%s' is a keyword\") else which(\"%s\") endif\n"
1717 fn fn fn)))
1718 (let* ((line (car inferior-octave-output-list))
1719 (file (when (and line (string-match "from the file \\(.*\\)$" line))
1720 (match-string 1 line))))
1721 (if (not file)
1722 (user-error "%s" (or line (format "`%s' not found" fn)))
1723 (require 'etags)
1724 (ring-insert find-tag-marker-ring (point-marker))
1725 (setq file (funcall octave-find-definition-filename-function file))
1726 (when file
1727 (find-file file)
1728 (octave-goto-function-definition fn)))))
1729
1730
1731(provide 'octave)
1732;;; octave.el ends here
diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el
index 5f78b770936..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-text-properties (from to properties)
410 ;; Like `set-text-properties', except we do not consider this to be a buffer
411 ;; modification.
412 (opascal-save-state
413 (set-text-properties from to properties)))
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,96 +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-literal-text-properties (kind)
494 ;; Creates a list of text properties for the literal kind.
495 (if (and (boundp 'font-lock-mode)
496 font-lock-mode)
497 (list 'token kind 'face (opascal-face-of kind) 'lazy-lock t)
498 (list 'token kind)))
499
500(defun opascal-parse-next-literal (limit)
501 ;; Searches for the next literal region (i.e. comment or string) and sets the
502 ;; the point to its end (or the limit, if not found). The literal region is
503 ;; marked as such with a text property, to speed up tokenizing during face
504 ;; coloring and indentation scanning.
505 (let ((search-start (point)))
506 (cond ((not (opascal-is-literal-end search-start))
507 ;; We are completing an incomplete literal.
508 (let ((kind (opascal-literal-kind (1- search-start))))
509 (opascal-complete-literal kind limit)
510 (opascal-set-text-properties
511 search-start (point) (opascal-literal-text-properties kind))))
512
513 ((re-search-forward
514 "\\(//\\)\\|\\({\\)\\|\\((\\*\\)\\|\\('\\)\\|\\(\"\\)"
515 limit 'goto-limit-on-fail)
516 ;; We found the start of a new literal. Find its end and mark it.
517 (let ((kind (cond ((match-beginning 1) 'comment-single-line)
518 ((match-beginning 2) 'comment-multi-line-1)
519 ((match-beginning 3) 'comment-multi-line-2)
520 ((match-beginning 4) 'string)
521 ((match-beginning 5) 'double-quoted-string)))
522 (start (match-beginning 0)))
523 (opascal-set-text-properties search-start start nil)
524 (opascal-complete-literal kind limit)
525 (opascal-set-text-properties
526 start (point) (opascal-literal-text-properties kind))))
527
528 ;; Nothing found. Mark it as a non-literal.
529 ((opascal-set-text-properties search-start limit nil)))
530 (opascal-step-progress (point) "Parsing" opascal-parsing-progress-step)))
531 438
532(defun opascal-literal-token-at (p) 439(defun opascal-literal-token-at (p)
533 ;; 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."
534 (let ((kind (opascal-literal-kind p))) 441 (save-excursion
535 (when kind 442 (let ((ppss (syntax-ppss p)))
536 (let ((start (previous-single-property-change (1+ p) 'token)) 443 (when (or (nth 8 ppss) (looking-at opascal--literal-start-re))
537 (end (next-single-property-change p 'token))) 444 (let* ((new-start (or (nth 8 ppss) p))
538 (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))))))
539 454
540(defun opascal-point-token-at (p kind) 455(defun opascal-point-token-at (p kind)
541 ;; Returns the single character token at the point p. 456 ;; Returns the single character token at the point p.
@@ -645,55 +560,6 @@ non-OPascal buffer. Set to nil in OPascal buffers. To override, just do:
645 (opascal-is (opascal-token-kind next-token) '(space newline)))) 560 (opascal-is (opascal-token-kind next-token) '(space newline))))
646 next-token)) 561 next-token))
647 562
648(defun opascal-parse-region (from to)
649 ;; Parses the literal tokens in the region. The point is set to "to".
650 (save-restriction
651 (widen)
652 (goto-char from)
653 (while (< (point) to)
654 (opascal-parse-next-literal to))))
655
656(defun opascal-parse-region-until-stable (from to)
657 ;; Parses at least the literal tokens in the region. After that, parsing
658 ;; continues as long as obsolete literal regions are encountered. The point
659 ;; is set to the encountered stable point.
660 (save-restriction
661 (widen)
662 (opascal-parse-region from to)
663 (while (not (opascal-is-stable-literal (point)))
664 (opascal-parse-next-literal (point-max)))))
665
666(defun opascal-fontify-region (from to &optional verbose)
667 ;; Colors the text in the region according to OPascal rules.
668 (opascal-save-excursion
669 (opascal-save-state
670 (let ((p from)
671 (opascal-verbose verbose)
672 (token nil))
673 (opascal-progress-start)
674 (while (< p to)
675 ;; Color the token and move past it.
676 (setq token (opascal-token-at p))
677 (add-text-properties
678 (opascal-token-start token) (opascal-token-end token)
679 (list 'face (opascal-face-of (opascal-token-kind token)) 'lazy-lock t))
680 (setq p (opascal-token-end token))
681 (opascal-step-progress p "Fontifying" opascal-fontifying-progress-step))
682 (opascal-progress-done)))))
683
684(defun opascal-after-change (change-start change-end _old-length)
685 ;; Called when the buffer has changed. Reparses the changed region.
686 (unless opascal--ignore-changes
687 (let ((opascal--ignore-changes t)) ; Prevent recursive calls.
688 (opascal-save-excursion
689 (opascal-progress-start)
690 ;; Reparse at least from the token previous to the change to the end of
691 ;; line after the change.
692 (opascal-parse-region-until-stable
693 (opascal-token-start (opascal-token-at (1- change-start)))
694 (progn (goto-char change-end) (end-of-line) (point)))
695 (opascal-progress-done)))))
696
697(defun opascal-group-start (from-token) 563(defun opascal-group-start (from-token)
698 ;; Returns the token that denotes the start of the ()/[] group. 564 ;; Returns the token that denotes the start of the ()/[] group.
699 (let ((token (opascal-previous-token from-token)) 565 (let ((token (opascal-previous-token from-token))
@@ -1561,41 +1427,6 @@ If before the indent, the point is moved to the indent."
1561 (interactive "r") 1427 (interactive "r")
1562 (opascal-debug-log "String: %S" (buffer-substring from to))) 1428 (opascal-debug-log "String: %S" (buffer-substring from to)))
1563 1429
1564(defun opascal-debug-show-is-stable ()
1565 (interactive)
1566 (opascal-debug-log "stable: %S prev: %S next: %S"
1567 (opascal-is-stable-literal (point))
1568 (opascal-literal-kind (1- (point)))
1569 (opascal-literal-kind (point))))
1570
1571(defun opascal-debug-unparse-buffer ()
1572 (interactive)
1573 (opascal-set-text-properties (point-min) (point-max) nil))
1574
1575(defun opascal-debug-parse-region (from to)
1576 (interactive "r")
1577 (let ((opascal-verbose t))
1578 (opascal-save-excursion
1579 (opascal-progress-start)
1580 (opascal-parse-region from to)
1581 (opascal-progress-done "Parsing done"))))
1582
1583(defun opascal-debug-parse-window ()
1584 (interactive)
1585 (opascal-debug-parse-region (window-start) (window-end)))
1586
1587(defun opascal-debug-parse-buffer ()
1588 (interactive)
1589 (opascal-debug-parse-region (point-min) (point-max)))
1590
1591(defun opascal-debug-fontify-window ()
1592 (interactive)
1593 (opascal-fontify-region (window-start) (window-end) t))
1594
1595(defun opascal-debug-fontify-buffer ()
1596 (interactive)
1597 (opascal-fontify-region (point-min) (point-max) t))
1598
1599(defun opascal-debug-tokenize-region (from to) 1430(defun opascal-debug-tokenize-region (from to)
1600 (interactive) 1431 (interactive)
1601 (opascal-save-excursion 1432 (opascal-save-excursion
@@ -1747,6 +1578,7 @@ An error is raised if not in a comment."
1747 (error "Not in a comment") 1578 (error "Not in a comment")
1748 (let* ((start-comment (opascal-comment-block-start comment)) 1579 (let* ((start-comment (opascal-comment-block-start comment))
1749 (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'.
1750 (comment-start (opascal-token-start start-comment)) 1582 (comment-start (opascal-token-start start-comment))
1751 (comment-end (opascal-token-end end-comment)) 1583 (comment-end (opascal-token-end end-comment))
1752 (content-start (opascal-comment-content-start start-comment)) 1584 (content-start (opascal-comment-content-start start-comment))
@@ -1814,12 +1646,7 @@ An error is raised if not in a comment."
1814 1646
1815 ;; Restore our position 1647 ;; Restore our position
1816 (goto-char marked-point) 1648 (goto-char marked-point)
1817 (set-marker marked-point nil) 1649 (set-marker marked-point nil)))))))
1818
1819 ;; React to the entire fill change as a whole.
1820 (opascal-progress-start)
1821 (opascal-parse-region comment-start comment-end)
1822 (opascal-progress-done)))))))
1823 1650
1824(defun opascal-new-comment-line () 1651(defun opascal-new-comment-line ()
1825 "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
@@ -1848,16 +1675,37 @@ comment block. If not in a // comment, just does a normal newline."
1848 (goto-char end) 1675 (goto-char end)
1849 token))) 1676 token)))
1850 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
1851(defconst opascal-font-lock-defaults 1684(defconst opascal-font-lock-defaults
1852 '(nil ; We have our own fontify routine, so keywords don't apply. 1685 '(opascal-font-lock-keywords
1853 t ; Syntactic fontification doesn't apply. 1686 nil ; Syntactic fontification does apply.
1854 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.
1855 nil ; Syntax alists don't apply. 1688 nil ; Syntax alists don't apply.
1856 nil ; Syntax begin movement doesn't apply 1689 nil ; Syntax begin movement doesn't apply.
1857 (font-lock-fontify-region-function . opascal-fontify-region) 1690 )
1858 (font-lock-verbose . opascal-fontifying-progress-step))
1859 "OPascal mode font-lock defaults. Syntactic fontification is ignored.") 1691 "OPascal mode font-lock defaults. Syntactic fontification is ignored.")
1860 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
1861(defvar opascal-debug-mode-map 1709(defvar opascal-debug-mode-map
1862 (let ((kmap (make-sparse-keymap))) 1710 (let ((kmap (make-sparse-keymap)))
1863 (dolist (binding '(("n" opascal-debug-goto-next-token) 1711 (dolist (binding '(("n" opascal-debug-goto-next-token)
@@ -1866,14 +1714,7 @@ comment block. If not in a // comment, just does a normal newline."
1866 ("T" opascal-debug-tokenize-buffer) 1714 ("T" opascal-debug-tokenize-buffer)
1867 ("W" opascal-debug-tokenize-window) 1715 ("W" opascal-debug-tokenize-window)
1868 ("g" opascal-debug-goto-point) 1716 ("g" opascal-debug-goto-point)
1869 ("s" opascal-debug-show-current-string) 1717 ("s" opascal-debug-show-current-string)))
1870 ("a" opascal-debug-parse-buffer)
1871 ("w" opascal-debug-parse-window)
1872 ("f" opascal-debug-fontify-window)
1873 ("F" opascal-debug-fontify-buffer)
1874 ("r" opascal-debug-parse-region)
1875 ("c" opascal-debug-unparse-buffer)
1876 ("x" opascal-debug-show-is-stable)))
1877 (define-key kmap (car binding) (cadr binding))) 1718 (define-key kmap (car binding) (cadr binding)))
1878 kmap) 1719 kmap)
1879 "Keystrokes for OPascal mode debug commands.") 1720 "Keystrokes for OPascal mode debug commands.")
@@ -1923,14 +1764,8 @@ Customization:
1923 1764
1924Coloring: 1765Coloring:
1925 1766
1926 `opascal-comment-face' (default font-lock-comment-face)
1927 Face used to color OPascal comments.
1928 `opascal-string-face' (default font-lock-string-face)
1929 Face used to color OPascal strings.
1930 `opascal-keyword-face' (default font-lock-keyword-face) 1767 `opascal-keyword-face' (default font-lock-keyword-face)
1931 Face used to color OPascal keywords. 1768 Face used to color OPascal keywords.
1932 `opascal-other-face' (default nil)
1933 Face used to color everything else.
1934 1769
1935Turning 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'
1936with no args, if that value is non-nil." 1771with no args, if that value is non-nil."
@@ -1940,21 +1775,13 @@ with no args, if that value is non-nil."
1940 (setq-local comment-indent-function #'opascal-indent-line) 1775 (setq-local comment-indent-function #'opascal-indent-line)
1941 (setq-local case-fold-search t) 1776 (setq-local case-fold-search t)
1942 (setq-local opascal-progress-last-reported-point nil) 1777 (setq-local opascal-progress-last-reported-point nil)
1943 (setq-local opascal--ignore-changes nil)
1944 (setq-local font-lock-defaults opascal-font-lock-defaults) 1778 (setq-local font-lock-defaults opascal-font-lock-defaults)
1945 (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)
1946 1781
1947 ;; FIXME: Use syntax-propertize-function to tokenize, maybe? 1782 (setq-local comment-start "// ")
1948 1783 (setq-local comment-start-skip "\\(?://\\|(\\*\\|{\\)[ \t]*")
1949 ;; We need to keep track of changes to the buffer to determine if we need 1784 (setq-local comment-end-skip "[ \t]*\\(?:\n\\|\\*)\\|}\\)"))
1950 ;; to retokenize changed text.
1951 (add-hook 'after-change-functions #'opascal-after-change nil t)
1952
1953 (opascal-save-excursion
1954 (let ((opascal-verbose t))
1955 (opascal-progress-start)
1956 (opascal-parse-region (point-min) (point-max))
1957 (opascal-progress-done))))
1958 1785
1959(provide 'opascal) 1786(provide 'opascal)
1960;;; opascal.el ends here 1787;;; opascal.el ends here
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 829ecda5150..ffc8200644a 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -158,31 +158,44 @@
158 158
159 159
160 160
161(defconst pascal-font-lock-keywords (purecopy 161(defconst pascal-font-lock-keywords
162 (list 162 `(("\\_<\\(function\\|pro\\(cedure\\|gram\\)\\)[ \t]+\\([[:alpha:]][[:alnum:]_]*\\)"
163 '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z]\\)" 163 (1 font-lock-keyword-face)
164 (3 font-lock-function-name-face))
165 ;; ("type" "const" "real" "integer" "char" "boolean" "var"
166 ;; "record" "array" "file")
167 (,(concat "\\<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
168 "integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\>")
169 font-lock-type-face)
170 ("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-constant-face)
171 ("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-function-name-face)
172 ;; ("of" "to" "for" "if" "then" "else" "case" "while"
173 ;; "do" "until" "and" "or" "not" "in" "with" "repeat" "begin" "end")
174 ,(concat "\\<\\("
175 "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
176 "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
177 "\\)\\>")
178 ("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
164 1 font-lock-keyword-face) 179 1 font-lock-keyword-face)
165 '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z][a-z0-9_]*\\)" 180 ("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
166 3 font-lock-function-name-face t) 181 2 font-lock-keyword-face t))
167; ("type" "const" "real" "integer" "char" "boolean" "var"
168; "record" "array" "file")
169 (cons (concat "\\<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
170 "integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\>")
171 'font-lock-type-face)
172 '("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-constant-face)
173 '("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-function-name-face)
174; ("of" "to" "for" "if" "then" "else" "case" "while"
175; "do" "until" "and" "or" "not" "in" "with" "repeat" "begin" "end")
176 (concat "\\<\\("
177 "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
178 "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
179 "\\)\\>")
180 '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
181 1 font-lock-keyword-face)
182 '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
183 2 font-lock-keyword-face t)))
184 "Additional expressions to highlight in Pascal mode.") 182 "Additional expressions to highlight in Pascal mode.")
185(put 'pascal-mode 'font-lock-defaults '(pascal-font-lock-keywords nil t)) 183
184(defconst pascal--syntax-propertize
185 (syntax-propertize-rules
186 ;; The syntax-table settings are too coarse and end up treating /* and (/
187 ;; as comment starters. Fix it here by removing the "2" from the syntax
188 ;; of the second char of such sequences.
189 ("/\\(\\*\\)" (1 ". 3b"))
190 ("(\\(\\/\\)" (1 (prog1 ". 1c" (forward-char -1) nil)))
191 ;; Pascal uses '' and "" rather than \' and \" to escape quotes.
192 ("''\\|\"\"" (0 (if (save-excursion
193 (nth 3 (syntax-ppss (match-beginning 0))))
194 (string-to-syntax ".")
195 ;; In case of 3 or more quotes in a row, only advance
196 ;; one quote at a time.
197 (forward-char -1)
198 nil)))))
186 199
187(defcustom pascal-indent-level 3 200(defcustom pascal-indent-level 3
188 "Indentation of Pascal statements with respect to containing block." 201 "Indentation of Pascal statements with respect to containing block."
@@ -346,23 +359,22 @@ See also the user variables `pascal-type-keywords', `pascal-start-keywords' and
346 359
347Turning on Pascal mode calls the value of the variable pascal-mode-hook with 360Turning on Pascal mode calls the value of the variable pascal-mode-hook with
348no args, if that value is non-nil." 361no args, if that value is non-nil."
349 (set (make-local-variable 'local-abbrev-table) pascal-mode-abbrev-table) 362 (setq-local local-abbrev-table pascal-mode-abbrev-table)
350 (set (make-local-variable 'indent-line-function) 'pascal-indent-line) 363 (setq-local indent-line-function 'pascal-indent-line)
351 (set (make-local-variable 'comment-indent-function) 'pascal-indent-comment) 364 (setq-local comment-indent-function 'pascal-indent-comment)
352 (set (make-local-variable 'parse-sexp-ignore-comments) nil) 365 (setq-local parse-sexp-ignore-comments nil)
353 (set (make-local-variable 'blink-matching-paren-dont-ignore-comments) t) 366 (setq-local blink-matching-paren-dont-ignore-comments t)
354 (set (make-local-variable 'case-fold-search) t) 367 (setq-local case-fold-search t)
355 (set (make-local-variable 'comment-start) "{") 368 (setq-local comment-start "{")
356 (set (make-local-variable 'comment-start-skip) "(\\*+ *\\|{ *") 369 (setq-local comment-start-skip "(\\*+ *\\|{ *")
357 (set (make-local-variable 'comment-end) "}") 370 (setq-local comment-end "}")
358 (add-hook 'completion-at-point-functions 'pascal-completions-at-point nil t) 371 (add-hook 'completion-at-point-functions 'pascal-completions-at-point nil t)
359 ;; Font lock support 372 ;; Font lock support
360 (set (make-local-variable 'font-lock-defaults) 373 (setq-local font-lock-defaults '(pascal-font-lock-keywords nil t))
361 '(pascal-font-lock-keywords nil t)) 374 (setq-local syntax-propertize-function pascal--syntax-propertize)
362 ;; Imenu support 375 ;; Imenu support
363 (set (make-local-variable 'imenu-generic-expression) 376 (setq-local imenu-generic-expression pascal-imenu-generic-expression)
364 pascal-imenu-generic-expression) 377 (setq-local imenu-case-fold-search t)
365 (set (make-local-variable 'imenu-case-fold-search) t)
366 ;; Pascal-mode's own hide/show support. 378 ;; Pascal-mode's own hide/show support.
367 (add-to-invisibility-spec '(pascal . t))) 379 (add-to-invisibility-spec '(pascal . t)))
368 380
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index bd58a7300ec..01ac8584e19 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -148,10 +148,10 @@
148 148
149(defvar perl-imenu-generic-expression 149(defvar perl-imenu-generic-expression
150 '(;; Functions 150 '(;; Functions
151 (nil "^[ \t]*sub\\s-+\\([-A-Za-z0-9+_:]+\\)" 1) 151 (nil "^[ \t]*sub\\s-+\\([-[:alnum:]+_:]+\\)" 1)
152 ;;Variables 152 ;;Variables
153 ("Variables" "^\\(?:my\\|our\\)\\s-+\\([$@%][-A-Za-z0-9+_:]+\\)\\s-*=" 1) 153 ("Variables" "^\\(?:my\\|our\\)\\s-+\\([$@%][-[:alnum:]+_:]+\\)\\s-*=" 1)
154 ("Packages" "^[ \t]*package\\s-+\\([-A-Za-z0-9+_:]+\\);" 1) 154 ("Packages" "^[ \t]*package\\s-+\\([-[:alnum:]+_:]+\\);" 1)
155 ("Doc sections" "^=head[0-9][ \t]+\\(.*\\)" 1)) 155 ("Doc sections" "^=head[0-9][ \t]+\\(.*\\)" 1))
156 "Imenu generic expression for Perl mode. See `imenu-generic-expression'.") 156 "Imenu generic expression for Perl mode. See `imenu-generic-expression'.")
157 157
@@ -160,6 +160,7 @@
160 160
161(defcustom perl-prettify-symbols t 161(defcustom perl-prettify-symbols t
162 "If non-nil, some symbols will be displayed using Unicode chars." 162 "If non-nil, some symbols will be displayed using Unicode chars."
163 :version "24.4"
163 :type 'boolean) 164 :type 'boolean)
164 165
165(defconst perl--prettify-symbols-alist 166(defconst perl--prettify-symbols-alist
@@ -275,7 +276,6 @@ Regexp match data 0 points to the chars."
275 (let ((case-fold-search nil)) 276 (let ((case-fold-search nil))
276 (goto-char start) 277 (goto-char start)
277 (perl-syntax-propertize-special-constructs end) 278 (perl-syntax-propertize-special-constructs end)
278 ;; TODO: here-documents ("<<\\(\\sw\\|['\"]\\)")
279 (funcall 279 (funcall
280 (syntax-propertize-rules 280 (syntax-propertize-rules
281 ;; Turn POD into b-style comments. Place the cut rule first since it's 281 ;; Turn POD into b-style comments. Place the cut rule first since it's
@@ -287,7 +287,7 @@ Regexp match data 0 points to the chars."
287 ;; check that it occurs inside a '..' string. 287 ;; check that it occurs inside a '..' string.
288 ("\\(\\$\\)[{']" (1 ". p")) 288 ("\\(\\$\\)[{']" (1 ". p"))
289 ;; Handle funny names like $DB'stop. 289 ;; Handle funny names like $DB'stop.
290 ("\\$ ?{?^?[_a-zA-Z][_a-zA-Z0-9]*\\('\\)[_a-zA-Z]" (1 "_")) 290 ("\\$ ?{?^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
291 ;; format statements 291 ;; format statements
292 ("^[ \t]*format.*=[ \t]*\\(\n\\)" 292 ("^[ \t]*format.*=[ \t]*\\(\n\\)"
293 (1 (prog1 "\"" (perl-syntax-propertize-special-constructs end)))) 293 (1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
@@ -345,7 +345,29 @@ Regexp match data 0 points to the chars."
345 perl-quote-like-pairs) 345 perl-quote-like-pairs)
346 (string-to-syntax "|") 346 (string-to-syntax "|")
347 (string-to-syntax "\""))) 347 (string-to-syntax "\"")))
348 (perl-syntax-propertize-special-constructs end)))))) 348 (perl-syntax-propertize-special-constructs end)))))
349 ;; Here documents.
350 ;; TODO: Handle <<WORD. These are trickier because you need to
351 ;; disambiguate with the shift operator.
352 ("<<[ \t]*\\('[^'\n]*'\\|\"[^\"\n]*\"\\|\\\\[[:alpha:]][[:alnum:]]*\\).*\\(\n\\)"
353 (2 (let* ((st (get-text-property (match-beginning 2) 'syntax-table))
354 (name (match-string 1)))
355 (goto-char (match-end 1))
356 (if (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
357 ;; Leave the property of the newline unchanged.
358 st
359 (cons (car (string-to-syntax "< c"))
360 ;; Remember the names of heredocs found on this line.
361 (cons (pcase (aref name 0)
362 (`?\\ (substring name 1))
363 (_ (substring name 1 -1)))
364 (cdr st)))))))
365 ;; We don't call perl-syntax-propertize-special-constructs directly
366 ;; from the << rule, because there might be other elements (between
367 ;; the << and the \n) that need to be propertized.
368 ("\\(?:$\\)\\s<"
369 (0 (ignore (perl-syntax-propertize-special-constructs end))))
370 )
349 (point) end))) 371 (point) end)))
350 372
351(defvar perl-empty-syntax-table 373(defvar perl-empty-syntax-table
@@ -370,6 +392,22 @@ Regexp match data 0 points to the chars."
370 (let ((state (syntax-ppss)) 392 (let ((state (syntax-ppss))
371 char) 393 char)
372 (cond 394 (cond
395 ((eq 2 (nth 7 state))
396 ;; A Here document.
397 (let ((names (cdr (get-text-property (nth 8 state) 'syntax-table))))
398 (when (cdr names)
399 (setq names (reverse names))
400 ;; Multiple heredocs on a single line, we have to search from the
401 ;; beginning, since we don't know which names might be
402 ;; before point.
403 (goto-char (nth 8 state)))
404 (while (and names
405 (re-search-forward
406 (concat "^" (regexp-quote (pop names)) "\n")
407 limit 'move))
408 (unless names
409 (put-text-property (1- (point)) (point) 'syntax-table
410 (string-to-syntax "> c"))))))
373 ((or (null (setq char (nth 3 state))) 411 ((or (null (setq char (nth 3 state)))
374 (and (characterp char) (eq (char-syntax (nth 3 state)) ?\"))) 412 (and (characterp char) (eq (char-syntax (nth 3 state)) ?\")))
375 ;; Normal text, or comment, or docstring, or normal string. 413 ;; Normal text, or comment, or docstring, or normal string.
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 85e4172c8fe..63bd9258d69 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -278,16 +278,16 @@
278 278
279;;; Code: 279;;; Code:
280 280
281(require 'comint)
282
281(eval-when-compile 283(eval-when-compile
282 (require 'font-lock) 284 (require 'font-lock)
283 ;; We need imenu everywhere because of the predicate index! 285 ;; We need imenu everywhere because of the predicate index!
284 (require 'imenu) 286 (require 'imenu)
285 ;) 287 ;)
286 (require 'info)
287 (require 'shell) 288 (require 'shell)
288 ) 289 )
289 290
290(require 'comint)
291(require 'easymenu) 291(require 'easymenu)
292(require 'align) 292(require 'align)
293 293
@@ -772,6 +772,8 @@ Relevant only when `prolog-imenu-flag' is non-nil."
772 :version "24.1" 772 :version "24.1"
773 :group 'prolog-other 773 :group 'prolog-other
774 :type 'boolean) 774 :type 'boolean)
775(make-obsolete-variable 'prolog-underscore-wordchar-flag
776 'superword-mode "24.4")
775 777
776(defcustom prolog-use-sicstus-sd nil 778(defcustom prolog-use-sicstus-sd nil
777 "If non-nil, use the source level debugger of SICStus 3#7 and later." 779 "If non-nil, use the source level debugger of SICStus 3#7 and later."
@@ -785,6 +787,7 @@ This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
785 :version "24.1" 787 :version "24.1"
786 :group 'prolog-other 788 :group 'prolog-other
787 :type 'boolean) 789 :type 'boolean)
790(make-obsolete-variable 'prolog-char-quote-workaround nil "24.1")
788 791
789 792
790;;------------------------------------------------------------------- 793;;-------------------------------------------------------------------
@@ -802,10 +805,7 @@ This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
802 ;; - In atoms \x<hex> sometimes needs a terminating \ (ISO-style) 805 ;; - In atoms \x<hex> sometimes needs a terminating \ (ISO-style)
803 ;; and sometimes not. 806 ;; and sometimes not.
804 (let ((table (make-syntax-table))) 807 (let ((table (make-syntax-table)))
805 (if prolog-underscore-wordchar-flag 808 (modify-syntax-entry ?_ (if prolog-underscore-wordchar-flag "w" "_") table)
806 (modify-syntax-entry ?_ "w" table)
807 (modify-syntax-entry ?_ "_" table))
808
809 (modify-syntax-entry ?+ "." table) 809 (modify-syntax-entry ?+ "." table)
810 (modify-syntax-entry ?- "." table) 810 (modify-syntax-entry ?- "." table)
811 (modify-syntax-entry ?= "." table) 811 (modify-syntax-entry ?= "." table)
@@ -815,7 +815,8 @@ This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
815 (modify-syntax-entry ?\' "\"" table) 815 (modify-syntax-entry ?\' "\"" table)
816 816
817 ;; Any better way to handle the 0'<char> construct?!? 817 ;; Any better way to handle the 0'<char> construct?!?
818 (when prolog-char-quote-workaround 818 (when (and prolog-char-quote-workaround
819 (not (fboundp 'syntax-propertize-rules)))
819 (modify-syntax-entry ?0 "\\" table)) 820 (modify-syntax-entry ?0 "\\" table))
820 821
821 (modify-syntax-entry ?% "<" table) 822 (modify-syntax-entry ?% "<" table)
@@ -1770,7 +1771,8 @@ This function must be called from the source code buffer."
1770 real-file)) 1771 real-file))
1771 (with-current-buffer buffer 1772 (with-current-buffer buffer
1772 (goto-char (point-max)) 1773 (goto-char (point-max))
1773 (set-process-filter process 'prolog-consult-compile-filter) 1774 (add-function :override (process-filter process)
1775 #'prolog-consult-compile-filter)
1774 (process-send-string "prolog" command-string) 1776 (process-send-string "prolog" command-string)
1775 ;; (prolog-build-prolog-command compilep file real-file first-line)) 1777 ;; (prolog-build-prolog-command compilep file real-file first-line))
1776 (while (and prolog-process-flag 1778 (while (and prolog-process-flag
@@ -1781,7 +1783,8 @@ This function must be called from the source code buffer."
1781 (insert (if compilep 1783 (insert (if compilep
1782 "\nCompilation finished.\n" 1784 "\nCompilation finished.\n"
1783 "\nConsulted.\n")) 1785 "\nConsulted.\n"))
1784 (set-process-filter process old-filter)))) 1786 (remove-function (process-filter process)
1787 #'prolog-consult-compile-filter))))
1785 1788
1786(defvar compilation-error-list) 1789(defvar compilation-error-list)
1787 1790
@@ -3027,11 +3030,14 @@ The rest of the elements are undefined."
3027 (error "Sorry, no help method defined for this Prolog system.")))) 3030 (error "Sorry, no help method defined for this Prolog system."))))
3028 )) 3031 ))
3029 3032
3033
3034(autoload 'Info-goto-node "info" nil t)
3035(declare-function Info-follow-nearest-node "info" (&optional FORK))
3036
3030(defun prolog-help-info (predicate) 3037(defun prolog-help-info (predicate)
3031 (let ((buffer (current-buffer)) 3038 (let ((buffer (current-buffer))
3032 oldp 3039 oldp
3033 (str (concat "^\\* " (regexp-quote predicate) " */"))) 3040 (str (concat "^\\* " (regexp-quote predicate) " */")))
3034 (require 'info)
3035 (pop-to-buffer nil) 3041 (pop-to-buffer nil)
3036 (Info-goto-node prolog-info-predicate-index) 3042 (Info-goto-node prolog-info-predicate-index)
3037 (if (not (re-search-forward str nil t)) 3043 (if (not (re-search-forward str nil t))
@@ -3120,7 +3126,6 @@ Only for internal use by `prolog-find-documentation'")
3120(defun prolog-goto-predicate-info (predicate) 3126(defun prolog-goto-predicate-info (predicate)
3121 "Go to the info page for PREDICATE, which is a PredSpec." 3127 "Go to the info page for PREDICATE, which is a PredSpec."
3122 (interactive) 3128 (interactive)
3123 (require 'info)
3124 (string-match "\\(.*\\)/\\([0-9]+\\).*$" predicate) 3129 (string-match "\\(.*\\)/\\([0-9]+\\).*$" predicate)
3125 (let ((buffer (current-buffer)) 3130 (let ((buffer (current-buffer))
3126 (name (match-string 1 predicate)) 3131 (name (match-string 1 predicate))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index f0f67d01845..ccb2dcba42e 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -157,7 +157,7 @@
157 157
158;; Skeletons: 6 skeletons are provided for simple inserting of class, 158;; Skeletons: 6 skeletons are provided for simple inserting of class,
159;; def, for, if, try and while. These skeletons are integrated with 159;; def, for, if, try and while. These skeletons are integrated with
160;; dabbrev. If you have `dabbrev-mode' activated and 160;; abbrev. If you have `abbrev-mode' activated and
161;; `python-skeleton-autoinsert' is set to t, then whenever you type 161;; `python-skeleton-autoinsert' is set to t, then whenever you type
162;; the name of any of those defined and hit SPC, they will be 162;; the name of any of those defined and hit SPC, they will be
163;; automatically expanded. As an alternative you can use the defined 163;; automatically expanded. As an alternative you can use the defined
@@ -177,12 +177,14 @@
177;; might guessed you should run `python-shell-send-buffer' from time 177;; might guessed you should run `python-shell-send-buffer' from time
178;; to time to get better results too. 178;; to time to get better results too.
179 179
180;; Imenu: This mode supports Imenu in its most basic form, letting it 180;; Imenu: There are two index building functions to be used as
181;; build the necessary alist via `imenu-default-create-index-function' 181;; `imenu-create-index-function': `python-imenu-create-index' (the
182;; by having set `imenu-extract-index-name-function' to 182;; default one, builds the alist in form of a tree) and
183;; `python-info-current-defun' and 183;; `python-imenu-create-flat-index'. See also
184;; `imenu-prev-index-position-function' to 184;; `python-imenu-format-item-label-function',
185;; `python-imenu-prev-index-position'. 185;; `python-imenu-format-parent-item-label-function',
186;; `python-imenu-format-parent-item-jump-label-function' variables for
187;; changing the way labels are formatted in the tree version.
186 188
187;; If you used python-mode.el you probably will miss auto-indentation 189;; If you used python-mode.el you probably will miss auto-indentation
188;; when inserting newlines. To achieve the same behavior you have 190;; when inserting newlines. To achieve the same behavior you have
@@ -368,22 +370,24 @@ This variant of `rx' supports common python named REGEXPS."
368 370
369;;; Font-lock and syntax 371;;; Font-lock and syntax
370 372
373(eval-when-compile
374 (defun python-syntax--context-compiler-macro (form type &optional syntax-ppss)
375 (pcase type
376 (`'comment
377 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
378 (and (nth 4 ppss) (nth 8 ppss))))
379 (`'string
380 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
381 (and (nth 3 ppss) (nth 8 ppss))))
382 (`'paren
383 `(nth 1 (or ,syntax-ppss (syntax-ppss))))
384 (_ form))))
385
371(defun python-syntax-context (type &optional syntax-ppss) 386(defun python-syntax-context (type &optional syntax-ppss)
372 "Return non-nil if point is on TYPE using SYNTAX-PPSS. 387 "Return non-nil if point is on TYPE using SYNTAX-PPSS.
373TYPE can be `comment', `string' or `paren'. It returns the start 388TYPE can be `comment', `string' or `paren'. It returns the start
374character address of the specified TYPE." 389character address of the specified TYPE."
375 (declare (compiler-macro 390 (declare (compiler-macro python-syntax--context-compiler-macro))
376 (lambda (form)
377 (pcase type
378 (`'comment
379 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
380 (and (nth 4 ppss) (nth 8 ppss))))
381 (`'string
382 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
383 (and (nth 3 ppss) (nth 8 ppss))))
384 (`'paren
385 `(nth 1 (or ,syntax-ppss (syntax-ppss))))
386 (_ form)))))
387 (let ((ppss (or syntax-ppss (syntax-ppss)))) 391 (let ((ppss (or syntax-ppss (syntax-ppss))))
388 (pcase type 392 (pcase type
389 (`comment (and (nth 4 ppss) (nth 8 ppss))) 393 (`comment (and (nth 4 ppss) (nth 8 ppss)))
@@ -638,6 +642,13 @@ It makes underscores and dots word constituent chars.")
638These make `python-indent-calculate-indentation' subtract the value of 642These make `python-indent-calculate-indentation' subtract the value of
639`python-indent-offset'.") 643`python-indent-offset'.")
640 644
645(defvar python-indent-block-enders
646 '("break" "continue" "pass" "raise" "return")
647 "List of words that mark the end of a block.
648These make `python-indent-calculate-indentation' subtract the
649value of `python-indent-offset' when `python-indent-context' is
650AFTER-LINE.")
651
641(defun python-indent-guess-indent-offset () 652(defun python-indent-guess-indent-offset ()
642 "Guess and set `python-indent-offset' for the current buffer." 653 "Guess and set `python-indent-offset' for the current buffer."
643 (interactive) 654 (interactive)
@@ -763,9 +774,13 @@ START is the buffer position where the sexp starts."
763 (save-excursion 774 (save-excursion
764 (goto-char context-start) 775 (goto-char context-start)
765 (current-indentation)) 776 (current-indentation))
766 (if (progn 777 (if (or (save-excursion
767 (back-to-indentation) 778 (back-to-indentation)
768 (looking-at (regexp-opt python-indent-dedenters))) 779 (looking-at (regexp-opt python-indent-dedenters)))
780 (save-excursion
781 (python-util-forward-comment -1)
782 (python-nav-beginning-of-statement)
783 (member (current-word) python-indent-block-enders)))
769 python-indent-offset 784 python-indent-offset
770 0))) 785 0)))
771 ;; When inside of a string, do nothing. just use the current 786 ;; When inside of a string, do nothing. just use the current
@@ -1180,6 +1195,70 @@ Returns nil if point is not in a def or class."
1180 ;; Ensure point moves forward. 1195 ;; Ensure point moves forward.
1181 (and (> beg-pos (point)) (goto-char beg-pos))))) 1196 (and (> beg-pos (point)) (goto-char beg-pos)))))
1182 1197
1198(defun python-nav--syntactically (fn poscompfn &optional contextfn)
1199 "Move point using FN avoiding places with specific context.
1200FN must take no arguments. POSCOMPFN is a two arguments function
1201used to compare current and previous point after it is moved
1202using FN, this is normally a less-than or greater-than
1203comparison. Optional argument CONTEXTFN defaults to
1204`python-syntax-context-type' and is used for checking current
1205point context, it must return a non-nil value if this point must
1206be skipped."
1207 (let ((contextfn (or contextfn 'python-syntax-context-type))
1208 (start-pos (point-marker))
1209 (prev-pos))
1210 (catch 'found
1211 (while t
1212 (let* ((newpos
1213 (and (funcall fn) (point-marker)))
1214 (context (funcall contextfn)))
1215 (cond ((and (not context) newpos
1216 (or (and (not prev-pos) newpos)
1217 (and prev-pos newpos
1218 (funcall poscompfn newpos prev-pos))))
1219 (throw 'found (point-marker)))
1220 ((and newpos context)
1221 (setq prev-pos (point)))
1222 (t (when (not newpos) (goto-char start-pos))
1223 (throw 'found nil))))))))
1224
1225(defun python-nav--forward-defun (arg)
1226 "Internal implementation of python-nav-{backward,forward}-defun.
1227Uses ARG to define which function to call, and how many times
1228repeat it."
1229 (let ((found))
1230 (while (and (> arg 0)
1231 (setq found
1232 (python-nav--syntactically
1233 (lambda ()
1234 (re-search-forward
1235 python-nav-beginning-of-defun-regexp nil t))
1236 '>)))
1237 (setq arg (1- arg)))
1238 (while (and (< arg 0)
1239 (setq found
1240 (python-nav--syntactically
1241 (lambda ()
1242 (re-search-backward
1243 python-nav-beginning-of-defun-regexp nil t))
1244 '<)))
1245 (setq arg (1+ arg)))
1246 found))
1247
1248(defun python-nav-backward-defun (&optional arg)
1249 "Navigate to closer defun backward ARG times.
1250Unlikely `python-nav-beginning-of-defun' this doesn't care about
1251nested definitions."
1252 (interactive "^p")
1253 (python-nav--forward-defun (- (or arg 1))))
1254
1255(defun python-nav-forward-defun (&optional arg)
1256 "Navigate to closer defun forward ARG times.
1257Unlikely `python-nav-beginning-of-defun' this doesn't care about
1258nested definitions."
1259 (interactive "^p")
1260 (python-nav--forward-defun (or arg 1)))
1261
1183(defun python-nav-beginning-of-statement () 1262(defun python-nav-beginning-of-statement ()
1184 "Move to start of current statement." 1263 "Move to start of current statement."
1185 (interactive "^") 1264 (interactive "^")
@@ -1603,7 +1682,7 @@ This variable, when set to a string, makes the values stored in
1603`python-shell-process-environment' and `python-shell-exec-path' 1682`python-shell-process-environment' and `python-shell-exec-path'
1604to be modified properly so shells are started with the specified 1683to be modified properly so shells are started with the specified
1605virtualenv." 1684virtualenv."
1606 :type 'string 1685 :type '(choice (const nil) string)
1607 :group 'python 1686 :group 'python
1608 :safe 'stringp) 1687 :safe 'stringp)
1609 1688
@@ -2644,8 +2723,8 @@ the if condition."
2644(defvar python-skeleton-available '() 2723(defvar python-skeleton-available '()
2645 "Internal list of available skeletons.") 2724 "Internal list of available skeletons.")
2646 2725
2647(define-abbrev-table 'python-mode-abbrev-table () 2726(define-abbrev-table 'python-mode-skeleton-abbrev-table ()
2648 "Abbrev table for Python mode." 2727 "Abbrev table for Python mode skeletons."
2649 :case-fixed t 2728 :case-fixed t
2650 ;; Allow / inside abbrevs. 2729 ;; Allow / inside abbrevs.
2651 :regexp "\\(?:^\\|[^/]\\)\\<\\([[:word:]/]+\\)\\W*" 2730 :regexp "\\(?:^\\|[^/]\\)\\<\\([[:word:]/]+\\)\\W*"
@@ -2658,13 +2737,13 @@ the if condition."
2658(defmacro python-skeleton-define (name doc &rest skel) 2737(defmacro python-skeleton-define (name doc &rest skel)
2659 "Define a `python-mode' skeleton using NAME DOC and SKEL. 2738 "Define a `python-mode' skeleton using NAME DOC and SKEL.
2660The skeleton will be bound to python-skeleton-NAME and will 2739The skeleton will be bound to python-skeleton-NAME and will
2661be added to `python-mode-abbrev-table'." 2740be added to `python-mode-skeleton-abbrev-table'."
2662 (declare (indent 2)) 2741 (declare (indent 2))
2663 (let* ((name (symbol-name name)) 2742 (let* ((name (symbol-name name))
2664 (function-name (intern (concat "python-skeleton-" name)))) 2743 (function-name (intern (concat "python-skeleton-" name))))
2665 `(progn 2744 `(progn
2666 (define-abbrev python-mode-abbrev-table ,name "" ',function-name 2745 (define-abbrev python-mode-skeleton-abbrev-table
2667 :system t) 2746 ,name "" ',function-name :system t)
2668 (setq python-skeleton-available 2747 (setq python-skeleton-available
2669 (cons ',function-name python-skeleton-available)) 2748 (cons ',function-name python-skeleton-available))
2670 (define-skeleton ,function-name 2749 (define-skeleton ,function-name
@@ -2672,6 +2751,10 @@ be added to `python-mode-abbrev-table'."
2672 (format "Insert %s statement." name)) 2751 (format "Insert %s statement." name))
2673 ,@skel)))) 2752 ,@skel))))
2674 2753
2754(define-abbrev-table 'python-mode-abbrev-table ()
2755 "Abbrev table for Python mode."
2756 :parents (list python-mode-skeleton-abbrev-table))
2757
2675(defmacro python-define-auxiliary-skeleton (name doc &optional &rest skel) 2758(defmacro python-define-auxiliary-skeleton (name doc &optional &rest skel)
2676 "Define a `python-mode' auxiliary skeleton using NAME DOC and SKEL. 2759 "Define a `python-mode' auxiliary skeleton using NAME DOC and SKEL.
2677The skeleton will be bound to python-skeleton-NAME." 2760The skeleton will be bound to python-skeleton-NAME."
@@ -2928,15 +3011,193 @@ Interactively, prompt for symbol."
2928 3011
2929;;; Imenu 3012;;; Imenu
2930 3013
2931(defun python-imenu-prev-index-position () 3014(defvar python-imenu-format-item-label-function
2932 "Python mode's `imenu-prev-index-position-function'." 3015 'python-imenu-format-item-label
2933 (let ((found)) 3016 "Imenu function used to format an item label.
2934 (while (and (setq found 3017It must be a function with two arguments: TYPE and NAME.")
2935 (re-search-backward python-nav-beginning-of-defun-regexp nil t)) 3018
2936 (not (python-info-looking-at-beginning-of-defun)))) 3019(defvar python-imenu-format-parent-item-label-function
2937 (and found 3020 'python-imenu-format-parent-item-label
2938 (python-info-looking-at-beginning-of-defun) 3021 "Imenu function used to format a parent item label.
2939 (python-info-current-defun)))) 3022It must be a function with two arguments: TYPE and NAME.")
3023
3024(defvar python-imenu-format-parent-item-jump-label-function
3025 'python-imenu-format-parent-item-jump-label
3026 "Imenu function used to format a parent jump item label.
3027It must be a function with two arguments: TYPE and NAME.")
3028
3029(defun python-imenu-format-item-label (type name)
3030 "Return imenu label for single node using TYPE and NAME."
3031 (format "%s (%s)" name type))
3032
3033(defun python-imenu-format-parent-item-label (type name)
3034 "Return imenu label for parent node using TYPE and NAME."
3035 (format "%s..." (python-imenu-format-item-label type name)))
3036
3037(defun python-imenu-format-parent-item-jump-label (type name)
3038 "Return imenu label for parent node jump using TYPE and NAME."
3039 (if (string= type "class")
3040 "*class definition*"
3041 "*function definition*"))
3042
3043(defun python-imenu--put-parent (type name pos num-children tree &optional root)
3044 "Add the parent with TYPE, NAME, POS and NUM-CHILDREN to TREE.
3045Optional Argument ROOT must be non-nil when the node being
3046processed is the root of the TREE."
3047 (let ((label
3048 (funcall python-imenu-format-item-label-function type name))
3049 (jump-label
3050 (funcall python-imenu-format-parent-item-jump-label-function type name)))
3051 (if root
3052 ;; This is the root, everything is a children.
3053 (cons label (cons (cons jump-label pos) tree))
3054 ;; This is node a which may contain some children.
3055 (cons
3056 (cons label (cons (cons jump-label pos)
3057 ;; Append all the children
3058 (python-util-popn tree num-children)))
3059 ;; All previous non-children nodes.
3060 (nthcdr num-children tree)))))
3061
3062(defun python-imenu--build-tree (&optional min-indent prev-indent num-children tree)
3063 "Recursively build the tree of nested definitions of a node.
3064Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are
3065internal and should not be passed explicitly unless you know what
3066you are doing."
3067 (setq num-children (or num-children 0)
3068 min-indent (or min-indent 0))
3069 (let* ((pos (python-nav-backward-defun))
3070 (type)
3071 (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp))
3072 (let ((split (split-string (match-string-no-properties 0))))
3073 (setq type (car split))
3074 (cadr split))))
3075 (label (when name
3076 (funcall python-imenu-format-item-label-function type name)))
3077 (indent (current-indentation)))
3078 (cond ((not pos)
3079 ;; No defun found, nothing to add.
3080 tree)
3081 ((equal indent 0)
3082 (if (> num-children 0)
3083 ;; Append it as the parent of everything collected to
3084 ;; this point.
3085 (python-imenu--put-parent type name pos num-children tree t)
3086 ;; There are no children, this is a lonely defun.
3087 (cons label pos)))
3088 ((equal min-indent indent)
3089 ;; Stop collecting nodes after moving to a position with
3090 ;; indentation equaling min-indent. This is specially
3091 ;; useful for navigating nested definitions recursively.
3092 tree)
3093 (t
3094 (python-imenu--build-tree
3095 min-indent
3096 indent
3097 ;; Add another children, either when this is the
3098 ;; first call or when indentation is
3099 ;; less-or-equal than previous. And do not
3100 ;; discard the number of children, because the
3101 ;; way code is scanned, all children are
3102 ;; collected until a root node yet to be found
3103 ;; appears.
3104 (if (or (not prev-indent)
3105 (and
3106 (> indent min-indent)
3107 (<= indent prev-indent)))
3108 (1+ num-children)
3109 num-children)
3110 (cond ((not prev-indent)
3111 ;; First call to the function: append this
3112 ;; defun to the index.
3113 (list (cons label pos)))
3114 ((= indent prev-indent)
3115 ;; Add another defun with the same depth
3116 ;; as the previous.
3117 (cons (cons label pos) tree))
3118 ((and (< indent prev-indent)
3119 (< 0 num-children))
3120 ;; There are children to be appended and
3121 ;; the previous defun had more
3122 ;; indentation, the current one must be a
3123 ;; parent.
3124 (python-imenu--put-parent type name pos num-children tree))
3125 ((> indent prev-indent)
3126 ;; There are children defuns deeper than
3127 ;; current depth. Fear not, we already
3128 ;; know how to treat them.
3129 (cons
3130 (prog1
3131 (python-imenu--build-tree
3132 prev-indent indent 1 (list (cons label pos)))
3133 ;; Adjustment: after scanning backwards
3134 ;; for all deeper children, we need to
3135 ;; continue our scan for a parent from
3136 ;; the current defun we are looking at.
3137 (python-nav-forward-defun))
3138 tree))))))))
3139
3140(defun python-imenu-create-index ()
3141 "Return tree Imenu alist for the current python buffer.
3142Change `python-imenu-format-item-label-function',
3143`python-imenu-format-parent-item-label-function',
3144`python-imenu-format-parent-item-jump-label-function' to
3145customize how labels are formatted."
3146 (goto-char (point-max))
3147 (let ((index)
3148 (tree))
3149 (while (setq tree (python-imenu--build-tree))
3150 (setq index (cons tree index)))
3151 index))
3152
3153(defun python-imenu-create-flat-index (&optional alist prefix)
3154 "Return flat outline of the current python buffer for Imenu.
3155Optional Argument ALIST is the tree to be flattened, when nil
3156`python-imenu-build-index' is used with
3157`python-imenu-format-parent-item-jump-label-function'
3158`python-imenu-format-parent-item-label-function'
3159`python-imenu-format-item-label-function' set to (lambda (type
3160name) name). Optional Argument PREFIX is used in recursive calls
3161and should not be passed explicitly.
3162
3163Converts this:
3164
3165 \((\"Foo\" . 103)
3166 (\"Bar\" . 138)
3167 (\"decorator\"
3168 (\"decorator\" . 173)
3169 (\"wrap\"
3170 (\"wrap\" . 353)
3171 (\"wrapped_f\" . 393))))
3172
3173To this:
3174
3175 \((\"Foo\" . 103)
3176 (\"Bar\" . 138)
3177 (\"decorator\" . 173)
3178 (\"decorator.wrap\" . 353)
3179 (\"decorator.wrapped_f\" . 393))"
3180 ;; Inspired by imenu--flatten-index-alist removed in revno 21853.
3181 (apply
3182 'nconc
3183 (mapcar
3184 (lambda (item)
3185 (let ((name (if prefix
3186 (concat prefix "." (car item))
3187 (car item)))
3188 (pos (cdr item)))
3189 (cond ((or (numberp pos) (markerp pos))
3190 (list (cons name pos)))
3191 ((listp pos)
3192 (cons
3193 (cons name (cdar pos))
3194 (python-imenu-create-flat-index (cddr item) name))))))
3195 (or alist
3196 (let* ((fn (lambda (type name) name))
3197 (python-imenu-format-item-label-function fn)
3198 (python-imenu-format-parent-item-label-function fn)
3199 (python-imenu-format-parent-item-jump-label-function fn))
3200 (python-imenu-create-index))))))
2940 3201
2941 3202
2942;;; Misc helpers 3203;;; Misc helpers
@@ -3257,6 +3518,22 @@ Optional argument DIRECTION defines the direction to move to."
3257 (goto-char comment-start)) 3518 (goto-char comment-start))
3258 (forward-comment factor))) 3519 (forward-comment factor)))
3259 3520
3521(defun python-util-popn (lst n)
3522 "Return LST first N elements.
3523N should be an integer, when it's a natural negative number its
3524opposite is used. When N is bigger than the length of LST, the
3525list is returned as is."
3526 (let* ((n (min (abs n)))
3527 (len (length lst))
3528 (acc))
3529 (if (> n len)
3530 lst
3531 (while (< 0 n)
3532 (setq acc (cons (car lst) acc)
3533 lst (cdr lst)
3534 n (1- n)))
3535 (reverse acc))))
3536
3260 3537
3261;;;###autoload 3538;;;###autoload
3262(define-derived-mode python-mode prog-mode "Python" 3539(define-derived-mode python-mode prog-mode "Python"
@@ -3302,11 +3579,8 @@ if that value is non-nil."
3302 (add-hook 'post-self-insert-hook 3579 (add-hook 'post-self-insert-hook
3303 'python-indent-post-self-insert-function nil 'local) 3580 'python-indent-post-self-insert-function nil 'local)
3304 3581
3305 (set (make-local-variable 'imenu-extract-index-name-function) 3582 (set (make-local-variable 'imenu-create-index-function)
3306 #'python-info-current-defun) 3583 #'python-imenu-create-index)
3307
3308 (set (make-local-variable 'imenu-prev-index-position-function)
3309 #'python-imenu-prev-index-position)
3310 3584
3311 (set (make-local-variable 'add-log-current-defun-function) 3585 (set (make-local-variable 'add-log-current-defun-function)
3312 #'python-info-current-defun) 3586 #'python-info-current-defun)
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 6e471d1aa2a..fa4efe49b7b 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -113,7 +113,7 @@
113 "Regexp to match the beginning of a heredoc.") 113 "Regexp to match the beginning of a heredoc.")
114 114
115 (defconst ruby-expression-expansion-re 115 (defconst ruby-expression-expansion-re
116 "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)")) 116 "\\(?:[^\\]\\|\\=\\)\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)"))
117 117
118(defun ruby-here-doc-end-match () 118(defun ruby-here-doc-end-match ()
119 "Return a regexp to find the end of a heredoc. 119 "Return a regexp to find the end of a heredoc.
@@ -148,13 +148,16 @@ This should only be called after matching against `ruby-here-doc-beg-re'."
148(define-abbrev-table 'ruby-mode-abbrev-table () 148(define-abbrev-table 'ruby-mode-abbrev-table ()
149 "Abbrev table in use in Ruby mode buffers.") 149 "Abbrev table in use in Ruby mode buffers.")
150 150
151(defvar ruby-use-smie nil)
152
151(defvar ruby-mode-map 153(defvar ruby-mode-map
152 (let ((map (make-sparse-keymap))) 154 (let ((map (make-sparse-keymap)))
153 (define-key map (kbd "M-C-b") 'ruby-backward-sexp) 155 (unless ruby-use-smie
154 (define-key map (kbd "M-C-f") 'ruby-forward-sexp) 156 (define-key map (kbd "M-C-b") 'ruby-backward-sexp)
157 (define-key map (kbd "M-C-f") 'ruby-forward-sexp)
158 (define-key map (kbd "M-C-q") 'ruby-indent-exp))
155 (define-key map (kbd "M-C-p") 'ruby-beginning-of-block) 159 (define-key map (kbd "M-C-p") 'ruby-beginning-of-block)
156 (define-key map (kbd "M-C-n") 'ruby-end-of-block) 160 (define-key map (kbd "M-C-n") 'ruby-end-of-block)
157 (define-key map (kbd "M-C-q") 'ruby-indent-exp)
158 (define-key map (kbd "C-c {") 'ruby-toggle-block) 161 (define-key map (kbd "C-c {") 'ruby-toggle-block)
159 map) 162 map)
160 "Keymap used in Ruby mode.") 163 "Keymap used in Ruby mode.")
@@ -236,6 +239,111 @@ Also ignores spaces after parenthesis when 'space."
236(put 'ruby-comment-column 'safe-local-variable 'integerp) 239(put 'ruby-comment-column 'safe-local-variable 'integerp)
237(put 'ruby-deep-arglist 'safe-local-variable 'booleanp) 240(put 'ruby-deep-arglist 'safe-local-variable 'booleanp)
238 241
242;;; SMIE support
243
244(require 'smie)
245
246(defconst ruby-smie-grammar
247 ;; FIXME: Add support for Cucumber.
248 (smie-prec2->grammar
249 (smie-bnf->prec2
250 '((id)
251 (insts (inst) (insts ";" insts))
252 (inst (exp) (inst "iuwu-mod" exp))
253 (exp (exp1) (exp "," exp))
254 (exp1 (exp2) (exp2 "?" exp1 ":" exp1))
255 (exp2 ("def" insts "end")
256 ("begin" insts-rescue-insts "end")
257 ("do" insts "end")
258 ("class" insts "end") ("module" insts "end")
259 ("for" for-body "end")
260 ("[" expseq "]")
261 ("{" hashvals "}")
262 ("while" insts "end")
263 ("until" insts "end")
264 ("unless" insts "end")
265 ("if" if-body "end")
266 ("case" cases "end"))
267 (for-body (for-head ";" insts))
268 (for-head (id "in" exp))
269 (cases (exp "then" insts) ;; FIXME: Ruby also allows (exp ":" insts).
270 (cases "when" cases) (insts "else" insts))
271 (expseq (exp) );;(expseq "," expseq)
272 (hashvals (id "=>" exp1) (hashvals "," hashvals))
273 (insts-rescue-insts (insts)
274 (insts-rescue-insts "rescue" insts-rescue-insts)
275 (insts-rescue-insts "ensure" insts-rescue-insts))
276 (itheni (insts) (exp "then" insts))
277 (ielsei (itheni) (itheni "else" insts))
278 (if-body (ielsei) (if-body "elsif" if-body)))
279 '((nonassoc "in") (assoc ";") (assoc ","))
280 '((assoc "when"))
281 '((assoc "elsif"))
282 '((assoc "rescue" "ensure"))
283 '((assoc ",")))))
284
285(defun ruby-smie--bosp ()
286 (save-excursion (skip-chars-backward " \t")
287 (or (bolp) (eq (char-before) ?\;))))
288
289(defun ruby-smie--implicit-semi-p ()
290 (save-excursion
291 (skip-chars-backward " \t")
292 (not (or (bolp)
293 (memq (char-before) '(?\; ?- ?+ ?* ?/ ?:))
294 (and (memq (char-before) '(?\? ?=))
295 (not (memq (char-syntax (char-before (1- (point))))
296 '(?w ?_))))))))
297
298(defun ruby-smie--forward-token ()
299 (skip-chars-forward " \t")
300 (if (and (looking-at "[\n#]")
301 ;; Only add implicit ; when needed.
302 (ruby-smie--implicit-semi-p))
303 (progn
304 (if (eolp) (forward-char 1) (forward-comment 1))
305 ";")
306 (forward-comment (point-max))
307 (let ((tok (smie-default-forward-token)))
308 (cond
309 ((member tok '("unless" "if" "while" "until"))
310 (if (save-excursion (forward-word -1) (ruby-smie--bosp))
311 tok "iuwu-mod"))
312 (t tok)))))
313
314(defun ruby-smie--backward-token ()
315 (let ((pos (point)))
316 (forward-comment (- (point)))
317 (if (and (> pos (line-end-position))
318 (ruby-smie--implicit-semi-p))
319 (progn (skip-chars-forward " \t")
320 ";")
321 (let ((tok (smie-default-backward-token)))
322 (cond
323 ((member tok '("unless" "if" "while" "until"))
324 (if (ruby-smie--bosp)
325 tok "iuwu-mod"))
326 (t tok))))))
327
328(defun ruby-smie-rules (kind token)
329 (pcase (cons kind token)
330 (`(:elem . basic) ruby-indent-level)
331 (`(:after . ";")
332 (if (smie-rule-parent-p "def" "begin" "do" "class" "module" "for"
333 "[" "{" "while" "until" "unless"
334 "if" "then" "elsif" "else" "when"
335 "rescue" "ensure")
336 (smie-rule-parent ruby-indent-level)
337 ;; For (invalid) code between switch and case.
338 ;; (if (smie-parent-p "switch") 4)
339 0))
340 (`(:before . ,(or `"else" `"then" `"elsif")) 0)
341 (`(:before . ,(or `"when"))
342 (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level
343 ;; Hack attack: Since newlines are separators, don't try to align args that
344 ;; appear on a separate line.
345 (`(:list-intro . ";") t)))
346
239(defun ruby-imenu-create-index-in-block (prefix beg end) 347(defun ruby-imenu-create-index-in-block (prefix beg end)
240 "Create an imenu index of methods inside a block." 348 "Create an imenu index of methods inside a block."
241 (let ((index-alist '()) (case-fold-search nil) 349 (let ((index-alist '()) (case-fold-search nil)
@@ -290,7 +398,11 @@ Also ignores spaces after parenthesis when 'space."
290 (set-syntax-table ruby-mode-syntax-table) 398 (set-syntax-table ruby-mode-syntax-table)
291 (setq local-abbrev-table ruby-mode-abbrev-table) 399 (setq local-abbrev-table ruby-mode-abbrev-table)
292 (setq indent-tabs-mode ruby-indent-tabs-mode) 400 (setq indent-tabs-mode ruby-indent-tabs-mode)
293 (set (make-local-variable 'indent-line-function) 'ruby-indent-line) 401 (if ruby-use-smie
402 (smie-setup ruby-smie-grammar #'ruby-smie-rules
403 :forward-token #'ruby-smie--forward-token
404 :backward-token #'ruby-smie--backward-token)
405 (set (make-local-variable 'indent-line-function) 'ruby-indent-line))
294 (set (make-local-variable 'require-final-newline) t) 406 (set (make-local-variable 'require-final-newline) t)
295 (set (make-local-variable 'comment-start) "# ") 407 (set (make-local-variable 'comment-start) "# ")
296 (set (make-local-variable 'comment-end) "") 408 (set (make-local-variable 'comment-end) "")
@@ -847,22 +959,24 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'."
847 indent)))) 959 indent))))
848 960
849(defun ruby-beginning-of-defun (&optional arg) 961(defun ruby-beginning-of-defun (&optional arg)
850 "Move backward to the beginning of the current top-level defun. 962 "Move backward to the beginning of the current defun.
851With ARG, move backward multiple defuns. Negative ARG means 963With ARG, move backward multiple defuns. Negative ARG means
852move forward." 964move forward."
853 (interactive "p") 965 (interactive "p")
854 (and (re-search-backward (concat "^\\s *" ruby-defun-beg-re "\\_>") 966 (let (case-fold-search)
855 nil t (or arg 1)) 967 (and (re-search-backward (concat "^\\s *" ruby-defun-beg-re "\\_>")
856 (beginning-of-line))) 968 nil t (or arg 1))
857 969 (beginning-of-line))))
858(defun ruby-end-of-defun (&optional arg) 970
859 "Move forward to the end of the current top-level defun. 971(defun ruby-end-of-defun ()
860With ARG, move forward multiple defuns. Negative ARG means 972 "Move point to the end of the current defun.
861move backward." 973The defun begins at or after the point. This function is called
974by `end-of-defun'."
862 (interactive "p") 975 (interactive "p")
863 (ruby-forward-sexp) 976 (ruby-forward-sexp)
864 (when (looking-back (concat "^\\s *" ruby-block-end-re)) 977 (let (case-fold-search)
865 (forward-line 1))) 978 (when (looking-back (concat "^\\s *" ruby-block-end-re))
979 (forward-line 1))))
866 980
867(defun ruby-beginning-of-indent () 981(defun ruby-beginning-of-indent ()
868 "Backtrack to a line which can be used as a reference for 982 "Backtrack to a line which can be used as a reference for
@@ -881,6 +995,7 @@ current block, a sibling block, or an outer block. Do that (abs N) times."
881 (depth (or (nth 2 (ruby-parse-region (line-beginning-position) 995 (depth (or (nth 2 (ruby-parse-region (line-beginning-position)
882 (line-end-position))) 996 (line-end-position)))
883 0)) 997 0))
998 case-fold-search
884 down done) 999 down done)
885 (when (< (* depth signum) 0) 1000 (when (< (* depth signum) 0)
886 ;; Moving end -> end or beginning -> beginning. 1001 ;; Moving end -> end or beginning -> beginning.
@@ -1232,6 +1347,9 @@ If the result is do-end block, it will always be multiline."
1232(declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit)) 1347(declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit))
1233(declare-function ruby-syntax-enclosing-percent-literal "ruby-mode" (limit)) 1348(declare-function ruby-syntax-enclosing-percent-literal "ruby-mode" (limit))
1234(declare-function ruby-syntax-propertize-percent-literal "ruby-mode" (limit)) 1349(declare-function ruby-syntax-propertize-percent-literal "ruby-mode" (limit))
1350;; Unusual code layout confuses the byte-compiler.
1351(declare-function ruby-syntax-propertize-expansion "ruby-mode" ())
1352(declare-function ruby-syntax-expansion-allowed-p "ruby-mode" (parse-state))
1235 1353
1236(if (eval-when-compile (fboundp #'syntax-propertize-rules)) 1354(if (eval-when-compile (fboundp #'syntax-propertize-rules))
1237 ;; New code that works independently from font-lock. 1355 ;; New code that works independently from font-lock.
@@ -1245,54 +1363,70 @@ If the result is do-end block, it will always be multiline."
1245 '("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match" 1363 '("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match"
1246 "assert_match" "Given" "Then" "When") 1364 "assert_match" "Given" "Then" "When")
1247 "Methods that can take regexp as the first argument. 1365 "Methods that can take regexp as the first argument.
1248It will be properly highlighted even when the call omits parens.")) 1366It will be properly highlighted even when the call omits parens.")
1367
1368 (defvar ruby-syntax-before-regexp-re
1369 (concat
1370 ;; Special tokens that can't be followed by a division operator.
1371 "\\(^\\|[[=(,~?:;<>]"
1372 ;; Control flow keywords and operators following bol or whitespace.
1373 "\\|\\(?:^\\|\\s \\)"
1374 (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
1375 "or" "not" "&&" "||"))
1376 ;; Method name from the list.
1377 "\\|\\_<"
1378 (regexp-opt ruby-syntax-methods-before-regexp)
1379 "\\)\\s *")
1380 "Regexp to match text that can be followed by a regular expression."))
1249 1381
1250 (defun ruby-syntax-propertize-function (start end) 1382 (defun ruby-syntax-propertize-function (start end)
1251 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." 1383 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
1252 (goto-char start) 1384 (let (case-fold-search)
1253 (ruby-syntax-propertize-heredoc end) 1385 (goto-char start)
1254 (ruby-syntax-enclosing-percent-literal end) 1386 (remove-text-properties start end '(ruby-expansion-match-data))
1255 (funcall 1387 (ruby-syntax-propertize-heredoc end)
1256 (syntax-propertize-rules 1388 (ruby-syntax-enclosing-percent-literal end)
1257 ;; $' $" $` .... are variables. 1389 (funcall
1258 ;; ?' ?" ?` are ascii codes. 1390 (syntax-propertize-rules
1259 ("\\([?$]\\)[#\"'`]" 1391 ;; $' $" $` .... are variables.
1260 (1 (unless (save-excursion 1392 ;; ?' ?" ?` are ascii codes.
1261 ;; Not within a string. 1393 ("\\([?$]\\)[#\"'`]"
1262 (nth 3 (syntax-ppss (match-beginning 0)))) 1394 (1 (unless (save-excursion
1263 (string-to-syntax "\\")))) 1395 ;; Not within a string.
1264 ;; Regexps: regexps are distinguished from division because 1396 (nth 3 (syntax-ppss (match-beginning 0))))
1265 ;; of the keyword, symbol, or method name before them. 1397 (string-to-syntax "\\"))))
1266 ((concat 1398 ;; Regular expressions. Start with matching unescaped slash.
1267 ;; Special tokens that can't be followed by a division operator. 1399 ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)"
1268 "\\(^\\|[[=(,~?:;<>]" 1400 (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1)))))
1269 ;; Control flow keywords and operators following bol or whitespace. 1401 (when (or
1270 "\\|\\(?:^\\|\\s \\)" 1402 ;; Beginning of a regexp.
1271 (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and" 1403 (and (null (nth 8 state))
1272 "or" "not" "&&" "||")) 1404 (save-excursion
1273 ;; Method name from the list. 1405 (forward-char -1)
1274 "\\|\\_<" 1406 (looking-back ruby-syntax-before-regexp-re
1275 (regexp-opt ruby-syntax-methods-before-regexp) 1407 (point-at-bol))))
1276 "\\)\\s *" 1408 ;; End of regexp. We don't match the whole
1277 ;; The regular expression itself. 1409 ;; regexp at once because it can have
1278 "\\(/\\)[^/\n\\\\]*\\(?:\\\\.[^/\n\\\\]*\\)*\\(/\\)") 1410 ;; string interpolation inside, or span
1279 (3 (unless (nth 3 (syntax-ppss (match-beginning 2))) 1411 ;; several lines.
1280 (put-text-property (match-beginning 2) (match-end 2) 1412 (eq ?/ (nth 3 state)))
1281 'syntax-table (string-to-syntax "\"/")) 1413 (string-to-syntax "\"/")))))
1282 (string-to-syntax "\"/")))) 1414 ;; Expression expansions in strings. We're handling them
1283 ("^=en\\(d\\)\\_>" (1 "!")) 1415 ;; here, so that the regexp rule never matches inside them.
1284 ("^\\(=\\)begin\\_>" (1 "!")) 1416 (ruby-expression-expansion-re
1285 ;; Handle here documents. 1417 (0 (ignore (ruby-syntax-propertize-expansion))))
1286 ((concat ruby-here-doc-beg-re ".*\\(\n\\)") 1418 ("^=en\\(d\\)\\_>" (1 "!"))
1287 (7 (unless (ruby-singleton-class-p (match-beginning 0)) 1419 ("^\\(=\\)begin\\_>" (1 "!"))
1288 (put-text-property (match-beginning 7) (match-end 7) 1420 ;; Handle here documents.
1289 'syntax-table (string-to-syntax "\"")) 1421 ((concat ruby-here-doc-beg-re ".*\\(\n\\)")
1290 (ruby-syntax-propertize-heredoc end)))) 1422 (7 (unless (ruby-singleton-class-p (match-beginning 0))
1291 ;; Handle percent literals: %w(), %q{}, etc. 1423 (put-text-property (match-beginning 7) (match-end 7)
1292 ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re) 1424 'syntax-table (string-to-syntax "\""))
1293 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) 1425 (ruby-syntax-propertize-heredoc end))))
1294 (point) end) 1426 ;; Handle percent literals: %w(), %q{}, etc.
1295 (ruby-syntax-propertize-expansions start end)) 1427 ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re)
1428 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end)))))
1429 (point) end)))
1296 1430
1297 (defun ruby-syntax-propertize-heredoc (limit) 1431 (defun ruby-syntax-propertize-heredoc (limit)
1298 (let ((ppss (syntax-ppss)) 1432 (let ((ppss (syntax-ppss))
@@ -1305,7 +1439,7 @@ It will be properly highlighted even when the call omits parens."))
1305 (line-end-position) t) 1439 (line-end-position) t)
1306 (unless (ruby-singleton-class-p (match-beginning 0)) 1440 (unless (ruby-singleton-class-p (match-beginning 0))
1307 (push (concat (ruby-here-doc-end-match) "\n") res)))) 1441 (push (concat (ruby-here-doc-end-match) "\n") res))))
1308 (let ((start (point))) 1442 (save-excursion
1309 ;; With multiple openers on the same line, we don't know in which 1443 ;; With multiple openers on the same line, we don't know in which
1310 ;; part `start' is, so we have to go back to the beginning. 1444 ;; part `start' is, so we have to go back to the beginning.
1311 (when (cdr res) 1445 (when (cdr res)
@@ -1315,9 +1449,9 @@ It will be properly highlighted even when the call omits parens."))
1315 (if (null res) 1449 (if (null res)
1316 (put-text-property (1- (point)) (point) 1450 (put-text-property (1- (point)) (point)
1317 'syntax-table (string-to-syntax "\"")))) 1451 'syntax-table (string-to-syntax "\""))))
1318 ;; Make extra sure we don't move back, lest we could fall into an 1452 ;; End up at bol following the heredoc openers.
1319 ;; inf-loop. 1453 ;; Propertize expression expansions from this point forward.
1320 (if (< (point) start) (goto-char start)))))) 1454 ))))
1321 1455
1322 (defun ruby-syntax-enclosing-percent-literal (limit) 1456 (defun ruby-syntax-enclosing-percent-literal (limit)
1323 (let ((state (syntax-ppss)) 1457 (let ((state (syntax-ppss))
@@ -1338,44 +1472,59 @@ It will be properly highlighted even when the call omits parens."))
1338 (cl (or (cdr (aref (syntax-table) op)) 1472 (cl (or (cdr (aref (syntax-table) op))
1339 (cdr (assoc op '((?< . ?>)))))) 1473 (cdr (assoc op '((?< . ?>))))))
1340 parse-sexp-lookup-properties) 1474 parse-sexp-lookup-properties)
1341 (condition-case nil 1475 (save-excursion
1342 (progn 1476 (condition-case nil
1343 (if cl ; Paired delimiters. 1477 (progn
1344 ;; Delimiter pairs of the same kind can be nested 1478 (if cl ; Paired delimiters.
1345 ;; inside the literal, as long as they are balanced. 1479 ;; Delimiter pairs of the same kind can be nested
1346 ;; Create syntax table that ignores other characters. 1480 ;; inside the literal, as long as they are balanced.
1347 (with-syntax-table (make-char-table 'syntax-table nil) 1481 ;; Create syntax table that ignores other characters.
1348 (modify-syntax-entry op (concat "(" (char-to-string cl))) 1482 (with-syntax-table (make-char-table 'syntax-table nil)
1349 (modify-syntax-entry cl (concat ")" ops)) 1483 (modify-syntax-entry op (concat "(" (char-to-string cl)))
1350 (modify-syntax-entry ?\\ "\\") 1484 (modify-syntax-entry cl (concat ")" ops))
1351 (save-restriction 1485 (modify-syntax-entry ?\\ "\\")
1352 (narrow-to-region (point) limit) 1486 (save-restriction
1353 (forward-list))) ; skip to the paired character 1487 (narrow-to-region (point) limit)
1354 ;; Single character delimiter. 1488 (forward-list))) ; skip to the paired character
1355 (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*" 1489 ;; Single character delimiter.
1356 (regexp-quote ops)) limit nil)) 1490 (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
1357 ;; Found the closing delimiter. 1491 (regexp-quote ops)) limit nil))
1358 (put-text-property (1- (point)) (point) 'syntax-table 1492 ;; Found the closing delimiter.
1359 (string-to-syntax "|"))) 1493 (put-text-property (1- (point)) (point) 'syntax-table
1360 ;; Unclosed literal, leave the following text unpropertized. 1494 (string-to-syntax "|")))
1361 ((scan-error search-failed) (goto-char limit)))))) 1495 ;; Unclosed literal, do nothing.
1496 ((scan-error search-failed)))))))
1497
1498 (defun ruby-syntax-propertize-expansion ()
1499 ;; Save the match data to a text property, for font-locking later.
1500 ;; Set the syntax of all double quotes and backticks to punctuation.
1501 (let* ((beg (match-beginning 2))
1502 (end (match-end 2))
1503 (state (and beg (save-excursion (syntax-ppss beg)))))
1504 (when (ruby-syntax-expansion-allowed-p state)
1505 (put-text-property beg (1+ beg) 'ruby-expansion-match-data
1506 (match-data))
1507 (goto-char beg)
1508 (while (re-search-forward "[\"`]" end 'move)
1509 (put-text-property (match-beginning 0) (match-end 0)
1510 'syntax-table (string-to-syntax "."))))))
1511
1512 (defun ruby-syntax-expansion-allowed-p (parse-state)
1513 "Return non-nil if expression expansion is allowed."
1514 (let ((term (nth 3 parse-state)))
1515 (cond
1516 ((memq term '(?\" ?` ?\n ?/)))
1517 ((eq term t)
1518 (save-match-data
1519 (save-excursion
1520 (goto-char (nth 8 parse-state))
1521 (looking-at "%\\(?:[QWrx]\\|\\W\\)")))))))
1362 1522
1363 (defun ruby-syntax-propertize-expansions (start end) 1523 (defun ruby-syntax-propertize-expansions (start end)
1364 (remove-text-properties start end '(ruby-expansion-match-data)) 1524 (save-excursion
1365 (goto-char start) 1525 (goto-char start)
1366 ;; Find all expression expansions and 1526 (while (re-search-forward ruby-expression-expansion-re end 'move)
1367 ;; - save the match data to a text property, for font-locking later, 1527 (ruby-syntax-propertize-expansion))))
1368 ;; - set the syntax of all double quotes and backticks to punctuation.
1369 (while (re-search-forward ruby-expression-expansion-re end 'move)
1370 (let ((beg (match-beginning 2))
1371 (end (match-end 2)))
1372 (when (and beg (save-excursion (nth 3 (syntax-ppss beg))))
1373 (put-text-property beg (1+ beg) 'ruby-expansion-match-data
1374 (match-data))
1375 (goto-char beg)
1376 (while (re-search-forward "[\"`]" end 'move)
1377 (put-text-property (match-beginning 0) (match-end 0)
1378 'syntax-table (string-to-syntax ".")))))))
1379 ) 1528 )
1380 1529
1381 ;; For Emacsen where syntax-propertize-rules is not (yet) available, 1530 ;; For Emacsen where syntax-propertize-rules is not (yet) available,
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 8f1954402e5..07e9bb85c4e 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -335,11 +335,11 @@ shell it really is."
335 . ((nil 335 . ((nil
336 ;; function FOO 336 ;; function FOO
337 ;; function FOO() 337 ;; function FOO()
338 "^\\s-*function\\s-+\\\([[:alpha:]_][[:alnum:]_]+\\)\\s-*\\(?:()\\)?" 338 "^\\s-*function\\s-+\\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*\\(?:()\\)?"
339 1) 339 1)
340 ;; FOO() 340 ;; FOO()
341 (nil 341 (nil
342 "^\\s-*\\([[:alpha:]_][[:alnum:]_]+\\)\\s-*()" 342 "^\\s-*\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*()"
343 1) 343 1)
344 ))) 344 )))
345 "Alist of regular expressions for recognizing shell function definitions. 345 "Alist of regular expressions for recognizing shell function definitions.
@@ -353,6 +353,28 @@ See `sh-feature' and `imenu-generic-expression'."
353 :group 'sh-script 353 :group 'sh-script
354 :version "20.4") 354 :version "20.4")
355 355
356(defun sh-current-defun-name ()
357 "Find the name of function or variable at point.
358For use in `add-log-current-defun-function'."
359 (save-excursion
360 (end-of-line)
361 (when (re-search-backward
362 (concat "\\(?:"
363 ;; function FOO
364 ;; function FOO()
365 "^\\s-*function\\s-+\\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*\\(?:()\\)?"
366 "\\)\\|\\(?:"
367 ;; FOO()
368 "^\\s-*\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*()"
369 "\\)\\|\\(?:"
370 ;; FOO=
371 "^\\([[:alpha:]_][[:alnum:]_]*\\)="
372 "\\)")
373 nil t)
374 (or (match-string-no-properties 1)
375 (match-string-no-properties 2)
376 (match-string-no-properties 3)))))
377
356(defvar sh-shell-variables nil 378(defvar sh-shell-variables nil
357 "Alist of shell variable names that should be included in completion. 379 "Alist of shell variable names that should be included in completion.
358These are used for completion in addition to all the variables named 380These are used for completion in addition to all the variables named
@@ -1533,6 +1555,7 @@ with your script for an edit-interpret-debug cycle."
1533 (setq-local skeleton-newline-indent-rigidly t) 1555 (setq-local skeleton-newline-indent-rigidly t)
1534 (setq-local defun-prompt-regexp 1556 (setq-local defun-prompt-regexp
1535 (concat "^\\(function[ \t]\\|[[:alnum:]]+[ \t]+()[ \t]+\\)")) 1557 (concat "^\\(function[ \t]\\|[[:alnum:]]+[ \t]+()[ \t]+\\)"))
1558 (setq-local add-log-current-defun-function #'sh-current-defun-name)
1536 ;; Parse or insert magic number for exec, and set all variables depending 1559 ;; Parse or insert magic number for exec, and set all variables depending
1537 ;; on the shell thus determined. 1560 ;; on the shell thus determined.
1538 (sh-set-shell 1561 (sh-set-shell
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 3cf6757d5ec..940afc3d5f4 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -285,36 +285,49 @@ file. Since that is a plaintext file, this could be dangerous."
285 285
286(define-widget 'sql-login-params 'lazy 286(define-widget 'sql-login-params 'lazy
287 "Widget definition of the login parameters list" 287 "Widget definition of the login parameters list"
288 ;; FIXME: does not implement :default property for the user,
289 ;; database and server options. Anybody have some guidance on how to
290 ;; do this.
291 :tag "Login Parameters" 288 :tag "Login Parameters"
292 :type '(repeat (choice 289 :type '(set :tag "Login Parameters"
293 (const user) 290 (choice :tag "user"
294 (const password) 291 :value user
295 (choice :tag "server" 292 (const user)
296 (const server) 293 (list :tag "Specify a default"
297 (list :tag "file" 294 (const user)
298 (const :format "" server) 295 (list :tag "Default"
299 (const :format "" :file) 296 :inline t (const :default) string)))
300 regexp) 297 (const password)
301 (list :tag "completion" 298 (choice :tag "server"
302 (const :format "" server) 299 :value server
300 (const server)
301 (list :tag "Specify a default"
302 (const server)
303 (list :tag "Default"
304 :inline t (const :default) string))
305 (list :tag "file"
306 (const :format "" server)
307 (const :format "" :file)
308 regexp)
309 (list :tag "completion"
310 (const :format "" server)
311 (const :format "" :completion)
312 (restricted-sexp
313 :match-alternatives (listp stringp))))
314 (choice :tag "database"
315 :value database
316 (const database)
317 (list :tag "Specify a default"
318 (const database)
319 (list :tag "Default"
320 :inline t (const :default) string))
321 (list :tag "file"
322 (const :format "" database)
323 (const :format "" :file)
324 regexp)
325 (list :tag "completion"
326 (const :format "" database)
303 (const :format "" :completion) 327 (const :format "" :completion)
304 (restricted-sexp 328 (restricted-sexp
305 :match-alternatives (listp stringp)))) 329 :match-alternatives (listp stringp))))
306 (choice :tag "database" 330 (const port)))
307 (const database)
308 (list :tag "file"
309 (const :format "" database)
310 (const :format "" :file)
311 regexp)
312 (list :tag "completion"
313 (const :format "" database)
314 (const :format "" :completion)
315 (restricted-sexp
316 :match-alternatives (listp stringp))))
317 (const port))))
318 331
319;; SQL Product support 332;; SQL Product support
320 333
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index 80e632c6ef6..a75bdff27bd 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -26,7 +26,8 @@
26 26
27;; This package provides `subword' oriented commands and a minor mode 27;; This package provides `subword' oriented commands and a minor mode
28;; (`subword-mode') that substitutes the common word handling 28;; (`subword-mode') that substitutes the common word handling
29;; functions with them. 29;; functions with them. It also provides the `superword-mode' minor
30;; mode that treats symbols as words, the opposite of `subword-mode'.
30 31
31;; In spite of GNU Coding Standards, it is popular to name a symbol by 32;; In spite of GNU Coding Standards, it is popular to name a symbol by
32;; mixing uppercase and lowercase letters, e.g. "GtkWidget", 33;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
@@ -43,12 +44,13 @@
43 44
44;; The subword oriented commands defined in this package recognize 45;; The subword oriented commands defined in this package recognize
45;; subwords in a nomenclature to move between them and to edit them as 46;; subwords in a nomenclature to move between them and to edit them as
46;; words. 47;; words. You also get a mode to treat symbols as words instead,
48;; called `superword-mode' (the opposite of `subword-mode').
47 49
48;; In the minor mode, all common key bindings for word oriented 50;; In the minor mode, all common key bindings for word oriented
49;; commands are overridden by the subword oriented commands: 51;; commands are overridden by the subword oriented commands:
50 52
51;; Key Word oriented command Subword oriented command 53;; Key Word oriented command Subword oriented command (also superword)
52;; ============================================================ 54;; ============================================================
53;; M-f `forward-word' `subword-forward' 55;; M-f `forward-word' `subword-forward'
54;; M-b `backward-word' `subword-backward' 56;; M-b `backward-word' `subword-backward'
@@ -67,8 +69,13 @@
67;; To make the mode turn on automatically, put the following code in 69;; To make the mode turn on automatically, put the following code in
68;; your .emacs: 70;; your .emacs:
69;; 71;;
70;; (add-hook 'c-mode-common-hook 72;; (add-hook 'c-mode-common-hook 'subword-mode)
71;; (lambda () (subword-mode 1))) 73;;
74
75;; To make the mode turn `superword-mode' on automatically for
76;; only some modes, put the following code in your .emacs:
77;;
78;; (add-hook 'c-mode-common-hook 'superword-mode)
72;; 79;;
73 80
74;; Acknowledgment: 81;; Acknowledgment:
@@ -98,7 +105,8 @@
98 (let ((map (make-sparse-keymap))) 105 (let ((map (make-sparse-keymap)))
99 (dolist (cmd '(forward-word backward-word mark-word kill-word 106 (dolist (cmd '(forward-word backward-word mark-word kill-word
100 backward-kill-word transpose-words 107 backward-kill-word transpose-words
101 capitalize-word upcase-word downcase-word)) 108 capitalize-word upcase-word downcase-word
109 left-word right-word))
102 (let ((othercmd (let ((name (symbol-name cmd))) 110 (let ((othercmd (let ((name (symbol-name cmd)))
103 (string-match "\\([[:alpha:]-]+\\)-word[s]?" name) 111 (string-match "\\([[:alpha:]-]+\\)-word[s]?" name)
104 (intern (concat "subword-" (match-string 1 name)))))) 112 (intern (concat "subword-" (match-string 1 name))))))
@@ -133,21 +141,21 @@ subwords in a nomenclature to move between subwords and to edit them
133as words. 141as words.
134 142
135\\{subword-mode-map}" 143\\{subword-mode-map}"
136 nil 144 :lighter " ,"
137 nil 145 (when subword-mode (superword-mode -1)))
138 subword-mode-map)
139 146
140(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2") 147(define-obsolete-function-alias 'c-subword-mode 'subword-mode "23.2")
141 148
142;;;###autoload 149;;;###autoload
143(define-global-minor-mode global-subword-mode subword-mode 150(define-global-minor-mode global-subword-mode subword-mode
144 (lambda () (subword-mode 1))) 151 (lambda () (subword-mode 1))
152 :group 'convenience)
145 153
146(defun subword-forward (&optional arg) 154(defun subword-forward (&optional arg)
147 "Do the same as `forward-word' but on subwords. 155 "Do the same as `forward-word' but on subwords.
148See the command `subword-mode' for a description of subwords. 156See the command `subword-mode' for a description of subwords.
149Optional argument ARG is the same as for `forward-word'." 157Optional argument ARG is the same as for `forward-word'."
150 (interactive "p") 158 (interactive "^p")
151 (unless arg (setq arg 1)) 159 (unless arg (setq arg 1))
152 (cond 160 (cond
153 ((< 0 arg) 161 ((< 0 arg)
@@ -165,9 +173,23 @@ Optional argument ARG is the same as for `forward-word'."
165 "Do the same as `backward-word' but on subwords. 173 "Do the same as `backward-word' but on subwords.
166See the command `subword-mode' for a description of subwords. 174See the command `subword-mode' for a description of subwords.
167Optional argument ARG is the same as for `backward-word'." 175Optional argument ARG is the same as for `backward-word'."
168 (interactive "p") 176 (interactive "^p")
169 (subword-forward (- (or arg 1)))) 177 (subword-forward (- (or arg 1))))
170 178
179(defun subword-right (&optional arg)
180 "Do the same as `right-word' but on subwords."
181 (interactive "^p")
182 (if (eq (current-bidi-paragraph-direction) 'left-to-right)
183 (subword-forward arg)
184 (subword-backward arg)))
185
186(defun subword-left (&optional arg)
187 "Do the same as `left-word' but on subwords."
188 (interactive "^p")
189 (if (eq (current-bidi-paragraph-direction) 'left-to-right)
190 (subword-backward arg)
191 (subword-forward arg)))
192
171(defun subword-mark (arg) 193(defun subword-mark (arg)
172 "Do the same as `mark-word' but on subwords. 194 "Do the same as `mark-word' but on subwords.
173See the command `subword-mode' for a description of subwords. 195See the command `subword-mode' for a description of subwords.
@@ -254,41 +276,74 @@ Optional argument ARG is the same as for `capitalize-word'."
254 (unless advance 276 (unless advance
255 (goto-char start)))) 277 (goto-char start))))
256 278
279
280
281(defvar superword-mode-map subword-mode-map
282 "Keymap used in `superword-mode' minor mode.")
283
284;;;###autoload
285(define-minor-mode superword-mode
286 "Toggle superword movement and editing (Superword mode).
287With a prefix argument ARG, enable Superword mode if ARG is
288positive, and disable it otherwise. If called from Lisp, enable
289the mode if ARG is omitted or nil.
290
291Superword mode is a buffer-local minor mode. Enabling it remaps
292word-based editing commands to superword-based commands that
293treat symbols as words, e.g. \"this_is_a_symbol\".
294
295The superword oriented commands activated in this minor mode
296recognize symbols as superwords to move between superwords and to
297edit them as words.
298
299\\{superword-mode-map}"
300 :lighter " ²"
301 (when superword-mode (subword-mode -1)))
302
303;;;###autoload
304(define-global-minor-mode global-superword-mode superword-mode
305 (lambda () (superword-mode 1))
306 :group 'convenience)
257 307
258 308
259;; 309;;
260;; Internal functions 310;; Internal functions
261;; 311;;
262(defun subword-forward-internal () 312(defun subword-forward-internal ()
263 (if (and 313 (if superword-mode
264 (save-excursion 314 (forward-symbol 1)
265 (let ((case-fold-search nil)) 315 (if (and
266 (re-search-forward subword-forward-regexp nil t))) 316 (save-excursion
267 (> (match-end 0) (point))) 317 (let ((case-fold-search nil))
268 (goto-char 318 (re-search-forward subword-forward-regexp nil t)))
269 (cond 319 (> (match-end 0) (point)))
270 ((< 1 (- (match-end 2) (match-beginning 2))) 320 (goto-char
271 (1- (match-end 2))) 321 (cond
272 (t 322 ((< 1 (- (match-end 2) (match-beginning 2)))
273 (match-end 0)))) 323 (1- (match-end 2)))
274 (forward-word 1))) 324 (t
275 325 (match-end 0))))
326 (forward-word 1))))
276 327
277(defun subword-backward-internal () 328(defun subword-backward-internal ()
278 (if (save-excursion 329 (if superword-mode
279 (let ((case-fold-search nil)) 330 (forward-symbol -1)
280 (re-search-backward subword-backward-regexp nil t))) 331 (if (save-excursion
281 (goto-char 332 (let ((case-fold-search nil))
282 (cond 333 (re-search-backward subword-backward-regexp nil t)))
283 ((and (match-end 3) 334 (goto-char
284 (< 1 (- (match-end 3) (match-beginning 3))) 335 (cond
285 (not (eq (point) (match-end 3)))) 336 ((and (match-end 3)
286 (1- (match-end 3))) 337 (< 1 (- (match-end 3) (match-beginning 3)))
287 (t 338 (not (eq (point) (match-end 3))))
288 (1+ (match-beginning 0))))) 339 (1- (match-end 3)))
289 (backward-word 1))) 340 (t
341 (1+ (match-beginning 0)))))
342 (backward-word 1))))
290 343
291 344
345
292(provide 'subword) 346(provide 'subword)
347(provide 'superword)
293 348
294;;; subword.el ends here 349;;; subword.el ends here
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index 9169a433015..3e91aeba9a1 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -266,7 +266,7 @@ quoted for Tcl."
266 ;; Maybe someone has a better set? 266 ;; Maybe someone has a better set?
267 (let ((map (make-sparse-keymap))) 267 (let ((map (make-sparse-keymap)))
268 ;; Will inherit from `comint-mode-map' thanks to define-derived-mode. 268 ;; Will inherit from `comint-mode-map' thanks to define-derived-mode.
269 (define-key map "\t" 'comint-dynamic-complete) 269 (define-key map "\t" 'completion-at-point)
270 (define-key map "\M-?" 'comint-dynamic-list-filename-completions) 270 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
271 (define-key map "\177" 'backward-delete-char-untabify) 271 (define-key map "\177" 'backward-delete-char-untabify)
272 (define-key map "\M-\C-x" 'tcl-eval-defun) 272 (define-key map "\M-\C-x" 'tcl-eval-defun)
diff --git a/lisp/progmodes/vera-mode.el b/lisp/progmodes/vera-mode.el
index 7b59faca261..443472192be 100644
--- a/lisp/progmodes/vera-mode.el
+++ b/lisp/progmodes/vera-mode.el
@@ -101,6 +101,8 @@ select and move operations. All parts of an identifier separated by underscore
101are treated as single words otherwise." 101are treated as single words otherwise."
102 :type 'boolean 102 :type 'boolean
103 :group 'vera) 103 :group 'vera)
104(make-obsolete-variable 'vera-underscore-is-part-of-word
105 'superword-mode "24.4")
104 106
105(defcustom vera-intelligent-tab t 107(defcustom vera-intelligent-tab t
106 "Non-nil means `TAB' does indentation, word completion and tab insertion. 108 "Non-nil means `TAB' does indentation, word completion and tab insertion.
@@ -1353,6 +1355,11 @@ If `vera-intelligent-tab' is nil, always indent line."
1353(defvar vera-expand-upper-case nil) 1355(defvar vera-expand-upper-case nil)
1354 1356
1355(eval-when-compile (require 'hippie-exp)) 1357(eval-when-compile (require 'hippie-exp))
1358(declare-function he-init-string "hippie-exp" (beg end))
1359(declare-function he-dabbrev-beg "hippie-exp" ())
1360(declare-function he-string-member "hippie-exp" (str lst &optional trans-case))
1361(declare-function he-reset-string "hippie-exp" ())
1362(declare-function he-substitute-string "hippie-exp" (str &optional trans-case))
1356 1363
1357(defun vera-try-expand-abbrev (old) 1364(defun vera-try-expand-abbrev (old)
1358 "Try expanding abbreviations from `vera-abbrev-list'." 1365 "Try expanding abbreviations from `vera-abbrev-list'."
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 5571a905f85..ed911fcbba2 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -123,9 +123,9 @@
123;;; Code: 123;;; Code:
124 124
125;; This variable will always hold the version number of the mode 125;; This variable will always hold the version number of the mode
126(defconst verilog-mode-version (substring "$$Revision: 820 $$" 12 -3) 126(defconst verilog-mode-version (substring "$$Revision: 840 $$" 12 -3)
127 "Version of this Verilog mode.") 127 "Version of this Verilog mode.")
128(defconst verilog-mode-release-date (substring "$$Date: 2012-09-17 20:43:10 -0400 (Mon, 17 Sep 2012) $$" 8 -3) 128(defconst verilog-mode-release-date (substring "$$Date: 2013-01-03 05:29:05 -0800 (Thu, 03 Jan 2013) $$" 8 -3)
129 "Release date of this Verilog mode.") 129 "Release date of this Verilog mode.")
130(defconst verilog-mode-release-emacs t 130(defconst verilog-mode-release-emacs t
131 "If non-nil, this version of Verilog mode was released with Emacs itself.") 131 "If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -501,7 +501,7 @@ entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
501 "Type of statements to lineup across multiple lines. 501 "Type of statements to lineup across multiple lines.
502If 'all' is selected, then all line ups described below are done. 502If 'all' is selected, then all line ups described below are done.
503 503
504If 'declaration', then just declarations are lined up with any 504If 'declarations', then just declarations are lined up with any
505preceding declarations, taking into account widths and the like, 505preceding declarations, taking into account widths and the like,
506so or example the code: 506so or example the code:
507 reg [31:0] a; 507 reg [31:0] a;
@@ -964,7 +964,7 @@ See also `verilog-library-flags', `verilog-library-directories'."
964This is used for AUTORESET and AUTOTIEOFF. For proper behavior, 964This is used for AUTORESET and AUTOTIEOFF. For proper behavior,
965you will probably also need `verilog-auto-reset-widths' set." 965you will probably also need `verilog-auto-reset-widths' set."
966 :group 'verilog-mode-auto 966 :group 'verilog-mode-auto
967 :type 'string) 967 :type '(choice (const nil) regexp))
968(put 'verilog-active-low-regexp 'safe-local-variable 'stringp) 968(put 'verilog-active-low-regexp 'safe-local-variable 'stringp)
969 969
970(defcustom verilog-auto-sense-include-inputs nil 970(defcustom verilog-auto-sense-include-inputs nil
@@ -1129,37 +1129,37 @@ won't merge conflict."
1129 1129
1130(defcustom verilog-auto-inst-interfaced-ports nil 1130(defcustom verilog-auto-inst-interfaced-ports nil
1131 "Non-nil means include interfaced ports in AUTOINST expansions." 1131 "Non-nil means include interfaced ports in AUTOINST expansions."
1132 :version "24.3" ;; rev773, default change rev815
1132 :group 'verilog-mode-auto 1133 :group 'verilog-mode-auto
1133 :type 'boolean 1134 :type 'boolean)
1134 :version "24.3")
1135(put 'verilog-auto-inst-interfaced-ports 'safe-local-variable 'verilog-booleanp) 1135(put 'verilog-auto-inst-interfaced-ports 'safe-local-variable 'verilog-booleanp)
1136 1136
1137(defcustom verilog-auto-input-ignore-regexp nil 1137(defcustom verilog-auto-input-ignore-regexp nil
1138 "If set, when creating AUTOINPUT list, ignore signals matching this regexp. 1138 "If set, when creating AUTOINPUT list, ignore signals matching this regexp.
1139See the \\[verilog-faq] for examples on using this." 1139See the \\[verilog-faq] for examples on using this."
1140 :group 'verilog-mode-auto 1140 :group 'verilog-mode-auto
1141 :type 'string) 1141 :type '(choice (const nil) regexp))
1142(put 'verilog-auto-input-ignore-regexp 'safe-local-variable 'stringp) 1142(put 'verilog-auto-input-ignore-regexp 'safe-local-variable 'stringp)
1143 1143
1144(defcustom verilog-auto-inout-ignore-regexp nil 1144(defcustom verilog-auto-inout-ignore-regexp nil
1145 "If set, when creating AUTOINOUT list, ignore signals matching this regexp. 1145 "If set, when creating AUTOINOUT list, ignore signals matching this regexp.
1146See the \\[verilog-faq] for examples on using this." 1146See the \\[verilog-faq] for examples on using this."
1147 :group 'verilog-mode-auto 1147 :group 'verilog-mode-auto
1148 :type 'string) 1148 :type '(choice (const nil) regexp))
1149(put 'verilog-auto-inout-ignore-regexp 'safe-local-variable 'stringp) 1149(put 'verilog-auto-inout-ignore-regexp 'safe-local-variable 'stringp)
1150 1150
1151(defcustom verilog-auto-output-ignore-regexp nil 1151(defcustom verilog-auto-output-ignore-regexp nil
1152 "If set, when creating AUTOOUTPUT list, ignore signals matching this regexp. 1152 "If set, when creating AUTOOUTPUT list, ignore signals matching this regexp.
1153See the \\[verilog-faq] for examples on using this." 1153See the \\[verilog-faq] for examples on using this."
1154 :group 'verilog-mode-auto 1154 :group 'verilog-mode-auto
1155 :type 'string) 1155 :type '(choice (const nil) regexp))
1156(put 'verilog-auto-output-ignore-regexp 'safe-local-variable 'stringp) 1156(put 'verilog-auto-output-ignore-regexp 'safe-local-variable 'stringp)
1157 1157
1158(defcustom verilog-auto-template-warn-unused nil 1158(defcustom verilog-auto-template-warn-unused nil
1159 "Non-nil means report warning if an AUTO_TEMPLATE line is not used. 1159 "Non-nil means report warning if an AUTO_TEMPLATE line is not used.
1160This feature is not supported before Emacs 21.1 or XEmacs 21.4." 1160This feature is not supported before Emacs 21.1 or XEmacs 21.4."
1161 :version "24.3" ;;rev787
1161 :group 'verilog-mode-auto 1162 :group 'verilog-mode-auto
1162 :version "24.3"
1163 :type 'boolean) 1163 :type 'boolean)
1164(put 'verilog-auto-template-warn-unused 'safe-local-variable 'verilog-booleanp) 1164(put 'verilog-auto-template-warn-unused 'safe-local-variable 'verilog-booleanp)
1165 1165
@@ -1176,21 +1176,21 @@ assignment, else the data type for variable creation."
1176 "If set, when creating AUTOTIEOFF list, ignore signals matching this regexp. 1176 "If set, when creating AUTOTIEOFF list, ignore signals matching this regexp.
1177See the \\[verilog-faq] for examples on using this." 1177See the \\[verilog-faq] for examples on using this."
1178 :group 'verilog-mode-auto 1178 :group 'verilog-mode-auto
1179 :type 'string) 1179 :type '(choice (const nil) regexp))
1180(put 'verilog-auto-tieoff-ignore-regexp 'safe-local-variable 'stringp) 1180(put 'verilog-auto-tieoff-ignore-regexp 'safe-local-variable 'stringp)
1181 1181
1182(defcustom verilog-auto-unused-ignore-regexp nil 1182(defcustom verilog-auto-unused-ignore-regexp nil
1183 "If set, when creating AUTOUNUSED list, ignore signals matching this regexp. 1183 "If set, when creating AUTOUNUSED list, ignore signals matching this regexp.
1184See the \\[verilog-faq] for examples on using this." 1184See the \\[verilog-faq] for examples on using this."
1185 :group 'verilog-mode-auto 1185 :group 'verilog-mode-auto
1186 :type 'string) 1186 :type '(choice (const nil) regexp))
1187(put 'verilog-auto-unused-ignore-regexp 'safe-local-variable 'stringp) 1187(put 'verilog-auto-unused-ignore-regexp 'safe-local-variable 'stringp)
1188 1188
1189(defcustom verilog-typedef-regexp nil 1189(defcustom verilog-typedef-regexp nil
1190 "If non-nil, regular expression that matches Verilog-2001 typedef names. 1190 "If non-nil, regular expression that matches Verilog-2001 typedef names.
1191For example, \"_t$\" matches typedefs named with _t, as in the C language." 1191For example, \"_t$\" matches typedefs named with _t, as in the C language."
1192 :group 'verilog-mode-auto 1192 :group 'verilog-mode-auto
1193 :type 'string) 1193 :type '(choice (const nil) regexp))
1194(put 'verilog-typedef-regexp 'safe-local-variable 'stringp) 1194(put 'verilog-typedef-regexp 'safe-local-variable 'stringp)
1195 1195
1196(defcustom verilog-mode-hook 'verilog-set-compile-command 1196(defcustom verilog-mode-hook 'verilog-set-compile-command
@@ -1230,14 +1230,14 @@ For example, \"_t$\" matches typedefs named with _t, as in the C language."
1230 1230
1231(defcustom verilog-before-save-font-hook nil 1231(defcustom verilog-before-save-font-hook nil
1232 "Hook run before `verilog-save-font-mods' removes highlighting." 1232 "Hook run before `verilog-save-font-mods' removes highlighting."
1233 :version "24.3" ;;rev735
1233 :group 'verilog-mode-auto 1234 :group 'verilog-mode-auto
1234 :version "24.3"
1235 :type 'hook) 1235 :type 'hook)
1236 1236
1237(defcustom verilog-after-save-font-hook nil 1237(defcustom verilog-after-save-font-hook nil
1238 "Hook run after `verilog-save-font-mods' restores highlighting." 1238 "Hook run after `verilog-save-font-mods' restores highlighting."
1239 :version "24.3" ;;rev735
1239 :group 'verilog-mode-auto 1240 :group 'verilog-mode-auto
1240 :version "24.3"
1241 :type 'hook) 1241 :type 'hook)
1242 1242
1243(defvar verilog-imenu-generic-expression 1243(defvar verilog-imenu-generic-expression
@@ -2784,6 +2784,8 @@ find the errors."
2784 (modify-syntax-entry ?> "." table) 2784 (modify-syntax-entry ?> "." table)
2785 (modify-syntax-entry ?& "." table) 2785 (modify-syntax-entry ?& "." table)
2786 (modify-syntax-entry ?| "." table) 2786 (modify-syntax-entry ?| "." table)
2787 ;; FIXME: This goes against Emacs conventions. Use "_" syntax instead and
2788 ;; then use regexps with things like "\\_<...\\_>".
2787 (modify-syntax-entry ?` "w" table) 2789 (modify-syntax-entry ?` "w" table)
2788 (modify-syntax-entry ?_ "w" table) 2790 (modify-syntax-entry ?_ "w" table)
2789 (modify-syntax-entry ?\' "." table) 2791 (modify-syntax-entry ?\' "." table)
@@ -7771,9 +7773,12 @@ Tieoff value uses `verilog-active-low-regexp' and
7771 ;; Else presume verilog-auto-reset-widths is true 7773 ;; Else presume verilog-auto-reset-widths is true
7772 (t 7774 (t
7773 (let* ((width (verilog-sig-width sig))) 7775 (let* ((width (verilog-sig-width sig)))
7774 (if (string-match "^[0-9]+$" width) 7776 (cond ((not width)
7775 (concat width (if (verilog-sig-signed sig) "'sh0" "'h0")) 7777 "`0/*NOWIDTH*/")
7776 (concat "{" width "{1'b0}}"))))))) 7778 ((string-match "^[0-9]+$" width)
7779 (concat width (if (verilog-sig-signed sig) "'sh0" "'h0")))
7780 (t
7781 (concat "{" width "{1'b0}}"))))))))
7777 7782
7778;; 7783;;
7779;; Dumping 7784;; Dumping
@@ -7954,6 +7959,7 @@ Return an array of [outputs inouts inputs wire reg assign const]."
7954 vec expect-signal keywd newsig rvalue enum io signed typedefed multidim 7959 vec expect-signal keywd newsig rvalue enum io signed typedefed multidim
7955 modport 7960 modport
7956 varstack tmp) 7961 varstack tmp)
7962 ;;(if dbg (setq dbg (concat dbg (format "\n\nverilog-read-decls START PT %s END %s\n" (point) end-mod-point))))
7957 (save-excursion 7963 (save-excursion
7958 (verilog-beg-of-defun-quick) 7964 (verilog-beg-of-defun-quick)
7959 (setq sigs-const (verilog-read-auto-constants (point) end-mod-point)) 7965 (setq sigs-const (verilog-read-auto-constants (point) end-mod-point))
@@ -8008,7 +8014,7 @@ Return an array of [outputs inouts inputs wire reg assign const]."
8008 (setq paren (1- paren)) 8014 (setq paren (1- paren))
8009 (forward-char 1) 8015 (forward-char 1)
8010 (when (< paren sig-paren) 8016 (when (< paren sig-paren)
8011 (setq expect-signal nil))) ; ) that ends variables inside v2k arg list 8017 (setq expect-signal nil rvalue nil))) ; ) that ends variables inside v2k arg list
8012 ((looking-at "\\s-*\\(\\[[^]]+\\]\\)") 8018 ((looking-at "\\s-*\\(\\[[^]]+\\]\\)")
8013 (goto-char (match-end 0)) 8019 (goto-char (match-end 0))
8014 (cond (newsig ; Memory, not just width. Patch last signal added's memory (nth 3) 8020 (cond (newsig ; Memory, not just width. Patch last signal added's memory (nth 3)
@@ -12456,12 +12462,20 @@ used on the right hand side of assignments.
12456 12462
12457By default, AUTORESET will include the width of the signal in the 12463By default, AUTORESET will include the width of the signal in the
12458autos, SystemVerilog designs may want to change this. To control 12464autos, SystemVerilog designs may want to change this. To control
12459this behavior, see `verilog-auto-reset-widths'. 12465this behavior, see `verilog-auto-reset-widths'. In some cases
12466AUTORESET must use a '0 assignment and it will print NOWIDTH; use
12467`verilog-auto-reset-widths' unbased to prevent this.
12460 12468
12461AUTORESET ties signals to deasserted, which is presumed to be zero. 12469AUTORESET ties signals to deasserted, which is presumed to be zero.
12462Signals that match `verilog-active-low-regexp' will be deasserted by tying 12470Signals that match `verilog-active-low-regexp' will be deasserted by tying
12463them to a one. 12471them to a one.
12464 12472
12473AUTORESET may try to reset arrays or structures that cannot be
12474reset by a simple assignment, resulting in compile errors. This
12475is a feature to be taken as a hint that you need to reset these
12476signals manually (or put them into a \"`ifdef NEVER signal<=`0;
12477`endif\" so Verilog-Mode ignores them.)
12478
12465An example: 12479An example:
12466 12480
12467 always @(posedge clk or negedge reset_l) begin 12481 always @(posedge clk or negedge reset_l) begin
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index e3b421efbe1..0050a94513a 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -13,10 +13,10 @@
13;; filed in the Emacs bug reporting system against this file, a copy 13;; filed in the Emacs bug reporting system against this file, a copy
14;; of the bug report be sent to the maintainer's email address. 14;; of the bug report be sent to the maintainer's email address.
15 15
16(defconst vhdl-version "3.33.28" 16(defconst vhdl-version "3.34.2"
17 "VHDL Mode version number.") 17 "VHDL Mode version number.")
18 18
19(defconst vhdl-time-stamp "2010-09-22" 19(defconst vhdl-time-stamp "2012-11-21"
20 "VHDL Mode time stamp for last update.") 20 "VHDL Mode time stamp for last update.")
21 21
22;; This file is part of GNU Emacs. 22;; This file is part of GNU Emacs.
@@ -72,8 +72,7 @@
72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73;; Emacs Versions 73;; Emacs Versions
74 74
75;; supported: GNU Emacs 20.X/21.X/22.X,23.X, XEmacs 20.X/21.X 75;; this updated version was only tested on: GNU Emacs 20.4
76;; tested on: GNU Emacs 20.4/21.3/22.1,23.X, XEmacs 21.1 (marginally)
77 76
78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
79;; Installation 78;; Installation
@@ -84,7 +83,7 @@
84;; or into an arbitrary directory that is added to the load path by the 83;; or into an arbitrary directory that is added to the load path by the
85;; following line in your Emacs start-up file `.emacs': 84;; following line in your Emacs start-up file `.emacs':
86 85
87;; (setq load-path (cons (expand-file-name "<directory-name>") load-path)) 86;; (push (expand-file-name "<directory-name>") load-path)
88 87
89;; If you already have the compiled `vhdl-mode.elc' file, put it in the same 88;; If you already have the compiled `vhdl-mode.elc' file, put it in the same
90;; directory. Otherwise, byte-compile the source file: 89;; directory. Otherwise, byte-compile the source file:
@@ -96,7 +95,7 @@
96;; (not required in Emacs 20 and higher): 95;; (not required in Emacs 20 and higher):
97 96
98;; (autoload 'vhdl-mode "vhdl-mode" "VHDL Mode" t) 97;; (autoload 'vhdl-mode "vhdl-mode" "VHDL Mode" t)
99;; (setq auto-mode-alist (cons '("\\.vhdl?\\'" . vhdl-mode) auto-mode-alist)) 98;; (push '("\\.vhdl?\\'" . vhdl-mode) auto-mode-alist)
100 99
101;; More detailed installation instructions are included in the official 100;; More detailed installation instructions are included in the official
102;; VHDL Mode distribution. 101;; VHDL Mode distribution.
@@ -130,6 +129,7 @@
130;; Emacs 21+ handling 129;; Emacs 21+ handling
131(defconst vhdl-emacs-21 (and (<= 21 emacs-major-version) (not (featurep 'xemacs))) 130(defconst vhdl-emacs-21 (and (<= 21 emacs-major-version) (not (featurep 'xemacs)))
132 "Non-nil if GNU Emacs 21, 22, ... is used.") 131 "Non-nil if GNU Emacs 21, 22, ... is used.")
132;; Emacs 22+ handling
133(defconst vhdl-emacs-22 (and (<= 22 emacs-major-version) (not (featurep 'xemacs))) 133(defconst vhdl-emacs-22 (and (<= 22 emacs-major-version) (not (featurep 'xemacs)))
134 "Non-nil if GNU Emacs 22, ... is used.") 134 "Non-nil if GNU Emacs 22, ... is used.")
135 135
@@ -210,22 +210,25 @@ Overrides local variable `indent-tabs-mode'."
210 210
211(defcustom vhdl-compiler-alist 211(defcustom vhdl-compiler-alist
212 '( 212 '(
213 ;; 60: docal <= false;
214 ;; ^^^^^
215 ;; [Error] Assignment error: variable is illegal target of signal assignment
213 ("ADVance MS" "vacom" "-work \\1" "make" "-f \\1" 216 ("ADVance MS" "vacom" "-work \\1" "make" "-f \\1"
214 nil "valib \\1; vamap \\2 \\1" "./" "work/" "Makefile" "adms" 217 nil "valib \\1; vamap \\2 \\1" "./" "work/" "Makefile" "adms"
215 ("\\s-\\([0-9]+\\):" 0 1 0) ("Compiling file \\(.+\\)" 1) 218 ("^\\s-+\\([0-9]+\\):\\s-+" nil 1 nil) ("Compiling file \\(.+\\)" 1)
216 ("ENTI/\\1.vif" "ARCH/\\1-\\2.vif" "CONF/\\1.vif" 219 ("ENTI/\\1.vif" "ARCH/\\1-\\2.vif" "CONF/\\1.vif"
217 "PACK/\\1.vif" "BODY/\\1.vif" upcase)) 220 "PACK/\\1.vif" "BODY/\\1.vif" upcase))
218 ;; Aldec 221 ;; Aldec
219 ;; COMP96 ERROR COMP96_0078: "Unknown identifier "Addr_Bits"." "<filename>" 40 30 222 ;; COMP96 ERROR COMP96_0018: "Identifier expected." "test.vhd" 66 3
220 ("Aldec" "vcom" "-93 -work \\1" "make" "-f \\1" 223 ("Aldec" "vcom" "-work \\1" "make" "-f \\1"
221 nil "vlib \\1; vmap \\2 \\1" "./" "work/" "Makefile" "aldec" 224 nil "vlib \\1; vmap \\2 \\1" "./" "work/" "Makefile" "aldec"
222 (".+?[ \t]+\\(?:ERROR\\)[^:]+:.+?\\(?:.+\"\\(.+?\\)\"[ \t]+\\([0-9]+\\)\\)" 1 2 0) ("" 0) 225 (".* ERROR [^:]+: \".*\" \"\\([^ \\t\\n]+\\)\" \\([0-9]+\\) \\([0-9]+\\)" 1 2 3) ("" 0)
223 nil) 226 nil)
224 ;; Cadence Leapfrog: cv -file test.vhd 227 ;; Cadence Leapfrog: cv -file test.vhd
225 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared 228 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
226 ("Cadence Leapfrog" "cv" "-work \\1 -file" "make" "-f \\1" 229 ("Cadence Leapfrog" "cv" "-work \\1 -file" "make" "-f \\1"
227 nil "mkdir \\1" "./" "work/" "Makefile" "leapfrog" 230 nil "mkdir \\1" "./" "work/" "Makefile" "leapfrog"
228 ("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2 0) ("" 0) 231 ("duluth: \\*E,[0-9]+ (\\([^ \\t\\n]+\\),\\([0-9]+\\)):" 1 2 nil) ("" 0)
229 ("\\1/entity" "\\2/\\1" "\\1/configuration" 232 ("\\1/entity" "\\2/\\1" "\\1/configuration"
230 "\\1/package" "\\1/body" downcase)) 233 "\\1/package" "\\1/body" downcase))
231 ;; Cadence Affirma NC vhdl: ncvhdl test.vhd 234 ;; Cadence Affirma NC vhdl: ncvhdl test.vhd
@@ -233,21 +236,27 @@ Overrides local variable `indent-tabs-mode'."
233 ;; (PLL_400X_TOP) is not declared [10.3]. 236 ;; (PLL_400X_TOP) is not declared [10.3].
234 ("Cadence NC" "ncvhdl" "-work \\1" "make" "-f \\1" 237 ("Cadence NC" "ncvhdl" "-work \\1" "make" "-f \\1"
235 nil "mkdir \\1" "./" "work/" "Makefile" "ncvhdl" 238 nil "mkdir \\1" "./" "work/" "Makefile" "ncvhdl"
236 ("ncvhdl_p: \\*E,\\w+ (\\(.+\\),\\([0-9]+\\)|\\([0-9]+\\)):" 1 2 3) ("" 0) 239 ("ncvhdl_p: \\*E,\\w+ (\\([^ \\t\\n]+\\),\\([0-9]+\\)|\\([0-9]+\\)):" 1 2 3) ("" 0)
237 ("\\1/entity/pc.db" "\\2/\\1/pc.db" "\\1/configuration/pc.db" 240 ("\\1/entity/pc.db" "\\2/\\1/pc.db" "\\1/configuration/pc.db"
238 "\\1/package/pc.db" "\\1/body/pc.db" downcase)) 241 "\\1/package/pc.db" "\\1/body/pc.db" downcase))
239 ;; ghdl vhdl: ghdl test.vhd 242 ;; ghdl vhdl: ghdl test.vhd
240 ("GHDL" "ghdl" "-i --workdir=\\1 --ieee=synopsys -fexplicit " "make" "-f \\1" 243 ("GHDL" "ghdl" "-i --workdir=\\1 --ieee=synopsys -fexplicit " "make" "-f \\1"
241 nil "mkdir \\1" "./" "work/" "Makefile" "ghdl" 244 nil "mkdir \\1" "./" "work/" "Makefile" "ghdl"
242 ("ghdl_p: \\*E,\\w+ (\\(.+\\),\\([0-9]+\\)|\\([0-9]+\\)):" 1 2 3) ("" 0) 245 ("ghdl_p: \\*E,\\w+ (\\([^ \\t\\n]+\\),\\([0-9]+\\)|\\([0-9]+\\)):" 1 2 3) ("" 0)
243 ("\\1/entity" "\\2/\\1" "\\1/configuration" 246 ("\\1/entity" "\\2/\\1" "\\1/configuration"
244 "\\1/package" "\\1/body" downcase)) 247 "\\1/package" "\\1/body" downcase))
248 ;; IBM Compiler
249 ;; 00 COACHDL* | [CCHDL-1]: File: adder.vhd, line.column: 120.6
250 ("IBM Compiler" "g2tvc" "-src" "precomp" "\\1"
251 nil "mkdir \\1" "./" "work/" "Makefile" "ibm"
252 ("[0-9]+ COACHDL.*: File: \\([^ \\t\\n]+\\), line.column: \\([0-9]+\\).\\([0-9]+\\)" 1 2 3) (" " 0)
253 nil)
245 ;; Ikos Voyager: analyze test.vhd 254 ;; Ikos Voyager: analyze test.vhd
246 ;; analyze test.vhd 255 ;; analyze test.vhd
247 ;; E L4/C5: this library unit is inaccessible 256 ;; E L4/C5: this library unit is inaccessible
248 ("Ikos" "analyze" "-l \\1" "make" "-f \\1" 257 ("Ikos" "analyze" "-l \\1" "make" "-f \\1"
249 nil "mkdir \\1" "./" "work/" "Makefile" "ikos" 258 nil "mkdir \\1" "./" "work/" "Makefile" "ikos"
250 ("E L\\([0-9]+\\)/C\\([0-9]+\\):" 0 1 2) 259 ("E L\\([0-9]+\\)/C\\([0-9]+\\):" nil 1 2)
251 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2) 260 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2)
252 nil) 261 nil)
253 ;; ModelSim, Model Technology: vcom test.vhd 262 ;; ModelSim, Model Technology: vcom test.vhd
@@ -257,29 +266,39 @@ Overrides local variable `indent-tabs-mode'."
257 ;; ** Error: adder.vhd(190): Unknown identifier: ctl_numb 266 ;; ** Error: adder.vhd(190): Unknown identifier: ctl_numb
258 ("ModelSim" "vcom" "-93 -work \\1" "make" "-f \\1" 267 ("ModelSim" "vcom" "-93 -work \\1" "make" "-f \\1"
259 nil "vlib \\1; vmap \\2 \\1" "./" "work/" "Makefile" "modelsim" 268 nil "vlib \\1; vmap \\2 \\1" "./" "work/" "Makefile" "modelsim"
260 ("\\(ERROR\\|WARNING\\|\\*\\* Error\\|\\*\\* Warning\\)[^:]*:\\( *\[[0-9]+\]\\)? \\(.+\\)(\\([0-9]+\\)):" 3 4 0) ("" 0) 269 ("\\(ERROR\\|WARNING\\|\\*\\* Error\\|\\*\\* Warning\\)[^:]*:\\( *\[[0-9]+\]\\)? \\([^ \\t\\n]+\\)(\\([0-9]+\\)):" 3 4 nil) ("" 0)
261 ("\\1/_primary.dat" "\\2/\\1.dat" "\\1/_primary.dat" 270 ("\\1/_primary.dat" "\\2/\\1.dat" "\\1/_primary.dat"
262 "\\1/_primary.dat" "\\1/body.dat" downcase)) 271 "\\1/_primary.dat" "\\1/body.dat" downcase))
263 ;; ProVHDL, Synopsys LEDA: provhdl -w work -f test.vhd 272 ;; ProVHDL, Synopsys LEDA: provhdl -w work -f test.vhd
264 ;; test.vhd:34: error message 273 ;; test.vhd:34: error message
265 ("LEDA ProVHDL" "provhdl" "-w \\1 -f" "make" "-f \\1" 274 ("LEDA ProVHDL" "provhdl" "-w \\1 -f" "make" "-f \\1"
266 nil "mkdir \\1" "./" "work/" "Makefile" "provhdl" 275 nil "mkdir \\1" "./" "work/" "Makefile" "provhdl"
267 ("\\([^ \t\n]+\\):\\([0-9]+\\): " 1 2 0) ("" 0) 276 ("\\([^ \\t\\n]+\\):\\([0-9]+\\): " 1 2 nil) ("" 0)
268 ("ENTI/\\1.vif" "ARCH/\\1-\\2.vif" "CONF/\\1.vif" 277 ("ENTI/\\1.vif" "ARCH/\\1-\\2.vif" "CONF/\\1.vif"
269 "PACK/\\1.vif" "BODY/BODY-\\1.vif" upcase)) 278 "PACK/\\1.vif" "BODY/BODY-\\1.vif" upcase))
279 ;; Quartus compiler
280 ;; Error: VHDL error at dvi2sdi.vhd(473): object k2_alto_out_lvl is used
281 ;; Error: Verilog HDL syntax error at otsuif_v1_top.vhd(147) near text
282 ;; Error: VHDL syntax error at otsuif_v1_top.vhd(147): clk_ is an illegal
283 ;; Error: VHDL Use Clause error at otsuif_v1_top.vhd(455): design library
284 ;; Warning: VHDL Process Statement warning at dvi2sdi_tst.vhd(172): ...
285 ("Quartus" "make" "-work \\1" "make" "-f \\1"
286 nil "mkdir \\1" "./" "work/" "Makefile" "quartus"
287 ("\\(Error\\|Warning\\): .* \\([^ \\t\\n]+\\)(\\([0-9]+\\))" 2 3 nil) ("" 0)
288 nil)
270 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd 289 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd
271 ;; ERROR: test.vhd(24): near "dnd": expecting: END 290 ;; ERROR: test.vhd(24): near "dnd": expecting: END
272 ;; WARNING[4]: test.vhd(30): A space is required between ... 291 ;; WARNING[4]: test.vhd(30): A space is required between ...
273 ("QuickHDL" "qvhcom" "-work \\1" "make" "-f \\1" 292 ("QuickHDL" "qvhcom" "-work \\1" "make" "-f \\1"
274 nil "mkdir \\1" "./" "work/" "Makefile" "quickhdl" 293 nil "mkdir \\1" "./" "work/" "Makefile" "quickhdl"
275 ("\\(ERROR\\|WARNING\\)[^:]*: \\(.+\\)(\\([0-9]+\\)):" 2 3 0) ("" 0) 294 ("\\(ERROR\\|WARNING\\)[^:]*: \\([^ \\t\\n]+\\)(\\([0-9]+\\)):" 2 3 nil) ("" 0)
276 ("\\1/_primary.dat" "\\2/\\1.dat" "\\1/_primary.dat" 295 ("\\1/_primary.dat" "\\2/\\1.dat" "\\1/_primary.dat"
277 "\\1/_primary.dat" "\\1/body.dat" downcase)) 296 "\\1/_primary.dat" "\\1/body.dat" downcase))
278 ;; Savant: scram -publish-cc test.vhd 297 ;; Savant: scram -publish-cc test.vhd
279 ;; test.vhd:87: _set_passed_through_out_port(IIR_Boolean) not defined for 298 ;; test.vhd:87: _set_passed_through_out_port(IIR_Boolean) not defined for
280 ("Savant" "scram" "-publish-cc -design-library-name \\1" "make" "-f \\1" 299 ("Savant" "scram" "-publish-cc -design-library-name \\1" "make" "-f \\1"
281 nil "mkdir \\1" "./" "work._savant_lib/" "Makefile" "savant" 300 nil "mkdir \\1" "./" "work._savant_lib/" "Makefile" "savant"
282 ("\\([^ \t\n]+\\):\\([0-9]+\\): " 1 2 0) ("" 0) 301 ("\\([^ \\t\\n]+\\):\\([0-9]+\\): " 1 2 nil) ("" 0)
283 ("\\1_entity.vhdl" "\\2_secondary_units._savant_lib/\\2_\\1.vhdl" 302 ("\\1_entity.vhdl" "\\2_secondary_units._savant_lib/\\2_\\1.vhdl"
284 "\\1_config.vhdl" "\\1_package.vhdl" 303 "\\1_config.vhdl" "\\1_package.vhdl"
285 "\\1_secondary_units._savant_lib/\\1_package_body.vhdl" downcase)) 304 "\\1_secondary_units._savant_lib/\\1_package_body.vhdl" downcase))
@@ -287,39 +306,39 @@ Overrides local variable `indent-tabs-mode'."
287 ;; Error: CSVHDL0002: test.vhd: (line 97): Invalid prefix 306 ;; Error: CSVHDL0002: test.vhd: (line 97): Invalid prefix
288 ("Simili" "vhdlp" "-work \\1" "make" "-f \\1" 307 ("Simili" "vhdlp" "-work \\1" "make" "-f \\1"
289 nil "mkdir \\1" "./" "work/" "Makefile" "simili" 308 nil "mkdir \\1" "./" "work/" "Makefile" "simili"
290 ("\\(Error\\|Warning\\): \\w+: \\(.+\\): (line \\([0-9]+\\)): " 2 3 0) ("" 0) 309 ("\\(Error\\|Warning\\): \\w+: \\([^ \\t\\n]+\\): (line \\([0-9]+\\)): " 2 3 nil) ("" 0)
291 ("\\1/prim.var" "\\2/_\\1.var" "\\1/prim.var" 310 ("\\1/prim.var" "\\2/_\\1.var" "\\1/prim.var"
292 "\\1/prim.var" "\\1/_body.var" downcase)) 311 "\\1/prim.var" "\\1/_body.var" downcase))
293 ;; Speedwave (Innoveda): analyze -libfile vsslib.ini -src test.vhd 312 ;; Speedwave (Innoveda): analyze -libfile vsslib.ini -src test.vhd
294 ;; ERROR[11]::File test.vhd Line 100: Use of undeclared identifier 313 ;; ERROR[11]::File test.vhd Line 100: Use of undeclared identifier
295 ("Speedwave" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1" 314 ("Speedwave" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1"
296 nil "mkdir \\1" "./" "work/" "Makefile" "speedwave" 315 nil "mkdir \\1" "./" "work/" "Makefile" "speedwave"
297 ("^ *ERROR\[[0-9]+\]::File \\(.+\\) Line \\([0-9]+\\):" 1 2 0) ("" 0) 316 ("^ *ERROR\[[0-9]+\]::File \\([^ \\t\\n]+\\) Line \\([0-9]+\\):" 1 2 nil) ("" 0)
298 nil) 317 nil)
299 ;; Synopsys, VHDL Analyzer (sim): vhdlan -nc test.vhd 318 ;; Synopsys, VHDL Analyzer (sim): vhdlan -nc test.vhd
300 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context. 319 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
301 ("Synopsys" "vhdlan" "-nc -work \\1" "make" "-f \\1" 320 ("Synopsys" "vhdlan" "-nc -work \\1" "make" "-f \\1"
302 nil "mkdir \\1" "./" "work/" "Makefile" "synopsys" 321 nil "mkdir \\1" "./" "work/" "Makefile" "synopsys"
303 ("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2 0) ("" 0) 322 ("\\*\\*Error: vhdlan,[0-9]+ \\([^ \\t\\n]+\\)(\\([0-9]+\\)):" 1 2 nil) ("" 0)
304 ("\\1.sim" "\\2__\\1.sim" "\\1.sim" "\\1.sim" "\\1__.sim" upcase)) 323 ("\\1.sim" "\\2__\\1.sim" "\\1.sim" "\\1.sim" "\\1__.sim" upcase))
305 ;; Synopsys, VHDL Analyzer (syn): vhdlan -nc -spc test.vhd 324 ;; Synopsys, VHDL Analyzer (syn): vhdlan -nc -spc test.vhd
306 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context. 325 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
307 ("Synopsys Design Compiler" "vhdlan" "-nc -spc -work \\1" "make" "-f \\1" 326 ("Synopsys Design Compiler" "vhdlan" "-nc -spc -work \\1" "make" "-f \\1"
308 nil "mkdir \\1" "./" "work/" "Makefile" "synopsys_dc" 327 nil "mkdir \\1" "./" "work/" "Makefile" "synopsys_dc"
309 ("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2 0) ("" 0) 328 ("\\*\\*Error: vhdlan,[0-9]+ \\([^ \\t\\n]+\\)(\\([0-9]+\\)):" 1 2 nil) ("" 0)
310 ("\\1.syn" "\\2__\\1.syn" "\\1.syn" "\\1.syn" "\\1__.syn" upcase)) 329 ("\\1.syn" "\\2__\\1.syn" "\\1.syn" "\\1.syn" "\\1__.syn" upcase))
311 ;; Synplify: 330 ;; Synplify:
312 ;; @W:"test.vhd":57:8:57:9|Optimizing register bit count_x(5) to a constant 0 331 ;; @W:"test.vhd":57:8:57:9|Optimizing register bit count_x(5) to a constant 0
313 ("Synplify" "n/a" "n/a" "make" "-f \\1" 332 ("Synplify" "n/a" "n/a" "make" "-f \\1"
314 nil "mkdir \\1" "./" "work/" "Makefile" "synplify" 333 nil "mkdir \\1" "./" "work/" "Makefile" "synplify"
315 ("@[EWN]:\"\\(.+\\)\":\\([0-9]+\\):\\([0-9]+\\):" 1 2 3) ("" 0) 334 ("@[EWN]:\"\\([^ \\t\\n]+\\)\":\\([0-9]+\\):\\([0-9]+\\):" 1 2 3) ("" 0)
316 nil) 335 nil)
317 ;; Vantage: analyze -libfile vsslib.ini -src test.vhd 336 ;; Vantage: analyze -libfile vsslib.ini -src test.vhd
318 ;; Compiling "test.vhd" line 1... 337 ;; Compiling "test.vhd" line 1...
319 ;; **Error: LINE 49 *** No aggregate value is valid in this context. 338 ;; **Error: LINE 49 *** No aggregate value is valid in this context.
320 ("Vantage" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1" 339 ("Vantage" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1"
321 nil "mkdir \\1" "./" "work/" "Makefile" "vantage" 340 nil "mkdir \\1" "./" "work/" "Makefile" "vantage"
322 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 0 1 0) 341 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1 nil)
323 ("^ *Compiling \"\\(.+\\)\" " 1) 342 ("^ *Compiling \"\\(.+\\)\" " 1)
324 nil) 343 nil)
325 ;; VeriBest: vc vhdl test.vhd 344 ;; VeriBest: vc vhdl test.vhd
@@ -329,21 +348,21 @@ Overrides local variable `indent-tabs-mode'."
329 ;; [Error] Name BITA is unknown 348 ;; [Error] Name BITA is unknown
330 ("VeriBest" "vc" "vhdl" "make" "-f \\1" 349 ("VeriBest" "vc" "vhdl" "make" "-f \\1"
331 nil "mkdir \\1" "./" "work/" "Makefile" "veribest" 350 nil "mkdir \\1" "./" "work/" "Makefile" "veribest"
332 ("^ +\\([0-9]+\\): +[^ ]" 0 1 0) ("" 0) 351 ("^ +\\([0-9]+\\): +[^ ]" nil 1 nil) ("" 0)
333 nil) 352 nil)
334 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd 353 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
335 ;; Compiling "test.vhd" line 1... 354 ;; Compiling "test.vhd" line 1...
336 ;; **Error: LINE 49 *** No aggregate value is valid in this context. 355 ;; **Error: LINE 49 *** No aggregate value is valid in this context.
337 ("Viewlogic" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1" 356 ("Viewlogic" "analyze" "-libfile vsslib.ini -src" "make" "-f \\1"
338 nil "mkdir \\1" "./" "work/" "Makefile" "viewlogic" 357 nil "mkdir \\1" "./" "work/" "Makefile" "viewlogic"
339 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 0 1 0) 358 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1 nil)
340 ("^ *Compiling \"\\(.+\\)\" " 1) 359 ("^ *Compiling \"\\(.+\\)\" " 1)
341 nil) 360 nil)
342 ;; Xilinx XST: 361 ;; Xilinx XST:
343 ;; ERROR:HDLParsers:164 - "test.vhd" Line 3. parse error 362 ;; ERROR:HDLParsers:164 - "test.vhd" Line 3. parse error
344 ("Xilinx XST" "xflow" "" "make" "-f \\1" 363 ("Xilinx XST" "xflow" "" "make" "-f \\1"
345 nil "mkdir \\1" "./" "work/" "Makefile" "xilinx" 364 nil "mkdir \\1" "./" "work/" "Makefile" "xilinx"
346 ("^ERROR:HDLParsers:[0-9]+ - \"\\(.+\\)\" Line \\([0-9]+\\)\." 1 2 0) ("" 0) 365 ("^ERROR:HDLParsers:[0-9]+ - \"\\([^ \\t\\n]+\\)\" Line \\([0-9]+\\)\." 1 2 nil) ("" 0)
347 nil) 366 nil)
348 ) 367 )
349 "List of available VHDL compilers and their properties. 368 "List of available VHDL compilers and their properties.
@@ -429,9 +448,13 @@ NOTE: Activate new error and file message regexps and reflect the new setting
429 (string :tag "ID string ") 448 (string :tag "ID string ")
430 (list :tag "Error message" :indent 4 449 (list :tag "Error message" :indent 4
431 (regexp :tag "Regexp ") 450 (regexp :tag "Regexp ")
432 (integer :tag "File subexp index") 451 (choice :tag "File subexp "
452 (integer :tag "Index")
453 (const :tag "No file name" nil))
433 (integer :tag "Line subexp index") 454 (integer :tag "Line subexp index")
434 (integer :tag "Column subexp idx")) 455 (choice :tag "Column subexp "
456 (integer :tag "Index")
457 (const :tag "No column number" nil)))
435 (list :tag "File message" :indent 4 458 (list :tag "File message" :indent 4
436 (regexp :tag "Regexp ") 459 (regexp :tag "Regexp ")
437 (integer :tag "File subexp index")) 460 (integer :tag "File subexp index"))
@@ -450,6 +473,7 @@ NOTE: Activate new error and file message regexps and reflect the new setting
450 (const :tag "Downcase" downcase)))))) 473 (const :tag "Downcase" downcase))))))
451 :set (lambda (variable value) 474 :set (lambda (variable value)
452 (vhdl-custom-set variable value 'vhdl-update-mode-menu)) 475 (vhdl-custom-set variable value 'vhdl-update-mode-menu))
476 :version "24.4"
453 :group 'vhdl-compile) 477 :group 'vhdl-compile)
454 478
455(defcustom vhdl-compiler "GHDL" 479(defcustom vhdl-compiler "GHDL"
@@ -457,7 +481,7 @@ NOTE: Activate new error and file message regexps and reflect the new setting
457Select a compiler name from the ones defined in option `vhdl-compiler-alist'." 481Select a compiler name from the ones defined in option `vhdl-compiler-alist'."
458 :type (let ((alist vhdl-compiler-alist) list) 482 :type (let ((alist vhdl-compiler-alist) list)
459 (while alist 483 (while alist
460 (setq list (cons (list 'const (caar alist)) list)) 484 (push (list 'const (caar alist)) list)
461 (setq alist (cdr alist))) 485 (setq alist (cdr alist)))
462 (append '(choice) (nreverse list))) 486 (append '(choice) (nreverse list)))
463 :group 'vhdl-compile) 487 :group 'vhdl-compile)
@@ -602,7 +626,7 @@ NOTE: Reflect the new setting in the choice list of option `vhdl-project'
602 (list :tag "Compiler" :indent 6 626 (list :tag "Compiler" :indent 6
603 ,(let ((alist vhdl-compiler-alist) list) 627 ,(let ((alist vhdl-compiler-alist) list)
604 (while alist 628 (while alist
605 (setq list (cons (list 'const (caar alist)) list)) 629 (push (list 'const (caar alist)) list)
606 (setq alist (cdr alist))) 630 (setq alist (cdr alist)))
607 (append '(choice :tag "Compiler name") 631 (append '(choice :tag "Compiler name")
608 (nreverse list))) 632 (nreverse list)))
@@ -637,7 +661,7 @@ headers and the source files/directories to be scanned in the hierarchy
637browser. The current project can also be changed temporarily in the menu." 661browser. The current project can also be changed temporarily in the menu."
638 :type (let ((alist vhdl-project-alist) list) 662 :type (let ((alist vhdl-project-alist) list)
639 (while alist 663 (while alist
640 (setq list (cons (list 'const (caar alist)) list)) 664 (push (list 'const (caar alist)) list)
641 (setq alist (cdr alist))) 665 (setq alist (cdr alist)))
642 (append '(choice (const :tag "None" nil) (const :tag "--")) 666 (append '(choice (const :tag "None" nil) (const :tag "--"))
643 (nreverse list))) 667 (nreverse list)))
@@ -1268,6 +1292,18 @@ The comments and empty lines between groups of ports are pasted:
1268 (const :tag "Always" always)) 1292 (const :tag "Always" always))
1269 :group 'vhdl-port) 1293 :group 'vhdl-port)
1270 1294
1295(defcustom vhdl-actual-generic-name '(".*" . "\\&")
1296 (concat
1297 "Specifies how actual generic names are obtained from formal generic names.
1298In a component instantiation, an actual generic name can be
1299obtained by modifying the formal generic name (e.g. attaching or stripping
1300off a substring)."
1301 vhdl-name-doc-string)
1302 :type '(cons (regexp :tag "From regexp")
1303 (string :tag "To string "))
1304 :group 'vhdl-port
1305 :version "24.4")
1306
1271(defcustom vhdl-actual-port-name '(".*" . "\\&") 1307(defcustom vhdl-actual-port-name '(".*" . "\\&")
1272 (concat 1308 (concat
1273 "Specifies how actual port names are obtained from formal port names. 1309 "Specifies how actual port names are obtained from formal port names.
@@ -1469,21 +1505,21 @@ NOTE: Activate the new setting in a VHDL buffer by using the menu entry
1469(defvar end-comment-column) 1505(defvar end-comment-column)
1470 1506
1471 1507
1472(defgroup vhdl-align nil 1508(defgroup vhdl-beautify nil
1473 "Customizations for alignment." 1509 "Customizations for beautification."
1474 :group 'vhdl) 1510 :group 'vhdl)
1475 1511
1476(defcustom vhdl-auto-align t 1512(defcustom vhdl-auto-align t
1477 "Non-nil means align some templates automatically after generation." 1513 "Non-nil means align some templates automatically after generation."
1478 :type 'boolean 1514 :type 'boolean
1479 :group 'vhdl-align) 1515 :group 'vhdl-beautify)
1480 1516
1481(defcustom vhdl-align-groups t 1517(defcustom vhdl-align-groups t
1482 "Non-nil means align groups of code lines separately. 1518 "Non-nil means align groups of code lines separately.
1483A group of code lines is a region of consecutive lines between two lines that 1519A group of code lines is a region of consecutive lines between two lines that
1484match the regexp in option `vhdl-align-group-separate'." 1520match the regexp in option `vhdl-align-group-separate'."
1485 :type 'boolean 1521 :type 'boolean
1486 :group 'vhdl-align) 1522 :group 'vhdl-beautify)
1487 1523
1488(defcustom vhdl-align-group-separate "^\\s-*$" 1524(defcustom vhdl-align-group-separate "^\\s-*$"
1489 "Regexp for matching a line that separates groups of lines for alignment. 1525 "Regexp for matching a line that separates groups of lines for alignment.
@@ -1491,7 +1527,7 @@ Examples:
1491 \"^\\s-*$\": matches an empty line 1527 \"^\\s-*$\": matches an empty line
1492 \"^\\s-*\\(--.*\\)?$\": matches an empty line or a comment-only line" 1528 \"^\\s-*\\(--.*\\)?$\": matches an empty line or a comment-only line"
1493 :type 'regexp 1529 :type 'regexp
1494 :group 'vhdl-align) 1530 :group 'vhdl-beautify)
1495 1531
1496(defcustom vhdl-align-same-indent t 1532(defcustom vhdl-align-same-indent t
1497 "Non-nil means align blocks with same indent separately. 1533 "Non-nil means align blocks with same indent separately.
@@ -1500,7 +1536,18 @@ blocks of same indent which are aligned separately (except for argument/port
1500lists). This gives nicer alignment in most cases. 1536lists). This gives nicer alignment in most cases.
1501Option `vhdl-align-groups' still applies within these blocks." 1537Option `vhdl-align-groups' still applies within these blocks."
1502 :type 'boolean 1538 :type 'boolean
1503 :group 'vhdl-align) 1539 :group 'vhdl-beautify)
1540
1541(defcustom vhdl-beautify-options '(t t t t t)
1542 "List of options for beautifying code. Allows to disable individual
1543features of code beautification."
1544 :type '(list (boolean :tag "Whitespace cleanup ")
1545 (boolean :tag "Single statement per line")
1546 (boolean :tag "Indentation ")
1547 (boolean :tag "Alignment ")
1548 (boolean :tag "Case fixing "))
1549 :group 'vhdl-beautify
1550 :version "24.4")
1504 1551
1505 1552
1506(defgroup vhdl-highlight nil 1553(defgroup vhdl-highlight nil
@@ -1846,7 +1893,7 @@ useful in large files where syntax-based indentation gets very slow."
1846 :group 'vhdl-misc) 1893 :group 'vhdl-misc)
1847 1894
1848(defcustom vhdl-indent-comment-like-next-code-line t 1895(defcustom vhdl-indent-comment-like-next-code-line t
1849 "*Non-nil means comment lines are indented like the following code line. 1896 "Non-nil means comment lines are indented like the following code line.
1850Otherwise, comment lines are indented like the preceding code line. 1897Otherwise, comment lines are indented like the preceding code line.
1851Indenting comment lines like the following code line gives nicer indentation 1898Indenting comment lines like the following code line gives nicer indentation
1852when comments precede the code that they refer to." 1899when comments precede the code that they refer to."
@@ -1872,14 +1919,11 @@ NOTE: Activate the new setting by restarting Emacs."
1872 "Non-nil means consider the underscore character `_' as part of word. 1919 "Non-nil means consider the underscore character `_' as part of word.
1873An identifier containing underscores is then treated as a single word in 1920An identifier containing underscores is then treated as a single word in
1874select and move operations. All parts of an identifier separated by underscore 1921select and move operations. All parts of an identifier separated by underscore
1875are treated as single words otherwise. 1922are treated as single words otherwise."
1876
1877NOTE: Activate the new setting in a VHDL buffer by using the menu entry
1878 \"Activate Options\"."
1879 :type 'boolean 1923 :type 'boolean
1880 :set (lambda (variable value)
1881 (vhdl-custom-set variable value 'vhdl-mode-syntax-table-init))
1882 :group 'vhdl-misc) 1924 :group 'vhdl-misc)
1925(make-obsolete-variable 'vhdl-underscore-is-part-of-word
1926 'superword-mode "24.4")
1883 1927
1884 1928
1885(defgroup vhdl-related nil 1929(defgroup vhdl-related nil
@@ -2070,7 +2114,7 @@ your style, only those that are different from the default.")
2070 (lambda (var) 2114 (lambda (var)
2071 (cons var (symbol-value var)))) 2115 (cons var (symbol-value var))))
2072 varlist)))) 2116 varlist))))
2073 (setq vhdl-style-alist (cons default vhdl-style-alist)))) 2117 (push default vhdl-style-alist)))
2074 2118
2075(defvar vhdl-mode-hook nil 2119(defvar vhdl-mode-hook nil
2076 "Hook called by `vhdl-mode'.") 2120 "Hook called by `vhdl-mode'.")
@@ -2087,10 +2131,11 @@ your style, only those that are different from the default.")
2087(require 'hippie-exp) 2131(require 'hippie-exp)
2088 2132
2089;; optional (minimize warning messages during compile) 2133;; optional (minimize warning messages during compile)
2134(unless (featurep 'xemacs)
2090(eval-when-compile 2135(eval-when-compile
2091 (require 'font-lock) 2136 (require 'font-lock)
2092 (require 'ps-print) 2137 (require 'ps-print)
2093 (require 'speedbar)) 2138 (require 'speedbar))) ; for speedbar-with-writable
2094 2139
2095 2140
2096;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2141;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2190,6 +2235,17 @@ Ignore byte-compiler warnings you might see."
2190(unless (fboundp 'member-ignore-case) 2235(unless (fboundp 'member-ignore-case)
2191 (defalias 'member-ignore-case 'member)) 2236 (defalias 'member-ignore-case 'member))
2192 2237
2238;; `last-input-char' obsolete in Emacs 24, `last-input-event' different
2239;; behavior in XEmacs
2240(defvar vhdl-last-input-event)
2241(if (featurep 'xemacs)
2242 (defvaralias 'vhdl-last-input-event 'last-input-char)
2243 (defvaralias 'vhdl-last-input-event 'last-input-event))
2244
2245;; `help-print-return-message' changed to `print-help-return-message' in Emacs
2246;;;(unless (fboundp 'help-print-return-message)
2247;;; (defalias 'help-print-return-message 'print-help-return-message))
2248
2193;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2249;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2194;; Compatibility with older VHDL Mode versions 2250;; Compatibility with older VHDL Mode versions
2195 2251
@@ -2210,7 +2266,7 @@ Ignore byte-compiler warnings you might see."
2210 (vhdl-warning (apply 'format args) t) 2266 (vhdl-warning (apply 'format args) t)
2211 (unless vhdl-warnings 2267 (unless vhdl-warnings
2212 (vhdl-run-when-idle .1 nil 'vhdl-print-warnings)) 2268 (vhdl-run-when-idle .1 nil 'vhdl-print-warnings))
2213 (setq vhdl-warnings (cons (apply 'format args) vhdl-warnings)))) 2269 (push (apply 'format args) vhdl-warnings)))
2214 2270
2215(defun vhdl-warning (string &optional nobeep) 2271(defun vhdl-warning (string &optional nobeep)
2216 "Print out warning STRING and beep." 2272 "Print out warning STRING and beep."
@@ -2244,7 +2300,7 @@ Ignore byte-compiler warnings you might see."
2244 (let ((old-alist vhdl-model-alist) 2300 (let ((old-alist vhdl-model-alist)
2245 new-alist) 2301 new-alist)
2246 (while old-alist 2302 (while old-alist
2247 (setq new-alist (cons (append (car old-alist) '("")) new-alist)) 2303 (push (append (car old-alist) '("")) new-alist)
2248 (setq old-alist (cdr old-alist))) 2304 (setq old-alist (cdr old-alist)))
2249 (setq vhdl-model-alist (nreverse new-alist))) 2305 (setq vhdl-model-alist (nreverse new-alist)))
2250 (customize-save-variable 'vhdl-model-alist vhdl-model-alist)) 2306 (customize-save-variable 'vhdl-model-alist vhdl-model-alist))
@@ -2254,7 +2310,7 @@ Ignore byte-compiler warnings you might see."
2254 (let ((old-alist vhdl-project-alist) 2310 (let ((old-alist vhdl-project-alist)
2255 new-alist) 2311 new-alist)
2256 (while old-alist 2312 (while old-alist
2257 (setq new-alist (cons (append (car old-alist) '("")) new-alist)) 2313 (push (append (car old-alist) '("")) new-alist)
2258 (setq old-alist (cdr old-alist))) 2314 (setq old-alist (cdr old-alist)))
2259 (setq vhdl-project-alist (nreverse new-alist))) 2315 (setq vhdl-project-alist (nreverse new-alist)))
2260 (customize-save-variable 'vhdl-project-alist vhdl-project-alist)) 2316 (customize-save-variable 'vhdl-project-alist vhdl-project-alist))
@@ -2342,7 +2398,6 @@ Ignore byte-compiler warnings you might see."
2342 (unless (get 'speedbar-indentation-width 'saved-value) 2398 (unless (get 'speedbar-indentation-width 'saved-value)
2343 (setq speedbar-indentation-width 2))) 2399 (setq speedbar-indentation-width 2)))
2344 2400
2345
2346;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2401;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2347;;; Help functions / inline substitutions / macros 2402;;; Help functions / inline substitutions / macros
2348;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2403;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2433,6 +2488,7 @@ old environment. Used for consistent searching."
2433 (progn (set-buffer (create-file-buffer ,file-name)) 2488 (progn (set-buffer (create-file-buffer ,file-name))
2434 (setq file-opened t) 2489 (setq file-opened t)
2435 (vhdl-insert-file-contents ,file-name) 2490 (vhdl-insert-file-contents ,file-name)
2491 ;; FIXME: This modifies a global syntax-table!
2436 (modify-syntax-entry ?\- ". 12" (syntax-table)) 2492 (modify-syntax-entry ?\- ". 12" (syntax-table))
2437 (modify-syntax-entry ?\n ">" (syntax-table)) 2493 (modify-syntax-entry ?\n ">" (syntax-table))
2438 (modify-syntax-entry ?\^M ">" (syntax-table)) 2494 (modify-syntax-entry ?\^M ">" (syntax-table))
@@ -2489,7 +2545,7 @@ conversion."
2489 2545
2490(defun vhdl-delete (elt list) 2546(defun vhdl-delete (elt list)
2491 "Delete by side effect the first occurrence of ELT as a member of LIST." 2547 "Delete by side effect the first occurrence of ELT as a member of LIST."
2492 (setq list (cons nil list)) 2548 (push nil list)
2493 (let ((list1 list)) 2549 (let ((list1 list))
2494 (while (and (cdr list1) (not (equal elt (cadr list1)))) 2550 (while (and (cdr list1) (not (equal elt (cadr list1))))
2495 (setq list1 (cdr list1))) 2551 (setq list1 (cdr list1)))
@@ -2497,6 +2553,9 @@ conversion."
2497 (setcdr list1 (cddr list1)))) 2553 (setcdr list1 (cddr list1))))
2498 (cdr list)) 2554 (cdr list))
2499 2555
2556(declare-function speedbar-refresh "speedbar" (&optional arg))
2557(declare-function speedbar-do-function-pointer "speedbar" ())
2558
2500(defun vhdl-speedbar-refresh (&optional key) 2559(defun vhdl-speedbar-refresh (&optional key)
2501 "Refresh directory or project with name KEY." 2560 "Refresh directory or project with name KEY."
2502 (when (and (boundp 'speedbar-frame) 2561 (when (and (boundp 'speedbar-frame)
@@ -2537,6 +2596,11 @@ conversion."
2537 (set-buffer (marker-buffer marker))) 2596 (set-buffer (marker-buffer marker)))
2538 (goto-char marker)) 2597 (goto-char marker))
2539 2598
2599(defun vhdl-goto-line (line)
2600 "Use this instead of calling user level function `goto-line'."
2601 (goto-char (point-min))
2602 (forward-line (1- line)))
2603
2540(defun vhdl-menu-split (list title) 2604(defun vhdl-menu-split (list title)
2541 "Split menu LIST into several submenus, if number of 2605 "Split menu LIST into several submenus, if number of
2542elements > `vhdl-menu-max-size'." 2606elements > `vhdl-menu-max-size'."
@@ -2547,19 +2611,19 @@ elements > `vhdl-menu-max-size'."
2547 (menuno 1) 2611 (menuno 1)
2548 (i 0)) 2612 (i 0))
2549 (while remain 2613 (while remain
2550 (setq sublist (cons (car remain) sublist)) 2614 (push (car remain) sublist)
2551 (setq remain (cdr remain)) 2615 (setq remain (cdr remain))
2552 (setq i (+ i 1)) 2616 (setq i (+ i 1))
2553 (if (= i vhdl-menu-max-size) 2617 (if (= i vhdl-menu-max-size)
2554 (progn 2618 (progn
2555 (setq result (cons (cons (format "%s %s" title menuno) 2619 (push (cons (format "%s %s" title menuno)
2556 (nreverse sublist)) result)) 2620 (nreverse sublist)) result)
2557 (setq i 0) 2621 (setq i 0)
2558 (setq menuno (+ menuno 1)) 2622 (setq menuno (+ menuno 1))
2559 (setq sublist '())))) 2623 (setq sublist '()))))
2560 (and sublist 2624 (and sublist
2561 (setq result (cons (cons (format "%s %s" title menuno) 2625 (push (cons (format "%s %s" title menuno)
2562 (nreverse sublist)) result))) 2626 (nreverse sublist)) result))
2563 (nreverse result)) 2627 (nreverse result))
2564 list)) 2628 list))
2565 2629
@@ -2723,11 +2787,6 @@ STRING are replaced by `-' and substrings are converted to lower case."
2723 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)) 2787 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun))
2724 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp) 2788 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
2725 (define-key vhdl-mode-map "\M-^" 'vhdl-delete-indentation) 2789 (define-key vhdl-mode-map "\M-^" 'vhdl-delete-indentation)
2726 ;; backspace/delete key bindings
2727 (define-key vhdl-mode-map [backspace] 'backward-delete-char-untabify)
2728 (unless (boundp 'delete-key-deletes-forward) ; XEmacs variable
2729 (define-key vhdl-mode-map [delete] 'delete-char)
2730 (define-key vhdl-mode-map [(meta delete)] 'kill-word))
2731 ;; mode specific key bindings 2790 ;; mode specific key bindings
2732 (define-key vhdl-mode-map "\C-c\C-m\C-e" 'vhdl-electric-mode) 2791 (define-key vhdl-mode-map "\C-c\C-m\C-e" 'vhdl-electric-mode)
2733 (define-key vhdl-mode-map "\C-c\C-m\C-s" 'vhdl-stutter-mode) 2792 (define-key vhdl-mode-map "\C-c\C-m\C-s" 'vhdl-stutter-mode)
@@ -2794,6 +2853,8 @@ STRING are replaced by `-' and substrings are converted to lower case."
2794 (define-key vhdl-mode-map "\C-c\C-l\C-o" 'vhdl-line-open) 2853 (define-key vhdl-mode-map "\C-c\C-l\C-o" 'vhdl-line-open)
2795 (define-key vhdl-mode-map "\C-c\C-l\C-g" 'goto-line) 2854 (define-key vhdl-mode-map "\C-c\C-l\C-g" 'goto-line)
2796 (define-key vhdl-mode-map "\C-c\C-l\C-c" 'vhdl-comment-uncomment-line) 2855 (define-key vhdl-mode-map "\C-c\C-l\C-c" 'vhdl-comment-uncomment-line)
2856 (define-key vhdl-mode-map "\C-c\C-x\C-s" 'vhdl-fix-statement-region)
2857 (define-key vhdl-mode-map "\C-c\C-x\M-s" 'vhdl-fix-statement-buffer)
2797 (define-key vhdl-mode-map "\C-c\C-x\C-p" 'vhdl-fix-clause) 2858 (define-key vhdl-mode-map "\C-c\C-x\C-p" 'vhdl-fix-clause)
2798 (define-key vhdl-mode-map "\C-c\C-x\M-c" 'vhdl-fix-case-region) 2859 (define-key vhdl-mode-map "\C-c\C-x\M-c" 'vhdl-fix-case-region)
2799 (define-key vhdl-mode-map "\C-c\C-x\C-c" 'vhdl-fix-case-buffer) 2860 (define-key vhdl-mode-map "\C-c\C-x\C-c" 'vhdl-fix-case-buffer)
@@ -2864,56 +2925,51 @@ STRING are replaced by `-' and substrings are converted to lower case."
2864;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2925;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2865;; Syntax table 2926;; Syntax table
2866 2927
2867(defvar vhdl-mode-syntax-table nil 2928(defvar vhdl-mode-syntax-table
2929 (let ((st (make-syntax-table)))
2930 ;; define punctuation
2931 (modify-syntax-entry ?\# "." st)
2932 (modify-syntax-entry ?\$ "." st)
2933 (modify-syntax-entry ?\% "." st)
2934 (modify-syntax-entry ?\& "." st)
2935 (modify-syntax-entry ?\' "." st)
2936 (modify-syntax-entry ?\* "." st)
2937 (modify-syntax-entry ?\+ "." st)
2938 (modify-syntax-entry ?\. "." st)
2939 (modify-syntax-entry ?\/ "." st)
2940 (modify-syntax-entry ?\: "." st)
2941 (modify-syntax-entry ?\; "." st)
2942 (modify-syntax-entry ?\< "." st)
2943 (modify-syntax-entry ?\= "." st)
2944 (modify-syntax-entry ?\> "." st)
2945 (modify-syntax-entry ?\\ "." st)
2946 (modify-syntax-entry ?\| "." st)
2947 ;; define string
2948 (modify-syntax-entry ?\" "\"" st)
2949 ;; define underscore
2950 (modify-syntax-entry ?\_ (if vhdl-underscore-is-part-of-word "w" "_") st)
2951 ;; a single hyphen is punctuation, but a double hyphen starts a comment
2952 (modify-syntax-entry ?\- ". 12" st)
2953 ;; and \n and \^M end a comment
2954 (modify-syntax-entry ?\n ">" st)
2955 (modify-syntax-entry ?\^M ">" st)
2956 ;; define parentheses to match
2957 (modify-syntax-entry ?\( "()" st)
2958 (modify-syntax-entry ?\) ")(" st)
2959 (modify-syntax-entry ?\[ "(]" st)
2960 (modify-syntax-entry ?\] ")[" st)
2961 (modify-syntax-entry ?\{ "(}" st)
2962 (modify-syntax-entry ?\} "){" st)
2963 st)
2868 "Syntax table used in `vhdl-mode' buffers.") 2964 "Syntax table used in `vhdl-mode' buffers.")
2869 2965
2870(defvar vhdl-mode-ext-syntax-table nil 2966(defvar vhdl-mode-ext-syntax-table
2967 ;; Extended syntax table including '_' (for simpler search regexps).
2968 (let ((st (copy-syntax-table vhdl-mode-syntax-table)))
2969 (modify-syntax-entry ?_ "w" st)
2970 st)
2871 "Syntax table extended by `_' used in `vhdl-mode' buffers.") 2971 "Syntax table extended by `_' used in `vhdl-mode' buffers.")
2872 2972
2873(defun vhdl-mode-syntax-table-init ()
2874 "Initialize `vhdl-mode-syntax-table'."
2875 (setq vhdl-mode-syntax-table (make-syntax-table))
2876 ;; define punctuation
2877 (modify-syntax-entry ?\# "." vhdl-mode-syntax-table)
2878 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
2879 (modify-syntax-entry ?\% "." vhdl-mode-syntax-table)
2880 (modify-syntax-entry ?\& "." vhdl-mode-syntax-table)
2881 (modify-syntax-entry ?\' "." vhdl-mode-syntax-table)
2882 (modify-syntax-entry ?\* "." vhdl-mode-syntax-table)
2883 (modify-syntax-entry ?\+ "." vhdl-mode-syntax-table)
2884 (modify-syntax-entry ?\. "." vhdl-mode-syntax-table)
2885 (modify-syntax-entry ?\/ "." vhdl-mode-syntax-table)
2886 (modify-syntax-entry ?\: "." vhdl-mode-syntax-table)
2887 (modify-syntax-entry ?\; "." vhdl-mode-syntax-table)
2888 (modify-syntax-entry ?\< "." vhdl-mode-syntax-table)
2889 (modify-syntax-entry ?\= "." vhdl-mode-syntax-table)
2890 (modify-syntax-entry ?\> "." vhdl-mode-syntax-table)
2891 (modify-syntax-entry ?\\ "." vhdl-mode-syntax-table)
2892 (modify-syntax-entry ?\| "." vhdl-mode-syntax-table)
2893 ;; define string
2894 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
2895 ;; define underscore
2896 (when vhdl-underscore-is-part-of-word
2897 (modify-syntax-entry ?\_ "w" vhdl-mode-syntax-table))
2898 ;; a single hyphen is punctuation, but a double hyphen starts a comment
2899 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
2900 ;; and \n and \^M end a comment
2901 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
2902 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table)
2903 ;; define parentheses to match
2904 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
2905 (modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table)
2906 (modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table)
2907 (modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table)
2908 (modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table)
2909 (modify-syntax-entry ?\} "){" vhdl-mode-syntax-table)
2910 ;; extended syntax table including '_' (for simpler search regexps)
2911 (setq vhdl-mode-ext-syntax-table (copy-syntax-table vhdl-mode-syntax-table))
2912 (modify-syntax-entry ?_ "w" vhdl-mode-ext-syntax-table))
2913
2914;; initialize syntax table for VHDL Mode
2915(vhdl-mode-syntax-table-init)
2916
2917(defvar vhdl-syntactic-context nil 2973(defvar vhdl-syntactic-context nil
2918 "Buffer local variable containing syntactic analysis list.") 2974 "Buffer local variable containing syntactic analysis list.")
2919(make-variable-buffer-local 'vhdl-syntactic-context) 2975(make-variable-buffer-local 'vhdl-syntactic-context)
@@ -3506,6 +3562,9 @@ STRING are replaced by `-' and substrings are converted to lower case."
3506 ["Whitespace Region" vhdl-fixup-whitespace-region (mark)] 3562 ["Whitespace Region" vhdl-fixup-whitespace-region (mark)]
3507 ["Whitespace Buffer" vhdl-fixup-whitespace-buffer t] 3563 ["Whitespace Buffer" vhdl-fixup-whitespace-buffer t]
3508 "--" 3564 "--"
3565 ["Statement Region" vhdl-fix-statement-region (mark)]
3566 ["Statement Buffer" vhdl-fix-statement-buffer t]
3567 "--"
3509 ["Trailing Spaces Buffer" vhdl-remove-trailing-spaces t]) 3568 ["Trailing Spaces Buffer" vhdl-remove-trailing-spaces t])
3510 ("Update" 3569 ("Update"
3511 ["Sensitivity List" vhdl-update-sensitivity-list-process t] 3570 ["Sensitivity List" vhdl-update-sensitivity-list-process t]
@@ -3814,6 +3873,7 @@ STRING are replaced by `-' and substrings are converted to lower case."
3814 ["Always" 3873 ["Always"
3815 (customize-set-variable 'vhdl-include-group-comments 'always) 3874 (customize-set-variable 'vhdl-include-group-comments 'always)
3816 :style radio :selected (eq 'always vhdl-include-group-comments)]) 3875 :style radio :selected (eq 'always vhdl-include-group-comments)])
3876 ["Actual Generic Name..." (customize-option 'vhdl-actual-generic-name) t]
3817 ["Actual Port Name..." (customize-option 'vhdl-actual-port-name) t] 3877 ["Actual Port Name..." (customize-option 'vhdl-actual-port-name) t]
3818 ["Instance Name..." (customize-option 'vhdl-instance-name) t] 3878 ["Instance Name..." (customize-option 'vhdl-instance-name) t]
3819 ("Testbench" 3879 ("Testbench"
@@ -3910,7 +3970,7 @@ STRING are replaced by `-' and substrings are converted to lower case."
3910 ["End Comment Column..." (customize-option 'vhdl-end-comment-column) t] 3970 ["End Comment Column..." (customize-option 'vhdl-end-comment-column) t]
3911 "--" 3971 "--"
3912 ["Customize Group..." (customize-group 'vhdl-comment) t]) 3972 ["Customize Group..." (customize-group 'vhdl-comment) t])
3913 ("Align" 3973 ("Beautify"
3914 ["Auto Align Templates" 3974 ["Auto Align Templates"
3915 (customize-set-variable 'vhdl-auto-align (not vhdl-auto-align)) 3975 (customize-set-variable 'vhdl-auto-align (not vhdl-auto-align))
3916 :style toggle :selected vhdl-auto-align] 3976 :style toggle :selected vhdl-auto-align]
@@ -3918,13 +3978,14 @@ STRING are replaced by `-' and substrings are converted to lower case."
3918 (customize-set-variable 'vhdl-align-groups (not vhdl-align-groups)) 3978 (customize-set-variable 'vhdl-align-groups (not vhdl-align-groups))
3919 :style toggle :selected vhdl-align-groups] 3979 :style toggle :selected vhdl-align-groups]
3920 ["Group Separation String..." 3980 ["Group Separation String..."
3921 (customize-set-variable 'vhdl-align-group-separate) t] 3981 (customize-option 'vhdl-align-group-separate) t]
3922 ["Align Lines with Same Indent" 3982 ["Align Lines with Same Indent"
3923 (customize-set-variable 'vhdl-align-same-indent 3983 (customize-set-variable 'vhdl-align-same-indent
3924 (not vhdl-align-same-indent)) 3984 (not vhdl-align-same-indent))
3925 :style toggle :selected vhdl-align-same-indent] 3985 :style toggle :selected vhdl-align-same-indent]
3986 ["Beautify Options..." (customize-option 'vhdl-beautify-options) t]
3926 "--" 3987 "--"
3927 ["Customize Group..." (customize-group 'vhdl-align) t]) 3988 ["Customize Group..." (customize-group 'vhdl-beautify) t])
3928 ("Highlight" 3989 ("Highlight"
3929 ["Highlighting On/Off..." 3990 ["Highlighting On/Off..."
3930 (customize-option 3991 (customize-option
@@ -4188,14 +4249,13 @@ The directory of the current source file is scanned."
4188 (setq found nil) 4249 (setq found nil)
4189 (while file-list 4250 (while file-list
4190 (setq found t) 4251 (setq found t)
4191 (setq menu-list (cons (vector (car file-list) 4252 (push (vector (car file-list) (list 'find-file (car file-list)) t)
4192 (list 'find-file (car file-list)) t) 4253 menu-list)
4193 menu-list))
4194 (setq file-list (cdr file-list))) 4254 (setq file-list (cdr file-list)))
4195 (setq menu-list (vhdl-menu-split menu-list "Sources")) 4255 (setq menu-list (vhdl-menu-split menu-list "Sources"))
4196 (when found (setq menu-list (cons "--" menu-list))) 4256 (when found (push "--" menu-list))
4197 (setq menu-list (cons ["*Rescan*" vhdl-add-source-files-menu t] menu-list)) 4257 (push ["*Rescan*" vhdl-add-source-files-menu t] menu-list)
4198 (setq menu-list (cons "Sources" menu-list)) 4258 (push "Sources" menu-list)
4199 ;; Create menu 4259 ;; Create menu
4200 (easy-menu-add menu-list) 4260 (easy-menu-add menu-list)
4201 (easy-menu-define vhdl-sources-menu newmap 4261 (easy-menu-define vhdl-sources-menu newmap
@@ -4579,7 +4639,7 @@ Usage:
4579 option `vhdl-index-menu' to non-nil) or made accessible as a mouse menu 4639 option `vhdl-index-menu' to non-nil) or made accessible as a mouse menu
4580 (e.g. add \"(global-set-key '[S-down-mouse-3] 'imenu)\" to your start-up 4640 (e.g. add \"(global-set-key '[S-down-mouse-3] 'imenu)\" to your start-up
4581 file) for browsing the file contents (is not populated if buffer is 4641 file) for browsing the file contents (is not populated if buffer is
4582 larger than `font-lock-maximum-size'). Also, a source file menu can be 4642 larger than 256000). Also, a source file menu can be
4583 added (set option `vhdl-source-file-menu' to non-nil) for browsing the 4643 added (set option `vhdl-source-file-menu' to non-nil) for browsing the
4584 current directory for VHDL source files. 4644 current directory for VHDL source files.
4585 4645
@@ -4706,7 +4766,7 @@ Usage:
4706 automatically recognized as VHDL source files. To add an extension 4766 automatically recognized as VHDL source files. To add an extension
4707 \".xxx\", add the following line to your Emacs start-up file (`.emacs'): 4767 \".xxx\", add the following line to your Emacs start-up file (`.emacs'):
4708 4768
4709 \(setq auto-mode-alist (cons '(\"\\\\.xxx\\\\'\" . vhdl-mode) auto-mode-alist)) 4769 \(push '(\"\\\\.xxx\\\\'\" . vhdl-mode) auto-mode-alist)
4710 4770
4711 4771
4712 HINTS: 4772 HINTS:
@@ -7277,7 +7337,7 @@ indentation change."
7277 (beginning-of-line 2) 7337 (beginning-of-line 2)
7278 (setq syntax (vhdl-get-syntactic-context))))) 7338 (setq syntax (vhdl-get-syntactic-context)))))
7279 (when is-comment 7339 (when is-comment
7280 (setq syntax (cons (cons 'comment nil) syntax))) 7340 (push (cons 'comment nil) syntax))
7281 (apply '+ (mapcar 'vhdl-get-offset syntax))) 7341 (apply '+ (mapcar 'vhdl-get-offset syntax)))
7282 ;; indent like previous nonblank line 7342 ;; indent like previous nonblank line
7283 (save-excursion (beginning-of-line) 7343 (save-excursion (beginning-of-line)
@@ -7388,7 +7448,7 @@ ENDPOS is encountered."
7388 7448
7389 7449
7390;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7450;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7391;;; Alignment, whitespace fixup, beautifying 7451;;; Alignment, beautifying
7392;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7452;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7393 7453
7394(defconst vhdl-align-alist 7454(defconst vhdl-align-alist
@@ -7604,7 +7664,8 @@ the token in MATCH."
7604 (when vhdl-progress-interval 7664 (when vhdl-progress-interval
7605 (setq vhdl-progress-info (vector (count-lines (point-min) beg) 7665 (setq vhdl-progress-info (vector (count-lines (point-min) beg)
7606 (count-lines (point-min) end) 0)))) 7666 (count-lines (point-min) end) 0))))
7607 (vhdl-fixup-whitespace-region beg end t) 7667 (when (nth 0 vhdl-beautify-options)
7668 (vhdl-fixup-whitespace-region beg end t))
7608 (goto-char beg) 7669 (goto-char beg)
7609 (if (not vhdl-align-groups) 7670 (if (not vhdl-align-groups)
7610 ;; align entire region 7671 ;; align entire region
@@ -7728,14 +7789,14 @@ the token in MATCH."
7728 ;; search for comment start positions and lengths 7789 ;; search for comment start positions and lengths
7729 (while (< (point) end) 7790 (while (< (point) end)
7730 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>")) 7791 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
7731 (looking-at "^\\(.*[^ \t\n\r\f-]+\\)\\s-*\\(--.*\\)$") 7792 (looking-at "^\\(.*?[^ \t\n\r\f-]+\\)\\s-*\\(--.*\\)$")
7732 (not (save-excursion (goto-char (match-beginning 2)) 7793 (not (save-excursion (goto-char (match-beginning 2))
7733 (vhdl-in-literal)))) 7794 (vhdl-in-literal))))
7734 (setq start (+ (- (match-end 1) (match-beginning 1)) spacing)) 7795 (setq start (+ (- (match-end 1) (match-beginning 1)) spacing))
7735 (setq length (- (match-end 2) (match-beginning 2))) 7796 (setq length (- (match-end 2) (match-beginning 2)))
7736 (setq start-max (max start start-max)) 7797 (setq start-max (max start start-max))
7737 (setq length-max (max length length-max)) 7798 (setq length-max (max length length-max))
7738 (setq comment-list (cons (cons start length) comment-list))) 7799 (push (cons start length) comment-list))
7739 (beginning-of-line 2)) 7800 (beginning-of-line 2))
7740 (setq comment-list 7801 (setq comment-list
7741 (sort comment-list (function (lambda (a b) (> (car a) (car b)))))) 7802 (sort comment-list (function (lambda (a b) (> (car a) (car b))))))
@@ -7746,14 +7807,14 @@ the token in MATCH."
7746 (unless (or (= (caar comment-list) (car start-list)) 7807 (unless (or (= (caar comment-list) (car start-list))
7747 (<= (+ (car start-list) (cdar comment-list)) 7808 (<= (+ (car start-list) (cdar comment-list))
7748 end-comment-column)) 7809 end-comment-column))
7749 (setq start-list (cons (caar comment-list) start-list))) 7810 (push (caar comment-list) start-list))
7750 (setq comment-list (cdr comment-list))) 7811 (setq comment-list (cdr comment-list)))
7751 ;; align lines as nicely as possible 7812 ;; align lines as nicely as possible
7752 (goto-char beg) 7813 (goto-char beg)
7753 (while (< (point) end) 7814 (while (< (point) end)
7754 (setq cur-start nil) 7815 (setq cur-start nil)
7755 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>")) 7816 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
7756 (or (and (looking-at "^\\(.*[^ \t\n\r\f-]+\\)\\(\\s-*\\)\\(--.*\\)$") 7817 (or (and (looking-at "^\\(.*?[^ \t\n\r\f-]+\\)\\(\\s-*\\)\\(--.*\\)$")
7757 (not (save-excursion 7818 (not (save-excursion
7758 (goto-char (match-beginning 3)) 7819 (goto-char (match-beginning 3))
7759 (vhdl-in-literal)))) 7820 (vhdl-in-literal))))
@@ -7879,7 +7940,7 @@ end of line, do nothing in comments and strings."
7879 (replace-match "\\2"))) 7940 (replace-match "\\2")))
7880 ;; surround operator symbols by one space 7941 ;; surround operator symbols by one space
7881 (goto-char beg) 7942 (goto-char beg)
7882 (while (re-search-forward "\\(--.*\n\\|\"[^\"\n]*[\"\n]\\|\'.\'\\|\\\\[^\\\n]*[\\\n]\\)\\|\\(\\([^/:<>=]\\)\\(:\\|\\??=\\|\\??<<\\|\\??>>\\|\\??<\\|\\??>\\|:=\\|\\??<=\\|\\??>=\\|=>\\|\\??/=\\|\\?\\?\\)\\([^=>]\\|$\\)\\)" end t) 7943 (while (re-search-forward "\\(--.*\n\\|\"[^\"\n]*[\"\n]\\|\'.\'\\|\\\\[^\\\n]*[\\\n]\\)\\|\\(\\([^/:<>=\n]\\)\\(:\\|\\??=\\|\\??<<\\|\\??>>\\|\\??<\\|\\??>\\|:=\\|\\??<=\\|\\??>=\\|=>\\|\\??/=\\|\\?\\?\\)\\([^=>\n]\\|$\\)\\)" end t)
7883 (if (or (match-string 1) 7944 (if (or (match-string 1)
7884 (<= (match-beginning 0) ; not if at boi 7945 (<= (match-beginning 0) ; not if at boi
7885 (save-excursion (back-to-indentation) (point)))) 7946 (save-excursion (back-to-indentation) (point))))
@@ -7913,6 +7974,154 @@ end of line, do nothing in comments."
7913 (vhdl-fixup-whitespace-region (point-min) (point-max))) 7974 (vhdl-fixup-whitespace-region (point-min) (point-max)))
7914 7975
7915;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7976;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7977;; Case fixing
7978
7979(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
7980 "Convert all words matching WORD-REGEXP in region to lower or upper case,
7981depending on parameter UPPER-CASE."
7982 (let ((case-replace nil)
7983 (last-update 0))
7984 (vhdl-prepare-search-2
7985 (save-excursion
7986 (goto-char end)
7987 (setq end (point-marker))
7988 (goto-char beg)
7989 (while (re-search-forward word-regexp end t)
7990 (or (vhdl-in-literal)
7991 (if upper-case
7992 (upcase-word -1)
7993 (downcase-word -1)))
7994 (when (and count vhdl-progress-interval (not noninteractive)
7995 (< vhdl-progress-interval
7996 (- (nth 1 (current-time)) last-update)))
7997 (message "Fixing case... (%2d%s)"
7998 (+ (* count 20) (/ (* 20 (- (point) beg)) (- end beg)))
7999 "%")
8000 (setq last-update (nth 1 (current-time)))))
8001 (goto-char end)))))
8002
8003(defun vhdl-fix-case-region (beg end &optional arg)
8004 "Convert all VHDL words in region to lower or upper case, depending on
8005options vhdl-upper-case-{keywords,types,attributes,enum-values}."
8006 (interactive "r\nP")
8007 (vhdl-fix-case-region-1
8008 beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
8009 (vhdl-fix-case-region-1
8010 beg end vhdl-upper-case-types vhdl-types-regexp 1)
8011 (vhdl-fix-case-region-1
8012 beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
8013 (vhdl-fix-case-region-1
8014 beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3)
8015 (vhdl-fix-case-region-1
8016 beg end vhdl-upper-case-constants vhdl-constants-regexp 4)
8017 (when vhdl-progress-interval (message "Fixing case...done")))
8018
8019(defun vhdl-fix-case-buffer ()
8020 "Convert all VHDL words in buffer to lower or upper case, depending on
8021options vhdl-upper-case-{keywords,types,attributes,enum-values}."
8022 (interactive)
8023 (vhdl-fix-case-region (point-min) (point-max)))
8024
8025(defun vhdl-fix-case-word (&optional arg)
8026 "Convert word after cursor to upper case if necessary."
8027 (interactive "p")
8028 (save-excursion
8029 (when arg (backward-word 1))
8030 (vhdl-prepare-search-1
8031 (when (and vhdl-upper-case-keywords
8032 (looking-at vhdl-keywords-regexp))
8033 (upcase-word 1))
8034 (when (and vhdl-upper-case-types
8035 (looking-at vhdl-types-regexp))
8036 (upcase-word 1))
8037 (when (and vhdl-upper-case-attributes
8038 (looking-at vhdl-attributes-regexp))
8039 (upcase-word 1))
8040 (when (and vhdl-upper-case-enum-values
8041 (looking-at vhdl-enum-values-regexp))
8042 (upcase-word 1))
8043 (when (and vhdl-upper-case-constants
8044 (looking-at vhdl-constants-regexp))
8045 (upcase-word 1)))))
8046
8047;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8048;; Fix statements
8049;; - force each statement to be on a separate line except when on same line
8050;; with 'end' keyword
8051
8052(defun vhdl-fix-statement-region (beg end &optional arg)
8053 "Force statements in region on separate line except when on same line
8054with 'end' keyword (necessary for correct indentation).
8055Currently supported keywords: 'begin', 'if'."
8056 (interactive "r\nP")
8057 (vhdl-prepare-search-2
8058 (let (point)
8059 (save-excursion
8060 (goto-char end)
8061 (setq end (point-marker))
8062 (goto-char beg)
8063 ;; `begin' keyword
8064 (while (re-search-forward
8065 "^\\s-*[^ \t\n].*?\\(\\<begin\\>\\)\\(.*\\<end\\>\\)?" end t)
8066 (goto-char (match-end 0))
8067 (setq point (point-marker))
8068 (when (and (match-string 1)
8069 (or (not (match-string 2))
8070 (save-excursion (goto-char (match-end 2))
8071 (vhdl-in-literal)))
8072 (not (save-excursion (goto-char (match-beginning 1))
8073 (vhdl-in-literal))))
8074 (goto-char (match-beginning 1))
8075 (insert "\n")
8076 (indent-according-to-mode))
8077 (goto-char point))
8078 (goto-char beg)
8079 ;; `for', `if' keywords
8080 (while (re-search-forward "\\<\\(for\\|if\\)\\>" end t)
8081 (goto-char (match-end 1))
8082 (setq point (point-marker))
8083 ;; exception: in literal or preceded by `end' or label
8084 (when (and (not (save-excursion (goto-char (match-beginning 1))
8085 (vhdl-in-literal)))
8086 (save-excursion
8087 (beginning-of-line 1)
8088 (save-match-data
8089 (and (re-search-forward "^\\s-*\\([^ \t\n].*\\)"
8090 (match-beginning 1) t)
8091 (not (string-match
8092 "\\(\\<end\\>\\|\\<wait\\>\\|\\w+\\s-*:\\)\\s-*$"
8093 (match-string 1)))))))
8094 (goto-char (match-beginning 1))
8095 (insert "\n")
8096 (indent-according-to-mode))
8097 (goto-char point))))))
8098
8099(defun vhdl-fix-statement-buffer ()
8100 "Force statements in buffer on separate line except when on same line
8101with 'end' keyword (necessary for correct indentation)."
8102 (interactive)
8103 (vhdl-fix-statement-region (point-min) (point-max)))
8104
8105;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8106;; Trailing spaces
8107
8108(defun vhdl-remove-trailing-spaces-region (beg end &optional arg)
8109 "Remove trailing spaces in region."
8110 (interactive "r\nP")
8111 (save-excursion
8112 (goto-char end)
8113 (setq end (point-marker))
8114 (goto-char beg)
8115 (while (re-search-forward "[ \t]+$" end t)
8116 (unless (vhdl-in-literal)
8117 (replace-match "" nil nil)))))
8118
8119(defun vhdl-remove-trailing-spaces ()
8120 "Remove trailing spaces in buffer."
8121 (interactive)
8122 (vhdl-remove-trailing-spaces-region (point-min) (point-max)))
8123
8124;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7916;; Beautify 8125;; Beautify
7917 8126
7918(defun vhdl-beautify-region (beg end) 8127(defun vhdl-beautify-region (beg end)
@@ -7922,10 +8131,17 @@ case fixing to a region. Calls functions `vhdl-indent-buffer',
7922`vhdl-fix-case-buffer'." 8131`vhdl-fix-case-buffer'."
7923 (interactive "r") 8132 (interactive "r")
7924 (setq end (save-excursion (goto-char end) (point-marker))) 8133 (setq end (save-excursion (goto-char end) (point-marker)))
7925 (vhdl-indent-region beg end) 8134 (save-excursion ; remove DOS EOL characters in UNIX file
8135 (goto-char beg)
8136 (while (search-forward " " nil t)
8137 (replace-match "" nil t)))
8138 (when (nth 0 vhdl-beautify-options) (vhdl-fixup-whitespace-region beg end t))
8139 (when (nth 1 vhdl-beautify-options) (vhdl-fix-statement-region beg end))
8140 (when (nth 2 vhdl-beautify-options) (vhdl-indent-region beg end))
7926 (let ((vhdl-align-groups t)) 8141 (let ((vhdl-align-groups t))
7927 (vhdl-align-region beg end)) 8142 (when (nth 3 vhdl-beautify-options) (vhdl-align-region beg end)))
7928 (vhdl-fix-case-region beg end)) 8143 (when (nth 4 vhdl-beautify-options) (vhdl-fix-case-region beg end))
8144 (when (nth 0 vhdl-beautify-options) (vhdl-remove-trailing-spaces-region beg end)))
7929 8145
7930(defun vhdl-beautify-buffer () 8146(defun vhdl-beautify-buffer ()
7931 "Beautify buffer by applying indentation, whitespace fixup, alignment, and 8147 "Beautify buffer by applying indentation, whitespace fixup, alignment, and
@@ -8021,7 +8237,8 @@ buffer."
8021 (while (re-search-forward "^\\s-*\\(\\w+[ \t\n\r\f]*:[ \t\n\r\f]*\\)?process\\>" nil t) 8237 (while (re-search-forward "^\\s-*\\(\\w+[ \t\n\r\f]*:[ \t\n\r\f]*\\)?process\\>" nil t)
8022 (goto-char (match-beginning 0)) 8238 (goto-char (match-beginning 0))
8023 (condition-case nil (vhdl-update-sensitivity-list) (error ""))) 8239 (condition-case nil (vhdl-update-sensitivity-list) (error "")))
8024 (message "Updating sensitivity lists...done")))) 8240 (message "Updating sensitivity lists...done")))
8241 (when noninteractive (save-buffer)))
8025 8242
8026(defun vhdl-update-sensitivity-list () 8243(defun vhdl-update-sensitivity-list ()
8027 "Update sensitivity list." 8244 "Update sensitivity list."
@@ -8047,57 +8264,57 @@ buffer."
8047 (scan-regions-list 8264 (scan-regions-list
8048 '(;; right-hand side of signal/variable assignment 8265 '(;; right-hand side of signal/variable assignment
8049 ;; (special case: "<=" is relational operator in a condition) 8266 ;; (special case: "<=" is relational operator in a condition)
8050 ((re-search-forward "[<:]=" proc-end t) 8267 ((vhdl-re-search-forward "[<:]=" proc-end t)
8051 (re-search-forward ";\\|\\<\\(then\\|loop\\|report\\|severity\\|is\\)\\>" proc-end t)) 8268 (vhdl-re-search-forward ";\\|\\<\\(then\\|loop\\|report\\|severity\\|is\\)\\>" proc-end t))
8052 ;; if condition 8269 ;; if condition
8053 ((re-search-forward "^\\s-*if\\>" proc-end t) 8270 ((vhdl-re-search-forward "^\\s-*if\\>" proc-end t)
8054 (re-search-forward "\\<then\\>" proc-end t)) 8271 (vhdl-re-search-forward "\\<then\\>" proc-end t))
8055 ;; elsif condition 8272 ;; elsif condition
8056 ((re-search-forward "\\<elsif\\>" proc-end t) 8273 ((vhdl-re-search-forward "\\<elsif\\>" proc-end t)
8057 (re-search-forward "\\<then\\>" proc-end t)) 8274 (vhdl-re-search-forward "\\<then\\>" proc-end t))
8058 ;; while loop condition 8275 ;; while loop condition
8059 ((re-search-forward "^\\s-*while\\>" proc-end t) 8276 ((vhdl-re-search-forward "^\\s-*while\\>" proc-end t)
8060 (re-search-forward "\\<loop\\>" proc-end t)) 8277 (vhdl-re-search-forward "\\<loop\\>" proc-end t))
8061 ;; exit/next condition 8278 ;; exit/next condition
8062 ((re-search-forward "\\<\\(exit\\|next\\)\\s-+\\w+\\s-+when\\>" proc-end t) 8279 ((vhdl-re-search-forward "\\<\\(exit\\|next\\)\\s-+\\w+\\s-+when\\>" proc-end t)
8063 (re-search-forward ";" proc-end t)) 8280 (vhdl-re-search-forward ";" proc-end t))
8064 ;; assert condition 8281 ;; assert condition
8065 ((re-search-forward "\\<assert\\>" proc-end t) 8282 ((vhdl-re-search-forward "\\<assert\\>" proc-end t)
8066 (re-search-forward "\\(\\<report\\>\\|\\<severity\\>\\|;\\)" proc-end t)) 8283 (vhdl-re-search-forward "\\(\\<report\\>\\|\\<severity\\>\\|;\\)" proc-end t))
8067 ;; case expression 8284 ;; case expression
8068 ((re-search-forward "^\\s-*case\\>" proc-end t) 8285 ((vhdl-re-search-forward "^\\s-*case\\>" proc-end t)
8069 (re-search-forward "\\<is\\>" proc-end t)) 8286 (vhdl-re-search-forward "\\<is\\>" proc-end t))
8070 ;; parameter list of procedure call, array index 8287 ;; parameter list of procedure call, array index
8071 ((and (re-search-forward "^\\s-*\\(\\w\\|\\.\\)+[ \t\n\r\f]*(" proc-end t) 8288 ((and (re-search-forward "^\\s-*\\(\\w\\|\\.\\)+[ \t\n\r\f]*(" proc-end t)
8072 (1- (point))) 8289 (1- (point)))
8073 (progn (backward-char) (forward-sexp) 8290 (progn (backward-char) (forward-sexp)
8074 (while (looking-at "(") (forward-sexp)) (point))))) 8291 (while (looking-at "(") (forward-sexp)) (point)))))
8075 name field read-list sens-list signal-list 8292 name field read-list sens-list signal-list tmp-list
8076 sens-beg sens-end beg end margin) 8293 sens-beg sens-end beg end margin)
8077 ;; scan for signals in old sensitivity list 8294 ;; scan for signals in old sensitivity list
8078 (goto-char proc-beg) 8295 (goto-char proc-beg)
8079 (re-search-forward "\\<process\\>" proc-mid t) 8296 (vhdl-re-search-forward "\\<process\\>" proc-mid t)
8080 (if (not (looking-at "[ \t\n\r\f]*(")) 8297 (if (not (looking-at "[ \t\n\r\f]*("))
8081 (setq sens-beg (point)) 8298 (setq sens-beg (point))
8082 (setq sens-beg (re-search-forward "\\([ \t\n\r\f]*\\)([ \t\n\r\f]*" nil t)) 8299 (setq sens-beg (vhdl-re-search-forward "\\([ \t\n\r\f]*\\)([ \t\n\r\f]*" nil t))
8083 (goto-char (match-end 1)) 8300 (goto-char (match-end 1))
8084 (forward-sexp) 8301 (forward-sexp)
8085 (setq sens-end (1- (point))) 8302 (setq sens-end (1- (point)))
8086 (goto-char sens-beg) 8303 (goto-char sens-beg)
8087 (while (and (re-search-forward "\\(\\w+\\)" sens-end t) 8304 (while (and (vhdl-re-search-forward "\\(\\w+\\)" sens-end t)
8088 (setq sens-list 8305 (setq sens-list
8089 (cons (downcase (match-string 0)) sens-list)) 8306 (cons (downcase (match-string 0)) sens-list))
8090 (re-search-forward "\\s-*,\\s-*" sens-end t)))) 8307 (vhdl-re-search-forward "\\s-*,\\s-*" sens-end t))))
8091 (setq signal-list (append visible-list sens-list)) 8308 (setq signal-list (append visible-list sens-list))
8092 ;; search for sequential parts 8309 ;; search for sequential parts
8093 (goto-char proc-mid) 8310 (goto-char proc-mid)
8094 (while (setq beg (re-search-forward "^\\s-*\\(els\\)?if\\>" proc-end t)) 8311 (while (setq beg (re-search-forward "^\\s-*\\(els\\)?if\\>" proc-end t))
8095 (setq end (re-search-forward "\\<then\\>" proc-end t)) 8312 (setq end (vhdl-re-search-forward "\\<then\\>" proc-end t))
8096 (when (re-search-backward "\\('event\\|\\<\\(falling\\|rising\\)_edge\\)\\>" beg t) 8313 (when (vhdl-re-search-backward "\\('event\\|\\<\\(falling\\|rising\\)_edge\\)\\>" beg t)
8097 (goto-char end) 8314 (goto-char end)
8098 (backward-word 1) 8315 (backward-word 1)
8099 (vhdl-forward-sexp) 8316 (vhdl-forward-sexp)
8100 (setq seq-region-list (cons (cons end (point)) seq-region-list)) 8317 (push (cons end (point)) seq-region-list)
8101 (beginning-of-line))) 8318 (beginning-of-line)))
8102 ;; scan for signals read in process 8319 ;; scan for signals read in process
8103 (while scan-regions-list 8320 (while scan-regions-list
@@ -8114,15 +8331,35 @@ buffer."
8114 (and tmp-list (< (point) (cdar tmp-list)))))) 8331 (and tmp-list (< (point) (cdar tmp-list))))))
8115 (while (vhdl-re-search-forward "[^'\".]\\<\\([a-zA-Z]\\w*\\)\\(\\(\\.\\w+\\|[ \t\n\r\f]*([^)]*)\\)*\\)[ \t\n\r\f]*\\('\\(\\w+\\)\\|\\(=>\\)\\)?" end t) 8332 (while (vhdl-re-search-forward "[^'\".]\\<\\([a-zA-Z]\\w*\\)\\(\\(\\.\\w+\\|[ \t\n\r\f]*([^)]*)\\)*\\)[ \t\n\r\f]*\\('\\(\\w+\\)\\|\\(=>\\)\\)?" end t)
8116 (setq name (match-string 1)) 8333 (setq name (match-string 1))
8334 ;; get array index range
8117 (when vhdl-array-index-record-field-in-sensitivity-list 8335 (when vhdl-array-index-record-field-in-sensitivity-list
8118 (setq field (match-string 2))) 8336 (setq field (match-string 2))
8337 ;; not use if it includes a variable name
8338 (save-match-data
8339 (setq tmp-list visible-list)
8340 (while (and field tmp-list)
8341 (when (string-match
8342 (concat "\\<" (car tmp-list) "\\>") field)
8343 (setq field nil))
8344 (setq tmp-list (cdr tmp-list)))))
8119 (when (and (not (match-string 6)) ; not when formal parameter 8345 (when (and (not (match-string 6)) ; not when formal parameter
8120 (not (and (match-string 5) ; not event attribute 8346 (not (and (match-string 5) ; not event attribute
8121 (not (member (downcase (match-string 5)) 8347 (not (member (downcase (match-string 5))
8122 '("event" "last_event" "transaction"))))) 8348 '("event" "last_event" "transaction")))))
8123 (member (downcase name) signal-list)) 8349 (member (downcase name) signal-list))
8124 (unless (member-ignore-case (concat name field) read-list) 8350 ;; not add if name or name+field already exists
8125 (setq read-list (cons (concat name field) read-list)))) 8351 (unless
8352 (or (member-ignore-case name read-list)
8353 (member-ignore-case (concat name field) read-list))
8354 (push (concat name field) read-list))
8355 (setq tmp-list read-list)
8356 ;; remove existing name+field if name is added
8357 (save-match-data
8358 (while tmp-list
8359 (when (string-match (concat "^" name field "[(.]")
8360 (car tmp-list))
8361 (setq read-list (delete (car tmp-list) read-list)))
8362 (setq tmp-list (cdr tmp-list)))))
8126 (goto-char (match-end 1))))) 8363 (goto-char (match-end 1)))))
8127 (setq scan-regions-list (cdr scan-regions-list))) 8364 (setq scan-regions-list (cdr scan-regions-list)))
8128 ;; update sensitivity list 8365 ;; update sensitivity list
@@ -8178,7 +8415,7 @@ buffer."
8178 (while (< (point) end) 8415 (while (< (point) end)
8179 (when (looking-at "signal[ \t\n\r\f]+") 8416 (when (looking-at "signal[ \t\n\r\f]+")
8180 (goto-char (match-end 0))) 8417 (goto-char (match-end 0)))
8181 (while (looking-at "\\(\\w+\\)[ \t\n\r\f,]+") 8418 (while (looking-at "\\([a-zA-Z]\\w*\\)[ \t\n\r\f,]+")
8182 (setq signal-list 8419 (setq signal-list
8183 (cons (downcase (match-string 1)) signal-list)) 8420 (cons (downcase (match-string 1)) signal-list))
8184 (goto-char (match-end 0)) 8421 (goto-char (match-end 0))
@@ -8197,12 +8434,12 @@ buffer."
8197 (when (= 0 (nth 0 (parse-partial-sexp beg (point)))) 8434 (when (= 0 (nth 0 (parse-partial-sexp beg (point))))
8198 (if (match-string 2) 8435 (if (match-string 2)
8199 ;; scan signal name 8436 ;; scan signal name
8200 (while (looking-at "[ \t\n\r\f,]+\\(\\w+\\)") 8437 (while (looking-at "[ \t\n\r\f,]+\\([a-zA-Z]\\w*\\)")
8201 (setq signal-list 8438 (setq signal-list
8202 (cons (downcase (match-string 1)) signal-list)) 8439 (cons (downcase (match-string 1)) signal-list))
8203 (goto-char (match-end 0))) 8440 (goto-char (match-end 0)))
8204 ;; scan alias name, check is alias of (declared) signal 8441 ;; scan alias name, check is alias of (declared) signal
8205 (when (and (looking-at "[ \t\n\r\f]+\\(\\w+\\)[^;]*\\<is[ \t\n\r\f]+\\(\\w+\\)") 8442 (when (and (looking-at "[ \t\n\r\f]+\\([a-zA-Z]\\w*\\)[^;]*\\<is[ \t\n\r\f]+\\([a-zA-Z]\\w*\\)")
8206 (member (downcase (match-string 2)) signal-list)) 8443 (member (downcase (match-string 2)) signal-list))
8207 (setq signal-list 8444 (setq signal-list
8208 (cons (downcase (match-string 1)) signal-list)) 8445 (cons (downcase (match-string 1)) signal-list))
@@ -8290,19 +8527,6 @@ buffer."
8290 (goto-char end) 8527 (goto-char end)
8291 (insert ")"))))))) 8528 (insert ")")))))))
8292 8529
8293;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8294;; Miscellaneous
8295
8296(defun vhdl-remove-trailing-spaces ()
8297 "Remove trailing spaces in the whole buffer."
8298 (interactive)
8299 (save-match-data
8300 (save-excursion
8301 (goto-char (point-min))
8302 (while (re-search-forward "[ \t]+$" (point-max) t)
8303 (unless (vhdl-in-literal)
8304 (replace-match "" nil nil))))))
8305
8306 8530
8307;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8531;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8308;;; Electrification 8532;;; Electrification
@@ -8334,14 +8558,14 @@ project is defined."
8334With a prefix argument ARG, enable the mode if ARG is positive, 8558With a prefix argument ARG, enable the mode if ARG is positive,
8335and disable it otherwise. If called from Lisp, enable it if ARG 8559and disable it otherwise. If called from Lisp, enable it if ARG
8336is omitted or nil." 8560is omitted or nil."
8337 :global t) 8561 :global t :group 'vhdl-mode)
8338 8562
8339(define-minor-mode vhdl-stutter-mode 8563(define-minor-mode vhdl-stutter-mode
8340 "Toggle VHDL stuttering mode. 8564 "Toggle VHDL stuttering mode.
8341With a prefix argument ARG, enable the mode if ARG is positive, 8565With a prefix argument ARG, enable the mode if ARG is positive,
8342and disable it otherwise. If called from Lisp, enable it if ARG 8566and disable it otherwise. If called from Lisp, enable it if ARG
8343is omitted or nil." 8567is omitted or nil."
8344 :global t) 8568 :global t :group 'vhdl-mode)
8345 8569
8346;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8570;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8347;; Stuttering 8571;; Stuttering
@@ -8398,7 +8622,7 @@ is omitted or nil."
8398(defun vhdl-electric-quote (count) "'' --> \"" 8622(defun vhdl-electric-quote (count) "'' --> \""
8399 (interactive "p") 8623 (interactive "p")
8400 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal))) 8624 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
8401 (if (= (preceding-char) last-input-event) 8625 (if (= (preceding-char) vhdl-last-input-event)
8402 (progn (delete-char -1) (insert-char ?\" 1)) 8626 (progn (delete-char -1) (insert-char ?\" 1))
8403 (insert-char ?\' 1)) 8627 (insert-char ?\' 1))
8404 (self-insert-command count))) 8628 (self-insert-command count)))
@@ -8406,7 +8630,7 @@ is omitted or nil."
8406(defun vhdl-electric-semicolon (count) "';;' --> ' : ', ': ;' --> ' := '" 8630(defun vhdl-electric-semicolon (count) "';;' --> ' : ', ': ;' --> ' := '"
8407 (interactive "p") 8631 (interactive "p")
8408 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal))) 8632 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
8409 (cond ((= (preceding-char) last-input-event) 8633 (cond ((= (preceding-char) vhdl-last-input-event)
8410 (progn (delete-char -1) 8634 (progn (delete-char -1)
8411 (unless (eq (preceding-char) ? ) (insert " ")) 8635 (unless (eq (preceding-char) ? ) (insert " "))
8412 (insert ": ") 8636 (insert ": ")
@@ -8420,7 +8644,7 @@ is omitted or nil."
8420(defun vhdl-electric-comma (count) "',,' --> ' <= '" 8644(defun vhdl-electric-comma (count) "',,' --> ' <= '"
8421 (interactive "p") 8645 (interactive "p")
8422 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal))) 8646 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
8423 (cond ((= (preceding-char) last-input-event) 8647 (cond ((= (preceding-char) vhdl-last-input-event)
8424 (progn (delete-char -1) 8648 (progn (delete-char -1)
8425 (unless (eq (preceding-char) ? ) (insert " ")) 8649 (unless (eq (preceding-char) ? ) (insert " "))
8426 (insert "<= "))) 8650 (insert "<= ")))
@@ -8430,7 +8654,7 @@ is omitted or nil."
8430(defun vhdl-electric-period (count) "'..' --> ' => '" 8654(defun vhdl-electric-period (count) "'..' --> ' => '"
8431 (interactive "p") 8655 (interactive "p")
8432 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal))) 8656 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
8433 (cond ((= (preceding-char) last-input-event) 8657 (cond ((= (preceding-char) vhdl-last-input-event)
8434 (progn (delete-char -1) 8658 (progn (delete-char -1)
8435 (unless (eq (preceding-char) ? ) (insert " ")) 8659 (unless (eq (preceding-char) ? ) (insert " "))
8436 (insert "=> "))) 8660 (insert "=> ")))
@@ -8440,7 +8664,7 @@ is omitted or nil."
8440(defun vhdl-electric-equal (count) "'==' --> ' == '" 8664(defun vhdl-electric-equal (count) "'==' --> ' == '"
8441 (interactive "p") 8665 (interactive "p")
8442 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal))) 8666 (if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
8443 (cond ((= (preceding-char) last-input-event) 8667 (cond ((= (preceding-char) vhdl-last-input-event)
8444 (progn (delete-char -1) 8668 (progn (delete-char -1)
8445 (unless (eq (preceding-char) ? ) (insert " ")) 8669 (unless (eq (preceding-char) ? ) (insert " "))
8446 (insert "== "))) 8670 (insert "== ")))
@@ -8711,12 +8935,13 @@ since these are almost equivalent)."
8711 "[COMPONENT | ENTITY | CONFIGURATION]" " " t)) 8935 "[COMPONENT | ENTITY | CONFIGURATION]" " " t))
8712 (setq unit (upcase (or unit ""))) 8936 (setq unit (upcase (or unit "")))
8713 (cond ((equal unit "ENTITY") 8937 (cond ((equal unit "ENTITY")
8714 (vhdl-template-field "library name" "." nil nil nil nil 8938 (let ((begin (point)))
8939 (vhdl-template-field "library name" "." t begin (point) nil
8715 (vhdl-work-library)) 8940 (vhdl-work-library))
8716 (vhdl-template-field "entity name" "(") 8941 (vhdl-template-field "entity name" "(")
8717 (if (vhdl-template-field "[architecture name]" nil t) 8942 (if (vhdl-template-field "[architecture name]" nil t)
8718 (insert ")") 8943 (insert ")")
8719 (delete-char -1))) 8944 (delete-char -1))))
8720 ((equal unit "CONFIGURATION") 8945 ((equal unit "CONFIGURATION")
8721 (vhdl-template-field "library name" "." nil nil nil nil 8946 (vhdl-template-field "library name" "." nil nil nil nil
8722 (vhdl-work-library)) 8947 (vhdl-work-library))
@@ -9852,7 +10077,7 @@ otherwise."
9852 (let ((definition 10077 (let ((definition
9853 (upcase 10078 (upcase
9854 (or (vhdl-template-field 10079 (or (vhdl-template-field
9855 "[scalar type | ARRAY | RECORD | ACCESS | FILE]" nil t) 10080 "[scalar type | ARRAY | RECORD | ACCESS | FILE | ENUM]" nil t)
9856 "")))) 10081 ""))))
9857 (cond ((equal definition "") 10082 (cond ((equal definition "")
9858 (delete-char -4) 10083 (delete-char -4)
@@ -9870,6 +10095,11 @@ otherwise."
9870 ((equal definition "FILE") 10095 ((equal definition "FILE")
9871 (vhdl-insert-keyword " OF ") 10096 (vhdl-insert-keyword " OF ")
9872 (vhdl-template-field "type" ";")) 10097 (vhdl-template-field "type" ";"))
10098 ((equal definition "ENUM")
10099 (kill-word -1)
10100 (insert "(")
10101 (setq end-pos (point-marker))
10102 (insert ");"))
9873 (t (insert ";"))) 10103 (t (insert ";")))
9874 (when mid-pos 10104 (when mid-pos
9875 (setq end-pos (point-marker)) 10105 (setq end-pos (point-marker))
@@ -10916,7 +11146,7 @@ but not if inside a comment or quote."
10916 (backward-word 1) 11146 (backward-word 1)
10917 (vhdl-case-word 1) 11147 (vhdl-case-word 1)
10918 (delete-char 1)) 11148 (delete-char 1))
10919 (let ((invoke-char last-command-event) 11149 (let ((invoke-char vhdl-last-input-event)
10920 (abbrev-mode -1) 11150 (abbrev-mode -1)
10921 (vhdl-template-invoked-by-hook t)) 11151 (vhdl-template-invoked-by-hook t))
10922 (let ((caught (catch 'abort 11152 (let ((caught (catch 'abort
@@ -11640,7 +11870,8 @@ reflected in a subsequent paste operation."
11640 ;; paste formal and actual generic 11870 ;; paste formal and actual generic
11641 (insert (car (nth 0 generic)) " => " 11871 (insert (car (nth 0 generic)) " => "
11642 (if no-constants 11872 (if no-constants
11643 (car (nth 0 generic)) 11873 (vhdl-replace-string vhdl-actual-generic-name
11874 (car (nth 0 generic)))
11644 (or (nth 2 generic) ""))) 11875 (or (nth 2 generic) "")))
11645 (setq generic-list (cdr generic-list)) 11876 (setq generic-list (cdr generic-list))
11646 (insert (if generic-list "," ")")) 11877 (insert (if generic-list "," ")"))
@@ -11783,7 +12014,7 @@ reflected in a subsequent paste operation."
11783 ;; paste generic constants 12014 ;; paste generic constants
11784 (setq name (nth 0 generic)) 12015 (setq name (nth 0 generic))
11785 (when name 12016 (when name
11786 (insert (car name)) 12017 (insert (vhdl-replace-string vhdl-actual-generic-name (car name)))
11787 ;; paste type 12018 ;; paste type
11788 (insert " : " (nth 1 generic)) 12019 (insert " : " (nth 1 generic))
11789 ;; paste initialization 12020 ;; paste initialization
@@ -11809,7 +12040,7 @@ reflected in a subsequent paste operation."
11809 (message "Pasting port as signals...") 12040 (message "Pasting port as signals...")
11810 (unless no-indent (indent-according-to-mode)) 12041 (unless no-indent (indent-according-to-mode))
11811 (let ((margin (current-indentation)) 12042 (let ((margin (current-indentation))
11812 start port names 12043 start port names type generic-list port-name constant-name pos
11813 (port-list (nth 2 vhdl-port-list))) 12044 (port-list (nth 2 vhdl-port-list)))
11814 (when port-list 12045 (when port-list
11815 (setq start (point)) 12046 (setq start (point))
@@ -11829,7 +12060,21 @@ reflected in a subsequent paste operation."
11829 (setq names (cdr names)) 12060 (setq names (cdr names))
11830 (when names (insert ", "))) 12061 (when names (insert ", ")))
11831 ;; paste type 12062 ;; paste type
11832 (insert " : " (nth 3 port)) 12063 (setq type (nth 3 port))
12064 (setq generic-list (nth 1 vhdl-port-list))
12065 (vhdl-prepare-search-1
12066 (setq pos 0)
12067 ;; replace formal by actual generics
12068 (while generic-list
12069 (setq port-name (car (nth 0 (car generic-list))))
12070 (while (string-match (concat "\\<" port-name "\\>") type pos)
12071 (setq constant-name
12072 (save-match-data (vhdl-replace-string
12073 vhdl-actual-generic-name port-name)))
12074 (setq type (replace-match constant-name t nil type))
12075 (setq pos (match-end 0)))
12076 (setq generic-list (cdr generic-list))))
12077 (insert " : " type)
11833 ;; paste initialization (inputs only) 12078 ;; paste initialization (inputs only)
11834 (when (and initialize (nth 2 port) (equal "IN" (upcase (nth 2 port)))) 12079 (when (and initialize (nth 2 port) (equal "IN" (upcase (nth 2 port))))
11835 (insert " := " 12080 (insert " := "
@@ -12418,77 +12663,6 @@ expressions (e.g. for index ranges of types and signals)."
12418 try-expand-list-all-buffers))) 12663 try-expand-list-all-buffers)))
12419 12664
12420;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 12665;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12421;; Case fixing
12422
12423(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
12424 "Convert all words matching WORD-REGEXP in region to lower or upper case,
12425depending on parameter UPPER-CASE."
12426 (let ((case-replace nil)
12427 (last-update 0))
12428 (vhdl-prepare-search-2
12429 (save-excursion
12430 (goto-char end)
12431 (setq end (point-marker))
12432 (goto-char beg)
12433 (while (re-search-forward word-regexp end t)
12434 (or (vhdl-in-literal)
12435 (if upper-case
12436 (upcase-word -1)
12437 (downcase-word -1)))
12438 (when (and count vhdl-progress-interval (not noninteractive)
12439 (< vhdl-progress-interval
12440 (- (nth 1 (current-time)) last-update)))
12441 (message "Fixing case... (%2d%s)"
12442 (+ (* count 20) (/ (* 20 (- (point) beg)) (- end beg)))
12443 "%")
12444 (setq last-update (nth 1 (current-time)))))
12445 (goto-char end)))))
12446
12447(defun vhdl-fix-case-region (beg end &optional arg)
12448 "Convert all VHDL words in region to lower or upper case, depending on
12449options vhdl-upper-case-{keywords,types,attributes,enum-values}."
12450 (interactive "r\nP")
12451 (vhdl-fix-case-region-1
12452 beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
12453 (vhdl-fix-case-region-1
12454 beg end vhdl-upper-case-types vhdl-types-regexp 1)
12455 (vhdl-fix-case-region-1
12456 beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
12457 (vhdl-fix-case-region-1
12458 beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3)
12459 (vhdl-fix-case-region-1
12460 beg end vhdl-upper-case-constants vhdl-constants-regexp 4)
12461 (when vhdl-progress-interval (message "Fixing case...done")))
12462
12463(defun vhdl-fix-case-buffer ()
12464 "Convert all VHDL words in buffer to lower or upper case, depending on
12465options vhdl-upper-case-{keywords,types,attributes,enum-values}."
12466 (interactive)
12467 (vhdl-fix-case-region (point-min) (point-max)))
12468
12469(defun vhdl-fix-case-word (&optional arg)
12470 "Convert word after cursor to upper case if necessary."
12471 (interactive "p")
12472 (save-excursion
12473 (when arg (backward-word 1))
12474 (vhdl-prepare-search-1
12475 (when (and vhdl-upper-case-keywords
12476 (looking-at vhdl-keywords-regexp))
12477 (upcase-word 1))
12478 (when (and vhdl-upper-case-types
12479 (looking-at vhdl-types-regexp))
12480 (upcase-word 1))
12481 (when (and vhdl-upper-case-attributes
12482 (looking-at vhdl-attributes-regexp))
12483 (upcase-word 1))
12484 (when (and vhdl-upper-case-enum-values
12485 (looking-at vhdl-enum-values-regexp))
12486 (upcase-word 1))
12487 (when (and vhdl-upper-case-constants
12488 (looking-at vhdl-constants-regexp))
12489 (upcase-word 1)))))
12490
12491;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12492;; Line handling functions 12666;; Line handling functions
12493 12667
12494(defun vhdl-current-line () 12668(defun vhdl-current-line ()
@@ -12642,7 +12816,7 @@ it works within comments too."
12642 ;; print results 12816 ;; print results
12643 (message "\n\ 12817 (message "\n\
12644File statistics: \"%s\"\n\ 12818File statistics: \"%s\"\n\
12645---------------------\n\ 12819-----------------------\n\
12646# statements : %5d\n\ 12820# statements : %5d\n\
12647# code lines : %5d\n\ 12821# code lines : %5d\n\
12648# empty lines : %5d\n\ 12822# empty lines : %5d\n\
@@ -13493,9 +13667,9 @@ hierarchy otherwise.")
13493 (while (and (re-search-backward "^[ \t]*\\(end\\|use\\)\\>" nil t) 13667 (while (and (re-search-backward "^[ \t]*\\(end\\|use\\)\\>" nil t)
13494 (equal "USE" (upcase (match-string 1)))) 13668 (equal "USE" (upcase (match-string 1))))
13495 (when (looking-at "^[ \t]*use[ \t\n\r\f]*\\(\\w+\\)\\.\\(\\w+\\)\\.\\w+") 13669 (when (looking-at "^[ \t]*use[ \t\n\r\f]*\\(\\w+\\)\\.\\(\\w+\\)\\.\\w+")
13496 (setq lib-alist (cons (cons (match-string-no-properties 1) 13670 (push (cons (match-string-no-properties 1)
13497 (vhdl-match-string-downcase 2)) 13671 (vhdl-match-string-downcase 2))
13498 lib-alist)))))) 13672 lib-alist)))))
13499 lib-alist)) 13673 lib-alist))
13500 13674
13501(defun vhdl-scan-directory-contents (name &optional project update num-string 13675(defun vhdl-scan-directory-contents (name &optional project update num-string
@@ -13541,7 +13715,7 @@ hierarchy otherwise.")
13541 file-tmp-list) 13715 file-tmp-list)
13542 (while file-list 13716 (while file-list
13543 (unless (string-match file-exclude-regexp (car file-list)) 13717 (unless (string-match file-exclude-regexp (car file-list))
13544 (setq file-tmp-list (cons (car file-list) file-tmp-list))) 13718 (push (car file-list) file-tmp-list))
13545 (setq file-list (cdr file-list))) 13719 (setq file-list (cdr file-list)))
13546 (setq file-list (nreverse file-tmp-list)))) 13720 (setq file-list (nreverse file-tmp-list))))
13547 ;; do for all files 13721 ;; do for all files
@@ -13576,7 +13750,7 @@ hierarchy otherwise.")
13576 "Entity declared twice (used 1.): \"%s\"\n 1. in \"%s\" (line %d)\n 2. in \"%s\" (line %d)" 13750 "Entity declared twice (used 1.): \"%s\"\n 1. in \"%s\" (line %d)\n 2. in \"%s\" (line %d)"
13577 ent-name (nth 1 ent-entry) (nth 2 ent-entry) 13751 ent-name (nth 1 ent-entry) (nth 2 ent-entry)
13578 file-name (vhdl-current-line)) 13752 file-name (vhdl-current-line))
13579 (setq ent-list (cons ent-key ent-list)) 13753 (push ent-key ent-list)
13580 (aput 'ent-alist ent-key 13754 (aput 'ent-alist ent-key
13581 (list ent-name file-name (vhdl-current-line) 13755 (list ent-name file-name (vhdl-current-line)
13582 (nth 3 ent-entry) (nth 4 ent-entry) 13756 (nth 3 ent-entry) (nth 4 ent-entry)
@@ -13628,7 +13802,7 @@ hierarchy otherwise.")
13628 "Configuration declared twice (used 1.): \"%s\" of \"%s\"\n 1. in \"%s\" (line %d)\n 2. in \"%s\" (line %d)" 13802 "Configuration declared twice (used 1.): \"%s\" of \"%s\"\n 1. in \"%s\" (line %d)\n 2. in \"%s\" (line %d)"
13629 conf-name ent-name (nth 1 conf-entry) 13803 conf-name ent-name (nth 1 conf-entry)
13630 (nth 2 conf-entry) file-name conf-line) 13804 (nth 2 conf-entry) file-name conf-line)
13631 (setq conf-list (cons conf-key conf-list)) 13805 (push conf-key conf-list)
13632 ;; scan for subconfigurations and subentities 13806 ;; scan for subconfigurations and subentities
13633 (while (re-search-forward "^[ \t]*for[ \t\n\r\f]+\\(\\w+\\([ \t\n\r\f]*,[ \t\n\r\f]*\\w+\\)*\\)[ \t\n\r\f]*:[ \t\n\r\f]*\\(\\w+\\)[ \t\n\r\f]+" end-of-unit t) 13807 (while (re-search-forward "^[ \t]*for[ \t\n\r\f]+\\(\\w+\\([ \t\n\r\f]*,[ \t\n\r\f]*\\w+\\)*\\)[ \t\n\r\f]*:[ \t\n\r\f]*\\(\\w+\\)[ \t\n\r\f]+" end-of-unit t)
13634 (setq inst-comp-key (vhdl-match-string-downcase 3) 13808 (setq inst-comp-key (vhdl-match-string-downcase 3)
@@ -13691,8 +13865,8 @@ hierarchy otherwise.")
13691 (setq func-alist (nreverse func-alist)) 13865 (setq func-alist (nreverse func-alist))
13692 (setq comp-alist (nreverse comp-alist)) 13866 (setq comp-alist (nreverse comp-alist))
13693 (if is-body 13867 (if is-body
13694 (setq pack-body-list (cons pack-key pack-body-list)) 13868 (push pack-key pack-body-list)
13695 (setq pack-list (cons pack-key pack-list))) 13869 (push pack-key pack-list))
13696 (aput 13870 (aput
13697 'pack-alist pack-key 13871 'pack-alist pack-key
13698 (if is-body 13872 (if is-body
@@ -13946,7 +14120,7 @@ of PROJECT."
13946 (let ((case-fold-search nil)) 14120 (let ((case-fold-search nil))
13947 (while dir-list 14121 (while dir-list
13948 (unless (string-match file-exclude-regexp (car dir-list)) 14122 (unless (string-match file-exclude-regexp (car dir-list))
13949 (setq dir-list-tmp (cons (car dir-list) dir-list-tmp))) 14123 (push (car dir-list) dir-list-tmp))
13950 (setq dir-list (cdr dir-list))) 14124 (setq dir-list (cdr dir-list)))
13951 (setq dir-list (nreverse dir-list-tmp)))) 14125 (setq dir-list (nreverse dir-list-tmp))))
13952 (message "Collecting source files...done") 14126 (message "Collecting source files...done")
@@ -14338,12 +14512,19 @@ if required."
14338;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14512;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14339;; Add hierarchy browser functionality to speedbar 14513;; Add hierarchy browser functionality to speedbar
14340 14514
14341(defvar vhdl-speedbar-key-map nil 14515(defvar vhdl-speedbar-mode-map nil
14342 "Keymap used when in the VHDL hierarchy browser mode.") 14516 "Keymap used when in the VHDL hierarchy browser mode.")
14343 14517
14344(defvar vhdl-speedbar-menu-items nil 14518(defvar vhdl-speedbar-menu-items nil
14345 "Additional menu-items to add to speedbar frame.") 14519 "Additional menu-items to add to speedbar frame.")
14346 14520
14521(declare-function speedbar-add-supported-extension "speedbar" (extension))
14522(declare-function speedbar-add-mode-functions-list "speedbar" (new-list))
14523(declare-function speedbar-make-specialized-keymap "speedbar" ())
14524(declare-function speedbar-change-initial-expansion-list "speedbar"
14525 (new-default))
14526(declare-function speedbar-add-expansion-list "speedbar" (new-list))
14527
14347(defun vhdl-speedbar-initialize () 14528(defun vhdl-speedbar-initialize ()
14348 "Initialize speedbar." 14529 "Initialize speedbar."
14349 ;; general settings 14530 ;; general settings
@@ -14366,24 +14547,24 @@ if required."
14366 (speedbar-item-info . vhdl-speedbar-item-info) 14547 (speedbar-item-info . vhdl-speedbar-item-info)
14367 (speedbar-line-directory . vhdl-speedbar-line-project))) 14548 (speedbar-line-directory . vhdl-speedbar-line-project)))
14368 ;; keymap 14549 ;; keymap
14369 (unless vhdl-speedbar-key-map 14550 (unless vhdl-speedbar-mode-map
14370 (setq vhdl-speedbar-key-map (speedbar-make-specialized-keymap)) 14551 (setq vhdl-speedbar-mode-map (speedbar-make-specialized-keymap))
14371 (define-key vhdl-speedbar-key-map "e" 'speedbar-edit-line) 14552 (define-key vhdl-speedbar-mode-map "e" 'speedbar-edit-line)
14372 (define-key vhdl-speedbar-key-map "\C-m" 'speedbar-edit-line) 14553 (define-key vhdl-speedbar-mode-map "\C-m" 'speedbar-edit-line)
14373 (define-key vhdl-speedbar-key-map "+" 'speedbar-expand-line) 14554 (define-key vhdl-speedbar-mode-map "+" 'speedbar-expand-line)
14374 (define-key vhdl-speedbar-key-map "=" 'speedbar-expand-line) 14555 (define-key vhdl-speedbar-mode-map "=" 'speedbar-expand-line)
14375 (define-key vhdl-speedbar-key-map "-" 'vhdl-speedbar-contract-level) 14556 (define-key vhdl-speedbar-mode-map "-" 'vhdl-speedbar-contract-level)
14376 (define-key vhdl-speedbar-key-map "_" 'vhdl-speedbar-contract-all) 14557 (define-key vhdl-speedbar-mode-map "_" 'vhdl-speedbar-contract-all)
14377 (define-key vhdl-speedbar-key-map "C" 'vhdl-speedbar-port-copy) 14558 (define-key vhdl-speedbar-mode-map "C" 'vhdl-speedbar-port-copy)
14378 (define-key vhdl-speedbar-key-map "P" 'vhdl-speedbar-place-component) 14559 (define-key vhdl-speedbar-mode-map "P" 'vhdl-speedbar-place-component)
14379 (define-key vhdl-speedbar-key-map "F" 'vhdl-speedbar-configuration) 14560 (define-key vhdl-speedbar-mode-map "F" 'vhdl-speedbar-configuration)
14380 (define-key vhdl-speedbar-key-map "A" 'vhdl-speedbar-select-mra) 14561 (define-key vhdl-speedbar-mode-map "A" 'vhdl-speedbar-select-mra)
14381 (define-key vhdl-speedbar-key-map "K" 'vhdl-speedbar-make-design) 14562 (define-key vhdl-speedbar-mode-map "K" 'vhdl-speedbar-make-design)
14382 (define-key vhdl-speedbar-key-map "R" 'vhdl-speedbar-rescan-hierarchy) 14563 (define-key vhdl-speedbar-mode-map "R" 'vhdl-speedbar-rescan-hierarchy)
14383 (define-key vhdl-speedbar-key-map "S" 'vhdl-save-caches) 14564 (define-key vhdl-speedbar-mode-map "S" 'vhdl-save-caches)
14384 (let ((key 0)) 14565 (let ((key 0))
14385 (while (<= key 9) 14566 (while (<= key 9)
14386 (define-key vhdl-speedbar-key-map (int-to-string key) 14567 (define-key vhdl-speedbar-mode-map (int-to-string key)
14387 `(lambda () (interactive) (vhdl-speedbar-set-depth ,key))) 14568 `(lambda () (interactive) (vhdl-speedbar-set-depth ,key)))
14388 (setq key (1+ key))))) 14569 (setq key (1+ key)))))
14389 (define-key speedbar-mode-map "h" 14570 (define-key speedbar-mode-map "h"
@@ -14436,10 +14617,10 @@ if required."
14436 ["Save Caches" vhdl-save-caches vhdl-updated-project-list]))) 14617 ["Save Caches" vhdl-save-caches vhdl-updated-project-list])))
14437 ;; hook-ups 14618 ;; hook-ups
14438 (speedbar-add-expansion-list 14619 (speedbar-add-expansion-list
14439 '("vhdl directory" vhdl-speedbar-menu-items vhdl-speedbar-key-map 14620 '("vhdl directory" vhdl-speedbar-menu-items vhdl-speedbar-mode-map
14440 vhdl-speedbar-display-directory)) 14621 vhdl-speedbar-display-directory))
14441 (speedbar-add-expansion-list 14622 (speedbar-add-expansion-list
14442 '("vhdl project" vhdl-speedbar-menu-items vhdl-speedbar-key-map 14623 '("vhdl project" vhdl-speedbar-menu-items vhdl-speedbar-mode-map
14443 vhdl-speedbar-display-projects)) 14624 vhdl-speedbar-display-projects))
14444 (setq speedbar-stealthy-function-list 14625 (setq speedbar-stealthy-function-list
14445 (append 14626 (append
@@ -14473,11 +14654,15 @@ if required."
14473 "Name of last selected project.") 14654 "Name of last selected project.")
14474 14655
14475;; macros must be defined in the file they are used (copied from `speedbar.el') 14656;; macros must be defined in the file they are used (copied from `speedbar.el')
14476(defmacro speedbar-with-writable (&rest forms) 14657;;; (defmacro speedbar-with-writable (&rest forms)
14477 "Allow the buffer to be writable and evaluate FORMS." 14658;;; "Allow the buffer to be writable and evaluate FORMS."
14478 (list 'let '((inhibit-read-only t)) 14659;;; (list 'let '((inhibit-read-only t))
14479 (cons 'progn forms))) 14660;;; (cons 'progn forms)))
14480(put 'speedbar-with-writable 'lisp-indent-function 0) 14661;;; (put 'speedbar-with-writable 'lisp-indent-function 0)
14662
14663(declare-function speedbar-extension-list-to-regex "speedbar" (extlist))
14664(declare-function speedbar-directory-buttons "speedbar" (directory _index))
14665(declare-function speedbar-file-lists "speedbar" (directory))
14481 14666
14482(defun vhdl-speedbar-display-directory (directory depth &optional rescan) 14667(defun vhdl-speedbar-display-directory (directory depth &optional rescan)
14483 "Display directory and hierarchy information in speedbar." 14668 "Display directory and hierarchy information in speedbar."
@@ -14513,6 +14698,9 @@ if required."
14513 (error (vhdl-warning-when-idle "ERROR: Invalid hierarchy information, unable to display correctly")))) 14698 (error (vhdl-warning-when-idle "ERROR: Invalid hierarchy information, unable to display correctly"))))
14514 (setq speedbar-full-text-cache nil)) ; prevent caching 14699 (setq speedbar-full-text-cache nil)) ; prevent caching
14515 14700
14701(declare-function speedbar-make-tag-line "speedbar"
14702 (type char func data tag tfunc tdata tface depth))
14703
14516(defun vhdl-speedbar-insert-projects () 14704(defun vhdl-speedbar-insert-projects ()
14517 "Insert all projects in speedbar." 14705 "Insert all projects in speedbar."
14518 (vhdl-speedbar-make-title-line "Projects:") 14706 (vhdl-speedbar-make-title-line "Projects:")
@@ -14616,6 +14804,8 @@ otherwise use cached data."
14616 depth) 14804 depth)
14617 (setq pack-alist (cdr pack-alist)))))) 14805 (setq pack-alist (cdr pack-alist))))))
14618 14806
14807(declare-function speedbar-line-directory "speedbar" (&optional depth))
14808
14619(defun vhdl-speedbar-rescan-hierarchy () 14809(defun vhdl-speedbar-rescan-hierarchy ()
14620 "Rescan hierarchy for the directory or project under the cursor." 14810 "Rescan hierarchy for the directory or project under the cursor."
14621 (interactive) 14811 (interactive)
@@ -14637,6 +14827,8 @@ otherwise use cached data."
14637 (abbreviate-file-name (match-string 1 path))))) 14827 (abbreviate-file-name (match-string 1 path)))))
14638 (vhdl-speedbar-refresh key))) 14828 (vhdl-speedbar-refresh key)))
14639 14829
14830(declare-function speedbar-goto-this-file "speedbar" (file))
14831
14640(defun vhdl-speedbar-expand-dirs (directory) 14832(defun vhdl-speedbar-expand-dirs (directory)
14641 "Expand subdirectories in DIRECTORY according to 14833 "Expand subdirectories in DIRECTORY according to
14642 `speedbar-shown-directories'." 14834 `speedbar-shown-directories'."
@@ -14686,6 +14878,8 @@ otherwise use cached data."
14686 (setq unit-alist (cdr unit-alist)))))) 14878 (setq unit-alist (cdr unit-alist))))))
14687 (vhdl-speedbar-update-current-unit nil t)) 14879 (vhdl-speedbar-update-current-unit nil t))
14688 14880
14881(declare-function speedbar-center-buffer-smartly "speedbar" ())
14882
14689(defun vhdl-speedbar-contract-level () 14883(defun vhdl-speedbar-contract-level ()
14690 "Contract current level in current directory/project." 14884 "Contract current level in current directory/project."
14691 (interactive) 14885 (interactive)
@@ -14726,21 +14920,24 @@ otherwise use cached data."
14726 (setq arch-alist (nth 4 (car ent-alist))) 14920 (setq arch-alist (nth 4 (car ent-alist)))
14727 (setq subunit-alist nil) 14921 (setq subunit-alist nil)
14728 (while arch-alist 14922 (while arch-alist
14729 (setq subunit-alist (cons (caar arch-alist) subunit-alist)) 14923 (push (caar arch-alist) subunit-alist)
14730 (setq arch-alist (cdr arch-alist))) 14924 (setq arch-alist (cdr arch-alist)))
14731 (setq unit-alist (cons (list (caar ent-alist) subunit-alist) unit-alist)) 14925 (push (list (caar ent-alist) subunit-alist) unit-alist)
14732 (setq ent-alist (cdr ent-alist))) 14926 (setq ent-alist (cdr ent-alist)))
14733 (while conf-alist 14927 (while conf-alist
14734 (setq unit-alist (cons (list (caar conf-alist)) unit-alist)) 14928 (push (list (caar conf-alist)) unit-alist)
14735 (setq conf-alist (cdr conf-alist))) 14929 (setq conf-alist (cdr conf-alist)))
14736 (while pack-alist 14930 (while pack-alist
14737 (setq unit-alist (cons (list (caar pack-alist)) unit-alist)) 14931 (push (list (caar pack-alist)) unit-alist)
14738 (setq pack-alist (cdr pack-alist))) 14932 (setq pack-alist (cdr pack-alist)))
14739 (aput 'vhdl-speedbar-shown-unit-alist key unit-alist) 14933 (aput 'vhdl-speedbar-shown-unit-alist key unit-alist)
14740 (vhdl-speedbar-refresh) 14934 (vhdl-speedbar-refresh)
14741 (when (memq 'display vhdl-speedbar-save-cache) 14935 (when (memq 'display vhdl-speedbar-save-cache)
14742 (add-to-list 'vhdl-updated-project-list key)))) 14936 (add-to-list 'vhdl-updated-project-list key))))
14743 14937
14938(declare-function speedbar-change-expand-button-char "speedbar" (char))
14939(declare-function speedbar-delete-subblock "speedbar" (indent))
14940
14744(defun vhdl-speedbar-expand-project (text token indent) 14941(defun vhdl-speedbar-expand-project (text token indent)
14745 "Expand/contract the project under the cursor." 14942 "Expand/contract the project under the cursor."
14746 (cond 14943 (cond
@@ -15069,6 +15266,8 @@ otherwise use cached data."
15069 (setq vhdl-speedbar-last-selected-project vhdl-project))) 15266 (setq vhdl-speedbar-last-selected-project vhdl-project)))
15070 t) 15267 t)
15071 15268
15269(declare-function speedbar-position-cursor-on-line "speedbar" ())
15270
15072(defun vhdl-speedbar-update-current-unit (&optional no-position always) 15271(defun vhdl-speedbar-update-current-unit (&optional no-position always)
15073 "Highlight all design units that are contained in the current file. 15272 "Highlight all design units that are contained in the current file.
15074NO-POSITION non-nil means do not re-position cursor." 15273NO-POSITION non-nil means do not re-position cursor."
@@ -15158,6 +15357,9 @@ NO-POSITION non-nil means do not re-position cursor."
15158 (setq unit-list (cdr unit-list))) 15357 (setq unit-list (cdr unit-list)))
15159 pos) 15358 pos)
15160 15359
15360(declare-function speedbar-make-button "speedbar"
15361 (start end face mouse function &optional token))
15362
15161(defun vhdl-speedbar-make-inst-line (inst-name inst-file-marker 15363(defun vhdl-speedbar-make-inst-line (inst-name inst-file-marker
15162 ent-name ent-file-marker 15364 ent-name ent-file-marker
15163 arch-name arch-file-marker 15365 arch-name arch-file-marker
@@ -15344,6 +15546,8 @@ NO-POSITION non-nil means do not re-position cursor."
15344 'speedbar-directory-face level) 15546 'speedbar-directory-face level)
15345 (setq dirs (cdr dirs))))) 15547 (setq dirs (cdr dirs)))))
15346 15548
15549(declare-function speedbar-reset-scanners "speedbar" ())
15550
15347(defun vhdl-speedbar-dired (text token indent) 15551(defun vhdl-speedbar-dired (text token indent)
15348 "Speedbar click handler for directory expand button in hierarchy mode." 15552 "Speedbar click handler for directory expand button in hierarchy mode."
15349 (cond ((string-match "+" text) ; we have to expand this dir 15553 (cond ((string-match "+" text) ; we have to expand this dir
@@ -15374,7 +15578,7 @@ NO-POSITION non-nil means do not re-position cursor."
15374 (concat (speedbar-line-directory indent) token)))) 15578 (concat (speedbar-line-directory indent) token))))
15375 (while oldl 15579 (while oldl
15376 (if (not (string-match (concat "^" (regexp-quote td)) (car oldl))) 15580 (if (not (string-match (concat "^" (regexp-quote td)) (car oldl)))
15377 (setq newl (cons (car oldl) newl))) 15581 (push (car oldl) newl))
15378 (setq oldl (cdr oldl))) 15582 (setq oldl (cdr oldl)))
15379 (setq speedbar-shown-directories (nreverse newl))) 15583 (setq speedbar-shown-directories (nreverse newl)))
15380 (speedbar-change-expand-button-char ?+) 15584 (speedbar-change-expand-button-char ?+)
@@ -15383,6 +15587,8 @@ NO-POSITION non-nil means do not re-position cursor."
15383 (when (equal (selected-frame) speedbar-frame) 15587 (when (equal (selected-frame) speedbar-frame)
15384 (speedbar-center-buffer-smartly))) 15588 (speedbar-center-buffer-smartly)))
15385 15589
15590(declare-function speedbar-files-item-info "speedbar" ())
15591
15386(defun vhdl-speedbar-item-info () 15592(defun vhdl-speedbar-item-info ()
15387 "Derive and display information about this line item." 15593 "Derive and display information about this line item."
15388 (save-excursion 15594 (save-excursion
@@ -15431,6 +15637,8 @@ NO-POSITION non-nil means do not re-position cursor."
15431 (vhdl-default-directory))))) 15637 (vhdl-default-directory)))))
15432 (t (message ""))))) 15638 (t (message "")))))
15433 15639
15640(declare-function speedbar-line-text "speedbar" (&optional p))
15641
15434(defun vhdl-speedbar-line-text () 15642(defun vhdl-speedbar-line-text ()
15435 "Calls `speedbar-line-text' and removes text properties." 15643 "Calls `speedbar-line-text' and removes text properties."
15436 (let ((string (speedbar-line-text))) 15644 (let ((string (speedbar-line-text)))
@@ -15481,7 +15689,7 @@ NO-POSITION non-nil means do not re-position cursor."
15481 (setq dir (car path-list)) 15689 (setq dir (car path-list))
15482 (string-match "\\(-r \\)?\\(\\([^?*]*[/\\]\\)*\\)" dir) 15690 (string-match "\\(-r \\)?\\(\\([^?*]*[/\\]\\)*\\)" dir)
15483 (if (file-directory-p (match-string 2 dir)) 15691 (if (file-directory-p (match-string 2 dir))
15484 (setq path-list-1 (cons dir path-list-1)) 15692 (push dir path-list-1)
15485 (vhdl-warning-when-idle "No such directory: \"%s\"" (match-string 2 dir))) 15693 (vhdl-warning-when-idle "No such directory: \"%s\"" (match-string 2 dir)))
15486 (setq path-list (cdr path-list))) 15694 (setq path-list (cdr path-list)))
15487 ;; resolve path wildcards 15695 ;; resolve path wildcards
@@ -15503,13 +15711,13 @@ NO-POSITION non-nil means do not re-position cursor."
15503 dir-list) 15711 dir-list)
15504 (while all-list 15712 (while all-list
15505 (when (file-directory-p (car all-list)) 15713 (when (file-directory-p (car all-list))
15506 (setq dir-list (cons (car all-list) dir-list))) 15714 (push (car all-list) dir-list))
15507 (setq all-list (cdr all-list))) 15715 (setq all-list (cdr all-list)))
15508 dir-list)) 15716 dir-list))
15509 (cdr path-list-1)))) 15717 (cdr path-list-1))))
15510 (string-match "\\(-r \\)?\\(.*\\)[/\\].*" dir) 15718 (string-match "\\(-r \\)?\\(.*\\)[/\\].*" dir)
15511 (when (file-directory-p (match-string 2 dir)) 15719 (when (file-directory-p (match-string 2 dir))
15512 (setq path-list-2 (cons dir path-list-2))) 15720 (push dir path-list-2))
15513 (setq path-list-1 (cdr path-list-1)))) 15721 (setq path-list-1 (cdr path-list-1))))
15514 (nreverse path-list-2))) 15722 (nreverse path-list-2)))
15515 15723
@@ -15525,6 +15733,11 @@ NO-POSITION non-nil means do not re-position cursor."
15525 (goto-char dest) 15733 (goto-char dest)
15526 nil))) 15734 nil)))
15527 15735
15736(declare-function speedbar-find-file-in-frame "speedbar" (file))
15737(declare-function speedbar-set-timer "speedbar" (timeout))
15738;; speedbar loads dframe at runtime.
15739(declare-function dframe-maybee-jump-to-attached-frame "dframe" ())
15740
15528(defun vhdl-speedbar-find-file (text token indent) 15741(defun vhdl-speedbar-find-file (text token indent)
15529 "When user clicks on TEXT, load file with name and position in TOKEN. 15742 "When user clicks on TEXT, load file with name and position in TOKEN.
15530Jump to the design unit if `vhdl-speedbar-jump-to-unit' is t or if the file 15743Jump to the design unit if `vhdl-speedbar-jump-to-unit' is t or if the file
@@ -15534,12 +15747,11 @@ is already shown in a buffer."
15534 (let ((buffer (get-file-buffer (car token)))) 15747 (let ((buffer (get-file-buffer (car token))))
15535 (speedbar-find-file-in-frame (car token)) 15748 (speedbar-find-file-in-frame (car token))
15536 (when (or vhdl-speedbar-jump-to-unit buffer) 15749 (when (or vhdl-speedbar-jump-to-unit buffer)
15537 (goto-char (point-min)) 15750 (vhdl-goto-line (cdr token))
15538 (forward-line (1- (cdr token)))
15539 (recenter)) 15751 (recenter))
15540 (vhdl-speedbar-update-current-unit t t) 15752 (vhdl-speedbar-update-current-unit t t)
15541 (speedbar-set-timer dframe-update-speed) 15753 (speedbar-set-timer dframe-update-speed)
15542 (speedbar-maybee-jump-to-attached-frame)))) 15754 (dframe-maybee-jump-to-attached-frame))))
15543 15755
15544(defun vhdl-speedbar-port-copy () 15756(defun vhdl-speedbar-port-copy ()
15545 "Copy the port of the entity/component or subprogram under the cursor." 15757 "Copy the port of the entity/component or subprogram under the cursor."
@@ -15553,8 +15765,7 @@ is already shown in a buffer."
15553 (let ((token (get-text-property 15765 (let ((token (get-text-property
15554 (match-beginning 3) 'speedbar-token))) 15766 (match-beginning 3) 'speedbar-token)))
15555 (vhdl-visit-file (car token) t 15767 (vhdl-visit-file (car token) t
15556 (progn (goto-char (point-min)) 15768 (progn (vhdl-goto-line (cdr token))
15557 (forward-line (1- (cdr token)))
15558 (end-of-line) 15769 (end-of-line)
15559 (if is-entity 15770 (if is-entity
15560 (vhdl-port-copy) 15771 (vhdl-port-copy)
@@ -15600,6 +15811,8 @@ is already shown in a buffer."
15600 (setcar (cddr (cddr ent-entry)) arch-key) ; (nth 4 ent-entry) 15811 (setcar (cddr (cddr ent-entry)) arch-key) ; (nth 4 ent-entry)
15601 (speedbar-refresh)))) 15812 (speedbar-refresh))))
15602 15813
15814(declare-function speedbar-line-file "speedbar" (&optional p))
15815
15603(defun vhdl-speedbar-make-design () 15816(defun vhdl-speedbar-make-design ()
15604 "Make (compile) design unit or directory/project under the cursor." 15817 "Make (compile) design unit or directory/project under the cursor."
15605 (interactive) 15818 (interactive)
@@ -16007,7 +16220,7 @@ component instantiation."
16007 (or (aget generic-alist (match-string 2) t) 16220 (or (aget generic-alist (match-string 2) t)
16008 (error "ERROR: Formal generic \"%s\" mismatch for instance \"%s\"" (match-string 2) inst-name)) 16221 (error "ERROR: Formal generic \"%s\" mismatch for instance \"%s\"" (match-string 2) inst-name))
16009 (cdar generic-alist)))) 16222 (cdar generic-alist))))
16010 (setq constant-alist (cons constant-entry constant-alist)) 16223 (push constant-entry constant-alist)
16011 (setq constant-name (downcase constant-name)) 16224 (setq constant-name (downcase constant-name))
16012 (if (or (member constant-name single-list) 16225 (if (or (member constant-name single-list)
16013 (member constant-name multi-list)) 16226 (member constant-name multi-list))
@@ -16027,7 +16240,7 @@ component instantiation."
16027 (or (aget port-alist (match-string 2) t) 16240 (or (aget port-alist (match-string 2) t)
16028 (error "ERROR: Formal port \"%s\" mismatch for instance \"%s\"" (match-string 2) inst-name)) 16241 (error "ERROR: Formal port \"%s\" mismatch for instance \"%s\"" (match-string 2) inst-name))
16029 (cdar port-alist)))) 16242 (cdar port-alist))))
16030 (setq signal-alist (cons signal-entry signal-alist)) 16243 (push signal-entry signal-alist)
16031 (setq signal-name (downcase signal-name)) 16244 (setq signal-name (downcase signal-name))
16032 (if (equal (upcase (nth 2 signal-entry)) "IN") 16245 (if (equal (upcase (nth 2 signal-entry)) "IN")
16033 ;; input signal 16246 ;; input signal
@@ -16061,8 +16274,8 @@ component instantiation."
16061 (unless (match-string 1) 16274 (unless (match-string 1)
16062 (setq port-alist (cdr port-alist))) 16275 (setq port-alist (cdr port-alist)))
16063 (vhdl-forward-syntactic-ws)) 16276 (vhdl-forward-syntactic-ws))
16064 (setq inst-alist (cons (list inst-name (nreverse constant-alist) 16277 (push (list inst-name (nreverse constant-alist)
16065 (nreverse signal-alist)) inst-alist))) 16278 (nreverse signal-alist)) inst-alist))
16066 ;; prepare signal insertion 16279 ;; prepare signal insertion
16067 (vhdl-goto-marker arch-decl-pos) 16280 (vhdl-goto-marker arch-decl-pos)
16068 (forward-line 1) 16281 (forward-line 1)
@@ -16129,6 +16342,7 @@ component instantiation."
16129 (while constant-alist 16342 (while constant-alist
16130 (setq constant-name (downcase (caar constant-alist)) 16343 (setq constant-name (downcase (caar constant-alist))
16131 constant-entry (car constant-alist)) 16344 constant-entry (car constant-alist))
16345 (unless (string-match "^[0-9]+" constant-name)
16132 (cond ((member constant-name written-list) 16346 (cond ((member constant-name written-list)
16133 nil) 16347 nil)
16134 ((member constant-name multi-list) 16348 ((member constant-name multi-list)
@@ -16145,7 +16359,7 @@ component instantiation."
16145 (setq generic-end-pos 16359 (setq generic-end-pos
16146 (vhdl-compose-insert-generic constant-entry)) 16360 (vhdl-compose-insert-generic constant-entry))
16147 (setq generic-inst-pos (point-marker)) 16361 (setq generic-inst-pos (point-marker))
16148 (add-to-list 'written-list constant-name))) 16362 (add-to-list 'written-list constant-name))))
16149 (setq constant-alist (cdr constant-alist))) 16363 (setq constant-alist (cdr constant-alist)))
16150 (when (/= constant-temp-pos generic-inst-pos) 16364 (when (/= constant-temp-pos generic-inst-pos)
16151 (vhdl-goto-marker (vhdl-max-marker constant-temp-pos generic-pos)) 16365 (vhdl-goto-marker (vhdl-max-marker constant-temp-pos generic-pos))
@@ -16305,8 +16519,7 @@ current project/directory."
16305 ;; insert component declarations 16519 ;; insert component declarations
16306 (while ent-alist 16520 (while ent-alist
16307 (vhdl-visit-file (nth 2 (car ent-alist)) nil 16521 (vhdl-visit-file (nth 2 (car ent-alist)) nil
16308 (progn (goto-char (point-min)) 16522 (progn (vhdl-goto-line (nth 3 (car ent-alist)))
16309 (forward-line (1- (nth 3 (car ent-alist))))
16310 (end-of-line) 16523 (end-of-line)
16311 (vhdl-port-copy))) 16524 (vhdl-port-copy)))
16312 (goto-char component-pos) 16525 (goto-char component-pos)
@@ -16562,12 +16775,12 @@ no project is defined."
16562 (setq sublist (nth 11 (car commands-alist))) 16775 (setq sublist (nth 11 (car commands-alist)))
16563 (unless (or (equal "" (car sublist)) 16776 (unless (or (equal "" (car sublist))
16564 (assoc (car sublist) regexp-alist)) 16777 (assoc (car sublist) regexp-alist))
16565 (setq regexp-alist (cons (list (nth 0 sublist) 16778 (push (list (nth 0 sublist)
16566 (if (= 0 (nth 1 sublist)) 16779 (if (and (featurep 'xemacs) (not (nth 1 sublist)))
16567 (if (featurep 'xemacs) 9 nil) 16780 9
16568 (nth 1 sublist)) 16781 (nth 1 sublist))
16569 (nth 2 sublist) (nth 3 sublist)) 16782 (nth 2 sublist) (nth 3 sublist))
16570 regexp-alist))) 16783 regexp-alist))
16571 (setq commands-alist (cdr commands-alist))) 16784 (setq commands-alist (cdr commands-alist)))
16572 (setq compilation-error-regexp-alist 16785 (setq compilation-error-regexp-alist
16573 (append compilation-error-regexp-alist (nreverse regexp-alist)))) 16786 (append compilation-error-regexp-alist (nreverse regexp-alist))))
@@ -16580,7 +16793,7 @@ no project is defined."
16580 (setq sublist (nth 12 (car commands-alist))) 16793 (setq sublist (nth 12 (car commands-alist)))
16581 (unless (or (equal "" (car sublist)) 16794 (unless (or (equal "" (car sublist))
16582 (assoc (car sublist) regexp-alist)) 16795 (assoc (car sublist) regexp-alist))
16583 (setq regexp-alist (cons sublist regexp-alist))) 16796 (push sublist regexp-alist))
16584 (setq commands-alist (cdr commands-alist))) 16797 (setq commands-alist (cdr commands-alist)))
16585 (setq compilation-file-regexp-alist 16798 (setq compilation-file-regexp-alist
16586 (append compilation-file-regexp-alist (nreverse regexp-alist)))))) 16799 (append compilation-file-regexp-alist (nreverse regexp-alist))))))
@@ -16709,6 +16922,42 @@ specified by a target."
16709 (compile (concat (if (equal command "") "make" command) 16922 (compile (concat (if (equal command "") "make" command)
16710 " " options " " vhdl-make-target)))) 16923 " " options " " vhdl-make-target))))
16711 16924
16925;; Emacs 22+ setup
16926(defvar vhdl-error-regexp-emacs-alist
16927 ;; Get regexps from `vhdl-compiler-alist'
16928 (let ((compiler-alist vhdl-compiler-alist)
16929 (error-regexp-alist '((vhdl-directory "^ *Compiling \"\\(.+\\)\"" 1))))
16930 (while compiler-alist
16931 ;; add error message regexps
16932 (setq error-regexp-alist
16933 (cons (append (list (make-symbol (concat "vhdl-" (subst-char-in-string ? ?- (downcase (nth 0 (car compiler-alist)))))))
16934 (nth 11 (car compiler-alist)))
16935 error-regexp-alist))
16936 ;; add filename regexps
16937 (when (/= 0 (nth 1 (nth 12 (car compiler-alist))))
16938 (setq error-regexp-alist
16939 (cons (append (list (make-symbol (concat "vhdl-" (subst-char-in-string ? ?- (downcase (nth 0 (car compiler-alist)))) "-file")))
16940 (nth 12 (car compiler-alist)))
16941 error-regexp-alist)))
16942 (setq compiler-alist (cdr compiler-alist)))
16943 error-regexp-alist)
16944 "List of regexps for VHDL compilers. For Emacs 22+.")
16945
16946;; Add error regexps using compilation-mode-hook.
16947(defun vhdl-error-regexp-add-emacs ()
16948 "Set up Emacs compile for VHDL."
16949 (interactive)
16950 (when (and (boundp 'compilation-error-regexp-alist-alist)
16951 (not (assoc 'vhdl-modelsim compilation-error-regexp-alist-alist)))
16952 (mapcar
16953 (lambda (item)
16954 (push (car item) compilation-error-regexp-alist)
16955 (push item compilation-error-regexp-alist-alist))
16956 vhdl-error-regexp-emacs-alist)))
16957
16958(when vhdl-emacs-22
16959 (add-hook 'compilation-mode-hook 'vhdl-error-regexp-add-emacs))
16960
16712;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16961;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16713;; Makefile generation 16962;; Makefile generation
16714 16963
@@ -16731,7 +16980,7 @@ specified by a target."
16731 (let (pack-list) 16980 (let (pack-list)
16732 (while lib-alist 16981 (while lib-alist
16733 (when (equal (downcase (caar lib-alist)) (downcase work-library)) 16982 (when (equal (downcase (caar lib-alist)) (downcase work-library))
16734 (setq pack-list (cons (cdar lib-alist) pack-list))) 16983 (push (cdar lib-alist) pack-list))
16735 (setq lib-alist (cdr lib-alist))) 16984 (setq lib-alist (cdr lib-alist)))
16736 pack-list)) 16985 pack-list))
16737 16986
@@ -16783,8 +17032,10 @@ specified by a target."
16783 (setq ent-entry (car ent-alist) 17032 (setq ent-entry (car ent-alist)
16784 ent-key (nth 0 ent-entry)) 17033 ent-key (nth 0 ent-entry))
16785 (when (nth 2 ent-entry) 17034 (when (nth 2 ent-entry)
16786 (setq ent-file-name (file-relative-name 17035 (setq ent-file-name (if vhdl-compile-absolute-path
16787 (nth 2 ent-entry) compile-directory) 17036 (nth 2 ent-entry)
17037 (file-relative-name (nth 2 ent-entry)
17038 compile-directory))
16788 arch-alist (nth 4 ent-entry) 17039 arch-alist (nth 4 ent-entry)
16789 lib-alist (nth 6 ent-entry) 17040 lib-alist (nth 6 ent-entry)
16790 rule (aget rule-alist ent-file-name) 17041 rule (aget rule-alist ent-file-name)
@@ -16794,9 +17045,9 @@ specified by a target."
16794 subcomp-list nil) 17045 subcomp-list nil)
16795 (setq tmp-key (vhdl-replace-string 17046 (setq tmp-key (vhdl-replace-string
16796 ent-regexp (funcall adjust-case ent-key))) 17047 ent-regexp (funcall adjust-case ent-key)))
16797 (setq unit-list (cons (cons ent-key tmp-key) unit-list)) 17048 (push (cons ent-key tmp-key) unit-list)
16798 ;; rule target for this entity 17049 ;; rule target for this entity
16799 (setq target-list (cons ent-key target-list)) 17050 (push ent-key target-list)
16800 ;; rule dependencies for all used packages 17051 ;; rule dependencies for all used packages
16801 (setq pack-list (vhdl-get-packages lib-alist work-library)) 17052 (setq pack-list (vhdl-get-packages lib-alist work-library))
16802 (setq depend-list (append depend-list pack-list)) 17053 (setq depend-list (append depend-list pack-list))
@@ -16808,8 +17059,10 @@ specified by a target."
16808 (setq arch-entry (car arch-alist) 17059 (setq arch-entry (car arch-alist)
16809 arch-key (nth 0 arch-entry) 17060 arch-key (nth 0 arch-entry)
16810 ent-arch-key (concat ent-key "-" arch-key) 17061 ent-arch-key (concat ent-key "-" arch-key)
16811 arch-file-name (file-relative-name (nth 2 arch-entry) 17062 arch-file-name (if vhdl-compile-absolute-path
16812 compile-directory) 17063 (nth 2 arch-entry)
17064 (file-relative-name (nth 2 arch-entry)
17065 compile-directory))
16813 inst-alist (nth 4 arch-entry) 17066 inst-alist (nth 4 arch-entry)
16814 lib-alist (nth 5 arch-entry) 17067 lib-alist (nth 5 arch-entry)
16815 rule (aget rule-alist arch-file-name) 17068 rule (aget rule-alist arch-file-name)
@@ -16820,11 +17073,11 @@ specified by a target."
16820 (funcall adjust-case (concat arch-key " " ent-key)))) 17073 (funcall adjust-case (concat arch-key " " ent-key))))
16821 (setq unit-list 17074 (setq unit-list
16822 (cons (cons ent-arch-key tmp-key) unit-list)) 17075 (cons (cons ent-arch-key tmp-key) unit-list))
16823 (setq second-list (cons ent-arch-key second-list)) 17076 (push ent-arch-key second-list)
16824 ;; rule target for this architecture 17077 ;; rule target for this architecture
16825 (setq target-list (cons ent-arch-key target-list)) 17078 (push ent-arch-key target-list)
16826 ;; rule dependency for corresponding entity 17079 ;; rule dependency for corresponding entity
16827 (setq depend-list (cons ent-key depend-list)) 17080 (push ent-key depend-list)
16828 ;; rule dependencies for contained component instantiations 17081 ;; rule dependencies for contained component instantiations
16829 (while inst-alist 17082 (while inst-alist
16830 (setq inst-entry (car inst-alist)) 17083 (setq inst-entry (car inst-alist))
@@ -16842,9 +17095,8 @@ specified by a target."
16842 ;; add rule 17095 ;; add rule
16843 (aput 'rule-alist arch-file-name (list target-list depend-list)) 17096 (aput 'rule-alist arch-file-name (list target-list depend-list))
16844 (setq arch-alist (cdr arch-alist))) 17097 (setq arch-alist (cdr arch-alist)))
16845 (setq prim-list (cons (list ent-key second-list 17098 (push (list ent-key second-list (append subcomp-list all-pack-list))
16846 (append subcomp-list all-pack-list)) 17099 prim-list))
16847 prim-list)))
16848 (setq ent-alist (cdr ent-alist))) 17100 (setq ent-alist (cdr ent-alist)))
16849 (setq ent-alist tmp-list) 17101 (setq ent-alist tmp-list)
16850 ;; rules for all configurations 17102 ;; rules for all configurations
@@ -16852,8 +17104,10 @@ specified by a target."
16852 (while conf-alist 17104 (while conf-alist
16853 (setq conf-entry (car conf-alist) 17105 (setq conf-entry (car conf-alist)
16854 conf-key (nth 0 conf-entry) 17106 conf-key (nth 0 conf-entry)
16855 conf-file-name (file-relative-name 17107 conf-file-name (if vhdl-compile-absolute-path
16856 (nth 2 conf-entry) compile-directory) 17108 (nth 2 conf-entry)
17109 (file-relative-name (nth 2 conf-entry)
17110 compile-directory))
16857 ent-key (nth 4 conf-entry) 17111 ent-key (nth 4 conf-entry)
16858 arch-key (nth 5 conf-entry) 17112 arch-key (nth 5 conf-entry)
16859 inst-alist (nth 6 conf-entry) 17113 inst-alist (nth 6 conf-entry)
@@ -16864,9 +17118,9 @@ specified by a target."
16864 subcomp-list (list ent-key)) 17118 subcomp-list (list ent-key))
16865 (setq tmp-key (vhdl-replace-string 17119 (setq tmp-key (vhdl-replace-string
16866 conf-regexp (funcall adjust-case conf-key))) 17120 conf-regexp (funcall adjust-case conf-key)))
16867 (setq unit-list (cons (cons conf-key tmp-key) unit-list)) 17121 (push (cons conf-key tmp-key) unit-list)
16868 ;; rule target for this configuration 17122 ;; rule target for this configuration
16869 (setq target-list (cons conf-key target-list)) 17123 (push conf-key target-list)
16870 ;; rule dependency for corresponding entity and architecture 17124 ;; rule dependency for corresponding entity and architecture
16871 (setq depend-list 17125 (setq depend-list
16872 (cons ent-key (cons (concat ent-key "-" arch-key) depend-list))) 17126 (cons ent-key (cons (concat ent-key "-" arch-key) depend-list)))
@@ -16884,16 +17138,14 @@ specified by a target."
16884 (setq depend-list (cons inst-ent-key depend-list) 17138 (setq depend-list (cons inst-ent-key depend-list)
16885 subcomp-list (cons inst-ent-key subcomp-list))) 17139 subcomp-list (cons inst-ent-key subcomp-list)))
16886; (when comp-arch-key 17140; (when comp-arch-key
16887; (setq depend-list (cons (concat comp-ent-key "-" comp-arch-key) 17141; (push (concat comp-ent-key "-" comp-arch-key) depend-list))
16888; depend-list)))
16889 (when inst-conf-key 17142 (when inst-conf-key
16890 (setq depend-list (cons inst-conf-key depend-list) 17143 (setq depend-list (cons inst-conf-key depend-list)
16891 subcomp-list (cons inst-conf-key subcomp-list)))) 17144 subcomp-list (cons inst-conf-key subcomp-list))))
16892 (setq inst-alist (cdr inst-alist))) 17145 (setq inst-alist (cdr inst-alist)))
16893 ;; add rule 17146 ;; add rule
16894 (aput 'rule-alist conf-file-name (list target-list depend-list)) 17147 (aput 'rule-alist conf-file-name (list target-list depend-list))
16895 (setq prim-list (cons (list conf-key nil (append subcomp-list pack-list)) 17148 (push (list conf-key nil (append subcomp-list pack-list)) prim-list)
16896 prim-list))
16897 (setq conf-alist (cdr conf-alist))) 17149 (setq conf-alist (cdr conf-alist)))
16898 (setq conf-alist tmp-list) 17150 (setq conf-alist tmp-list)
16899 ;; rules for all packages 17151 ;; rules for all packages
@@ -16903,16 +17155,18 @@ specified by a target."
16903 pack-key (nth 0 pack-entry) 17155 pack-key (nth 0 pack-entry)
16904 pack-body-key nil) 17156 pack-body-key nil)
16905 (when (nth 2 pack-entry) 17157 (when (nth 2 pack-entry)
16906 (setq pack-file-name (file-relative-name (nth 2 pack-entry) 17158 (setq pack-file-name (if vhdl-compile-absolute-path
16907 compile-directory) 17159 (nth 2 pack-entry)
17160 (file-relative-name (nth 2 pack-entry)
17161 compile-directory))
16908 lib-alist (nth 6 pack-entry) lib-body-alist (nth 10 pack-entry) 17162 lib-alist (nth 6 pack-entry) lib-body-alist (nth 10 pack-entry)
16909 rule (aget rule-alist pack-file-name) 17163 rule (aget rule-alist pack-file-name)
16910 target-list (nth 0 rule) depend-list (nth 1 rule)) 17164 target-list (nth 0 rule) depend-list (nth 1 rule))
16911 (setq tmp-key (vhdl-replace-string 17165 (setq tmp-key (vhdl-replace-string
16912 pack-regexp (funcall adjust-case pack-key))) 17166 pack-regexp (funcall adjust-case pack-key)))
16913 (setq unit-list (cons (cons pack-key tmp-key) unit-list)) 17167 (push (cons pack-key tmp-key) unit-list)
16914 ;; rule target for this package 17168 ;; rule target for this package
16915 (setq target-list (cons pack-key target-list)) 17169 (push pack-key target-list)
16916 ;; rule dependencies for all used packages 17170 ;; rule dependencies for all used packages
16917 (setq pack-list (vhdl-get-packages lib-alist work-library)) 17171 (setq pack-list (vhdl-get-packages lib-alist work-library))
16918 (setq depend-list (append depend-list pack-list)) 17172 (setq depend-list (append depend-list pack-list))
@@ -16922,8 +17176,10 @@ specified by a target."
16922 ;; rules for this package's body 17176 ;; rules for this package's body
16923 (when (nth 7 pack-entry) 17177 (when (nth 7 pack-entry)
16924 (setq pack-body-key (concat pack-key "-body") 17178 (setq pack-body-key (concat pack-key "-body")
16925 pack-body-file-name (file-relative-name (nth 7 pack-entry) 17179 pack-body-file-name (if vhdl-compile-absolute-path
16926 compile-directory) 17180 (nth 7 pack-entry)
17181 (file-relative-name (nth 7 pack-entry)
17182 compile-directory))
16927 rule (aget rule-alist pack-body-file-name) 17183 rule (aget rule-alist pack-body-file-name)
16928 target-list (nth 0 rule) 17184 target-list (nth 0 rule)
16929 depend-list (nth 1 rule)) 17185 depend-list (nth 1 rule))
@@ -16932,9 +17188,9 @@ specified by a target."
16932 (setq unit-list 17188 (setq unit-list
16933 (cons (cons pack-body-key tmp-key) unit-list)) 17189 (cons (cons pack-body-key tmp-key) unit-list))
16934 ;; rule target for this package's body 17190 ;; rule target for this package's body
16935 (setq target-list (cons pack-body-key target-list)) 17191 (push pack-body-key target-list)
16936 ;; rule dependency for corresponding package declaration 17192 ;; rule dependency for corresponding package declaration
16937 (setq depend-list (cons pack-key depend-list)) 17193 (push pack-key depend-list)
16938 ;; rule dependencies for all used packages 17194 ;; rule dependencies for all used packages
16939 (setq pack-list (vhdl-get-packages lib-body-alist work-library)) 17195 (setq pack-list (vhdl-get-packages lib-body-alist work-library))
16940 (setq depend-list (append depend-list pack-list)) 17196 (setq depend-list (append depend-list pack-list))
@@ -17057,16 +17313,16 @@ specified by a target."
17057 (unless (equal unit-key unit-name) 17313 (unless (equal unit-key unit-name)
17058 (insert " \\\n" unit-name)) 17314 (insert " \\\n" unit-name))
17059 (insert " :" 17315 (insert " :"
17060 " \\\n\t\t" (nth 2 vhdl-makefile-default-targets) 17316 " \\\n\t\t" (nth 2 vhdl-makefile-default-targets))
17061 " \\\n\t\t$(UNIT-" work-library "-" unit-key ")")
17062 (while second-list
17063 (insert " \\\n\t\t$(UNIT-" work-library "-" (car second-list) ")")
17064 (setq second-list (cdr second-list)))
17065 (while subcomp-list 17317 (while subcomp-list
17066 (when (and (assoc (car subcomp-list) unit-list) 17318 (when (and (assoc (car subcomp-list) unit-list)
17067 (not (equal unit-key (car subcomp-list)))) 17319 (not (equal unit-key (car subcomp-list))))
17068 (insert " \\\n\t\t" (car subcomp-list))) 17320 (insert " \\\n\t\t" (car subcomp-list)))
17069 (setq subcomp-list (cdr subcomp-list))) 17321 (setq subcomp-list (cdr subcomp-list)))
17322 (insert " \\\n\t\t$(UNIT-" work-library "-" unit-key ")")
17323 (while second-list
17324 (insert " \\\n\t\t$(UNIT-" work-library "-" (car second-list) ")")
17325 (setq second-list (cdr second-list)))
17070 (insert "\n") 17326 (insert "\n")
17071 (setq prim-list (cdr prim-list))) 17327 (setq prim-list (cdr prim-list)))
17072 ;; insert rule for each library unit file 17328 ;; insert rule for each library unit file
@@ -17205,6 +17461,7 @@ specified by a target."
17205 'vhdl-include-direction-comments 17461 'vhdl-include-direction-comments
17206 'vhdl-include-type-comments 17462 'vhdl-include-type-comments
17207 'vhdl-include-group-comments 17463 'vhdl-include-group-comments
17464 'vhdl-actual-generic-name
17208 'vhdl-actual-port-name 17465 'vhdl-actual-port-name
17209 'vhdl-instance-name 17466 'vhdl-instance-name
17210 'vhdl-testbench-entity-name 17467 'vhdl-testbench-entity-name
@@ -17287,13 +17544,21 @@ specified by a target."
17287 17544
17288(defconst vhdl-doc-release-notes nil 17545(defconst vhdl-doc-release-notes nil
17289 "\ 17546 "\
17290Release Notes for VHDL Mode 3.33 17547Release Notes for VHDL Mode 3.34
17291================================ 17548================================
17292 17549
17293 - New Features 17550- Added support for GNU Emacs 22/23/24:
17294 - User Options 17551 - Compilation error parsing fixed for new `compile.el' package.
17552
17553- Port translation: Derive actual generic name from formal generic name.
17554
17555- New user options:
17556 `vhdl-actual-generic-name': Specify how actual generic names are obtained.
17295 17557
17296 17558
17559Release Notes for VHDL Mode 3.33
17560================================
17561
17297New Features 17562New Features
17298------------ 17563------------
17299 17564
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el
index edfe368479c..c8044f407fc 100644
--- a/lisp/progmodes/which-func.el
+++ b/lisp/progmodes/which-func.el
@@ -343,6 +343,10 @@ If no function name is found, return nil."
343 343
344;;; Integration with other packages 344;;; Integration with other packages
345 345
346(defvar ediff-window-A)
347(defvar ediff-window-B)
348(defvar ediff-window-C)
349
346(defun which-func-update-ediff-windows () 350(defun which-func-update-ediff-windows ()
347 "Update Which-Function mode display for Ediff windows. 351 "Update Which-Function mode display for Ediff windows.
348This function is meant to be called from `ediff-select-hook'." 352This function is meant to be called from `ediff-select-hook'."
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index 2ad44b4b1c8..37c3cd37a6c 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -35,7 +35,6 @@
35;;;; Internal Variables 35;;;; Internal Variables
36 36
37(defvar xscheme-previous-mode) 37(defvar xscheme-previous-mode)
38(defvar xscheme-previous-process-state)
39(defvar xscheme-last-input-end) 38(defvar xscheme-last-input-end)
40 39
41(defvar xscheme-process-command-line nil 40(defvar xscheme-process-command-line nil
@@ -388,8 +387,6 @@ with no args, if that value is non-nil.
388 (if (not preserve) 387 (if (not preserve)
389 (let ((previous-mode major-mode)) 388 (let ((previous-mode major-mode))
390 (kill-all-local-variables) 389 (kill-all-local-variables)
391 (make-local-variable 'xscheme-process-name)
392 (make-local-variable 'xscheme-previous-process-state)
393 (make-local-variable 'xscheme-runlight-string) 390 (make-local-variable 'xscheme-runlight-string)
394 (make-local-variable 'xscheme-runlight) 391 (make-local-variable 'xscheme-runlight)
395 (set (make-local-variable 'xscheme-previous-mode) previous-mode) 392 (set (make-local-variable 'xscheme-previous-mode) previous-mode)
@@ -397,35 +394,29 @@ with no args, if that value is non-nil.
397 (set (make-local-variable 'xscheme-buffer-name) (buffer-name buffer)) 394 (set (make-local-variable 'xscheme-buffer-name) (buffer-name buffer))
398 (set (make-local-variable 'xscheme-last-input-end) (make-marker)) 395 (set (make-local-variable 'xscheme-last-input-end) (make-marker))
399 (let ((process (get-buffer-process buffer))) 396 (let ((process (get-buffer-process buffer)))
400 (if process 397 (when process
401 (progn 398 (setq-local xscheme-process-name (process-name process))
402 (setq xscheme-process-name (process-name process)) 399 ;; FIXME: Use add-function!
403 (setq xscheme-previous-process-state 400 (xscheme-process-filter-initialize t)
404 (cons (process-filter process) 401 (xscheme-mode-line-initialize xscheme-buffer-name)
405 (process-sentinel process))) 402 (add-function :override (process-sentinel process)
406 (xscheme-process-filter-initialize t) 403 #'xscheme-process-sentinel)
407 (xscheme-mode-line-initialize xscheme-buffer-name) 404 (add-function :override (process-filter process)
408 (set-process-sentinel process 'xscheme-process-sentinel) 405 #'xscheme-process-filter))))))
409 (set-process-filter process 'xscheme-process-filter))
410 (setq xscheme-previous-process-state (cons nil nil)))))))
411 (scheme-interaction-mode-initialize) 406 (scheme-interaction-mode-initialize)
412 (scheme-mode-variables) 407 (scheme-mode-variables)
413 (run-mode-hooks 'scheme-mode-hook 'scheme-interaction-mode-hook)) 408 (run-mode-hooks 'scheme-mode-hook 'scheme-interaction-mode-hook))
414 409
415(defun exit-scheme-interaction-mode () 410(defun exit-scheme-interaction-mode ()
416 "Take buffer out of scheme interaction mode" 411 "Take buffer out of scheme interaction mode."
417 (interactive) 412 (interactive)
418 (if (not (derived-mode-p 'scheme-interaction-mode)) 413 (if (not (derived-mode-p 'scheme-interaction-mode))
419 (error "Buffer not in scheme interaction mode")) 414 (error "Buffer not in scheme interaction mode"))
420 (let ((previous-state xscheme-previous-process-state)) 415 (funcall xscheme-previous-mode)
421 (funcall xscheme-previous-mode) 416 (let ((process (get-buffer-process (current-buffer))))
422 (let ((process (get-buffer-process (current-buffer)))) 417 (when process
423 (if process 418 (remove-function (process-sentinel process) #'xscheme-process-sentinel)
424 (progn 419 (remove-function (process-filter process) #'xscheme-process-filter))))
425 (if (eq (process-filter process) 'xscheme-process-filter)
426 (set-process-filter process (car previous-state)))
427 (if (eq (process-sentinel process) 'xscheme-process-sentinel)
428 (set-process-sentinel process (cdr previous-state))))))))
429 420
430(defvar scheme-interaction-mode-commands-alist nil) 421(defvar scheme-interaction-mode-commands-alist nil)
431(defvar scheme-interaction-mode-map nil) 422(defvar scheme-interaction-mode-map nil)