aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes
diff options
context:
space:
mode:
authorKenichi Handa2010-09-16 11:11:13 +0900
committerKenichi Handa2010-09-16 11:11:13 +0900
commit38d50547c2a8195bed0aaeafbbc4c0f277d4e416 (patch)
tree388416c9f2cc4746d0d2d9e525a50a6c2f00f3d4 /lisp/progmodes
parentfa3f60399014127e711f3f438004950cba0bddb9 (diff)
parent6139f995addcb8fce63deb30c7ed0e6f2b618b02 (diff)
downloademacs-38d50547c2a8195bed0aaeafbbc4c0f277d4e416.tar.gz
emacs-38d50547c2a8195bed0aaeafbbc4c0f277d4e416.zip
merge trunk
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/ada-mode.el632
-rw-r--r--lisp/progmodes/antlr-mode.el2
-rw-r--r--lisp/progmodes/autoconf.el7
-rw-r--r--lisp/progmodes/cc-engine.el112
-rw-r--r--lisp/progmodes/cfengine.el20
-rw-r--r--lisp/progmodes/compile.el33
-rw-r--r--lisp/progmodes/cperl-mode.el8
-rw-r--r--lisp/progmodes/fortran.el19
-rw-r--r--lisp/progmodes/gud.el24
-rw-r--r--lisp/progmodes/js.el76
-rw-r--r--lisp/progmodes/make-mode.el37
-rw-r--r--lisp/progmodes/mixal-mode.el23
-rw-r--r--lisp/progmodes/octave-mod.el49
-rw-r--r--lisp/progmodes/perl-mode.el334
-rw-r--r--lisp/progmodes/python.el96
-rw-r--r--lisp/progmodes/ruby-mode.el390
-rw-r--r--lisp/progmodes/sh-script.el104
-rw-r--r--lisp/progmodes/simula.el28
-rw-r--r--lisp/progmodes/sql.el701
-rw-r--r--lisp/progmodes/tcl.el13
-rw-r--r--lisp/progmodes/vhdl-mode.el18
21 files changed, 1536 insertions, 1190 deletions
diff --git a/lisp/progmodes/ada-mode.el b/lisp/progmodes/ada-mode.el
index 227f202fef0..4bbe1e43f85 100644
--- a/lisp/progmodes/ada-mode.el
+++ b/lisp/progmodes/ada-mode.el
@@ -834,10 +834,7 @@ the 4 file locations can be clicked on and jumped to."
834;; 834;;
835;; On Emacs, this is done through the `syntax-table' text property. The 835;; On Emacs, this is done through the `syntax-table' text property. The
836;; corresponding action is applied automatically each time the buffer 836;; corresponding action is applied automatically each time the buffer
837;; changes. If `font-lock-mode' is enabled (the default) the action is 837;; changes via syntax-propertize-function.
838;; set up by `font-lock-syntactic-keywords'. Otherwise, we do it
839;; manually in `ada-after-change-function'. The proper method is
840;; installed by `ada-handle-syntax-table-properties'.
841;; 838;;
842;; on XEmacs, the `syntax-table' property does not exist and we have to use a 839;; on XEmacs, the `syntax-table' property does not exist and we have to use a
843;; slow advice to `parse-partial-sexp' to do the same thing. 840;; slow advice to `parse-partial-sexp' to do the same thing.
@@ -937,6 +934,12 @@ declares it as a word constituent."
937 (insert (caddar change)) 934 (insert (caddar change))
938 (setq change (cdr change))))))) 935 (setq change (cdr change)))))))
939 936
937(unless (eval-when-compile (fboundp 'syntax-propertize-via-font-lock))
938 ;; Before `syntax-propertize', we had to use font-lock to apply syntax-table
939 ;; properties, and in some cases we even had to do it manually (in
940 ;; `ada-after-change-function'). `ada-handle-syntax-table-properties'
941 ;; decides which method to use.
942
940(defun ada-set-syntax-table-properties () 943(defun ada-set-syntax-table-properties ()
941 "Assign `syntax-table' properties in accessible part of buffer. 944 "Assign `syntax-table' properties in accessible part of buffer.
942In particular, character constants are said to be strings, #...# 945In particular, character constants are said to be strings, #...#
@@ -991,6 +994,8 @@ OLD-LEN indicates what the length of the replaced text was."
991 ;; Take care of `syntax-table' properties manually. 994 ;; Take care of `syntax-table' properties manually.
992 (ada-initialize-syntax-table-properties))) 995 (ada-initialize-syntax-table-properties)))
993 996
997) ;;(not (fboundp 'syntax-propertize))
998
994;;------------------------------------------------------------------ 999;;------------------------------------------------------------------
995;; Testing the grammatical context 1000;; Testing the grammatical context
996;;------------------------------------------------------------------ 1001;;------------------------------------------------------------------
@@ -1118,7 +1123,8 @@ the file name."
1118 1123
1119;;;###autoload 1124;;;###autoload
1120(defun ada-mode () 1125(defun ada-mode ()
1121 "Ada mode is the major mode for editing Ada code." 1126 "Ada mode is the major mode for editing Ada code.
1127\\{ada-mode-map}"
1122 1128
1123 (interactive) 1129 (interactive)
1124 (kill-all-local-variables) 1130 (kill-all-local-variables)
@@ -1161,9 +1167,9 @@ the file name."
1161 (set (make-local-variable 'comment-padding) 0) 1167 (set (make-local-variable 'comment-padding) 0)
1162 (set (make-local-variable 'parse-sexp-lookup-properties) t)) 1168 (set (make-local-variable 'parse-sexp-lookup-properties) t))
1163 1169
1164 (set 'case-fold-search t) 1170 (setq case-fold-search t)
1165 (if (boundp 'imenu-case-fold-search) 1171 (if (boundp 'imenu-case-fold-search)
1166 (set 'imenu-case-fold-search t)) 1172 (setq imenu-case-fold-search t))
1167 1173
1168 (set (make-local-variable 'fill-paragraph-function) 1174 (set (make-local-variable 'fill-paragraph-function)
1169 'ada-fill-comment-paragraph) 1175 'ada-fill-comment-paragraph)
@@ -1186,8 +1192,13 @@ the file name."
1186 '(ada-font-lock-keywords 1192 '(ada-font-lock-keywords
1187 nil t 1193 nil t
1188 ((?\_ . "w") (?# . ".")) 1194 ((?\_ . "w") (?# . "."))
1189 beginning-of-line 1195 beginning-of-line))
1190 (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords))) 1196
1197 (if (eval-when-compile (fboundp 'syntax-propertize-via-font-lock))
1198 (set (make-local-variable 'syntax-propertize-function)
1199 (syntax-propertize-via-font-lock ada-font-lock-syntactic-keywords))
1200 (set (make-local-variable 'font-lock-syntactic-keywords)
1201 ada-font-lock-syntactic-keywords))
1191 1202
1192 ;; Set up support for find-file.el. 1203 ;; Set up support for find-file.el.
1193 (set (make-local-variable 'ff-other-file-alist) 1204 (set (make-local-variable 'ff-other-file-alist)
@@ -1322,22 +1333,24 @@ the file name."
1322 1333
1323 ;; To be run after the hook, in case the user modified 1334 ;; To be run after the hook, in case the user modified
1324 ;; ada-fill-comment-prefix 1335 ;; ada-fill-comment-prefix
1325 (make-local-variable 'comment-start) 1336 ;; FIXME: if the user modified ada-fill-comment-prefix in his .emacs
1326 (if ada-fill-comment-prefix 1337 ;; then it was already available before running the hook, and if he
1327 (set 'comment-start ada-fill-comment-prefix) 1338 ;; modifies it in the hook, he might as well modify comment-start instead.
1328 (set 'comment-start "-- ")) 1339 (set (make-local-variable 'comment-start) (or ada-fill-comment-prefix "-- "))
1329 1340
1330 ;; Run this after the hook to give the users a chance to activate 1341 ;; Run this after the hook to give the users a chance to activate
1331 ;; font-lock-mode 1342 ;; font-lock-mode
1332 1343
1333 (unless (featurep 'xemacs) 1344 (unless (or (eval-when-compile (fboundp 'syntax-propertize-via-font-lock))
1345 (featurep 'xemacs))
1334 (ada-initialize-syntax-table-properties) 1346 (ada-initialize-syntax-table-properties)
1335 (add-hook 'font-lock-mode-hook 'ada-handle-syntax-table-properties nil t)) 1347 (add-hook 'font-lock-mode-hook 'ada-handle-syntax-table-properties nil t))
1336 1348
1337 ;; the following has to be done after running the ada-mode-hook 1349 ;; the following has to be done after running the ada-mode-hook
1338 ;; because users might want to set the values of these variable 1350 ;; because users might want to set the values of these variable
1339 ;; inside the hook 1351 ;; inside the hook
1340 1352 ;; FIXME: it might even be set later on via file-local vars, no?
1353 ;; so maybe ada-keywords should be set lazily.
1341 (cond ((eq ada-language-version 'ada83) 1354 (cond ((eq ada-language-version 'ada83)
1342 (setq ada-keywords ada-83-keywords)) 1355 (setq ada-keywords ada-83-keywords))
1343 ((eq ada-language-version 'ada95) 1356 ((eq ada-language-version 'ada95)
@@ -1397,25 +1410,21 @@ If WORD is not given, then the current word in the buffer is used instead.
1397The new word is added to the first file in `ada-case-exception-file'. 1410The new word is added to the first file in `ada-case-exception-file'.
1398The standard casing rules will no longer apply to this word." 1411The standard casing rules will no longer apply to this word."
1399 (interactive) 1412 (interactive)
1400 (let ((previous-syntax-table (syntax-table)) 1413 (let ((file-name
1401 file-name 1414 (cond ((stringp ada-case-exception-file)
1402 ) 1415 ada-case-exception-file)
1403 1416 ((listp ada-case-exception-file)
1404 (cond ((stringp ada-case-exception-file) 1417 (car ada-case-exception-file))
1405 (setq file-name ada-case-exception-file)) 1418 (t
1406 ((listp ada-case-exception-file) 1419 (error (concat "No exception file specified. "
1407 (setq file-name (car ada-case-exception-file))) 1420 "See variable ada-case-exception-file"))))))
1408 (t
1409 (error (concat "No exception file specified. "
1410 "See variable ada-case-exception-file"))))
1411 1421
1412 (set-syntax-table ada-mode-symbol-syntax-table)
1413 (unless word 1422 (unless word
1414 (save-excursion 1423 (with-syntax-table ada-mode-symbol-syntax-table
1415 (skip-syntax-backward "w") 1424 (save-excursion
1416 (setq word (buffer-substring-no-properties 1425 (skip-syntax-backward "w")
1417 (point) (save-excursion (forward-word 1) (point)))))) 1426 (setq word (buffer-substring-no-properties
1418 (set-syntax-table previous-syntax-table) 1427 (point) (save-excursion (forward-word 1) (point)))))))
1419 1428
1420 ;; Reread the exceptions file, in case it was modified by some other, 1429 ;; Reread the exceptions file, in case it was modified by some other,
1421 (ada-case-read-exceptions-from-file file-name) 1430 (ada-case-read-exceptions-from-file file-name)
@@ -1425,11 +1434,9 @@ The standard casing rules will no longer apply to this word."
1425 (if (and (not (equal ada-case-exception '())) 1434 (if (and (not (equal ada-case-exception '()))
1426 (assoc-string word ada-case-exception t)) 1435 (assoc-string word ada-case-exception t))
1427 (setcar (assoc-string word ada-case-exception t) word) 1436 (setcar (assoc-string word ada-case-exception t) word)
1428 (add-to-list 'ada-case-exception (cons word t)) 1437 (add-to-list 'ada-case-exception (cons word t)))
1429 )
1430 1438
1431 (ada-save-exceptions-to-file file-name) 1439 (ada-save-exceptions-to-file file-name)))
1432 ))
1433 1440
1434(defun ada-create-case-exception-substring (&optional word) 1441(defun ada-create-case-exception-substring (&optional word)
1435 "Define the substring WORD as an exception for the casing system. 1442 "Define the substring WORD as an exception for the casing system.
@@ -1464,7 +1471,7 @@ word itself has a special casing."
1464 (modify-syntax-entry ?_ "." (syntax-table)) 1471 (modify-syntax-entry ?_ "." (syntax-table))
1465 (save-excursion 1472 (save-excursion
1466 (skip-syntax-backward "w") 1473 (skip-syntax-backward "w")
1467 (set 'word (buffer-substring-no-properties 1474 (setq word (buffer-substring-no-properties
1468 (point) 1475 (point)
1469 (save-excursion (forward-word 1) (point)))))) 1476 (save-excursion (forward-word 1) (point))))))
1470 (modify-syntax-entry ?_ (make-string 1 underscore-syntax) 1477 (modify-syntax-entry ?_ (make-string 1 underscore-syntax)
@@ -1633,37 +1640,30 @@ ARG is the prefix the user entered with \\[universal-argument]."
1633 (interactive "P") 1640 (interactive "P")
1634 1641
1635 (if ada-auto-case 1642 (if ada-auto-case
1636 (let ((lastk last-command-event) 1643 (let ((lastk last-command-event))
1637 (previous-syntax-table (syntax-table))) 1644
1638 1645 (with-syntax-table ada-mode-symbol-syntax-table
1639 (unwind-protect 1646 (cond ((or (eq lastk ?\n)
1640 (progn 1647 (eq lastk ?\r))
1641 (set-syntax-table ada-mode-symbol-syntax-table) 1648 ;; horrible kludge
1642 (cond ((or (eq lastk ?\n) 1649 (insert " ")
1643 (eq lastk ?\r)) 1650 (ada-adjust-case)
1644 ;; horrible kludge 1651 ;; horrible dekludge
1645 (insert " ") 1652 (delete-char -1)
1646 (ada-adjust-case) 1653 ;; some special keys and their bindings
1647 ;; horrible dekludge 1654 (cond
1648 (delete-char -1) 1655 ((eq lastk ?\n)
1649 ;; some special keys and their bindings 1656 (funcall ada-lfd-binding))
1650 (cond 1657 ((eq lastk ?\r)
1651 ((eq lastk ?\n) 1658 (funcall ada-ret-binding))))
1652 (funcall ada-lfd-binding)) 1659 ((eq lastk ?\C-i) (ada-tab))
1653 ((eq lastk ?\r) 1660 ;; Else just insert the character
1654 (funcall ada-ret-binding)))) 1661 ((self-insert-command (prefix-numeric-value arg))))
1655 ((eq lastk ?\C-i) (ada-tab)) 1662 ;; if there is a keyword in front of the underscore
1656 ;; Else just insert the character 1663 ;; then it should be part of an identifier (MH)
1657 ((self-insert-command (prefix-numeric-value arg)))) 1664 (if (eq lastk ?_)
1658 ;; if there is a keyword in front of the underscore 1665 (ada-adjust-case t)
1659 ;; then it should be part of an identifier (MH) 1666 (ada-adjust-case))))
1660 (if (eq lastk ?_)
1661 (ada-adjust-case t)
1662 (ada-adjust-case))
1663 )
1664 ;; Restore the syntax table
1665 (set-syntax-table previous-syntax-table))
1666 )
1667 1667
1668 ;; Else, no auto-casing 1668 ;; Else, no auto-casing
1669 (cond 1669 (cond
@@ -1672,10 +1672,10 @@ ARG is the prefix the user entered with \\[universal-argument]."
1672 ((eq last-command-event ?\r) 1672 ((eq last-command-event ?\r)
1673 (funcall ada-ret-binding)) 1673 (funcall ada-ret-binding))
1674 (t 1674 (t
1675 (self-insert-command (prefix-numeric-value arg)))) 1675 (self-insert-command (prefix-numeric-value arg))))))
1676 ))
1677 1676
1678(defun ada-activate-keys-for-case () 1677(defun ada-activate-keys-for-case ()
1678 ;; FIXME: Use post-self-insert-hook instead of changing key bindings.
1679 "Modify the key bindings for all the keys that should readjust the casing." 1679 "Modify the key bindings for all the keys that should readjust the casing."
1680 (interactive) 1680 (interactive)
1681 ;; Save original key-bindings to allow swapping ret/lfd 1681 ;; Save original key-bindings to allow swapping ret/lfd
@@ -1735,44 +1735,41 @@ Attention: This function might take very long for big regions!"
1735 (let ((begin nil) 1735 (let ((begin nil)
1736 (end nil) 1736 (end nil)
1737 (keywordp nil) 1737 (keywordp nil)
1738 (attribp nil) 1738 (attribp nil))
1739 (previous-syntax-table (syntax-table)))
1740 (message "Adjusting case ...") 1739 (message "Adjusting case ...")
1741 (unwind-protect 1740 (with-syntax-table ada-mode-symbol-syntax-table
1742 (save-excursion 1741 (save-excursion
1743 (set-syntax-table ada-mode-symbol-syntax-table) 1742 (goto-char to)
1744 (goto-char to) 1743 ;;
1745 ;; 1744 ;; loop: look for all identifiers, keywords, and attributes
1746 ;; loop: look for all identifiers, keywords, and attributes 1745 ;;
1747 ;; 1746 (while (re-search-backward "\\<\\(\\sw+\\)\\>" from t)
1748 (while (re-search-backward "\\<\\(\\sw+\\)\\>" from t) 1747 (setq end (match-end 1))
1749 (setq end (match-end 1)) 1748 (setq attribp
1750 (setq attribp 1749 (and (> (point) from)
1751 (and (> (point) from) 1750 (save-excursion
1752 (save-excursion 1751 (forward-char -1)
1753 (forward-char -1) 1752 (setq attribp (looking-at "'.[^']")))))
1754 (setq attribp (looking-at "'.[^']"))))) 1753 (or
1755 (or 1754 ;; do nothing if it is a string or comment
1756 ;; do nothing if it is a string or comment 1755 (ada-in-string-or-comment-p)
1757 (ada-in-string-or-comment-p) 1756 (progn
1758 (progn 1757 ;;
1759 ;; 1758 ;; get the identifier or keyword or attribute
1760 ;; get the identifier or keyword or attribute 1759 ;;
1761 ;; 1760 (setq begin (point))
1762 (setq begin (point)) 1761 (setq keywordp (looking-at ada-keywords))
1763 (setq keywordp (looking-at ada-keywords)) 1762 (goto-char end)
1764 (goto-char end) 1763 ;;
1765 ;; 1764 ;; casing according to user-option
1766 ;; casing according to user-option 1765 ;;
1767 ;; 1766 (if attribp
1768 (if attribp 1767 (funcall ada-case-attribute -1)
1769 (funcall ada-case-attribute -1) 1768 (if keywordp
1770 (if keywordp 1769 (funcall ada-case-keyword -1)
1771 (funcall ada-case-keyword -1) 1770 (ada-adjust-case-identifier)))
1772 (ada-adjust-case-identifier))) 1771 (goto-char begin))))
1773 (goto-char begin)))) 1772 (message "Adjusting case ... Done")))))
1774 (message "Adjusting case ... Done"))
1775 (set-syntax-table previous-syntax-table))))
1776 1773
1777(defun ada-adjust-case-buffer () 1774(defun ada-adjust-case-buffer ()
1778 "Adjust the case of all words in the whole buffer. 1775 "Adjust the case of all words in the whole buffer.
@@ -1803,46 +1800,39 @@ ATTENTION: This function might take very long for big buffers!"
1803 (let ((begin nil) 1800 (let ((begin nil)
1804 (end nil) 1801 (end nil)
1805 (delend nil) 1802 (delend nil)
1806 (paramlist nil) 1803 (paramlist nil))
1807 (previous-syntax-table (syntax-table))) 1804 (with-syntax-table ada-mode-symbol-syntax-table
1808 (unwind-protect
1809 (progn
1810 (set-syntax-table ada-mode-symbol-syntax-table)
1811 1805
1812 ;; check if really inside parameter list 1806 ;; check if really inside parameter list
1813 (or (ada-in-paramlist-p) 1807 (or (ada-in-paramlist-p)
1814 (error "Not in parameter list")) 1808 (error "Not in parameter list"))
1815 1809
1816 ;; find start of current parameter-list 1810 ;; find start of current parameter-list
1817 (ada-search-ignore-string-comment 1811 (ada-search-ignore-string-comment
1818 (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil) 1812 (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil)
1819 (down-list 1) 1813 (down-list 1)
1820 (backward-char 1) 1814 (backward-char 1)
1821 (setq begin (point)) 1815 (setq begin (point))
1822 1816
1823 ;; find end of parameter-list 1817 ;; find end of parameter-list
1824 (forward-sexp 1) 1818 (forward-sexp 1)
1825 (setq delend (point)) 1819 (setq delend (point))
1826 (delete-char -1) 1820 (delete-char -1)
1827 (insert "\n") 1821 (insert "\n")
1828
1829 ;; find end of last parameter-declaration
1830 (forward-comment -1000)
1831 (setq end (point))
1832 1822
1833 ;; build a list of all elements of the parameter-list 1823 ;; find end of last parameter-declaration
1834 (setq paramlist (ada-scan-paramlist (1+ begin) end)) 1824 (forward-comment -1000)
1825 (setq end (point))
1835 1826
1836 ;; delete the original parameter-list 1827 ;; build a list of all elements of the parameter-list
1837 (delete-region begin delend) 1828 (setq paramlist (ada-scan-paramlist (1+ begin) end))
1838 1829
1839 ;; insert the new parameter-list 1830 ;; delete the original parameter-list
1840 (goto-char begin) 1831 (delete-region begin delend)
1841 (ada-insert-paramlist paramlist))
1842 1832
1843 ;; restore syntax-table 1833 ;; insert the new parameter-list
1844 (set-syntax-table previous-syntax-table) 1834 (goto-char begin)
1845 ))) 1835 (ada-insert-paramlist paramlist))))
1846 1836
1847(defun ada-scan-paramlist (begin end) 1837(defun ada-scan-paramlist (begin end)
1848 "Scan the parameter list found in between BEGIN and END. 1838 "Scan the parameter list found in between BEGIN and END.
@@ -2186,14 +2176,12 @@ Return the new position of point or nil if not found."
2186Return the calculation that was done, including the reference point 2176Return the calculation that was done, including the reference point
2187and the offset." 2177and the offset."
2188 (interactive) 2178 (interactive)
2189 (let ((previous-syntax-table (syntax-table)) 2179 (let ((orgpoint (point-marker))
2190 (orgpoint (point-marker))
2191 cur-indent tmp-indent 2180 cur-indent tmp-indent
2192 prev-indent) 2181 prev-indent)
2193 2182
2194 (unwind-protect 2183 (unwind-protect
2195 (progn 2184 (with-syntax-table ada-mode-symbol-syntax-table
2196 (set-syntax-table ada-mode-symbol-syntax-table)
2197 2185
2198 ;; This need to be done here so that the advice is not always 2186 ;; This need to be done here so that the advice is not always
2199 ;; activated (this might interact badly with other modes) 2187 ;; activated (this might interact badly with other modes)
@@ -2203,14 +2191,14 @@ and the offset."
2203 (save-excursion 2191 (save-excursion
2204 (setq cur-indent 2192 (setq cur-indent
2205 2193
2206 ;; Not First line in the buffer ? 2194 ;; Not First line in the buffer ?
2207 (if (save-excursion (zerop (forward-line -1))) 2195 (if (save-excursion (zerop (forward-line -1)))
2208 (progn 2196 (progn
2209 (back-to-indentation) 2197 (back-to-indentation)
2210 (ada-get-current-indent)) 2198 (ada-get-current-indent))
2211 2199
2212 ;; first line in the buffer 2200 ;; first line in the buffer
2213 (list (point-min) 0)))) 2201 (list (point-min) 0))))
2214 2202
2215 ;; Evaluate the list to get the column to indent to 2203 ;; Evaluate the list to get the column to indent to
2216 ;; prev-indent contains the column to indent to 2204 ;; prev-indent contains the column to indent to
@@ -2242,14 +2230,10 @@ and the offset."
2242 (if (< (current-column) (current-indentation)) 2230 (if (< (current-column) (current-indentation))
2243 (back-to-indentation))) 2231 (back-to-indentation)))
2244 2232
2245 ;; restore syntax-table
2246 (set-syntax-table previous-syntax-table)
2247 (if (featurep 'xemacs) 2233 (if (featurep 'xemacs)
2248 (ad-deactivate 'parse-partial-sexp)) 2234 (ad-deactivate 'parse-partial-sexp)))
2249 )
2250 2235
2251 cur-indent 2236 cur-indent))
2252 ))
2253 2237
2254(defun ada-get-current-indent () 2238(defun ada-get-current-indent ()
2255 "Return the indentation to use for the current line." 2239 "Return the indentation to use for the current line."
@@ -2512,11 +2496,11 @@ and the offset."
2512 (if (looking-at "renames") 2496 (if (looking-at "renames")
2513 (let (pos) 2497 (let (pos)
2514 (save-excursion 2498 (save-excursion
2515 (set 'pos (ada-search-ignore-string-comment ";\\|return\\>" t))) 2499 (setq pos (ada-search-ignore-string-comment ";\\|return\\>" t)))
2516 (if (and pos 2500 (if (and pos
2517 (= (downcase (char-after (car pos))) ?r)) 2501 (= (downcase (char-after (car pos))) ?r))
2518 (goto-char (car pos))) 2502 (goto-char (car pos)))
2519 (set 'var 'ada-indent-renames))) 2503 (setq var 'ada-indent-renames)))
2520 2504
2521 (forward-comment -1000) 2505 (forward-comment -1000)
2522 (if (= (char-before) ?\)) 2506 (if (= (char-before) ?\))
@@ -2533,7 +2517,7 @@ and the offset."
2533 (looking-at "\\(function\\|procedure\\)\\>")) 2517 (looking-at "\\(function\\|procedure\\)\\>"))
2534 (progn 2518 (progn
2535 (backward-word 1) 2519 (backward-word 1)
2536 (set 'num-back 2) 2520 (setq num-back 2)
2537 (looking-at "\\(function\\|procedure\\)\\>"))))) 2521 (looking-at "\\(function\\|procedure\\)\\>")))))
2538 2522
2539 ;; The indentation depends of the value of ada-indent-return 2523 ;; The indentation depends of the value of ada-indent-return
@@ -4046,8 +4030,7 @@ Point is moved at the beginning of the SEARCH-RE."
4046 (let (found 4030 (let (found
4047 begin 4031 begin
4048 end 4032 end
4049 parse-result 4033 parse-result)
4050 (previous-syntax-table (syntax-table)))
4051 4034
4052 ;; FIXME: need to pass BACKWARD to search-func! 4035 ;; FIXME: need to pass BACKWARD to search-func!
4053 (unless search-func 4036 (unless search-func
@@ -4057,67 +4040,65 @@ Point is moved at the beginning of the SEARCH-RE."
4057 ;; search until found or end-of-buffer 4040 ;; search until found or end-of-buffer
4058 ;; We have to test that we do not look further than limit 4041 ;; We have to test that we do not look further than limit
4059 ;; 4042 ;;
4060 (set-syntax-table ada-mode-symbol-syntax-table) 4043 (with-syntax-table ada-mode-symbol-syntax-table
4061 (while (and (not found) 4044 (while (and (not found)
4062 (or (not limit) 4045 (or (not limit)
4063 (or (and backward (<= limit (point))) 4046 (or (and backward (<= limit (point)))
4064 (>= limit (point)))) 4047 (>= limit (point))))
4065 (funcall search-func search-re limit 1)) 4048 (funcall search-func search-re limit 1))
4066 (setq begin (match-beginning 0)) 4049 (setq begin (match-beginning 0))
4067 (setq end (match-end 0)) 4050 (setq end (match-end 0))
4068 4051
4069 (setq parse-result (parse-partial-sexp 4052 (setq parse-result (parse-partial-sexp
4070 (save-excursion (beginning-of-line) (point)) 4053 (save-excursion (beginning-of-line) (point))
4071 (point))) 4054 (point)))
4072 4055
4073 (cond 4056 (cond
4074 ;; 4057 ;;
4075 ;; If inside a string, skip it (and the following comments) 4058 ;; If inside a string, skip it (and the following comments)
4076 ;; 4059 ;;
4077 ((ada-in-string-p parse-result) 4060 ((ada-in-string-p parse-result)
4078 (if (featurep 'xemacs) 4061 (if (featurep 'xemacs)
4079 (search-backward "\"" nil t) 4062 (search-backward "\"" nil t)
4080 (goto-char (nth 8 parse-result))) 4063 (goto-char (nth 8 parse-result)))
4081 (unless backward (forward-sexp 1))) 4064 (unless backward (forward-sexp 1)))
4082 ;; 4065 ;;
4083 ;; If inside a comment, skip it (and the following comments) 4066 ;; If inside a comment, skip it (and the following comments)
4084 ;; There is a special code for comments at the end of the file 4067 ;; There is a special code for comments at the end of the file
4085 ;; 4068 ;;
4086 ((ada-in-comment-p parse-result) 4069 ((ada-in-comment-p parse-result)
4087 (if (featurep 'xemacs) 4070 (if (featurep 'xemacs)
4088 (progn 4071 (progn
4089 (forward-line 1) 4072 (forward-line 1)
4090 (beginning-of-line) 4073 (beginning-of-line)
4091 (forward-comment -1)) 4074 (forward-comment -1))
4092 (goto-char (nth 8 parse-result))) 4075 (goto-char (nth 8 parse-result)))
4093 (unless backward 4076 (unless backward
4094 ;; at the end of the file, it is not possible to skip a comment 4077 ;; at the end of the file, it is not possible to skip a comment
4095 ;; so we just go at the end of the line 4078 ;; so we just go at the end of the line
4096 (if (forward-comment 1) 4079 (if (forward-comment 1)
4097 (progn 4080 (progn
4098 (forward-comment 1000) 4081 (forward-comment 1000)
4099 (beginning-of-line)) 4082 (beginning-of-line))
4100 (end-of-line)))) 4083 (end-of-line))))
4101 ;; 4084 ;;
4102 ;; directly in front of a comment => skip it, if searching forward 4085 ;; directly in front of a comment => skip it, if searching forward
4103 ;; 4086 ;;
4104 ((and (= (char-after begin) ?-) (= (char-after (1+ begin)) ?-)) 4087 ((and (= (char-after begin) ?-) (= (char-after (1+ begin)) ?-))
4105 (unless backward (progn (forward-char -1) (forward-comment 1000)))) 4088 (unless backward (progn (forward-char -1) (forward-comment 1000))))
4106 4089
4107 ;; 4090 ;;
4108 ;; found a parameter-list but should ignore it => skip it 4091 ;; found a parameter-list but should ignore it => skip it
4109 ;; 4092 ;;
4110 ((and (not paramlists) (ada-in-paramlist-p)) 4093 ((and (not paramlists) (ada-in-paramlist-p))
4111 (if backward 4094 (if backward
4112 (search-backward "(" nil t) 4095 (search-backward "(" nil t)
4113 (search-forward ")" nil t))) 4096 (search-forward ")" nil t)))
4114 ;; 4097 ;;
4115 ;; found what we were looking for 4098 ;; found what we were looking for
4116 ;; 4099 ;;
4117 (t 4100 (t
4118 (setq found t)))) ; end of loop 4101 (setq found t))))) ; end of loop
4119
4120 (set-syntax-table previous-syntax-table)
4121 4102
4122 (if found 4103 (if found
4123 (cons begin end) 4104 (cons begin end)
@@ -4398,122 +4379,109 @@ of the region. Otherwise, operate only on the current line."
4398(defun ada-move-to-start () 4379(defun ada-move-to-start ()
4399 "Move point to the matching start of the current Ada structure." 4380 "Move point to the matching start of the current Ada structure."
4400 (interactive) 4381 (interactive)
4401 (let ((pos (point)) 4382 (let ((pos (point)))
4402 (previous-syntax-table (syntax-table))) 4383 (with-syntax-table ada-mode-symbol-syntax-table
4403 (unwind-protect
4404 (progn
4405 (set-syntax-table ada-mode-symbol-syntax-table)
4406 4384
4407 (save-excursion 4385 (save-excursion
4408 ;; 4386 ;;
4409 ;; do nothing if in string or comment or not on 'end ...;' 4387 ;; do nothing if in string or comment or not on 'end ...;'
4410 ;; or if an error occurs during processing 4388 ;; or if an error occurs during processing
4411 ;; 4389 ;;
4412 (or 4390 (or
4413 (ada-in-string-or-comment-p) 4391 (ada-in-string-or-comment-p)
4414 (and (progn 4392 (and (progn
4415 (or (looking-at "[ \t]*\\<end\\>") 4393 (or (looking-at "[ \t]*\\<end\\>")
4416 (backward-word 1)) 4394 (backward-word 1))
4417 (or (looking-at "[ \t]*\\<end\\>") 4395 (or (looking-at "[ \t]*\\<end\\>")
4418 (backward-word 1)) 4396 (backward-word 1))
4419 (or (looking-at "[ \t]*\\<end\\>") 4397 (or (looking-at "[ \t]*\\<end\\>")
4420 (error "Not on end ...;"))) 4398 (error "Not on end ...;")))
4421 (ada-goto-matching-start 1) 4399 (ada-goto-matching-start 1)
4422 (setq pos (point)) 4400 (setq pos (point))
4423 4401
4424 ;; 4402 ;;
4425 ;; on 'begin' => go on, according to user option 4403 ;; on 'begin' => go on, according to user option
4426 ;; 4404 ;;
4427 ada-move-to-declaration 4405 ada-move-to-declaration
4428 (looking-at "\\<begin\\>") 4406 (looking-at "\\<begin\\>")
4429 (ada-goto-decl-start) 4407 (ada-goto-decl-start)
4430 (setq pos (point)))) 4408 (setq pos (point))))
4431 4409
4432 ) ; end of save-excursion 4410 ) ; end of save-excursion
4433 4411
4434 ;; now really move to the found position 4412 ;; now really move to the found position
4435 (goto-char pos)) 4413 (goto-char pos))))
4436
4437 ;; restore syntax-table
4438 (set-syntax-table previous-syntax-table))))
4439 4414
4440(defun ada-move-to-end () 4415(defun ada-move-to-end ()
4441 "Move point to the end of the block around point. 4416 "Move point to the end of the block around point.
4442Moves to 'begin' if in a declarative part." 4417Moves to 'begin' if in a declarative part."
4443 (interactive) 4418 (interactive)
4444 (let ((pos (point)) 4419 (let ((pos (point))
4445 decl-start 4420 decl-start)
4446 (previous-syntax-table (syntax-table))) 4421 (with-syntax-table ada-mode-symbol-syntax-table
4447 (unwind-protect
4448 (progn
4449 (set-syntax-table ada-mode-symbol-syntax-table)
4450
4451 (save-excursion
4452
4453 (cond
4454 ;; Go to the beginning of the current word, and check if we are
4455 ;; directly on 'begin'
4456 ((save-excursion
4457 (skip-syntax-backward "w")
4458 (looking-at "\\<begin\\>"))
4459 (ada-goto-matching-end 1)
4460 )
4461
4462 ;; on first line of subprogram body
4463 ;; Do nothing for specs or generic instantion, since these are
4464 ;; handled as the general case (find the enclosing block)
4465 ;; We also need to make sure that we ignore nested subprograms
4466 ((save-excursion
4467 (and (skip-syntax-backward "w")
4468 (looking-at "\\<function\\>\\|\\<procedure\\>" )
4469 (ada-search-ignore-string-comment "is\\|;")
4470 (not (= (char-before) ?\;))
4471 ))
4472 (skip-syntax-backward "w")
4473 (ada-goto-matching-end 0 t))
4474
4475 ;; on first line of task declaration
4476 ((save-excursion
4477 (and (ada-goto-stmt-start)
4478 (looking-at "\\<task\\>" )
4479 (forward-word 1)
4480 (ada-goto-next-non-ws)
4481 (looking-at "\\<body\\>")))
4482 (ada-search-ignore-string-comment "begin" nil nil nil
4483 'word-search-forward))
4484 ;; accept block start
4485 ((save-excursion
4486 (and (ada-goto-stmt-start)
4487 (looking-at "\\<accept\\>" )))
4488 (ada-goto-matching-end 0))
4489 ;; package start
4490 ((save-excursion
4491 (setq decl-start (and (ada-goto-decl-start t) (point)))
4492 (and decl-start (looking-at "\\<package\\>")))
4493 (ada-goto-matching-end 1))
4494
4495 ;; On a "declare" keyword
4496 ((save-excursion
4497 (skip-syntax-backward "w")
4498 (looking-at "\\<declare\\>"))
4499 (ada-goto-matching-end 0 t))
4500
4501 ;; inside a 'begin' ... 'end' block
4502 (decl-start
4503 (goto-char decl-start)
4504 (ada-goto-matching-end 0 t))
4505
4506 ;; (hopefully ;-) everything else
4507 (t
4508 (ada-goto-matching-end 1)))
4509 (setq pos (point))
4510 )
4511 4422
4512 ;; now really move to the position found 4423 (save-excursion
4513 (goto-char pos))
4514 4424
4515 ;; restore syntax-table 4425 (cond
4516 (set-syntax-table previous-syntax-table)))) 4426 ;; Go to the beginning of the current word, and check if we are
4427 ;; directly on 'begin'
4428 ((save-excursion
4429 (skip-syntax-backward "w")
4430 (looking-at "\\<begin\\>"))
4431 (ada-goto-matching-end 1))
4432
4433 ;; on first line of subprogram body
4434 ;; Do nothing for specs or generic instantion, since these are
4435 ;; handled as the general case (find the enclosing block)
4436 ;; We also need to make sure that we ignore nested subprograms
4437 ((save-excursion
4438 (and (skip-syntax-backward "w")
4439 (looking-at "\\<function\\>\\|\\<procedure\\>" )
4440 (ada-search-ignore-string-comment "is\\|;")
4441 (not (= (char-before) ?\;))
4442 ))
4443 (skip-syntax-backward "w")
4444 (ada-goto-matching-end 0 t))
4445
4446 ;; on first line of task declaration
4447 ((save-excursion
4448 (and (ada-goto-stmt-start)
4449 (looking-at "\\<task\\>" )
4450 (forward-word 1)
4451 (ada-goto-next-non-ws)
4452 (looking-at "\\<body\\>")))
4453 (ada-search-ignore-string-comment "begin" nil nil nil
4454 'word-search-forward))
4455 ;; accept block start
4456 ((save-excursion
4457 (and (ada-goto-stmt-start)
4458 (looking-at "\\<accept\\>" )))
4459 (ada-goto-matching-end 0))
4460 ;; package start
4461 ((save-excursion
4462 (setq decl-start (and (ada-goto-decl-start t) (point)))
4463 (and decl-start (looking-at "\\<package\\>")))
4464 (ada-goto-matching-end 1))
4465
4466 ;; On a "declare" keyword
4467 ((save-excursion
4468 (skip-syntax-backward "w")
4469 (looking-at "\\<declare\\>"))
4470 (ada-goto-matching-end 0 t))
4471
4472 ;; inside a 'begin' ... 'end' block
4473 (decl-start
4474 (goto-char decl-start)
4475 (ada-goto-matching-end 0 t))
4476
4477 ;; (hopefully ;-) everything else
4478 (t
4479 (ada-goto-matching-end 1)))
4480 (setq pos (point))
4481 )
4482
4483 ;; now really move to the position found
4484 (goto-char pos))))
4517 4485
4518(defun ada-next-procedure () 4486(defun ada-next-procedure ()
4519 "Move point to next procedure." 4487 "Move point to next procedure."
@@ -4818,7 +4786,7 @@ Moves to 'begin' if in a declarative part."
4818 (if (featurep 'xemacs) 4786 (if (featurep 'xemacs)
4819 (progn 4787 (progn
4820 (define-key ada-mode-map [menu-bar] ada-mode-menu) 4788 (define-key ada-mode-map [menu-bar] ada-mode-menu)
4821 (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu)))))) 4789 (setq mode-popup-menu (cons "Ada mode" ada-mode-menu))))))
4822 4790
4823 4791
4824;; ------------------------------------------------------- 4792;; -------------------------------------------------------
@@ -5040,7 +5008,7 @@ or the spec otherwise."
5040 (ada-find-src-file-in-dir 5008 (ada-find-src-file-in-dir
5041 (file-name-nondirectory (concat name (car suffixes)))))) 5009 (file-name-nondirectory (concat name (car suffixes))))))
5042 (if other 5010 (if other
5043 (set 'is-spec other))) 5011 (setq is-spec other)))
5044 5012
5045 ;; Else search in the current directory 5013 ;; Else search in the current directory
5046 (if (file-exists-p (concat name (car suffixes))) 5014 (if (file-exists-p (concat name (car suffixes)))
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index 9b24ac7a1f4..742bcf726eb 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -951,7 +951,7 @@ group. The string matched by the first group is highlighted with
951 (3 antlr-keyword-face) 951 (3 antlr-keyword-face)
952 (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser")) 952 (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser"))
953 antlr-keyword-face 953 antlr-keyword-face
954 type-face))) 954 font-lock-type-face)))
955 (,(lambda (limit) 955 (,(lambda (limit)
956 (antlr-re-search-forward 956 (antlr-re-search-forward
957 "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>" 957 "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>"
diff --git a/lisp/progmodes/autoconf.el b/lisp/progmodes/autoconf.el
index a56623f22da..004bb3de78d 100644
--- a/lisp/progmodes/autoconf.el
+++ b/lisp/progmodes/autoconf.el
@@ -43,9 +43,6 @@
43(defvar autoconf-mode-hook nil 43(defvar autoconf-mode-hook nil
44 "Hook run by `autoconf-mode'.") 44 "Hook run by `autoconf-mode'.")
45 45
46(defconst autoconf-font-lock-syntactic-keywords
47 '(("\\<dnl\\>" 0 '(11))))
48
49(defconst autoconf-definition-regexp 46(defconst autoconf-definition-regexp
50 "AC_\\(SUBST\\|DEFINE\\(_UNQUOTED\\)?\\)(\\[*\\(\\sw+\\)\\]*") 47 "AC_\\(SUBST\\|DEFINE\\(_UNQUOTED\\)?\\)(\\[*\\(\\sw+\\)\\]*")
51 48
@@ -94,8 +91,8 @@ searching backwards at another AC_... command."
94 "^[ \t]*A[CM]_\\(\\sw\\|\\s_\\)+") 91 "^[ \t]*A[CM]_\\(\\sw\\|\\s_\\)+")
95 (set (make-local-variable 'comment-start) "dnl ") 92 (set (make-local-variable 'comment-start) "dnl ")
96 (set (make-local-variable 'comment-start-skip) "\\(?:\\<dnl\\|#\\) +") 93 (set (make-local-variable 'comment-start-skip) "\\(?:\\<dnl\\|#\\) +")
97 (set (make-local-variable 'font-lock-syntactic-keywords) 94 (set (make-local-variable 'syntax-propertize-function)
98 autoconf-font-lock-syntactic-keywords) 95 (syntax-propertize-rules ("\\<dnl\\>" (0 "<"))))
99 (set (make-local-variable 'font-lock-defaults) 96 (set (make-local-variable 'font-lock-defaults)
100 `(autoconf-font-lock-keywords nil nil (("_" . "w")))) 97 `(autoconf-font-lock-keywords nil nil (("_" . "w"))))
101 (set (make-local-variable 'imenu-generic-expression) 98 (set (make-local-variable 'imenu-generic-expression)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index e389007065a..2a24bf1ce90 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -5449,49 +5449,47 @@ comment at the start of cc-engine.el for more info."
5449 (forward-char) 5449 (forward-char)
5450 5450
5451 (unless (looking-at c-<-op-cont-regexp) 5451 (unless (looking-at c-<-op-cont-regexp)
5452 (while (and 5452 (while (and
5453 (progn 5453 (progn
5454 (c-forward-syntactic-ws) 5454 (c-forward-syntactic-ws)
5455 (let ((orig-record-found-types c-record-found-types)) 5455 (let ((orig-record-found-types c-record-found-types))
5456 (when (or (and c-record-type-identifiers all-types) 5456 (when (or (and c-record-type-identifiers all-types)
5457 (c-major-mode-is 'java-mode)) 5457 (c-major-mode-is 'java-mode))
5458 ;; All encountered identifiers are types, so set the 5458 ;; All encountered identifiers are types, so set the
5459 ;; promote flag and parse the type. 5459 ;; promote flag and parse the type.
5460 (progn 5460 (progn
5461 (c-forward-syntactic-ws) 5461 (c-forward-syntactic-ws)
5462 (if (looking-at "\\?") 5462 (if (looking-at "\\?")
5463 (forward-char) 5463 (forward-char)
5464 (when (looking-at c-identifier-start) 5464 (when (looking-at c-identifier-start)
5465 (let ((c-promote-possible-types t) 5465 (let ((c-promote-possible-types t)
5466 (c-record-found-types t)) 5466 (c-record-found-types t))
5467 (c-forward-type)))) 5467 (c-forward-type))))
5468 5468
5469 (c-forward-syntactic-ws) 5469 (c-forward-syntactic-ws)
5470 5470
5471 (when (or (looking-at "extends") 5471 (when (or (looking-at "extends")
5472 (looking-at "super")) 5472 (looking-at "super"))
5473 (forward-word) 5473 (forward-word)
5474 (c-forward-syntactic-ws) 5474 (c-forward-syntactic-ws)
5475 (let ((c-promote-possible-types t) 5475 (let ((c-promote-possible-types t)
5476 (c-record-found-types t)) 5476 (c-record-found-types t))
5477 (c-forward-type) 5477 (c-forward-type)
5478 (c-forward-syntactic-ws)))))) 5478 (c-forward-syntactic-ws))))))
5479
5480 (setq pos (point))
5481
5482 (or
5483 ;; Note: These regexps exploit the match order in \| so
5484 ;; that "<>" is matched by "<" rather than "[^>:-]>".
5485 (c-syntactic-re-search-forward
5486 ;; Stop on ',', '|', '&', '+' and '-' to catch
5487 ;; common binary operators that could be between
5488 ;; two comparison expressions "a<b" and "c>d".
5489 "[<;{},|+&-]\\|[>)]"
5490 nil t t)
5491 t))
5492 5479
5493 (cond 5480 (setq pos (point))
5494 ((eq (char-before) ?>) 5481
5482 ;; Note: These regexps exploit the match order in \| so
5483 ;; that "<>" is matched by "<" rather than "[^>:-]>".
5484 (c-syntactic-re-search-forward
5485 ;; Stop on ',', '|', '&', '+' and '-' to catch
5486 ;; common binary operators that could be between
5487 ;; two comparison expressions "a<b" and "c>d".
5488 "[<;{},|+&-]\\|[>)]"
5489 nil t t))
5490
5491 (cond
5492 ((eq (char-before) ?>)
5495 ;; Either an operator starting with '>' or the end of 5493 ;; Either an operator starting with '>' or the end of
5496 ;; the angle bracket arglist. 5494 ;; the angle bracket arglist.
5497 5495
@@ -5532,14 +5530,14 @@ comment at the start of cc-engine.el for more info."
5532 (when (or (setq keyword-match 5530 (when (or (setq keyword-match
5533 (looking-at c-opt-<>-sexp-key)) 5531 (looking-at c-opt-<>-sexp-key))
5534 (not (looking-at c-keywords-regexp))) 5532 (not (looking-at c-keywords-regexp)))
5535 (setq id-start (point)))) 5533 (setq id-start (point))))
5536 5534
5537 (setq subres 5535 (setq subres
5538 (let ((c-promote-possible-types t) 5536 (let ((c-promote-possible-types t)
5539 (c-record-found-types t)) 5537 (c-record-found-types t))
5540 (c-forward-<>-arglist-recur 5538 (c-forward-<>-arglist-recur
5541 (and keyword-match 5539 (and keyword-match
5542 (c-keyword-member 5540 (c-keyword-member
5543 (c-keyword-sym (match-string 1)) 5541 (c-keyword-sym (match-string 1))
5544 'c-<>-type-kwds))))) 5542 'c-<>-type-kwds)))))
5545 ))) 5543 )))
@@ -5560,16 +5558,16 @@ comment at the start of cc-engine.el for more info."
5560 (c-forward-syntactic-ws) 5558 (c-forward-syntactic-ws)
5561 (looking-at c-opt-identifier-concat-key))) 5559 (looking-at c-opt-identifier-concat-key)))
5562 (c-record-ref-id (cons id-start id-end)) 5560 (c-record-ref-id (cons id-start id-end))
5563 (c-record-type-id (cons id-start id-end)))))) 5561 (c-record-type-id (cons id-start id-end))))))
5564 t) 5562 t)
5565 5563
5566 ((and (not c-restricted-<>-arglists) 5564 ((and (not c-restricted-<>-arglists)
5567 (or (and (eq (char-before) ?&) 5565 (or (and (eq (char-before) ?&)
5568 (not (eq (char-after) ?&))) 5566 (not (eq (char-after) ?&)))
5569 (eq (char-before) ?,))) 5567 (eq (char-before) ?,)))
5570 ;; Just another argument. Record the position. The 5568 ;; Just another argument. Record the position. The
5571 ;; type check stuff that made us stop at it is at 5569 ;; type check stuff that made us stop at it is at
5572 ;; the top of the loop. 5570 ;; the top of the loop.
5573 (setq arg-start-pos (cons (point) arg-start-pos))) 5571 (setq arg-start-pos (cons (point) arg-start-pos)))
5574 5572
5575 (t 5573 (t
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 86a6be40cc5..e074e92fbe5 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -83,12 +83,6 @@ This includes those for cfservd as well as cfagent."))
83 ;; File, acl &c in group: { token ... } 83 ;; File, acl &c in group: { token ... }
84 ("{[ \t]*\\([^ \t\n]+\\)" 1 font-lock-constant-face))) 84 ("{[ \t]*\\([^ \t\n]+\\)" 1 font-lock-constant-face)))
85 85
86(defconst cfengine-font-lock-syntactic-keywords
87 ;; In the main syntax-table, backslash is marked as a punctuation, because
88 ;; of its use in DOS-style directory separators. Here we try to recognize
89 ;; the cases where backslash is used as an escape inside strings.
90 '(("\\(\\(?:\\\\\\)+\\)\"" 1 "\\")))
91
92(defvar cfengine-imenu-expression 86(defvar cfengine-imenu-expression
93 `((nil ,(concat "^[ \t]*" (eval-when-compile 87 `((nil ,(concat "^[ \t]*" (eval-when-compile
94 (regexp-opt cfengine-actions t)) 88 (regexp-opt cfengine-actions t))
@@ -237,13 +231,15 @@ to the action header."
237 (set (make-local-variable 'fill-paragraph-function) 231 (set (make-local-variable 'fill-paragraph-function)
238 #'cfengine-fill-paragraph) 232 #'cfengine-fill-paragraph)
239 (define-abbrev-table 'cfengine-mode-abbrev-table cfengine-mode-abbrevs) 233 (define-abbrev-table 'cfengine-mode-abbrev-table cfengine-mode-abbrevs)
240 ;; Fixme: Use `font-lock-syntactic-keywords' to set the args of
241 ;; functions in evaluated classes to string syntax, and then obey
242 ;; syntax properties.
243 (setq font-lock-defaults 234 (setq font-lock-defaults
244 '(cfengine-font-lock-keywords nil nil nil beginning-of-line 235 '(cfengine-font-lock-keywords nil nil nil beginning-of-line))
245 (font-lock-syntactic-keywords 236 ;; Fixme: set the args of functions in evaluated classes to string
246 . cfengine-font-lock-syntactic-keywords))) 237 ;; syntax, and then obey syntax properties.
238 (set (make-local-variable 'syntax-propertize-function)
239 ;; In the main syntax-table, \ is marked as a punctuation, because
240 ;; of its use in DOS-style directory separators. Here we try to
241 ;; recognize the cases where \ is used as an escape inside strings.
242 (syntax-propertize-rules ("\\(\\(?:\\\\\\)+\\)\"" (1 "\\"))))
247 (setq imenu-generic-expression cfengine-imenu-expression) 243 (setq imenu-generic-expression cfengine-imenu-expression)
248 (set (make-local-variable 'beginning-of-defun-function) 244 (set (make-local-variable 'beginning-of-defun-function)
249 #'cfengine-beginning-of-defun) 245 #'cfengine-beginning-of-defun)
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 598733cb5d7..7f0732ecffc 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -164,7 +164,7 @@ and a string describing how the process finished.")
164 164
165(defvar compilation-num-errors-found) 165(defvar compilation-num-errors-found)
166 166
167(defconst compilation-error-regexp-alist-alist 167(defvar compilation-error-regexp-alist-alist
168 '((absoft 168 '((absoft
169 "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\ 169 "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
170of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) 170of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
@@ -263,9 +263,11 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
263 ;; The core of the regexp is the one with *?. It says that a file name 263 ;; The core of the regexp is the one with *?. It says that a file name
264 ;; can be composed of any non-newline char, but it also rules out some 264 ;; can be composed of any non-newline char, but it also rules out some
265 ;; valid but unlikely cases, such as a trailing space or a space 265 ;; valid but unlikely cases, such as a trailing space or a space
266 ;; followed by a -. 266 ;; followed by a -, or a colon followed by a space.
267
268 ;; The "in \\|from " exception was added to handle messages from Ruby.
267 "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\ 269 "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\
268\\([0-9]*[^0-9\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\ 270\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\): ?\
269\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\ 271\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
270\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\ 272\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
271\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\ 273\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
@@ -766,12 +768,27 @@ The value can be either 2 -- skip anything less than error, 1 --
766skip anything less than warning or 0 -- don't skip any messages. 768skip anything less than warning or 0 -- don't skip any messages.
767Note that all messages not positively identified as warning or 769Note that all messages not positively identified as warning or
768info, are considered errors." 770info, are considered errors."
769 :type '(choice (const :tag "Warnings and info" 2) 771 :type '(choice (const :tag "Skip warnings and info" 2)
770 (const :tag "Info" 1) 772 (const :tag "Skip info" 1)
771 (const :tag "None" 0)) 773 (const :tag "No skip" 0))
772 :group 'compilation 774 :group 'compilation
773 :version "22.1") 775 :version "22.1")
774 776
777(defun compilation-set-skip-threshold (level)
778 "Switch the `compilation-skip-threshold' level."
779 (interactive
780 (list
781 (mod (if current-prefix-arg
782 (prefix-numeric-value current-prefix-arg)
783 (1+ compilation-skip-threshold))
784 3)))
785 (setq compilation-skip-threshold level)
786 (message "Skipping %s"
787 (case compilation-skip-threshold
788 (0 "Nothing")
789 (1 "Info messages")
790 (2 "Warnings and info"))))
791
775(defcustom compilation-skip-visited nil 792(defcustom compilation-skip-visited nil
776 "Compilation motion commands skip visited messages if this is t. 793 "Compilation motion commands skip visited messages if this is t.
777Visited messages are ones for which the file, line and column have been jumped 794Visited messages are ones for which the file, line and column have been jumped
@@ -1212,7 +1229,7 @@ Returns the compilation buffer created."
1212 (let* ((name-of-mode 1229 (let* ((name-of-mode
1213 (if (eq mode t) 1230 (if (eq mode t)
1214 "compilation" 1231 "compilation"
1215 (replace-regexp-in-string "-mode$" "" (symbol-name mode)))) 1232 (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
1216 (thisdir default-directory) 1233 (thisdir default-directory)
1217 outwin outbuf) 1234 outwin outbuf)
1218 (with-current-buffer 1235 (with-current-buffer
@@ -2377,7 +2394,7 @@ The file-structure looks like this:
2377(defun compilation-forget-errors () 2394(defun compilation-forget-errors ()
2378 ;; In case we hit the same file/line specs, we want to recompute a new 2395 ;; In case we hit the same file/line specs, we want to recompute a new
2379 ;; marker for them, so flush our cache. 2396 ;; marker for them, so flush our cache.
2380 (setq compilation-locs (make-hash-table :test 'equal :weakness 'value)) 2397 (clrhash compilation-locs)
2381 (setq compilation-gcpro nil) 2398 (setq compilation-gcpro nil)
2382 ;; FIXME: the old code reset the directory-stack, so maybe we should 2399 ;; FIXME: the old code reset the directory-stack, so maybe we should
2383 ;; put a `directory change' marker of some sort, but where? -stef 2400 ;; put a `directory change' marker of some sort, but where? -stef
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index d69cce76faa..d89e41b38fb 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1840,7 +1840,13 @@ or as help on variables `cperl-tips', `cperl-problems',
1840 (make-local-variable 'cperl-syntax-state) 1840 (make-local-variable 'cperl-syntax-state)
1841 (setq cperl-syntax-state nil) ; reset syntaxification cache 1841 (setq cperl-syntax-state nil) ; reset syntaxification cache
1842 (if cperl-use-syntax-table-text-property 1842 (if cperl-use-syntax-table-text-property
1843 (progn 1843 (if (boundp 'syntax-propertize-function)
1844 (progn
1845 ;; Reset syntaxification cache.
1846 (set (make-local-variable 'cperl-syntax-done-to) nil)
1847 (set (make-local-variable 'syntax-propertize-function)
1848 (lambda (start end)
1849 (goto-char start) (cperl-fontify-syntaxically end))))
1844 (make-local-variable 'parse-sexp-lookup-properties) 1850 (make-local-variable 'parse-sexp-lookup-properties)
1845 ;; Do not introduce variable if not needed, we check it! 1851 ;; Do not introduce variable if not needed, we check it!
1846 (set 'parse-sexp-lookup-properties t) 1852 (set 'parse-sexp-lookup-properties t)
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index c37744bfe45..daa0fd07364 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -483,6 +483,7 @@ The only difference is, it returns t in a case when the default returns nil."
483 "Maximum highlighting for Fortran mode. 483 "Maximum highlighting for Fortran mode.
484Consists of level 3 plus all other intrinsics not already highlighted.") 484Consists of level 3 plus all other intrinsics not already highlighted.")
485 485
486(defvar fortran--font-lock-syntactic-keywords)
486;; Comments are real pain in Fortran because there is no way to 487;; Comments are real pain in Fortran because there is no way to
487;; represent the standard comment syntax in an Emacs syntax table. 488;; represent the standard comment syntax in an Emacs syntax table.
488;; (We can do so for F90-style). Therefore an unmatched quote in a 489;; (We can do so for F90-style). Therefore an unmatched quote in a
@@ -887,9 +888,11 @@ with no args, if that value is non-nil."
887 fortran-font-lock-keywords-3 888 fortran-font-lock-keywords-3
888 fortran-font-lock-keywords-4) 889 fortran-font-lock-keywords-4)
889 nil t ((?/ . "$/") ("_$" . "w")) 890 nil t ((?/ . "$/") ("_$" . "w"))
890 fortran-beginning-of-subprogram 891 fortran-beginning-of-subprogram))
891 (font-lock-syntactic-keywords 892 (set (make-local-variable 'fortran--font-lock-syntactic-keywords)
892 . fortran-font-lock-syntactic-keywords))) 893 (fortran-make-syntax-propertize-function))
894 (set (make-local-variable 'syntax-propertize-function)
895 (syntax-propertize-via-font-lock fortran--font-lock-syntactic-keywords))
893 (set (make-local-variable 'imenu-case-fold-search) t) 896 (set (make-local-variable 'imenu-case-fold-search) t)
894 (set (make-local-variable 'imenu-generic-expression) 897 (set (make-local-variable 'imenu-generic-expression)
895 fortran-imenu-generic-expression) 898 fortran-imenu-generic-expression)
@@ -917,11 +920,13 @@ affects all Fortran buffers, and also the default."
917 (when (eq major-mode 'fortran-mode) 920 (when (eq major-mode 'fortran-mode)
918 (setq fortran-line-length nchars 921 (setq fortran-line-length nchars
919 fill-column fortran-line-length 922 fill-column fortran-line-length
920 new (fortran-font-lock-syntactic-keywords)) 923 new (fortran-make-syntax-propertize-function))
921 ;; Refontify only if necessary. 924 ;; Refontify only if necessary.
922 (unless (equal new font-lock-syntactic-keywords) 925 (unless (equal new fortran--font-lock-syntactic-keywords)
923 (setq font-lock-syntactic-keywords 926 (setq fortran--font-lock-syntactic-keywords new)
924 (fortran-font-lock-syntactic-keywords)) 927 (setq syntax-propertize-function
928 (syntax-propertize-via-font-lock new))
929 (syntax-ppss-flush-cache (point-min))
925 (if font-lock-mode (font-lock-mode 1)))))) 930 (if font-lock-mode (font-lock-mode 1))))))
926 (if global 931 (if global
927 (buffer-list) 932 (buffer-list)
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index d20a14682c7..4c1471e39ec 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -3123,10 +3123,12 @@ class of the file (using s to separate nested class ids)."
3123 ("\\$\\(\\w+\\)" (1 font-lock-variable-name-face)) 3123 ("\\$\\(\\w+\\)" (1 font-lock-variable-name-face))
3124 ("^\\s-*\\(\\w\\(\\w\\|\\s_\\)*\\)" (1 font-lock-keyword-face)))) 3124 ("^\\s-*\\(\\w\\(\\w\\|\\s_\\)*\\)" (1 font-lock-keyword-face))))
3125 3125
3126(defvar gdb-script-font-lock-syntactic-keywords 3126(defconst gdb-script-syntax-propertize-function
3127 '(("^document\\s-.*\\(\n\\)" (1 "< b")) 3127 (syntax-propertize-rules
3128 ("^end\\>" 3128 ("^document\\s-.*\\(\n\\)" (1 "< b"))
3129 (0 (unless (eq (match-beginning 0) (point-min)) 3129 ("^end\\(\\>\\)"
3130 (1 (ignore
3131 (unless (eq (match-beginning 0) (point-min))
3130 ;; We change the \n in front, which is more difficult, but results 3132 ;; We change the \n in front, which is more difficult, but results
3131 ;; in better highlighting. If the doc is empty, the single \n is 3133 ;; in better highlighting. If the doc is empty, the single \n is
3132 ;; both the beginning and the end of the docstring, which can't be 3134 ;; both the beginning and the end of the docstring, which can't be
@@ -3138,10 +3140,9 @@ class of the file (using s to separate nested class ids)."
3138 'syntax-table (eval-when-compile 3140 'syntax-table (eval-when-compile
3139 (string-to-syntax "> b"))) 3141 (string-to-syntax "> b")))
3140 ;; Make sure that rehighlighting the previous line won't erase our 3142 ;; Make sure that rehighlighting the previous line won't erase our
3141 ;; syntax-table property. 3143 ;; syntax-table property and that modifying `end' will.
3142 (put-text-property (1- (match-beginning 0)) (match-end 0) 3144 (put-text-property (1- (match-beginning 0)) (match-end 0)
3143 'font-lock-multiline t) 3145 'syntax-multiline t)))))))
3144 nil)))))
3145 3146
3146(defun gdb-script-font-lock-syntactic-face (state) 3147(defun gdb-script-font-lock-syntactic-face (state)
3147 (cond 3148 (cond
@@ -3239,10 +3240,13 @@ Treats actions as defuns."
3239 #'gdb-script-end-of-defun) 3240 #'gdb-script-end-of-defun)
3240 (set (make-local-variable 'font-lock-defaults) 3241 (set (make-local-variable 'font-lock-defaults)
3241 '(gdb-script-font-lock-keywords nil nil ((?_ . "w")) nil 3242 '(gdb-script-font-lock-keywords nil nil ((?_ . "w")) nil
3242 (font-lock-syntactic-keywords
3243 . gdb-script-font-lock-syntactic-keywords)
3244 (font-lock-syntactic-face-function 3243 (font-lock-syntactic-face-function
3245 . gdb-script-font-lock-syntactic-face)))) 3244 . gdb-script-font-lock-syntactic-face)))
3245 ;; Recognize docstrings.
3246 (set (make-local-variable 'syntax-propertize-function)
3247 gdb-script-syntax-propertize-function)
3248 (add-hook 'syntax-propertize-extend-region-functions
3249 #'syntax-propertize-multiline 'append 'local))
3246 3250
3247 3251
3248;;; tooltips for GUD 3252;;; tooltips for GUD
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 5e854f852e1..ba70bb8ecce 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -45,16 +45,16 @@
45 45
46;;; Code: 46;;; Code:
47 47
48(eval-and-compile 48
49 (require 'cc-mode) 49(require 'cc-mode)
50 (require 'font-lock) 50(require 'font-lock)
51 (require 'newcomment) 51(require 'newcomment)
52 (require 'imenu) 52(require 'imenu)
53 (require 'etags) 53(require 'etags)
54 (require 'thingatpt) 54(require 'thingatpt)
55 (require 'easymenu) 55(require 'easymenu)
56 (require 'moz nil t) 56(require 'moz nil t)
57 (require 'json nil t)) 57(require 'json nil t)
58 58
59(eval-when-compile 59(eval-when-compile
60 (require 'cl) 60 (require 'cl)
@@ -725,20 +725,19 @@ as if strings, cpp macros, and comments have been removed.
725 725
726If invoked while inside a macro, it treats the contents of the 726If invoked while inside a macro, it treats the contents of the
727macro as normal text." 727macro as normal text."
728 (unless count (setq count 1))
728 (let ((saved-point (point)) 729 (let ((saved-point (point))
729 (search-expr 730 (search-fun
730 (cond ((null count) 731 (cond ((< count 0) (setq count (- count))
731 '(js--re-search-forward-inner regexp bound 1)) 732 #'js--re-search-backward-inner)
732 ((< count 0) 733 ((> count 0) #'js--re-search-forward-inner)
733 '(js--re-search-backward-inner regexp bound (- count))) 734 (t #'ignore))))
734 ((> count 0)
735 '(js--re-search-forward-inner regexp bound count)))))
736 (condition-case err 735 (condition-case err
737 (eval search-expr) 736 (funcall search-fun regexp bound count)
738 (search-failed 737 (search-failed
739 (goto-char saved-point) 738 (goto-char saved-point)
740 (unless noerror 739 (unless noerror
741 (error (error-message-string err))))))) 740 (signal (car err) (cdr err)))))))
742 741
743 742
744(defun js--re-search-backward-inner (regexp &optional bound count) 743(defun js--re-search-backward-inner (regexp &optional bound count)
@@ -782,20 +781,7 @@ as if strings, preprocessor macros, and comments have been
782removed. 781removed.
783 782
784If invoked while inside a macro, treat the macro as normal text." 783If invoked while inside a macro, treat the macro as normal text."
785 (let ((saved-point (point)) 784 (js--re-search-forward regexp bound noerror (if count (- count) -1)))
786 (search-expr
787 (cond ((null count)
788 '(js--re-search-backward-inner regexp bound 1))
789 ((< count 0)
790 '(js--re-search-forward-inner regexp bound (- count)))
791 ((> count 0)
792 '(js--re-search-backward-inner regexp bound count)))))
793 (condition-case err
794 (eval search-expr)
795 (search-failed
796 (goto-char saved-point)
797 (unless noerror
798 (error (error-message-string err)))))))
799 785
800(defun js--forward-expression () 786(defun js--forward-expression ()
801 "Move forward over a whole JavaScript expression. 787 "Move forward over a whole JavaScript expression.
@@ -1674,18 +1660,19 @@ This performs fontification according to `js--class-styles'."
1674;; XXX: Javascript can continue a regexp literal across lines so long 1660;; XXX: Javascript can continue a regexp literal across lines so long
1675;; as the newline is escaped with \. Account for that in the regexp 1661;; as the newline is escaped with \. Account for that in the regexp
1676;; below. 1662;; below.
1677(defconst js--regexp-literal 1663(eval-and-compile
1664 (defconst js--regexp-literal
1678 "[=(,:]\\(?:\\s-\\|\n\\)*\\(/\\)\\(?:\\\\/\\|[^/*]\\)\\(?:\\\\/\\|[^/]\\)*\\(/\\)" 1665 "[=(,:]\\(?:\\s-\\|\n\\)*\\(/\\)\\(?:\\\\/\\|[^/*]\\)\\(?:\\\\/\\|[^/]\\)*\\(/\\)"
1679 "Regexp matching a JavaScript regular expression literal. 1666 "Regexp matching a JavaScript regular expression literal.
1680Match groups 1 and 2 are the characters forming the beginning and 1667Match groups 1 and 2 are the characters forming the beginning and
1681end of the literal.") 1668end of the literal."))
1669
1682 1670
1683;; we want to match regular expressions only at the beginning of 1671(defconst js-syntax-propertize-function
1684;; expressions 1672 (syntax-propertize-rules
1685(defconst js-font-lock-syntactic-keywords 1673 ;; We want to match regular expressions only at the beginning of
1686 `((,js--regexp-literal (1 "|") (2 "|"))) 1674 ;; expressions.
1687 "Syntactic font lock keywords matching regexps in JavaScript. 1675 (js--regexp-literal (1 "\"") (2 "\""))))
1688See `font-lock-keywords'.")
1689 1676
1690;;; Indentation 1677;;; Indentation
1691 1678
@@ -3317,10 +3304,9 @@ Key bindings:
3317 3304
3318 (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) 3305 (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
3319 (set (make-local-variable 'font-lock-defaults) 3306 (set (make-local-variable 'font-lock-defaults)
3320 (list js--font-lock-keywords 3307 '(js--font-lock-keywords))
3321 nil nil nil nil 3308 (set (make-local-variable 'syntax-propertize-function)
3322 '(font-lock-syntactic-keywords 3309 js-syntax-propertize-function)
3323 . js-font-lock-syntactic-keywords)))
3324 3310
3325 (set (make-local-variable 'parse-sexp-ignore-comments) t) 3311 (set (make-local-variable 'parse-sexp-ignore-comments) t)
3326 (set (make-local-variable 'parse-sexp-lookup-properties) t) 3312 (set (make-local-variable 'parse-sexp-lookup-properties) t)
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 362a1db6c10..187c838382b 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -505,15 +505,16 @@ not be enclosed in { } or ( )."
505 cpp-font-lock-keywords)) 505 cpp-font-lock-keywords))
506 506
507 507
508(defconst makefile-font-lock-syntactic-keywords 508(defconst makefile-syntax-propertize-function
509 ;; From sh-script.el. 509 (syntax-propertize-rules
510 ;; A `#' begins a comment in sh when it is unquoted and at the beginning 510 ;; From sh-script.el.
511 ;; of a word. In the shell, words are separated by metacharacters. 511 ;; A `#' begins a comment in sh when it is unquoted and at the beginning
512 ;; The list of special chars is taken from the single-unix spec of the 512 ;; of a word. In the shell, words are separated by metacharacters.
513 ;; shell command language (under `quoting') but with `$' removed. 513 ;; The list of special chars is taken from the single-unix spec of the
514 '(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 "_") 514 ;; shell command language (under `quoting') but with `$' removed.
515 ;; Change the syntax of a quoted newline so that it does not end a comment. 515 ("[^|&;<>()`\\\"' \t\n]\\(#+\\)" (1 "_"))
516 ("\\\\\n" 0 "."))) 516 ;; Change the syntax of a quoted newline so that it does not end a comment.
517 ("\\\\\n" (0 "."))))
517 518
518(defvar makefile-imenu-generic-expression 519(defvar makefile-imenu-generic-expression
519 `(("Dependencies" makefile-previous-dependency 1) 520 `(("Dependencies" makefile-previous-dependency 1)
@@ -872,9 +873,9 @@ Makefile mode can be configured by modifying the following variables:
872 '(makefile-font-lock-keywords 873 '(makefile-font-lock-keywords
873 nil nil 874 nil nil
874 ((?$ . ".")) 875 ((?$ . "."))
875 backward-paragraph 876 backward-paragraph))
876 (font-lock-syntactic-keywords 877 (set (make-local-variable 'syntax-propertize-function)
877 . makefile-font-lock-syntactic-keywords))) 878 makefile-syntax-propertize-function)
878 879
879 ;; Add-log. 880 ;; Add-log.
880 (set (make-local-variable 'add-log-current-defun-function) 881 (set (make-local-variable 'add-log-current-defun-function)
@@ -943,15 +944,9 @@ Makefile mode can be configured by modifying the following variables:
943(define-derived-mode makefile-imake-mode makefile-mode "Imakefile" 944(define-derived-mode makefile-imake-mode makefile-mode "Imakefile"
944 "An adapted `makefile-mode' that knows about imake." 945 "An adapted `makefile-mode' that knows about imake."
945 :syntax-table makefile-imake-mode-syntax-table 946 :syntax-table makefile-imake-mode-syntax-table
946 (let ((base `(makefile-imake-font-lock-keywords ,@(cdr font-lock-defaults))) 947 (set (make-local-variable 'syntax-propertize-function) nil)
947 new) 948 (setq font-lock-defaults
948 ;; Remove `font-lock-syntactic-keywords' entry from font-lock-defaults. 949 `(makefile-imake-font-lock-keywords ,@(cdr font-lock-defaults))))
949 (mapc (lambda (elt)
950 (unless (and (consp elt)
951 (eq (car elt) 'font-lock-syntactic-keywords))
952 (setq new (cons elt new))))
953 base)
954 (setq font-lock-defaults (nreverse new))))
955 950
956 951
957 952
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index ecb8461a9f2..94af563d88f 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -89,7 +89,7 @@
89(defvar mixal-mode-syntax-table 89(defvar mixal-mode-syntax-table
90 (let ((st (make-syntax-table))) 90 (let ((st (make-syntax-table)))
91 ;; We need to do a bit more to make fontlocking for comments work. 91 ;; We need to do a bit more to make fontlocking for comments work.
92 ;; See mixal-font-lock-syntactic-keywords. 92 ;; See use of syntax-propertize-function.
93 ;; (modify-syntax-entry ?* "<" st) 93 ;; (modify-syntax-entry ?* "<" st)
94 (modify-syntax-entry ?\n ">" st) 94 (modify-syntax-entry ?\n ">" st)
95 st) 95 st)
@@ -1028,13 +1028,14 @@ EXECUTION-TIME holds info about the time it takes, number or string.")
1028 1028
1029 1029
1030;;; Font-locking: 1030;;; Font-locking:
1031(defvar mixal-font-lock-syntactic-keywords 1031(defconst mixal-syntax-propertize-function
1032 ;; Normal comments start with a * in column 0 and end at end of line. 1032 (syntax-propertize-rules
1033 '(("^\\*" (0 '(11))) ;(string-to-syntax "<") == '(11) 1033 ;; Normal comments start with a * in column 0 and end at end of line.
1034 ;; Every line can end with a comment which is placed after the operand. 1034 ("^\\*" (0 "<"))
1035 ;; I assume here that mnemonics without operands can not have a comment. 1035 ;; Every line can end with a comment which is placed after the operand.
1036 ("^[[:alnum:]]*[ \t]+[[:alnum:]]+[ \t]+[^ \n\t]+[ \t]*\\([ \t]\\)[^\n \t]" 1036 ;; I assume here that mnemonics without operands can not have a comment.
1037 (1 '(11))))) 1037 ("^[[:alnum:]]*[ \t]+[[:alnum:]]+[ \t]+[^ \n\t]+[ \t]*\\([ \t]\\)[^\n \t]"
1038 (1 "<"))))
1038 1039
1039(defvar mixal-font-lock-keywords 1040(defvar mixal-font-lock-keywords
1040 `(("^\\([A-Z0-9a-z]+\\)" 1041 `(("^\\([A-Z0-9a-z]+\\)"
@@ -1110,9 +1111,9 @@ Assumes that file has been compiled with debugging support."
1110 (set (make-local-variable 'comment-start) "*") 1111 (set (make-local-variable 'comment-start) "*")
1111 (set (make-local-variable 'comment-start-skip) "^\\*[ \t]*") 1112 (set (make-local-variable 'comment-start-skip) "^\\*[ \t]*")
1112 (set (make-local-variable 'font-lock-defaults) 1113 (set (make-local-variable 'font-lock-defaults)
1113 `(mixal-font-lock-keywords nil nil nil nil 1114 `(mixal-font-lock-keywords))
1114 (font-lock-syntactic-keywords . ,mixal-font-lock-syntactic-keywords) 1115 (set (make-local-variable 'syntax-propertize-function)
1115 (parse-sexp-lookup-properties . t))) 1116 mixal-syntax-propertize-function)
1116 ;; might add an indent function in the future 1117 ;; might add an indent function in the future
1117 ;; (set (make-local-variable 'indent-line-function) 'mixal-indent-line) 1118 ;; (set (make-local-variable 'indent-line-function) 'mixal-indent-line)
1118 (set (make-local-variable 'compile-command) (concat "mixasm " 1119 (set (make-local-variable 'compile-command) (concat "mixasm "
diff --git a/lisp/progmodes/octave-mod.el b/lisp/progmodes/octave-mod.el
index ede850f87ab..bbefdaa2ccf 100644
--- a/lisp/progmodes/octave-mod.el
+++ b/lisp/progmodes/octave-mod.el
@@ -179,38 +179,28 @@ parenthetical grouping.")
179 '(3 font-lock-function-name-face nil t))) 179 '(3 font-lock-function-name-face nil t)))
180 "Additional Octave expressions to highlight.") 180 "Additional Octave expressions to highlight.")
181 181
182(defvar octave-font-lock-syntactic-keywords 182(defun octave-syntax-propertize-function (start end)
183 (goto-char start)
184 (octave-syntax-propertize-sqs end)
185 (funcall (syntax-propertize-rules
183 ;; Try to distinguish the string-quotes from the transpose-quotes. 186 ;; Try to distinguish the string-quotes from the transpose-quotes.
184 '(("[[({,; ]\\('\\)" (1 "\"'")) 187 ("[[({,; ]\\('\\)"
185 (octave-font-lock-close-quotes))) 188 (1 (prog1 "\"'" (octave-syntax-propertize-sqs end)))))
186 189 (point) end))
187(defun octave-font-lock-close-quotes (limit) 190
188 "Fix the syntax-table of the closing quotes of single-quote strings." 191(defun octave-syntax-propertize-sqs (end)
189 ;; Freely inspired from perl-font-lock-special-syntactic-constructs. 192 "Propertize the content/end of single-quote strings."
190 (let ((state (syntax-ppss))) 193 (when (eq (nth 3 (syntax-ppss)) ?\')
191 (while (< (point) limit)
192 (cond
193 ((eq (nth 3 state) ?\')
194 ;; A '..' string. 194 ;; A '..' string.
195 (save-excursion 195 (when (re-search-forward
196 (when (re-search-forward "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)[^']" 196 "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)\\($\\|[^']\\)" end 'move)
197 nil t) 197 (goto-char (match-beginning 2))
198 (goto-char (1- (point)))
199 ;; Remove any syntax-table property we may have applied to
200 ;; some of the (doubled) single quotes within the string.
201 ;; Since these are the only chars on which we place properties,
202 ;; we take a shortcut and just remove all properties.
203 (remove-text-properties (1+ (nth 8 state)) (match-beginning 1)
204 '(syntax-table nil))
205 (when (eq (char-before (match-beginning 1)) ?\\) 198 (when (eq (char-before (match-beginning 1)) ?\\)
206 ;; Backslash cannot escape a single quote. 199 ;; Backslash cannot escape a single quote.
207 (put-text-property (1- (match-beginning 1)) (match-beginning 1) 200 (put-text-property (1- (match-beginning 1)) (match-beginning 1)
208 'syntax-table (string-to-syntax "."))) 201 'syntax-table (string-to-syntax ".")))
209 (put-text-property (match-beginning 1) (match-end 1) 202 (put-text-property (match-beginning 1) (match-end 1)
210 'syntax-table (string-to-syntax "\"'")))))) 203 'syntax-table (string-to-syntax "\"'")))))
211
212 (setq state (parse-partial-sexp (point) limit nil nil state
213 'syntax-table)))))
214 204
215(defcustom inferior-octave-buffer "*Inferior Octave*" 205(defcustom inferior-octave-buffer "*Inferior Octave*"
216 "Name of buffer for running an inferior Octave process." 206 "Name of buffer for running an inferior Octave process."
@@ -544,6 +534,8 @@ Non-nil means always go to the next Octave code line after sending."
544 0) 534 0)
545 ((:before . "case") octave-block-offset))) 535 ((:before . "case") octave-block-offset)))
546 536
537(defvar electric-indent-chars)
538
547;;;###autoload 539;;;###autoload
548(define-derived-mode octave-mode prog-mode "Octave" 540(define-derived-mode octave-mode prog-mode "Octave"
549 "Major mode for editing Octave code. 541 "Major mode for editing Octave code.
@@ -682,9 +674,10 @@ including a reproducible test case and send the message."
682 (set (make-local-variable 'normal-auto-fill-function) 'octave-auto-fill) 674 (set (make-local-variable 'normal-auto-fill-function) 'octave-auto-fill)
683 675
684 (set (make-local-variable 'font-lock-defaults) 676 (set (make-local-variable 'font-lock-defaults)
685 '(octave-font-lock-keywords nil nil nil nil 677 '(octave-font-lock-keywords))
686 (font-lock-syntactic-keywords . octave-font-lock-syntactic-keywords) 678
687 (parse-sexp-lookup-properties . t))) 679 (set (make-local-variable 'syntax-propertize-function)
680 #'octave-syntax-propertize-function)
688 681
689 (set (make-local-variable 'imenu-generic-expression) 682 (set (make-local-variable 'imenu-generic-expression)
690 octave-mode-imenu-generic-expression) 683 octave-mode-imenu-generic-expression)
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index f8eba5accdb..ae3acc3cda3 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -250,59 +250,76 @@ The expansion is entirely correct because it uses the C preprocessor."
250;; y /.../.../ 250;; y /.../.../
251;; 251;;
252;; <file*glob> 252;; <file*glob>
253(defvar perl-font-lock-syntactic-keywords 253(defun perl-syntax-propertize-function (start end)
254 ;; TODO: here-documents ("<<\\(\\sw\\|['\"]\\)") 254 (let ((case-fold-search nil))
255 `(;; Turn POD into b-style comments 255 (goto-char start)
256 ("^\\(=\\)\\sw" (1 "< b")) 256 (perl-syntax-propertize-special-constructs end)
257 ("^=cut[ \t]*\\(\n\\)" (1 "> b")) 257 ;; TODO: here-documents ("<<\\(\\sw\\|['\"]\\)")
258 ;; Catch ${ so that ${var} doesn't screw up indentation. 258 (funcall
259 ;; This also catches $' to handle 'foo$', although it should really 259 (syntax-propertize-rules
260 ;; check that it occurs inside a '..' string. 260 ;; Turn POD into b-style comments. Place the cut rule first since it's
261 ("\\(\\$\\)[{']" (1 ". p")) 261 ;; more specific.
262 ;; Handle funny names like $DB'stop. 262 ("^=cut\\>.*\\(\n\\)" (1 "> b"))
263 ("\\$ ?{?^?[_a-zA-Z][_a-zA-Z0-9]*\\('\\)[_a-zA-Z]" (1 "_")) 263 ("^\\(=\\)\\sw" (1 "< b"))
264 ;; format statements 264 ;; Catch ${ so that ${var} doesn't screw up indentation.
265 ("^[ \t]*format.*=[ \t]*\\(\n\\)" (1 '(7))) 265 ;; This also catches $' to handle 'foo$', although it should really
266 ;; Funny things in `sub' arg-specs like `sub myfun ($)' or `sub ($)'. 266 ;; check that it occurs inside a '..' string.
267 ;; Be careful not to match "sub { (...) ... }". 267 ("\\(\\$\\)[{']" (1 ". p"))
268 ("\\<sub\\(?:[[:space:]]+[^{}[:punct:][:space:]]+\\)?[[:space:]]*(\\([^)]+\\))" 268 ;; Handle funny names like $DB'stop.
269 1 '(1)) 269 ("\\$ ?{?^?[_a-zA-Z][_a-zA-Z0-9]*\\('\\)[_a-zA-Z]" (1 "_"))
270 ;; Regexp and funny quotes. Distinguishing a / that starts a regexp 270 ;; format statements
271 ;; match from the division operator is ...interesting. 271 ("^[ \t]*format.*=[ \t]*\\(\n\\)"
272 ;; Basically, / is a regexp match if it's preceded by an infix operator 272 (1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
273 ;; (or some similar separator), or by one of the special keywords 273 ;; Funny things in `sub' arg-specs like `sub myfun ($)' or `sub ($)'.
274 ;; corresponding to builtin functions that can take their first arg 274 ;; Be careful not to match "sub { (...) ... }".
275 ;; without parentheses. Of course, that presume we're looking at the 275 ("\\<sub\\(?:[[:space:]]+[^{}[:punct:][:space:]]+\\)?[[:space:]]*(\\([^)]+\\))"
276 ;; *opening* slash. We can afford to mis-match the closing ones 276 (1 "."))
277 ;; here, because they will be re-treated separately later in 277 ;; Regexp and funny quotes. Distinguishing a / that starts a regexp
278 ;; perl-font-lock-special-syntactic-constructs. 278 ;; match from the division operator is ...interesting.
279 (,(concat "\\(?:\\(?:\\(?:^\\|[^$@&%[:word:]]\\)" 279 ;; Basically, / is a regexp match if it's preceded by an infix operator
280 (regexp-opt '("split" "if" "unless" "until" "while" "split" 280 ;; (or some similar separator), or by one of the special keywords
281 "grep" "map" "not" "or" "and")) 281 ;; corresponding to builtin functions that can take their first arg
282 "\\)\\|[?:.,;=!~({[]\\|\\(^\\)\\)[ \t\n]*\\(/\\)") 282 ;; without parentheses. Of course, that presume we're looking at the
283 (2 (if (and (match-end 1) 283 ;; *opening* slash. We can afford to mis-match the closing ones
284 (save-excursion 284 ;; here, because they will be re-treated separately later in
285 (goto-char (match-end 1)) 285 ;; perl-font-lock-special-syntactic-constructs.
286 ;; Not 100% correct since we haven't finished setting up 286 ((concat "\\(?:\\(?:^\\|[^$@&%[:word:]]\\)"
287 ;; the syntax-table before point, but better than nothing. 287 (regexp-opt '("split" "if" "unless" "until" "while" "split"
288 (forward-comment (- (point-max))) 288 "grep" "map" "not" "or" "and"))
289 (put-text-property (point) (match-end 2) 289 "\\|[?:.,;=!~({[]\\|\\(^\\)\\)[ \t\n]*\\(/\\)")
290 'jit-lock-defer-multiline t) 290 (2 (ignore
291 (not (memq (char-before) 291 (if (and (match-end 1) ; / at BOL.
292 '(?? ?: ?. ?, ?\; ?= ?! ?~ ?\( ?\[))))) 292 (save-excursion
293 nil ;; A division sign instead of a regexp-match. 293 (goto-char (match-end 1))
294 '(7)))) 294 (forward-comment (- (point-max)))
295 ("\\(^\\|[?:.,;=!~({[ \t]\\)\\([msy]\\|q[qxrw]?\\|tr\\)\\>\\s-*\\([^])}> \n\t]\\)" 295 (put-text-property (point) (match-end 2)
296 ;; Nasty cases: 296 'syntax-multiline t)
297 ;; /foo/m $a->m $#m $m @m %m 297 (not (memq (char-before)
298 ;; \s (appears often in regexps). 298 '(?? ?: ?. ?, ?\; ?= ?! ?~ ?\( ?\[)))))
299 ;; -s file 299 nil ;; A division sign instead of a regexp-match.
300 (3 (if (assoc (char-after (match-beginning 3)) 300 (put-text-property (match-beginning 2) (match-end 2)
301 perl-quote-like-pairs) 301 'syntax-table (string-to-syntax "\""))
302 '(15) '(7)))) 302 (perl-syntax-propertize-special-constructs end)))))
303 ;; Find and mark the end of funny quotes and format statements. 303 ("\\(^\\|[?:.,;=!~({[ \t]\\)\\([msy]\\|q[qxrw]?\\|tr\\)\\>\\s-*\\([^])}> \n\t]\\)"
304 (perl-font-lock-special-syntactic-constructs) 304 ;; Nasty cases:
305 )) 305 ;; /foo/m $a->m $#m $m @m %m
306 ;; \s (appears often in regexps).
307 ;; -s file
308 ;; sub tr {...}
309 (3 (ignore
310 (if (save-excursion (goto-char (match-beginning 0))
311 (forward-word -1)
312 (looking-at-p "sub[ \t\n]"))
313 ;; This is defining a function.
314 nil
315 (put-text-property (match-beginning 3) (match-end 3)
316 'syntax-table
317 (if (assoc (char-after (match-beginning 3))
318 perl-quote-like-pairs)
319 (string-to-syntax "|")
320 (string-to-syntax "\"")))
321 (perl-syntax-propertize-special-constructs end))))))
322 (point) end)))
306 323
307(defvar perl-empty-syntax-table 324(defvar perl-empty-syntax-table
308 (let ((st (copy-syntax-table))) 325 (let ((st (copy-syntax-table)))
@@ -321,95 +338,123 @@ The expansion is entirely correct because it uses the C preprocessor."
321 (modify-syntax-entry close ")" st)) 338 (modify-syntax-entry close ")" st))
322 st)) 339 st))
323 340
324(defun perl-font-lock-special-syntactic-constructs (limit) 341(defun perl-syntax-propertize-special-constructs (limit)
325 ;; We used to do all this in a font-lock-syntactic-face-function, which 342 "Propertize special constructs like regexps and formats."
326 ;; did not work correctly because sometimes some parts of the buffer are
327 ;; treated with font-lock-syntactic-keywords but not with
328 ;; font-lock-syntactic-face-function (mostly because of
329 ;; font-lock-syntactically-fontified). That meant that some syntax-table
330 ;; properties were missing. So now we do the parse-partial-sexp loop
331 ;; ourselves directly from font-lock-syntactic-keywords, so we're sure
332 ;; it's done when necessary.
333 (let ((state (syntax-ppss)) 343 (let ((state (syntax-ppss))
334 char) 344 char)
335 (while (< (point) limit) 345 (cond
336 (cond 346 ((or (null (setq char (nth 3 state)))
337 ((or (null (setq char (nth 3 state))) 347 (and (characterp char) (eq (char-syntax (nth 3 state)) ?\")))
338 (and (characterp char) (eq (char-syntax (nth 3 state)) ?\"))) 348 ;; Normal text, or comment, or docstring, or normal string.
339 ;; Normal text, or comment, or docstring, or normal string. 349 nil)
340 nil) 350 ((eq (nth 3 state) ?\n)
341 ((eq (nth 3 state) ?\n) 351 ;; A `format' command.
342 ;; A `format' command. 352 (when (re-search-forward "^\\s *\\.\\s *\n" limit 'move)
343 (save-excursion 353 (put-text-property (1- (point)) (point)
344 (when (and (re-search-forward "^\\s *\\.\\s *$" nil t) 354 'syntax-table (string-to-syntax "\""))))
345 (not (eobp))) 355 (t
346 (put-text-property (point) (1+ (point)) 'syntax-table '(7))))) 356 ;; This is regexp like quote thingy.
347 (t 357 (setq char (char-after (nth 8 state)))
348 ;; This is regexp like quote thingy. 358 (let ((twoargs (save-excursion
349 (setq char (char-after (nth 8 state))) 359 (goto-char (nth 8 state))
350 (save-excursion 360 (skip-syntax-backward " ")
351 (let ((twoargs (save-excursion 361 (skip-syntax-backward "w")
352 (goto-char (nth 8 state)) 362 (member (buffer-substring
353 (skip-syntax-backward " ") 363 (point) (progn (forward-word 1) (point)))
354 (skip-syntax-backward "w") 364 '("tr" "s" "y"))))
355 (member (buffer-substring 365 (close (cdr (assq char perl-quote-like-pairs)))
356 (point) (progn (forward-word 1) (point))) 366 (st (perl-quote-syntax-table char)))
357 '("tr" "s" "y")))) 367 (when (with-syntax-table st
358 (close (cdr (assq char perl-quote-like-pairs))) 368 (if close
359 (pos (point)) 369 ;; For paired delimiters, Perl allows nesting them, but
360 (st (perl-quote-syntax-table char))) 370 ;; since we treat them as strings, Emacs does not count
361 (if (not close) 371 ;; those delimiters in `state', so we don't know how deep
362 ;; The closing char is the same as the opening char. 372 ;; we are: we have to go back to the beginning of this
363 (with-syntax-table st 373 ;; "string" and count from there.
364 (parse-partial-sexp (point) (point-max) 374 (condition-case nil
365 nil nil state 'syntax-table) 375 (progn
366 (when twoargs 376 ;; Start after the first char since it doesn't have
367 (parse-partial-sexp (point) (point-max) 377 ;; paren-syntax (an alternative would be to let-bind
368 nil nil state 'syntax-table))) 378 ;; parse-sexp-lookup-properties).
369 ;; The open/close chars are matched like () [] {} and <>. 379 (goto-char (1+ (nth 8 state)))
370 (let ((parse-sexp-lookup-properties nil)) 380 (up-list 1)
371 (condition-case err 381 t)
372 (progn 382 (scan-error nil))
373 (with-syntax-table st 383 (not (or (nth 8 (parse-partial-sexp
374 (goto-char (nth 8 state)) (forward-sexp 1)) 384 (point) limit nil nil state 'syntax-table))
375 (when twoargs 385 ;; If we have a self-paired opener and a twoargs
376 (save-excursion 386 ;; command, the form is s/../../ so we have to skip
377 ;; Skip whitespace and make sure that font-lock will 387 ;; a second time.
378 ;; refontify the second part in the proper context. 388 ;; In the case of s{...}{...}, we only handle the
379 (put-text-property 389 ;; first part here and the next below.
380 (point) (progn (forward-comment (point-max)) (point)) 390 (when (and twoargs (not close))
381 'font-lock-multiline t) 391 (nth 8 (parse-partial-sexp
382 ;; 392 (point) limit
383 (unless 393 nil nil state 'syntax-table)))))))
384 (or (eobp) 394 ;; Point is now right after the arg(s).
385 (save-excursion 395 (when (eq (char-before (1- (point))) ?$)
386 (with-syntax-table 396 (put-text-property (- (point) 2) (1- (point))
387 (perl-quote-syntax-table (char-after)) 397 'syntax-table '(1)))
388 (forward-sexp 1)) 398 (put-text-property (1- (point)) (point)
389 (put-text-property pos (line-end-position) 399 'syntax-table
390 'jit-lock-defer-multiline t) 400 (if close
391 (looking-at "\\s-*\\sw*e"))) 401 (string-to-syntax "|")
392 (put-text-property (point) (1+ (point)) 402 (string-to-syntax "\"")))
393 'syntax-table 403 ;; If we have two args with a non-self-paired starter (e.g.
394 (if (assoc (char-after) 404 ;; s{...}{...}) we're right after the first arg, so we still have to
395 perl-quote-like-pairs) 405 ;; handle the second part.
396 '(15) '(7))))))) 406 (when (and twoargs close)
397 ;; The arg(s) is not terminated, so it extends until EOB. 407 ;; Skip whitespace and make sure that font-lock will
398 (scan-error (goto-char (point-max)))))) 408 ;; refontify the second part in the proper context.
399 ;; Point is now right after the arg(s). 409 (put-text-property
400 ;; Erase any syntactic marks within the quoted text. 410 (point) (progn (forward-comment (point-max)) (point))
401 (put-text-property pos (1- (point)) 'syntax-table nil) 411 'syntax-multiline t)
402 (when (eq (char-before (1- (point))) ?$) 412 ;;
403 (put-text-property (- (point) 2) (1- (point)) 413 (when (< (point) limit)
404 'syntax-table '(1))) 414 (put-text-property (point) (1+ (point))
405 (put-text-property (1- (point)) (point) 415 'syntax-table
406 'syntax-table (if close '(15) '(7))))))) 416 (if (assoc (char-after)
407 417 perl-quote-like-pairs)
408 (setq state (parse-partial-sexp (point) limit nil nil state 418 ;; Put an `e' in the cdr to mark this
409 'syntax-table)))) 419 ;; char as "second arg starter".
410 ;; Tell font-lock that this needs not further processing. 420 (string-to-syntax "|e")
411 nil) 421 (string-to-syntax "\"e")))
412 422 (forward-char 1)
423 ;; Re-use perl-syntax-propertize-special-constructs to handle the
424 ;; second part (the first delimiter of second part can't be
425 ;; preceded by "s" or "tr" or "y", so it will not be considered
426 ;; as twoarg).
427 (perl-syntax-propertize-special-constructs limit)))))))))
428
429(defun perl-font-lock-syntactic-face-function (state)
430 (cond
431 ((and (nth 3 state)
432 (eq ?e (cdr-safe (get-text-property (nth 8 state) 'syntax-table)))
433 ;; This is a second-arg of s{..}{...} form; let's check if this second
434 ;; arg is executable code rather than a string. For that, we need to
435 ;; look for an "e" after this second arg, so we have to hunt for the
436 ;; end of the arg. Depending on whether the whole arg has already
437 ;; been syntax-propertized or not, the end-char will have different
438 ;; syntaxes, so let's ignore syntax-properties temporarily so we can
439 ;; pretend it has not been syntax-propertized yet.
440 (let* ((parse-sexp-lookup-properties nil)
441 (char (char-after (nth 8 state)))
442 (paired (assq char perl-quote-like-pairs)))
443 (with-syntax-table (perl-quote-syntax-table char)
444 (save-excursion
445 (if (not paired)
446 (parse-partial-sexp (point) (point-max)
447 nil nil state 'syntax-table)
448 (condition-case nil
449 (progn
450 (goto-char (1+ (nth 8 state)))
451 (up-list 1))
452 (scan-error (goto-char (point-max)))))
453 (put-text-property (nth 8 state) (point)
454 'jit-lock-defer-multiline t)
455 (looking-at "[ \t]*\\sw*e")))))
456 nil)
457 (t (funcall (default-value 'font-lock-syntactic-face-function) state))))
413 458
414(defcustom perl-indent-level 4 459(defcustom perl-indent-level 4
415 "*Indentation of Perl statements with respect to containing block." 460 "*Indentation of Perl statements with respect to containing block."
@@ -574,9 +619,12 @@ Turning on Perl mode runs the normal hook `perl-mode-hook'."
574 perl-font-lock-keywords-1 619 perl-font-lock-keywords-1
575 perl-font-lock-keywords-2) 620 perl-font-lock-keywords-2)
576 nil nil ((?\_ . "w")) nil 621 nil nil ((?\_ . "w")) nil
577 (font-lock-syntactic-keywords 622 (font-lock-syntactic-face-function
578 . perl-font-lock-syntactic-keywords) 623 . perl-font-lock-syntactic-face-function)))
579 (parse-sexp-lookup-properties . t))) 624 (set (make-local-variable 'syntax-propertize-function)
625 #'perl-syntax-propertize-function)
626 (add-hook 'syntax-propertize-extend-region-functions
627 #'syntax-propertize-multiline 'append 'local)
580 ;; Tell imenu how to handle Perl. 628 ;; Tell imenu how to handle Perl.
581 (set (make-local-variable 'imenu-generic-expression) 629 (set (make-local-variable 'imenu-generic-expression)
582 perl-imenu-generic-expression) 630 perl-imenu-generic-expression)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 2f65ffa1e17..10e852223ce 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -166,29 +166,32 @@
166 symbol-end) 166 symbol-end)
167 . font-lock-builtin-face))) 167 . font-lock-builtin-face)))
168 168
169(defconst python-font-lock-syntactic-keywords 169(defconst python-syntax-propertize-function
170 ;; Make outer chars of matching triple-quote sequences into generic 170 ;; Make outer chars of matching triple-quote sequences into generic
171 ;; string delimiters. Fixme: Is there a better way? 171 ;; string delimiters. Fixme: Is there a better way?
172 ;; First avoid a sequence preceded by an odd number of backslashes. 172 ;; First avoid a sequence preceded by an odd number of backslashes.
173 `((,(rx (not (any ?\\)) 173 (syntax-propertize-rules
174 ?\\ (* (and ?\\ ?\\)) 174 (;; (rx (not (any ?\\))
175 (group (syntax string-quote)) 175 ;; ?\\ (* (and ?\\ ?\\))
176 (backref 1) 176 ;; (group (syntax string-quote))
177 (group (backref 1))) 177 ;; (backref 1)
178 (2 ,(string-to-syntax "\""))) ; dummy 178 ;; (group (backref 1)))
179 (,(rx (group (optional (any "uUrR"))) ; prefix gets syntax property 179 ;; ¡Backrefs don't work in syntax-propertize-rules!
180 (optional (any "rR")) ; possible second prefix 180 "[^\\]\\\\\\(\\\\\\\\\\)*\\(?:''\\('\\)\\|\"\"\\(?2:\"\\)\\)"
181 (group (syntax string-quote)) ; maybe gets property 181 (2 "\"")) ; dummy
182 (backref 2) ; per first quote 182 (;; (rx (optional (group (any "uUrR"))) ; prefix gets syntax property
183 (group (backref 2))) ; maybe gets property 183 ;; (optional (any "rR")) ; possible second prefix
184 (1 (python-quote-syntax 1)) 184 ;; (group (syntax string-quote)) ; maybe gets property
185 (2 (python-quote-syntax 2)) 185 ;; (backref 2) ; per first quote
186 (3 (python-quote-syntax 3))) 186 ;; (group (backref 2))) ; maybe gets property
187 ;; This doesn't really help. 187 ;; ¡Backrefs don't work in syntax-propertize-rules!
188;;; (,(rx (and ?\\ (group ?\n))) (1 " ")) 188 "\\([RUru]\\)?[Rr]?\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)"
189 )) 189 (3 (ignore (python-quote-syntax))))
190 190 ;; This doesn't really help.
191(defun python-quote-syntax (n) 191 ;;((rx (and ?\\ (group ?\n))) (1 " "))
192 ))
193
194(defun python-quote-syntax ()
192 "Put `syntax-table' property correctly on triple quote. 195 "Put `syntax-table' property correctly on triple quote.
193Used for syntactic keywords. N is the match number (1, 2 or 3)." 196Used for syntactic keywords. N is the match number (1, 2 or 3)."
194 ;; Given a triple quote, we have to check the context to know 197 ;; Given a triple quote, we have to check the context to know
@@ -206,28 +209,25 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
206 ;; x '"""' x """ \"""" x 209 ;; x '"""' x """ \"""" x
207 (save-excursion 210 (save-excursion
208 (goto-char (match-beginning 0)) 211 (goto-char (match-beginning 0))
209 (cond 212 (let ((syntax (save-match-data (syntax-ppss))))
210 ;; Consider property for the last char if in a fenced string. 213 (cond
211 ((= n 3) 214 ((eq t (nth 3 syntax)) ; after unclosed fence
212 (let* ((font-lock-syntactic-keywords nil) 215 ;; Consider property for the last char if in a fenced string.
213 (syntax (syntax-ppss))) 216 (goto-char (nth 8 syntax)) ; fence position
214 (when (eq t (nth 3 syntax)) ; after unclosed fence 217 (skip-chars-forward "uUrR") ; skip any prefix
215 (goto-char (nth 8 syntax)) ; fence position 218 ;; Is it a matching sequence?
216 (skip-chars-forward "uUrR") ; skip any prefix 219 (if (eq (char-after) (char-after (match-beginning 2)))
217 ;; Is it a matching sequence? 220 (put-text-property (match-beginning 3) (match-end 3)
218 (if (eq (char-after) (char-after (match-beginning 2))) 221 'syntax-table (string-to-syntax "|"))))
219 (eval-when-compile (string-to-syntax "|")))))) 222 ((match-end 1)
220 ;; Consider property for initial char, accounting for prefixes. 223 ;; Consider property for initial char, accounting for prefixes.
221 ((or (and (= n 2) ; leading quote (not prefix) 224 (put-text-property (match-beginning 1) (match-end 1)
222 (= (match-beginning 1) (match-end 1))) ; prefix is null 225 'syntax-table (string-to-syntax "|")))
223 (and (= n 1) ; prefix 226 (t
224 (/= (match-beginning 1) (match-end 1)))) ; non-empty 227 ;; Consider property for initial char, accounting for prefixes.
225 (let ((font-lock-syntactic-keywords nil)) 228 (put-text-property (match-beginning 2) (match-end 2)
226 (unless (eq 'string (syntax-ppss-context (syntax-ppss))) 229 'syntax-table (string-to-syntax "|"))))
227 (eval-when-compile (string-to-syntax "|"))))) 230 )))
228 ;; Otherwise (we're in a non-matching string) the property is
229 ;; nil, which is OK.
230 )))
231 231
232;; This isn't currently in `font-lock-defaults' as probably not worth 232;; This isn't currently in `font-lock-defaults' as probably not worth
233;; it -- we basically only mess with a few normally-symbol characters. 233;; it -- we basically only mess with a few normally-symbol characters.
@@ -2495,12 +2495,12 @@ with skeleton expansions for compound statement templates.
2495 :group 'python 2495 :group 'python
2496 (set (make-local-variable 'font-lock-defaults) 2496 (set (make-local-variable 'font-lock-defaults)
2497 '(python-font-lock-keywords nil nil nil nil 2497 '(python-font-lock-keywords nil nil nil nil
2498 (font-lock-syntactic-keywords 2498 ;; This probably isn't worth it.
2499 . python-font-lock-syntactic-keywords) 2499 ;; (font-lock-syntactic-face-function
2500 ;; This probably isn't worth it. 2500 ;; . python-font-lock-syntactic-face-function)
2501 ;; (font-lock-syntactic-face-function 2501 ))
2502 ;; . python-font-lock-syntactic-face-function) 2502 (set (make-local-variable 'syntax-propertize-function)
2503 )) 2503 python-syntax-propertize-function)
2504 (set (make-local-variable 'parse-sexp-lookup-properties) t) 2504 (set (make-local-variable 'parse-sexp-lookup-properties) t)
2505 (set (make-local-variable 'parse-sexp-ignore-comments) t) 2505 (set (make-local-variable 'parse-sexp-ignore-comments) t)
2506 (set (make-local-variable 'comment-start) "# ") 2506 (set (make-local-variable 'comment-start) "# ")
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 0b92234bf1c..4d015de5198 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -100,17 +100,10 @@
100 100
101(defconst ruby-block-end-re "\\<end\\>") 101(defconst ruby-block-end-re "\\<end\\>")
102 102
103(defconst ruby-here-doc-beg-re 103(eval-and-compile
104 (defconst ruby-here-doc-beg-re
104 "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" 105 "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
105 "Regexp to match the beginning of a heredoc.") 106 "Regexp to match the beginning of a heredoc."))
106
107(defconst ruby-here-doc-end-re
108 "^\\([ \t]+\\)?\\(.*\\)\\(.\\)$"
109 "Regexp to match the end of heredocs.
110
111This will actually match any line with one or more characters.
112It's useful in that it divides up the match string so that
113`ruby-here-doc-beg-match' can search for the beginning of the heredoc.")
114 107
115(defun ruby-here-doc-end-match () 108(defun ruby-here-doc-end-match ()
116 "Return a regexp to find the end of a heredoc. 109 "Return a regexp to find the end of a heredoc.
@@ -123,18 +116,6 @@ This should only be called after matching against `ruby-here-doc-beg-re'."
123 (match-string 5) 116 (match-string 5)
124 (match-string 6))))) 117 (match-string 6)))))
125 118
126(defun ruby-here-doc-beg-match ()
127 "Return a regexp to find the beginning of a heredoc.
128
129This should only be called after matching against `ruby-here-doc-end-re'."
130 (let ((contents (regexp-quote (concat (match-string 2) (match-string 3)))))
131 (concat "<<"
132 (let ((match (match-string 1)))
133 (if (and match (> (length match) 0))
134 (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" (match-string 1) "\\)"
135 contents "\\b\\(\\1\\|\\2\\)")
136 (concat "-?\\([\"']\\|\\)" contents "\\b\\1"))))))
137
138(defconst ruby-delimiter 119(defconst ruby-delimiter
139 (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\(" 120 (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
140 ruby-block-beg-re 121 ruby-block-beg-re
@@ -362,7 +343,7 @@ Also ignores spaces after parenthesis when 'space."
362 (back-to-indentation) 343 (back-to-indentation)
363 (current-column))) 344 (current-column)))
364 345
365(defun ruby-indent-line (&optional flag) 346(defun ruby-indent-line (&optional ignored)
366 "Correct the indentation of the current Ruby line." 347 "Correct the indentation of the current Ruby line."
367 (interactive) 348 (interactive)
368 (ruby-indent-to (ruby-calculate-indent))) 349 (ruby-indent-to (ruby-calculate-indent)))
@@ -405,8 +386,7 @@ and `\\' when preceded by `?'."
405 "TODO: document." 386 "TODO: document."
406 (save-excursion 387 (save-excursion
407 (store-match-data nil) 388 (store-match-data nil)
408 (let ((space (skip-chars-backward " \t")) 389 (let ((space (skip-chars-backward " \t")))
409 (start (point)))
410 (cond 390 (cond
411 ((bolp) t) 391 ((bolp) t)
412 ((progn 392 ((progn
@@ -700,7 +680,7 @@ and `\\' when preceded by `?'."
700 (beginning-of-line) 680 (beginning-of-line)
701 (let ((ruby-indent-point (point)) 681 (let ((ruby-indent-point (point))
702 (case-fold-search nil) 682 (case-fold-search nil)
703 state bol eol begin op-end 683 state eol begin op-end
704 (paren (progn (skip-syntax-forward " ") 684 (paren (progn (skip-syntax-forward " ")
705 (and (char-after) (matching-paren (char-after))))) 685 (and (char-after) (matching-paren (char-after)))))
706 (indent 0)) 686 (indent 0))
@@ -780,7 +760,6 @@ and `\\' when preceded by `?'."
780 (if (re-search-forward "^\\s *#" end t) 760 (if (re-search-forward "^\\s *#" end t)
781 (beginning-of-line) 761 (beginning-of-line)
782 (setq done t)))) 762 (setq done t))))
783 (setq bol (point))
784 (end-of-line) 763 (end-of-line)
785 ;; skip the comment at the end 764 ;; skip the comment at the end
786 (skip-chars-backward " \t") 765 (skip-chars-backward " \t")
@@ -1037,10 +1016,8 @@ With ARG, do it many times. Negative ARG means move forward."
1037 (ruby-beginning-of-defun) 1016 (ruby-beginning-of-defun)
1038 (re-search-backward "^\n" (- (point) 1) t)) 1017 (re-search-backward "^\n" (- (point) 1) t))
1039 1018
1040(defun ruby-indent-exp (&optional shutup-p) 1019(defun ruby-indent-exp (&optional ignored)
1041 "Indent each line in the balanced expression following the point. 1020 "Indent each line in the balanced expression following the point."
1042If a prefix arg is given or SHUTUP-P is non-nil, no errors
1043are signalled if a balanced expression isn't found."
1044 (interactive "*P") 1021 (interactive "*P")
1045 (let ((here (point-marker)) start top column (nest t)) 1022 (let ((here (point-marker)) start top column (nest t))
1046 (set-marker-insertion-type here t) 1023 (set-marker-insertion-type here t)
@@ -1133,58 +1110,208 @@ See `add-log-current-defun-function'."
1133 (if mlist (concat mlist mname) mname) 1110 (if mlist (concat mlist mname) mname)
1134 mlist))))) 1111 mlist)))))
1135 1112
1136(defconst ruby-font-lock-syntactic-keywords 1113(if (eval-when-compile (fboundp #'syntax-propertize-rules))
1137 `(;; #{ }, #$hoge, #@foo are not comments 1114 ;; New code that works independently from font-lock.
1138 ("\\(#\\)[{$@]" 1 (1 . nil)) 1115 (progn
1139 ;; the last $', $", $` in the respective string is not variable 1116 (defun ruby-syntax-propertize-function (start end)
1140 ;; the last ?', ?", ?` in the respective string is not ascii code 1117 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
1141 ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)" 1118 (goto-char start)
1142 (2 (7 . nil)) 1119 (ruby-syntax-propertize-heredoc end)
1143 (4 (7 . nil))) 1120 (funcall
1144 ;; $' $" $` .... are variables 1121 (syntax-propertize-rules
1145 ;; ?' ?" ?` are ascii codes 1122 ;; #{ }, #$hoge, #@foo are not comments
1146 ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil)) 1123 ("\\(#\\)[{$@]" (1 "."))
1147 ;; regexps 1124 ;; the last $', $", $` in the respective string is not variable
1148 ("\\(^\\|[=(,~?:;<>]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)" 1125 ;; the last ?', ?", ?` in the respective string is not ascii code
1149 (4 (7 . ?/)) 1126 ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
1150 (6 (7 . ?/))) 1127 (2 "\"")
1151 ("^=en\\(d\\)\\_>" 1 "!") 1128 (4 "\""))
1152 ("^\\(=\\)begin\\_>" 1 (ruby-comment-beg-syntax)) 1129 ;; $' $" $` .... are variables
1153 ;; Currently, the following case is highlighted incorrectly: 1130 ;; ?' ?" ?` are ascii codes
1154 ;; 1131 ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" (3 "."))
1155 ;; <<FOO 1132 ;; regexps
1156 ;; FOO 1133 ("\\(^\\|[=(,~?:;<>]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
1157 ;; <<BAR 1134 (4 "\"/")
1158 ;; <<BAZ 1135 (6 "\"/"))
1159 ;; BAZ 1136 ("^=en\\(d\\)\\_>" (1 "!"))
1160 ;; BAR 1137 ("^\\(=\\)begin\\_>" (1 "!"))
1161 ;; 1138 ;; Handle here documents.
1162 ;; This is because all here-doc beginnings are highlighted before any endings, 1139 ((concat ruby-here-doc-beg-re ".*\\(\n\\)")
1163 ;; so although <<BAR is properly marked as a beginning, when we get to <<BAZ 1140 (7 (prog1 "\"" (ruby-syntax-propertize-heredoc end)))))
1164 ;; it thinks <<BAR is part of a string so it's marked as well. 1141 (point) end))
1165 ;; 1142
1166 ;; This may be fixable by modifying ruby-in-here-doc-p to use 1143 (defun ruby-syntax-propertize-heredoc (limit)
1167 ;; ruby-in-non-here-doc-string-p rather than syntax-ppss-context, 1144 (let ((ppss (syntax-ppss))
1168 ;; but I don't want to try that until we've got unit tests set up 1145 (res '()))
1169 ;; to make sure I don't break anything else. 1146 (when (eq ?\n (nth 3 ppss))
1170 (,(concat ruby-here-doc-beg-re ".*\\(\n\\)") 1147 (save-excursion
1171 ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re)) 1148 (goto-char (nth 8 ppss))
1172 (ruby-here-doc-beg-syntax)) 1149 (beginning-of-line)
1173 (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax))) 1150 (while (re-search-forward ruby-here-doc-beg-re
1174 "Syntactic keywords for Ruby mode. See `font-lock-syntactic-keywords'.") 1151 (line-end-position) t)
1175 1152 (push (concat (ruby-here-doc-end-match) "\n") res)))
1176(defun ruby-comment-beg-syntax () 1153 (let ((start (point)))
1177 "Return the syntax cell for a the first character of a =begin. 1154 ;; With multiple openers on the same line, we don't know in which
1155 ;; part `start' is, so we have to go back to the beginning.
1156 (when (cdr res)
1157 (goto-char (nth 8 ppss))
1158 (setq res (nreverse res)))
1159 (while (and res (re-search-forward (pop res) limit 'move))
1160 (if (null res)
1161 (put-text-property (1- (point)) (point)
1162 'syntax-table (string-to-syntax "\""))))
1163 ;; Make extra sure we don't move back, lest we could fall into an
1164 ;; inf-loop.
1165 (if (< (point) start) (goto-char start))))))
1166 )
1167
1168 ;; For Emacsen where syntax-propertize-rules is not (yet) available,
1169 ;; fallback on the old font-lock-syntactic-keywords stuff.
1170
1171 (defconst ruby-here-doc-end-re
1172 "^\\([ \t]+\\)?\\(.*\\)\\(\n\\)"
1173 "Regexp to match the end of heredocs.
1174
1175This will actually match any line with one or more characters.
1176It's useful in that it divides up the match string so that
1177`ruby-here-doc-beg-match' can search for the beginning of the heredoc.")
1178
1179 (defun ruby-here-doc-beg-match ()
1180 "Return a regexp to find the beginning of a heredoc.
1181
1182This should only be called after matching against `ruby-here-doc-end-re'."
1183 (let ((contents (regexp-quote (match-string 2))))
1184 (concat "<<"
1185 (let ((match (match-string 1)))
1186 (if (and match (> (length match) 0))
1187 (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" match "\\)"
1188 contents "\\b\\(\\1\\|\\2\\)")
1189 (concat "-?\\([\"']\\|\\)" contents "\\b\\1"))))))
1190
1191 (defconst ruby-font-lock-syntactic-keywords
1192 `( ;; #{ }, #$hoge, #@foo are not comments
1193 ("\\(#\\)[{$@]" 1 (1 . nil))
1194 ;; the last $', $", $` in the respective string is not variable
1195 ;; the last ?', ?", ?` in the respective string is not ascii code
1196 ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
1197 (2 (7 . nil))
1198 (4 (7 . nil)))
1199 ;; $' $" $` .... are variables
1200 ;; ?' ?" ?` are ascii codes
1201 ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil))
1202 ;; regexps
1203 ("\\(^\\|[=(,~?:;<>]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
1204 (4 (7 . ?/))
1205 (6 (7 . ?/)))
1206 ("^=en\\(d\\)\\_>" 1 "!")
1207 ("^\\(=\\)begin\\_>" 1 (ruby-comment-beg-syntax))
1208 ;; Currently, the following case is highlighted incorrectly:
1209 ;;
1210 ;; <<FOO
1211 ;; FOO
1212 ;; <<BAR
1213 ;; <<BAZ
1214 ;; BAZ
1215 ;; BAR
1216 ;;
1217 ;; This is because all here-doc beginnings are highlighted before any endings,
1218 ;; so although <<BAR is properly marked as a beginning, when we get to <<BAZ
1219 ;; it thinks <<BAR is part of a string so it's marked as well.
1220 ;;
1221 ;; This may be fixable by modifying ruby-in-here-doc-p to use
1222 ;; ruby-in-non-here-doc-string-p rather than syntax-ppss-context,
1223 ;; but I don't want to try that until we've got unit tests set up
1224 ;; to make sure I don't break anything else.
1225 (,(concat ruby-here-doc-beg-re ".*\\(\n\\)")
1226 ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re))
1227 (ruby-here-doc-beg-syntax))
1228 (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax)))
1229 "Syntactic keywords for Ruby mode. See `font-lock-syntactic-keywords'.")
1230
1231 (defun ruby-comment-beg-syntax ()
1232 "Return the syntax cell for a the first character of a =begin.
1178See the definition of `ruby-font-lock-syntactic-keywords'. 1233See the definition of `ruby-font-lock-syntactic-keywords'.
1179 1234
1180This returns a comment-delimiter cell as long as the =begin 1235This returns a comment-delimiter cell as long as the =begin
1181isn't in a string or another comment." 1236isn't in a string or another comment."
1182 (when (not (nth 3 (syntax-ppss))) 1237 (when (not (nth 3 (syntax-ppss)))
1183 (string-to-syntax "!"))) 1238 (string-to-syntax "!")))
1239
1240 (defun ruby-in-here-doc-p ()
1241 "Return whether or not the point is in a heredoc."
1242 (save-excursion
1243 (let ((old-point (point)) (case-fold-search nil))
1244 (beginning-of-line)
1245 (catch 'found-beg
1246 (while (re-search-backward ruby-here-doc-beg-re nil t)
1247 (if (not (or (ruby-in-ppss-context-p 'anything)
1248 (ruby-here-doc-find-end old-point)))
1249 (throw 'found-beg t)))))))
1250
1251 (defun ruby-here-doc-find-end (&optional limit)
1252 "Expects the point to be on a line with one or more heredoc openers.
1253Returns the buffer position at which all heredocs on the line
1254are terminated, or nil if they aren't terminated before the
1255buffer position `limit' or the end of the buffer."
1256 (save-excursion
1257 (beginning-of-line)
1258 (catch 'done
1259 (let ((eol (save-excursion (end-of-line) (point)))
1260 (case-fold-search nil)
1261 ;; Fake match data such that (match-end 0) is at eol
1262 (end-match-data (progn (looking-at ".*$") (match-data)))
1263 beg-match-data end-re)
1264 (while (re-search-forward ruby-here-doc-beg-re eol t)
1265 (setq beg-match-data (match-data))
1266 (setq end-re (ruby-here-doc-end-match))
1267
1268 (set-match-data end-match-data)
1269 (goto-char (match-end 0))
1270 (unless (re-search-forward end-re limit t) (throw 'done nil))
1271 (setq end-match-data (match-data))
1272
1273 (set-match-data beg-match-data)
1274 (goto-char (match-end 0)))
1275 (set-match-data end-match-data)
1276 (goto-char (match-end 0))
1277 (point)))))
1278
1279 (defun ruby-here-doc-beg-syntax ()
1280 "Return the syntax cell for a line that may begin a heredoc.
1281See the definition of `ruby-font-lock-syntactic-keywords'.
1282
1283This sets the syntax cell for the newline ending the line
1284containing the heredoc beginning so that cases where multiple
1285heredocs are started on one line are handled correctly."
1286 (save-excursion
1287 (goto-char (match-beginning 0))
1288 (unless (or (ruby-in-ppss-context-p 'non-heredoc)
1289 (ruby-in-here-doc-p))
1290 (string-to-syntax "\""))))
1291
1292 (defun ruby-here-doc-end-syntax ()
1293 "Return the syntax cell for a line that may end a heredoc.
1294See the definition of `ruby-font-lock-syntactic-keywords'."
1295 (let ((pss (syntax-ppss)) (case-fold-search nil))
1296 ;; If we aren't in a string, we definitely aren't ending a heredoc,
1297 ;; so we can just give up.
1298 ;; This means we aren't doing a full-document search
1299 ;; every time we enter a character.
1300 (when (ruby-in-ppss-context-p 'heredoc pss)
1301 (save-excursion
1302 (goto-char (nth 8 pss)) ; Go to the beginning of heredoc.
1303 (let ((eol (point)))
1304 (beginning-of-line)
1305 (if (and (re-search-forward (ruby-here-doc-beg-match) eol t) ; If there is a heredoc that matches this line...
1306 (not (ruby-in-ppss-context-p 'anything)) ; And that's not inside a heredoc/string/comment...
1307 (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
1308 (not (re-search-forward ruby-here-doc-beg-re eol t))))
1309 (string-to-syntax "\"")))))))
1184 1310
1185(unless (functionp 'syntax-ppss) 1311 (unless (functionp 'syntax-ppss)
1186 (defun syntax-ppss (&optional pos) 1312 (defun syntax-ppss (&optional pos)
1187 (parse-partial-sexp (point-min) (or pos (point))))) 1313 (parse-partial-sexp (point-min) (or pos (point)))))
1314 )
1188 1315
1189(defun ruby-in-ppss-context-p (context &optional ppss) 1316(defun ruby-in-ppss-context-p (context &optional ppss)
1190 (let ((ppss (or ppss (syntax-ppss (point))))) 1317 (let ((ppss (or ppss (syntax-ppss (point)))))
@@ -1195,10 +1322,7 @@ isn't in a string or another comment."
1195 ((eq context 'string) 1322 ((eq context 'string)
1196 (nth 3 ppss)) 1323 (nth 3 ppss))
1197 ((eq context 'heredoc) 1324 ((eq context 'heredoc)
1198 (and (nth 3 ppss) 1325 (eq ?\n (nth 3 ppss)))
1199 ;; If it's generic string, it's a heredoc and we don't care
1200 ;; See `parse-partial-sexp'
1201 (not (numberp (nth 3 ppss)))))
1202 ((eq context 'non-heredoc) 1326 ((eq context 'non-heredoc)
1203 (and (ruby-in-ppss-context-p 'anything) 1327 (and (ruby-in-ppss-context-p 'anything)
1204 (not (ruby-in-ppss-context-p 'heredoc)))) 1328 (not (ruby-in-ppss-context-p 'heredoc))))
@@ -1210,77 +1334,6 @@ isn't in a string or another comment."
1210 "context name `" (symbol-name context) "' is unknown")))) 1334 "context name `" (symbol-name context) "' is unknown"))))
1211 t))) 1335 t)))
1212 1336
1213(defun ruby-in-here-doc-p ()
1214 "Return whether or not the point is in a heredoc."
1215 (save-excursion
1216 (let ((old-point (point)) (case-fold-search nil))
1217 (beginning-of-line)
1218 (catch 'found-beg
1219 (while (re-search-backward ruby-here-doc-beg-re nil t)
1220 (if (not (or (ruby-in-ppss-context-p 'anything)
1221 (ruby-here-doc-find-end old-point)))
1222 (throw 'found-beg t)))))))
1223
1224(defun ruby-here-doc-find-end (&optional limit)
1225 "Expects the point to be on a line with one or more heredoc openers.
1226Returns the buffer position at which all heredocs on the line
1227are terminated, or nil if they aren't terminated before the
1228buffer position `limit' or the end of the buffer."
1229 (save-excursion
1230 (beginning-of-line)
1231 (catch 'done
1232 (let ((eol (save-excursion (end-of-line) (point)))
1233 (case-fold-search nil)
1234 ;; Fake match data such that (match-end 0) is at eol
1235 (end-match-data (progn (looking-at ".*$") (match-data)))
1236 beg-match-data end-re)
1237 (while (re-search-forward ruby-here-doc-beg-re eol t)
1238 (setq beg-match-data (match-data))
1239 (setq end-re (ruby-here-doc-end-match))
1240
1241 (set-match-data end-match-data)
1242 (goto-char (match-end 0))
1243 (unless (re-search-forward end-re limit t) (throw 'done nil))
1244 (setq end-match-data (match-data))
1245
1246 (set-match-data beg-match-data)
1247 (goto-char (match-end 0)))
1248 (set-match-data end-match-data)
1249 (goto-char (match-end 0))
1250 (point)))))
1251
1252(defun ruby-here-doc-beg-syntax ()
1253 "Return the syntax cell for a line that may begin a heredoc.
1254See the definition of `ruby-font-lock-syntactic-keywords'.
1255
1256This sets the syntax cell for the newline ending the line
1257containing the heredoc beginning so that cases where multiple
1258heredocs are started on one line are handled correctly."
1259 (save-excursion
1260 (goto-char (match-beginning 0))
1261 (unless (or (ruby-in-ppss-context-p 'non-heredoc)
1262 (ruby-in-here-doc-p))
1263 (string-to-syntax "|"))))
1264
1265(defun ruby-here-doc-end-syntax ()
1266 "Return the syntax cell for a line that may end a heredoc.
1267See the definition of `ruby-font-lock-syntactic-keywords'."
1268 (let ((pss (syntax-ppss)) (case-fold-search nil))
1269 ;; If we aren't in a string, we definitely aren't ending a heredoc,
1270 ;; so we can just give up.
1271 ;; This means we aren't doing a full-document search
1272 ;; every time we enter a character.
1273 (when (ruby-in-ppss-context-p 'heredoc pss)
1274 (save-excursion
1275 (goto-char (nth 8 pss)) ; Go to the beginning of heredoc.
1276 (let ((eol (point)))
1277 (beginning-of-line)
1278 (if (and (re-search-forward (ruby-here-doc-beg-match) eol t) ; If there is a heredoc that matches this line...
1279 (not (ruby-in-ppss-context-p 'anything)) ; And that's not inside a heredoc/string/comment...
1280 (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
1281 (not (re-search-forward ruby-here-doc-beg-re eol t))))
1282 (string-to-syntax "|")))))))
1283
1284(if (featurep 'xemacs) 1337(if (featurep 'xemacs)
1285 (put 'ruby-mode 'font-lock-defaults 1338 (put 'ruby-mode 'font-lock-defaults
1286 '((ruby-font-lock-keywords) 1339 '((ruby-font-lock-keywords)
@@ -1377,8 +1430,10 @@ See `font-lock-syntax-table'.")
1377 ) 1430 )
1378 "Additional expressions to highlight in Ruby mode.") 1431 "Additional expressions to highlight in Ruby mode.")
1379 1432
1433(defvar electric-indent-chars)
1434
1380;;;###autoload 1435;;;###autoload
1381(defun ruby-mode () 1436(define-derived-mode ruby-mode prog-mode "Ruby"
1382 "Major mode for editing Ruby scripts. 1437 "Major mode for editing Ruby scripts.
1383\\[ruby-indent-line] properly indents subexpressions of multi-line 1438\\[ruby-indent-line] properly indents subexpressions of multi-line
1384class, module, def, if, while, for, do, and case statements, taking 1439class, module, def, if, while, for, do, and case statements, taking
@@ -1387,27 +1442,22 @@ nesting into account.
1387The variable `ruby-indent-level' controls the amount of indentation. 1442The variable `ruby-indent-level' controls the amount of indentation.
1388 1443
1389\\{ruby-mode-map}" 1444\\{ruby-mode-map}"
1390 (interactive)
1391 (kill-all-local-variables)
1392 (use-local-map ruby-mode-map)
1393 (setq mode-name "Ruby")
1394 (setq major-mode 'ruby-mode)
1395 (ruby-mode-variables) 1445 (ruby-mode-variables)
1396 1446
1397 (set (make-local-variable 'indent-line-function)
1398 'ruby-indent-line)
1399 (set (make-local-variable 'imenu-create-index-function) 1447 (set (make-local-variable 'imenu-create-index-function)
1400 'ruby-imenu-create-index) 1448 'ruby-imenu-create-index)
1401 (set (make-local-variable 'add-log-current-defun-function) 1449 (set (make-local-variable 'add-log-current-defun-function)
1402 'ruby-add-log-current-method) 1450 'ruby-add-log-current-method)
1403 1451
1404 (add-hook 1452 (add-hook
1405 (cond ((boundp 'before-save-hook) 1453 (cond ((boundp 'before-save-hook) 'before-save-hook)
1406 (make-local-variable 'before-save-hook)
1407 'before-save-hook)
1408 ((boundp 'write-contents-functions) 'write-contents-functions) 1454 ((boundp 'write-contents-functions) 'write-contents-functions)
1409 ((boundp 'write-contents-hooks) 'write-contents-hooks)) 1455 ((boundp 'write-contents-hooks) 'write-contents-hooks))
1410 'ruby-mode-set-encoding) 1456 'ruby-mode-set-encoding nil 'local)
1457
1458 (set (make-local-variable 'electric-indent-chars)
1459 (append '(?\{ ?\}) (if (boundp 'electric-indent-chars)
1460 (default-value 'electric-indent-chars))))
1411 1461
1412 (set (make-local-variable 'font-lock-defaults) 1462 (set (make-local-variable 'font-lock-defaults)
1413 '((ruby-font-lock-keywords) nil nil)) 1463 '((ruby-font-lock-keywords) nil nil))
@@ -1415,12 +1465,12 @@ The variable `ruby-indent-level' controls the amount of indentation.
1415 ruby-font-lock-keywords) 1465 ruby-font-lock-keywords)
1416 (set (make-local-variable 'font-lock-syntax-table) 1466 (set (make-local-variable 'font-lock-syntax-table)
1417 ruby-font-lock-syntax-table) 1467 ruby-font-lock-syntax-table)
1418 (set (make-local-variable 'font-lock-syntactic-keywords)
1419 ruby-font-lock-syntactic-keywords)
1420 1468
1421 (if (fboundp 'run-mode-hooks) 1469 (if (eval-when-compile (fboundp 'syntax-propertize-rules))
1422 (run-mode-hooks 'ruby-mode-hook) 1470 (set (make-local-variable 'syntax-propertize-function)
1423 (run-hooks 'ruby-mode-hook))) 1471 #'ruby-syntax-propertize-function)
1472 (set (make-local-variable 'font-lock-syntactic-keywords)
1473 ruby-font-lock-syntactic-keywords)))
1424 1474
1425;;; Invoke ruby-mode when appropriate 1475;;; Invoke ruby-mode when appropriate
1426 1476
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 9041bd50259..d41a81e38a6 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -939,7 +939,6 @@ See `sh-feature'.")
939;; These are used for the syntax table stuff (derived from cperl-mode). 939;; These are used for the syntax table stuff (derived from cperl-mode).
940;; Note: parse-sexp-lookup-properties must be set to t for it to work. 940;; Note: parse-sexp-lookup-properties must be set to t for it to work.
941(defconst sh-st-punc (string-to-syntax ".")) 941(defconst sh-st-punc (string-to-syntax "."))
942(defconst sh-st-symbol (string-to-syntax "_"))
943(defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string 942(defconst sh-here-doc-syntax (string-to-syntax "|")) ;; generic string
944 943
945(defconst sh-escaped-line-re 944(defconst sh-escaped-line-re
@@ -957,7 +956,7 @@ See `sh-feature'.")
957(defvar sh-here-doc-re sh-here-doc-open-re) 956(defvar sh-here-doc-re sh-here-doc-open-re)
958(make-variable-buffer-local 'sh-here-doc-re) 957(make-variable-buffer-local 'sh-here-doc-re)
959 958
960(defun sh-font-lock-close-heredoc (bol eof indented) 959(defun sh-font-lock-close-heredoc (bol eof indented eol)
961 "Determine the syntax of the \\n after an EOF. 960 "Determine the syntax of the \\n after an EOF.
962If non-nil INDENTED indicates that the EOF was indented." 961If non-nil INDENTED indicates that the EOF was indented."
963 (let* ((eof-re (if eof (regexp-quote eof) "")) 962 (let* ((eof-re (if eof (regexp-quote eof) ""))
@@ -971,6 +970,8 @@ If non-nil INDENTED indicates that the EOF was indented."
971 (ere (concat "^" (if indented "[ \t]*") eof-re "\n")) 970 (ere (concat "^" (if indented "[ \t]*") eof-re "\n"))
972 (start (save-excursion 971 (start (save-excursion
973 (goto-char bol) 972 (goto-char bol)
973 ;; FIXME: will incorrectly find a <<EOF embedded inside
974 ;; the heredoc.
974 (re-search-backward (concat sre "\\|" ere) nil t)))) 975 (re-search-backward (concat sre "\\|" ere) nil t))))
975 ;; If subgroup 1 matched, we found an open-heredoc, otherwise we first 976 ;; If subgroup 1 matched, we found an open-heredoc, otherwise we first
976 ;; found a close-heredoc which makes the current close-heredoc inoperant. 977 ;; found a close-heredoc which makes the current close-heredoc inoperant.
@@ -990,7 +991,7 @@ If non-nil INDENTED indicates that the EOF was indented."
990 (sh-in-comment-or-string (point))))) 991 (sh-in-comment-or-string (point)))))
991 ;; No <<EOF2 found after our <<. 992 ;; No <<EOF2 found after our <<.
992 (= (point) start))) 993 (= (point) start)))
993 sh-here-doc-syntax) 994 (put-text-property eol (1+ eol) 'syntax-table sh-here-doc-syntax))
994 ((not (or start (save-excursion (re-search-forward sre nil t)))) 995 ((not (or start (save-excursion (re-search-forward sre nil t))))
995 ;; There's no <<EOF either before or after us, 996 ;; There's no <<EOF either before or after us,
996 ;; so we should remove ourselves from font-lock's keywords. 997 ;; so we should remove ourselves from font-lock's keywords.
@@ -1000,7 +1001,7 @@ If non-nil INDENTED indicates that the EOF was indented."
1000 (regexp-opt sh-here-doc-markers t) "\\(\n\\)")) 1001 (regexp-opt sh-here-doc-markers t) "\\(\n\\)"))
1001 nil)))) 1002 nil))))
1002 1003
1003(defun sh-font-lock-open-heredoc (start string) 1004(defun sh-font-lock-open-heredoc (start string eol)
1004 "Determine the syntax of the \\n after a <<EOF. 1005 "Determine the syntax of the \\n after a <<EOF.
1005START is the position of <<. 1006START is the position of <<.
1006STRING is the actual word used as delimiter (e.g. \"EOF\"). 1007STRING is the actual word used as delimiter (e.g. \"EOF\").
@@ -1030,13 +1031,8 @@ Point is at the beginning of the next line."
1030 ;; Don't bother fixing it now, but place a multiline property so 1031 ;; Don't bother fixing it now, but place a multiline property so
1031 ;; that when jit-lock-context-* refontifies the rest of the 1032 ;; that when jit-lock-context-* refontifies the rest of the
1032 ;; buffer, it also refontifies the current line with it. 1033 ;; buffer, it also refontifies the current line with it.
1033 (put-text-property start (point) 'font-lock-multiline t))) 1034 (put-text-property start (point) 'syntax-multiline t)))
1034 sh-here-doc-syntax)) 1035 (put-text-property eol (1+ eol) 'syntax-table sh-here-doc-syntax)))
1035
1036(defun sh-font-lock-here-doc (limit)
1037 "Search for a heredoc marker."
1038 ;; This looks silly, but it's because `sh-here-doc-re' keeps changing.
1039 (re-search-forward sh-here-doc-re limit t))
1040 1036
1041(defun sh-font-lock-quoted-subshell (limit) 1037(defun sh-font-lock-quoted-subshell (limit)
1042 "Search for a subshell embedded in a string. 1038 "Search for a subshell embedded in a string.
@@ -1045,9 +1041,7 @@ subshells can nest."
1045 ;; FIXME: This can (and often does) match multiple lines, yet it makes no 1041 ;; FIXME: This can (and often does) match multiple lines, yet it makes no
1046 ;; effort to handle multiline cases correctly, so it ends up being 1042 ;; effort to handle multiline cases correctly, so it ends up being
1047 ;; rather flakey. 1043 ;; rather flakey.
1048 (when (and (re-search-forward "\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(?:\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)" limit t) 1044 (when (eq ?\" (nth 3 (syntax-ppss))) ; Check we matched an opening quote.
1049 ;; Make sure the " we matched is an opening quote.
1050 (eq ?\" (nth 3 (syntax-ppss))))
1051 ;; bingo we have a $( or a ` inside a "" 1045 ;; bingo we have a $( or a ` inside a ""
1052 (let ((char (char-after (point))) 1046 (let ((char (char-after (point)))
1053 ;; `state' can be: double-quote, backquote, code. 1047 ;; `state' can be: double-quote, backquote, code.
@@ -1082,8 +1076,7 @@ subshells can nest."
1082 (double-quote nil) 1076 (double-quote nil)
1083 (t (setq state (pop states))))) 1077 (t (setq state (pop states)))))
1084 (t (error "Internal error in sh-font-lock-quoted-subshell"))) 1078 (t (error "Internal error in sh-font-lock-quoted-subshell")))
1085 (forward-char 1))) 1079 (forward-char 1)))))
1086 t))
1087 1080
1088 1081
1089(defun sh-is-quoted-p (pos) 1082(defun sh-is-quoted-p (pos)
@@ -1122,7 +1115,7 @@ subshells can nest."
1122 (when (progn (backward-char 2) 1115 (when (progn (backward-char 2)
1123 (if (> start (line-end-position)) 1116 (if (> start (line-end-position))
1124 (put-text-property (point) (1+ start) 1117 (put-text-property (point) (1+ start)
1125 'font-lock-multiline t)) 1118 'syntax-multiline t))
1126 ;; FIXME: The `in' may just be a random argument to 1119 ;; FIXME: The `in' may just be a random argument to
1127 ;; a normal command rather than the real `in' keyword. 1120 ;; a normal command rather than the real `in' keyword.
1128 ;; I.e. we should look back to try and find the 1121 ;; I.e. we should look back to try and find the
@@ -1136,40 +1129,44 @@ subshells can nest."
1136 sh-st-punc 1129 sh-st-punc
1137 nil)) 1130 nil))
1138 1131
1139(defun sh-font-lock-flush-syntax-ppss-cache (limit) 1132(defun sh-syntax-propertize-function (start end)
1140 ;; This should probably be a standard function provided by font-lock.el 1133 (goto-char start)
1141 ;; (or syntax.el). 1134 (while (prog1
1142 (syntax-ppss-flush-cache (point)) 1135 (re-search-forward sh-here-doc-re end 'move)
1143 (goto-char limit) 1136 (save-excursion
1144 nil) 1137 (save-match-data
1145 1138 (funcall
1146(defconst sh-font-lock-syntactic-keywords 1139 (syntax-propertize-rules
1147 ;; A `#' begins a comment when it is unquoted and at the beginning of a 1140 ;; A `#' begins a comment when it is unquoted and at the
1148 ;; word. In the shell, words are separated by metacharacters. 1141 ;; beginning of a word. In the shell, words are separated by
1149 ;; The list of special chars is taken from the single-unix spec 1142 ;; metacharacters. The list of special chars is taken from
1150 ;; of the shell command language (under `quoting') but with `$' removed. 1143 ;; the single-unix spec of the shell command language (under
1151 `(("[^|&;<>()`\\\"' \t\n]\\(#+\\)" 1 ,sh-st-symbol) 1144 ;; `quoting') but with `$' removed.
1152 ;; In a '...' the backslash is not escaping. 1145 ("[^|&;<>()`\\\"' \t\n]\\(#+\\)" (1 "_"))
1153 ("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote))) 1146 ;; In a '...' the backslash is not escaping.
1154 ;; The previous rule uses syntax-ppss, but the subsequent rules may 1147 ("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote)))
1155 ;; change the syntax, so we have to tell syntax-ppss that the states it 1148 ;; Make sure $@ and $? are correctly recognized as sexps.
1156 ;; has just computed will need to be recomputed. 1149 ("\\$\\([?@]\\)" (1 "_"))
1157 (sh-font-lock-flush-syntax-ppss-cache) 1150 ;; Distinguish the special close-paren in `case'.
1158 ;; Make sure $@ and $? are correctly recognized as sexps. 1151 (")" (0 (sh-font-lock-paren (match-beginning 0))))
1159 ("\\$\\([?@]\\)" 1 ,sh-st-symbol) 1152 ;; Highlight (possibly nested) subshells inside "" quoted
1160 ;; Find HEREDOC starters and add a corresponding rule for the ender. 1153 ;; regions correctly.
1161 (sh-font-lock-here-doc 1154 ("\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(?:\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)"
1162 (2 (sh-font-lock-open-heredoc 1155 (1 (ignore
1163 (match-beginning 0) (match-string 1)) nil t) 1156 ;; Save excursion because we want to also apply other
1164 (5 (sh-font-lock-close-heredoc 1157 ;; syntax-propertize rules within the affected region.
1165 (match-beginning 0) (match-string 4) 1158 (save-excursion
1166 (and (match-beginning 3) (/= (match-beginning 3) (match-end 3)))) 1159 (sh-font-lock-quoted-subshell end))))))
1167 nil t)) 1160 (prog1 start (setq start (point))) (point)))))
1168 ;; Distinguish the special close-paren in `case'. 1161 (if (match-beginning 2)
1169 (")" 0 (sh-font-lock-paren (match-beginning 0))) 1162 ;; FIXME: actually, once we see an heredoc opener, we should just
1170 ;; highlight (possibly nested) subshells inside "" quoted regions correctly. 1163 ;; search for its ender without propertizing anything in it.
1171 ;; This should be at the very end because it uses syntax-ppss. 1164 (sh-font-lock-open-heredoc
1172 (sh-font-lock-quoted-subshell))) 1165 (match-beginning 0) (match-string 1) (match-beginning 2))
1166 (sh-font-lock-close-heredoc
1167 (match-beginning 0) (match-string 4)
1168 (and (match-beginning 3) (/= (match-beginning 3) (match-end 3)))
1169 (match-beginning 5)))))
1173 1170
1174(defun sh-font-lock-syntactic-face-function (state) 1171(defun sh-font-lock-syntactic-face-function (state)
1175 (let ((q (nth 3 state))) 1172 (let ((q (nth 3 state)))
@@ -1553,9 +1550,12 @@ with your script for an edit-interpret-debug cycle."
1553 sh-font-lock-keywords-1 sh-font-lock-keywords-2) 1550 sh-font-lock-keywords-1 sh-font-lock-keywords-2)
1554 nil nil 1551 nil nil
1555 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil 1552 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
1556 (font-lock-syntactic-keywords . sh-font-lock-syntactic-keywords)
1557 (font-lock-syntactic-face-function 1553 (font-lock-syntactic-face-function
1558 . sh-font-lock-syntactic-face-function))) 1554 . sh-font-lock-syntactic-face-function)))
1555 (set (make-local-variable 'syntax-propertize-function)
1556 #'sh-syntax-propertize-function)
1557 (add-hook 'syntax-propertize-extend-region-functions
1558 #'syntax-propertize-multiline 'append 'local)
1559 (set (make-local-variable 'skeleton-pair-alist) '((?` _ ?`))) 1559 (set (make-local-variable 'skeleton-pair-alist) '((?` _ ?`)))
1560 (set (make-local-variable 'skeleton-pair-filter-function) 'sh-quoted-p) 1560 (set (make-local-variable 'skeleton-pair-filter-function) 'sh-quoted-p)
1561 (set (make-local-variable 'skeleton-further-elements) 1561 (set (make-local-variable 'skeleton-further-elements)
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index f8d1a6aca97..34c50b6cfe5 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -163,17 +163,18 @@ for SIMULA mode to function correctly."
163(defvar simula-mode-syntax-table nil 163(defvar simula-mode-syntax-table nil
164 "Syntax table in SIMULA mode buffers.") 164 "Syntax table in SIMULA mode buffers.")
165 165
166(defconst simula-font-lock-syntactic-keywords 166(defconst simula-syntax-propertize-function
167 `(;; `comment' directive. 167 (syntax-propertize-rules
168 ("\\<\\(c\\)omment\\>" 1 "<") 168 ;; `comment' directive.
169 ;; end comments 169 ("\\<\\(c\\)omment\\>" (1 "<"))
170 (,(concat "\\<end\\>\\([^;\n]\\).*?\\(\n\\|\\(.\\)\\(;\\|" 170 ;; end comments
171 (regexp-opt '("end" "else" "when" "otherwise")) 171 ((concat "\\<end\\>\\([^;\n]\\).*?\\(\n\\|\\(.\\)\\(;\\|"
172 "\\)\\)") 172 (regexp-opt '("end" "else" "when" "otherwise"))
173 (1 "< b") 173 "\\)\\)")
174 (3 "> b" nil t)) 174 (1 "< b")
175 ;; non-quoted single-quote char. 175 (3 "> b"))
176 ("'\\('\\)'" 1 "."))) 176 ;; non-quoted single-quote char.
177 ("'\\('\\)'" (1 "."))))
177 178
178;; Regexps written with help from Alf-Ivar Holm <alfh@ifi.uio.no>. 179;; Regexps written with help from Alf-Ivar Holm <alfh@ifi.uio.no>.
179(defconst simula-font-lock-keywords-1 180(defconst simula-font-lock-keywords-1
@@ -396,8 +397,9 @@ with no arguments, if that value is non-nil."
396 (setq font-lock-defaults 397 (setq font-lock-defaults
397 '((simula-font-lock-keywords simula-font-lock-keywords-1 398 '((simula-font-lock-keywords simula-font-lock-keywords-1
398 simula-font-lock-keywords-2 simula-font-lock-keywords-3) 399 simula-font-lock-keywords-2 simula-font-lock-keywords-3)
399 nil t ((?_ . "w")) nil 400 nil t ((?_ . "w"))))
400 (font-lock-syntactic-keywords . simula-font-lock-syntactic-keywords))) 401 (set (make-local-variable 'syntax-propertize-function)
402 simula-syntax-propertize-function)
401 (abbrev-mode 1)) 403 (abbrev-mode 1))
402 404
403(defun simula-indent-exp () 405(defun simula-indent-exp ()
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index e44504688f2..e9860c5fa71 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -5,7 +5,7 @@
5 5
6;; Author: Alex Schroeder <alex@gnu.org> 6;; Author: Alex Schroeder <alex@gnu.org>
7;; Maintainer: Michael Mauger <mmaug@yahoo.com> 7;; Maintainer: Michael Mauger <mmaug@yahoo.com>
8;; Version: 2.5 8;; Version: 2.7
9;; Keywords: comm languages processes 9;; Keywords: comm languages processes
10;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el 10;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el
11;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode 11;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode
@@ -187,10 +187,10 @@
187 187
188;; 6) Define a convienence function to invoke the SQL interpreter. 188;; 6) Define a convienence function to invoke the SQL interpreter.
189 189
190;; (defun my-sql-xyz () 190;; (defun my-sql-xyz (&optional buffer)
191;; "Run ixyz by XyzDB as an inferior process." 191;; "Run ixyz by XyzDB as an inferior process."
192;; (interactive) 192;; (interactive "P")
193;; (sql-product-interactive 'xyz)) 193;; (sql-product-interactive 'xyz buffer))
194 194
195;;; To Do: 195;;; To Do:
196 196
@@ -275,8 +275,8 @@ Customizing your password will store it in your ~/.emacs file."
275 :group 'SQL 275 :group 'SQL
276 :safe 'stringp) 276 :safe 'stringp)
277 277
278(defcustom sql-port nil 278(defcustom sql-port 0
279 "Default server or host." 279 "Default port."
280 :version "24.1" 280 :version "24.1"
281 :type 'number 281 :type 'number
282 :group 'SQL 282 :group 'SQL
@@ -430,9 +430,9 @@ Customizing your password will store it in your ~/.emacs file."
430 :sqli-comint-func sql-comint-postgres 430 :sqli-comint-func sql-comint-postgres
431 :prompt-regexp "^.*=[#>] " 431 :prompt-regexp "^.*=[#>] "
432 :prompt-length 5 432 :prompt-length 5
433 :prompt-cont-regexp "^.*-[#>] " 433 :prompt-cont-regexp "^.*[-(][#>] "
434 :input-filter sql-remove-tabs-filter 434 :input-filter sql-remove-tabs-filter
435 :terminator ("\\(^[\\]g\\|;\\)" . ";")) 435 :terminator ("\\(^\\s-*\\\\g\\|;\\)" . ";"))
436 436
437 (solid 437 (solid
438 :name "Solid" 438 :name "Solid"
@@ -551,7 +551,6 @@ settings.")
551(defvar sql-indirect-features 551(defvar sql-indirect-features
552 '(:font-lock :sqli-program :sqli-options :sqli-login)) 552 '(:font-lock :sqli-program :sqli-options :sqli-login))
553 553
554;;;###autoload
555(defcustom sql-connection-alist nil 554(defcustom sql-connection-alist nil
556 "An alist of connection parameters for interacting with a SQL 555 "An alist of connection parameters for interacting with a SQL
557 product. 556 product.
@@ -600,7 +599,6 @@ prompted for during login."
600 :version "24.1" 599 :version "24.1"
601 :group 'SQL) 600 :group 'SQL)
602 601
603;;;###autoload
604(defcustom sql-product 'ansi 602(defcustom sql-product 'ansi
605 "Select the SQL database product used so that buffers can be 603 "Select the SQL database product used so that buffers can be
606highlighted properly when you open them." 604highlighted properly when you open them."
@@ -613,6 +611,7 @@ highlighted properly when you open them."
613 sql-product-alist)) 611 sql-product-alist))
614 :group 'SQL 612 :group 'SQL
615 :safe 'symbolp) 613 :safe 'symbolp)
614(defvaralias 'sql-dialect 'sql-product)
616 615
617;; misc customization of sql.el behaviour 616;; misc customization of sql.el behaviour
618 617
@@ -788,7 +787,9 @@ to be safe:
788 787
789;; Customization for SQLite 788;; Customization for SQLite
790 789
791(defcustom sql-sqlite-program "sqlite3" 790(defcustom sql-sqlite-program (or (executable-find "sqlite3")
791 (executable-find "sqlite")
792 "sqlite")
792 "Command to start SQLite. 793 "Command to start SQLite.
793 794
794Starts `sql-interactive-mode' after doing some setup." 795Starts `sql-interactive-mode' after doing some setup."
@@ -801,7 +802,7 @@ Starts `sql-interactive-mode' after doing some setup."
801 :version "20.8" 802 :version "20.8"
802 :group 'SQL) 803 :group 'SQL)
803 804
804(defcustom sql-sqlite-login-params '((database :file ".*\\.db")) 805(defcustom sql-sqlite-login-params '((database :file ".*\\.\\(db\\|sqlite[23]?\\)"))
805 "List of login parameters needed to connect to SQLite." 806 "List of login parameters needed to connect to SQLite."
806 :type 'sql-login-params 807 :type 'sql-login-params
807 :version "24.1" 808 :version "24.1"
@@ -1022,9 +1023,6 @@ Starts `sql-interactive-mode' after doing some setup."
1022(defvar sql-server-history nil 1023(defvar sql-server-history nil
1023 "History of servers used.") 1024 "History of servers used.")
1024 1025
1025(defvar sql-port-history nil
1026 "History of ports used.")
1027
1028;; Passwords are not kept in a history. 1026;; Passwords are not kept in a history.
1029 1027
1030(defvar sql-buffer nil 1028(defvar sql-buffer nil
@@ -1054,6 +1052,25 @@ You can change `sql-prompt-length' on `sql-interactive-mode-hook'.")
1054 1052
1055Used by `sql-rename-buffer'.") 1053Used by `sql-rename-buffer'.")
1056 1054
1055(defun sql-buffer-live-p (buffer &optional product)
1056 "Returns non-nil if the process associated with buffer is live.
1057
1058BUFFER can be a buffer object or a buffer name. The buffer must
1059be a live buffer, have an running process attached to it, be in
1060`sql-interactive-mode', and, if PRODUCT is specified, it's
1061`sql-product' must match."
1062
1063 (when buffer
1064 (setq buffer (get-buffer buffer))
1065 (and buffer
1066 (buffer-live-p buffer)
1067 (get-buffer-process buffer)
1068 (comint-check-proc buffer)
1069 (with-current-buffer buffer
1070 (and (derived-mode-p 'sql-product-interactive)
1071 (or (not product)
1072 (eq product sql-product)))))))
1073
1057;; Keymap for sql-interactive-mode. 1074;; Keymap for sql-interactive-mode.
1058 1075
1059(defvar sql-interactive-mode-map 1076(defvar sql-interactive-mode-map
@@ -1091,15 +1108,11 @@ Based on `comint-mode-map'.")
1091 sql-mode-menu sql-mode-map 1108 sql-mode-menu sql-mode-map
1092 "Menu for `sql-mode'." 1109 "Menu for `sql-mode'."
1093 `("SQL" 1110 `("SQL"
1094 ["Send Paragraph" sql-send-paragraph (and (buffer-live-p sql-buffer) 1111 ["Send Paragraph" sql-send-paragraph (sql-buffer-live-p sql-buffer)]
1095 (get-buffer-process sql-buffer))]
1096 ["Send Region" sql-send-region (and mark-active 1112 ["Send Region" sql-send-region (and mark-active
1097 (buffer-live-p sql-buffer) 1113 (sql-buffer-live-p sql-buffer))]
1098 (get-buffer-process sql-buffer))] 1114 ["Send Buffer" sql-send-buffer (sql-buffer-live-p sql-buffer)]
1099 ["Send Buffer" sql-send-buffer (and (buffer-live-p sql-buffer) 1115 ["Send String" sql-send-string (sql-buffer-live-p sql-buffer)]
1100 (get-buffer-process sql-buffer))]
1101 ["Send String" sql-send-string (and (buffer-live-p sql-buffer)
1102 (get-buffer-process sql-buffer))]
1103 "--" 1116 "--"
1104 ["Start SQLi session" sql-product-interactive 1117 ["Start SQLi session" sql-product-interactive
1105 :visible (not sql-connection-alist) 1118 :visible (not sql-connection-alist)
@@ -1364,7 +1377,7 @@ to add functions and PL/SQL keywords.")
1364 ;; Oracle SQL*Plus Commands 1377 ;; Oracle SQL*Plus Commands
1365 (cons 1378 (cons
1366 (concat 1379 (concat
1367 "^\\(?:\\(?:" (regexp-opt '( 1380 "^\\s-*\\(?:\\(?:" (regexp-opt '(
1368"@" "@@" "accept" "append" "archive" "attribute" "break" 1381"@" "@@" "accept" "append" "archive" "attribute" "break"
1369"btitle" "change" "clear" "column" "connect" "copy" "define" 1382"btitle" "change" "clear" "column" "connect" "copy" "define"
1370"del" "describe" "disconnect" "edit" "execute" "exit" "get" "help" 1383"del" "describe" "disconnect" "edit" "execute" "exit" "get" "help"
@@ -1403,7 +1416,7 @@ to add functions and PL/SQL keywords.")
1403 "\\)\\b.*" 1416 "\\)\\b.*"
1404 ) 1417 )
1405 'font-lock-doc-face) 1418 'font-lock-doc-face)
1406 '("^[ \t]*rem\\(?:ark\\)?.*" . font-lock-comment-face) 1419 '("^\\s-*rem\\(?:ark\\)?\\>.*" . font-lock-comment-face)
1407 1420
1408 ;; Oracle Functions 1421 ;; Oracle Functions
1409 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil 1422 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
@@ -1585,81 +1598,153 @@ to add functions and PL/SQL keywords.")
1585(defvar sql-mode-postgres-font-lock-keywords 1598(defvar sql-mode-postgres-font-lock-keywords
1586 (eval-when-compile 1599 (eval-when-compile
1587 (list 1600 (list
1588 ;; Postgres Functions 1601 ;; Postgres psql commands
1602 '("^\\s-*\\\\.*$" . font-lock-doc-face)
1603
1604 ;; Postgres unreserved words but may have meaning
1605 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil "a"
1606"abs" "absent" "according" "ada" "alias" "allocate" "are" "array_agg"
1607"asensitive" "atomic" "attribute" "attributes" "avg" "base64"
1608"bernoulli" "bit_length" "bitvar" "blob" "blocked" "bom" "breadth" "c"
1609"call" "cardinality" "catalog_name" "ceil" "ceiling" "char_length"
1610"character_length" "character_set_catalog" "character_set_name"
1611"character_set_schema" "characters" "checked" "class_origin" "clob"
1612"cobol" "collation" "collation_catalog" "collation_name"
1613"collation_schema" "collect" "column_name" "columns"
1614"command_function" "command_function_code" "completion" "condition"
1615"condition_number" "connect" "connection_name" "constraint_catalog"
1616"constraint_name" "constraint_schema" "constructor" "contains"
1617"control" "convert" "corr" "corresponding" "count" "covar_pop"
1618"covar_samp" "cube" "cume_dist" "current_default_transform_group"
1619"current_path" "current_transform_group_for_type" "cursor_name"
1620"datalink" "datetime_interval_code" "datetime_interval_precision" "db"
1621"defined" "degree" "dense_rank" "depth" "deref" "derived" "describe"
1622"descriptor" "destroy" "destructor" "deterministic" "diagnostics"
1623"disconnect" "dispatch" "dlnewcopy" "dlpreviouscopy" "dlurlcomplete"
1624"dlurlcompleteonly" "dlurlcompletewrite" "dlurlpath" "dlurlpathonly"
1625"dlurlpathwrite" "dlurlscheme" "dlurlserver" "dlvalue" "dynamic"
1626"dynamic_function" "dynamic_function_code" "element" "empty"
1627"end-exec" "equals" "every" "exception" "exec" "existing" "exp" "file"
1628"filter" "final" "first_value" "flag" "floor" "fortran" "found" "free"
1629"fs" "fusion" "g" "general" "generated" "get" "go" "goto" "grouping"
1630"hex" "hierarchy" "host" "id" "ignore" "implementation" "import"
1631"indent" "indicator" "infix" "initialize" "instance" "instantiable"
1632"integrity" "intersection" "iterate" "k" "key_member" "key_type" "lag"
1633"last_value" "lateral" "lead" "length" "less" "library" "like_regex"
1634"link" "ln" "locator" "lower" "m" "map" "matched" "max"
1635"max_cardinality" "member" "merge" "message_length"
1636"message_octet_length" "message_text" "method" "min" "mod" "modifies"
1637"modify" "module" "more" "multiset" "mumps" "namespace" "nclob"
1638"nesting" "new" "nfc" "nfd" "nfkc" "nfkd" "nil" "normalize"
1639"normalized" "nth_value" "ntile" "nullable" "number"
1640"occurrences_regex" "octet_length" "octets" "old" "open" "operation"
1641"ordering" "ordinality" "others" "output" "overriding" "p" "pad"
1642"parameter" "parameter_mode" "parameter_name"
1643"parameter_ordinal_position" "parameter_specific_catalog"
1644"parameter_specific_name" "parameter_specific_schema" "parameters"
1645"pascal" "passing" "passthrough" "percent_rank" "percentile_cont"
1646"percentile_disc" "permission" "pli" "position_regex" "postfix"
1647"power" "prefix" "preorder" "public" "rank" "reads" "recovery" "ref"
1648"referencing" "regr_avgx" "regr_avgy" "regr_count" "regr_intercept"
1649"regr_r2" "regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "requiring"
1650"respect" "restore" "result" "return" "returned_cardinality"
1651"returned_length" "returned_octet_length" "returned_sqlstate" "rollup"
1652"routine" "routine_catalog" "routine_name" "routine_schema"
1653"row_count" "row_number" "scale" "schema_name" "scope" "scope_catalog"
1654"scope_name" "scope_schema" "section" "selective" "self" "sensitive"
1655"server_name" "sets" "size" "source" "space" "specific"
1656"specific_name" "specifictype" "sql" "sqlcode" "sqlerror"
1657"sqlexception" "sqlstate" "sqlwarning" "sqrt" "state" "static"
1658"stddev_pop" "stddev_samp" "structure" "style" "subclass_origin"
1659"sublist" "submultiset" "substring_regex" "sum" "system_user" "t"
1660"table_name" "tablesample" "terminate" "than" "ties" "timezone_hour"
1661"timezone_minute" "token" "top_level_count" "transaction_active"
1662"transactions_committed" "transactions_rolled_back" "transform"
1663"transforms" "translate" "translate_regex" "translation"
1664"trigger_catalog" "trigger_name" "trigger_schema" "trim_array"
1665"uescape" "under" "unlink" "unnamed" "unnest" "untyped" "upper" "uri"
1666"usage" "user_defined_type_catalog" "user_defined_type_code"
1667"user_defined_type_name" "user_defined_type_schema" "var_pop"
1668"var_samp" "varbinary" "variable" "whenever" "width_bucket" "within"
1669"xmlagg" "xmlbinary" "xmlcast" "xmlcomment" "xmldeclaration"
1670"xmldocument" "xmlexists" "xmliterate" "xmlnamespaces" "xmlquery"
1671"xmlschema" "xmltable" "xmltext" "xmlvalidate"
1672)
1673
1674 ;; Postgres non-reserved words
1589 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil 1675 (sql-font-lock-keywords-builder 'font-lock-builtin-face nil
1590"abbrev" "abs" "acos" "age" "area" "ascii" "asin" "atab2" "atan" 1676"abort" "absolute" "access" "action" "add" "admin" "after" "aggregate"
1591"atan2" "avg" "bit_length" "both" "broadcast" "btrim" "cbrt" "ceil" 1677"also" "alter" "always" "assertion" "assignment" "at" "backward"
1592"center" "char_length" "chr" "coalesce" "col_description" "convert" 1678"before" "begin" "between" "by" "cache" "called" "cascade" "cascaded"
1593"cos" "cot" "count" "current_database" "current_date" "current_schema" 1679"catalog" "chain" "characteristics" "checkpoint" "class" "close"
1594"current_schemas" "current_setting" "current_time" "current_timestamp" 1680"cluster" "coalesce" "comment" "comments" "commit" "committed"
1595"current_user" "currval" "date_part" "date_trunc" "decode" "degrees" 1681"configuration" "connection" "constraints" "content" "continue"
1596"diameter" "encode" "exp" "extract" "floor" "get_bit" "get_byte" 1682"conversion" "copy" "cost" "createdb" "createrole" "createuser" "csv"
1597"has_database_privilege" "has_function_privilege" 1683"current" "cursor" "cycle" "data" "database" "day" "deallocate" "dec"
1598"has_language_privilege" "has_schema_privilege" "has_table_privilege" 1684"declare" "defaults" "deferred" "definer" "delete" "delimiter"
1599"height" "host" "initcap" "isclosed" "isfinite" "isopen" "leading" 1685"delimiters" "dictionary" "disable" "discard" "document" "domain"
1600"length" "ln" "localtime" "localtimestamp" "log" "lower" "lpad" 1686"drop" "each" "enable" "encoding" "encrypted" "enum" "escape"
1601"ltrim" "masklen" "max" "min" "mod" "netmask" "network" "nextval" 1687"exclude" "excluding" "exclusive" "execute" "exists" "explain"
1602"now" "npoints" "nullif" "obj_description" "octet_length" "overlay" 1688"external" "extract" "family" "first" "float" "following" "force"
1603"pclose" "pg_client_encoding" "pg_function_is_visible" 1689"forward" "function" "functions" "global" "granted" "greatest"
1604"pg_get_constraintdef" "pg_get_indexdef" "pg_get_ruledef" 1690"handler" "header" "hold" "hour" "identity" "if" "immediate"
1605"pg_get_userbyid" "pg_get_viewdef" "pg_opclass_is_visible" 1691"immutable" "implicit" "including" "increment" "index" "indexes"
1606"pg_operator_is_visible" "pg_table_is_visible" "pg_type_is_visible" 1692"inherit" "inherits" "inline" "inout" "input" "insensitive" "insert"
1607"pi" "popen" "position" "pow" "quote_ident" "quote_literal" "radians" 1693"instead" "invoker" "isolation" "key" "language" "large" "last"
1608"radius" "random" "repeat" "replace" "round" "rpad" "rtrim" 1694"lc_collate" "lc_ctype" "least" "level" "listen" "load" "local"
1609"session_user" "set_bit" "set_byte" "set_config" "set_masklen" 1695"location" "lock" "login" "mapping" "match" "maxvalue" "minute"
1610"setval" "sign" "sin" "split_part" "sqrt" "stddev" "strpos" "substr" 1696"minvalue" "mode" "month" "move" "name" "names" "national" "nchar"
1611"substring" "sum" "tan" "timeofday" "to_ascii" "to_char" "to_date" 1697"next" "no" "nocreatedb" "nocreaterole" "nocreateuser" "noinherit"
1612"to_hex" "to_number" "to_timestamp" "trailing" "translate" "trim" 1698"nologin" "none" "nosuperuser" "nothing" "notify" "nowait" "nullif"
1613"trunc" "upper" "variance" "version" "width" 1699"nulls" "object" "of" "oids" "operator" "option" "options" "out"
1700"overlay" "owned" "owner" "parser" "partial" "partition" "password"
1701"plans" "position" "preceding" "prepare" "prepared" "preserve" "prior"
1702"privileges" "procedural" "procedure" "quote" "range" "read"
1703"reassign" "recheck" "recursive" "reindex" "relative" "release"
1704"rename" "repeatable" "replace" "replica" "reset" "restart" "restrict"
1705"returns" "revoke" "role" "rollback" "row" "rows" "rule" "savepoint"
1706"schema" "scroll" "search" "second" "security" "sequence" "sequences"
1707"serializable" "server" "session" "set" "setof" "share" "show"
1708"simple" "stable" "standalone" "start" "statement" "statistics"
1709"stdin" "stdout" "storage" "strict" "strip" "substring" "superuser"
1710"sysid" "system" "tables" "tablespace" "temp" "template" "temporary"
1711"transaction" "treat" "trigger" "trim" "truncate" "trusted" "type"
1712"unbounded" "uncommitted" "unencrypted" "unknown" "unlisten" "until"
1713"update" "vacuum" "valid" "validator" "value" "values" "version"
1714"view" "volatile" "whitespace" "work" "wrapper" "write"
1715"xmlattributes" "xmlconcat" "xmlelement" "xmlforest" "xmlparse"
1716"xmlpi" "xmlroot" "xmlserialize" "year" "yes"
1614) 1717)
1718
1615 ;; Postgres Reserved 1719 ;; Postgres Reserved
1616 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil 1720 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1617"abort" "access" "add" "after" "aggregate" "alignment" "all" "alter" 1721"all" "analyse" "analyze" "and" "any" "array" "asc" "as" "asymmetric"
1618"analyze" "and" "any" "as" "asc" "assignment" "authorization" 1722"authorization" "binary" "both" "case" "cast" "check" "collate"
1619"backward" "basetype" "before" "begin" "between" "binary" "by" "cache" 1723"column" "concurrently" "constraint" "create" "cross"
1620"called" "cascade" "case" "cast" "characteristics" "check" 1724"current_catalog" "current_date" "current_role" "current_schema"
1621"checkpoint" "class" "close" "cluster" "column" "comment" "commit" 1725"current_time" "current_timestamp" "current_user" "default"
1622"committed" "commutator" "constraint" "constraints" "conversion" 1726"deferrable" "desc" "distinct" "do" "else" "end" "except" "false"
1623"copy" "create" "createdb" "createuser" "cursor" "cycle" "database" 1727"fetch" "foreign" "for" "freeze" "from" "full" "grant" "group"
1624"deallocate" "declare" "default" "deferrable" "deferred" "definer" 1728"having" "ilike" "initially" "inner" "in" "intersect" "into" "isnull"
1625"delete" "delimiter" "desc" "distinct" "do" "domain" "drop" "each" 1729"is" "join" "leading" "left" "like" "limit" "localtime"
1626"element" "else" "encoding" "encrypted" "end" "escape" "except" 1730"localtimestamp" "natural" "notnull" "not" "null" "off" "offset"
1627"exclusive" "execute" "exists" "explain" "extended" "external" "false" 1731"only" "on" "order" "or" "outer" "overlaps" "over" "placing" "primary"
1628"fetch" "finalfunc" "for" "force" "foreign" "forward" "freeze" "from" 1732"references" "returning" "right" "select" "session_user" "similar"
1629"full" "function" "grant" "group" "gtcmp" "handler" "hashes" "having" 1733"some" "symmetric" "table" "then" "to" "trailing" "true" "union"
1630"immediate" "immutable" "implicit" "in" "increment" "index" "inherits" 1734"unique" "user" "using" "variadic" "verbose" "when" "where" "window"
1631"initcond" "initially" "input" "insensitive" "insert" "instead" 1735"with"
1632"internallength" "intersect" "into" "invoker" "is" "isnull"
1633"isolation" "join" "key" "language" "leftarg" "level" "like" "limit"
1634"listen" "load" "local" "location" "lock" "ltcmp" "main" "match"
1635"maxvalue" "merges" "minvalue" "mode" "move" "natural" "negator"
1636"next" "nocreatedb" "nocreateuser" "none" "not" "nothing" "notify"
1637"notnull" "null" "of" "offset" "oids" "on" "only" "operator" "or"
1638"order" "output" "owner" "partial" "passedbyvalue" "password" "plain"
1639"prepare" "primary" "prior" "privileges" "procedural" "procedure"
1640"public" "read" "recheck" "references" "reindex" "relative" "rename"
1641"reset" "restrict" "returns" "revoke" "rightarg" "rollback" "row"
1642"rule" "schema" "scroll" "security" "select" "sequence" "serializable"
1643"session" "set" "sfunc" "share" "show" "similar" "some" "sort1"
1644"sort2" "stable" "start" "statement" "statistics" "storage" "strict"
1645"stype" "sysid" "table" "temp" "template" "temporary" "then" "to"
1646"transaction" "trigger" "true" "truncate" "trusted" "type"
1647"unencrypted" "union" "unique" "unknown" "unlisten" "until" "update"
1648"usage" "user" "using" "vacuum" "valid" "validator" "values"
1649"variable" "verbose" "view" "volatile" "when" "where" "with" "without"
1650"work"
1651) 1736)
1652 1737
1653 ;; Postgres Data Types 1738 ;; Postgres Data Types
1654 (sql-font-lock-keywords-builder 'font-lock-type-face nil 1739 (sql-font-lock-keywords-builder 'font-lock-type-face nil
1655"anyarray" "bigint" "bigserial" "bit" "boolean" "box" "bytea" "char" 1740"bigint" "bigserial" "bit" "bool" "boolean" "box" "bytea" "char"
1656"character" "cidr" "circle" "cstring" "date" "decimal" "double" 1741"character" "cidr" "circle" "date" "decimal" "double" "float4"
1657"float4" "float8" "inet" "int2" "int4" "int8" "integer" "internal" 1742"float8" "inet" "int" "int2" "int4" "int8" "integer" "interval" "line"
1658"interval" "language_handler" "line" "lseg" "macaddr" "money" 1743"lseg" "macaddr" "money" "numeric" "path" "point" "polygon"
1659"numeric" "oid" "opaque" "path" "point" "polygon" "precision" "real" 1744"precision" "real" "serial" "serial4" "serial8" "smallint" "text"
1660"record" "regclass" "regoper" "regoperator" "regproc" "regprocedure" 1745"time" "timestamp" "timestamptz" "timetz" "tsquery" "tsvector"
1661"regtype" "serial" "serial4" "serial8" "smallint" "text" "time" 1746"txid_snapshot" "uuid" "varbit" "varchar" "varying" "without"
1662"timestamp" "varchar" "varying" "void" "zone" 1747"xml" "zone"
1663))) 1748)))
1664 1749
1665 "Postgres SQL keywords used by font-lock. 1750 "Postgres SQL keywords used by font-lock.
@@ -1979,6 +2064,9 @@ you define your own `sql-mode-mysql-font-lock-keywords'.")
1979(defvar sql-mode-sqlite-font-lock-keywords 2064(defvar sql-mode-sqlite-font-lock-keywords
1980 (eval-when-compile 2065 (eval-when-compile
1981 (list 2066 (list
2067 ;; SQLite commands
2068 '("^[.].*$" . font-lock-doc-face)
2069
1982 ;; SQLite Keyword 2070 ;; SQLite Keyword
1983 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil 2071 (sql-font-lock-keywords-builder 'font-lock-keyword-face nil
1984"abort" "action" "add" "after" "all" "alter" "analyze" "and" "as" 2072"abort" "action" "add" "after" "all" "alter" "analyze" "and" "as"
@@ -2493,29 +2581,31 @@ function like this: (sql-get-login 'user 'password 'database)."
2493 2581
2494 ((eq token 'port) ; port 2582 ((eq token 'port) ; port
2495 (setq sql-port 2583 (setq sql-port
2496 (read-number "Port: " sql-port)))))) 2584 (read-number "Port: " (if (numberp sql-port)
2497 what)) 2585 sql-port
2586 0)))))))
2587 what))
2498 2588
2499(defun sql-find-sqli-buffer () 2589(defun sql-find-sqli-buffer ()
2500 "Returns the current default SQLi buffer or nil. 2590 "Returns the name of the current default SQLi buffer or nil.
2501In order to qualify, the SQLi buffer must be alive, 2591In order to qualify, the SQLi buffer must be alive, be in
2502be in `sql-interactive-mode' and have a process." 2592`sql-interactive-mode' and have a process."
2503 (let ((default-buffer (default-value 'sql-buffer))) 2593 (let ((buf sql-buffer)
2504 (if (and (buffer-live-p default-buffer) 2594 (prod sql-product))
2505 (get-buffer-process default-buffer)) 2595 (or
2506 default-buffer 2596 ;; Current sql-buffer, if there is one.
2507 (save-current-buffer 2597 (and (sql-buffer-live-p buf prod)
2508 (let ((buflist (buffer-list)) 2598 buf)
2509 (found)) 2599 ;; Global sql-buffer
2510 (while (not (or (null buflist) 2600 (and (setq buf (default-value 'sql-buffer))
2511 found)) 2601 (sql-buffer-live-p buf prod)
2512 (let ((candidate (car buflist))) 2602 buf)
2513 (set-buffer candidate) 2603 ;; Look thru each buffer
2514 (if (and (derived-mode-p 'sql-interactive-mode) 2604 (car (apply 'append
2515 (get-buffer-process candidate)) 2605 (mapcar (lambda (b)
2516 (setq found candidate)) 2606 (and (sql-buffer-live-p b prod)
2517 (setq buflist (cdr buflist)))) 2607 (list (buffer-name b))))
2518 found))))) 2608 (buffer-list)))))))
2519 2609
2520(defun sql-set-sqli-buffer-generally () 2610(defun sql-set-sqli-buffer-generally ()
2521 "Set SQLi buffer for all SQL buffers that have none. 2611 "Set SQLi buffer for all SQL buffers that have none.
@@ -2527,16 +2617,17 @@ using `sql-find-sqli-buffer'. If `sql-buffer' is set,
2527 (interactive) 2617 (interactive)
2528 (save-excursion 2618 (save-excursion
2529 (let ((buflist (buffer-list)) 2619 (let ((buflist (buffer-list))
2530 (default-sqli-buffer (sql-find-sqli-buffer))) 2620 (default-buffer (sql-find-sqli-buffer)))
2531 (setq-default sql-buffer default-sqli-buffer) 2621 (setq-default sql-buffer default-buffer)
2532 (while (not (null buflist)) 2622 (while (not (null buflist))
2533 (let ((candidate (car buflist))) 2623 (let ((candidate (car buflist)))
2534 (set-buffer candidate) 2624 (set-buffer candidate)
2535 (if (and (derived-mode-p 'sql-mode) 2625 (if (and (derived-mode-p 'sql-mode)
2536 (not (buffer-live-p sql-buffer))) 2626 (not (sql-buffer-live-p sql-buffer)))
2537 (progn 2627 (progn
2538 (setq sql-buffer default-sqli-buffer) 2628 (setq sql-buffer default-buffer)
2539 (run-hooks 'sql-set-sqli-hook)))) 2629 (when default-buffer
2630 (run-hooks 'sql-set-sqli-hook)))))
2540 (setq buflist (cdr buflist)))))) 2631 (setq buflist (cdr buflist))))))
2541 2632
2542(defun sql-set-sqli-buffer () 2633(defun sql-set-sqli-buffer ()
@@ -2554,19 +2645,13 @@ If you call it from anywhere else, it sets the global copy of
2554 (interactive) 2645 (interactive)
2555 (let ((default-buffer (sql-find-sqli-buffer))) 2646 (let ((default-buffer (sql-find-sqli-buffer)))
2556 (if (null default-buffer) 2647 (if (null default-buffer)
2557 (error "There is no suitable SQLi buffer")) 2648 (error "There is no suitable SQLi buffer")
2558 (let ((new-buffer 2649 (let ((new-buffer (read-buffer "New SQLi buffer: " default-buffer t)))
2559 (get-buffer 2650 (if (null (sql-buffer-live-p new-buffer))
2560 (read-buffer "New SQLi buffer: " default-buffer t)))) 2651 (error "Buffer %s is not a working SQLi buffer" new-buffer)
2561 (if (null (get-buffer-process new-buffer)) 2652 (when new-buffer
2562 (error "Buffer %s has no process" (buffer-name new-buffer))) 2653 (setq sql-buffer new-buffer)
2563 (if (null (with-current-buffer new-buffer 2654 (run-hooks 'sql-set-sqli-hook)))))))
2564 (equal major-mode 'sql-interactive-mode)))
2565 (error "Buffer %s is no SQLi buffer" (buffer-name new-buffer)))
2566 (if new-buffer
2567 (progn
2568 (setq sql-buffer new-buffer)
2569 (run-hooks 'sql-set-sqli-hook))))))
2570 2655
2571(defun sql-show-sqli-buffer () 2656(defun sql-show-sqli-buffer ()
2572 "Show the name of current SQLi buffer. 2657 "Show the name of current SQLi buffer.
@@ -2574,11 +2659,11 @@ If you call it from anywhere else, it sets the global copy of
2574This is the buffer SQL strings are sent to. It is stored in the 2659This is the buffer SQL strings are sent to. It is stored in the
2575variable `sql-buffer'. See `sql-help' on how to create such a buffer." 2660variable `sql-buffer'. See `sql-help' on how to create such a buffer."
2576 (interactive) 2661 (interactive)
2577 (if (null (buffer-live-p sql-buffer)) 2662 (if (null (buffer-live-p (get-buffer sql-buffer)))
2578 (message "%s has no SQLi buffer set." (buffer-name (current-buffer))) 2663 (message "%s has no SQLi buffer set." (buffer-name (current-buffer)))
2579 (if (null (get-buffer-process sql-buffer)) 2664 (if (null (get-buffer-process sql-buffer))
2580 (message "Buffer %s has no process." (buffer-name sql-buffer)) 2665 (message "Buffer %s has no process." sql-buffer)
2581 (message "Current SQLi buffer is %s." (buffer-name sql-buffer))))) 2666 (message "Current SQLi buffer is %s." sql-buffer))))
2582 2667
2583(defun sql-make-alternate-buffer-name () 2668(defun sql-make-alternate-buffer-name ()
2584 "Return a string that can be used to rename a SQLi buffer. 2669 "Return a string that can be used to rename a SQLi buffer.
@@ -2610,8 +2695,9 @@ server/database name."
2610 (unless (string= "" sql-user) 2695 (unless (string= "" sql-user)
2611 (list "/" sql-user))) 2696 (list "/" sql-user)))
2612 ((eq token 'port) 2697 ((eq token 'port)
2613 (unless (= 0 sql-port) 2698 (unless (or (not (numberp sql-port))
2614 (list ":" sql-port))) 2699 (= 0 sql-port))
2700 (list ":" (number-to-string sql-port))))
2615 ((eq token 'server) 2701 ((eq token 'server)
2616 (unless (string= "" sql-server) 2702 (unless (string= "" sql-server)
2617 (list "." 2703 (list "."
@@ -2619,7 +2705,7 @@ server/database name."
2619 (file-name-nondirectory sql-server) 2705 (file-name-nondirectory sql-server)
2620 sql-server)))) 2706 sql-server))))
2621 ((eq token 'database) 2707 ((eq token 'database)
2622 (when (string= "" sql-database) 2708 (unless (string= "" sql-database)
2623 (list "@" 2709 (list "@"
2624 (if (eq type :file) 2710 (if (eq type :file)
2625 (file-name-nondirectory sql-database) 2711 (file-name-nondirectory sql-database)
@@ -2649,10 +2735,32 @@ server/database name."
2649 ;; Use the name we've got 2735 ;; Use the name we've got
2650 name)))) 2736 name))))
2651 2737
2652(defun sql-rename-buffer () 2738(defun sql-rename-buffer (&optional new-name)
2653 "Rename a SQLi buffer." 2739 "Rename a SQL interactive buffer.
2654 (interactive) 2740
2655 (rename-buffer (format "*SQL: %s*" sql-alternate-buffer-name) t)) 2741Prompts for the new name if command is preceeded by
2742\\[universal-argument]. If no buffer name is provided, then the
2743`sql-alternate-buffer-name' is used.
2744
2745The actual buffer name set will be \"*SQL: NEW-NAME*\". If
2746NEW-NAME is empty, then the buffer name will be \"*SQL*\"."
2747 (interactive "P")
2748
2749 (if (not (derived-mode-p 'sql-interactive-mode))
2750 (message "Current buffer is not a SQL interactive buffer")
2751
2752 (setq sql-alternate-buffer-name
2753 (cond
2754 ((stringp new-name) new-name)
2755 ((consp new-name)
2756 (read-string "Buffer name (\"*SQL: XXX*\"; enter `XXX'): "
2757 sql-alternate-buffer-name))
2758 (t sql-alternate-buffer-name)))
2759
2760 (rename-buffer (if (string= "" sql-alternate-buffer-name)
2761 "*SQL*"
2762 (format "*SQL: %s*" sql-alternate-buffer-name))
2763 t)))
2656 2764
2657(defun sql-copy-column () 2765(defun sql-copy-column ()
2658 "Copy current column to the end of buffer. 2766 "Copy current column to the end of buffer.
@@ -2801,7 +2909,7 @@ to force the output from the query to appear on a new line."
2801 2909
2802 (let ((comint-input-sender-no-newline nil) 2910 (let ((comint-input-sender-no-newline nil)
2803 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str))) 2911 (s (replace-regexp-in-string "[[:space:]\n\r]+\\'" "" str)))
2804 (if (buffer-live-p sql-buffer) 2912 (if (sql-buffer-live-p sql-buffer)
2805 (progn 2913 (progn
2806 ;; Ignore the hoping around... 2914 ;; Ignore the hoping around...
2807 (save-excursion 2915 (save-excursion
@@ -2814,7 +2922,7 @@ to force the output from the query to appear on a new line."
2814 (if sql-send-terminator 2922 (if sql-send-terminator
2815 (sql-send-magic-terminator sql-buffer s sql-send-terminator)) 2923 (sql-send-magic-terminator sql-buffer s sql-send-terminator))
2816 2924
2817 (message "Sent string to buffer %s." (buffer-name sql-buffer)))) 2925 (message "Sent string to buffer %s." sql-buffer)))
2818 2926
2819 ;; Display the sql buffer 2927 ;; Display the sql buffer
2820 (if sql-pop-to-buffer-after-send-region 2928 (if sql-pop-to-buffer-after-send-region
@@ -2893,6 +3001,91 @@ If given the optional parameter VALUE, sets
2893 3001
2894 3002
2895 3003
3004;;; Redirect output functions
3005
3006(defun sql-redirect (command combuf &optional outbuf save-prior)
3007 "Execute the SQL command and send output to OUTBUF.
3008
3009COMBUF must be an active SQL interactive buffer. OUTBUF may be
3010an existing buffer, or the name of a non-existing buffer. If
3011omitted the output is sent to a temporary buffer which will be
3012killed after the command completes. COMMAND should be a string
3013of commands accepted by the SQLi program."
3014
3015 (with-current-buffer combuf
3016 (let ((buf (get-buffer-create (or outbuf " *SQL-Redirect*")))
3017 (proc (get-buffer-process (current-buffer)))
3018 (comint-prompt-regexp (sql-get-product-feature sql-product
3019 :prompt-regexp))
3020 (start nil))
3021 (with-current-buffer buf
3022 (unless save-prior
3023 (erase-buffer))
3024 (goto-char (point-max))
3025 (setq start (point)))
3026
3027 ;; Run the command
3028 (comint-redirect-send-command-to-process command buf proc nil t)
3029 (while (null comint-redirect-completed)
3030 (accept-process-output nil 1))
3031
3032 ;; Remove echo if there was one
3033 (with-current-buffer buf
3034 (goto-char start)
3035 (when (looking-at (concat "^" (regexp-quote command) "[\\n]"))
3036 (delete-region (match-beginning 0) (match-end 0)))
3037 (goto-char start)))))
3038
3039(defun sql-redirect-value (command combuf regexp &optional regexp-groups)
3040 "Execute the SQL command and return part of result.
3041
3042COMBUF must be an active SQL interactive buffer. COMMAND should
3043be a string of commands accepted by the SQLi program. From the
3044output, the REGEXP is repeatedly matched and the list of
3045REGEXP-GROUPS submatches is returned. This behaves much like
3046\\[comint-redirect-results-list-from-process] but instead of
3047returning a single submatch it returns a list of each submatch
3048for each match."
3049
3050 (let ((outbuf " *SQL-Redirect-values*")
3051 (results nil))
3052 (sql-redirect command combuf outbuf nil)
3053 (with-current-buffer outbuf
3054 (while (re-search-forward regexp nil t)
3055 (push
3056 (cond
3057 ;; no groups-return all of them
3058 ((null regexp-groups)
3059 (let ((i 1)
3060 (r nil))
3061 (while (match-beginning i)
3062 (push (match-string i) r))
3063 (nreverse r)))
3064 ;; one group specified
3065 ((numberp regexp-groups)
3066 (match-string regexp-groups))
3067 ;; (buffer-substring-no-properties
3068 ;; (match-beginning regexp-groups)
3069 ;; (match-end regexp-groups)))
3070 ;; list of numbers; return the specified matches only
3071 ((consp regexp-groups)
3072 (mapcar (lambda (c)
3073 (cond
3074 ((numberp c) (match-string c))
3075 ((stringp c) (match-substitute-replacement c))
3076 (t (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s" c))))
3077 regexp-groups))
3078 ;; String is specified; return replacement string
3079 ((stringp regexp-groups)
3080 (match-substitute-replacement regexp-groups))
3081 (t
3082 (error "sql-redirect-value: unknown REGEXP-GROUPS value - %s"
3083 regexp-groups)))
3084 results)))
3085 (nreverse results)))
3086
3087
3088
2896;;; SQL mode -- uses SQL interactive mode 3089;;; SQL mode -- uses SQL interactive mode
2897 3090
2898;;;###autoload 3091;;;###autoload
@@ -3063,7 +3256,7 @@ you entered, right above the output it created.
3063 (setq local-abbrev-table sql-mode-abbrev-table) 3256 (setq local-abbrev-table sql-mode-abbrev-table)
3064 (setq abbrev-all-caps 1) 3257 (setq abbrev-all-caps 1)
3065 ;; Exiting the process will call sql-stop. 3258 ;; Exiting the process will call sql-stop.
3066 (set-process-sentinel (get-buffer-process sql-buffer) 'sql-stop) 3259 (set-process-sentinel (get-buffer-process (current-buffer)) 'sql-stop)
3067 ;; Save the connection name 3260 ;; Save the connection name
3068 (make-local-variable 'sql-connection) 3261 (make-local-variable 'sql-connection)
3069 ;; Create a usefull name for renaming this buffer later. 3262 ;; Create a usefull name for renaming this buffer later.
@@ -3248,49 +3441,57 @@ optionally is saved to the user's init file."
3248;;; Entry functions for different SQL interpreters. 3441;;; Entry functions for different SQL interpreters.
3249 3442
3250;;;###autoload 3443;;;###autoload
3251(defun sql-product-interactive (&optional product) 3444(defun sql-product-interactive (&optional product new-name)
3252 "Run PRODUCT interpreter as an inferior process. 3445 "Run PRODUCT interpreter as an inferior process.
3253 3446
3254If buffer `*SQL*' exists but no process is running, make a new process. 3447If buffer `*SQL*' exists but no process is running, make a new process.
3255If buffer exists and a process is running, just switch to buffer `*SQL*'. 3448If buffer exists and a process is running, just switch to buffer `*SQL*'.
3256 3449
3450To specify the SQL product, prefix the call with
3451\\[universal-argument]. To set the buffer name as well, prefix
3452the call to \\[sql-product-interactive] with
3453\\[universal-argument] \\[universal-argument].
3454
3257\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3455\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3258 (interactive "P") 3456 (interactive "P")
3259 3457
3458 ;; Handle universal arguments if specified
3459 (when (not (or executing-kbd-macro noninteractive))
3460 (when (and (consp product)
3461 (not (cdr product))
3462 (numberp (car product)))
3463 (when (>= (car product) 16)
3464 (when (not new-name)
3465 (setq new-name '(4)))
3466 (setq product '(4)))))
3467
3468 ;; Get the value of product that we need
3260 (setq product 3469 (setq product
3261 (cond 3470 (cond
3262 ((equal product '(4)) ; Universal arg, prompt for product 3471 ((equal product '(4)) ; C-u, prompt for product
3263 (intern (completing-read "SQL product: " 3472 (intern (completing-read "SQL product: "
3264 (mapcar (lambda (info) (symbol-name (car info))) 3473 (mapcar (lambda (info) (symbol-name (car info)))
3265 sql-product-alist) 3474 sql-product-alist)
3266 nil 'require-match 3475 nil 'require-match
3267 (or (and sql-product (symbol-name sql-product)) "ansi")))) 3476 (or (and sql-product
3477 (symbol-name sql-product))
3478 "ansi"))))
3268 ((and product ; Product specified 3479 ((and product ; Product specified
3269 (symbolp product)) product) 3480 (symbolp product)) product)
3270 (t sql-product))) ; Default to sql-product 3481 (t sql-product))) ; Default to sql-product
3271 3482
3483 ;; If we have a product and it has a interactive mode
3272 (if product 3484 (if product
3273 (when (sql-get-product-feature product :sqli-comint-func) 3485 (when (sql-get-product-feature product :sqli-comint-func)
3274 (if (and sql-buffer 3486 ;; If no new name specified, fall back on sql-buffer if its for
3275 (buffer-live-p sql-buffer) 3487 ;; the same product
3276 (comint-check-proc sql-buffer)) 3488 (if (and (not new-name)
3489 (sql-buffer-live-p sql-buffer product))
3277 (pop-to-buffer sql-buffer) 3490 (pop-to-buffer sql-buffer)
3278 3491
3279 ;; Is the current buffer in sql-mode and 3492 ;; We have a new name or sql-buffer doesn't exist or match
3280 ;; there is a buffer local setting of sql-buffer 3493 ;; Start by remembering where we start
3281 (let* ((start-buffer 3494 (let* ((start-buffer (current-buffer))
3282 (and (derived-mode-p 'sql-mode)
3283 (current-buffer)))
3284 (start-sql-buffer
3285 (and start-buffer
3286 (let (found)
3287 (dolist (var (buffer-local-variables))
3288 (and (consp var)
3289 (eq (car var) 'sql-buffer)
3290 (buffer-live-p (cdr var))
3291 (get-buffer-process (cdr var))
3292 (setq found (cdr var))))
3293 found)))
3294 new-sqli-buffer) 3495 new-sqli-buffer)
3295 3496
3296 ;; Get credentials. 3497 ;; Get credentials.
@@ -3303,15 +3504,19 @@ If buffer exists and a process is running, just switch to buffer `*SQL*'.
3303 (sql-get-product-feature product :sqli-options)) 3504 (sql-get-product-feature product :sqli-options))
3304 3505
3305 ;; Set SQLi mode. 3506 ;; Set SQLi mode.
3306 (setq sql-interactive-product product 3507 (setq new-sqli-buffer (current-buffer))
3307 new-sqli-buffer (current-buffer) 3508 (let ((sql-interactive-product product))
3308 sql-buffer new-sqli-buffer) 3509 (sql-interactive-mode))
3309 (sql-interactive-mode) 3510
3511 ;; Set the new buffer name
3512 (when new-name
3513 (sql-rename-buffer new-name))
3310 3514
3311 ;; Set `sql-buffer' in the start buffer 3515 ;; Set `sql-buffer' in the new buffer and the start buffer
3312 (when (and start-buffer (not start-sql-buffer)) 3516 (setq sql-buffer (buffer-name new-sqli-buffer))
3313 (with-current-buffer start-buffer 3517 (with-current-buffer start-buffer
3314 (setq sql-buffer new-sqli-buffer))) 3518 (setq sql-buffer (buffer-name new-sqli-buffer))
3519 (run-hooks 'sql-set-sqli-hook))
3315 3520
3316 ;; All done. 3521 ;; All done.
3317 (message "Login...done") 3522 (message "Login...done")
@@ -3323,12 +3528,22 @@ If buffer exists and a process is running, just switch to buffer `*SQL*'.
3323 3528
3324PRODUCT is the SQL product. PARAMS is a list of strings which are 3529PRODUCT is the SQL product. PARAMS is a list of strings which are
3325passed as command line arguments." 3530passed as command line arguments."
3326 (let ((program (sql-get-product-feature product :sqli-program))) 3531 (let ((program (sql-get-product-feature product :sqli-program))
3532 (buf-name "SQL"))
3533 ;; Make sure buffer name is unique
3534 (when (get-buffer (format "*%s*" buf-name))
3535 (setq buf-name (format "SQL-%s" product))
3536 (when (get-buffer (format "*%s*" buf-name))
3537 (let ((i 1))
3538 (while (get-buffer (format "*%s*"
3539 (setq buf-name
3540 (format "SQL-%s%d" product i))))
3541 (setq i (1+ i))))))
3327 (set-buffer 3542 (set-buffer
3328 (apply 'make-comint "SQL" program nil params)))) 3543 (apply 'make-comint buf-name program nil params))))
3329 3544
3330;;;###autoload 3545;;;###autoload
3331(defun sql-oracle () 3546(defun sql-oracle (&optional buffer)
3332 "Run sqlplus by Oracle as an inferior process. 3547 "Run sqlplus by Oracle as an inferior process.
3333 3548
3334If buffer `*SQL*' exists but no process is running, make a new process. 3549If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3343,6 +3558,11 @@ the list `sql-oracle-options'.
3343The buffer is put in SQL interactive mode, giving commands for sending 3558The buffer is put in SQL interactive mode, giving commands for sending
3344input. See `sql-interactive-mode'. 3559input. See `sql-interactive-mode'.
3345 3560
3561To set the buffer name directly, use \\[universal-argument]
3562before \\[sql-oracle]. Once session has started,
3563\\[sql-rename-buffer] can be called separately to rename the
3564buffer.
3565
3346To specify a coding system for converting non-ASCII characters 3566To specify a coding system for converting non-ASCII characters
3347in the input and output to the process, use \\[universal-coding-system-argument] 3567in the input and output to the process, use \\[universal-coding-system-argument]
3348before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system] 3568before \\[sql-oracle]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3351,8 +3571,8 @@ The default comes from `process-coding-system-alist' and
3351`default-process-coding-system'. 3571`default-process-coding-system'.
3352 3572
3353\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3573\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3354 (interactive) 3574 (interactive "P")
3355 (sql-product-interactive 'oracle)) 3575 (sql-product-interactive 'oracle buffer))
3356 3576
3357(defun sql-comint-oracle (product options) 3577(defun sql-comint-oracle (product options)
3358 "Create comint buffer and connect to Oracle." 3578 "Create comint buffer and connect to Oracle."
@@ -3375,7 +3595,7 @@ The default comes from `process-coding-system-alist' and
3375 3595
3376 3596
3377;;;###autoload 3597;;;###autoload
3378(defun sql-sybase () 3598(defun sql-sybase (&optional buffer)
3379 "Run isql by Sybase as an inferior process. 3599 "Run isql by Sybase as an inferior process.
3380 3600
3381If buffer `*SQL*' exists but no process is running, make a new process. 3601If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3390,6 +3610,11 @@ can be stored in the list `sql-sybase-options'.
3390The buffer is put in SQL interactive mode, giving commands for sending 3610The buffer is put in SQL interactive mode, giving commands for sending
3391input. See `sql-interactive-mode'. 3611input. See `sql-interactive-mode'.
3392 3612
3613To set the buffer name directly, use \\[universal-argument]
3614before \\[sql-sybase]. Once session has started,
3615\\[sql-rename-buffer] can be called separately to rename the
3616buffer.
3617
3393To specify a coding system for converting non-ASCII characters 3618To specify a coding system for converting non-ASCII characters
3394in the input and output to the process, use \\[universal-coding-system-argument] 3619in the input and output to the process, use \\[universal-coding-system-argument]
3395before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system] 3620before \\[sql-sybase]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3398,8 +3623,8 @@ The default comes from `process-coding-system-alist' and
3398`default-process-coding-system'. 3623`default-process-coding-system'.
3399 3624
3400\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3625\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3401 (interactive) 3626 (interactive "P")
3402 (sql-product-interactive 'sybase)) 3627 (sql-product-interactive 'sybase buffer))
3403 3628
3404(defun sql-comint-sybase (product options) 3629(defun sql-comint-sybase (product options)
3405 "Create comint buffer and connect to Sybase." 3630 "Create comint buffer and connect to Sybase."
@@ -3419,7 +3644,7 @@ The default comes from `process-coding-system-alist' and
3419 3644
3420 3645
3421;;;###autoload 3646;;;###autoload
3422(defun sql-informix () 3647(defun sql-informix (&optional buffer)
3423 "Run dbaccess by Informix as an inferior process. 3648 "Run dbaccess by Informix as an inferior process.
3424 3649
3425If buffer `*SQL*' exists but no process is running, make a new process. 3650If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3432,6 +3657,11 @@ the variable `sql-database' as default, if set.
3432The buffer is put in SQL interactive mode, giving commands for sending 3657The buffer is put in SQL interactive mode, giving commands for sending
3433input. See `sql-interactive-mode'. 3658input. See `sql-interactive-mode'.
3434 3659
3660To set the buffer name directly, use \\[universal-argument]
3661before \\[sql-informix]. Once session has started,
3662\\[sql-rename-buffer] can be called separately to rename the
3663buffer.
3664
3435To specify a coding system for converting non-ASCII characters 3665To specify a coding system for converting non-ASCII characters
3436in the input and output to the process, use \\[universal-coding-system-argument] 3666in the input and output to the process, use \\[universal-coding-system-argument]
3437before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system] 3667before \\[sql-informix]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3440,8 +3670,8 @@ The default comes from `process-coding-system-alist' and
3440`default-process-coding-system'. 3670`default-process-coding-system'.
3441 3671
3442\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3672\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3443 (interactive) 3673 (interactive "P")
3444 (sql-product-interactive 'informix)) 3674 (sql-product-interactive 'informix buffer))
3445 3675
3446(defun sql-comint-informix (product options) 3676(defun sql-comint-informix (product options)
3447 "Create comint buffer and connect to Informix." 3677 "Create comint buffer and connect to Informix."
@@ -3456,7 +3686,7 @@ The default comes from `process-coding-system-alist' and
3456 3686
3457 3687
3458;;;###autoload 3688;;;###autoload
3459(defun sql-sqlite () 3689(defun sql-sqlite (&optional buffer)
3460 "Run sqlite as an inferior process. 3690 "Run sqlite as an inferior process.
3461 3691
3462SQLite is free software. 3692SQLite is free software.
@@ -3473,6 +3703,11 @@ can be stored in the list `sql-sqlite-options'.
3473The buffer is put in SQL interactive mode, giving commands for sending 3703The buffer is put in SQL interactive mode, giving commands for sending
3474input. See `sql-interactive-mode'. 3704input. See `sql-interactive-mode'.
3475 3705
3706To set the buffer name directly, use \\[universal-argument]
3707before \\[sql-sqlite]. Once session has started,
3708\\[sql-rename-buffer] can be called separately to rename the
3709buffer.
3710
3476To specify a coding system for converting non-ASCII characters 3711To specify a coding system for converting non-ASCII characters
3477in the input and output to the process, use \\[universal-coding-system-argument] 3712in the input and output to the process, use \\[universal-coding-system-argument]
3478before \\[sql-sqlite]. You can also specify this with \\[set-buffer-process-coding-system] 3713before \\[sql-sqlite]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3481,8 +3716,8 @@ The default comes from `process-coding-system-alist' and
3481`default-process-coding-system'. 3716`default-process-coding-system'.
3482 3717
3483\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3718\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3484 (interactive) 3719 (interactive "P")
3485 (sql-product-interactive 'sqlite)) 3720 (sql-product-interactive 'sqlite buffer))
3486 3721
3487(defun sql-comint-sqlite (product options) 3722(defun sql-comint-sqlite (product options)
3488 "Create comint buffer and connect to SQLite." 3723 "Create comint buffer and connect to SQLite."
@@ -3498,7 +3733,7 @@ The default comes from `process-coding-system-alist' and
3498 3733
3499 3734
3500;;;###autoload 3735;;;###autoload
3501(defun sql-mysql () 3736(defun sql-mysql (&optional buffer)
3502 "Run mysql by TcX as an inferior process. 3737 "Run mysql by TcX as an inferior process.
3503 3738
3504Mysql versions 3.23 and up are free software. 3739Mysql versions 3.23 and up are free software.
@@ -3515,6 +3750,11 @@ can be stored in the list `sql-mysql-options'.
3515The buffer is put in SQL interactive mode, giving commands for sending 3750The buffer is put in SQL interactive mode, giving commands for sending
3516input. See `sql-interactive-mode'. 3751input. See `sql-interactive-mode'.
3517 3752
3753To set the buffer name directly, use \\[universal-argument]
3754before \\[sql-mysql]. Once session has started,
3755\\[sql-rename-buffer] can be called separately to rename the
3756buffer.
3757
3518To specify a coding system for converting non-ASCII characters 3758To specify a coding system for converting non-ASCII characters
3519in the input and output to the process, use \\[universal-coding-system-argument] 3759in the input and output to the process, use \\[universal-coding-system-argument]
3520before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system] 3760before \\[sql-mysql]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3523,8 +3763,8 @@ The default comes from `process-coding-system-alist' and
3523`default-process-coding-system'. 3763`default-process-coding-system'.
3524 3764
3525\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3765\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3526 (interactive) 3766 (interactive "P")
3527 (sql-product-interactive 'mysql)) 3767 (sql-product-interactive 'mysql buffer))
3528 3768
3529(defun sql-comint-mysql (product options) 3769(defun sql-comint-mysql (product options)
3530 "Create comint buffer and connect to MySQL." 3770 "Create comint buffer and connect to MySQL."
@@ -3535,7 +3775,7 @@ The default comes from `process-coding-system-alist' and
3535 (setq params (append (list sql-database) params))) 3775 (setq params (append (list sql-database) params)))
3536 (if (not (string= "" sql-server)) 3776 (if (not (string= "" sql-server))
3537 (setq params (append (list (concat "--host=" sql-server)) params))) 3777 (setq params (append (list (concat "--host=" sql-server)) params)))
3538 (if (and sql-port (numberp sql-port)) 3778 (if (not (= 0 sql-port))
3539 (setq params (append (list (concat "--port=" (number-to-string sql-port))) params))) 3779 (setq params (append (list (concat "--port=" (number-to-string sql-port))) params)))
3540 (if (not (string= "" sql-password)) 3780 (if (not (string= "" sql-password))
3541 (setq params (append (list (concat "--password=" sql-password)) params))) 3781 (setq params (append (list (concat "--password=" sql-password)) params)))
@@ -3547,7 +3787,7 @@ The default comes from `process-coding-system-alist' and
3547 3787
3548 3788
3549;;;###autoload 3789;;;###autoload
3550(defun sql-solid () 3790(defun sql-solid (&optional buffer)
3551 "Run solsql by Solid as an inferior process. 3791 "Run solsql by Solid as an inferior process.
3552 3792
3553If buffer `*SQL*' exists but no process is running, make a new process. 3793If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3561,6 +3801,11 @@ defaults, if set.
3561The buffer is put in SQL interactive mode, giving commands for sending 3801The buffer is put in SQL interactive mode, giving commands for sending
3562input. See `sql-interactive-mode'. 3802input. See `sql-interactive-mode'.
3563 3803
3804To set the buffer name directly, use \\[universal-argument]
3805before \\[sql-solid]. Once session has started,
3806\\[sql-rename-buffer] can be called separately to rename the
3807buffer.
3808
3564To specify a coding system for converting non-ASCII characters 3809To specify a coding system for converting non-ASCII characters
3565in the input and output to the process, use \\[universal-coding-system-argument] 3810in the input and output to the process, use \\[universal-coding-system-argument]
3566before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system] 3811before \\[sql-solid]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3569,8 +3814,8 @@ The default comes from `process-coding-system-alist' and
3569`default-process-coding-system'. 3814`default-process-coding-system'.
3570 3815
3571\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3816\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3572 (interactive) 3817 (interactive "P")
3573 (sql-product-interactive 'solid)) 3818 (sql-product-interactive 'solid buffer))
3574 3819
3575(defun sql-comint-solid (product options) 3820(defun sql-comint-solid (product options)
3576 "Create comint buffer and connect to Solid." 3821 "Create comint buffer and connect to Solid."
@@ -3588,7 +3833,7 @@ The default comes from `process-coding-system-alist' and
3588 3833
3589 3834
3590;;;###autoload 3835;;;###autoload
3591(defun sql-ingres () 3836(defun sql-ingres (&optional buffer)
3592 "Run sql by Ingres as an inferior process. 3837 "Run sql by Ingres as an inferior process.
3593 3838
3594If buffer `*SQL*' exists but no process is running, make a new process. 3839If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3601,6 +3846,11 @@ the variable `sql-database' as default, if set.
3601The buffer is put in SQL interactive mode, giving commands for sending 3846The buffer is put in SQL interactive mode, giving commands for sending
3602input. See `sql-interactive-mode'. 3847input. See `sql-interactive-mode'.
3603 3848
3849To set the buffer name directly, use \\[universal-argument]
3850before \\[sql-ingres]. Once session has started,
3851\\[sql-rename-buffer] can be called separately to rename the
3852buffer.
3853
3604To specify a coding system for converting non-ASCII characters 3854To specify a coding system for converting non-ASCII characters
3605in the input and output to the process, use \\[universal-coding-system-argument] 3855in the input and output to the process, use \\[universal-coding-system-argument]
3606before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system] 3856before \\[sql-ingres]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3609,8 +3859,8 @@ The default comes from `process-coding-system-alist' and
3609`default-process-coding-system'. 3859`default-process-coding-system'.
3610 3860
3611\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3861\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3612 (interactive) 3862 (interactive "P")
3613 (sql-product-interactive 'ingres)) 3863 (sql-product-interactive 'ingres buffer))
3614 3864
3615(defun sql-comint-ingres (product options) 3865(defun sql-comint-ingres (product options)
3616 "Create comint buffer and connect to Ingres." 3866 "Create comint buffer and connect to Ingres."
@@ -3624,7 +3874,7 @@ The default comes from `process-coding-system-alist' and
3624 3874
3625 3875
3626;;;###autoload 3876;;;###autoload
3627(defun sql-ms () 3877(defun sql-ms (&optional buffer)
3628 "Run osql by Microsoft as an inferior process. 3878 "Run osql by Microsoft as an inferior process.
3629 3879
3630If buffer `*SQL*' exists but no process is running, make a new process. 3880If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3639,6 +3889,11 @@ in the list `sql-ms-options'.
3639The buffer is put in SQL interactive mode, giving commands for sending 3889The buffer is put in SQL interactive mode, giving commands for sending
3640input. See `sql-interactive-mode'. 3890input. See `sql-interactive-mode'.
3641 3891
3892To set the buffer name directly, use \\[universal-argument]
3893before \\[sql-ms]. Once session has started,
3894\\[sql-rename-buffer] can be called separately to rename the
3895buffer.
3896
3642To specify a coding system for converting non-ASCII characters 3897To specify a coding system for converting non-ASCII characters
3643in the input and output to the process, use \\[universal-coding-system-argument] 3898in the input and output to the process, use \\[universal-coding-system-argument]
3644before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system] 3899before \\[sql-ms]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3647,8 +3902,8 @@ The default comes from `process-coding-system-alist' and
3647`default-process-coding-system'. 3902`default-process-coding-system'.
3648 3903
3649\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3904\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3650 (interactive) 3905 (interactive "P")
3651 (sql-product-interactive 'ms)) 3906 (sql-product-interactive 'ms buffer))
3652 3907
3653(defun sql-comint-ms (product options) 3908(defun sql-comint-ms (product options)
3654 "Create comint buffer and connect to Microsoft SQL Server." 3909 "Create comint buffer and connect to Microsoft SQL Server."
@@ -3675,7 +3930,7 @@ The default comes from `process-coding-system-alist' and
3675 3930
3676 3931
3677;;;###autoload 3932;;;###autoload
3678(defun sql-postgres () 3933(defun sql-postgres (&optional buffer)
3679 "Run psql by Postgres as an inferior process. 3934 "Run psql by Postgres as an inferior process.
3680 3935
3681If buffer `*SQL*' exists but no process is running, make a new process. 3936If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3690,6 +3945,11 @@ Additional command line parameters can be stored in the list
3690The buffer is put in SQL interactive mode, giving commands for sending 3945The buffer is put in SQL interactive mode, giving commands for sending
3691input. See `sql-interactive-mode'. 3946input. See `sql-interactive-mode'.
3692 3947
3948To set the buffer name directly, use \\[universal-argument]
3949before \\[sql-postgres]. Once session has started,
3950\\[sql-rename-buffer] can be called separately to rename the
3951buffer.
3952
3693To specify a coding system for converting non-ASCII characters 3953To specify a coding system for converting non-ASCII characters
3694in the input and output to the process, use \\[universal-coding-system-argument] 3954in the input and output to the process, use \\[universal-coding-system-argument]
3695before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system] 3955before \\[sql-postgres]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3703,8 +3963,8 @@ Try to set `comint-output-filter-functions' like this:
3703 '(comint-strip-ctrl-m))) 3963 '(comint-strip-ctrl-m)))
3704 3964
3705\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 3965\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3706 (interactive) 3966 (interactive "P")
3707 (sql-product-interactive 'postgres)) 3967 (sql-product-interactive 'postgres buffer))
3708 3968
3709(defun sql-comint-postgres (product options) 3969(defun sql-comint-postgres (product options)
3710 "Create comint buffer and connect to Postgres." 3970 "Create comint buffer and connect to Postgres."
@@ -3725,7 +3985,7 @@ Try to set `comint-output-filter-functions' like this:
3725 3985
3726 3986
3727;;;###autoload 3987;;;###autoload
3728(defun sql-interbase () 3988(defun sql-interbase (&optional buffer)
3729 "Run isql by Interbase as an inferior process. 3989 "Run isql by Interbase as an inferior process.
3730 3990
3731If buffer `*SQL*' exists but no process is running, make a new process. 3991If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3739,6 +3999,11 @@ defaults, if set.
3739The buffer is put in SQL interactive mode, giving commands for sending 3999The buffer is put in SQL interactive mode, giving commands for sending
3740input. See `sql-interactive-mode'. 4000input. See `sql-interactive-mode'.
3741 4001
4002To set the buffer name directly, use \\[universal-argument]
4003before \\[sql-interbase]. Once session has started,
4004\\[sql-rename-buffer] can be called separately to rename the
4005buffer.
4006
3742To specify a coding system for converting non-ASCII characters 4007To specify a coding system for converting non-ASCII characters
3743in the input and output to the process, use \\[universal-coding-system-argument] 4008in the input and output to the process, use \\[universal-coding-system-argument]
3744before \\[sql-interbase]. You can also specify this with \\[set-buffer-process-coding-system] 4009before \\[sql-interbase]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3747,8 +4012,8 @@ The default comes from `process-coding-system-alist' and
3747`default-process-coding-system'. 4012`default-process-coding-system'.
3748 4013
3749\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 4014\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3750 (interactive) 4015 (interactive "P")
3751 (sql-product-interactive 'interbase)) 4016 (sql-product-interactive 'interbase buffer))
3752 4017
3753(defun sql-comint-interbase (product options) 4018(defun sql-comint-interbase (product options)
3754 "Create comint buffer and connect to Interbase." 4019 "Create comint buffer and connect to Interbase."
@@ -3766,7 +4031,7 @@ The default comes from `process-coding-system-alist' and
3766 4031
3767 4032
3768;;;###autoload 4033;;;###autoload
3769(defun sql-db2 () 4034(defun sql-db2 (&optional buffer)
3770 "Run db2 by IBM as an inferior process. 4035 "Run db2 by IBM as an inferior process.
3771 4036
3772If buffer `*SQL*' exists but no process is running, make a new process. 4037If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3784,6 +4049,11 @@ db2, newlines will be escaped if necessary. If you don't want that, set
3784`comint-input-sender' back to `comint-simple-send' by writing an after 4049`comint-input-sender' back to `comint-simple-send' by writing an after
3785advice. See the elisp manual for more information. 4050advice. See the elisp manual for more information.
3786 4051
4052To set the buffer name directly, use \\[universal-argument]
4053before \\[sql-db2]. Once session has started,
4054\\[sql-rename-buffer] can be called separately to rename the
4055buffer.
4056
3787To specify a coding system for converting non-ASCII characters 4057To specify a coding system for converting non-ASCII characters
3788in the input and output to the process, use \\[universal-coding-system-argument] 4058in the input and output to the process, use \\[universal-coding-system-argument]
3789before \\[sql-db2]. You can also specify this with \\[set-buffer-process-coding-system] 4059before \\[sql-db2]. You can also specify this with \\[set-buffer-process-coding-system]
@@ -3792,8 +4062,8 @@ The default comes from `process-coding-system-alist' and
3792`default-process-coding-system'. 4062`default-process-coding-system'.
3793 4063
3794\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 4064\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3795 (interactive) 4065 (interactive "P")
3796 (sql-product-interactive 'db2)) 4066 (sql-product-interactive 'db2 buffer))
3797 4067
3798(defun sql-comint-db2 (product options) 4068(defun sql-comint-db2 (product options)
3799 "Create comint buffer and connect to DB2." 4069 "Create comint buffer and connect to DB2."
@@ -3801,11 +4071,9 @@ The default comes from `process-coding-system-alist' and
3801 ;; make-comint. 4071 ;; make-comint.
3802 (sql-comint product options) 4072 (sql-comint product options)
3803) 4073)
3804;; ;; Properly escape newlines when DB2 is interactive.
3805;; (setq comint-input-sender 'sql-escape-newlines-and-send))
3806 4074
3807;;;###autoload 4075;;;###autoload
3808(defun sql-linter () 4076(defun sql-linter (&optional buffer)
3809 "Run inl by RELEX as an inferior process. 4077 "Run inl by RELEX as an inferior process.
3810 4078
3811If buffer `*SQL*' exists but no process is running, make a new process. 4079If buffer `*SQL*' exists but no process is running, make a new process.
@@ -3827,9 +4095,14 @@ an empty password.
3827The buffer is put in SQL interactive mode, giving commands for sending 4095The buffer is put in SQL interactive mode, giving commands for sending
3828input. See `sql-interactive-mode'. 4096input. See `sql-interactive-mode'.
3829 4097
4098To set the buffer name directly, use \\[universal-argument]
4099before \\[sql-linter]. Once session has started,
4100\\[sql-rename-buffer] can be called separately to rename the
4101buffer.
4102
3830\(Type \\[describe-mode] in the SQL buffer for a list of commands.)" 4103\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
3831 (interactive) 4104 (interactive "P")
3832 (sql-product-interactive 'linter)) 4105 (sql-product-interactive 'linter buffer))
3833 4106
3834(defun sql-comint-linter (product options) 4107(defun sql-comint-linter (product options)
3835 "Create comint buffer and connect to Linter." 4108 "Create comint buffer and connect to Linter."
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index 29096a23046..8f80d13bab6 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -411,9 +411,10 @@ This variable is generally set from `tcl-proc-regexp',
411`tcl-typeword-list', and `tcl-keyword-list' by the function 411`tcl-typeword-list', and `tcl-keyword-list' by the function
412`tcl-set-font-lock-keywords'.") 412`tcl-set-font-lock-keywords'.")
413 413
414(defvar tcl-font-lock-syntactic-keywords 414(defconst tcl-syntax-propertize-function
415 ;; Mark the few `#' that are not comment-markers. 415 (syntax-propertize-rules
416 '(("[^;[{ \t\n][ \t]*\\(#\\)" (1 "."))) 416 ;; Mark the few `#' that are not comment-markers.
417 ("[^;[{ \t\n][ \t]*\\(#\\)" (1 ".")))
417 "Syntactic keywords for `tcl-mode'.") 418 "Syntactic keywords for `tcl-mode'.")
418 419
419;; FIXME need some way to recognize variables because array refs look 420;; FIXME need some way to recognize variables because array refs look
@@ -593,9 +594,9 @@ Commands:
593 (set (make-local-variable 'outline-level) 'tcl-outline-level) 594 (set (make-local-variable 'outline-level) 'tcl-outline-level)
594 595
595 (set (make-local-variable 'font-lock-defaults) 596 (set (make-local-variable 'font-lock-defaults)
596 '(tcl-font-lock-keywords nil nil nil beginning-of-defun 597 '(tcl-font-lock-keywords nil nil nil beginning-of-defun))
597 (font-lock-syntactic-keywords . tcl-font-lock-syntactic-keywords) 598 (set (make-local-variable 'syntax-propertize-function)
598 (parse-sexp-lookup-properties . t))) 599 tcl-syntax-propertize-function)
599 600
600 (set (make-local-variable 'imenu-generic-expression) 601 (set (make-local-variable 'imenu-generic-expression)
601 tcl-imenu-generic-expression) 602 tcl-imenu-generic-expression)
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index 4ff9cf92b8d..24768d93e6a 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -4693,8 +4693,15 @@ Key bindings:
4693 (set (make-local-variable 'font-lock-defaults) 4693 (set (make-local-variable 'font-lock-defaults)
4694 (list 4694 (list
4695 '(nil vhdl-font-lock-keywords) nil 4695 '(nil vhdl-font-lock-keywords) nil
4696 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line 4696 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line))
4697 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords))) 4697 (if (eval-when-compile (fboundp 'syntax-propertize-rules))
4698 (set (make-local-variable 'syntax-propertize-function)
4699 (syntax-propertize-rules
4700 ;; Mark single quotes as having string quote syntax in
4701 ;; 'c' instances.
4702 ("\\(\'\\).\\(\'\\)" (1 "\"'") (2 "\"'"))))
4703 (set (make-local-variable 'font-lock-syntactic-keywords)
4704 vhdl-font-lock-syntactic-keywords))
4698 (unless vhdl-emacs-21 4705 (unless vhdl-emacs-21
4699 (set (make-local-variable 'font-lock-support-mode) 'lazy-lock-mode) 4706 (set (make-local-variable 'font-lock-support-mode) 'lazy-lock-mode)
4700 (set (make-local-variable 'lazy-lock-defer-contextually) nil) 4707 (set (make-local-variable 'lazy-lock-defer-contextually) nil)
@@ -12914,10 +12921,9 @@ This does background highlighting of translate-off regions.")
12914 "Re-initialize fontification and fontify buffer." 12921 "Re-initialize fontification and fontify buffer."
12915 (interactive) 12922 (interactive)
12916 (setq font-lock-defaults 12923 (setq font-lock-defaults
12917 (list 12924 `(vhdl-font-lock-keywords
12918 'vhdl-font-lock-keywords nil 12925 nil ,(not vhdl-highlight-case-sensitive) ((?\_ . "w"))
12919 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line 12926 beginning-of-line))
12920 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
12921 (when (fboundp 'font-lock-unset-defaults) 12927 (when (fboundp 'font-lock-unset-defaults)
12922 (font-lock-unset-defaults)) ; not implemented in XEmacs 12928 (font-lock-unset-defaults)) ; not implemented in XEmacs
12923 (font-lock-set-defaults) 12929 (font-lock-set-defaults)