aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes
diff options
context:
space:
mode:
authorMiles Bader2004-06-28 07:56:49 +0000
committerMiles Bader2004-06-28 07:56:49 +0000
commit327719ee8a3fcdb36ed6acaf6d8cb5fbdf0bd801 (patch)
tree21de188e13b5e41a79bb50040933072ae0235217 /lisp/progmodes
parent852f73b7fa7b71910282eacb6263b3ecfd4ee783 (diff)
parent376de73927383d6062483db10b8a82448505f52b (diff)
downloademacs-327719ee8a3fcdb36ed6acaf6d8cb5fbdf0bd801.tar.gz
emacs-327719ee8a3fcdb36ed6acaf6d8cb5fbdf0bd801.zip
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-15
Merge from emacs--cvs-trunk--0 Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-218 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-220 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-221 Restore deleted tagline in etc/TUTORIAL.ru * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-222 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-228 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-229 Remove TeX output files from the archive * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-230 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-247 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-248 src/lisp.h (CYCLE_CHECK): Macro moved from xfaces.c * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-249 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-256 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-258 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-263 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-264 Update from CVS: lispref/display.texi: emacs -> Emacs. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-265 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-274 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-275 Update from CVS: man/makefile.w32-in: Revert last change * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-276 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-295 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-296 Allow restarting an existing debugger session that's exited * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-297 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-299 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-300 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-327 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-328 Update from CVS: src/.gdbinit (xsymbol): Fix last change. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-329 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-344 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-345 Tweak source regexps so that building in place won't cause problems * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-346 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-351 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-352 Update from CVS: lisp/flymake.el: New file. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-353 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-361 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-362 Support " [...]" style defaults in minibuffer-electric-default-mode * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-363 (read-number): Use canonical format for default in prompt. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-364 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-367 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-368 Improve display-supports-face-attributes-p on non-ttys * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-369 Rewrite face-differs-from-default-p * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-370 Move `display-supports-face-attributes-p' entirely into C code * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-371 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-372 Simplify face-differs-from-default-p; don't consider :stipple. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-373 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-374 (tty_supports_face_attributes_p): Ensure attributes differ from default * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-375 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-376 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-377 (Fdisplay_supports_face_attributes_p): Work around bootstrapping problem * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-378 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-380 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-381 Face merging cleanups * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-382 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-384 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-385 src/xfaces.c (push_named_merge_point): Return 0 if a cycle is detected * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-386 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-395 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-396 Tweak arch tagging to make build/install-in-place less annoying * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-397 Work around vc-arch problems when building eshell * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-398 Tweak permissions * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-399 Tweak directory permissions * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-400 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-401 More build-in-place tweaking of arch tagging * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-402 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-403 Yet more build-in-place tweaking of arch tagging * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-404 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-409 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-410 Make sure image types are initialized for lookup too * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-411 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-416 Update from CVS
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/ada-mode.el16
-rw-r--r--lisp/progmodes/cc-cmds.el2
-rw-r--r--lisp/progmodes/cfengine.el7
-rw-r--r--lisp/progmodes/compile.el619
-rw-r--r--lisp/progmodes/cperl-mode.el9
-rw-r--r--lisp/progmodes/etags.el19
-rw-r--r--lisp/progmodes/f90.el60
-rw-r--r--lisp/progmodes/flymake.el2504
-rw-r--r--lisp/progmodes/fortran.el3
-rw-r--r--lisp/progmodes/gdb-ui.el520
-rw-r--r--lisp/progmodes/grep.el4
-rw-r--r--lisp/progmodes/gud.el95
-rw-r--r--lisp/progmodes/idlw-shell.el4
-rw-r--r--lisp/progmodes/python.el569
-rw-r--r--lisp/progmodes/sh-script.el2
-rw-r--r--lisp/progmodes/sql.el941
16 files changed, 4188 insertions, 1186 deletions
diff --git a/lisp/progmodes/ada-mode.el b/lisp/progmodes/ada-mode.el
index abc8db6d2c3..f7688e24069 100644
--- a/lisp/progmodes/ada-mode.el
+++ b/lisp/progmodes/ada-mode.el
@@ -1466,8 +1466,8 @@ The standard casing rules will no longer apply to this word."
1466 ;; If the word is already in the list, even with a different casing 1466 ;; If the word is already in the list, even with a different casing
1467 ;; we simply want to replace it. 1467 ;; we simply want to replace it.
1468 (if (and (not (equal ada-case-exception '())) 1468 (if (and (not (equal ada-case-exception '()))
1469 (assoc-ignore-case word ada-case-exception)) 1469 (assoc-string word ada-case-exception t))
1470 (setcar (assoc-ignore-case word ada-case-exception) word) 1470 (setcar (assoc-string word ada-case-exception t) word)
1471 (add-to-list 'ada-case-exception (cons word t)) 1471 (add-to-list 'ada-case-exception (cons word t))
1472 ) 1472 )
1473 1473
@@ -1519,8 +1519,8 @@ word itself has a special casing."
1519 ;; If the word is already in the list, even with a different casing 1519 ;; If the word is already in the list, even with a different casing
1520 ;; we simply want to replace it. 1520 ;; we simply want to replace it.
1521 (if (and (not (equal ada-case-exception-substring '())) 1521 (if (and (not (equal ada-case-exception-substring '()))
1522 (assoc-ignore-case word ada-case-exception-substring)) 1522 (assoc-string word ada-case-exception-substring t))
1523 (setcar (assoc-ignore-case word ada-case-exception-substring) word) 1523 (setcar (assoc-string word ada-case-exception-substring t) word)
1524 (add-to-list 'ada-case-exception-substring (cons word t)) 1524 (add-to-list 'ada-case-exception-substring (cons word t))
1525 ) 1525 )
1526 1526
@@ -1548,9 +1548,9 @@ word itself has a special casing."
1548 (if (char-equal (string-to-char word) ?*) 1548 (if (char-equal (string-to-char word) ?*)
1549 (progn 1549 (progn
1550 (setq word (substring word 1)) 1550 (setq word (substring word 1))
1551 (unless (assoc-ignore-case word ada-case-exception-substring) 1551 (unless (assoc-string word ada-case-exception-substring t)
1552 (add-to-list 'ada-case-exception-substring (cons word t)))) 1552 (add-to-list 'ada-case-exception-substring (cons word t))))
1553 (unless (assoc-ignore-case word ada-case-exception) 1553 (unless (assoc-string word ada-case-exception t)
1554 (add-to-list 'ada-case-exception (cons word t))))) 1554 (add-to-list 'ada-case-exception (cons word t)))))
1555 1555
1556 (forward-line 1)) 1556 (forward-line 1))
@@ -1618,8 +1618,8 @@ the exceptions defined in `ada-case-exception-file'."
1618 (point))) 1618 (point)))
1619 match) 1619 match)
1620 ;; If we have an exception, replace the word by the correct casing 1620 ;; If we have an exception, replace the word by the correct casing
1621 (if (setq match (assoc-ignore-case (buffer-substring start end) 1621 (if (setq match (assoc-string (buffer-substring start end)
1622 ada-case-exception)) 1622 ada-case-exception t))
1623 1623
1624 (progn 1624 (progn
1625 (delete-region start end) 1625 (delete-region start end)
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index c6f60d3dcc0..a61369004e8 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1488,7 +1488,7 @@ more \"DWIM:ey\"."
1488 (save-excursion 1488 (save-excursion
1489 (beginning-of-line) 1489 (beginning-of-line)
1490 (or (not (re-search-backward 1490 (or (not (re-search-backward
1491 sentence-end 1491 (sentence-end)
1492 (c-point 'bopl) 1492 (c-point 'bopl)
1493 t)) 1493 t))
1494 (< (match-end 0) 1494 (< (match-end 0)
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 62633fe2940..16064586ee9 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1,6 +1,6 @@
1;;; cfengine.el --- mode for editing Cfengine files 1;;; cfengine.el --- mode for editing Cfengine files
2 2
3;; Copyright (C) 2003 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 4
5;; Author: Dave Love <fx@gnu.org> 5;; Author: Dave Love <fx@gnu.org>
6;; Keywords: languages 6;; Keywords: languages
@@ -102,7 +102,8 @@ This includes those for cfservd as well as cfagent."))
102(defun cfengine-beginning-of-defun () 102(defun cfengine-beginning-of-defun ()
103 "`beginning-of-defun' function for Cfengine mode. 103 "`beginning-of-defun' function for Cfengine mode.
104Treats actions as defuns." 104Treats actions as defuns."
105 (end-of-line) 105 (unless (<= (current-column) (current-indentation))
106 (end-of-line))
106 (if (re-search-backward "^[[:alpha:]]+: *$" nil t) 107 (if (re-search-backward "^[[:alpha:]]+: *$" nil t)
107 (beginning-of-line) 108 (beginning-of-line)
108 (goto-char (point-min))) 109 (goto-char (point-min)))
@@ -113,7 +114,7 @@ Treats actions as defuns."
113Treats actions as defuns." 114Treats actions as defuns."
114 (end-of-line) 115 (end-of-line)
115 (if (re-search-forward "^[[:alpha:]]+: *$" nil t) 116 (if (re-search-forward "^[[:alpha:]]+: *$" nil t)
116 (progn (forward-line -1) (end-of-line)) 117 (beginning-of-line)
117 (goto-char (point-max))) 118 (goto-char (point-max)))
118 t) 119 t)
119 120
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index ff4256192c4..033ce883e5f 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -100,7 +100,7 @@ in the compilation output, and should return a transformed file name.")
100;;;###autoload 100;;;###autoload
101(defvar compilation-process-setup-function nil 101(defvar compilation-process-setup-function nil
102 "*Function to call to customize the compilation process. 102 "*Function to call to customize the compilation process.
103This functions is called immediately before the compilation process is 103This function is called immediately before the compilation process is
104started. It can be used to set any variables or functions that are used 104started. It can be used to set any variables or functions that are used
105while processing the output of the compilation process. The function 105while processing the output of the compilation process. The function
106is called with variables `compilation-buffer' and `compilation-window' 106is called with variables `compilation-buffer' and `compilation-window'
@@ -125,11 +125,6 @@ describing how the process finished.")
125Each function is called with two arguments: the compilation buffer, 125Each function is called with two arguments: the compilation buffer,
126and a string describing how the process finished.") 126and a string describing how the process finished.")
127 127
128(defvar compilation-last-buffer nil
129 "The most recent compilation buffer.
130A buffer becomes most recent when its compilation is started
131or when it is used with \\[next-error] or \\[compile-goto-error].")
132
133(defvar compilation-in-progress nil 128(defvar compilation-in-progress nil
134 "List of compilation processes now running.") 129 "List of compilation processes now running.")
135(or (assq 'compilation-in-progress minor-mode-alist) 130(or (assq 'compilation-in-progress minor-mode-alist)
@@ -176,8 +171,15 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
176 "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\ 171 "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
177\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4)) 172\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))
178 173
174 (edg-1
175 "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
176 1 2 nil (3 . 4))
177 (edg-2
178 "at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$"
179 2 1 nil 0)
180
179 (epc 181 (epc
180 "^Error [0-9]+ at (\\([0-9]*\\):\\([^)\n]+\\))" 2 1) 182 "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
181 183
182 (iar 184 (iar
183 "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:" 185 "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
@@ -187,8 +189,9 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
187 "^\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) :\ 189 "^\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) :\
188 \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5)) 190 \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5))
189 191
192 ;; fixme: should be `mips'
190 (irix 193 (irix
191 "^[a-z0-9/]+: \\(?:[eE]rror\\|[wW]arnin\\(g\\)\\|[iI]nf\\(o\\)\\)[0-9 ]*:\ 194 "^[-[:alnum:]_/]+: \\(?:[sS]evere\\|[eE]rror\\|[wW]arnin\\(g\\)\\|[iI]nf\\(o\\)\\)[0-9 ]*:\
192 \\([^,\" \n\t]+\\)\\(?:, line\\|:\\) \\([0-9]+\\):" 3 4 nil (1 . 2)) 195 \\([^,\" \n\t]+\\)\\(?:, line\\|:\\) \\([0-9]+\\):" 3 4 nil (1 . 2))
193 196
194 (java 197 (java
@@ -206,8 +209,8 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
206\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4)) 209\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4))
207 210
208 (gnu 211 (gnu
209 "^\\(?:[a-zA-Z][-a-zA-Z0-9.]+: ?\\)?\ 212 "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\)?\
210\\([/.]*[a-zA-Z]:?[^ \t\n:]*\\): ?\ 213\\([/.]*[a-zA-Z]:?[^ \t\n:]*\\|{standard input}\\): ?\
211\\([0-9]+\\)\\([.:]?\\)\\([0-9]+\\)?\ 214\\([0-9]+\\)\\([.:]?\\)\\([0-9]+\\)?\
212\\(?:-\\(?:\\([0-9]+\\)\\3\\)?\\.?\\([0-9]+\\)?\\)?:\ 215\\(?:-\\(?:\\([0-9]+\\)\\3\\)?\\.?\\([0-9]+\\)?\\)?:\
213\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\ 216\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
@@ -228,6 +231,7 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
228 (1 (compilation-error-properties 2 3 nil nil nil 0 nil) 231 (1 (compilation-error-properties 2 3 nil nil nil 0 nil)
229 append))) 232 append)))
230 233
234 ;; Should be lint-1, lint-2 (SysV lint)
231 (mips-1 235 (mips-1
232 " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1) 236 " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
233 (mips-2 237 (mips-2
@@ -238,7 +242,9 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
238: \\(?:error\\|warnin\\(g\\)\\) C[0-9]+:" 1 2 nil (3)) 242: \\(?:error\\|warnin\\(g\\)\\) C[0-9]+:" 1 2 nil (3))
239 243
240 (oracle 244 (oracle
241 "^Semantic error at line \\([0-9]+\\), column \\([0-9]+\\), file \\(.*\\):$" 245 "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
246\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
247\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
242 3 1 2) 248 3 1 2)
243 249
244 (perl 250 (perl
@@ -261,16 +267,13 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
261 nil 1 nil (3) nil (2 (compilation-face '(3)))) 267 nil 1 nil (3) nil (2 (compilation-face '(3))))
262 268
263 (sun 269 (sun
264 ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[a-zA-Z0-9 ]+, \\)?\ 270 ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
265File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?" 271File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
266 3 4 5 (1 . 2)) 272 3 4 5 (1 . 2))
267 273
268 (sun-ada 274 (sun-ada
269 "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3) 275 "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
270 276
271 (ultrix
272 "^\\(?:cfe\\|fort\\): \\(Warning\\)?[^:\n]*: \\([^ \n]*\\), line \\([0-9]+\\):" 2 3 nil (1))
273
274 (4bsd 277 (4bsd
275 "\\(?:^\\|:: \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\ 278 "\\(?:^\\|:: \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
276\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))) 279\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3)))
@@ -279,14 +282,14 @@ File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
279(defcustom compilation-error-regexp-alist 282(defcustom compilation-error-regexp-alist
280 (mapcar 'car compilation-error-regexp-alist-alist) 283 (mapcar 'car compilation-error-regexp-alist-alist)
281 "Alist that specifies how to match errors in compiler output. 284 "Alist that specifies how to match errors in compiler output.
282Note that on Unix exerything is a valid filename, so these 285Note that on Unix everything is a valid filename, so these
283matchers must make some common sense assumptions, which catch 286matchers must make some common sense assumptions, which catch
284normal cases. A shorter list will be lighter on resource usage. 287normal cases. A shorter list will be lighter on resource usage.
285 288
286Instead of an alist element, you can use a symbol, which is 289Instead of an alist element, you can use a symbol, which is
287looked up in `compilation-error-regexp-alist-alist'. You can see 290looked up in `compilation-error-regexp-alist-alist'. You can see
288the predefined symbols and their effects in the file 291the predefined symbols and their effects in the file
289`etc/compilation.txt' (linked below if your are customizing this). 292`etc/compilation.txt' (linked below if you are customizing this).
290 293
291Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK 294Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK
292HIGHLIGHT...]). If REGEXP matches, the FILE'th subexpression 295HIGHLIGHT...]). If REGEXP matches, the FILE'th subexpression
@@ -328,7 +331,7 @@ be added."
328 (list 'const (car elt))) 331 (list 'const (car elt)))
329 compilation-error-regexp-alist-alist)) 332 compilation-error-regexp-alist-alist))
330 :link `(file-link :tag "example file" 333 :link `(file-link :tag "example file"
331 ,(concat doc-directory "compilation.txt")) 334 ,(expand-file-name "compilation.txt" data-directory))
332 :group 'compilation) 335 :group 'compilation)
333 336
334(defvar compilation-directory nil 337(defvar compilation-directory nil
@@ -357,7 +360,7 @@ you may also want to change `compilation-page-delimiter'.")
357 (1 font-lock-variable-name-face) 360 (1 font-lock-variable-name-face)
358 (2 (compilation-face '(4 . 3)))) 361 (2 (compilation-face '(4 . 3))))
359 ;; Command output lines. Recognize `make[n]:' lines too. 362 ;; Command output lines. Recognize `make[n]:' lines too.
360 ("^\\([A-Za-z_0-9/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:" 363 ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
361 (1 font-lock-function-name-face) (3 compilation-line-face nil t)) 364 (1 font-lock-function-name-face) (3 compilation-line-face nil t))
362 (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1) 365 (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
363 ("^Compilation finished" . compilation-info-face) 366 ("^Compilation finished" . compilation-info-face)
@@ -427,7 +430,7 @@ You might also use mode hooks to specify it in certain modes, like this:
427(defvar compilation-locs ()) 430(defvar compilation-locs ())
428 431
429(defvar compilation-debug nil 432(defvar compilation-debug nil
430 "*Set this to `t' before creating a *compilation* buffer. 433 "*Set this to t before creating a *compilation* buffer.
431Then every error line will have a debug text property with the matcher that 434Then every error line will have a debug text property with the matcher that
432fit this line and the match data. Use `describe-text-properties'.") 435fit this line and the match data. Use `describe-text-properties'.")
433 436
@@ -447,17 +450,19 @@ starting the compilation process.")
447(defvar compile-history nil) 450(defvar compile-history nil)
448 451
449(defface compilation-warning-face 452(defface compilation-warning-face
450 '((((type tty) (class color)) (:foreground "cyan" :weight bold)) 453 '((((class color) (min-colors 16)) (:foreground "Orange" :weight bold))
451 (((class color)) (:foreground "Orange" :weight bold)) 454 (((class color)) (:foreground "cyan" :weight bold))
452 (t (:weight bold))) 455 (t (:weight bold)))
453 "Face used to highlight compiler warnings." 456 "Face used to highlight compiler warnings."
454 :group 'font-lock-highlighting-faces 457 :group 'font-lock-highlighting-faces
455 :version "21.4") 458 :version "21.4")
456 459
457(defface compilation-info-face 460(defface compilation-info-face
458 '((((type tty) (class color)) (:foreground "green" :weight bold)) 461 '((((class color) (min-colors 16) (background light))
459 (((class color) (background light)) (:foreground "Green3" :weight bold)) 462 (:foreground "Green3" :weight bold))
460 (((class color) (background dark)) (:foreground "Green" :weight bold)) 463 (((class color) (min-colors 16) (background dark))
464 (:foreground "Green" :weight bold))
465 (((class color)) (:foreground "green" :weight bold))
461 (t (:weight bold))) 466 (t (:weight bold)))
462 "Face used to highlight compiler warnings." 467 "Face used to highlight compiler warnings."
463 :group 'font-lock-highlighting-faces 468 :group 'font-lock-highlighting-faces
@@ -494,7 +499,8 @@ Faces `compilation-error-face', `compilation-warning-face',
494 499
495 500
496;; Used for compatibility with the old compile.el. 501;; Used for compatibility with the old compile.el.
497(defvar compilation-parsing-end nil) 502(defvaralias 'compilation-last-buffer 'next-error-last-buffer)
503(defvar compilation-parsing-end (make-marker))
498(defvar compilation-parse-errors-function nil) 504(defvar compilation-parse-errors-function nil)
499(defvar compilation-error-list nil) 505(defvar compilation-error-list nil)
500(defvar compilation-old-error-list nil) 506(defvar compilation-old-error-list nil)
@@ -518,6 +524,7 @@ Faces `compilation-error-face', `compilation-warning-face',
518 '(nil)) ; nil only isn't a property-change 524 '(nil)) ; nil only isn't a property-change
519 (cons (match-string-no-properties idx) dir)) 525 (cons (match-string-no-properties idx) dir))
520 mouse-face highlight 526 mouse-face highlight
527 keymap compilation-button-map
521 help-echo "mouse-2: visit current directory"))) 528 help-echo "mouse-2: visit current directory")))
522 529
523;; Data type `reverse-ordered-alist' retriever. This function retrieves the 530;; Data type `reverse-ordered-alist' retriever. This function retrieves the
@@ -528,6 +535,7 @@ Faces `compilation-error-face', `compilation-warning-face',
528;; may be nil. The other KEYs are ordered backwards so that growing line 535;; may be nil. The other KEYs are ordered backwards so that growing line
529;; numbers can be inserted in front and searching can abort after half the 536;; numbers can be inserted in front and searching can abort after half the
530;; list on average. 537;; list on average.
538(eval-when-compile ;Don't keep it at runtime if not needed.
531(defmacro compilation-assq (key alist) 539(defmacro compilation-assq (key alist)
532 `(let* ((l1 ,alist) 540 `(let* ((l1 ,alist)
533 (l2 (cdr l1))) 541 (l2 (cdr l1)))
@@ -538,7 +546,7 @@ Faces `compilation-error-face', `compilation-warning-face',
538 l2 (cdr l1))) 546 l2 (cdr l1)))
539 (if l2 (eq ,key (caar l2)))) 547 (if l2 (eq ,key (caar l2))))
540 l2 548 l2
541 (setcdr l1 (cons (list ,key) l2)))))) 549 (setcdr l1 (cons (list ,key) l2)))))))
542 550
543 551
544;; This function is the central driver, called when font-locking to gather 552;; This function is the central driver, called when font-locking to gather
@@ -556,17 +564,13 @@ Faces `compilation-error-face', `compilation-warning-face',
556 (setq dir (previous-single-property-change (point) 'directory) 564 (setq dir (previous-single-property-change (point) 'directory)
557 dir (if dir (or (get-text-property (1- dir) 'directory) 565 dir (if dir (or (get-text-property (1- dir) 'directory)
558 (get-text-property dir 'directory))))) 566 (get-text-property dir 'directory)))))
559 (setq file (cons file (car dir)) ; top of dir stack is current 567 (setq file (cons file (car dir)))))
560 file (or (gethash file compilation-locs)
561 (puthash file (list file fmt) compilation-locs)))))
562 ;; This message didn't mention one, get it from previous 568 ;; This message didn't mention one, get it from previous
563 (setq file (previous-single-property-change (point) 'message) 569 (setq file (previous-single-property-change (point) 'message)
564 file (or (if file 570 file (or (if file
565 (nth 2 (car (or (get-text-property (1- file) 'message) 571 (car (nth 2 (car (or (get-text-property (1- file) 'message)
566 (get-text-property file 'message))))) 572 (get-text-property file 'message))))))
567 ;; no previous either -- let font-lock continue 573 '("*unknown*"))))
568 (gethash (setq file '("*unknown*")) compilation-locs)
569 (puthash file (list file fmt) compilation-locs))))
570 ;; All of these fields are optional, get them only if we have an index, and 574 ;; All of these fields are optional, get them only if we have an index, and
571 ;; it matched some part of the message. 575 ;; it matched some part of the message.
572 (and line 576 (and line
@@ -579,75 +583,87 @@ Faces `compilation-error-face', `compilation-warning-face',
579 (setq col (match-string-no-properties col)) 583 (setq col (match-string-no-properties col))
580 (setq col (- (string-to-number col) compilation-first-column))) 584 (setq col (- (string-to-number col) compilation-first-column)))
581 (if (and end-col (setq end-col (match-string-no-properties end-col))) 585 (if (and end-col (setq end-col (match-string-no-properties end-col)))
582 (setq end-col (- (string-to-number end-col) compilation-first-column)) 586 (setq end-col (- (string-to-number end-col) compilation-first-column -1))
583 (if end-line (setq end-col -1))) 587 (if end-line (setq end-col -1)))
584 (if (consp type) ; not a preset type, check what it is. 588 (if (consp type) ; not a static type, check what it is.
585 (setq type (or (and (car type) (match-end (car type)) 1) 589 (setq type (or (and (car type) (match-end (car type)) 1)
586 (and (cdr type) (match-end (cdr type)) 0) 590 (and (cdr type) (match-end (cdr type)) 0)
587 2))) 591 2)))
588 ;; Get any (first) already existing marker (if any has one, all have one). 592 (compilation-internal-error-properties file line end-line col end-col type fmt)))
589 ;; Do this first, as the next assq`s may create new nodes. 593
590 (let ((marker (nth 3 (car (cdar (cddr file))))) 594(defun compilation-internal-error-properties (file line end-line col end-col type fmt)
591 (loc (compilation-assq line (cdr file))) 595 "Get the meta-info that will be added as text-properties.
592 end-loc) 596LINE, END-LINE, COL, END-COL are integers or nil.
593 (if end-line 597TYPE can be 0, 1, or 2.
594 (setq end-loc (compilation-assq end-line (cdr file)) 598FILE should be (ABSOLUTE-FILENAME) or (RELATIVE-FILENAME . DIRNAME) or nil."
595 end-loc (compilation-assq end-col end-loc)) 599 (unless file (setq file '("*unknown*")))
596 (if end-col ; use same line element 600 (setq file (compilation-get-file-structure file fmt))
597 (setq end-loc (compilation-assq end-col loc)))) 601 ;; Get first already existing marker (if any has one, all have one).
598 (setq loc (compilation-assq col loc)) 602 ;; Do this first, as the compilation-assq`s may create new nodes.
599 ;; If they are new, make the loc(s) reference the file they point to. 603 (let* ((marker-line (car (cddr file))) ; a line structure
600 (or (cdr loc) (setcdr loc (list line file))) 604 (marker (nth 3 (cadr marker-line))) ; its marker
601 (if end-loc 605 (compilation-error-screen-columns compilation-error-screen-columns)
602 (or (cdr end-loc) (setcdr end-loc (list (or end-line line) file)))) 606 end-marker loc end-loc)
603 ;; If we'd found a marker, ensure that the new locs also get markers 607 (if (not (and marker (marker-buffer marker)))
604 (when (and marker 608 (setq marker) ; no valid marker for this file
605 (not (or (cddr loc) (cddr end-loc))) ; maybe new node w/o marker 609 (setq loc (or line 1)) ; normalize no linenumber to line 1
606 (marker-buffer marker)) ; other marker still valid 610 (catch 'marker ; find nearest loc, at least one exists
607 (or line (setq line 1)) ; normalize no linenumber to line 1 611 (dolist (x (nthcdr 3 file)) ; loop over remaining lines
608 (catch 'marker ; find nearest loc, at least one exists 612 (if (> (car x) loc) ; still bigger
609 (dolist (x (cddr file)) 613 (setq marker-line x)
610 (if (> (or (car x) 1) line) 614 (if (> (- (or (car marker-line) 1) loc)
611 (setq marker x) 615 (- loc (car x))) ; current line is nearer
612 (if (eq (or (car x) 1) line) 616 (setq marker-line x))
613 (if (cdr (cddr x)) ; at least one other column 617 (throw 'marker t))))
614 (throw 'marker (setq marker x)) 618 (setq marker (nth 3 (cadr marker-line))
615 (if marker (throw 'marker t))) 619 marker-line (or (car marker-line) 1))
616 (throw 'marker (or marker (setq marker x))))))) 620 (with-current-buffer (marker-buffer marker)
617 (setq marker (if (eq (car (cddr marker)) col) 621 (save-restriction
618 (nthcdr 3 marker) 622 (widen)
619 (cddr marker)) 623 (goto-char (marker-position marker))
620 file compilation-error-screen-columns) 624 (when (or end-col end-line)
621 (with-current-buffer (marker-buffer (cddr marker)) 625 (beginning-of-line (- (or end-line line) marker-line -1))
622 (save-restriction 626 (if (< end-col 0)
623 (widen) 627 (end-of-line)
624 (goto-char (marker-position (cddr marker))) 628 (if compilation-error-screen-columns
625 (beginning-of-line (- line (car (cadr marker)) -1)) 629 (move-to-column end-col)
626 (if file ; original c.-error-screen-columns 630 (forward-char end-col)))
627 (move-to-column (car loc)) 631 (setq end-marker (list (point-marker))))
628 (forward-char (car loc))) 632 (beginning-of-line (if end-line
629 (setcdr (cdr loc) (point-marker)) 633 (- end-line line -1)
630 (when end-loc 634 (- loc marker-line -1)))
631 (beginning-of-line (- end-line line -1)) 635 (if col
632 (if (< end-col 0) 636 (if compilation-error-screen-columns
633 (end-of-line) 637 (move-to-column col)
634 (if file ; original c.-error-screen-columns 638 (forward-char col))
635 (move-to-column (car end-loc)) 639 (forward-to-indentation 0))
636 (forward-char (car end-loc)))) 640 (setq marker (list (point-marker))))))
637 (setcdr (cdr end-loc) (point-marker)))))) 641
638 ;; Must start with face 642 (setq loc (compilation-assq line (cdr file)))
639 `(face ,compilation-message-face 643 (if end-line
640 message (,loc ,type ,end-loc) 644 (setq end-loc (compilation-assq end-line (cdr file))
641 ,@(if compilation-debug 645 end-loc (compilation-assq end-col end-loc))
642 `(debug (,(assoc (with-no-warnings matcher) font-lock-keywords) 646 (if end-col ; use same line element
643 ,@(match-data)))) 647 (setq end-loc (compilation-assq end-col loc))))
644 help-echo ,(if col 648 (setq loc (compilation-assq col loc))
645 "mouse-2: visit this file, line and column" 649 ;; If they are new, make the loc(s) reference the file they point to.
646 (if line 650 (or (cdr loc) (setcdr loc `(,line ,file ,@marker)))
647 "mouse-2: visit this file and line" 651 (if end-loc
648 "mouse-2: visit this file")) 652 (or (cdr end-loc) (setcdr end-loc `(,(or end-line line) ,file ,@end-marker))))
649 keymap compilation-button-map 653
650 mouse-face highlight)))) 654 ;; Must start with face
655 `(face ,compilation-message-face
656 message (,loc ,type ,end-loc)
657 ,@(if compilation-debug
658 `(debug (,(assoc (with-no-warnings matcher) font-lock-keywords)
659 ,@(match-data))))
660 help-echo ,(if col
661 "mouse-2: visit this file, line and column"
662 (if line
663 "mouse-2: visit this file and line"
664 "mouse-2: visit this file"))
665 keymap compilation-button-map
666 mouse-face highlight)))
651 667
652(defun compilation-mode-font-lock-keywords () 668(defun compilation-mode-font-lock-keywords ()
653 "Return expressions to highlight in Compilation mode." 669 "Return expressions to highlight in Compilation mode."
@@ -686,12 +702,15 @@ Faces `compilation-error-face', `compilation-warning-face',
686 ;; error location. Let's do our best. 702 ;; error location. Let's do our best.
687 `(,(car item) 703 `(,(car item)
688 (0 (compilation-compat-error-properties 704 (0 (compilation-compat-error-properties
689 (funcall ',line (list* (match-string ,file) 705 (funcall ',line (cons (match-string ,file)
690 default-directory 706 (cons default-directory
691 ',(nthcdr 4 item)) 707 ',(nthcdr 4 item)))
692 ,(if col `(match-string ,col))))) 708 ,(if col `(match-string ,col)))))
693 (,file compilation-error-face t)) 709 (,file compilation-error-face t))
694 710
711 (unless (or (null (nth 5 item)) (integerp (nth 5 item)))
712 (error "HYPERLINK should be an integer: %s" (nth 5 item)))
713
695 `(,(nth 0 item) 714 `(,(nth 0 item)
696 715
697 ,@(when (integerp file) 716 ,@(when (integerp file)
@@ -729,7 +748,7 @@ Faces `compilation-error-face', `compilation-warning-face',
729Runs COMMAND, a shell command, in a separate process asynchronously 748Runs COMMAND, a shell command, in a separate process asynchronously
730with output going to the buffer `*compilation*'. 749with output going to the buffer `*compilation*'.
731 750
732If optional second arg COMINT is t the buffer will be in comint mode with 751If optional second arg COMINT is t the buffer will be in Comint mode with
733`compilation-shell-minor-mode'. 752`compilation-shell-minor-mode'.
734 753
735You can then use the command \\[next-error] to find the next error message 754You can then use the command \\[next-error] to find the next error message
@@ -737,6 +756,8 @@ and move to the source code that caused it.
737 756
738Interactively, prompts for the command if `compilation-read-command' is 757Interactively, prompts for the command if `compilation-read-command' is
739non-nil; otherwise uses `compile-command'. With prefix arg, always prompts. 758non-nil; otherwise uses `compile-command'. With prefix arg, always prompts.
759Additionally, with universal prefix arg, compilation buffer will be in
760comint mode, i.e. interactive.
740 761
741To run more than one compilation at once, start one and rename 762To run more than one compilation at once, start one and rename
742the \`*compilation*' buffer to some other name with 763the \`*compilation*' buffer to some other name with
@@ -748,11 +769,13 @@ The name used for the buffer is actually whatever is returned by
748the function in `compilation-buffer-name-function', so you can set that 769the function in `compilation-buffer-name-function', so you can set that
749to a function that generates a unique name." 770to a function that generates a unique name."
750 (interactive 771 (interactive
751 (if (or compilation-read-command current-prefix-arg) 772 (list
752 (list (read-from-minibuffer "Compile command: " 773 (if (or compilation-read-command current-prefix-arg)
753 (eval compile-command) nil nil 774 (read-from-minibuffer "Compile command: "
754 '(compile-history . 1))) 775 (eval compile-command) nil nil
755 (list (eval compile-command)))) 776 '(compile-history . 1))
777 (eval compile-command))
778 (consp current-prefix-arg)))
756 (unless (equal command (eval compile-command)) 779 (unless (equal command (eval compile-command))
757 (setq compile-command command)) 780 (setq compile-command command))
758 (save-some-buffers (not compilation-ask-about-save) nil) 781 (save-some-buffers (not compilation-ask-about-save) nil)
@@ -762,8 +785,8 @@ to a function that generates a unique name."
762;; run compile with the default command line 785;; run compile with the default command line
763(defun recompile () 786(defun recompile ()
764 "Re-compile the program including the current buffer. 787 "Re-compile the program including the current buffer.
765If this is run in a compilation-mode buffer, re-use the arguments from the 788If this is run in a Compilation mode buffer, re-use the arguments from the
766original use. Otherwise, it recompiles using `compile-command'." 789original use. Otherwise, recompile using `compile-command'."
767 (interactive) 790 (interactive)
768 (save-some-buffers (not compilation-ask-about-save) nil) 791 (save-some-buffers (not compilation-ask-about-save) nil)
769 (let ((default-directory (or compilation-directory default-directory))) 792 (let ((default-directory (or compilation-directory default-directory)))
@@ -773,9 +796,9 @@ original use. Otherwise, it recompiles using `compile-command'."
773(defcustom compilation-scroll-output nil 796(defcustom compilation-scroll-output nil
774 "*Non-nil to scroll the *compilation* buffer window as output appears. 797 "*Non-nil to scroll the *compilation* buffer window as output appears.
775 798
776Setting it causes the compilation-mode commands to put point at the 799Setting it causes the Compilation mode commands to put point at the
777end of their output window so that the end of the output is always 800end of their output window so that the end of the output is always
778visible rather than the begining." 801visible rather than the beginning."
779 :type 'boolean 802 :type 'boolean
780 :version "20.3" 803 :version "20.3"
781 :group 'compilation) 804 :group 'compilation)
@@ -822,11 +845,11 @@ Otherwise, construct a buffer name from MODE-NAME."
822The rest of the arguments are optional; for them, nil means use the default. 845The rest of the arguments are optional; for them, nil means use the default.
823 846
824MODE is the major mode to set in the compilation buffer. Mode 847MODE is the major mode to set in the compilation buffer. Mode
825may also be `t' meaning `compilation-shell-minor-mode' under `comint-mode'. 848may also be t meaning use `compilation-shell-minor-mode' under `comint-mode'.
826NAME-FUNCTION is a function called to name the buffer. 849NAME-FUNCTION is a function called to name the buffer.
827 850
828If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight 851If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight
829matching section of the visited source line; the default is to use the 852the matching section of the visited source line; the default is to use the
830global value of `compilation-highlight-regexp'. 853global value of `compilation-highlight-regexp'.
831 854
832Returns the compilation buffer created." 855Returns the compilation buffer created."
@@ -838,8 +861,8 @@ Returns the compilation buffer created."
838 (process-environment 861 (process-environment
839 (append 862 (append
840 compilation-environment 863 compilation-environment
841 (if (and (boundp 'system-uses-terminfo) 864 (if (if (boundp 'system-uses-terminfo) ; `if' for compiler warning
842 system-uses-terminfo) 865 system-uses-terminfo)
843 (list "TERM=dumb" "TERMCAP=" 866 (list "TERM=dumb" "TERMCAP="
844 (format "COLUMNS=%d" (window-width))) 867 (format "COLUMNS=%d" (window-width)))
845 (list "TERM=emacs" 868 (list "TERM=emacs"
@@ -903,7 +926,9 @@ Returns the compilation buffer created."
903 'compilation-revert-buffer) 926 'compilation-revert-buffer)
904 (set-window-start outwin (point-min)) 927 (set-window-start outwin (point-min))
905 (or (eq outwin (selected-window)) 928 (or (eq outwin (selected-window))
906 (set-window-point outwin (point))) 929 (set-window-point outwin (if compilation-scroll-output
930 (point)
931 (point-min))))
907 ;; The setup function is called before compilation-set-window-height 932 ;; The setup function is called before compilation-set-window-height
908 ;; so it can set the compilation-window-height buffer locally. 933 ;; so it can set the compilation-window-height buffer locally.
909 (if compilation-process-setup-function 934 (if compilation-process-setup-function
@@ -930,6 +955,7 @@ Returns the compilation buffer created."
930 ;; Fake modeline display as if `start-process' were run. 955 ;; Fake modeline display as if `start-process' were run.
931 (setq mode-line-process ":run") 956 (setq mode-line-process ":run")
932 (force-mode-line-update) 957 (force-mode-line-update)
958 (sit-for 0) ; Force redisplay
933 (let ((status (call-process shell-file-name nil outbuf nil "-c" 959 (let ((status (call-process shell-file-name nil outbuf nil "-c"
934 command))) 960 command)))
935 (cond ((numberp status) 961 (cond ((numberp status)
@@ -944,13 +970,17 @@ exited abnormally with code %d\n"
944 (concat status "\n"))) 970 (concat status "\n")))
945 (t 971 (t
946 (compilation-handle-exit 'bizarre status status)))) 972 (compilation-handle-exit 'bizarre status status))))
973 ;; Without async subprocesses, the buffer is not yet
974 ;; fontified, so fontify it now.
975 (let ((font-lock-verbose nil)) ; shut up font-lock messages
976 (font-lock-fontify-buffer))
947 (message "Executing `%s'...done" command))) 977 (message "Executing `%s'...done" command)))
948 (if (buffer-local-value 'compilation-scroll-output outbuf) 978 (if (buffer-local-value 'compilation-scroll-output outbuf)
949 (save-selected-window 979 (save-selected-window
950 (select-window outwin) 980 (select-window outwin)
951 (goto-char (point-max)))) 981 (goto-char (point-max))))
952 ;; Make it so the next C-x ` will use this buffer. 982 ;; Make it so the next C-x ` will use this buffer.
953 (setq compilation-last-buffer outbuf))) 983 (setq next-error-last-buffer outbuf)))
954 984
955(defun compilation-set-window-height (window) 985(defun compilation-set-window-height (window)
956 "Set the height of WINDOW according to `compilation-window-height'." 986 "Set the height of WINDOW according to `compilation-window-height'."
@@ -960,9 +990,8 @@ exited abnormally with code %d\n"
960 ;; If window is alone in its frame, aside from a minibuffer, 990 ;; If window is alone in its frame, aside from a minibuffer,
961 ;; don't change its height. 991 ;; don't change its height.
962 (not (eq window (frame-root-window (window-frame window)))) 992 (not (eq window (frame-root-window (window-frame window))))
963 ;; This save-current-buffer prevents us from changing the current 993 ;; Stef said that doing the saves in this order is safer:
964 ;; buffer, which might not be the same as the selected window's buffer. 994 (save-excursion
965 (save-current-buffer
966 (save-selected-window 995 (save-selected-window
967 (select-window window) 996 (select-window window)
968 (enlarge-window (- height (window-height)))))))) 997 (enlarge-window (- height (window-height))))))))
@@ -1132,20 +1161,30 @@ variable exists."
1132 "Marker to the location from where the next error will be found. 1161 "Marker to the location from where the next error will be found.
1133The global commands next/previous/first-error/goto-error use this.") 1162The global commands next/previous/first-error/goto-error use this.")
1134 1163
1164(defvar compilation-messages-start nil
1165 "Buffer position of the beginning of the compilation messages.
1166If nil, use the beginning of buffer.")
1167
1135;; A function name can't be a hook, must be something with a value. 1168;; A function name can't be a hook, must be something with a value.
1136(defconst compilation-turn-on-font-lock 'turn-on-font-lock) 1169(defconst compilation-turn-on-font-lock 'turn-on-font-lock)
1137 1170
1138(defun compilation-setup (&optional minor) 1171(defun compilation-setup (&optional minor)
1139 "Prepare the buffer for the compilation parsing commands to work." 1172 "Prepare the buffer for the compilation parsing commands to work.
1173Optional argument MINOR indicates this is called from
1174`compilation-minor-mode'."
1140 (make-local-variable 'compilation-current-error) 1175 (make-local-variable 'compilation-current-error)
1176 (make-local-variable 'compilation-messages-start)
1141 (make-local-variable 'compilation-error-screen-columns) 1177 (make-local-variable 'compilation-error-screen-columns)
1142 (make-local-variable 'overlay-arrow-position) 1178 (make-local-variable 'overlay-arrow-position)
1143 (setq compilation-last-buffer (current-buffer)) 1179 ;; Note that compilation-next-error-function is for interfacing
1180 ;; with the next-error function in simple.el, and it's only
1181 ;; coincidentally named similarly to compilation-next-error.
1182 (setq next-error-function 'compilation-next-error-function)
1144 (set (make-local-variable 'font-lock-extra-managed-props) 1183 (set (make-local-variable 'font-lock-extra-managed-props)
1145 '(directory message help-echo mouse-face debug)) 1184 '(directory message help-echo mouse-face debug))
1146 (set (make-local-variable 'compilation-locs) 1185 (set (make-local-variable 'compilation-locs)
1147 (make-hash-table :test 'equal :weakness 'value)) 1186 (make-hash-table :test 'equal :weakness 'value))
1148 ;; lazy-lock would never find the message unless it's scrolled to 1187 ;; lazy-lock would never find the message unless it's scrolled to.
1149 ;; jit-lock might fontify some things too late. 1188 ;; jit-lock might fontify some things too late.
1150 (set (make-local-variable 'font-lock-support-mode) nil) 1189 (set (make-local-variable 'font-lock-support-mode) nil)
1151 (set (make-local-variable 'font-lock-maximum-size) nil) 1190 (set (make-local-variable 'font-lock-maximum-size) nil)
@@ -1193,7 +1232,7 @@ Turning the mode on runs the normal hook `compilation-minor-mode-hook'."
1193 (font-lock-fontify-buffer))) 1232 (font-lock-fontify-buffer)))
1194 1233
1195(defun compilation-handle-exit (process-status exit-status msg) 1234(defun compilation-handle-exit (process-status exit-status msg)
1196 "Write msg in the current buffer and hack its mode-line-process." 1235 "Write MSG in the current buffer and hack its mode-line-process."
1197 (let ((buffer-read-only nil) 1236 (let ((buffer-read-only nil)
1198 (status (if compilation-exit-message-function 1237 (status (if compilation-exit-message-function
1199 (funcall compilation-exit-message-function 1238 (funcall compilation-exit-message-function
@@ -1257,8 +1296,16 @@ Just inserts the text, but uses `insert-before-markers'."
1257 (insert-before-markers string) 1296 (insert-before-markers string)
1258 (run-hooks 'compilation-filter-hook)))))) 1297 (run-hooks 'compilation-filter-hook))))))
1259 1298
1299;;; test if a buffer is a compilation buffer, assuming we're in the buffer
1300(defsubst compilation-buffer-internal-p ()
1301 "Test if inside a compilation buffer."
1302 (local-variable-p 'compilation-locs))
1303
1304;;; test if a buffer is a compilation buffer, using compilation-buffer-internal-p
1260(defsubst compilation-buffer-p (buffer) 1305(defsubst compilation-buffer-p (buffer)
1261 (local-variable-p 'compilation-locs buffer)) 1306 "Test if BUFFER is a compilation buffer."
1307 (with-current-buffer buffer
1308 (compilation-buffer-internal-p)))
1262 1309
1263(defmacro compilation-loop (< property-change 1+ error) 1310(defmacro compilation-loop (< property-change 1+ error)
1264 `(while (,< n 0) 1311 `(while (,< n 0)
@@ -1289,7 +1336,6 @@ Does NOT find the source line like \\[next-error]."
1289 (or (compilation-buffer-p (current-buffer)) 1336 (or (compilation-buffer-p (current-buffer))
1290 (error "Not in a compilation buffer")) 1337 (error "Not in a compilation buffer"))
1291 (or pt (setq pt (point))) 1338 (or pt (setq pt (point)))
1292 (setq compilation-last-buffer (current-buffer))
1293 (let* ((msg (get-text-property pt 'message)) 1339 (let* ((msg (get-text-property pt 'message))
1294 (loc (car msg)) 1340 (loc (car msg))
1295 last) 1341 last)
@@ -1327,25 +1373,6 @@ Does NOT find the source line like \\[previous-error]."
1327 (interactive "p") 1373 (interactive "p")
1328 (compilation-next-error (- n))) 1374 (compilation-next-error (- n)))
1329 1375
1330(defun next-error-no-select (n)
1331 "Move point to the next error in the compilation buffer and highlight match.
1332Prefix arg N says how many error messages to move forwards (or
1333backwards, if negative).
1334Finds and highlights the source line like \\[next-error], but does not
1335select the source buffer."
1336 (interactive "p")
1337 (next-error n)
1338 (pop-to-buffer compilation-last-buffer))
1339
1340(defun previous-error-no-select (n)
1341 "Move point to the previous error in the compilation buffer and highlight match.
1342Prefix arg N says how many error messages to move backwards (or
1343forwards, if negative).
1344Finds and highlights the source line like \\[previous-error], but does not
1345select the source buffer."
1346 (interactive "p")
1347 (next-error-no-select (- n)))
1348
1349(defun compilation-next-file (n) 1376(defun compilation-next-file (n)
1350 "Move point to the next error for a different file than the current one. 1377 "Move point to the next error for a different file than the current one.
1351Prefix arg N says how many files to move forwards (or backwards, if negative)." 1378Prefix arg N says how many files to move forwards (or backwards, if negative)."
@@ -1383,73 +1410,35 @@ Use this command in a compilation log buffer. Sets the mark at point there."
1383 1410
1384;; Return a compilation buffer. 1411;; Return a compilation buffer.
1385;; If the current buffer is a compilation buffer, return it. 1412;; If the current buffer is a compilation buffer, return it.
1386;; If compilation-last-buffer is set to a live buffer, use that.
1387;; Otherwise, look for a compilation buffer and signal an error 1413;; Otherwise, look for a compilation buffer and signal an error
1388;; if there are none. 1414;; if there are none.
1389(defun compilation-find-buffer (&optional other-buffer) 1415(defun compilation-find-buffer (&optional other-buffer)
1390 (if (and (not other-buffer) 1416 (next-error-find-buffer other-buffer 'compilation-buffer-internal-p))
1391 (compilation-buffer-p (current-buffer)))
1392 ;; The current buffer is a compilation buffer.
1393 (current-buffer)
1394 (if (and compilation-last-buffer (buffer-name compilation-last-buffer)
1395 (compilation-buffer-p compilation-last-buffer)
1396 (or (not other-buffer) (not (eq compilation-last-buffer
1397 (current-buffer)))))
1398 compilation-last-buffer
1399 (let ((buffers (buffer-list)))
1400 (while (and buffers (or (not (compilation-buffer-p (car buffers)))
1401 (and other-buffer
1402 (eq (car buffers) (current-buffer)))))
1403 (setq buffers (cdr buffers)))
1404 (if buffers
1405 (car buffers)
1406 (or (and other-buffer
1407 (compilation-buffer-p (current-buffer))
1408 ;; The current buffer is a compilation buffer.
1409 (progn
1410 (if other-buffer
1411 (message "This is the only compilation buffer."))
1412 (current-buffer)))
1413 (error "No compilation started!")))))))
1414 1417
1415;;;###autoload 1418;;;###autoload
1416(defun next-error (&optional n) 1419(defun compilation-next-error-function (n &optional reset)
1417 "Visit next compilation error message and corresponding source code.
1418Prefix arg N says how many error messages to move forwards (or
1419backwards, if negative).
1420
1421\\[next-error] normally uses the most recently started compilation or
1422grep buffer. However, it can operate on any buffer with output from
1423the \\[compile] and \\[grep] commands, or, more generally, on any
1424buffer in Compilation mode or with Compilation Minor mode enabled. To
1425specify use of a particular buffer for error messages, type
1426\\[next-error] in that buffer.
1427
1428Once \\[next-error] has chosen the buffer for error messages,
1429it stays with that buffer until you use it in some other buffer which
1430uses Compilation mode or Compilation Minor mode.
1431
1432See variable `compilation-error-regexp-alist' for customization ideas."
1433 (interactive "p") 1420 (interactive "p")
1434 (set-buffer (setq compilation-last-buffer (compilation-find-buffer))) 1421 (set-buffer (compilation-find-buffer))
1422 (when reset
1423 (setq compilation-current-error nil))
1435 (let* ((columns compilation-error-screen-columns) ; buffer's local value 1424 (let* ((columns compilation-error-screen-columns) ; buffer's local value
1436 (last 1) 1425 (last 1)
1437 (loc (compilation-next-error (or n 1) nil 1426 (loc (compilation-next-error (or n 1) nil
1438 (or compilation-current-error (point-min)))) 1427 (or compilation-current-error
1428 compilation-messages-start
1429 (point-min))))
1439 (end-loc (nth 2 loc)) 1430 (end-loc (nth 2 loc))
1440 (marker (point-marker))) 1431 (marker (point-marker)))
1441 (setq compilation-current-error (point-marker) 1432 (setq compilation-current-error (point-marker)
1442 overlay-arrow-position 1433 overlay-arrow-position
1443 (if (bolp) 1434 (if (bolp)
1444 compilation-current-error 1435 compilation-current-error
1445 (save-excursion 1436 (copy-marker (line-beginning-position)))
1446 (beginning-of-line)
1447 (point-marker)))
1448 loc (car loc)) 1437 loc (car loc))
1449 ;; If loc contains no marker, no error in that file has been visited. If 1438 ;; If loc contains no marker, no error in that file has been visited. If
1450 ;; the marker is invalid the buffer has been killed. So, recalculate all 1439 ;; the marker is invalid the buffer has been killed. So, recalculate all
1451 ;; markers for that file. 1440 ;; markers for that file.
1452 (unless (and (nthcdr 3 loc) (marker-buffer (nth 3 loc))) 1441 (unless (and (nth 3 loc) (marker-buffer (nth 3 loc)))
1453 (with-current-buffer (compilation-find-file marker (caar (nth 2 loc)) 1442 (with-current-buffer (compilation-find-file marker (caar (nth 2 loc))
1454 (or (cdar (nth 2 loc)) 1443 (or (cdar (nth 2 loc))
1455 default-directory)) 1444 default-directory))
@@ -1472,50 +1461,66 @@ See variable `compilation-error-regexp-alist' for customization ideas."
1472 (forward-char (car col)))) 1461 (forward-char (car col))))
1473 (beginning-of-line) 1462 (beginning-of-line)
1474 (skip-chars-forward " \t")) 1463 (skip-chars-forward " \t"))
1475 (if (nthcdr 3 col) 1464 (if (nth 3 col)
1476 (set-marker (nth 3 col) (point)) 1465 (set-marker (nth 3 col) (point))
1477 (setcdr (nthcdr 2 col) `(,(point-marker))))))))) 1466 (setcdr (nthcdr 2 col) `(,(point-marker)))))))))
1478 (compilation-goto-locus marker (nth 3 loc) (nth 3 end-loc)) 1467 (compilation-goto-locus marker (nth 3 loc) (nth 3 end-loc))
1479 (setcdr (nthcdr 3 loc) t))) ; Set this one as visited. 1468 (setcdr (nthcdr 3 loc) t))) ; Set this one as visited.
1480 1469
1481;;;###autoload (define-key ctl-x-map "`" 'next-error) 1470(defvar compilation-gcpro nil
1482 1471 "Internal variable used to keep some values from being GC'd.")
1483(defun previous-error (n) 1472(make-variable-buffer-local 'compilation-gcpro)
1484 "Visit previous compilation error message and corresponding source code. 1473
1485Prefix arg N says how many error messages to move backwards (or 1474(defun compilation-fake-loc (marker file &optional line col)
1486forwards, if negative). 1475 "Preassociate MARKER with FILE.
1487 1476FILE should be ABSOLUTE-FILENAME or (RELATIVE-FILENAME . DIRNAME).
1488This operates on the output from the \\[compile] and \\[grep] commands." 1477This is useful when you compile temporary files, but want
1489 (interactive "p") 1478automatic translation of the messages to the real buffer from
1490 (next-error (- n))) 1479which the temporary file came. This only works if done before a
1491 1480message about FILE appears!
1492(defun first-error (n) 1481
1493 "Restart at the first error. 1482Optional args LINE and COL default to 1 and beginning of
1494Visit corresponding source code. 1483indentation respectively. The marker is expected to reflect
1495With prefix arg N, visit the source code of the Nth error. 1484this. In the simplest case the marker points to the first line
1496This operates on the output from the \\[compile] command." 1485of the region that was saved to the temp file.
1497 (interactive "p") 1486
1498 (set-buffer (setq compilation-last-buffer (compilation-find-buffer))) 1487If you concatenate several regions into the temp file (e.g. a
1499 (setq compilation-current-error nil) 1488header with variable assignments and a code region), you must
1500 (next-error n)) 1489call this several times, once each for the last line of one
1501 1490region and the first line of the next region."
1502(defcustom compilation-context-lines next-screen-context-lines 1491 (or (consp file) (setq file (list file)))
1503 "*Display this many lines of leading context before message." 1492 (setq file (compilation-get-file-structure file))
1504 :type 'integer 1493 ;; Between the current call to compilation-fake-loc and the first occurrence
1494 ;; of an error message referring to `file', the data is only kept is the
1495 ;; weak hash-table compilation-locs, so we need to prevent this entry
1496 ;; in compilation-locs from being GC'd away. --Stef
1497 (push file compilation-gcpro)
1498 (let ((loc (compilation-assq (or line 1) (cdr file))))
1499 (setq loc (compilation-assq col loc))
1500 (if (cdr loc)
1501 (setcdr (cddr loc) (list marker))
1502 (setcdr loc (list line file marker)))
1503 loc))
1504
1505(defcustom compilation-context-lines 0
1506 "*Display this many lines of leading context before message.
1507If nil, don't scroll the compilation output window."
1508 :type '(choice integer (const :tag "No window scrolling" nil))
1505 :group 'compilation 1509 :group 'compilation
1506 :version "21.4") 1510 :version "21.4")
1507 1511
1508(defsubst compilation-set-window (w mk) 1512(defsubst compilation-set-window (w mk)
1509 ;; Align the compilation output window W with marker MK near top. 1513 "Align the compilation output window W with marker MK near top."
1510 (set-window-start w (save-excursion 1514 (if (integerp compilation-context-lines)
1511 (goto-char mk) 1515 (set-window-start w (save-excursion
1512 (beginning-of-line (- 1 compilation-context-lines)) 1516 (goto-char mk)
1513 (point))) 1517 (beginning-of-line (- 1 compilation-context-lines))
1518 (point))))
1514 (set-window-point w mk)) 1519 (set-window-point w mk))
1515 1520
1516(defun compilation-goto-locus (msg mk end-mk) 1521(defun compilation-goto-locus (msg mk end-mk)
1517 "Jump to an error MESSAGE and SOURCE. 1522 "Jump to an error corresponding to MSG at MK.
1518All arguments are markers. If SOURCE-END is non nil, mark is set there." 1523All arguments are markers. If END-MK is non nil, mark is set there."
1519 (if (eq (window-buffer (selected-window)) 1524 (if (eq (window-buffer (selected-window))
1520 (marker-buffer msg)) 1525 (marker-buffer msg))
1521 ;; If the compilation buffer window is selected, 1526 ;; If the compilation buffer window is selected,
@@ -1622,67 +1627,58 @@ Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
1622 (overlays-in (point-min) (point-max))) 1627 (overlays-in (point-min) (point-max)))
1623 buffer))) 1628 buffer)))
1624 1629
1625(defun compilation-normalize-filename (filename) 1630(defun compilation-get-file-structure (file &optional fmt)
1626 "Convert a filename string found in an error message to make it usable." 1631 "Retrieve FILE's file-structure or create a new one.
1627 1632FILE should be (ABSOLUTE-FILENAME) or (RELATIVE-FILENAME . DIRNAME)."
1628 ;; Check for a comint-file-name-prefix and prepend it if 1633
1629 ;; appropriate. (This is very useful for 1634 (or (gethash file compilation-locs)
1630 ;; compilation-minor-mode in an rlogin-mode buffer.) 1635 ;; File was not previously encountered, at least not in the form passed.
1631 (and (boundp 'comint-file-name-prefix) 1636 ;; Let's normalize it and look again.
1632 ;; If file name is relative, default-directory will 1637 (let ((filename (car file))
1633 ;; already contain the comint-file-name-prefix (done 1638 (default-directory (if (cdr file)
1634 ;; by compile-abbreviate-directory). 1639 (file-truename (cdr file))
1635 (file-name-absolute-p filename) 1640 default-directory)))
1636 (setq filename 1641
1637 (concat (with-no-warnings 'comint-file-name-prefix) filename))) 1642 ;; Check for a comint-file-name-prefix and prepend it if appropriate.
1638 1643 ;; (This is very useful for compilation-minor-mode in an rlogin-mode
1639 ;; If compilation-parse-errors-filename-function is 1644 ;; buffer.)
1640 ;; defined, use it to process the filename. 1645 (if (boundp 'comint-file-name-prefix)
1641 (when compilation-parse-errors-filename-function 1646 (if (file-name-absolute-p filename)
1642 (setq filename 1647 (setq filename
1643 (funcall compilation-parse-errors-filename-function 1648 (concat (with-no-warnings comint-file-name-prefix) filename))
1644 filename))) 1649 (setq default-directory
1645 1650 (file-truename
1646 ;; Some compilers (e.g. Sun's java compiler, reportedly) 1651 (concat (with-no-warnings comint-file-name-prefix) default-directory)))))
1647 ;; produce bogus file names like "./bar//foo.c" for file 1652
1648 ;; "bar/foo.c"; expand-file-name will collapse these into 1653 ;; If compilation-parse-errors-filename-function is
1649 ;; "/foo.c" and fail to find the appropriate file. So we 1654 ;; defined, use it to process the filename.
1650 ;; look for doubled slashes in the file name and fix them 1655 (when compilation-parse-errors-filename-function
1651 ;; up in the buffer. 1656 (setq filename
1652 (setq filename (command-line-normalize-file-name filename))) 1657 (funcall compilation-parse-errors-filename-function
1653 1658 filename)))
1654 1659
1655;; If directory DIR is a subdir of ORIG or of ORIG's parent, 1660 ;; Some compilers (e.g. Sun's java compiler, reportedly) produce bogus
1656;; return a relative name for it starting from ORIG or its parent. 1661 ;; file names like "./bar//foo.c" for file "bar/foo.c";
1657;; ORIG-EXPANDED is an expanded version of ORIG. 1662 ;; expand-file-name will collapse these into "/foo.c" and fail to find
1658;; PARENT-EXPANDED is an expanded version of ORIG's parent. 1663 ;; the appropriate file. So we look for doubled slashes in the file
1659;; Those two args could be computed here, but we run faster by 1664 ;; name and fix them.
1660;; having the caller compute them just once. 1665 (setq filename (command-line-normalize-file-name filename))
1661(defun compile-abbreviate-directory (dir orig orig-expanded parent-expanded) 1666
1662 ;; Apply canonical abbreviations to DIR first thing. 1667 ;; Now eliminate any "..", because find-file would get them wrong.
1663 ;; Those abbreviations are already done in the other arguments passed. 1668 ;; Make relative and absolute filenames, with or without links, the
1664 (setq dir (abbreviate-file-name dir)) 1669 ;; same.
1665 1670 (setq filename
1666 ;; Check for a comint-file-name-prefix and prepend it if appropriate. 1671 (list (abbreviate-file-name
1667 ;; (This is very useful for compilation-minor-mode in an rlogin-mode 1672 (file-truename (if (cdr file)
1668 ;; buffer.) 1673 (expand-file-name filename)
1669 (if (boundp 'comint-file-name-prefix) 1674 filename)))))
1670 (setq dir (concat comint-file-name-prefix dir))) 1675
1671 1676 ;; Store it for the possibly unnormalized name
1672 (if (and (> (length dir) (length orig-expanded)) 1677 (puthash file
1673 (string= orig-expanded 1678 ;; Retrieve or create file-structure for normalized name
1674 (substring dir 0 (length orig-expanded)))) 1679 (or (gethash filename compilation-locs)
1675 (setq dir 1680 (puthash filename (list filename fmt) compilation-locs))
1676 (concat orig 1681 compilation-locs))))
1677 (substring dir (length orig-expanded)))))
1678 (if (and (> (length dir) (length parent-expanded))
1679 (string= parent-expanded
1680 (substring dir 0 (length parent-expanded))))
1681 (setq dir
1682 (concat (file-name-directory
1683 (directory-file-name orig))
1684 (substring dir (length parent-expanded)))))
1685 dir)
1686 1682
1687(add-to-list 'debug-ignored-errors "^No more [-a-z ]+s yet$") 1683(add-to-list 'debug-ignored-errors "^No more [-a-z ]+s yet$")
1688 1684
@@ -1691,17 +1687,26 @@ Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
1691(defun compile-buffer-substring (n) (if n (match-string n))) 1687(defun compile-buffer-substring (n) (if n (match-string n)))
1692 1688
1693(defun compilation-compat-error-properties (err) 1689(defun compilation-compat-error-properties (err)
1694 ;; Map old-style ERROR to new-style MESSAGE. 1690 "Map old-style error ERR to new-style message."
1695 (let* ((dst (cdr err)) 1691 ;; Old-style structure is (MARKER (FILE DIR) LINE COL) or
1696 (loc (cond ((markerp dst) (list nil nil nil dst)) 1692 ;; (MARKER . MARKER).
1697 ((consp dst) 1693 (let ((dst (cdr err)))
1698 (list (nth 2 dst) (nth 1 dst) 1694 (if (markerp dst)
1699 (cons (cdar dst) (caar dst))))))) 1695 ;; Must start with a face, for font-lock.
1700 ;; Must start with a face, for font-lock. 1696 `(face nil
1701 `(face nil 1697 message ,(list (list nil nil nil dst) 2)
1702 message ,(list loc 2) 1698 help-echo "mouse-2: visit the source location"
1703 help-echo "mouse-2: visit the source location" 1699 keymap compilation-button-map
1704 mouse-face highlight))) 1700 mouse-face highlight)
1701 ;; Too difficult to do it by hand: dispatch to the normal code.
1702 (let* ((file (pop dst))
1703 (line (pop dst))
1704 (col (pop dst))
1705 (filename (pop file))
1706 (dirname (pop file))
1707 (fmt (pop file)))
1708 (compilation-internal-error-properties
1709 (cons filename dirname) line nil col nil 2 fmt)))))
1705 1710
1706(defun compilation-compat-parse-errors (limit) 1711(defun compilation-compat-parse-errors (limit)
1707 (when compilation-parse-errors-function 1712 (when compilation-parse-errors-function
@@ -1739,10 +1744,12 @@ Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
1739 (goto-char limit) 1744 (goto-char limit)
1740 nil) 1745 nil)
1741 1746
1747;; Beware: this is not only compatiblity code. New code stil uses it. --Stef
1742(defun compilation-forget-errors () 1748(defun compilation-forget-errors ()
1743 ;; In case we hit the same file/line specs, we want to recompute a new 1749 ;; In case we hit the same file/line specs, we want to recompute a new
1744 ;; marker for them, so flush our cache. 1750 ;; marker for them, so flush our cache.
1745 (setq compilation-locs (make-hash-table :test 'equal :weakness 'value)) 1751 (setq compilation-locs (make-hash-table :test 'equal :weakness 'value))
1752 (setq compilation-gcpro nil)
1746 ;; FIXME: the old code reset the directory-stack, so maybe we should 1753 ;; FIXME: the old code reset the directory-stack, so maybe we should
1747 ;; put a `directory change' marker of some sort, but where? -stef 1754 ;; put a `directory change' marker of some sort, but where? -stef
1748 ;; 1755 ;;
@@ -1754,9 +1761,19 @@ Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
1754 ;; something equivalent to point-max. So we speculatively move 1761 ;; something equivalent to point-max. So we speculatively move
1755 ;; compilation-current-error to point-max (since the external package 1762 ;; compilation-current-error to point-max (since the external package
1756 ;; won't know that it should do it). --stef 1763 ;; won't know that it should do it). --stef
1757 (setq compilation-current-error (point-max))) 1764 (setq compilation-current-error nil)
1765 (let* ((proc (get-buffer-process (current-buffer)))
1766 (mark (if proc (process-mark proc)))
1767 (pos (or mark (point-max))))
1768 (setq compilation-messages-start
1769 ;; In the future, ignore the text already present in the buffer.
1770 ;; Since many process filter functions insert before markers,
1771 ;; we need to put ours just before the insertion point rather
1772 ;; than at the insertion point. If that's not possible, then
1773 ;; don't use a marker. --Stef
1774 (if (> pos (point-min)) (copy-marker (1- pos)) pos))))
1758 1775
1759(provide 'compile) 1776(provide 'compile)
1760 1777
1761;;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c 1778;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
1762;;; compile.el ends here 1779;;; compile.el ends here
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index e13198fb240..c651e06b899 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -926,12 +926,9 @@ the faces: please specify bold, italic, underline, shadow and box.)
926(defun cperl-putback-char (c) ; Emacs 19 926(defun cperl-putback-char (c) ; Emacs 19
927 (set 'unread-command-events (list c))) ; Avoid undefined warning 927 (set 'unread-command-events (list c))) ; Avoid undefined warning
928 928
929(if (boundp 'unread-command-events) 929(if cperl-xemacs-p
930 (if cperl-xemacs-p 930 (defun cperl-putback-char (c) ; XEmacs >= 19.12
931 (defun cperl-putback-char (c) ; XEmacs >= 19.12 931 (setq unread-command-events (list (eval '(character-to-event c))))))
932 (setq unread-command-events (list (eval '(character-to-event c))))))
933 (defun cperl-putback-char (c) ; XEmacs <= 19.11
934 (set 'unread-command-event (eval '(character-to-event c))))) ; Avoid warnings
935 932
936(or (fboundp 'uncomment-region) 933(or (fboundp 'uncomment-region)
937 (defun uncomment-region (beg end) 934 (defun uncomment-region (beg end)
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index ef5d1eba998..184077f6a3a 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1248,7 +1248,11 @@ where they were found."
1248 1248
1249 1249
1250(defun etags-tags-completion-table () 1250(defun etags-tags-completion-table ()
1251 (let ((table (make-vector 511 0))) 1251 (let ((table (make-vector 511 0))
1252 (point-max (/ (float (point-max)) 100.0))
1253 (msg-fmt (format
1254 "Making tags completion table for %s...%%d%%%%"
1255 buffer-file-name)))
1252 (save-excursion 1256 (save-excursion
1253 (goto-char (point-min)) 1257 (goto-char (point-min))
1254 ;; This monster regexp matches an etags tag line. 1258 ;; This monster regexp matches an etags tag line.
@@ -1264,11 +1268,12 @@ where they were found."
1264\\([-a-zA-Z0-9_+*$?:]+\\)[^-a-zA-Z0-9_+*$?:\177]*\\)\177\ 1268\\([-a-zA-Z0-9_+*$?:]+\\)[^-a-zA-Z0-9_+*$?:\177]*\\)\177\
1265\\(\\([^\n\001]+\\)\001\\)?\\([0-9]+\\)?,\\([0-9]+\\)?\n" 1269\\(\\([^\n\001]+\\)\001\\)?\\([0-9]+\\)?,\\([0-9]+\\)?\n"
1266 nil t) 1270 nil t)
1267 (intern (if (match-beginning 5) 1271 (intern (prog1 (if (match-beginning 5)
1268 ;; There is an explicit tag name. 1272 ;; There is an explicit tag name.
1269 (buffer-substring (match-beginning 5) (match-end 5)) 1273 (buffer-substring (match-beginning 5) (match-end 5))
1270 ;; No explicit tag name. Best guess. 1274 ;; No explicit tag name. Best guess.
1271 (buffer-substring (match-beginning 3) (match-end 3))) 1275 (buffer-substring (match-beginning 3) (match-end 3)))
1276 (message msg-fmt (/ (point) point-max)))
1272 table))) 1277 table)))
1273 table)) 1278 table))
1274 1279
@@ -1866,6 +1871,7 @@ directory specification."
1866 (or gotany 1871 (or gotany
1867 (error "File %s not in current tags tables" file))))) 1872 (error "File %s not in current tags tables" file)))))
1868 (with-current-buffer "*Tags List*" 1873 (with-current-buffer "*Tags List*"
1874 (require 'apropos)
1869 (apropos-mode) 1875 (apropos-mode)
1870 (setq buffer-read-only t))) 1876 (setq buffer-read-only t)))
1871 1877
@@ -1884,6 +1890,7 @@ directory specification."
1884 (funcall tags-apropos-function regexp)))) 1890 (funcall tags-apropos-function regexp))))
1885 (etags-tags-apropos-additional regexp)) 1891 (etags-tags-apropos-additional regexp))
1886 (with-current-buffer "*Tags List*" 1892 (with-current-buffer "*Tags List*"
1893 (require 'apropos)
1887 (apropos-mode) 1894 (apropos-mode)
1888 ;; apropos-mode is derived from fundamental-mode and it kills 1895 ;; apropos-mode is derived from fundamental-mode and it kills
1889 ;; all local variables. 1896 ;; all local variables.
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 11553a1fdb6..53165fbecb7 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -153,7 +153,7 @@
153;;; Code: 153;;; Code:
154 154
155;; TODO 155;; TODO
156;; Support for hideshow, align. 156;; Support for align.
157;; OpenMP, preprocessor highlighting. 157;; OpenMP, preprocessor highlighting.
158 158
159(defvar comment-auto-fill-only-comments) 159(defvar comment-auto-fill-only-comments)
@@ -589,6 +589,53 @@ characters long.")
589(make-variable-buffer-local 'f90-cache-position) 589(make-variable-buffer-local 'f90-cache-position)
590 590
591 591
592;; Hideshow support.
593(defconst f90-end-block-re
594 (concat "^[ \t0-9]*\\<end\\>[ \t]*"
595 (regexp-opt '("do" "if" "forall" "function" "interface"
596 "module" "program" "select" "subroutine"
597 "type" "where" ) t)
598 "[ \t]*\\sw*")
599 "Regexp matching the end of a \"block\" of F90 code.
600Used in the F90 entry in `hs-special-modes-alist'.")
601
602;; Ignore the fact that FUNCTION, SUBROUTINE, WHERE, FORALL have a
603;; following "(". DO, CASE, IF can have labels; IF must be
604;; accompanied by THEN.
605;; A big problem is that many of these statements can be broken over
606;; lines, even with embedded comments. We only try to handle this for
607;; IF ... THEN statements, assuming and hoping it will be less common
608;; for other constructs. We match up to one new-line, provided ")
609;; THEN" appears on one line. Matching on just ") THEN" is no good,
610;; since that includes ELSE branches.
611;; For a fully accurate solution, hideshow would probably have to be
612;; modified to allow functions as well as regexps to be used to
613;; specify block start and end positions.
614(defconst f90-start-block-re
615 (concat
616 "^[ \t0-9]*" ; statement number
617 "\\(\\("
618 "\\(\\sw+[ \t]*:[ \t]*\\)?" ; structure label
619 "\\(do\\|select[ \t]*case\\|if[ \t]*(.*\n?.*)[ \t]*then\\|"
620 ;; Distinguish WHERE block from isolated WHERE.
621 "\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)"
622 "\\|"
623 "program\\|interface\\|module\\|type\\|function\\|subroutine"
624 ;; ") THEN" at line end. Problem - also does ELSE.
625;;; "\\|.*)[ \t]*then[ \t]*\\($\\|!\\)"
626 "\\)"
627 "[ \t]*")
628 "Regexp matching the start of a \"block\" of F90 code.
629A simple regexp cannot do this in fully correct fashion, so this
630tries to strike a compromise between complexity and flexibility.
631Used in the F90 entry in `hs-special-modes-alist'.")
632
633;; hs-special-modes-alist is autoloaded.
634(add-to-list 'hs-special-modes-alist
635 `(f90-mode ,f90-start-block-re ,f90-end-block-re
636 "!" f90-end-of-block nil))
637
638
592;; Imenu support. 639;; Imenu support.
593(defvar f90-imenu-generic-expression 640(defvar f90-imenu-generic-expression
594 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]") 641 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]")
@@ -850,14 +897,16 @@ line-number before indenting."
850 897
851(defsubst f90-get-present-comment-type () 898(defsubst f90-get-present-comment-type ()
852 "If point lies within a comment, return the string starting the comment. 899 "If point lies within a comment, return the string starting the comment.
853For example, \"!\" or \"!!\"." 900For example, \"!\" or \"!!\", followed by the appropriate amount of
901whitespace, if any."
902 ;; Include the whitespace for consistent auto-filling of comment blocks.
854 (save-excursion 903 (save-excursion
855 (when (f90-in-comment) 904 (when (f90-in-comment)
856 (beginning-of-line) 905 (beginning-of-line)
857 (re-search-forward "!+" (line-end-position)) 906 (re-search-forward "!+[ \t]*" (line-end-position))
858 (while (f90-in-string) 907 (while (f90-in-string)
859 (re-search-forward "!+" (line-end-position))) 908 (re-search-forward "!+[ \t]*" (line-end-position)))
860 (match-string 0)))) 909 (match-string-no-properties 0))))
861 910
862(defsubst f90-equal-symbols (a b) 911(defsubst f90-equal-symbols (a b)
863 "Compare strings A and B neglecting case and allowing for nil value." 912 "Compare strings A and B neglecting case and allowing for nil value."
@@ -1519,6 +1568,7 @@ is non-nil, call `f90-update-line' after inserting the continuation marker."
1519 (cond ((f90-in-string) 1568 (cond ((f90-in-string)
1520 (insert "&\n&")) 1569 (insert "&\n&"))
1521 ((f90-in-comment) 1570 ((f90-in-comment)
1571 (delete-horizontal-space 'backwards) ; remove trailing whitespace
1522 (insert "\n" (f90-get-present-comment-type))) 1572 (insert "\n" (f90-get-present-comment-type)))
1523 (t (insert "&") 1573 (t (insert "&")
1524 (or no-update (f90-update-line)) 1574 (or no-update (f90-update-line))
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
new file mode 100644
index 00000000000..2cd62eeecee
--- /dev/null
+++ b/lisp/progmodes/flymake.el
@@ -0,0 +1,2504 @@
1;;; flymake.el -- a universal on-the-fly syntax checker
2
3;; Copyright (C) 2003 Free Software Foundation
4
5;; Author: Pavel Kobiakov <pk_at_work@yahoo.com>
6;; Maintainer: Pavel Kobiakov <pk_at_work@yahoo.com>
7;; Version: 0.3
8;; Keywords: c languages tools
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28;;
29;; Flymake is a minor Emacs mode performing on-the-fly syntax
30;; checks using the external syntax check tool (for C/C++ this
31;; is usually the compiler)
32
33;;; Code:
34
35;;;_* Provide
36(provide 'flymake)
37
38;;;; [[ Overlay compatibility
39(autoload 'make-overlay "overlay" "Overlay compatibility kit." t)
40(autoload 'overlayp "overlay" "Overlay compatibility kit." t)
41(autoload 'overlays-in "overlay" "Overlay compatibility kit." t)
42(autoload 'delete-overlay "overlay" "Overlay compatibility kit." t)
43(autoload 'overlay-put "overlay" "Overlay compatibility kit." t)
44(autoload 'overlay-get "overlay" "Overlay compatibility kit." t)
45;;;; ]]
46
47;;;; [[ cross-emacs compatibility routines
48(defvar flymake-emacs
49 (cond
50 ((string-match "XEmacs" emacs-version) 'xemacs)
51 (t 'emacs)
52 )
53 "Currently used emacs flavor"
54)
55
56(defun flymake-makehash(&optional test)
57 (cond
58 ((equal flymake-emacs 'xemacs) (if test (make-hash-table :test test) (make-hash-table)))
59 (t (makehash test))
60 )
61)
62
63(defun flymake-time-to-float(&optional tm)
64 "Convert `current-time` to a float number of seconds."
65 (multiple-value-bind (s0 s1 s2) (or tm (current-time))
66 (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2)))
67)
68(defun flymake-float-time()
69 (cond
70 ((equal flymake-emacs 'xemacs) (flymake-time-to-float (current-time)))
71 (t (float-time))
72 )
73)
74
75(defun flymake-replace-regexp-in-string(regexp rep str)
76 (cond
77 ((equal flymake-emacs 'xemacs) (replace-in-string str regexp rep))
78 (t (replace-regexp-in-string regexp rep str))
79 )
80)
81
82(defun flymake-split-string-remove-empty-edges(str pattern)
83 "split, then remove first and/or last in case it's empty"
84 (let* ((splitted (split-string str pattern)))
85 (if (and (> (length splitted) 0) (= 0 (length (elt splitted 0))))
86 (setq splitted (cdr splitted))
87 )
88 (if (and (> (length splitted) 0) (= 0 (length (elt splitted (1- (length splitted))))))
89 (setq splitted (reverse (cdr (reverse splitted))))
90 )
91 splitted
92 )
93)
94(defun flymake-split-string(str pattern)
95 (cond
96 ((equal flymake-emacs 'xemacs) (flymake-split-string-remove-empty-edges str pattern))
97 (t (split-string str pattern))
98 )
99)
100
101(defun flymake-get-temp-dir()
102 (cond
103 ((equal flymake-emacs 'xemacs) (temp-directory))
104 (t temporary-file-directory)
105 )
106)
107
108(defun flymake-line-beginning-position()
109 (save-excursion
110 (beginning-of-line)
111 (point)
112 )
113)
114
115(defun flymake-line-end-position()
116 (save-excursion
117 (end-of-line)
118 (point)
119 )
120)
121
122(defun flymake-popup-menu(pos menu-data)
123 (cond
124 ((equal flymake-emacs 'xemacs)
125 (let* ((x-pos (nth 0 (nth 0 pos)))
126 (y-pos (nth 1 (nth 0 pos)))
127 (fake-event-props '(button 1 x 1 y 1)))
128 (setq fake-event-props (plist-put fake-event-props 'x x-pos))
129 (setq fake-event-props (plist-put fake-event-props 'y y-pos))
130 (popup-menu (flymake-make-xemacs-menu menu-data) (make-event 'button-press fake-event-props))
131 )
132 )
133 (t (x-popup-menu pos (flymake-make-emacs-menu menu-data)))
134 )
135)
136
137(defun flymake-make-emacs-menu(menu-data)
138 (let* ((menu-title (nth 0 menu-data))
139 (menu-items (nth 1 menu-data))
140 (menu-commands nil))
141
142 (setq menu-commands (mapcar (lambda (foo)
143 (cons (nth 0 foo) (nth 1 foo)))
144 menu-items))
145 (list menu-title (cons "" menu-commands))
146 )
147)
148
149(defun flymake-nop()
150)
151
152(defun flymake-make-xemacs-menu(menu-data)
153 (let* ((menu-title (nth 0 menu-data))
154 (menu-items (nth 1 menu-data))
155 (menu-commands nil))
156 (setq menu-commands (mapcar (lambda (foo)
157 (vector (nth 0 foo) (or (nth 1 foo) '(flymake-nop)) t))
158 menu-items))
159 (cons menu-title menu-commands)
160 )
161)
162
163(defun flymake-xemacs-window-edges(&optional window)
164 (let ((edges (window-pixel-edges window))
165 tmp)
166 (setq tmp edges)
167 (setcar tmp (/ (car tmp) (face-width 'default)))
168 (setq tmp (cdr tmp))
169 (setcar tmp (/ (car tmp) (face-height 'default)))
170 (setq tmp (cdr tmp))
171 (setcar tmp (/ (car tmp) (face-width 'default)))
172 (setq tmp (cdr tmp))
173 (setcar tmp (/ (car tmp) (face-height 'default)))
174 edges
175 )
176)
177
178(defun flymake-current-row()
179 "return current row in current frame"
180 (cond
181 ((equal flymake-emacs 'xemacs) (count-lines (window-start) (point)))
182 (t (+ (car (cdr (window-edges))) (count-lines (window-start) (point))))
183 )
184)
185
186(defun flymake-selected-frame()
187 (cond
188 ((equal flymake-emacs 'xemacs) (selected-window))
189 (t (selected-frame))
190 )
191)
192
193;;;; ]]
194
195(defcustom flymake-log-level -1
196 "Logging level, only messages with level > flymake-log-level will not be logged
197-1 = NONE, 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG"
198 :group 'flymake
199 :type 'integer
200)
201
202(defun flymake-log(level text &rest args)
203 "Log a message with optional arguments"
204 (if (<= level flymake-log-level)
205 (let* ((msg (apply 'format text args)))
206 (message msg)
207 ;(with-temp-buffer
208 ; (insert msg)
209 ; (insert "\n")
210 ; (flymake-save-buffer-in-file (current-buffer) "d:/flymake.log" t) ; make log file name customizable
211 ;)
212 )
213 )
214)
215
216(defun flymake-ins-after(list pos val)
217 "insert val into list after position pos"
218 (let ((tmp (copy-sequence list))) ; (???)
219 (setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp)))
220 tmp
221 )
222)
223
224(defun flymake-set-at(list pos val)
225 "set val at position pos in list"
226 (let ((tmp (copy-sequence list))) ; (???)
227 (setcar (nthcdr pos tmp) val)
228 tmp
229 )
230)
231
232(defvar flymake-pid-to-names(flymake-makehash)
233 "pid -> source buffer name, output file name mapping"
234)
235
236(defun flymake-reg-names(pid source-buffer-name)
237 "Save into in pid map"
238 (unless (stringp source-buffer-name)
239 (error "invalid buffer name")
240 )
241 (puthash pid (list source-buffer-name) flymake-pid-to-names)
242)
243
244(defun flymake-get-source-buffer-name(pid)
245 "Return buffer name stored in pid map"
246 (nth 0 (gethash pid flymake-pid-to-names))
247)
248
249(defun flymake-unreg-names(pid)
250 "Delete pid->buffer name mapping"
251 (remhash pid flymake-pid-to-names)
252)
253
254(defun flymake-get-buffer-var(buffer var-name)
255 "switch to buffer if necessary and return local variable var"
256 (unless (bufferp buffer)
257 (error "invalid buffer")
258 )
259
260 (if (eq buffer (current-buffer))
261 (symbol-value var-name)
262 ;else
263 (save-excursion
264 (set-buffer buffer)
265 (symbol-value var-name)
266 )
267 )
268)
269
270(defun flymake-set-buffer-var(buffer var-name var-value)
271 "switch to buffer if necessary and set local variable var-name to var-value"
272 (unless (bufferp buffer)
273 (error "invalid buffer")
274 )
275
276 (if (eq buffer (current-buffer))
277 (set var-name var-value)
278 ;else
279 (save-excursion
280 (set-buffer buffer)
281 (set var-name var-value)
282 )
283 )
284)
285
286(defvar flymake-buffer-data(flymake-makehash)
287 "data specific to syntax check tool, in name-value pairs"
288)
289(make-variable-buffer-local 'flymake-buffer-data)
290(defun flymake-get-buffer-data(buffer)
291 (flymake-get-buffer-var buffer 'flymake-buffer-data)
292)
293(defun flymake-set-buffer-data(buffer data)
294 (flymake-set-buffer-var buffer 'flymake-buffer-data data)
295)
296(defun flymake-get-buffer-value(buffer name)
297 (gethash name (flymake-get-buffer-data buffer))
298)
299(defun flymake-set-buffer-value(buffer name value)
300 (puthash name value (flymake-get-buffer-data buffer))
301)
302
303(defvar flymake-output-residual nil
304 ""
305)
306(make-variable-buffer-local 'flymake-output-residual)
307(defun flymake-get-buffer-output-residual(buffer)
308 (flymake-get-buffer-var buffer 'flymake-output-residual)
309)
310(defun flymake-set-buffer-output-residual(buffer residual)
311 (flymake-set-buffer-var buffer 'flymake-output-residual residual)
312)
313
314(defcustom flymake-allowed-file-name-masks '((".+\\.c$" flymake-simple-make-init flymake-simple-cleanup flymake-get-real-file-name)
315 (".+\\.cpp$" flymake-simple-make-init flymake-simple-cleanup flymake-get-real-file-name)
316 (".+\\.xml$" flymake-xml-init flymake-simple-cleanup flymake-get-real-file-name)
317 (".+\\.html?$" flymake-xml-init flymake-simple-cleanup flymake-get-real-file-name)
318 (".+\\.cs$" flymake-simple-make-init flymake-simple-cleanup flymake-get-real-file-name)
319 (".+\\.pl$" flymake-perl-init flymake-simple-cleanup flymake-get-real-file-name)
320 (".+\\.h$" flymake-master-make-header-init flymake-master-cleanup flymake-get-real-file-name)
321 (".+\\.java$" flymake-simple-make-java-init flymake-simple-java-cleanup flymake-get-real-file-name)
322 (".+[0-9]+\\.tex$" flymake-master-tex-init flymake-master-cleanup flymake-get-real-file-name)
323 (".+\\.tex$" flymake-simple-tex-init flymake-simple-cleanup flymake-get-real-file-name)
324 (".+\\.idl$" flymake-simple-make-init flymake-simple-cleanup flymake-get-real-file-name)
325; (".+\\.cpp$" 1)
326; (".+\\.java$" 3)
327; (".+\\.h$" 2 (".+\\.cpp$" ".+\\.c$")
328; ("[ \t]*#[ \t]*include[ \t]*\"\\([\w0-9/\\_\.]*[/\\]*\\)\\(%s\\)\"" 1 2))
329; (".+\\.idl$" 1)
330; (".+\\.odl$" 1)
331; (".+[0-9]+\\.tex$" 2 (".+\\.tex$")
332; ("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2 ))
333; (".+\\.tex$" 1)
334 )
335 "*Files syntax checking is allowed for"
336 :group 'flymake
337 :type '(repeat (string symbol symbol symbol))
338)
339
340(defun flymake-get-file-name-mode-and-masks(file-name)
341 "return the corresponding entry from flymake-allowed-file-name-masks"
342 (unless (stringp file-name)
343 (error "invalid file-name")
344 )
345 (let ((count (length flymake-allowed-file-name-masks))
346 (idx 0)
347 (mode-and-masks nil))
348 (while (and (not mode-and-masks) (< idx count))
349 (if (string-match (nth 0 (nth idx flymake-allowed-file-name-masks)) file-name)
350 (setq mode-and-masks (cdr (nth idx flymake-allowed-file-name-masks)))
351 )
352 (setq idx (1+ idx))
353 )
354 (flymake-log 3 "file %s, init=%s" file-name (car mode-and-masks))
355 mode-and-masks
356 )
357)
358
359(defun flymake-can-syntax-check-file(file-name)
360 "Determine whether we can syntax check file-name: nil if cannot, non-nil if can"
361 (if (flymake-get-init-function file-name)
362 t
363 ;else
364 nil
365 )
366)
367
368(defun flymake-get-init-function(file-name)
369 "return init function to be used for the file"
370 (let* ((init-f (nth 0 (flymake-get-file-name-mode-and-masks file-name))))
371 ;(flymake-log 0 "calling %s" init-f)
372 ;(funcall init-f (current-buffer))
373 )
374 (nth 0 (flymake-get-file-name-mode-and-masks file-name))
375)
376
377(defun flymake-get-cleanup-function(file-name)
378 "return cleanup function to be used for the file"
379 (nth 1 (flymake-get-file-name-mode-and-masks file-name))
380)
381
382(defun flymake-get-real-file-name-function(file-name)
383 ""
384 (or (nth 2 (flymake-get-file-name-mode-and-masks file-name)) 'flymake-get-real-file-name)
385)
386
387(defcustom flymake-buildfile-dirs '("." ".." "../.." "../../.." "../../../.." "../../../../.." "../../../../../.." "../../../../../../.." "../../../../../../../.." "../../../../../../../../.." "../../../../../../../../../.." "../../../../../../../../../../..")
388 "dirs to look for buildfile"
389 :group 'flymake
390 :type '(repeat (string))
391)
392
393(defvar flymake-find-buildfile-cache (flymake-makehash 'equal))
394(defun flymake-get-buildfile-from-cache(dir-name)
395 (gethash dir-name flymake-find-buildfile-cache)
396)
397(defun flymake-add-buildfile-to-cache(dir-name buildfile)
398 (puthash dir-name buildfile flymake-find-buildfile-cache)
399)
400(defun flymake-clear-buildfile-cache()
401 (clrhash flymake-find-buildfile-cache)
402)
403
404(defun flymake-find-buildfile(buildfile-name source-dir-name dirs)
405 "find buildfile (i.e. Makefile, build.xml, etc.) starting from current directory. Return its path or nil if not found"
406 (if (flymake-get-buildfile-from-cache source-dir-name)
407 (progn
408 (flymake-get-buildfile-from-cache source-dir-name)
409 )
410 ;else
411 (let* ((buildfile-dir nil)
412 (buildfile nil)
413 (dir-count (length dirs))
414 (dir-idx 0)
415 (found nil))
416
417 (while (and (not found) (< dir-idx dir-count))
418
419 (setq buildfile-dir (concat source-dir-name (nth dir-idx dirs)))
420 (setq buildfile (concat buildfile-dir "/" buildfile-name))
421
422 (when (file-exists-p buildfile)
423 (setq found t)
424 )
425
426 (setq dir-idx (1+ dir-idx))
427 )
428 (if found
429 (progn
430 (flymake-log 3 "found buildfile at %s/%s" buildfile-dir buildfile-name)
431 (flymake-add-buildfile-to-cache source-dir-name buildfile-dir)
432 buildfile-dir
433 )
434 ;else
435 (progn
436 (flymake-log 3 "buildfile for %s not found" source-dir-name)
437 nil
438 )
439 )
440 )
441 )
442)
443
444(defun flymake-fix-path-name(name)
445 "replace all occurences of '\' with '/'"
446 (when name
447 (let* ((new-name (flymake-replace-regexp-in-string "[\\]" "/" (expand-file-name name)))
448 (last-char (elt new-name (1- (length new-name)))))
449 (setq new-name (flymake-replace-regexp-in-string "\\./" "" new-name))
450 (if (equal "/" (char-to-string last-char))
451 (setq new-name (substring new-name 0 (1- (length new-name))))
452 )
453 new-name
454 )
455 )
456)
457
458(defun flymake-same-files(file-name-one file-name-two)
459 "t if file-name-one and file-name-two actually point to the same file"
460 (equal (flymake-fix-path-name file-name-one) (flymake-fix-path-name file-name-two))
461)
462
463(defun flymake-ensure-ends-with-slash(path)
464 (if (not (= (elt path (1- (length path))) (string-to-char "/")))
465 (concat path "/")
466 ;else
467 path
468 )
469)
470
471(defun flymake-get-common-path-prefix(string-one string-two)
472 "return common prefix for two paths"
473 (when (and string-one string-two)
474 (let* ((slash-pos-one -1)
475 (slash-pos-two -1)
476 (done nil)
477 (prefix nil))
478
479 (setq string-one (flymake-ensure-ends-with-slash string-one))
480 (setq string-two (flymake-ensure-ends-with-slash string-two))
481
482 (while (not done)
483 (setq slash-pos-one (string-match "/" string-one (1+ slash-pos-one)))
484 (setq slash-pos-two (string-match "/" string-two (1+ slash-pos-two)))
485
486 (if (and slash-pos-one slash-pos-two
487 (= slash-pos-one slash-pos-two)
488 (string= (substring string-one 0 slash-pos-one) (substring string-two 0 slash-pos-two)))
489 (progn
490 (setq prefix (substring string-one 0 (1+ slash-pos-one)))
491 )
492 ;else
493 (setq done t)
494 )
495 )
496 prefix
497 )
498 )
499)
500
501(defun flymake-build-relative-path(from-dir to-dir)
502 "return rel: from-dir/rel == to-dir"
503 (if (not (equal (elt from-dir 0) (elt to-dir 0)))
504 (error "first chars in paths %s, %s must be equal (same drive)" from-dir to-dir)
505 ;else
506 (let* ((from (flymake-ensure-ends-with-slash (flymake-fix-path-name from-dir)))
507 (to (flymake-ensure-ends-with-slash (flymake-fix-path-name to-dir)))
508 (prefix (flymake-get-common-path-prefix from to))
509 (from-suffix (substring from (length prefix)))
510 (up-count (length (flymake-split-string from-suffix "[/]")))
511 (to-suffix (substring to (length prefix)))
512 (idx 0)
513 (rel nil))
514
515 (if (and (> (length to-suffix) 0) (equal "/" (char-to-string (elt to-suffix 0))))
516 (setq to-suffix (substring to-suffix 1))
517 )
518
519 (while (< idx up-count)
520 (if (> (length rel) 0)
521 (setq rel (concat rel "/"))
522 )
523 (setq rel (concat rel ".."))
524 (setq idx (1+ idx))
525 )
526 (if (> (length rel) 0)
527 (setq rel (concat rel "/"))
528 )
529 (if (> (length to-suffix) 0)
530 (setq rel (concat rel to-suffix))
531 )
532
533 (or rel "./")
534 )
535 )
536)
537
538(defcustom flymake-master-file-dirs '("." "./src" "./UnitTest")
539 "dirs where to llok for master files"
540 :group 'flymake
541 :type '(repeat (string))
542)
543
544(defcustom flymake-master-file-count-limit 32
545 "max number of master files to check"
546 :group 'flymake
547 :type 'integer
548)
549
550(defun flymake-find-possible-master-files(file-name master-file-dirs masks)
551 "find (by name and location) all posible master files, which are .cpp and .c for and .h.
552Files are searched for starting from the .h directory and max max-level parent dirs.
553File contents are not checked."
554 (let* ((dir-idx 0)
555 (dir-count (length master-file-dirs))
556 (files nil)
557 (done nil)
558 (masks-count (length masks)))
559
560 (while (and (not done) (< dir-idx dir-count))
561 (let* ((dir (concat (flymake-fix-path-name (file-name-directory file-name)) "/" (nth dir-idx master-file-dirs)))
562 (masks-idx 0))
563 (while (and (file-exists-p dir) (not done) (< masks-idx masks-count))
564 (let* ((mask (nth masks-idx masks))
565 (dir-files (directory-files dir t mask))
566 (file-count (length dir-files))
567 (file-idx 0))
568
569 (flymake-log 3 "dir %s, %d file(s) for mask %s" dir file-count mask)
570 (while (and (not done) (< file-idx file-count))
571 (when (not (file-directory-p (nth file-idx dir-files)))
572 (setq files (cons (nth file-idx dir-files) files))
573 (when (>= (length files) flymake-master-file-count-limit)
574 (flymake-log 3 "master file count limit (%d) reached" flymake-master-file-count-limit)
575 (setq done t)
576 )
577 )
578 (setq file-idx (1+ file-idx))
579 )
580 )
581 (setq masks-idx (1+ masks-idx))
582 )
583 )
584 (setq dir-idx (1+ dir-idx))
585 )
586 (when files
587 (setq flymake-included-file-name (file-name-nondirectory file-name))
588 (setq files (sort files 'flymake-master-file-compare))
589 (setq flymake-included-file-name nil)
590 )
591 (flymake-log 3 "found %d possible master file(s)" (length files))
592 files
593 )
594)
595
596(defvar flymake-included-file-name nil ; this is used to pass a parameter to a sort predicate below
597 ""
598)
599
600(defun flymake-master-file-compare(file-one file-two)
601 "used in sort to move most possible file names to the beginning of the list (File.h -> File.cpp moved to top"
602 (and (equal (file-name-sans-extension flymake-included-file-name)
603 (file-name-sans-extension (file-name-nondirectory file-one)))
604 (not (equal file-one file-two))
605 )
606)
607
608(defcustom flymake-check-file-limit 8192
609 "max number of chars to look at when checking possible master file"
610 :group 'flymake
611 :type 'integer
612)
613
614(defun flymake-check-patch-master-file-buffer(master-file-temp-buffer
615 master-file-name patched-master-file-name
616 source-file-name patched-source-file-name
617 include-dirs regexp-list)
618 "check whether master-file-name is indeed a master file for source-file-name.
619For .cpp master file this means it includes source-file-name (.h).
620If yes, patch a copy of master-file-name to include patched-source-file-name instead of source-file-name.
621Whenether a buffer for master-file-name exists, use it as a source instead of reading master file from disk"
622 (let* ((found nil)
623 (regexp (format (nth 0 regexp-list) ; "[ \t]*#[ \t]*include[ \t]*\"\\([\w0-9/\\_\.]*[/\\]*\\)\\(%s\\)\""
624 (file-name-nondirectory source-file-name)))
625 (path-idx (nth 1 regexp-list))
626 (name-idx (nth 2 regexp-list))
627 (inc-path nil)
628 (inc-name nil)
629 (search-limit flymake-check-file-limit))
630 (save-excursion
631 (unwind-protect
632 (progn
633 (set-buffer master-file-temp-buffer)
634 (when (> search-limit (point-max))
635 (setq search-limit (point-max))
636 )
637 (flymake-log 3 "checking %s against regexp %s" master-file-name regexp)
638 (goto-char (point-min))
639 (while (and (< (point) search-limit) (re-search-forward regexp search-limit t))
640 (let* ((match-beg (match-beginning name-idx))
641 (match-end (match-end name-idx)))
642
643 (flymake-log 3 "found possible match for %s" (file-name-nondirectory source-file-name))
644 (setq inc-path (match-string path-idx))
645 (setq inc-name (match-string name-idx))
646 (when (string= inc-name (file-name-nondirectory source-file-name))
647 (flymake-log 3 "inc-path=%s inc-name=%s" inc-path inc-name)
648 (when (flymake-check-include source-file-name inc-path inc-name include-dirs)
649 (setq found t)
650 ; replace-match is not used here as it fails in xemacs with
651 ; 'last match not a buffer' error as check-includes calls replace-in-string
652 (flymake-replace-region (current-buffer) match-beg match-end
653 (file-name-nondirectory patched-source-file-name))
654 )
655 )
656 (forward-line 1)
657 )
658 )
659 (when found
660 (flymake-save-buffer-in-file (current-buffer) patched-master-file-name)
661 )
662 )
663 ;+(flymake-log 3 "killing buffer %s" (buffer-name master-file-temp-buffer))
664 (kill-buffer master-file-temp-buffer)
665 )
666 )
667 ;+(flymake-log 3 "check-patch master file %s: %s" master-file-name found)
668 (when found
669 (flymake-log 2 "found master file %s" master-file-name)
670 )
671 found
672 )
673)
674
675(defun flymake-replace-region(buffer beg end rep)
676 "replace text in buffer in region (beg; end) with rep"
677 (save-excursion
678 (delete-region beg end)
679 (goto-char beg)
680 (insert rep)
681 )
682)
683
684(defun flymake-read-file-to-temp-buffer(file-name)
685 "isert contents of file-name into newly created temp buffer"
686 (let* ((temp-buffer (get-buffer-create (generate-new-buffer-name (concat "flymake:" (file-name-nondirectory file-name))))))
687 (save-excursion
688 (set-buffer temp-buffer)
689 (insert-file-contents file-name)
690 )
691 temp-buffer
692 )
693)
694
695(defun flymake-copy-buffer-to-temp-buffer(buffer)
696 "copy contents of buffer into newly created temp buffer"
697 (let ((contents nil)
698 (temp-buffer nil))
699 (save-excursion
700 (set-buffer buffer)
701 (setq contents (buffer-string))
702
703 (setq temp-buffer (get-buffer-create (generate-new-buffer-name (concat "flymake:" (buffer-name buffer)))))
704 (set-buffer temp-buffer)
705 (insert contents)
706 )
707 temp-buffer
708 )
709)
710
711(defun flymake-check-include(source-file-name inc-path inc-name include-dirs)
712 "t if source-file-name is the one found via include dirs using inc-path and inc-name"
713 (if (file-name-absolute-p inc-path)
714 (flymake-same-files source-file-name (concat inc-path "/" inc-name))
715 ;else
716 (let* ((count (length include-dirs))
717 (idx 0)
718 (file-name nil)
719 (found nil))
720 (while (and (not found) (< idx count))
721 (setq file-name (concat (file-name-directory source-file-name) "/" (nth idx include-dirs)))
722 (if (> (length inc-path) 0)
723 (setq file-name (concat file-name "/" inc-path))
724 )
725 (setq file-name (concat file-name "/" inc-name))
726 (when (flymake-same-files source-file-name file-name)
727 (setq found t)
728 )
729 (setq idx (1+ idx))
730 )
731 found
732 )
733 )
734)
735
736(defun flymake-find-buffer-for-file(file-name)
737 "buffer if there exists a buffer visiting file-name, nil otherwise"
738 (let ((buffer-name (get-file-buffer file-name)))
739 (if buffer-name
740 (get-buffer buffer-name)
741 )
742 )
743)
744
745(defun flymake-create-master-file(source-file-name patched-source-file-name get-incl-dirs-f create-temp-f masks include-regexp-list)
746 "save source-file-name with a different name, find master file, patch it and save it to."
747 (let* ((possible-master-files (flymake-find-possible-master-files source-file-name flymake-master-file-dirs masks))
748 (master-file-count (length possible-master-files))
749 (idx 0)
750 (temp-buffer nil)
751 (master-file-name nil)
752 (patched-master-file-name nil)
753 (found nil))
754
755 (while (and (not found) (< idx master-file-count))
756 (setq master-file-name (nth idx possible-master-files))
757 (setq patched-master-file-name (funcall create-temp-f master-file-name "flymake_master"))
758 (if (flymake-find-buffer-for-file master-file-name)
759 (setq temp-buffer (flymake-copy-buffer-to-temp-buffer (flymake-find-buffer-for-file master-file-name)))
760 ;else
761 (setq temp-buffer (flymake-read-file-to-temp-buffer master-file-name))
762 )
763 (setq found
764 (flymake-check-patch-master-file-buffer
765 temp-buffer
766 master-file-name
767 patched-master-file-name
768 source-file-name
769 patched-source-file-name
770 (funcall get-incl-dirs-f (file-name-directory master-file-name))
771 include-regexp-list))
772 (setq idx (1+ idx))
773 )
774 (if found
775 (list master-file-name patched-master-file-name)
776 ;else
777 (progn
778 (flymake-log 3 "none of %d master file(s) checked includes %s" master-file-count
779 (file-name-nondirectory source-file-name))
780 nil
781 )
782 )
783 )
784)
785
786(defun flymake-save-buffer-in-file(buffer file-name)
787 (or buffer
788 (error "invalid buffer")
789 )
790 (save-excursion
791 (save-restriction
792 (set-buffer buffer)
793 (widen)
794 (make-directory (file-name-directory file-name) 1)
795 (write-region (point-min) (point-max) file-name nil 566)
796 )
797 )
798 (flymake-log 3 "saved buffer %s in file %s" (buffer-name buffer) file-name)
799)
800
801(defun flymake-save-string-to-file(file-name data)
802 "save string data to file file-name"
803 (write-region data nil file-name nil 566)
804)
805
806(defun flymake-read-file-to-string(file-name)
807 "read file contents and return them as a string"
808 (with-temp-buffer
809 (insert-file-contents file-name)
810 (buffer-substring (point-min) (point-max))
811 )
812)
813
814(defun flymake-process-filter(process output)
815 "flymake process filter: parse output, highlight err lines"
816 (let* ((pid (process-id process))
817 (source-buffer (get-buffer (flymake-get-source-buffer-name pid))))
818
819 (flymake-log 3 "received %d byte(s) of output from process %d" (length output) pid)
820 (when source-buffer
821 (flymake-parse-output-and-residual source-buffer output)
822 )
823 )
824)
825
826(defun flymake-process-sentinel(process event)
827 "Sentinel for syntax check buffers"
828 (if (memq (process-status process) '(signal exit))
829 (let*((exit-status (process-exit-status process))
830 (command (process-command process))
831 (pid (process-id process))
832 (source-buffer (get-buffer (flymake-get-source-buffer-name pid)))
833 (cleanup-f (flymake-get-cleanup-function (buffer-file-name source-buffer))))
834
835 (flymake-log 2 "process %d exited with code %d" pid exit-status)
836 (condition-case err
837 (progn
838 (flymake-log 3 "cleaning up using %s" cleanup-f)
839 (funcall cleanup-f source-buffer)
840
841 (flymake-unreg-names pid)
842 (delete-process process)
843
844 (when source-buffer
845 (save-excursion
846 (set-buffer source-buffer)
847
848 (flymake-parse-residual source-buffer)
849 (flymake-post-syntax-check source-buffer)
850 (flymake-set-buffer-is-running source-buffer nil)
851 )
852 )
853 )
854 (error
855 (let ((err-str (format "Error in process sentinel for buffer %s: %s"
856 source-buffer (error-message-string err))))
857 (flymake-log 0 err-str)
858 (flymake-set-buffer-is-running source-buffer nil)
859 )
860 )
861 )
862 )
863 )
864)
865
866(defun flymake-post-syntax-check(source-buffer)
867 ""
868 (flymake-set-buffer-err-info source-buffer (flymake-get-buffer-new-err-info source-buffer))
869 (flymake-set-buffer-new-err-info source-buffer nil)
870
871 (flymake-set-buffer-err-info source-buffer (flymake-fix-line-numbers
872 (flymake-get-buffer-err-info source-buffer)
873 1
874 (flymake-count-lines source-buffer)))
875 (flymake-delete-own-overlays source-buffer)
876 (flymake-highlight-err-lines source-buffer (flymake-get-buffer-err-info source-buffer))
877
878 (let ((err-count (flymake-get-err-count (flymake-get-buffer-err-info source-buffer) "e"))
879 (warn-count (flymake-get-err-count (flymake-get-buffer-err-info source-buffer) "w")))
880
881 (flymake-log 2 "%s: %d error(s), %d warning(s) in %.2f second(s)"
882 (buffer-name source-buffer) err-count warn-count
883 (- (flymake-float-time) (flymake-get-buffer-check-start-time source-buffer)))
884 (flymake-set-buffer-check-start-time source-buffer nil)
885 (if (and (equal 0 err-count) (equal 0 warn-count))
886 (if (equal 0 exit-status)
887 (flymake-report-status source-buffer "" "") ; PASSED
888 ;else
889 (if (not (flymake-get-buffer-check-was-interrupted source-buffer))
890 (flymake-report-fatal-status (current-buffer) "CFGERR"
891 (format "Configuration error has occured while running %s" command))
892 ;else
893 (flymake-report-status source-buffer nil "") ; "STOPPED"
894 )
895 )
896 ;else
897 (flymake-report-status source-buffer (format "%d/%d" err-count warn-count) "")
898 )
899 )
900)
901
902(defun flymake-parse-output-and-residual(source-buffer output)
903 "split output into lines, merge in residual if necessary"
904 (save-excursion
905 (set-buffer source-buffer)
906 (let* ((buffer-residual (flymake-get-buffer-output-residual source-buffer))
907 (total-output (if buffer-residual (concat buffer-residual output) output))
908 (lines-and-residual (flymake-split-output total-output))
909 (lines (nth 0 lines-and-residual))
910 (new-residual (nth 1 lines-and-residual)))
911
912 (flymake-set-buffer-output-residual source-buffer new-residual)
913 (flymake-set-buffer-new-err-info source-buffer (flymake-parse-err-lines
914 (flymake-get-buffer-new-err-info source-buffer)
915 source-buffer lines))
916 )
917 )
918)
919
920(defun flymake-parse-residual(source-buffer)
921 "parse residual if it's non empty"
922 (save-excursion
923 (set-buffer source-buffer)
924 (when (flymake-get-buffer-output-residual source-buffer)
925 (flymake-set-buffer-new-err-info source-buffer (flymake-parse-err-lines
926 (flymake-get-buffer-new-err-info source-buffer)
927 source-buffer
928 (list (flymake-get-buffer-output-residual source-buffer))))
929 (flymake-set-buffer-output-residual source-buffer nil)
930 )
931 )
932)
933
934(defvar flymake-err-info nil
935 "sorted list of line numbers and lists of err info in the form (file, err-text)."
936)
937(make-variable-buffer-local 'flymake-err-info)
938(defun flymake-get-buffer-err-info(buffer)
939 (flymake-get-buffer-var buffer 'flymake-err-info)
940)
941(defun flymake-set-buffer-err-info(buffer err-info)
942 (flymake-set-buffer-var buffer 'flymake-err-info err-info)
943)
944(defun flymake-er-make-er(line-no line-err-info-list)
945 (list line-no line-err-info-list)
946)
947(defun flymake-er-get-line(err-info)
948 (nth 0 err-info)
949)
950(defun flymake-er-get-line-err-info-list(err-info)
951 (nth 1 err-info)
952)
953
954(defvar flymake-new-err-info nil
955 "the same as flymake -err-info, effective when a syntax check is in progress"
956)
957(make-variable-buffer-local 'flymake-new-err-info)
958(defun flymake-get-buffer-new-err-info(buffer)
959 (flymake-get-buffer-var buffer 'flymake-new-err-info)
960)
961(defun flymake-set-buffer-new-err-info(buffer new-err-info)
962 (flymake-set-buffer-var buffer 'flymake-new-err-info new-err-info)
963)
964
965;; getters/setters for line-err-info: (file, line, type, text).
966(defun flymake-ler-make-ler(file line type text &optional full-file)
967 (list file line type text full-file)
968)
969(defun flymake-ler-get-file(line-err-info)
970 (nth 0 line-err-info)
971)
972(defun flymake-ler-get-line(line-err-info)
973 (nth 1 line-err-info)
974)
975(defun flymake-ler-get-type(line-err-info)
976 (nth 2 line-err-info)
977)
978(defun flymake-ler-get-text(line-err-info)
979 (nth 3 line-err-info)
980)
981(defun flymake-ler-get-full-file(line-err-info)
982 (nth 4 line-err-info)
983)
984(defun flymake-ler-set-file(line-err-info file)
985 (flymake-ler-make-ler file
986 (flymake-ler-get-line line-err-info)
987 (flymake-ler-get-type line-err-info)
988 (flymake-ler-get-text line-err-info)
989 (flymake-ler-get-full-file line-err-info))
990)
991(defun flymake-ler-set-full-file(line-err-info full-file)
992 (flymake-ler-make-ler (flymake-ler-get-file line-err-info)
993 (flymake-ler-get-line line-err-info)
994 (flymake-ler-get-type line-err-info)
995 (flymake-ler-get-text line-err-info)
996 full-file)
997)
998(defun flymake-ler-set-line(line-err-info line)
999 (flymake-ler-make-ler (flymake-ler-get-file line-err-info)
1000 line
1001 (flymake-ler-get-type line-err-info)
1002 (flymake-ler-get-text line-err-info)
1003 (flymake-ler-get-full-file line-err-info))
1004)
1005
1006(defun flymake-get-line-err-count(line-err-info-list type)
1007 "return number of errors of specified type - e or w"
1008 (let* ((idx 0)
1009 (count (length line-err-info-list))
1010 (err-count 0))
1011
1012 (while (< idx count)
1013 (when (equal type (flymake-ler-get-type (nth idx line-err-info-list)))
1014 (setq err-count (1+ err-count))
1015 )
1016 (setq idx (1+ idx))
1017 )
1018 err-count
1019 )
1020)
1021
1022(defun flymake-get-err-count(err-info-list type)
1023 "return number of errors of specified type for the err-info-list"
1024 (let* ((idx 0)
1025 (count (length err-info-list))
1026 (err-count 0))
1027 (while (< idx count)
1028 (setq err-count (+ err-count (flymake-get-line-err-count (nth 1 (nth idx err-info-list)) type)))
1029 (setq idx (1+ idx))
1030 )
1031 err-count
1032 )
1033)
1034
1035(defun flymake-fix-line-numbers(err-info-list min-line max-line)
1036 "replace line-numbers < min-line with min-line and > max-line with max-line - as some compilers might report line number outside the file being compiled"
1037 (let* ((count (length err-info-list))
1038 (err-info nil)
1039 (line 0))
1040 (while (> count 0)
1041 (setq err-info (nth (1- count) err-info-list))
1042 (setq line (flymake-er-get-line err-info))
1043 (when (or (< line min-line) (> line max-line))
1044 (setq line (if (< line min-line) min-line max-line))
1045 (setq err-info-list (flymake-set-at err-info-list (1- count)
1046 (flymake-er-make-er line
1047 (flymake-er-get-line-err-info-list err-info))))
1048 )
1049 (setq count (1- count))
1050 )
1051 )
1052 err-info-list
1053)
1054
1055(defun flymake-highlight-err-lines(buffer err-info-list)
1056 "highlight err-lines in buffer using info from err-info-list"
1057 (save-excursion
1058 (set-buffer buffer)
1059 (let* ((idx 0)
1060 (count (length err-info-list)))
1061 (while (< idx count)
1062 (flymake-highlight-line (car (nth idx err-info-list)) (nth 1 (nth idx err-info-list)))
1063 (setq idx (1+ idx))
1064 )
1065 )
1066 )
1067)
1068
1069(defun flymake-overlay-p(ov)
1070 "Determine whether overlay was created by flymake"
1071 (and (overlayp ov) (overlay-get ov 'flymake-overlay))
1072)
1073
1074(defun flymake-make-overlay(beg end tooltip-text face mouse-face)
1075 "Allocate a flymake overlay in range beg end"
1076 (when (not (flymake-region-has-flymake-overlays beg end))
1077 (let ((ov (make-overlay beg end nil t t)))
1078 (overlay-put ov 'face face)
1079 (overlay-put ov 'mouse-face mouse-face)
1080 (overlay-put ov 'help-echo tooltip-text)
1081 (overlay-put ov 'flymake-overlay t)
1082 (overlay-put ov 'priority 100)
1083 ;+(flymake-log 3 "created overlay %s" ov)
1084 ov
1085 )
1086 (flymake-log 3 "created an overlay at (%d-%d)" beg end)
1087 )
1088)
1089
1090(defun flymake-delete-own-overlays(buffer)
1091 "Delete all flymake overlays in buffer"
1092 (save-excursion
1093 (set-buffer buffer)
1094 (let ((ov (overlays-in (point-min) (point-max))))
1095 (while (consp ov)
1096 (when (flymake-overlay-p (car ov))
1097 (delete-overlay (car ov))
1098 ;+(flymake-log 3 "deleted overlay %s" ov)
1099 )
1100 (setq ov (cdr ov))
1101 )
1102 )
1103 )
1104)
1105
1106(defun flymake-region-has-flymake-overlays(beg end)
1107 "t if specified regions has at least one flymake overlay, nil otrherwise"
1108 (let ((ov (overlays-in beg end))
1109 (has-flymake-overlays nil))
1110 (while (consp ov)
1111 (when (flymake-overlay-p (car ov))
1112 (setq has-flymake-overlays t)
1113 )
1114 (setq ov (cdr ov))
1115 )
1116 )
1117)
1118
1119(defface flymake-errline-face
1120;+ '((((class color)) (:foreground "OrangeRed" :bold t :underline t))
1121;+ '((((class color)) (:underline "OrangeRed"))
1122 '((((class color)) (:background "LightPink"))
1123 (t (:bold t)))
1124 "Face used for marking error lines"
1125 :group 'flymake
1126)
1127
1128(defface flymake-warnline-face
1129 '((((class color)) (:background "LightBlue2"))
1130 (t (:bold t)))
1131 "Face used for marking warning lines"
1132 :group 'flymake
1133)
1134
1135
1136(defun flymake-highlight-line(line-no line-err-info-list)
1137 "highlight line line-no in current buffer, perhaps use text from line-err-info-list to enhance highlighting"
1138 (goto-line line-no)
1139 (let* ((line-beg (flymake-line-beginning-position))
1140 (line-end (flymake-line-end-position))
1141 (beg line-beg)
1142 (end line-end)
1143 (tooltip-text (flymake-ler-get-text (nth 0 line-err-info-list)))
1144 (face nil))
1145
1146 (goto-char line-beg)
1147 (while (looking-at "[ \t]")
1148 (forward-char)
1149 )
1150
1151 (setq beg (point))
1152
1153 (goto-char line-end)
1154 (while (and (looking-at "[ \t\r\n]") (> (point) 1))
1155 (backward-char)
1156 )
1157
1158 (setq end (1+ (point)))
1159
1160 (when (<= end beg)
1161 (setq beg line-beg)
1162 (setq end line-end)
1163 )
1164 (when (= end beg)
1165 (goto-char end)
1166 (forward-line)
1167 (setq end (point))
1168 )
1169 (if (> (flymake-get-line-err-count line-err-info-list "e") 0)
1170 (setq face 'flymake-errline-face)
1171 ;else
1172 (setq face 'flymake-warnline-face)
1173 )
1174 (flymake-make-overlay beg end tooltip-text face nil)
1175 )
1176)
1177
1178(defun flymake-parse-err-lines(err-info-list source-buffer lines)
1179 "parse err lines, store info in err-info-list"
1180 (let* ((count (length lines))
1181 (idx 0)
1182 (line-err-info nil)
1183 (real-file-name nil)
1184 (source-file-name (buffer-file-name source-buffer))
1185 (get-real-file-name-f (flymake-get-real-file-name-function source-file-name)))
1186
1187 (while (< idx count)
1188 (setq line-err-info (flymake-parse-line (nth idx lines)))
1189 (when line-err-info
1190 (setq real-file-name (funcall get-real-file-name-f source-buffer (flymake-ler-get-file line-err-info)))
1191 (setq line-err-info (flymake-ler-set-full-file line-err-info real-file-name))
1192
1193 (if (flymake-same-files real-file-name source-file-name)
1194 (setq line-err-info (flymake-ler-set-file line-err-info nil))
1195 ;else
1196 (setq line-err-info (flymake-ler-set-file line-err-info (file-name-nondirectory real-file-name)))
1197 )
1198
1199 (setq err-info-list (flymake-add-err-info err-info-list line-err-info))
1200 )
1201 (flymake-log 3 "parsed '%s', %s line-err-info" (nth idx lines) (if line-err-info "got" "no"))
1202 (setq idx (1+ idx))
1203 )
1204 err-info-list
1205 )
1206)
1207
1208(defun flymake-split-output(output)
1209 "split output into lines, return last one as residual if it does not end with newline char. Returns ((lines) residual)"
1210 (when (and output (> (length output) 0))
1211 (let* ((lines (flymake-split-string output "[\n\r]+"))
1212 (complete (equal "\n" (char-to-string (aref output (1- (length output))))))
1213 (residual nil))
1214 (when (not complete)
1215 (setq residual (car (last lines)))
1216 (setq lines (butlast lines))
1217 )
1218 (list lines residual)
1219 )
1220 )
1221)
1222
1223(eval-when-compile (require 'compile))
1224(defvar flymake-err-line-patterns ; regexp file-idx line-idx col-idx (optional) text-idx(optional), match-end to end of string is error text
1225 (append
1226 '(
1227 ; MS Visual C++ 6.0
1228 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
1229 1 3 nil 4)
1230 ; jikes
1231 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
1232 1 3 nil 4)
1233 ; MS midl
1234 ("midl[ ]*:[ ]*\\(command line error .*\\)"
1235 nil nil nil 1)
1236 ; MS C#
1237 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+)\: \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
1238 1 3 nil 4)
1239 ; perl
1240 ("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" 2 3 nil 1)
1241 ; LaTeX warnings (fileless) ("\\(LaTeX \\(Warning\\|Error\\): .*\\) on input line \\([0-9]+\\)" 20 3 nil 1)
1242 ; ant/javac
1243 (" *\\(\\[javac\\]\\)? *\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[ \t\n]*\\(.+\\)"
1244 2 4 nil 5)
1245 )
1246 compilation-error-regexp-alist)
1247 "patterns for matching error/warning lines, (regexp file-idx line-idx err-text-idx)"
1248)
1249;(defcustom flymake-err-line-patterns
1250; '(
1251; ; MS Visual C++ 6.0
1252; ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
1253; 1 3 4)
1254; ; jikes
1255; ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\):[ \t\n]*\\(.+\\)\\)"
1256; 1 3 4))
1257; "patterns for matching error/warning lines, (regexp file-idx line-idx err-text-idx)"
1258; :group 'flymake
1259; :type '(repeat (string number number number))
1260;)
1261
1262(defun flymake-parse-line(line)
1263 "parse line to see whether it's an error of warning, return it's components or nil for no match"
1264 (let ((raw-file-name nil)
1265 (line-no 0)
1266 (err-type "e")
1267 (err-text nil)
1268 (count (length flymake-err-line-patterns))
1269 (idx 0)
1270 (matched nil))
1271 (while (and (< idx count) (not matched))
1272 (when (string-match (car (nth idx flymake-err-line-patterns)) line)
1273 (let* ((file-idx (nth 1 (nth idx flymake-err-line-patterns)))
1274 (line-idx (nth 2 (nth idx flymake-err-line-patterns))))
1275
1276 (setq raw-file-name (if file-idx (match-string file-idx line) nil))
1277 (setq line-no (if line-idx (string-to-int (match-string line-idx line)) 0))
1278 (setq err-text (if (> (length (nth idx flymake-err-line-patterns)) 4)
1279 (match-string (nth 4 (nth idx flymake-err-line-patterns)) line)
1280 (flymake-patch-err-text (substring line (match-end 0)))))
1281 (or err-text (setq err-text "<no error text>"))
1282 (if (and err-text (string-match "^[wW]arning" err-text))
1283 (setq err-type "w")
1284 )
1285 (flymake-log 3 "parse line: file-idx=%s line-idx=%s file=%s line=%s text=%s" file-idx line-idx
1286 raw-file-name line-no err-text)
1287 (setq matched t)
1288 )
1289 )
1290 (setq idx (1+ idx))
1291 )
1292 (if matched
1293 (flymake-ler-make-ler raw-file-name line-no err-type err-text)
1294 ; else
1295 ()
1296 )
1297 )
1298)
1299
1300(defun flymake-find-err-info(err-info-list line-no)
1301 "find (line-err-info-list pos) for specified line-no"
1302 (if err-info-list
1303 (let* ((line-err-info-list nil)
1304 (pos 0)
1305 (count (length err-info-list)))
1306
1307 (while (and (< pos count) (< (car (nth pos err-info-list)) line-no))
1308 (setq pos (1+ pos))
1309 )
1310 (when (and (< pos count) (equal (car (nth pos err-info-list)) line-no))
1311 (setq line-err-info-list (flymake-er-get-line-err-info-list (nth pos err-info-list)))
1312 )
1313 (list line-err-info-list pos)
1314 )
1315 ;else
1316 '(nil 0)
1317 )
1318)
1319
1320(defun flymake-line-err-info-is-less-or-equal(line-one line-two)
1321 (or (string< (flymake-ler-get-type line-one) (flymake-ler-get-type line-two))
1322 (and (string= (flymake-ler-get-type line-one) (flymake-ler-get-type line-two))
1323 (not (flymake-ler-get-file line-one)) (flymake-ler-get-file line-two)
1324 )
1325 (and (string= (flymake-ler-get-type line-one) (flymake-ler-get-type line-two))
1326 (or (and (flymake-ler-get-file line-one) (flymake-ler-get-file line-two))
1327 (and (not (flymake-ler-get-file line-one)) (not (flymake-ler-get-file line-two)))
1328 )
1329 )
1330 )
1331)
1332
1333(defun flymake-add-line-err-info(line-err-info-list line-err-info)
1334 "insert new err info favoring sorting: err-type e/w, filename nil/non-nill"
1335 (if (not line-err-info-list)
1336 (list line-err-info)
1337 ;else
1338 (let* ((count (length line-err-info-list))
1339 (idx 0))
1340 (while (and (< idx count) (flymake-line-err-info-is-less-or-equal (nth idx line-err-info-list) line-err-info))
1341 (setq idx (1+ idx))
1342 )
1343 (cond ((equal 0 idx) (setq line-err-info-list (cons line-err-info line-err-info-list)))
1344 (t (setq line-err-info-list (flymake-ins-after line-err-info-list (1- idx) line-err-info)))
1345 )
1346 line-err-info-list
1347 )
1348 )
1349)
1350
1351(defun flymake-add-err-info(err-info-list line-err-info)
1352 "add error info (file line type text) to err info list preserving sort order"
1353 (let* ((count (length err-info-list))
1354 (line-no (if (flymake-ler-get-file line-err-info) 1 (flymake-ler-get-line line-err-info)))
1355 (info-and-pos (flymake-find-err-info err-info-list line-no))
1356 (exists (car info-and-pos))
1357 (pos (nth 1 info-and-pos))
1358 (line-err-info-list nil)
1359 (err-info nil))
1360
1361 (if exists
1362 (setq line-err-info-list (flymake-er-get-line-err-info-list (car (nthcdr pos err-info-list))))
1363 )
1364 (setq line-err-info-list (flymake-add-line-err-info line-err-info-list line-err-info))
1365
1366 (setq err-info (flymake-er-make-er line-no line-err-info-list))
1367 (cond (exists (setq err-info-list (flymake-set-at err-info-list pos err-info)))
1368 ((equal 0 pos) (setq err-info-list (cons err-info err-info-list)))
1369 (t (setq err-info-list (flymake-ins-after err-info-list (1- pos) err-info)))
1370 )
1371 err-info-list
1372 )
1373)
1374
1375(defun flymake-get-project-include-dirs-imp(basedir)
1376 "include dirs for the project current file belongs to"
1377 (if (flymake-get-project-include-dirs-from-cache basedir)
1378 (progn
1379 (flymake-get-project-include-dirs-from-cache basedir)
1380 )
1381 ;else
1382 (let* ((command-line (concat "make -C\"" basedir "\" DUMPVARS=INCLUDE_DIRS dumpvars"))
1383 (output (shell-command-to-string command-line))
1384 (lines (flymake-split-string output "\n"))
1385 (count (length lines))
1386 (idx 0)
1387 (inc-dirs nil))
1388 (while (and (< idx count) (not (string-match "^INCLUDE_DIRS=.*" (nth idx lines))))
1389 (setq idx (1+ idx))
1390 )
1391 (when (< idx count)
1392 (let* ((inc-lines (flymake-split-string (nth idx lines) " *-I"))
1393 (inc-count (length inc-lines)))
1394 (while (> inc-count 0)
1395 (when (not (string-match "^INCLUDE_DIRS=.*" (nth (1- inc-count) inc-lines)))
1396 (setq inc-dirs (cons (flymake-replace-regexp-in-string "\"" "" (nth (1- inc-count) inc-lines)) inc-dirs))
1397 )
1398 (setq inc-count (1- inc-count))
1399 )
1400 )
1401 )
1402 (flymake-add-project-include-dirs-to-cache basedir inc-dirs)
1403 inc-dirs
1404 )
1405 )
1406)
1407
1408(defcustom flymake-get-project-include-dirs-function 'flymake-get-project-include-dirs-imp
1409 "function used to get project inc dirs, one paramater: basedir name"
1410 :group 'flymake
1411 :type 'function
1412)
1413
1414(defun flymake-get-project-include-dirs(basedir)
1415 (funcall flymake-get-project-include-dirs-function basedir)
1416)
1417
1418(defun flymake-get-system-include-dirs()
1419 "system include dirs - from the 'INCLUDE' env setting"
1420 (let* ((includes (getenv "INCLUDE")))
1421 (if includes (flymake-split-string includes path-separator) nil)
1422 )
1423)
1424
1425(defvar flymake-project-include-dirs-cache (flymake-makehash 'equal))
1426(defun flymake-get-project-include-dirs-from-cache(base-dir)
1427 (gethash base-dir flymake-project-include-dirs-cache)
1428)
1429(defun flymake-add-project-include-dirs-to-cache(base-dir include-dirs)
1430 (puthash base-dir include-dirs flymake-project-include-dirs-cache)
1431)
1432(defun flymake-clear-project-include-dirs-cache()
1433 (clrhash flymake-project-include-dirs-cache)
1434)
1435
1436(defun flymake-get-include-dirs(base-dir)
1437 "dirs to use when resolving local filenames"
1438 (let* ((include-dirs (append '(".") (flymake-get-project-include-dirs base-dir) (flymake-get-system-include-dirs))))
1439 include-dirs
1440 )
1441)
1442
1443(defun flymake-find-file(rel-file-name include-dirs)
1444 "iterate through include-dirs, return first 'include-dir/rel-file-name' that exists, or just rel-file-name if not"
1445 (let* ((count (length include-dirs))
1446 (idx 0)
1447 (found nil)
1448 (full-file-name rel-file-name))
1449
1450 (while (and (not found) (< idx count))
1451 (let* ((dir (nth idx include-dirs)))
1452 (setq full-file-name (concat dir "/" rel-file-name))
1453 (when (file-exists-p full-file-name)
1454 (setq done t)
1455 )
1456 )
1457 (setq idx (1+ idx))
1458 )
1459 (if found
1460 full-file-name
1461 ;else
1462 rel-file-name
1463 )
1464 )
1465)
1466
1467(defun flymake-restore-formatting(source-buffer)
1468 "Remove any formatting made by flymake"
1469)
1470
1471(defun flymake-get-program-dir(buffer)
1472 "dir to start profram in"
1473 (unless (bufferp buffer)
1474 (error "invlid buffer")
1475 )
1476 (save-excursion
1477 (set-buffer buffer)
1478 default-directory
1479 )
1480)
1481
1482(defun flymake-safe-delete-file(file-name)
1483 (when (and file-name (file-exists-p file-name))
1484 (delete-file file-name)
1485 (flymake-log 1 "deleted file %s" file-name)
1486 )
1487)
1488
1489(defun flymake-safe-delete-directory(dir-name)
1490 (condition-case err
1491 (progn
1492 (delete-directory dir-name)
1493 (flymake-log 1 "deleted dir %s" dir-name)
1494 )
1495 (error
1496 (flymake-log 1 "failed to delete dir %s, error ignored" dir-name)
1497 )
1498 )
1499)
1500
1501(defcustom flymake-compilation-prevents-syntax-check t
1502 "if non-nil, syntax check won't be started in case compilation is running"
1503 :group 'flymake
1504 :type 'boolean
1505)
1506
1507(defun flymake-start-syntax-check(buffer)
1508 "start syntax checking for buffer"
1509 (unless (bufferp buffer)
1510 (error "expected a buffer")
1511 )
1512 (save-excursion
1513 (set-buffer buffer)
1514 (flymake-log 3 "flymake is running: %s" (flymake-get-buffer-is-running buffer))
1515 (when (and (not (flymake-get-buffer-is-running buffer))
1516 (flymake-can-syntax-check-file (buffer-file-name buffer)))
1517 (when (or (not flymake-compilation-prevents-syntax-check)
1518 (not (flymake-compilation-is-running))) ;+ (flymake-rep-ort-status buffer "COMP")
1519 (flymake-clear-buildfile-cache)
1520 (flymake-clear-project-include-dirs-cache)
1521
1522 (flymake-set-buffer-check-was-interrupted buffer nil)
1523 (flymake-set-buffer-data buffer (flymake-makehash 'equal))
1524
1525 (let* ((source-file-name (buffer-file-name buffer))
1526 (init-f (flymake-get-init-function source-file-name))
1527 (cleanup-f (flymake-get-cleanup-function source-file-name))
1528 (cmd-and-args (funcall init-f buffer))
1529 (cmd (nth 0 cmd-and-args))
1530 (args (nth 1 cmd-and-args))
1531 (dir (nth 2 cmd-and-args)))
1532 (if (not cmd-and-args)
1533 (progn
1534 (flymake-log 0 "init function %s for %s failed, cleaning up" init-f source-file-name)
1535 (funcall cleanup-f buffer)
1536 )
1537 ;else
1538 (progn
1539 (flymake-set-buffer-last-change-time buffer nil)
1540 (flymake-start-syntax-check-process buffer cmd args dir)
1541 )
1542 )
1543 )
1544 )
1545 )
1546 )
1547)
1548
1549(defun flymake-start-syntax-check-process(buffer cmd args dir)
1550 "start syntax check-process"
1551
1552 (let* ((process nil))
1553 (condition-case err
1554 (progn
1555 (when dir
1556 (let ((default-directory dir))
1557 (flymake-log 3 "starting process on dir %s" default-directory)
1558 )
1559 )
1560 (setq process (get-process (apply 'start-process "flymake-proc" nil cmd args)))
1561 (set-process-sentinel process 'flymake-process-sentinel)
1562 (set-process-filter process 'flymake-process-filter)
1563
1564 (flymake-reg-names (process-id process) (buffer-name buffer))
1565
1566 (flymake-set-buffer-is-running buffer t)
1567 (flymake-set-buffer-last-change-time buffer nil)
1568 (flymake-set-buffer-check-start-time buffer (flymake-float-time))
1569
1570 (flymake-report-status buffer nil "*")
1571 (flymake-log 2 "started process %d, command=%s, dir=%s"
1572 (process-id process) (process-command process) default-directory)
1573 process
1574 )
1575 (error
1576 (let ((err-str (format "Failed to launch syntax check process '%s' with args %s: %s"
1577 cmd args (error-message-string err)))
1578 (source-file-name (buffer-file-name buffer))
1579 (cleanup-f (flymake-get-cleanup-function source-file-name)))
1580 (flymake-log 0 err-str)
1581 (funcall cleanup-f buffer)
1582 (flymake-report-fatal-status buffer "PROCERR" err-str)
1583 )
1584 )
1585 )
1586 )
1587)
1588
1589(defun flymake-kill-process(pid &optional rest)
1590 "kill process pid"
1591 (signal-process pid 9)
1592 (let* ((buffer-name (flymake-get-source-buffer-name pid)))
1593 (when (and buffer-name (get-buffer buffer-name))
1594 (flymake-set-buffer-check-was-interrupted (get-buffer buffer-name) t)
1595 )
1596 )
1597 (flymake-log 1 "killed process %d" pid)
1598)
1599
1600(defun flymake-stop-all-syntax-checks()
1601 "kill all syntax check processes"
1602 (interactive)
1603 (let ((pids (copy-hash-table flymake-pid-to-names)))
1604 (maphash 'flymake-kill-process pids)
1605 )
1606)
1607
1608(defun flymake-compilation-is-running()
1609 (and (boundp 'compilation-in-progress)
1610 compilation-in-progress)
1611)
1612
1613(defun flymake-compile()
1614 "kill all flymake syntax checks, start compilation"
1615 (interactive)
1616 (flymake-stop-all-syntax-checks)
1617 (call-interactively 'compile)
1618)
1619
1620(defvar flymake-is-running nil
1621 "t if flymake syntax check process is running for the current buffer"
1622)
1623(make-variable-buffer-local 'flymake-is-running)
1624(defun flymake-get-buffer-is-running(buffer)
1625 (flymake-get-buffer-var buffer 'flymake-is-running)
1626)
1627(defun flymake-set-buffer-is-running(buffer is-running)
1628 (flymake-set-buffer-var buffer 'flymake-is-running is-running)
1629)
1630
1631(defvar flymake-timer nil
1632 "timer for starting syntax checks"
1633)
1634(make-variable-buffer-local 'flymake-timer)
1635(defun flymake-get-buffer-timer(buffer)
1636 (flymake-get-buffer-var buffer 'flymake-timer)
1637)
1638(defun flymake-set-buffer-timer(buffer timer)
1639 (flymake-set-buffer-var buffer 'flymake-timer timer)
1640)
1641
1642(defvar flymake-last-change-time nil
1643 "time of last buffer change"
1644)
1645(make-variable-buffer-local 'flymake-last-change-time)
1646(defun flymake-get-buffer-last-change-time(buffer)
1647 (flymake-get-buffer-var buffer 'flymake-last-change-time)
1648)
1649(defun flymake-set-buffer-last-change-time(buffer change-time)
1650 (flymake-set-buffer-var buffer 'flymake-last-change-time change-time)
1651)
1652
1653(defvar flymake-check-start-time nil
1654 "time at which syntax check was started")
1655(make-variable-buffer-local 'flymake-check-start-time)
1656(defun flymake-get-buffer-check-start-time(buffer)
1657 (flymake-get-buffer-var buffer 'flymake-check-start-time)
1658)
1659(defun flymake-set-buffer-check-start-time(buffer check-start-time)
1660 (flymake-set-buffer-var buffer 'flymake-check-start-time check-start-time)
1661)
1662
1663(defvar flymake-check-was-interrupted nil
1664 "t if syntax check was killed by flymake-compile"
1665)
1666(make-variable-buffer-local 'flymake-check-was-interrupted)
1667(defun flymake-get-buffer-check-was-interrupted(buffer)
1668 (flymake-get-buffer-var buffer 'flymake-check-was-interrupted)
1669)
1670(defun flymake-set-buffer-check-was-interrupted(buffer interrupted)
1671 (flymake-set-buffer-var buffer 'flymake-check-was-interrupted interrupted)
1672)
1673
1674(defcustom flymake-no-changes-timeout 0.5
1675 "time to wait after last change before starting compilation"
1676 :group 'flymake
1677 :type 'number
1678)
1679
1680(defun flymake-on-timer-event(buffer)
1681 "start a syntax check for buffer if necessary"
1682 ;+(flymake-log 3 "timer: running=%s, time=%s, cur-time=%s" (flymake-get-buffer-is-running buffer) (flymake-get-buffer-last-change-time buffer) (flymake-float-time))
1683
1684 (when (and (bufferp buffer) (not (flymake-get-buffer-is-running buffer)))
1685 (save-excursion
1686 (set-buffer buffer)
1687 (when (and (flymake-get-buffer-last-change-time buffer)
1688 (> (flymake-float-time) (+ flymake-no-changes-timeout (flymake-get-buffer-last-change-time buffer))))
1689 (flymake-set-buffer-last-change-time buffer nil)
1690 (flymake-log 3 "starting syntax check as more than 1 second passed since last change")
1691 (flymake-start-syntax-check buffer)
1692 )
1693 )
1694 )
1695)
1696
1697(defun flymake-start-syntax-check-for-current-buffer()
1698 "run flymake-start-syntax-check for current buffer if it isn't already running"
1699 (interactive)
1700 (flymake-start-syntax-check (current-buffer))
1701)
1702
1703(defun flymake-current-line-no()
1704 "return number of current line in current buffer"
1705 (interactive)
1706 (let ((beg (point-min))
1707 (end (if (= (point) (point-max)) (point) (1+ (point)))))
1708 (count-lines beg end)
1709 )
1710)
1711
1712(defun flymake-get-line-count(buffer)
1713 "return number of lines in buffer"
1714 (unless (bufferp buffer)
1715 (error "invalid buffer")
1716 )
1717 (save-excursion
1718 (set-buffer buffer)
1719 (count-lines (point-min) (point-max))
1720 )
1721)
1722
1723(defun flymake-count-lines(buffer)
1724 "return number of lines in buffer"
1725 (save-excursion
1726 (set-buffer buffer)
1727 (count-lines (point-min) (point-max))
1728 )
1729)
1730
1731(defun flymake-get-point-pixel-pos()
1732 "return point position in pixels: (x, y)"
1733 (let ((mouse-pos (mouse-position))
1734 (pixel-pos nil)
1735 (ret nil))
1736 (if (car (cdr mouse-pos))
1737 (progn
1738 (set-mouse-position (flymake-selected-frame) (current-column) (flymake-current-row))
1739 (setq pixel-pos (mouse-pixel-position))
1740 (set-mouse-position (car mouse-pos) (car (cdr mouse-pos)) (cdr (cdr mouse-pos)))
1741 (setq ret (list (car (cdr pixel-pos)) (cdr (cdr pixel-pos))))
1742 )
1743 ;else
1744 (progn
1745 (setq ret '(0 0))
1746 )
1747 )
1748 (flymake-log 3 "mouse pos is %s" ret)
1749 ret
1750 )
1751)
1752
1753(defun flymake-display-err-menu-for-current-line()
1754 "Display a menu with errors/warnings for current line if it has errors and/or warnings"
1755 (interactive)
1756 (let* ((line-no (flymake-current-line-no))
1757 (line-err-info-list (nth 0 (flymake-find-err-info (flymake-get-buffer-err-info (current-buffer)) line-no)))
1758 (menu-data (flymake-make-err-menu-data line-no line-err-info-list))
1759 (choice nil)
1760 (mouse-pos (flymake-get-point-pixel-pos))
1761 (moved-mouse-pos (list (car mouse-pos) (+ 10 (car (cdr mouse-pos)))))
1762 (menu-pos (list (flymake-get-point-pixel-pos) (selected-window))))
1763 (if menu-data
1764 (progn
1765 (setq choice (flymake-popup-menu menu-pos menu-data))
1766 (flymake-log 3 "choice=%s" choice)
1767 (when choice
1768 (eval choice)
1769 )
1770 )
1771 ;else
1772 (flymake-log 1 "no errors for line %d" line-no)
1773 )
1774 )
1775)
1776
1777(defun flymake-make-err-menu-data(line-no line-err-info-list)
1778 "Make a (menu-title (item-title item-action)*) list with errors/warnings from line-err-info"
1779 (let* ((menu-items nil))
1780 (when line-err-info-list
1781 (let* ((count (length line-err-info-list))
1782 (menu-item-text nil))
1783 (while (> count 0)
1784 (setq menu-item-text (flymake-ler-get-text (nth (1- count) line-err-info-list)))
1785 (let* ((file (flymake-ler-get-file (nth (1- count) line-err-info-list)))
1786 (full-file (flymake-ler-get-full-file (nth (1- count) line-err-info-list)))
1787 (line (flymake-ler-get-line (nth (1- count) line-err-info-list))))
1788 (if file
1789 (setq menu-item-text (concat menu-item-text " - " file "(" (format "%d" line) ")"))
1790 )
1791 (setq menu-items (cons (list menu-item-text
1792 (if file (list 'flymake-goto-file-and-line full-file line) nil))
1793 menu-items))
1794 )
1795 (setq count (1- count))
1796 )
1797 (flymake-log 3 "created menu-items with %d item(s)" (length menu-items))
1798 )
1799 )
1800 (if menu-items
1801 (let* ((menu-title (format "Line %d: %d error(s), %d warning(s)" line-no
1802 (flymake-get-line-err-count line-err-info-list "e")
1803 (flymake-get-line-err-count line-err-info-list "w"))))
1804 (list menu-title menu-items)
1805 )
1806 ;else
1807 nil
1808 )
1809 )
1810)
1811
1812(defun flymake-goto-file-and-line(file line)
1813 "try to get buffer for file and goto line line in it"
1814 (if (not (file-exists-p file))
1815 (flymake-log 1 "file %s does not exists" file)
1816 ;else
1817 (progn
1818 (find-file file)
1819 (goto-line line)
1820 )
1821 )
1822)
1823;; flymake minor mode declarations
1824
1825(defvar flymake-mode nil)
1826(make-variable-buffer-local 'flymake-mode)
1827
1828(defvar flymake-mode-line nil
1829 ""
1830)
1831(make-variable-buffer-local 'flymake-mode-line)
1832(defun flymake-get-buffer-mode-line(buffer)
1833 (flymake-get-buffer-var buffer 'flymake-mode-line)
1834)
1835(defun flymake-set-buffer-mode-line(buffer mode-line-string)
1836 (flymake-set-buffer-var buffer 'flymake-mode-line mode-line-string)
1837)
1838
1839(defvar flymake-mode-line-e-w nil)
1840(make-variable-buffer-local 'flymake-mode-line-e-w)
1841(defun flymake-get-buffer-mode-line-e-w(buffer)
1842 (flymake-get-buffer-var buffer 'flymake-mode-line-e-w)
1843)
1844(defun flymake-set-buffer-mode-line-e-w(buffer e-w)
1845 (flymake-set-buffer-var buffer 'flymake-mode-line-e-w e-w)
1846)
1847
1848(defvar flymake-mode-line-status nil)
1849(make-variable-buffer-local 'flymake-mode-line-status)
1850(defun flymake-get-buffer-mode-line-status(buffer)
1851 (flymake-get-buffer-var buffer 'flymake-mode-line-status)
1852)
1853(defun flymake-set-buffer-mode-line-status(buffer status)
1854 (flymake-set-buffer-var buffer 'flymake-mode-line-status status)
1855)
1856
1857(defun flymake-report-status(buffer e-w &optional status)
1858 "show status in the mode line"
1859 (when (bufferp buffer)
1860 (save-excursion
1861 (set-buffer buffer)
1862 (when e-w
1863 (flymake-set-buffer-mode-line-e-w buffer e-w)
1864 )
1865 (when status
1866 (flymake-set-buffer-mode-line-status buffer status)
1867 )
1868 (let* ((mode-line " Flymake"))
1869 (when (> (length (flymake-get-buffer-mode-line-e-w buffer)) 0)
1870 (setq mode-line (concat mode-line ":" (flymake-get-buffer-mode-line-e-w buffer)))
1871 )
1872 (setq mode-line (concat mode-line (flymake-get-buffer-mode-line-status buffer)))
1873 (flymake-set-buffer-mode-line buffer mode-line)
1874 (force-mode-line-update)
1875 )
1876 )
1877 )
1878)
1879
1880(defun flymake-display-warning(warning)
1881 "display a warning to the user"
1882 (message-box warning)
1883)
1884
1885(defcustom flymake-gui-warnings-enabled t
1886 "enables/disables gui warnings"
1887 :group 'flymake
1888 :type 'boolean
1889)
1890
1891(defun flymake-report-fatal-status(buffer status warning)
1892 "display a warning and switch flymake mode OFF"
1893 (when flymake-gui-warnings-enabled
1894 (flymake-display-warning (format "Flymake: %s. Flymake will be switched OFF" warning))
1895 )
1896 (save-excursion
1897 (set-buffer buffer)
1898 (flymake-mode 0)
1899 (flymake-log 0 "switched OFF Flymake mode for buffer %s due to fatal status %s, warning %s"
1900 (buffer-name buffer) status warning)
1901 )
1902)
1903
1904(defun flymake-mode(&optional arg)
1905 "toggle flymake-mode"
1906 (interactive)
1907 (let ((old-flymake-mode flymake-mode))
1908
1909 (setq turn-on
1910 (if (null arg)
1911 (not flymake-mode)
1912 ;else
1913 (> (prefix-numeric-value arg) 0))
1914 )
1915
1916 (if turn-on
1917 (if (flymake-can-syntax-check-file (buffer-file-name))
1918 (flymake-mode-on)
1919 ;else
1920 (flymake-log 2 "flymake cannot check syntax in buffer %s" (buffer-name))
1921 )
1922 ;else
1923 (flymake-mode-off)
1924 )
1925 (force-mode-line-update)
1926 )
1927)
1928
1929;;;###autoload
1930(unless (assq 'flymake-mode minor-mode-alist)
1931 (setq minor-mode-alist (cons '(flymake-mode flymake-mode-line) minor-mode-alist))
1932)
1933
1934;;;###autoload
1935(defun flymake-mode-on()
1936 "turn flymake mode on"
1937 (when (not flymake-mode)
1938 (make-local-variable 'after-change-functions)
1939 (setq after-change-functions (cons 'flymake-after-change-function after-change-functions))
1940 (add-hook 'after-save-hook 'flymake-after-save-hook)
1941 (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook)
1942 ;+(add-hook 'find-file-hooks 'flymake-find-file-hook)
1943
1944 (flymake-report-status (current-buffer) "" "")
1945
1946 (flymake-set-buffer-timer (current-buffer) (run-at-time nil 1 'flymake-on-timer-event (current-buffer)))
1947
1948 (setq flymake-mode t)
1949 (flymake-log 1 "flymake mode turned ON for buffer %s" (buffer-name (current-buffer)))
1950 (when flymake-start-syntax-check-on-find-file
1951 (flymake-start-syntax-check-for-current-buffer) ; will be started by on-load hook
1952 )
1953 )
1954)
1955
1956;;;###autoload
1957(defun flymake-mode-off()
1958 "turn flymake mode off"
1959 (when flymake-mode
1960 (setq after-change-functions (delq 'flymake-after-change-function after-change-functions))
1961 (remove-hook 'after-save-hook (function flymake-after-save-hook) t)
1962 (remove-hook 'kill-buffer-hook (function flymake-kill-buffer-hook) t)
1963 ;+(remove-hook 'find-file-hooks (function flymake-find-file-hook) t)
1964
1965 (flymake-delete-own-overlays (current-buffer))
1966
1967 (when (flymake-get-buffer-timer (current-buffer))
1968 (cancel-timer (flymake-get-buffer-timer (current-buffer)))
1969 (flymake-set-buffer-timer (current-buffer) nil)
1970 )
1971
1972 (flymake-set-buffer-is-running (current-buffer) nil)
1973
1974 (setq flymake-mode nil)
1975 (flymake-log 1 "flymake mode turned OFF for buffer %s" (buffer-name (current-buffer)))
1976 )
1977)
1978
1979(defcustom flymake-start-syntax-check-on-newline t
1980 "start syntax check if newline char was added/removed from the buffer"
1981 :group 'flymake
1982 :type 'boolean
1983)
1984
1985(defun flymake-after-change-function(start stop len)
1986 "Start syntax check for current buffer if it isn't already running"
1987 ;+(flymake-log 0 "setting change time to %s" (flymake-float-time))
1988 (let((new-text (buffer-substring start stop)))
1989 (when (and flymake-start-syntax-check-on-newline (equal new-text "\n"))
1990 (flymake-log 3 "starting syntax check as new-line has been seen")
1991 (flymake-start-syntax-check-for-current-buffer)
1992 )
1993 (flymake-set-buffer-last-change-time (current-buffer) (flymake-float-time))
1994 )
1995)
1996
1997(defun flymake-after-save-hook()
1998 (if (local-variable-p 'flymake-mode (current-buffer)) ; (???) other way to determine whether flymake is active in buffer being saved?
1999 (progn
2000 (flymake-log 3 "starting syntax check as buffer was saved")
2001 (flymake-start-syntax-check-for-current-buffer) ; no more mode 3. cannot start check if mode 3 (to temp copies) is active - (???)
2002 )
2003 )
2004)
2005
2006(defun flymake-kill-buffer-hook()
2007 (when (flymake-get-buffer-timer (current-buffer))
2008 (cancel-timer (flymake-get-buffer-timer (current-buffer)))
2009 (flymake-set-buffer-timer (current-buffer) nil)
2010 )
2011)
2012
2013(defcustom flymake-start-syntax-check-on-find-file t
2014 "statr syntax check on find file"
2015 :group 'flymake
2016 :type 'boolean
2017)
2018
2019(defun flymake-find-file-hook()
2020 ;+(when flymake-start-syntax-check-on-find-file
2021 ;+ (flymake-log 3 "starting syntax check on file open")
2022 ;+ (flymake-start-syntax-check-for-current-buffer)
2023 ;+)
2024 (when (and (not (local-variable-p 'flymake-mode (current-buffer)))
2025 (flymake-can-syntax-check-file (buffer-file-name (current-buffer))))
2026 (flymake-mode)
2027 (flymake-log 3 "automatically turned ON flymake mode")
2028 )
2029)
2030
2031(defun flymake-get-first-err-line-no(err-info-list)
2032 "return first line-no with error"
2033 (when err-info-list
2034 (flymake-er-get-line (car err-info-list))
2035 )
2036)
2037
2038(defun flymake-get-last-err-line-no(err-info-list)
2039 "return last line-no with error"
2040 (when err-info-list
2041 (flymake-er-get-line (nth (1- (length err-info-list)) err-info-list))
2042 )
2043)
2044
2045(defun flymake-get-next-err-line-no(err-info-list line-no)
2046 "return next line with erroe"
2047 (when err-info-list
2048 (let* ((count (length err-info-list))
2049 (idx 0))
2050 (while (and (< idx count) (>= line-no (flymake-er-get-line (nth idx err-info-list))))
2051 (setq idx (1+ idx))
2052 )
2053 (if (< idx count)
2054 (flymake-er-get-line (nth idx err-info-list))
2055 )
2056 )
2057 )
2058)
2059
2060(defun flymake-get-prev-err-line-no(err-info-list line-no)
2061 "return prev line with error"
2062 (when err-info-list
2063 (let* ((count (length err-info-list)))
2064 (while (and (> count 0) (<= line-no (flymake-er-get-line (nth (1- count) err-info-list))))
2065 (setq count (1- count))
2066 )
2067 (if (> count 0)
2068 (flymake-er-get-line (nth (1- count) err-info-list))
2069 )
2070 )
2071 )
2072)
2073
2074(defun flymake-skip-whitespace()
2075 "move forward until nonwhitespace is reached"
2076 (while (looking-at "[ \t]")
2077 (forward-char)
2078 )
2079)
2080
2081(defun flymake-goto-line(line-no)
2082 "goto-line, then skip whitespace"
2083 (goto-line line-no)
2084 (flymake-skip-whitespace)
2085)
2086
2087(defun flymake-goto-next-error()
2088 "go to next error in err ring"
2089 (interactive)
2090 (let ((line-no (flymake-get-next-err-line-no (flymake-get-buffer-err-info (current-buffer)) (flymake-current-line-no))))
2091 (when (not line-no)
2092 (setq line-no (flymake-get-first-err-line-no (flymake-get-buffer-err-info (current-buffer))))
2093 (flymake-log 1 "passed end of file")
2094 )
2095 (if line-no
2096 (flymake-goto-line line-no)
2097 ;else
2098 (flymake-log 1 "no errors in current buffer")
2099 )
2100 )
2101)
2102
2103(defun flymake-goto-prev-error()
2104 "go to prev error in err ring"
2105 (interactive)
2106 (let ((line-no (flymake-get-prev-err-line-no (flymake-get-buffer-err-info (current-buffer)) (flymake-current-line-no))))
2107 (when (not line-no)
2108 (setq line-no (flymake-get-last-err-line-no (flymake-get-buffer-err-info (current-buffer))))
2109 (flymake-log 1 "passed beginning of file")
2110 )
2111 (if line-no
2112 (flymake-goto-line line-no)
2113 ;else
2114 (flymake-log 1 "no errors in current buffer")
2115 )
2116 )
2117)
2118
2119(defun flymake-patch-err-text(string)
2120 (if (string-match "^[\n\t :0-9]*\\(.*\\)$" string)
2121 (match-string 1 string)
2122 ;else
2123 string
2124 )
2125)
2126
2127;;;; general init-cleanup and helper routines
2128
2129(defun flymake-create-temp-inplace(file-name prefix)
2130 (unless (stringp file-name)
2131 (error "invalid file-name")
2132 )
2133 (or prefix
2134 (setq prefix "flymake")
2135 )
2136 (let* ((temp-name (concat (file-name-sans-extension file-name)
2137 "_" prefix
2138 (and (file-name-extension file-name)
2139 (concat "." (file-name-extension file-name))))))
2140 (flymake-log 3 "create-temp-inplace: file=%s temp=%s" file-name temp-name)
2141 temp-name
2142 )
2143)
2144
2145(defun flymake-create-temp-with-folder-structure(file-name prefix)
2146 (unless (stringp file-name)
2147 (error "invalid file-name")
2148 )
2149
2150 (let* ((dir (file-name-directory file-name))
2151 (slash-pos (string-match "/" dir))
2152 (temp-dir (concat (flymake-ensure-ends-with-slash (flymake-get-temp-dir)) (substring dir (1+ slash-pos)))))
2153
2154 (file-truename (concat (flymake-ensure-ends-with-slash temp-dir)
2155 (file-name-nondirectory file-name)))
2156 )
2157)
2158
2159(defun flymake-strrchr(str ch)
2160 (let* ((count (length str))
2161 (pos nil))
2162 (while (and (not pos) (> count 0))
2163 (if (= ch (elt str (1- count)))
2164 (setq pos (1- count))
2165 )
2166 (setq count (1- count))
2167 )
2168 pos
2169 )
2170)
2171
2172(defun flymake-delete-temp-directory(dir-name)
2173 "attempt to delete temp dir created by flymake-create-temp-with-folder-structure, do not fail on error"
2174 (let* ((temp-dir (flymake-get-temp-dir))
2175 (suffix (substring dir-name (1+ (length temp-dir))))
2176 (slash-pos nil))
2177
2178 (while (> (length suffix) 0)
2179 ;+(flymake-log 0 "suffix=%s" suffix)
2180 (flymake-safe-delete-directory (file-truename (concat (flymake-ensure-ends-with-slash temp-dir) suffix)))
2181 (setq slash-pos (flymake-strrchr suffix (string-to-char "/")))
2182 (if slash-pos
2183 (setq suffix (substring suffix 0 slash-pos))
2184 ;else
2185 (setq suffix "")
2186 )
2187 )
2188 )
2189)
2190
2191(defun flymake-init-create-temp-buffer-copy(buffer create-temp-f)
2192 "make a temporary copy of the current buffer, save its name in buffer data and return the name"
2193 (let* ((source-file-name (buffer-file-name buffer))
2194 (temp-source-file-name (funcall create-temp-f source-file-name "flymake")))
2195
2196 (flymake-save-buffer-in-file buffer temp-source-file-name)
2197 (flymake-set-buffer-value buffer "temp-source-file-name" temp-source-file-name)
2198
2199 temp-source-file-name
2200 )
2201)
2202
2203(defun flymake-simple-cleanup(buffer)
2204 "cleanup after flymake-init-create-temp-buffer-copy -- delete temp file"
2205 (let* ((temp-source-file-name (flymake-get-buffer-value buffer "temp-source-file-name")))
2206 (flymake-safe-delete-file temp-source-file-name)
2207 (flymake-set-buffer-last-change-time buffer nil)
2208 )
2209)
2210
2211(defun flymake-get-real-file-name(buffer file-name-from-err-msg)
2212 "Translate file name from error message to `real' file name. Return full-name. Names are real, not patched"
2213 (let* ((real-name nil)
2214 (source-file-name (buffer-file-name buffer))
2215 (master-file-name (flymake-get-buffer-value buffer "master-file-name"))
2216 (temp-source-file-name (flymake-get-buffer-value buffer "temp-source-file-name"))
2217 (temp-master-file-name (flymake-get-buffer-value buffer "temp-master-file-name"))
2218 (base-dirs (list (flymake-get-buffer-value buffer "base-dir")
2219 (file-name-directory source-file-name)
2220 (if master-file-name (file-name-directory master-file-name) nil)))
2221 (files (list (list source-file-name source-file-name)
2222 (list temp-source-file-name source-file-name)
2223 (list master-file-name master-file-name)
2224 (list temp-master-file-name master-file-name))))
2225
2226 (when (equal 0 (length file-name-from-err-msg))
2227 (setq file-name-from-err-msg source-file-name)
2228 )
2229
2230 (setq real-name (flymake-get-full-patched-file-name file-name-from-err-msg base-dirs files))
2231 ; if real-name is nil, than file name from err msg is none of the files we've patched
2232 (if (not real-name)
2233 (setq real-name (flymake-get-full-nonpatched-file-name file-name-from-err-msg base-dirs))
2234 )
2235 (if (not real-name)
2236 (setq real-name file-name-from-err-msg)
2237 )
2238 (setq real-name (flymake-fix-path-name real-name))
2239 (flymake-log 3 "get-real-file-name: file-name=%s real-name=%s" file-name-from-err-msg real-name)
2240 real-name
2241 )
2242)
2243
2244(defun flymake-get-full-patched-file-name(file-name-from-err-msg base-dirs files)
2245 (let* ((base-dirs-count (length base-dirs))
2246 (file-count (length files))
2247 (real-name nil))
2248
2249 (while (and (not real-name) (> base-dirs-count 0))
2250 (setq file-count (length files))
2251 (while (and (not real-name) (> file-count 0))
2252 (let* ((this-dir (nth (1- base-dirs-count) base-dirs))
2253 (this-file (nth 0 (nth (1- file-count) files)))
2254 (this-real-name (nth 1 (nth (1- file-count) files))))
2255 ;+(flymake-log 0 "this-dir=%s this-file=%s this-real=%s msg-file=%s" this-dir this-file this-real-name file-name-from-err-msg)
2256 (when (and this-dir this-file (flymake-same-files
2257 (flymake-get-absolute-file-name-basedir file-name-from-err-msg this-dir)
2258 this-file))
2259 (setq real-name this-real-name)
2260 )
2261 )
2262 (setq file-count (1- file-count))
2263 )
2264 (setq base-dirs-count (1- base-dirs-count))
2265 )
2266 real-name
2267 )
2268)
2269
2270(defun flymake-get-full-nonpatched-file-name(file-name-from-err-msg base-dirs)
2271 (let* ((real-name nil))
2272 (if (file-name-absolute-p file-name-from-err-msg)
2273 (setq real-name file-name-from-err-msg)
2274 ;else
2275 (let* ((base-dirs-count (length base-dirs)))
2276 (while (and (not real-name) (> base-dirs-count 0))
2277 (let* ((full-name (flymake-get-absolute-file-name-basedir file-name-from-err-msg
2278 (nth (1- base-dirs-count) base-dirs))))
2279 (if (file-exists-p full-name)
2280 (setq real-name full-name)
2281 )
2282 (setq base-dirs-count (1- base-dirs-count))
2283 )
2284 )
2285 )
2286 )
2287 real-name
2288 )
2289)
2290
2291(defun flymake-get-absolute-file-name-basedir(file-name dir-name)
2292 (if (file-name-absolute-p file-name)
2293 file-name
2294 ;else
2295 (concat dir-name "/" file-name)
2296 )
2297)
2298
2299(defun flymake-init-find-buildfile-dir(buffer source-file-name buildfile-name)
2300 "find buildfile, store its dir in buffer data and return its dir, if found"
2301 (let* ((buildfile-dir (flymake-find-buildfile buildfile-name
2302 (file-name-directory source-file-name)
2303 flymake-buildfile-dirs)))
2304 (if (not buildfile-dir)
2305 (progn
2306 (flymake-log 1 "no buildfile (%s) for %s" buildfile-name source-file-name)
2307 (flymake-report-fatal-status buffer "NOMK" (format "No buildfile (%s) found for %s" buildfile-name source-file-name))
2308 )
2309 ;else
2310 (progn
2311 (flymake-set-buffer-value buffer "base-dir" buildfile-dir)
2312 )
2313 )
2314 buildfile-dir
2315 )
2316)
2317
2318(defun flymake-init-create-temp-source-and-master-buffer-copy(buffer get-incl-dirs-f create-temp-f master-file-masks include-regexp-list)
2319 "find master file (or buffer), create it's copy along with a copy of the source file"
2320 (let* ((source-file-name (buffer-file-name buffer))
2321 (temp-source-file-name (flymake-init-create-temp-buffer-copy buffer create-temp-f))
2322 (master-file-name nil)
2323 (temp-master-file-name nil)
2324 (master-and-temp-master (flymake-create-master-file
2325 source-file-name temp-source-file-name
2326 get-incl-dirs-f create-temp-f
2327 master-file-masks include-regexp-list)))
2328
2329 (if (not master-and-temp-master)
2330 (progn
2331 (flymake-log 1 "cannot find master file for %s" source-file-name)
2332 (flymake-report-status buffer "!" "") ; NOMASTER
2333 )
2334 ;else
2335 (progn
2336 (setq master-file-name (nth 0 master-and-temp-master))
2337 (setq temp-master-file-name (nth 1 master-and-temp-master))
2338 (flymake-set-buffer-value buffer "master-file-name" master-file-name)
2339 (flymake-set-buffer-value buffer "temp-master-file-name" temp-master-file-name)
2340 )
2341 )
2342 temp-master-file-name
2343 )
2344)
2345
2346(defun flymake-master-cleanup(buffer)
2347 (flymake-simple-cleanup buffer)
2348 (flymake-safe-delete-file (flymake-get-buffer-value buffer "temp-master-file-name"))
2349)
2350
2351;;;; make-specific init-cleanup routines
2352
2353(defun flymake-get-syntax-check-program-args(source-file-name base-dir use-relative-base-dir use-relative-source get-cmd-line-f)
2354 "create a command line for the syntax check command, using get-cmd-line-f"
2355 (let* ((my-base-dir base-dir)
2356 (my-source source-file-name))
2357
2358 (when use-relative-base-dir
2359 (setq my-base-dir (flymake-build-relative-path (file-name-directory source-file-name) base-dir))
2360 )
2361
2362 (when use-relative-source
2363 (setq my-source (concat (flymake-build-relative-path base-dir (file-name-directory source-file-name))
2364 (file-name-nondirectory source-file-name)))
2365 )
2366
2367 (funcall get-cmd-line-f my-source my-base-dir)
2368 )
2369)
2370
2371(defun flymake-get-make-cmdline(source base-dir)
2372 (list "make"
2373 (list "-s"
2374 "-C"
2375 base-dir
2376 (concat "CHK_SOURCES=" source)
2377 "SYNTAX_CHECK_MODE=1"
2378 "check-syntax"))
2379)
2380
2381(defun flymake-get-ant-cmdline(source base-dir)
2382 (list "ant"
2383 (list "-buildfile"
2384 (concat base-dir "/" "build.xml")
2385 (concat "-DCHK_SOURCES=" source)
2386 "check-syntax"))
2387)
2388
2389(defun flymake-simple-make-init-impl(buffer create-temp-f use-relative-base-dir use-relative-source build-file-name get-cmdline-f)
2390 "create syntax check command line for a directly checked source file, use create-temp-f for creating temp copy"
2391 (let* ((args nil)
2392 (source-file-name (buffer-file-name buffer))
2393 (buildfile-dir (flymake-init-find-buildfile-dir buffer source-file-name build-file-name)))
2394 (if buildfile-dir
2395 (let* ((temp-source-file-name (flymake-init-create-temp-buffer-copy buffer create-temp-f)))
2396 (setq args (flymake-get-syntax-check-program-args temp-source-file-name buildfile-dir
2397 use-relative-base-dir use-relative-source
2398 get-cmdline-f))
2399 )
2400 )
2401
2402 args
2403 )
2404)
2405
2406(defun flymake-simple-make-init(buffer)
2407 (flymake-simple-make-init-impl buffer 'flymake-create-temp-inplace t t "Makefile" 'flymake-get-make-cmdline)
2408)
2409
2410(defun flymake-master-make-init(buffer get-incl-dirs-f master-file-masks include-regexp-list)
2411 "create make command line for a source file checked via master file compilation"
2412 (let* ((make-args nil)
2413 (temp-master-file-name (flymake-init-create-temp-source-and-master-buffer-copy
2414 buffer get-incl-dirs-f 'flymake-create-temp-inplace
2415 master-file-masks include-regexp-list)))
2416 (when temp-master-file-name
2417 (let* ((buildfile-dir (flymake-init-find-buildfile-dir buffer temp-master-file-name "Makefile")))
2418 (if buildfile-dir
2419 (setq make-args (flymake-get-syntax-check-program-args
2420 temp-master-file-name buildfile-dir nil nil 'flymake-get-make-cmdline))
2421 )
2422 )
2423 )
2424
2425 make-args
2426 )
2427)
2428
2429(defun flymake-find-make-buildfile(source-dir)
2430 (flymake-find-buildfile "Makefile" source-dir flymake-buildfile-dirs)
2431)
2432
2433;;;; .h/make specific
2434(defun flymake-master-make-header-init(buffer)
2435 (flymake-master-make-init buffer
2436 'flymake-get-include-dirs
2437 '(".+\\.cpp$" ".+\\.c$")
2438 '("[ \t]*#[ \t]*include[ \t]*\"\\([\w0-9/\\_\.]*[/\\]*\\)\\(%s\\)\"" 1 2))
2439)
2440
2441;;;; .java/make specific
2442(defun flymake-simple-make-java-init(buffer)
2443 (flymake-simple-make-init-impl buffer 'flymake-create-temp-with-folder-structure nil nil "Makefile" 'flymake-get-make-cmdline)
2444)
2445
2446(defun flymake-simple-ant-java-init(buffer)
2447 (flymake-simple-make-init-impl buffer 'flymake-create-temp-with-folder-structure nil nil "build.xml" 'flymake-get-ant-cmdline)
2448)
2449
2450(defun flymake-simple-java-cleanup(buffer)
2451 "cleanup after flymake-simple-make-java-init -- delete temp file and dirs"
2452 (let* ((temp-source-file-name (flymake-get-buffer-value buffer "temp-source-file-name")))
2453 (flymake-safe-delete-file temp-source-file-name)
2454 (when temp-source-file-name
2455 (flymake-delete-temp-directory (file-name-directory temp-source-file-name))
2456 )
2457 )
2458)
2459
2460;;;; perl-specific init-cleanup routines
2461
2462(defun flymake-perl-init(buffer)
2463 (let* ((temp-file (flymake-init-create-temp-buffer-copy buffer 'flymake-create-temp-inplace))
2464 (local-file (concat (flymake-build-relative-path (file-name-directory (buffer-file-name (current-buffer)))
2465 (file-name-directory temp-file))
2466 (file-name-nondirectory temp-file))))
2467 (list "perl" (list "-wc " local-file))
2468 )
2469)
2470
2471;;;; tex-specific init-cleanup routines
2472
2473(defun flymake-get-tex-args(file-name)
2474 ;(list "latex" (list "-c-style-errors" file-name))
2475 (list "texify" (list "--pdf" "--tex-option=-c-style-errors" file-name))
2476)
2477
2478(defun flymake-simple-tex-init(buffer)
2479 (flymake-get-tex-args (flymake-init-create-temp-buffer-copy buffer 'flymake-create-temp-inplace))
2480)
2481
2482(defun flymake-master-tex-init(buffer)
2483 (let* ((temp-master-file-name (flymake-init-create-temp-source-and-master-buffer-copy
2484 buffer 'flymake-get-include-dirs-dot 'flymake-create-temp-inplace
2485 '(".+\\.tex$")
2486 '("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2))))
2487 (when temp-master-file-name
2488 (flymake-get-tex-args temp-master-file-name)
2489 )
2490 )
2491)
2492
2493(defun flymake-get-include-dirs-dot(base-dir)
2494 '(".")
2495)
2496
2497;;;; xml-specific init-cleanup routines
2498
2499(defun flymake-xml-init(buffer)
2500 (list "xml" (list "val" (flymake-init-create-temp-buffer-copy buffer 'flymake-create-temp-inplace)))
2501)
2502
2503;;; arch-tag: 8f0d6090-061d-4cac-8862-7c151c4a02dd
2504;;; flymake.el ends here
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index f23eabe6e9c..88d41650c07 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1700,8 +1700,7 @@ If ALL is nil, only match comments that start in column > 0."
1700 (while repeat 1700 (while repeat
1701 (setq repeat nil) 1701 (setq repeat nil)
1702 ;; Adapted from f90-find-breakpoint. 1702 ;; Adapted from f90-find-breakpoint.
1703 (re-search-backward fortran-break-delimiters-re 1703 (re-search-backward fortran-break-delimiters-re bol)
1704 (line-beginning-position))
1705 (if (not fortran-break-before-delimiters) 1704 (if (not fortran-break-before-delimiters)
1706 (if (looking-at fortran-no-break-re) 1705 (if (looking-at fortran-no-break-re)
1707 ;; Deal with cases such as "**" split over 1706 ;; Deal with cases such as "**" split over
diff --git a/lisp/progmodes/gdb-ui.el b/lisp/progmodes/gdb-ui.el
index 5163471f47a..2f267787707 100644
--- a/lisp/progmodes/gdb-ui.el
+++ b/lisp/progmodes/gdb-ui.el
@@ -1,6 +1,6 @@
1;;; gdb-ui.el --- User Interface for running GDB 1;;; gdb-ui.el --- User Interface for running GDB
2 2
3;; Author: Nick Roberts <nick@nick.uklinux.net> 3;; Author: Nick Roberts <nickrob@gnu.org>
4;; Maintainer: FSF 4;; Maintainer: FSF
5;; Keywords: unix, tools 5;; Keywords: unix, tools
6 6
@@ -40,8 +40,15 @@
40;; Kingdon and uses GDB's annotation interface. You don't need to know about 40;; Kingdon and uses GDB's annotation interface. You don't need to know about
41;; annotations to use this mode as a debugger, but if you are interested 41;; annotations to use this mode as a debugger, but if you are interested
42;; developing the mode itself, then see the Annotations section in the GDB 42;; developing the mode itself, then see the Annotations section in the GDB
43;; info manual. Some GDB/MI commands are also used through th CLI command 43;; info manual.
44;; 'interpreter mi <mi-command>'. 44;;
45;; GDB developers plan to make the annotation interface obsolete. A new
46;; interface called GDB/MI (machine interface) has been designed to replace
47;; it. Some GDB/MI commands are used in this file through the CLI command
48;; 'interpreter mi <mi-command>'. A file called gdb-mi.el is included in the
49;; GDB repository for future releases (6.2 onwards) that uses GDB/MI as the
50;; primary interface to GDB. It is still under development and is part of a
51;; process to migrate Emacs from annotations to GDB/MI.
45;; 52;;
46;; Known Bugs: 53;; Known Bugs:
47;; 54;;
@@ -53,7 +60,7 @@
53(defvar gdb-current-address "main" "Initialisation for Assembler buffer.") 60(defvar gdb-current-address "main" "Initialisation for Assembler buffer.")
54(defvar gdb-previous-address nil) 61(defvar gdb-previous-address nil)
55(defvar gdb-previous-frame nil) 62(defvar gdb-previous-frame nil)
56(defvar gdb-current-frame "main") 63(defvar gdb-current-frame nil)
57(defvar gdb-current-language nil) 64(defvar gdb-current-language nil)
58(defvar gdb-view-source t "Non-nil means that source code can be viewed.") 65(defvar gdb-view-source t "Non-nil means that source code can be viewed.")
59(defvar gdb-selected-view 'source "Code type that user wishes to view.") 66(defvar gdb-selected-view 'source "Code type that user wishes to view.")
@@ -63,7 +70,8 @@
63(defvar gdb-overlay-arrow-position nil) 70(defvar gdb-overlay-arrow-position nil)
64(defvar gdb-variables '() 71(defvar gdb-variables '()
65 "A list of variables that are local to the GUD buffer.") 72 "A list of variables that are local to the GUD buffer.")
66 73(defvar gdb-server-prefix nil)
74
67;;;###autoload 75;;;###autoload
68(defun gdba (command-line) 76(defun gdba (command-line)
69 "Run gdb on program FILE in buffer *gud-FILE*. 77 "Run gdb on program FILE in buffer *gud-FILE*.
@@ -73,23 +81,34 @@ and source-file directory for your debugger.
73If `gdb-many-windows' is nil (the default value) then gdb just 81If `gdb-many-windows' is nil (the default value) then gdb just
74pops up the GUD buffer unless `gdb-show-main' is t. In this case 82pops up the GUD buffer unless `gdb-show-main' is t. In this case
75it starts with two windows: one displaying the GUD buffer and the 83it starts with two windows: one displaying the GUD buffer and the
76other with the source file with the main routine of the debugee. 84other with the source file with the main routine of the inferior.
77 85
78If `gdb-many-windows' is t the layout below will appear 86If `gdb-many-windows' is t, regardless of the value of
79regardless of the value of `gdb-show-main' unless 87`gdb-show-main', the layout below will appear unless
80`gdb-use-inferior-io-buffer' is nil when the source buffer 88`gdb-use-inferior-io-buffer' is nil when the source buffer
81occupies the full width of the frame. Keybindings are given in 89occupies the full width of the frame. Keybindings are given in
82relevant buffer. 90relevant buffer.
83 91
92Watch expressions appear in the speedbar/slowbar.
93
94The following interactive lisp functions help control operation :
95
96`gdb-many-windows' - Toggle the number of windows gdb uses.
97`gdb-restore-windows' - To restore the window layout.
98
99See Info node `(emacs)GDB Graphical Interface' for a more
100detailed description of this mode.
101
102
84--------------------------------------------------------------------- 103---------------------------------------------------------------------
85 GDB Toolbar 104 GDB Toolbar
86--------------------------------------------------------------------- 105---------------------------------------------------------------------
87GUD buffer (I/O of GDB) | Locals buffer 106 GUD buffer (I/O of GDB) | Locals buffer
88 | 107 |
89 | 108 |
90 | 109 |
91--------------------------------------------------------------------- 110---------------------------------------------------------------------
92Source buffer | Input/Output (of debugee) buffer 111 Source buffer | Input/Output (of inferior) buffer
93 | (comint-mode) 112 | (comint-mode)
94 | 113 |
95 | 114 |
@@ -98,28 +117,12 @@ Source buffer | Input/Output (of debugee) buffer
98 | 117 |
99 | 118 |
100--------------------------------------------------------------------- 119---------------------------------------------------------------------
101Stack buffer | Breakpoints buffer 120 Stack buffer | Breakpoints buffer
102 RET gdb-frames-select | SPC gdb-toggle-breakpoint 121 RET gdb-frames-select | SPC gdb-toggle-breakpoint
103 | RET gdb-goto-breakpoint 122 | RET gdb-goto-breakpoint
104 | d gdb-delete-breakpoint 123 | d gdb-delete-breakpoint
105--------------------------------------------------------------------- 124---------------------------------------------------------------------
106 125"
107All the buffers share the toolbar and source should always display in the same
108window e.g after typing g on a breakpoint in the breakpoints buffer. Breakpoint
109icons are displayed both by setting a break with gud-break and by typing break
110in the GUD buffer.
111
112This works best (depending on the size of your monitor) using most of the
113screen.
114
115Displayed expressions appear in separate frames. Arrays may be displayed
116as slices and visualised using the graph program from plotutils if installed.
117Pointers in structures may be followed in a tree-like fashion.
118
119The following interactive lisp functions help control operation :
120
121`gdb-many-windows' - Toggle the number of windows gdb uses.
122`gdb-restore-windows' - To restore the window layout."
123 ;; 126 ;;
124 (interactive (list (gud-query-cmdline 'gdba))) 127 (interactive (list (gud-query-cmdline 'gdba)))
125 ;; 128 ;;
@@ -179,12 +182,17 @@ The following interactive lisp functions help control operation :
179 (setq gdb-current-address "main") 182 (setq gdb-current-address "main")
180 (setq gdb-previous-address nil) 183 (setq gdb-previous-address nil)
181 (setq gdb-previous-frame nil) 184 (setq gdb-previous-frame nil)
182 (setq gdb-current-frame "main") 185 (setq gdb-current-frame nil)
183 (setq gdb-view-source t) 186 (setq gdb-view-source t)
184 (setq gdb-selected-view 'source) 187 (setq gdb-selected-view 'source)
185 (setq gdb-var-list nil) 188 (setq gdb-var-list nil)
186 (setq gdb-var-changed nil) 189 (setq gdb-var-changed nil)
187 (setq gdb-first-prompt nil) 190 (setq gdb-first-prompt nil)
191 (setq gdb-prompting nil)
192 (setq gdb-current-item nil)
193 (setq gdb-pending-triggers nil)
194 (setq gdb-output-sink 'user)
195 (setq gdb-server-prefix "server ")
188 ;; 196 ;;
189 (mapc 'make-local-variable gdb-variables) 197 (mapc 'make-local-variable gdb-variables)
190 (setq gdb-buffer-type 'gdba) 198 (setq gdb-buffer-type 'gdba)
@@ -213,16 +221,26 @@ speedbar."
213 (require 'tooltip) 221 (require 'tooltip)
214 (let ((expr (tooltip-identifier-from-point (point)))) 222 (let ((expr (tooltip-identifier-from-point (point))))
215 (if (and (string-equal gdb-current-language "c") 223 (if (and (string-equal gdb-current-language "c")
216 gdb-use-colon-colon-notation) 224 gdb-use-colon-colon-notation gdb-current-frame)
217 (setq expr (concat gdb-current-frame "::" expr))) 225 (setq expr (concat gdb-current-frame "::" expr)))
218 (catch 'already-watched 226 (catch 'already-watched
219 (dolist (var gdb-var-list) 227 (dolist (var gdb-var-list)
220 (if (string-equal expr (car var)) (throw 'already-watched nil))) 228 (if (string-equal expr (car var)) (throw 'already-watched nil)))
221 (set-text-properties 0 (length expr) nil expr) 229 (set-text-properties 0 (length expr) nil expr)
222 (gdb-enqueue-input 230 (gdb-enqueue-input
223 (list (concat "server interpreter mi \"-var-create - * " expr "\"\n") 231 (list
232 (if (eq gud-minor-mode 'gdba)
233 (concat "server interpreter mi \"-var-create - * " expr "\"\n")
234 (concat"-var-create - * " expr "\n"))
224 `(lambda () (gdb-var-create-handler ,expr)))))) 235 `(lambda () (gdb-var-create-handler ,expr))))))
225 (select-window (get-buffer-window gud-comint-buffer))) 236 (select-window (get-buffer-window gud-comint-buffer 'visible)))
237
238(defun gdb-goto-info ()
239 "Go to Emacs info node: GDB Graphical Interface."
240 (interactive)
241 (select-frame (make-frame))
242 (require 'info)
243 (Info-goto-node "(emacs)GDB Graphical Interface"))
226 244
227(defconst gdb-var-create-regexp 245(defconst gdb-var-create-regexp
228"name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"") 246"name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
@@ -306,12 +324,15 @@ speedbar."
306 (setq gdb-var-list (nreverse var-list)))))) 324 (setq gdb-var-list (nreverse var-list))))))
307 325
308(defun gdb-var-update () 326(defun gdb-var-update ()
309 (if (not (member 'gdb-var-update (gdb-get-pending-triggers))) 327 (if (not (member 'gdb-var-update gdb-pending-triggers))
310 (progn 328 (progn
311 (gdb-enqueue-input (list "server interpreter mi \"-var-update *\"\n" 329 (gdb-enqueue-input
330 (list
331 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
332 "server interpreter mi \"-var-update *\"\n"
333 "-var-update *\n")
312 'gdb-var-update-handler)) 334 'gdb-var-update-handler))
313 (gdb-set-pending-triggers (cons 'gdb-var-update 335 (push 'gdb-var-update gdb-pending-triggers))))
314 (gdb-get-pending-triggers))))))
315 336
316(defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"") 337(defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"")
317 338
@@ -321,12 +342,15 @@ speedbar."
321 (while (re-search-forward gdb-var-update-regexp nil t) 342 (while (re-search-forward gdb-var-update-regexp nil t)
322 (let ((varnum (match-string 1))) 343 (let ((varnum (match-string 1)))
323 (gdb-enqueue-input 344 (gdb-enqueue-input
324 (list (concat "server interpreter mi \"-var-evaluate-expression " 345 (list
325 varnum "\"\n") 346 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
347 (concat "server interpreter mi \"-var-evaluate-expression "
348 varnum "\"\n")
349 (concat "-var-evaluate-expression " varnum "\n"))
326 `(lambda () (gdb-var-evaluate-expression-handler 350 `(lambda () (gdb-var-evaluate-expression-handler
327 ,varnum t))))))) 351 ,varnum t)))))))
328 (gdb-set-pending-triggers 352 (setq gdb-pending-triggers
329 (delq 'gdb-var-update (gdb-get-pending-triggers)))) 353 (delq 'gdb-var-update gdb-pending-triggers)))
330 354
331(defun gdb-var-delete () 355(defun gdb-var-delete ()
332 "Delete watched expression from the speedbar." 356 "Delete watched expression from the speedbar."
@@ -339,8 +363,11 @@ speedbar."
339 (varnum (cadr var))) 363 (varnum (cadr var)))
340 (unless (string-match "\\." varnum) 364 (unless (string-match "\\." varnum)
341 (gdb-enqueue-input 365 (gdb-enqueue-input
342 (list (concat "server interpreter mi \"-var-delete " 366 (list
343 varnum "\"\n") 367 (if (with-current-buffer gud-comint-buffer
368 (eq gud-minor-mode 'gdba))
369 (concat "server interpreter mi \"-var-delete " varnum "\"\n")
370 (concat "-var-delete " varnum "\n"))
344 'ignore)) 371 'ignore))
345 (setq gdb-var-list (delq var gdb-var-list)) 372 (setq gdb-var-list (delq var gdb-var-list))
346 (dolist (varchild gdb-var-list) 373 (dolist (varchild gdb-var-list)
@@ -354,8 +381,11 @@ speedbar."
354 (varnum (cadr var)) (value)) 381 (varnum (cadr var)) (value))
355 (setq value (read-string "New value: ")) 382 (setq value (read-string "New value: "))
356 (gdb-enqueue-input 383 (gdb-enqueue-input
357 (list (concat "server interpreter mi \"-var-assign " 384 (list
358 varnum " " value "\"\n") 385 (if (with-current-buffer gud-comint-buffer
386 (eq gud-minor-mode 'gdba))
387 (concat "server interpreter mi \"-var-assign " varnum " " value "\"\n")
388 (concat "-var-assign " varnum " " value "\n"))
359 'ignore)))) 389 'ignore))))
360 390
361(defcustom gdb-show-changed-values t 391(defcustom gdb-show-changed-values t
@@ -370,49 +400,25 @@ TEXT is the text of the button we clicked on, a + or - item.
370TOKEN is data related to this node. 400TOKEN is data related to this node.
371INDENT is the current indentation depth." 401INDENT is the current indentation depth."
372 (cond ((string-match "+" text) ;expand this node 402 (cond ((string-match "+" text) ;expand this node
373 (gdb-var-list-children token)) 403 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
404 (gdb-var-list-children token)
405 (gdbmi-var-list-children token)))
374 ((string-match "-" text) ;contract this node 406 ((string-match "-" text) ;contract this node
375 (dolist (var gdb-var-list) 407 (dolist (var gdb-var-list)
376 (if (string-match (concat token "\\.") (nth 1 var)) 408 (if (string-match (concat token "\\.") (nth 1 var))
377 (setq gdb-var-list (delq var gdb-var-list)))) 409 (setq gdb-var-list (delq var gdb-var-list))))
378 (setq gdb-var-changed t)))) 410 (setq gdb-var-changed t))))
379
380 411
381;; ====================================================================== 412(defvar gdb-buffer-type nil
382;;
383;; In this world, there are gdb variables (of unspecified
384;; representation) and buffers associated with those objects.
385;; The list of variables is built up by the expansions of
386;; def-gdb-variable
387
388(defmacro def-gdb-var (root-symbol &optional default doc)
389 (let* ((root (symbol-name root-symbol))
390 (accessor (intern (concat "gdb-get-" root)))
391 (setter (intern (concat "gdb-set-" root)))
392 (name (intern (concat "gdb-" root))))
393 `(progn
394 (defvar ,name ,default ,doc)
395 (if (not (memq ',name gdb-variables))
396 (push ',name gdb-variables))
397 (defun ,accessor ()
398 (buffer-local-value ',name gud-comint-buffer))
399 (defun ,setter (val)
400 (with-current-buffer gud-comint-buffer
401 (setq ,name val))))))
402
403(def-gdb-var buffer-type nil
404 "One of the symbols bound in `gdb-buffer-rules'.") 413 "One of the symbols bound in `gdb-buffer-rules'.")
405 414
406(def-gdb-var burst "" 415(defvar gdb-input-queue ()
407 "A string of characters from gdb that have not yet been processed.")
408
409(def-gdb-var input-queue ()
410 "A list of gdb command objects.") 416 "A list of gdb command objects.")
411 417
412(def-gdb-var prompting nil 418(defvar gdb-prompting nil
413 "True when gdb is idle with no pending input.") 419 "True when gdb is idle with no pending input.")
414 420
415(def-gdb-var output-sink 'user 421(defvar gdb-output-sink 'user
416 "The disposition of the output of the current gdb command. 422 "The disposition of the output of the current gdb command.
417Possible values are these symbols: 423Possible values are these symbols:
418 424
@@ -430,12 +436,14 @@ Possible values are these symbols:
430 gdb mode sends to gdb on its own behalf. 436 gdb mode sends to gdb on its own behalf.
431 post-emacs -- ignore output until the prompt annotation is 437 post-emacs -- ignore output until the prompt annotation is
432 received, then go to USER disposition. 438 received, then go to USER disposition.
433")
434 439
435(def-gdb-var current-item nil 440gdba (gdb-ui.el) uses all five values, gdbmi (gdb-mi.el) only two
441(user and emacs).")
442
443(defvar gdb-current-item nil
436 "The most recent command item sent to gdb.") 444 "The most recent command item sent to gdb.")
437 445
438(def-gdb-var pending-triggers '() 446(defvar gdb-pending-triggers '()
439 "A list of trigger functions that have run later than their output 447 "A list of trigger functions that have run later than their output
440handlers.") 448handlers.")
441 449
@@ -479,8 +487,8 @@ The key should be one of the cars in `gdb-buffer-rules-assoc'."
479 (set (make-local-variable 'gdb-buffer-type) key) 487 (set (make-local-variable 'gdb-buffer-type) key)
480 (if (cdr (cdr rules)) 488 (if (cdr (cdr rules))
481 (funcall (car (cdr (cdr rules))))) 489 (funcall (car (cdr (cdr rules)))))
482 (set (make-local-variable 'gud-comint-buffer) gud-comint-buffer) 490 (set (make-local-variable 'gud-minor-mode)
483 (set (make-local-variable 'gud-minor-mode) 'gdba) 491 (with-current-buffer gud-comint-buffer gud-minor-mode))
484 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map) 492 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
485 new)))) 493 new))))
486 494
@@ -548,7 +556,7 @@ The key should be one of the cars in `gdb-buffer-rules-assoc'."
548 (define-key map "\C-c\C-d" 'gdb-inferior-io-eof) 556 (define-key map "\C-c\C-d" 'gdb-inferior-io-eof)
549 map)) 557 map))
550 558
551(define-derived-mode gdb-inferior-io-mode comint-mode "Debuggee I/O" 559(define-derived-mode gdb-inferior-io-mode comint-mode "Inferior I/O"
552 "Major mode for gdb inferior-io." 560 "Major mode for gdb inferior-io."
553 :syntax-table nil :abbrev-table nil 561 :syntax-table nil :abbrev-table nil
554 ;; We want to use comint because it has various nifty and familiar 562 ;; We want to use comint because it has various nifty and familiar
@@ -620,20 +628,18 @@ This filter may simply queue output for a later time."
620;; is a query, or other non-top-level prompt. 628;; is a query, or other non-top-level prompt.
621 629
622(defun gdb-enqueue-input (item) 630(defun gdb-enqueue-input (item)
623 (if (gdb-get-prompting) 631 (if gdb-prompting
624 (progn 632 (progn
625 (gdb-send-item item) 633 (gdb-send-item item)
626 (gdb-set-prompting nil)) 634 (setq gdb-prompting nil))
627 (gdb-set-input-queue 635 (push item gdb-input-queue)))
628 (cons item (gdb-get-input-queue)))))
629 636
630(defun gdb-dequeue-input () 637(defun gdb-dequeue-input ()
631 (let ((queue (gdb-get-input-queue))) 638 (let ((queue gdb-input-queue))
632 (and queue 639 (and queue
633 (let ((last (car (last queue)))) 640 (let ((last (car (last queue))))
634 (unless (nbutlast queue) (gdb-set-input-queue '())) 641 (unless (nbutlast queue) (setq gdb-input-queue '()))
635 last)))) 642 last))))
636
637 643
638;; 644;;
639;; output -- things gdb prints to emacs 645;; output -- things gdb prints to emacs
@@ -662,6 +668,8 @@ This filter may simply queue output for a later time."
662 ("commands" gdb-subprompt) 668 ("commands" gdb-subprompt)
663 ("overload-choice" gdb-subprompt) 669 ("overload-choice" gdb-subprompt)
664 ("query" gdb-subprompt) 670 ("query" gdb-subprompt)
671 ;; Need this prompt for GDB 6.1
672 ("nquery" gdb-subprompt)
665 ("prompt-for-continue" gdb-subprompt) 673 ("prompt-for-continue" gdb-subprompt)
666 ("post-prompt" gdb-post-prompt) 674 ("post-prompt" gdb-post-prompt)
667 ("source" gdb-source) 675 ("source" gdb-source)
@@ -688,89 +696,97 @@ This filter may simply queue output for a later time."
688 (string-to-int (match-string 2 args)))) 696 (string-to-int (match-string 2 args))))
689 (setq gdb-current-address (match-string 3 args)) 697 (setq gdb-current-address (match-string 3 args))
690 (setq gdb-view-source t) 698 (setq gdb-view-source t)
691;; cover for auto-display output which comes *before* 699 ;; cover for auto-display output which comes *before*
692;; stopped annotation 700 ;; stopped annotation
693 (if (eq (gdb-get-output-sink) 'inferior) (gdb-set-output-sink 'user))) 701 (if (eq gdb-output-sink 'inferior) (setq gdb-output-sink 'user)))
694 702
695(defun gdb-send-item (item) 703(defun gdb-send-item (item)
696 (if gdb-enable-debug-log (push (cons 'send item) gdb-debug-log)) 704 (if gdb-enable-debug-log (push (cons 'send item) gdb-debug-log))
697 (gdb-set-current-item item) 705 (setq gdb-current-item item)
698 (if (stringp item) 706 (with-current-buffer gud-comint-buffer
699 (progn 707 (if (eq gud-minor-mode 'gdba)
700 (gdb-set-output-sink 'user) 708 (progn
701 (process-send-string (get-buffer-process gud-comint-buffer) item)) 709 (if (stringp item)
702 (progn 710 (progn
711 (setq gdb-output-sink 'user)
712 (process-send-string (get-buffer-process gud-comint-buffer) item))
713 (progn
714 (gdb-clear-partial-output)
715 (setq gdb-output-sink 'pre-emacs)
716 (process-send-string (get-buffer-process gud-comint-buffer)
717 (car item)))))
718 ; case: eq gud-minor-mode 'gdbmi
703 (gdb-clear-partial-output) 719 (gdb-clear-partial-output)
704 (gdb-set-output-sink 'pre-emacs) 720 (setq gdb-output-sink 'emacs)
705 (process-send-string (get-buffer-process gud-comint-buffer) 721 (process-send-string (get-buffer-process gud-comint-buffer)
706 (car item))))) 722 (car item)))))
707 723
708(defun gdb-pre-prompt (ignored) 724(defun gdb-pre-prompt (ignored)
709 "An annotation handler for `pre-prompt'. This terminates the collection of 725 "An annotation handler for `pre-prompt'. This terminates the collection of
710output from a previous command if that happens to be in effect." 726output from a previous command if that happens to be in effect."
711 (let ((sink (gdb-get-output-sink))) 727 (let ((sink gdb-output-sink))
712 (cond 728 (cond
713 ((eq sink 'user) t) 729 ((eq sink 'user) t)
714 ((eq sink 'emacs) 730 ((eq sink 'emacs)
715 (gdb-set-output-sink 'post-emacs)) 731 (setq gdb-output-sink 'post-emacs))
716 (t 732 (t
717 (gdb-set-output-sink 'user) 733 (setq gdb-output-sink 'user)
718 (error "Phase error in gdb-pre-prompt (got %s)" sink))))) 734 (error "Phase error in gdb-pre-prompt (got %s)" sink)))))
719 735
720(defun gdb-prompt (ignored) 736(defun gdb-prompt (ignored)
721 "An annotation handler for `prompt'. 737 "An annotation handler for `prompt'.
722This sends the next command (if any) to gdb." 738This sends the next command (if any) to gdb."
723 (when gdb-first-prompt (gdb-ann3)) 739 (when gdb-first-prompt (gdb-ann3))
724 (let ((sink (gdb-get-output-sink))) 740 (let ((sink gdb-output-sink))
725 (cond 741 (cond
726 ((eq sink 'user) t) 742 ((eq sink 'user) t)
727 ((eq sink 'post-emacs) 743 ((eq sink 'post-emacs)
728 (gdb-set-output-sink 'user) 744 (setq gdb-output-sink 'user)
729 (let ((handler 745 (let ((handler
730 (car (cdr (gdb-get-current-item))))) 746 (car (cdr gdb-current-item))))
731 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 747 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
732 (funcall handler)))) 748 (funcall handler))))
733 (t 749 (t
734 (gdb-set-output-sink 'user) 750 (setq gdb-output-sink 'user)
735 (error "Phase error in gdb-prompt (got %s)" sink)))) 751 (error "Phase error in gdb-prompt (got %s)" sink))))
736 (let ((input (gdb-dequeue-input))) 752 (let ((input (gdb-dequeue-input)))
737 (if input 753 (if input
738 (gdb-send-item input) 754 (gdb-send-item input)
739 (progn 755 (progn
740 (gdb-set-prompting t) 756 (setq gdb-prompting t)
741 (gud-display-frame))))) 757 (gud-display-frame)))))
742 758
743(defun gdb-subprompt (ignored) 759(defun gdb-subprompt (ignored)
744 "An annotation handler for non-top-level prompts." 760 "An annotation handler for non-top-level prompts."
745 (gdb-set-prompting t)) 761 (setq gdb-prompting t))
746 762
747(defun gdb-starting (ignored) 763(defun gdb-starting (ignored)
748 "An annotation handler for `starting'. This says that I/O for the 764 "An annotation handler for `starting'. This says that I/O for the
749subprocess is now the program being debugged, not GDB." 765subprocess is now the program being debugged, not GDB."
750 (let ((sink (gdb-get-output-sink))) 766 (let ((sink gdb-output-sink))
751 (cond 767 (cond
752 ((eq sink 'user) 768 ((eq sink 'user)
753 (progn 769 (progn
754 (setq gud-running t) 770 (setq gud-running t)
755 (if gdb-use-inferior-io-buffer 771 (if gdb-use-inferior-io-buffer
756 (gdb-set-output-sink 'inferior)))) 772 (setq gdb-output-sink 'inferior))))
757 (t (error "Unexpected `starting' annotation"))))) 773 (t (error "Unexpected `starting' annotation")))))
758 774
759(defun gdb-stopping (ignored) 775(defun gdb-stopping (ignored)
760 "An annotation handler for `exited' and other annotations which say that I/O 776 "An annotation handler for `exited' and other annotations which say that I/O
761for the subprocess is now GDB, not the program being debugged." 777for the subprocess is now GDB, not the program being debugged."
762 (if gdb-use-inferior-io-buffer 778 (if gdb-use-inferior-io-buffer
763 (let ((sink (gdb-get-output-sink))) 779 (let ((sink gdb-output-sink))
764 (cond 780 (cond
765 ((eq sink 'inferior) 781 ((eq sink 'inferior)
766 (gdb-set-output-sink 'user)) 782 (setq gdb-output-sink 'user))
767 (t (error "Unexpected stopping annotation")))))) 783 (t (error "Unexpected stopping annotation"))))))
768 784
769(defun gdb-frame-begin (ignored) 785(defun gdb-frame-begin (ignored)
770 (let ((sink (gdb-get-output-sink))) 786 (let ((sink gdb-output-sink))
771 (cond 787 (cond
772 ((eq sink 'inferior) 788 ((eq sink 'inferior)
773 (gdb-set-output-sink 'user)) 789 (setq gdb-output-sink 'user))
774 ((eq sink 'user) t) 790 ((eq sink 'user) t)
775 ((eq sink 'emacs) t) 791 ((eq sink 'emacs) t)
776 (t (error "Unexpected frame-begin annotation (%S)" sink))))) 792 (t (error "Unexpected frame-begin annotation (%S)" sink)))))
@@ -779,17 +795,17 @@ for the subprocess is now GDB, not the program being debugged."
779 "An annotation handler for `stopped'. It is just like gdb-stopping, except 795 "An annotation handler for `stopped'. It is just like gdb-stopping, except
780that if we already set the output sink to 'user in gdb-stopping, that is fine." 796that if we already set the output sink to 'user in gdb-stopping, that is fine."
781 (setq gud-running nil) 797 (setq gud-running nil)
782 (let ((sink (gdb-get-output-sink))) 798 (let ((sink gdb-output-sink))
783 (cond 799 (cond
784 ((eq sink 'inferior) 800 ((eq sink 'inferior)
785 (gdb-set-output-sink 'user)) 801 (setq gdb-output-sink 'user))
786 ((eq sink 'user) t) 802 ((eq sink 'user) t)
787 (t (error "Unexpected stopped annotation"))))) 803 (t (error "Unexpected stopped annotation")))))
788 804
789(defun gdb-post-prompt (ignored) 805(defun gdb-post-prompt (ignored)
790 "An annotation handler for `post-prompt'. This begins the collection of 806 "An annotation handler for `post-prompt'. This begins the collection of
791output from the current command if that happens to be appropriate." 807output from the current command if that happens to be appropriate."
792 (if (not (gdb-get-pending-triggers)) 808 (if (not gdb-pending-triggers)
793 (progn 809 (progn
794 (gdb-get-current-frame) 810 (gdb-get-current-frame)
795 (gdb-invalidate-frames) 811 (gdb-invalidate-frames)
@@ -806,13 +822,13 @@ output from the current command if that happens to be appropriate."
806 (dolist (var gdb-var-list) 822 (dolist (var gdb-var-list)
807 (setcar (nthcdr 5 var) nil)))) 823 (setcar (nthcdr 5 var) nil))))
808 (gdb-var-update)))) 824 (gdb-var-update))))
809 (let ((sink (gdb-get-output-sink))) 825 (let ((sink gdb-output-sink))
810 (cond 826 (cond
811 ((eq sink 'user) t) 827 ((eq sink 'user) t)
812 ((eq sink 'pre-emacs) 828 ((eq sink 'pre-emacs)
813 (gdb-set-output-sink 'emacs)) 829 (setq gdb-output-sink 'emacs))
814 (t 830 (t
815 (gdb-set-output-sink 'user) 831 (setq gdb-output-sink 'user)
816 (error "Phase error in gdb-post-prompt (got %s)" sink))))) 832 (error "Phase error in gdb-post-prompt (got %s)" sink)))))
817 833
818(defun gud-gdba-marker-filter (string) 834(defun gud-gdba-marker-filter (string)
@@ -874,7 +890,7 @@ output from the current command if that happens to be appropriate."
874 output)) 890 output))
875 891
876(defun gdb-concat-output (so-far new) 892(defun gdb-concat-output (so-far new)
877 (let ((sink (gdb-get-output-sink ))) 893 (let ((sink gdb-output-sink))
878 (cond 894 (cond
879 ((eq sink 'user) (concat so-far new)) 895 ((eq sink 'user) (concat so-far new))
880 ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far) 896 ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far)
@@ -936,19 +952,17 @@ output from the current command if that happens to be appropriate."
936 `(defun ,name (&optional ignored) 952 `(defun ,name (&optional ignored)
937 (if (and (,demand-predicate) 953 (if (and (,demand-predicate)
938 (not (member ',name 954 (not (member ',name
939 (gdb-get-pending-triggers)))) 955 gdb-pending-triggers)))
940 (progn 956 (progn
941 (gdb-enqueue-input 957 (gdb-enqueue-input
942 (list ,gdb-command ',output-handler)) 958 (list ,gdb-command ',output-handler))
943 (gdb-set-pending-triggers 959 (push ',name gdb-pending-triggers)))))
944 (cons ',name
945 (gdb-get-pending-triggers)))))))
946 960
947(defmacro def-gdb-auto-update-handler (name trigger buf-key custom-defun) 961(defmacro def-gdb-auto-update-handler (name trigger buf-key custom-defun)
948 `(defun ,name () 962 `(defun ,name ()
949 (gdb-set-pending-triggers 963 (setq gdb-pending-triggers
950 (delq ',trigger 964 (delq ',trigger
951 (gdb-get-pending-triggers))) 965 gdb-pending-triggers))
952 (let ((buf (gdb-get-buffer ',buf-key))) 966 (let ((buf (gdb-get-buffer ',buf-key)))
953 (and buf 967 (and buf
954 (with-current-buffer buf 968 (with-current-buffer buf
@@ -1080,7 +1094,7 @@ static char *magick[] = {
1080 (dolist (buffer (buffer-list)) 1094 (dolist (buffer (buffer-list))
1081 (with-current-buffer buffer 1095 (with-current-buffer buffer
1082 (if (and (eq gud-minor-mode 'gdba) 1096 (if (and (eq gud-minor-mode 'gdba)
1083 (not (string-match "^\*" (buffer-name)))) 1097 (not (string-match "\\`\\*.+\\*\\'" (buffer-name))))
1084 (gdb-remove-breakpoint-icons (point-min) (point-max))))) 1098 (gdb-remove-breakpoint-icons (point-min) (point-max)))))
1085 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer) 1099 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
1086 (save-excursion 1100 (save-excursion
@@ -1112,10 +1126,11 @@ static char *magick[] = {
1112 (save-excursion 1126 (save-excursion
1113 (goto-line (string-to-number line)) 1127 (goto-line (string-to-number line))
1114 (gdb-put-breakpoint-icon (eq flag ?y))))))))) 1128 (gdb-put-breakpoint-icon (eq flag ?y)))))))))
1115 (end-of-line)))))) 1129 (end-of-line)))))
1130 (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom)))
1116 1131
1117(defun gdb-mouse-toggle-breakpoint (event) 1132(defun gdb-mouse-toggle-breakpoint (event)
1118 "Toggle breakpoint with mouse click in left margin." 1133 "Toggle breakpoint in left fringe/margin with mouse click"
1119 (interactive "e") 1134 (interactive "e")
1120 (mouse-minibuffer-check event) 1135 (mouse-minibuffer-check event)
1121 (let ((posn (event-end event))) 1136 (let ((posn (event-end event)))
@@ -1135,14 +1150,24 @@ static char *magick[] = {
1135 (concat "*breakpoints of " (gdb-get-target-string) "*"))) 1150 (concat "*breakpoints of " (gdb-get-target-string) "*")))
1136 1151
1137(defun gdb-display-breakpoints-buffer () 1152(defun gdb-display-breakpoints-buffer ()
1153 "Display status of user-settable breakpoints."
1138 (interactive) 1154 (interactive)
1139 (gdb-display-buffer 1155 (gdb-display-buffer
1140 (gdb-get-create-buffer 'gdb-breakpoints-buffer))) 1156 (gdb-get-create-buffer 'gdb-breakpoints-buffer)))
1141 1157
1158(defconst gdb-frame-parameters
1159 '((height . 12) (width . 60)
1160 (unsplittable . t)
1161 (tool-bar-lines . nil)
1162 (menu-bar-lines . nil)
1163 (minibuffer . nil)))
1164
1142(defun gdb-frame-breakpoints-buffer () 1165(defun gdb-frame-breakpoints-buffer ()
1166 "Display status of user-settable breakpoints in a new frame."
1143 (interactive) 1167 (interactive)
1144 (switch-to-buffer-other-frame 1168 (select-frame (make-frame gdb-frame-parameters))
1145 (gdb-get-create-buffer 'gdb-breakpoints-buffer))) 1169 (switch-to-buffer (gdb-get-create-buffer 'gdb-breakpoints-buffer))
1170 (set-window-dedicated-p (selected-window) t))
1146 1171
1147(defvar gdb-breakpoints-mode-map 1172(defvar gdb-breakpoints-mode-map
1148 (let ((map (make-sparse-keymap)) 1173 (let ((map (make-sparse-keymap))
@@ -1167,7 +1192,9 @@ static char *magick[] = {
1167 (setq mode-name "Breakpoints") 1192 (setq mode-name "Breakpoints")
1168 (use-local-map gdb-breakpoints-mode-map) 1193 (use-local-map gdb-breakpoints-mode-map)
1169 (setq buffer-read-only t) 1194 (setq buffer-read-only t)
1170 (gdb-invalidate-breakpoints)) 1195 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1196 (gdb-invalidate-breakpoints)
1197 (gdbmi-invalidate-breakpoints)))
1171 1198
1172(defun gdb-toggle-breakpoint () 1199(defun gdb-toggle-breakpoint ()
1173 "Enable/disable the breakpoint at current line." 1200 "Enable/disable the breakpoint at current line."
@@ -1180,8 +1207,8 @@ static char *magick[] = {
1180 (list 1207 (list
1181 (concat 1208 (concat
1182 (if (eq ?y (char-after (match-beginning 2))) 1209 (if (eq ?y (char-after (match-beginning 2)))
1183 "server disable " 1210 gdb-server-prefix "disable "
1184 "server enable ") 1211 gdb-server-prefix "enable ")
1185 (match-string 1) "\n") 1212 (match-string 1) "\n")
1186 'ignore))))) 1213 'ignore)))))
1187 1214
@@ -1192,28 +1219,31 @@ static char *magick[] = {
1192 (if (not (looking-at "\\([0-9]+\\).*point\\s-*\\S-*\\s-*\\(.\\)")) 1219 (if (not (looking-at "\\([0-9]+\\).*point\\s-*\\S-*\\s-*\\(.\\)"))
1193 (error "Not recognized as break/watchpoint line") 1220 (error "Not recognized as break/watchpoint line")
1194 (gdb-enqueue-input 1221 (gdb-enqueue-input
1195 (list (concat "server delete " (match-string 1) "\n") 'ignore)))) 1222 (list (concat gdb-server-prefix "delete " (match-string 1) "\n") 'ignore))))
1196 1223
1197(defun gdb-goto-breakpoint () 1224(defun gdb-goto-breakpoint ()
1198 "Display the file in the source buffer at the breakpoint specified on the 1225 "Display the breakpoint location specified at current line."
1199current line."
1200 (interactive) 1226 (interactive)
1201 (save-excursion 1227 (save-excursion
1202 (beginning-of-line 1) 1228 (beginning-of-line 1)
1203 (re-search-forward "in\\s-+\\S-+\\s-+at\\s-+" nil t) 1229 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdbmi))
1204 (looking-at "\\(\\S-*\\):\\([0-9]+\\)")) 1230 (looking-at "[0-9]*\\s-*\\S-*\\s-*\\S-*\\s-*.\\s-*\\S-*\\s-*\\(\\S-*\\):\\([0-9]+\\)")
1231 (re-search-forward "in\\s-+\\S-+\\s-+at\\s-+" nil t)
1232 (looking-at "\\(\\S-*\\):\\([0-9]+\\)")))
1205 (if (match-string 2) 1233 (if (match-string 2)
1206 (let ((line (match-string 2)) 1234 (let ((line (match-string 2))
1207 (file (match-string 1))) 1235 (file (match-string 1)))
1208 (save-selected-window 1236 (save-selected-window
1209 (gdb-display-buffer (find-file-noselect 1237 (let* ((buf (find-file-noselect (if (file-exists-p file)
1210 (if (file-exists-p file) 1238 file
1211 file 1239 (expand-file-name file gdb-cdir))))
1212 (expand-file-name file gdb-cdir)))) 1240 (window (gdb-display-buffer buf)))
1213 (goto-line (string-to-number line)))))) 1241 (with-current-buffer buf
1242 (goto-line (string-to-number line))
1243 (set-window-point window (point))))))))
1214 1244
1215(defun gdb-mouse-goto-breakpoint (event) 1245(defun gdb-mouse-goto-breakpoint (event)
1216 "Display the file in the source buffer at the selected breakpoint." 1246 "Display the breakpoint location that you click on."
1217 (interactive "e") 1247 (interactive "e")
1218 (mouse-set-point event) 1248 (mouse-set-point event)
1219 (gdb-goto-breakpoint)) 1249 (gdb-goto-breakpoint))
@@ -1256,14 +1286,17 @@ current line."
1256 (concat "*stack frames of " (gdb-get-target-string) "*"))) 1286 (concat "*stack frames of " (gdb-get-target-string) "*")))
1257 1287
1258(defun gdb-display-stack-buffer () 1288(defun gdb-display-stack-buffer ()
1289 "Display backtrace of current stack."
1259 (interactive) 1290 (interactive)
1260 (gdb-display-buffer 1291 (gdb-display-buffer
1261 (gdb-get-create-buffer 'gdb-stack-buffer))) 1292 (gdb-get-create-buffer 'gdb-stack-buffer)))
1262 1293
1263(defun gdb-frame-stack-buffer () 1294(defun gdb-frame-stack-buffer ()
1295 "Display backtrace of current stack in a new frame."
1264 (interactive) 1296 (interactive)
1265 (switch-to-buffer-other-frame 1297 (select-frame (make-frame gdb-frame-parameters))
1266 (gdb-get-create-buffer 'gdb-stack-buffer))) 1298 (switch-to-buffer (gdb-get-create-buffer 'gdb-stack-buffer))
1299 (set-window-dedicated-p (selected-window) t))
1267 1300
1268(defvar gdb-frames-mode-map 1301(defvar gdb-frames-mode-map
1269 (let ((map (make-sparse-keymap))) 1302 (let ((map (make-sparse-keymap)))
@@ -1281,25 +1314,25 @@ current line."
1281 (setq buffer-read-only t) 1314 (setq buffer-read-only t)
1282 (use-local-map gdb-frames-mode-map) 1315 (use-local-map gdb-frames-mode-map)
1283 (font-lock-mode -1) 1316 (font-lock-mode -1)
1284 (gdb-invalidate-frames)) 1317 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1318 (gdb-invalidate-frames)
1319 (gdbmi-invalidate-frames)))
1285 1320
1286(defun gdb-get-frame-number () 1321(defun gdb-get-frame-number ()
1287 (save-excursion 1322 (save-excursion
1288 (let* ((pos (re-search-backward "^#\\([0-9]*\\)" nil t)) 1323 (let* ((pos (re-search-backward "^#*\\([0-9]*\\)" nil t))
1289 (n (or (and pos (match-string-no-properties 1)) "0"))) 1324 (n (or (and pos (match-string-no-properties 1)) "0")))
1290 n))) 1325 n)))
1291 1326
1292(defun gdb-frames-select () 1327(defun gdb-frames-select ()
1293 "Make the frame on the current line become the current frame and display the 1328 "Select the frame and display the relevant source."
1294source in the source buffer."
1295 (interactive) 1329 (interactive)
1296 (gdb-enqueue-input 1330 (gdb-enqueue-input
1297 (list (concat "server frame " (gdb-get-frame-number) "\n") 'ignore)) 1331 (list (concat gdb-server-prefix "frame " (gdb-get-frame-number) "\n") 'ignore))
1298 (gud-display-frame)) 1332 (gud-display-frame))
1299 1333
1300(defun gdb-frames-mouse-select (event) 1334(defun gdb-frames-mouse-select (event)
1301 "Make the selected frame become the current frame and display the source in 1335 "Select the frame you click on and display the relevant source."
1302the source buffer."
1303 (interactive "e") 1336 (interactive "e")
1304 (mouse-set-point event) 1337 (mouse-set-point event)
1305 (gdb-frames-select)) 1338 (gdb-frames-select))
@@ -1313,7 +1346,7 @@ the source buffer."
1313 1346
1314(def-gdb-auto-updated-buffer gdb-threads-buffer 1347(def-gdb-auto-updated-buffer gdb-threads-buffer
1315 gdb-invalidate-threads 1348 gdb-invalidate-threads
1316 "server info threads\n" 1349 (concat gdb-server-prefix "info threads\n")
1317 gdb-info-threads-handler 1350 gdb-info-threads-handler
1318 gdb-info-threads-custom) 1351 gdb-info-threads-custom)
1319 1352
@@ -1332,14 +1365,17 @@ the source buffer."
1332 (concat "*threads of " (gdb-get-target-string) "*"))) 1365 (concat "*threads of " (gdb-get-target-string) "*")))
1333 1366
1334(defun gdb-display-threads-buffer () 1367(defun gdb-display-threads-buffer ()
1368 "Display IDs of currently known threads."
1335 (interactive) 1369 (interactive)
1336 (gdb-display-buffer 1370 (gdb-display-buffer
1337 (gdb-get-create-buffer 'gdb-threads-buffer))) 1371 (gdb-get-create-buffer 'gdb-threads-buffer)))
1338 1372
1339(defun gdb-frame-threads-buffer () 1373(defun gdb-frame-threads-buffer ()
1374 "Display IDs of currently known threads in a new frame."
1340 (interactive) 1375 (interactive)
1341 (switch-to-buffer-other-frame 1376 (select-frame (make-frame gdb-frame-parameters))
1342 (gdb-get-create-buffer 'gdb-threads-buffer))) 1377 (switch-to-buffer (gdb-get-create-buffer 'gdb-threads-buffer))
1378 (set-window-dedicated-p (selected-window) t))
1343 1379
1344(defvar gdb-threads-mode-map 1380(defvar gdb-threads-mode-map
1345 (let ((map (make-sparse-keymap))) 1381 (let ((map (make-sparse-keymap)))
@@ -1351,7 +1387,7 @@ the source buffer."
1351(defun gdb-threads-mode () 1387(defun gdb-threads-mode ()
1352 "Major mode for gdb frames. 1388 "Major mode for gdb frames.
1353 1389
1354\\{gdb-frames-mode-map}" 1390\\{gdb-threads-mode-map}"
1355 (setq major-mode 'gdb-threads-mode) 1391 (setq major-mode 'gdb-threads-mode)
1356 (setq mode-name "Threads") 1392 (setq mode-name "Threads")
1357 (setq buffer-read-only t) 1393 (setq buffer-read-only t)
@@ -1364,16 +1400,14 @@ the source buffer."
1364 (match-string-no-properties 1))) 1400 (match-string-no-properties 1)))
1365 1401
1366(defun gdb-threads-select () 1402(defun gdb-threads-select ()
1367 "Make the thread on the current line become the current thread and display the 1403 "Select the thread and display the relevant source."
1368source in the source buffer."
1369 (interactive) 1404 (interactive)
1370 (gdb-enqueue-input 1405 (gdb-enqueue-input
1371 (list (concat "thread " (gdb-get-thread-number) "\n") 'ignore)) 1406 (list (concat "thread " (gdb-get-thread-number) "\n") 'ignore))
1372 (gud-display-frame)) 1407 (gud-display-frame))
1373 1408
1374(defun gdb-threads-mouse-select (event) 1409(defun gdb-threads-mouse-select (event)
1375 "Make the selected frame become the current frame and display the source in 1410 "Select the thread you click on and display the relevant source."
1376the source buffer."
1377 (interactive "e") 1411 (interactive "e")
1378 (mouse-set-point event) 1412 (mouse-set-point event)
1379 (gdb-threads-select)) 1413 (gdb-threads-select))
@@ -1387,7 +1421,7 @@ the source buffer."
1387 1421
1388(def-gdb-auto-updated-buffer gdb-registers-buffer 1422(def-gdb-auto-updated-buffer gdb-registers-buffer
1389 gdb-invalidate-registers 1423 gdb-invalidate-registers
1390 "server info registers\n" 1424 (concat gdb-server-prefix "info registers\n")
1391 gdb-info-registers-handler 1425 gdb-info-registers-handler
1392 gdb-info-registers-custom) 1426 gdb-info-registers-custom)
1393 1427
@@ -1413,14 +1447,17 @@ the source buffer."
1413 (concat "*registers of " (gdb-get-target-string) "*"))) 1447 (concat "*registers of " (gdb-get-target-string) "*")))
1414 1448
1415(defun gdb-display-registers-buffer () 1449(defun gdb-display-registers-buffer ()
1450 "Display integer register contents."
1416 (interactive) 1451 (interactive)
1417 (gdb-display-buffer 1452 (gdb-display-buffer
1418 (gdb-get-create-buffer 'gdb-registers-buffer))) 1453 (gdb-get-create-buffer 'gdb-registers-buffer)))
1419 1454
1420(defun gdb-frame-registers-buffer () 1455(defun gdb-frame-registers-buffer ()
1456 "Display integer register contents in a new frame."
1421 (interactive) 1457 (interactive)
1422 (switch-to-buffer-other-frame 1458 (select-frame (make-frame gdb-frame-parameters))
1423 (gdb-get-create-buffer 'gdb-registers-buffer))) 1459 (switch-to-buffer (gdb-get-create-buffer 'gdb-registers-buffer))
1460 (set-window-dedicated-p (selected-window) t))
1424 1461
1425;; 1462;;
1426;; Locals buffer. 1463;; Locals buffer.
@@ -1438,8 +1475,8 @@ the source buffer."
1438;; Abbreviate for arrays and structures. 1475;; Abbreviate for arrays and structures.
1439;; These can be expanded using gud-display. 1476;; These can be expanded using gud-display.
1440(defun gdb-info-locals-handler nil 1477(defun gdb-info-locals-handler nil
1441 (gdb-set-pending-triggers (delq 'gdb-invalidate-locals 1478 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals
1442 (gdb-get-pending-triggers))) 1479 gdb-pending-triggers))
1443 (let ((buf (gdb-get-buffer 'gdb-partial-output-buffer))) 1480 (let ((buf (gdb-get-buffer 'gdb-partial-output-buffer)))
1444 (with-current-buffer buf 1481 (with-current-buffer buf
1445 (goto-char (point-min)) 1482 (goto-char (point-min))
@@ -1474,24 +1511,29 @@ the source buffer."
1474 1511
1475\\{gdb-locals-mode-map}" 1512\\{gdb-locals-mode-map}"
1476 (setq major-mode 'gdb-locals-mode) 1513 (setq major-mode 'gdb-locals-mode)
1477 (setq mode-name "Locals") 1514 (setq mode-name (concat "Locals:" gdb-current-frame))
1478 (setq buffer-read-only t) 1515 (setq buffer-read-only t)
1479 (use-local-map gdb-locals-mode-map) 1516 (use-local-map gdb-locals-mode-map)
1480 (gdb-invalidate-locals)) 1517 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1518 (gdb-invalidate-locals)
1519 (gdbmi-invalidate-locals)))
1481 1520
1482(defun gdb-locals-buffer-name () 1521(defun gdb-locals-buffer-name ()
1483 (with-current-buffer gud-comint-buffer 1522 (with-current-buffer gud-comint-buffer
1484 (concat "*locals of " (gdb-get-target-string) "*"))) 1523 (concat "*locals of " (gdb-get-target-string) "*")))
1485 1524
1486(defun gdb-display-locals-buffer () 1525(defun gdb-display-locals-buffer ()
1526 "Display local variables of current stack and their values."
1487 (interactive) 1527 (interactive)
1488 (gdb-display-buffer 1528 (gdb-display-buffer
1489 (gdb-get-create-buffer 'gdb-locals-buffer))) 1529 (gdb-get-create-buffer 'gdb-locals-buffer)))
1490 1530
1491(defun gdb-frame-locals-buffer () 1531(defun gdb-frame-locals-buffer ()
1532 "Display local variables of current stack and their values in a new frame."
1492 (interactive) 1533 (interactive)
1493 (switch-to-buffer-other-frame 1534 (select-frame (make-frame gdb-frame-parameters))
1494 (gdb-get-create-buffer 'gdb-locals-buffer))) 1535 (switch-to-buffer (gdb-get-create-buffer 'gdb-locals-buffer))
1536 (set-window-dedicated-p (selected-window) t))
1495 1537
1496 1538
1497;;;; Window management 1539;;;; Window management
@@ -1510,9 +1552,9 @@ the source buffer."
1510 #'(lambda (win) 1552 #'(lambda (win)
1511 (if (eq gud-comint-buffer (window-buffer win)) 1553 (if (eq gud-comint-buffer (window-buffer win))
1512 (set-window-dedicated-p win t)))) 1554 (set-window-dedicated-p win t))))
1513 (setq answer (get-buffer-window buf)) 1555 (setq answer (get-buffer-window buf 'visible))
1514 (if (not answer) 1556 (if (not answer)
1515 (let ((window (get-lru-window))) 1557 (let ((window (get-lru-window 'visible)))
1516 (if window 1558 (if window
1517 (progn 1559 (progn
1518 (set-window-buffer window buf) 1560 (set-window-buffer window buf)
@@ -1523,7 +1565,7 @@ the source buffer."
1523 (if (eq gud-comint-buffer (window-buffer win)) 1565 (if (eq gud-comint-buffer (window-buffer win))
1524 (set-window-dedicated-p win nil))))) 1566 (set-window-dedicated-p win nil)))))
1525 (if must-split 1567 (if must-split
1526 (let* ((largest (get-largest-window)) 1568 (let* ((largest (get-largest-window 'visible))
1527 (cur-size (window-height largest)) 1569 (cur-size (window-height largest))
1528 (new-size (and size (< size cur-size) (- cur-size size)))) 1570 (new-size (and size (< size cur-size) (- cur-size size))))
1529 (setq answer (split-window largest new-size)) 1571 (setq answer (split-window largest new-size))
@@ -1532,11 +1574,9 @@ the source buffer."
1532 1574
1533(defun gdb-display-source-buffer (buffer) 1575(defun gdb-display-source-buffer (buffer)
1534 (if (eq gdb-selected-view 'source) 1576 (if (eq gdb-selected-view 'source)
1535 (progn
1536 (gdb-display-buffer buffer) 1577 (gdb-display-buffer buffer)
1537 (get-buffer-window buffer)) 1578 (gdb-display-buffer (gdb-get-buffer 'gdb-assembler-buffer)))
1538 (gdb-display-buffer (gdb-get-buffer 'gdb-assembler-buffer)) 1579 (get-buffer-window buffer 'visible))
1539 nil))
1540 1580
1541 1581
1542;;; Shared keymap initialization: 1582;;; Shared keymap initialization:
@@ -1545,25 +1585,23 @@ the source buffer."
1545 (define-key gud-menu-map [frames] 1585 (define-key gud-menu-map [frames]
1546 `(menu-item "GDB-Frames" ,menu :visible (eq gud-minor-mode 'gdba))) 1586 `(menu-item "GDB-Frames" ,menu :visible (eq gud-minor-mode 'gdba)))
1547 (define-key menu [gdb] '("Gdb" . gdb-frame-gdb-buffer)) 1587 (define-key menu [gdb] '("Gdb" . gdb-frame-gdb-buffer))
1548 (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer)) 1588 (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
1589 (define-key menu [assembler] '("Machine" . gdb-frame-assembler-buffer))
1549 (define-key menu [registers] '("Registers" . gdb-frame-registers-buffer)) 1590 (define-key menu [registers] '("Registers" . gdb-frame-registers-buffer))
1591 (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer))
1550 (define-key menu [frames] '("Stack" . gdb-frame-stack-buffer)) 1592 (define-key menu [frames] '("Stack" . gdb-frame-stack-buffer))
1551 (define-key menu [breakpoints] '("Breakpoints" . gdb-frame-breakpoints-buffer)) 1593 (define-key menu [breakpoints] '("Breakpoints" . gdb-frame-breakpoints-buffer)))
1552 (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
1553; (define-key menu [assembler] '("Machine" . gdb-frame-assembler-buffer))
1554)
1555 1594
1556(let ((menu (make-sparse-keymap "GDB-Windows"))) 1595(let ((menu (make-sparse-keymap "GDB-Windows")))
1557 (define-key gud-menu-map [displays] 1596 (define-key gud-menu-map [displays]
1558 `(menu-item "GDB-Windows" ,menu :visible (eq gud-minor-mode 'gdba))) 1597 `(menu-item "GDB-Windows" ,menu :visible (eq gud-minor-mode 'gdba)))
1559 (define-key menu [gdb] '("Gdb" . gdb-display-gdb-buffer)) 1598 (define-key menu [gdb] '("Gdb" . gdb-display-gdb-buffer))
1560 (define-key menu [locals] '("Locals" . gdb-display-locals-buffer)) 1599 (define-key menu [assembler] '("Machine" . gdb-display-assembler-buffer))
1600 (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
1561 (define-key menu [registers] '("Registers" . gdb-display-registers-buffer)) 1601 (define-key menu [registers] '("Registers" . gdb-display-registers-buffer))
1602 (define-key menu [locals] '("Locals" . gdb-display-locals-buffer))
1562 (define-key menu [frames] '("Stack" . gdb-display-stack-buffer)) 1603 (define-key menu [frames] '("Stack" . gdb-display-stack-buffer))
1563 (define-key menu [breakpoints] '("Breakpoints" . gdb-display-breakpoints-buffer)) 1604 (define-key menu [breakpoints] '("Breakpoints" . gdb-display-breakpoints-buffer)))
1564 (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
1565; (define-key menu [assembler] '("Machine" . gdb-display-assembler-buffer))
1566)
1567 1605
1568(let ((menu (make-sparse-keymap "View"))) 1606(let ((menu (make-sparse-keymap "View")))
1569 (define-key gud-menu-map [view] 1607 (define-key gud-menu-map [view]
@@ -1589,11 +1627,14 @@ the source buffer."
1589 "Display locals, stack and breakpoint information"))) 1627 "Display locals, stack and breakpoint information")))
1590 1628
1591(defun gdb-frame-gdb-buffer () 1629(defun gdb-frame-gdb-buffer ()
1630 "Display GUD buffer in a new frame."
1592 (interactive) 1631 (interactive)
1593 (switch-to-buffer-other-frame 1632 (select-frame (make-frame gdb-frame-parameters))
1594 (gdb-get-create-buffer 'gdba))) 1633 (switch-to-buffer (gdb-get-create-buffer 'gdba))
1634 (set-window-dedicated-p (selected-window) t))
1595 1635
1596(defun gdb-display-gdb-buffer () 1636(defun gdb-display-gdb-buffer ()
1637 "Display GUD buffer."
1597 (interactive) 1638 (interactive)
1598 (gdb-display-buffer 1639 (gdb-display-buffer
1599 (gdb-get-create-buffer 'gdba))) 1640 (gdb-get-create-buffer 'gdba)))
@@ -1601,6 +1642,7 @@ the source buffer."
1601(defvar gdb-main-file nil "Source file from which program execution begins.") 1642(defvar gdb-main-file nil "Source file from which program execution begins.")
1602 1643
1603(defun gdb-view-source-function () 1644(defun gdb-view-source-function ()
1645 "Select source view."
1604 (interactive) 1646 (interactive)
1605 (if gdb-view-source 1647 (if gdb-view-source
1606 (gdb-display-buffer 1648 (gdb-display-buffer
@@ -1610,8 +1652,10 @@ the source buffer."
1610 (setq gdb-selected-view 'source)) 1652 (setq gdb-selected-view 'source))
1611 1653
1612(defun gdb-view-assembler() 1654(defun gdb-view-assembler()
1655 "Select disassembly view."
1613 (interactive) 1656 (interactive)
1614 (gdb-display-buffer (gdb-get-create-buffer 'gdb-assembler-buffer)) 1657 (gdb-display-buffer (gdb-get-create-buffer 'gdb-assembler-buffer))
1658 (gdb-invalidate-assembler)
1615 (setq gdb-selected-view 'assembler)) 1659 (setq gdb-selected-view 'assembler))
1616 1660
1617;(defun gdb-view-both() 1661;(defun gdb-view-both()
@@ -1656,10 +1700,10 @@ the source buffer."
1656 (other-window 1)) 1700 (other-window 1))
1657 1701
1658(defcustom gdb-many-windows nil 1702(defcustom gdb-many-windows nil
1659 "Nil (the default value) means just pops up the GUD buffer 1703 "Nil (the default value) means just pop up the GUD buffer
1660unless `gdb-show-main' is t. In this case it starts with two 1704unless `gdb-show-main' is t. In this case it starts with two
1661windows: one displaying the GUD buffer and the other with the 1705windows: one displaying the GUD buffer and the other with the
1662source file with the main routine of the debugee. Non-nil means 1706source file with the main routine of the inferior. Non-nil means
1663display the layout shown for `gdba'." 1707display the layout shown for `gdba'."
1664 :type 'boolean 1708 :type 'boolean
1665 :group 'gud) 1709 :group 'gud)
@@ -1701,15 +1745,15 @@ This arrangement depends on the value of `gdb-many-windows'."
1701 "Exit a debugging session cleanly by killing the gdb buffers and resetting 1745 "Exit a debugging session cleanly by killing the gdb buffers and resetting
1702 the source buffers." 1746 the source buffers."
1703 (dolist (buffer (buffer-list)) 1747 (dolist (buffer (buffer-list))
1704 (if (not (eq buffer gud-comint-buffer)) 1748 (unless (eq buffer gud-comint-buffer)
1705 (with-current-buffer buffer 1749 (with-current-buffer buffer
1706 (if (memq gud-minor-mode '(gdba pdb)) 1750 (if (memq gud-minor-mode '(gdbmi gdba))
1707 (if (string-match "^\*.+*$" (buffer-name)) 1751 (if (string-match "\\`\\*.+\\*\\'" (buffer-name))
1708 (kill-buffer nil) 1752 (kill-buffer nil)
1709 (gdb-remove-breakpoint-icons (point-min) (point-max) t) 1753 (gdb-remove-breakpoint-icons (point-min) (point-max) t)
1710 (setq gud-minor-mode nil) 1754 (setq gud-minor-mode nil)
1711 (kill-local-variable 'tool-bar-map) 1755 (kill-local-variable 'tool-bar-map)
1712 (setq gud-running nil)))))) 1756 (setq gud-running nil))))))
1713 (when (markerp gdb-overlay-arrow-position) 1757 (when (markerp gdb-overlay-arrow-position)
1714 (move-marker gdb-overlay-arrow-position nil) 1758 (move-marker gdb-overlay-arrow-position nil)
1715 (setq gdb-overlay-arrow-position nil)) 1759 (setq gdb-overlay-arrow-position nil))
@@ -1791,11 +1835,10 @@ BUFFER nil or omitted means use the current buffer."
1791 (when (< left-margin-width 2) 1835 (when (< left-margin-width 2)
1792 (save-current-buffer 1836 (save-current-buffer
1793 (setq left-margin-width 2) 1837 (setq left-margin-width 2)
1794 (if (get-buffer-window (current-buffer)) 1838 (if (get-buffer-window (current-buffer) 'visible)
1795 (set-window-margins (get-buffer-window 1839 (set-window-margins
1796 (current-buffer)) 1840 (get-buffer-window (current-buffer) 'visible)
1797 left-margin-width 1841 left-margin-width right-margin-width))))
1798 right-margin-width))))
1799 (put-image 1842 (put-image
1800 (if enabled 1843 (if enabled
1801 (or breakpoint-enabled-icon 1844 (or breakpoint-enabled-icon
@@ -1819,11 +1862,10 @@ BUFFER nil or omitted means use the current buffer."
1819 (when (< left-margin-width 2) 1862 (when (< left-margin-width 2)
1820 (save-current-buffer 1863 (save-current-buffer
1821 (setq left-margin-width 2) 1864 (setq left-margin-width 2)
1822 (if (get-buffer-window (current-buffer)) 1865 (if (get-buffer-window (current-buffer) 'visible)
1823 (set-window-margins (get-buffer-window 1866 (set-window-margins
1824 (current-buffer)) 1867 (get-buffer-window (current-buffer) 'visible)
1825 left-margin-width 1868 left-margin-width right-margin-width))))
1826 right-margin-width))))
1827 (gdb-put-string (if enabled "B" "b") (1+ start))))) 1869 (gdb-put-string (if enabled "B" "b") (1+ start)))))
1828 1870
1829(defun gdb-remove-breakpoint-icons (start end &optional remove-margin) 1871(defun gdb-remove-breakpoint-icons (start end &optional remove-margin)
@@ -1832,11 +1874,10 @@ BUFFER nil or omitted means use the current buffer."
1832 (remove-images start end)) 1874 (remove-images start end))
1833 (when remove-margin 1875 (when remove-margin
1834 (setq left-margin-width 0) 1876 (setq left-margin-width 0)
1835 (if (get-buffer-window (current-buffer)) 1877 (if (get-buffer-window (current-buffer) 'visible)
1836 (set-window-margins (get-buffer-window 1878 (set-window-margins
1837 (current-buffer)) 1879 (get-buffer-window (current-buffer) 'visible)
1838 left-margin-width 1880 left-margin-width right-margin-width))))
1839 right-margin-width))))
1840 1881
1841 1882
1842;; 1883;;
@@ -1848,7 +1889,7 @@ BUFFER nil or omitted means use the current buffer."
1848 1889
1849(def-gdb-auto-updated-buffer gdb-assembler-buffer 1890(def-gdb-auto-updated-buffer gdb-assembler-buffer
1850 gdb-invalidate-assembler 1891 gdb-invalidate-assembler
1851 (concat "server disassemble " gdb-current-address "\n") 1892 (concat gdb-server-prefix "disassemble " gdb-current-address "\n")
1852 gdb-assembler-handler 1893 gdb-assembler-handler
1853 gdb-assembler-custom) 1894 gdb-assembler-custom)
1854 1895
@@ -1887,7 +1928,7 @@ BUFFER nil or omitted means use the current buffer."
1887 (if (re-search-forward address nil t) 1928 (if (re-search-forward address nil t)
1888 (gdb-put-breakpoint-icon (eq flag ?y)))))))) 1929 (gdb-put-breakpoint-icon (eq flag ?y))))))))
1889 (if (not (equal gdb-current-address "main")) 1930 (if (not (equal gdb-current-address "main"))
1890 (set-window-point (get-buffer-window buffer) pos)))) 1931 (set-window-point (get-buffer-window buffer 'visible) pos))))
1891 1932
1892(defvar gdb-assembler-mode-map 1933(defvar gdb-assembler-mode-map
1893 (let ((map (make-sparse-keymap))) 1934 (let ((map (make-sparse-keymap)))
@@ -1913,14 +1954,17 @@ BUFFER nil or omitted means use the current buffer."
1913 (concat "*Machine Code " (gdb-get-target-string) "*"))) 1954 (concat "*Machine Code " (gdb-get-target-string) "*")))
1914 1955
1915(defun gdb-display-assembler-buffer () 1956(defun gdb-display-assembler-buffer ()
1957 "Display disassembly view."
1916 (interactive) 1958 (interactive)
1917 (gdb-display-buffer 1959 (gdb-display-buffer
1918 (gdb-get-create-buffer 'gdb-assembler-buffer))) 1960 (gdb-get-create-buffer 'gdb-assembler-buffer)))
1919 1961
1920(defun gdb-frame-assembler-buffer () 1962(defun gdb-frame-assembler-buffer ()
1963 "Display disassembly view in a new frame."
1921 (interactive) 1964 (interactive)
1922 (switch-to-buffer-other-frame 1965 (select-frame (make-frame gdb-frame-parameters))
1923 (gdb-get-create-buffer 'gdb-assembler-buffer))) 1966 (switch-to-buffer (gdb-get-create-buffer 'gdb-assembler-buffer))
1967 (set-window-dedicated-p (selected-window) t))
1924 1968
1925;; modified because if gdb-current-address has changed value a new command 1969;; modified because if gdb-current-address has changed value a new command
1926;; must be enqueued to update the buffer with the new output 1970;; must be enqueued to update the buffer with the new output
@@ -1929,44 +1973,44 @@ BUFFER nil or omitted means use the current buffer."
1929 (progn 1973 (progn
1930 (unless (string-equal gdb-current-frame gdb-previous-frame) 1974 (unless (string-equal gdb-current-frame gdb-previous-frame)
1931 (if (or (not (member 'gdb-invalidate-assembler 1975 (if (or (not (member 'gdb-invalidate-assembler
1932 (gdb-get-pending-triggers))) 1976 gdb-pending-triggers))
1933 (not (string-equal gdb-current-address 1977 (not (string-equal gdb-current-address
1934 gdb-previous-address))) 1978 gdb-previous-address)))
1935 (progn 1979 (progn
1936 ;; take previous disassemble command off the queue 1980 ;; take previous disassemble command off the queue
1937 (with-current-buffer gud-comint-buffer 1981 (with-current-buffer gud-comint-buffer
1938 (let ((queue (gdb-get-input-queue)) (item)) 1982 (let ((queue gdb-input-queue) (item))
1939 (dolist (item queue) 1983 (dolist (item queue)
1940 (if (equal (cdr item) '(gdb-assembler-handler)) 1984 (if (equal (cdr item) '(gdb-assembler-handler))
1941 (gdb-set-input-queue 1985 (setq gdb-input-queue
1942 (delete item (gdb-get-input-queue))))))) 1986 (delete item gdb-input-queue))))))
1943 (gdb-enqueue-input 1987 (gdb-enqueue-input
1944 (list (concat "server disassemble " gdb-current-address "\n") 1988 (list (concat gdb-server-prefix "disassemble " gdb-current-address "\n")
1945 'gdb-assembler-handler)) 1989 'gdb-assembler-handler))
1946 (gdb-set-pending-triggers 1990 (push 'gdb-invalidate-assembler gdb-pending-triggers)
1947 (cons 'gdb-invalidate-assembler
1948 (gdb-get-pending-triggers)))
1949 (setq gdb-previous-address gdb-current-address) 1991 (setq gdb-previous-address gdb-current-address)
1950 (setq gdb-previous-frame gdb-current-frame))))))) 1992 (setq gdb-previous-frame gdb-current-frame)))))))
1951 1993
1952(defun gdb-get-current-frame () 1994(defun gdb-get-current-frame ()
1953 (if (not (member 'gdb-get-current-frame (gdb-get-pending-triggers))) 1995 (if (not (member 'gdb-get-current-frame gdb-pending-triggers))
1954 (progn 1996 (progn
1955 (gdb-enqueue-input 1997 (gdb-enqueue-input
1956 (list (concat "server info frame\n") 'gdb-frame-handler)) 1998 (list (concat gdb-server-prefix "info frame\n") 'gdb-frame-handler))
1957 (gdb-set-pending-triggers 1999 (push 'gdb-get-current-frame
1958 (cons 'gdb-get-current-frame 2000 gdb-pending-triggers))))
1959 (gdb-get-pending-triggers))))))
1960 2001
1961(defun gdb-frame-handler () 2002(defun gdb-frame-handler ()
1962 (gdb-set-pending-triggers 2003 (setq gdb-pending-triggers
1963 (delq 'gdb-get-current-frame (gdb-get-pending-triggers))) 2004 (delq 'gdb-get-current-frame gdb-pending-triggers))
1964 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 2005 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
1965 (goto-char (point-min)) 2006 (goto-char (point-min))
1966 (forward-line) 2007 (forward-line)
1967 (if (looking-at ".*=\\s-+0x\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*\\)") 2008 (if (looking-at ".*=\\s-+0x\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? ")
1968 (progn 2009 (progn
1969 (setq gdb-current-frame (match-string 2)) 2010 (setq gdb-current-frame (match-string 2))
2011 (if (gdb-get-buffer 'gdb-locals-buffer)
2012 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
2013 (setq mode-name (concat "Locals:" gdb-current-frame))))
1970 (let ((address (match-string 1))) 2014 (let ((address (match-string 1)))
1971 ;; remove leading 0s from output of info frame command. 2015 ;; remove leading 0s from output of info frame command.
1972 (if (string-match "^0+\\(.*\\)" address) 2016 (if (string-match "^0+\\(.*\\)" address)
@@ -1986,5 +2030,5 @@ BUFFER nil or omitted means use the current buffer."
1986 2030
1987(provide 'gdb-ui) 2031(provide 'gdb-ui)
1988 2032
1989;;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352 2033;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352
1990;;; gdb-ui.el ends here 2034;;; gdb-ui.el ends here
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 94937ba1e87..aa9a50a2580 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -216,7 +216,7 @@ Notice that using \\[next-error] or \\[compile-goto-error] modifies
216`complation-last-buffer' rather than `grep-last-buffer'.") 216`complation-last-buffer' rather than `grep-last-buffer'.")
217 217
218(defvar grep-regexp-alist 218(defvar grep-regexp-alist
219 '(("^\\(.+?\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2) 219 '(("^\\(.+?\\)[:( \t]+\\([0-9]+\\)\\([:) \t]\\)\\(?:\\([0-9]+\\)\\(?:-\\([0-9]+\\)\\)?\\3\\)?" 1 2 (4 . 5))
220 ("^Binary file \\(.+\\) matches$" 1 nil nil 1)) 220 ("^Binary file \\(.+\\) matches$" 1 nil nil 1))
221 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") 221 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.")
222 222
@@ -555,7 +555,7 @@ those sub directories of DIR."
555 nil) ;; we change default-directory to dir 555 nil) ;; we change default-directory to dir
556 (and grep-tree-ignore-CVS-directories "-path '*/CVS' -prune -o ") 556 (and grep-tree-ignore-CVS-directories "-path '*/CVS' -prune -o ")
557 grep-tree-ignore-case)) 557 grep-tree-ignore-case))
558 (default-directory dir) 558 (default-directory (file-name-as-directory (expand-file-name dir)))
559 (null-device nil)) ; see grep 559 (null-device nil)) ; see grep
560 (grep command-args regexp))) 560 (grep command-args regexp)))
561 561
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index a34b0bb2d48..4ea4fcb6ea2 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -4,7 +4,7 @@
4;; Maintainer: FSF 4;; Maintainer: FSF
5;; Keywords: unix, tools 5;; Keywords: unix, tools
6 6
7;; Copyright (C) 1992,93,94,95,96,1998,2000,02,2003 Free Software Foundation, Inc. 7;; Copyright (C) 1992,93,94,95,96,1998,2000,02,03,04 Free Software Foundation, Inc.
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
@@ -92,44 +92,44 @@ If SOFT is non-nil, returns nil if the symbol doesn't already exist."
92Used to grey out relevant toolbar icons.") 92Used to grey out relevant toolbar icons.")
93 93
94(easy-mmode-defmap gud-menu-map 94(easy-mmode-defmap gud-menu-map
95 '(([refresh] "Refresh" . gud-refresh) 95 '(([help] menu-item "Help" gdb-goto-info
96 :enable (memq gud-minor-mode '(gdbmi gdba)))
97 ([refresh] "Refresh" . gud-refresh)
96 ([run] menu-item "Run" gud-run 98 ([run] menu-item "Run" gud-run
97 :enable (and (not gud-running) 99 :enable (and (not gud-running)
98 (memq gud-minor-mode '(gdba gdb dbx jdb)))) 100 (memq gud-minor-mode '(gdbmi gdba gdb dbx jdb))))
99 ([until] menu-item "Continue to selection" gud-until 101 ([until] menu-item "Continue to selection" gud-until
100 :enable (and (not gud-running) 102 :enable (and (not gud-running)
101 (memq gud-minor-mode '(gdba gdb perldb)))) 103 (memq gud-minor-mode '(gdbmi gdba gdb perldb))))
102 ([remove] menu-item "Remove Breakpoint" gud-remove 104 ([remove] menu-item "Remove Breakpoint" gud-remove
103 :enable (not gud-running)) 105 :enable (not gud-running))
104 ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak 106 ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak
105 :enable (memq gud-minor-mode '(gdba gdb sdb xdb bashdb))) 107 :enable (memq gud-minor-mode '(gdbmi gdba gdb sdb xdb bashdb)))
106 ([break] menu-item "Set Breakpoint" gud-break 108 ([break] menu-item "Set Breakpoint" gud-break
107 :enable (not gud-running)) 109 :enable (not gud-running))
108 ([up] menu-item "Up Stack" gud-up 110 ([up] menu-item "Up Stack" gud-up
109 :enable (and (not gud-running) 111 :enable (and (not gud-running)
110 (memq gud-minor-mode 112 (memq gud-minor-mode
111 '(gdba gdb dbx xdb jdb pdb bashdb)))) 113 '(gdbmi gdba gdb dbx xdb jdb pdb bashdb))))
112 ([down] menu-item "Down Stack" gud-down 114 ([down] menu-item "Down Stack" gud-down
113 :enable (and (not gud-running) 115 :enable (and (not gud-running)
114 (memq gud-minor-mode 116 (memq gud-minor-mode
115 '(gdba gdb dbx xdb jdb pdb bashdb)))) 117 '(gdbmi gdba gdb dbx xdb jdb pdb bashdb))))
116 ([print] menu-item "Print Expression" gud-print 118 ([print] menu-item "Print Expression" gud-print
117 :enable (not gud-running)) 119 :enable (not gud-running))
118 ([watch] menu-item "Watch Expression" gud-watch 120 ([watch] menu-item "Watch Expression" gud-watch
119 :enable (and (not gud-running) 121 :enable (and (not gud-running)
120 (eq gud-minor-mode 'gdba))) 122 (memq gud-minor-mode '(gdbmi gdba))))
121 ([finish] menu-item "Finish Function" gud-finish 123 ([finish] menu-item "Finish Function" gud-finish
122 :enable (and (not gud-running) 124 :enable (and (not gud-running)
123 (memq gud-minor-mode 125 (memq gud-minor-mode
124 '(gdba gdb xdb jdb pdb bashdb)))) 126 '(gdbmi gdba gdb xdb jdb pdb bashdb))))
125 ([stepi] menu-item "Step Instruction" gud-stepi 127 ([stepi] menu-item "Step Instruction" gud-stepi
126 :enable (and (not gud-running) 128 :enable (and (not gud-running)
127 (memq gud-minor-mode 129 (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
128 '(gdba gdb dbx))))
129 ([nexti] menu-item "Next Instruction" gud-nexti 130 ([nexti] menu-item "Next Instruction" gud-nexti
130 :enable (and (not gud-running) 131 :enable (and (not gud-running)
131 (memq gud-minor-mode 132 (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
132 '(gdba gdb dbx))))
133 ([step] menu-item "Step Line" gud-step 133 ([step] menu-item "Step Line" gud-step
134 :enable (not gud-running)) 134 :enable (not gud-running))
135 ([next] menu-item "Next Line" gud-next 135 ([next] menu-item "Next Line" gud-next
@@ -171,7 +171,8 @@ Used to grey out relevant toolbar icons.")
171 (gud-stepi . "gud-si") 171 (gud-stepi . "gud-si")
172 (gud-nexti . "gud-ni") 172 (gud-nexti . "gud-ni")
173 (gud-up . "gud-up") 173 (gud-up . "gud-up")
174 (gud-down . "gud-down")) 174 (gud-down . "gud-down")
175 (gdb-goto-info . "help"))
175 map) 176 map)
176 (tool-bar-local-item-from-menu 177 (tool-bar-local-item-from-menu
177 (car x) (cdr x) map gud-minor-mode-map))))) 178 (car x) (cdr x) map gud-minor-mode-map)))))
@@ -312,11 +313,14 @@ t means that there is no stack, and we are in display-file mode.")
312(defvar gud-speedbar-menu-items 313(defvar gud-speedbar-menu-items
313 ;; Note to self. Add expand, and turn off items when not available. 314 ;; Note to self. Add expand, and turn off items when not available.
314 '(["Jump to stack frame" speedbar-edit-line 315 '(["Jump to stack frame" speedbar-edit-line
315 (with-current-buffer gud-comint-buffer (not (eq gud-minor-mode 'gdba)))] 316 (with-current-buffer gud-comint-buffer
317 (not (memq gud-minor-mode '(gdbmi gdba))))]
316 ["Edit value" speedbar-edit-line 318 ["Edit value" speedbar-edit-line
317 (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))] 319 (with-current-buffer gud-comint-buffer
320 (not (memq gud-minor-mode '(gdbmi gdba))))]
318 ["Delete expression" gdb-var-delete 321 ["Delete expression" gdb-var-delete
319 (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))]) 322 (with-current-buffer gud-comint-buffer
323 (not (memq gud-minor-mode '(gdbmi gdba))))])
320 "Additional menu items to add to the speedbar frame.") 324 "Additional menu items to add to the speedbar frame.")
321 325
322;; Make sure our special speedbar mode is loaded 326;; Make sure our special speedbar mode is loaded
@@ -330,7 +334,7 @@ If the GUD BUFFER is not running a supported debugger, then turn
330off the specialized speedbar mode." 334off the specialized speedbar mode."
331 (let ((minor-mode (with-current-buffer buffer gud-minor-mode))) 335 (let ((minor-mode (with-current-buffer buffer gud-minor-mode)))
332 (cond 336 (cond
333 ((eq minor-mode 'gdba) 337 ((memq minor-mode '(gdbmi gdba))
334 (when (or gdb-var-changed 338 (when (or gdb-var-changed
335 (not (save-excursion 339 (not (save-excursion
336 (goto-char (point-min)) 340 (goto-char (point-min))
@@ -397,7 +401,7 @@ off the specialized speedbar mode."
397 (speedbar-insert-button (car frame) 401 (speedbar-insert-button (car frame)
398 'speedbar-file-face 402 'speedbar-file-face
399 'speedbar-highlight-face 403 'speedbar-highlight-face
400 (cond ((memq minor-mode '(gdba gdb)) 404 (cond ((memq minor-mode '(gdbmi gdba gdb))
401 'gud-gdb-goto-stackframe) 405 'gud-gdb-goto-stackframe)
402 (t (error "Should never be here"))) 406 (t (error "Should never be here")))
403 frame t))) 407 frame t)))
@@ -1401,7 +1405,7 @@ and source-file directory for your debugger."
1401 1405
1402 output)) 1406 output))
1403 1407
1404(defcustom gud-pdb-command-name "pdb" 1408(defcustom gud-pdb-command-name "pydb"
1405 "File name for executing the Python debugger. 1409 "File name for executing the Python debugger.
1406This should be an executable on your path, or an absolute file name." 1410This should be an executable on your path, or an absolute file name."
1407 :type 'string 1411 :type 'string
@@ -2339,7 +2343,8 @@ comint mode, which see."
2339 ;; Don't put repeated commands in command history many times. 2343 ;; Don't put repeated commands in command history many times.
2340 (set (make-local-variable 'comint-input-ignoredups) t) 2344 (set (make-local-variable 'comint-input-ignoredups) t)
2341 (make-local-variable 'paragraph-start) 2345 (make-local-variable 'paragraph-start)
2342 (set (make-local-variable 'gud-delete-prompt-marker) (make-marker))) 2346 (set (make-local-variable 'gud-delete-prompt-marker) (make-marker))
2347 (add-hook 'kill-buffer-hook 'gud-kill-buffer-hook nil t))
2343 2348
2344;; Cause our buffers to be displayed, by default, 2349;; Cause our buffers to be displayed, by default,
2345;; in the selected window. 2350;; in the selected window.
@@ -2384,8 +2389,11 @@ comint mode, which see."
2384 (if (file-name-directory file-subst) 2389 (if (file-name-directory file-subst)
2385 (expand-file-name file-subst) 2390 (expand-file-name file-subst)
2386 file-subst))) 2391 file-subst)))
2387 (filepart (and file-word (concat "-" (file-name-nondirectory file))))) 2392 (filepart (and file-word (concat "-" (file-name-nondirectory file))))
2393 (existing-buffer (get-buffer (concat "*gud" filepart "*"))))
2388 (pop-to-buffer (concat "*gud" filepart "*")) 2394 (pop-to-buffer (concat "*gud" filepart "*"))
2395 (when (and existing-buffer (get-buffer-process existing-buffer))
2396 (error "This program is already running under gdb"))
2389 ;; Set the dir, in case the buffer already existed with a different dir. 2397 ;; Set the dir, in case the buffer already existed with a different dir.
2390 (setq default-directory dir) 2398 (setq default-directory dir)
2391 ;; Set default-directory to the file's directory. 2399 ;; Set default-directory to the file's directory.
@@ -2507,14 +2515,14 @@ It is saved for when this flag is not set.")
2507 ;; Stop displaying an arrow in a source file. 2515 ;; Stop displaying an arrow in a source file.
2508 (setq overlay-arrow-position nil) 2516 (setq overlay-arrow-position nil)
2509 (set-process-buffer proc nil) 2517 (set-process-buffer proc nil)
2510 (if (eq gud-minor-mode-type 'gdba) 2518 (if (memq gud-minor-mode-type '(gdbmi gdba))
2511 (gdb-reset) 2519 (gdb-reset)
2512 (gud-reset))) 2520 (gud-reset)))
2513 ((memq (process-status proc) '(signal exit)) 2521 ((memq (process-status proc) '(signal exit))
2514 ;; Stop displaying an arrow in a source file. 2522 ;; Stop displaying an arrow in a source file.
2515 (setq overlay-arrow-position nil) 2523 (setq overlay-arrow-position nil)
2516 (with-current-buffer gud-comint-buffer 2524 (with-current-buffer gud-comint-buffer
2517 (if (eq gud-minor-mode 'gdba) 2525 (if (memq gud-minor-mode-type '(gdbmi gdba))
2518 (gdb-reset) 2526 (gdb-reset)
2519 (gud-reset))) 2527 (gud-reset)))
2520 (let* ((obuf (current-buffer))) 2528 (let* ((obuf (current-buffer)))
@@ -2543,19 +2551,18 @@ It is saved for when this flag is not set.")
2543 (set-buffer obuf)))))) 2551 (set-buffer obuf))))))
2544 2552
2545(defun gud-kill-buffer-hook () 2553(defun gud-kill-buffer-hook ()
2546 (if gud-minor-mode 2554 (setq gud-minor-mode-type gud-minor-mode)
2547 (setq gud-minor-mode-type gud-minor-mode))) 2555 (condition-case nil
2548 2556 (kill-process (get-buffer-process gud-comint-buffer))
2549(add-hook 'kill-buffer-hook 'gud-kill-buffer-hook) 2557 (error nil)))
2550 2558
2551(defun gud-reset () 2559(defun gud-reset ()
2552 (dolist (buffer (buffer-list)) 2560 (dolist (buffer (buffer-list))
2553 (if (not (eq buffer gud-comint-buffer)) 2561 (unless (eq buffer gud-comint-buffer)
2554 (save-excursion 2562 (with-current-buffer buffer
2555 (set-buffer buffer) 2563 (when gud-minor-mode
2556 (when gud-minor-mode 2564 (setq gud-minor-mode nil)
2557 (setq gud-minor-mode nil) 2565 (kill-local-variable 'tool-bar-map))))))
2558 (kill-local-variable 'tool-bar-map))))))
2559 2566
2560(defun gud-display-frame () 2567(defun gud-display-frame ()
2561 "Find and obey the last filename-and-line marker from the debugger. 2568 "Find and obey the last filename-and-line marker from the debugger.
@@ -2580,7 +2587,7 @@ Obeying it means displaying in another window the specified file and line."
2580 (with-current-buffer gud-comint-buffer 2587 (with-current-buffer gud-comint-buffer
2581 (gud-find-file true-file))) 2588 (gud-find-file true-file)))
2582 (window (and buffer (or (get-buffer-window buffer) 2589 (window (and buffer (or (get-buffer-window buffer)
2583 (if (eq gud-minor-mode 'gdba) 2590 (if (memq gud-minor-mode '(gdbmi gdba))
2584 (gdb-display-source-buffer buffer) 2591 (gdb-display-source-buffer buffer)
2585 (display-buffer buffer))))) 2592 (display-buffer buffer)))))
2586 (pos)) 2593 (pos))
@@ -2704,7 +2711,7 @@ Obeying it means displaying in another window the specified file and line."
2704 (forward-line 0) 2711 (forward-line 0)
2705 (if (looking-at comint-prompt-regexp) 2712 (if (looking-at comint-prompt-regexp)
2706 (set-marker gud-delete-prompt-marker (point))) 2713 (set-marker gud-delete-prompt-marker (point)))
2707 (if (eq gud-minor-mode 'gdba) 2714 (if (memq gud-minor-mode '(gdbmi gdba))
2708 (apply comint-input-sender (list proc command)) 2715 (apply comint-input-sender (list proc command))
2709 (process-send-string proc (concat command "\n"))))))) 2716 (process-send-string proc (concat command "\n")))))))
2710 2717
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index a600939ef71..ae0c43c2730 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -1823,8 +1823,8 @@ Change the default directory for the process buffer to concur."
1823 'hide 'wait) 1823 'hide 'wait)
1824 ;; If we don't know anything about the class, update shell routines 1824 ;; If we don't know anything about the class, update shell routines
1825 (if (and idlwave-shell-get-object-class 1825 (if (and idlwave-shell-get-object-class
1826 (not (assoc-ignore-case idlwave-shell-get-object-class 1826 (not (assoc-string idlwave-shell-get-object-class
1827 (idlwave-class-alist)))) 1827 (idlwave-class-alist) t)))
1828 (idlwave-shell-maybe-update-routine-info)) 1828 (idlwave-shell-maybe-update-routine-info))
1829 idlwave-shell-get-object-class))) 1829 idlwave-shell-get-object-class)))
1830 1830
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index bfa507b851a..274480a36de 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3,6 +3,7 @@
3;; Copyright (C) 2003, 04 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 04 Free Software Foundation, Inc.
4 4
5;; Author: Dave Love <fx@gnu.org> 5;; Author: Dave Love <fx@gnu.org>
6;; Maintainer: FSF
6;; Created: Nov 2003 7;; Created: Nov 2003
7;; Keywords: languages 8;; Keywords: languages
8 9
@@ -45,19 +46,18 @@
45;; I've installed a minor mode to do the job properly in Emacs 22. 46;; I've installed a minor mode to do the job properly in Emacs 22.
46;; Other things seem more natural or canonical here, e.g. the 47;; Other things seem more natural or canonical here, e.g. the
47;; {beginning,end}-of-defun implementation dealing with nested 48;; {beginning,end}-of-defun implementation dealing with nested
48;; definitions, and the inferior mode following `cmuscheme'. (The 49;; definitions, and the inferior mode following `cmuscheme'. The
49;; inferior mode should be able to find the source of errors from 50;; inferior mode can find the source of errors from
50;; `python-send-region' & al via `compilation-minor-mode', but I can't 51;; `python-send-region' & al via `compilation-minor-mode'. Successive
51;; make that work with the current (March '04) compile.el.) 52;; TABs cycle between possible indentations for the line. There is
52;; Successive TABs cycle between possible indentations for the line. 53;; symbol completion using lookup in Python.
53 54
54;; Even where it has similar facilities, this is incompatible with 55;; Even where it has similar facilities, this is incompatible with
55;; python-mode.el in various respects. For instance, various key 56;; python-mode.el in various respects. For instance, various key
56;; bindings are changed to obey Emacs conventions, and things like 57;; bindings are changed to obey Emacs conventions, and things like
57;; marking blocks and `beginning-of-defun' behave differently. 58;; marking blocks and `beginning-of-defun' behave differently.
58 59
59;; TODO: See various Fixmes below. It should be possible to arrange 60;; TODO: See various Fixmes below.
60;; some sort of completion using the inferior interpreter.
61 61
62;;; Code: 62;;; Code:
63 63
@@ -66,10 +66,8 @@
66(require 'comint) 66(require 'comint)
67(eval-when-compile 67(eval-when-compile
68 (require 'compile) 68 (require 'compile)
69 (autoload 'Info-last "info")
70 (autoload 'Info-exit "info")
71 (autoload 'info-lookup-maybe-add-help "info-look")) 69 (autoload 'info-lookup-maybe-add-help "info-look"))
72(autoload 'compilation-start "compile") ; spurious compiler warning anyway 70(autoload 'compilation-start "compile")
73 71
74(defgroup python nil 72(defgroup python nil
75 "Silly walks in the Python language" 73 "Silly walks in the Python language"
@@ -204,6 +202,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
204 (define-key map "\C-c\C-z" 'python-switch-to-python) 202 (define-key map "\C-c\C-z" 'python-switch-to-python)
205 (define-key map "\C-c\C-m" 'python-load-file) 203 (define-key map "\C-c\C-m" 'python-load-file)
206 (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme 204 (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme
205 (substitute-key-definition 'complete-symbol 'python-complete-symbol
206 map global-map)
207 ;; Fixme: Add :help to menu. 207 ;; Fixme: Add :help to menu.
208 (easy-menu-define python-menu map "Python Mode menu" 208 (easy-menu-define python-menu map "Python Mode menu"
209 '("Python" 209 '("Python"
@@ -262,9 +262,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
262;;;; Utility stuff 262;;;; Utility stuff
263 263
264(defsubst python-in-string/comment () 264(defsubst python-in-string/comment ()
265 "Return non-nil if point is in a Python literal (a comment or string). 265 "Return non-nil if point is in a Python literal (a comment or string)."
266Optional argument LIM indicates the beginning of the containing form,
267i.e. the limit on how far back to scan."
268 (syntax-ppss-context (syntax-ppss))) 266 (syntax-ppss-context (syntax-ppss)))
269 267
270(defconst python-space-backslash-table 268(defconst python-space-backslash-table
@@ -299,16 +297,18 @@ comments and strings, or that the bracket/paren nesting depth is nonzero."
299 (syntax-ppss (line-beginning-position))))))) 297 (syntax-ppss (line-beginning-position)))))))
300 298
301(defun python-comment-line-p () 299(defun python-comment-line-p ()
302 "Return non-nil if current line has only a comment or is blank." 300 "Return non-nil iff current line has only a comment."
303 (save-excursion 301 (save-excursion
304 (back-to-indentation) 302 (end-of-line)
305 (looking-at (rx (or (syntax comment-start) line-end))))) 303 (when (eq 'comment (syntax-ppss-context (syntax-ppss)))
304 (back-to-indentation)
305 (looking-at (rx (or (syntax comment-start) line-end))))))
306 306
307(defun python-beginning-of-string () 307(defun python-beginning-of-string ()
308 "Go to beginning of string around point. 308 "Go to beginning of string around point.
309Do nothing if not in string." 309Do nothing if not in string."
310 (let ((state (syntax-ppss))) 310 (let ((state (syntax-ppss)))
311 (when (nth 3 state) 311 (when (eq 'string (syntax-ppss-context state))
312 (goto-char (nth 8 state))))) 312 (goto-char (nth 8 state)))))
313 313
314(defun python-open-block-statement-p (&optional bos) 314(defun python-open-block-statement-p (&optional bos)
@@ -323,7 +323,8 @@ BOS non-nil means point is known to be at beginning of statement."
323 line-end)) 323 line-end))
324 (save-excursion (python-end-of-statement)) 324 (save-excursion (python-end-of-statement))
325 t) 325 t)
326 (not (python-in-string/comment))))) 326 (not (progn (goto-char (match-beginning 0))
327 (python-in-string/comment))))))
327 328
328(defun python-close-block-statement-p (&optional bos) 329(defun python-close-block-statement-p (&optional bos)
329 "Return non-nil if current line is a statement closing a block. 330 "Return non-nil if current line is a statement closing a block.
@@ -384,7 +385,8 @@ Otherwise indent them to column zero."
384(defcustom python-honour-comment-indentation nil 385(defcustom python-honour-comment-indentation nil
385 "Non-nil means indent relative to preceding comment line. 386 "Non-nil means indent relative to preceding comment line.
386Only do this for comments where the leading comment character is followed 387Only do this for comments where the leading comment character is followed
387by space." 388by space. This doesn't apply to comment lines, which are always indented
389in lines with preceding comments."
388 :type 'boolean 390 :type 'boolean
389 :group 'python) 391 :group 'python)
390 392
@@ -514,6 +516,16 @@ Set `python-indent' locally to the value guessed."
514 (- python-indent))) 516 (- python-indent)))
515 0))))))))) 517 0)))))))))
516 518
519(defun python-comment-indent ()
520 "`comment-indent-function' for Python."
521 ;; If previous non-blank line was a comment, use its indentation.
522 ;; FIXME: This seems unnecessary since the default code delegates to
523 ;; indent-according-to-mode. --Stef
524 (unless (bobp)
525 (save-excursion
526 (forward-comment -1)
527 (if (eq ?# (char-after)) (current-column)))))
528
517;;;; Cycling through the possible indentations with successive TABs. 529;;;; Cycling through the possible indentations with successive TABs.
518 530
519;; These don't need to be buffer-local since they're only relevant 531;; These don't need to be buffer-local since they're only relevant
@@ -538,11 +550,17 @@ Set `python-indent' locally to the value guessed."
538 (point)))) 550 (point))))
539 551
540(defun python-indentation-levels () 552(defun python-indentation-levels ()
541 "Return a list of possible indentations for this statement. 553 "Return a list of possible indentations for this line.
542Includes the default indentation and those which would close all 554Includes the default indentation and those which would close all
543enclosing blocks." 555enclosing blocks. Assumes the line has already been indented per
556`python-indent-line'. Elements of the list are actually pairs:
557\(INDENTATION . TEXT), where TEXT is the initial text of the
558corresponding block opening (or nil)."
544 (save-excursion 559 (save-excursion
545 (let ((levels (list (cons (current-indentation) nil)))) 560 (let ((levels (list (cons (current-indentation)
561 (save-excursion
562 (if (python-beginning-of-block)
563 (python-initial-text)))))))
546 ;; Only one possibility if we immediately follow a block open or 564 ;; Only one possibility if we immediately follow a block open or
547 ;; are in a continuation line. 565 ;; are in a continuation line.
548 (unless (or (python-continuation-line-p) 566 (unless (or (python-continuation-line-p)
@@ -568,8 +586,7 @@ enclosing blocks."
568 (if (> (- (point-max) pos) (point)) 586 (if (> (- (point-max) pos) (point))
569 (goto-char (- (point-max) pos)))))) 587 (goto-char (- (point-max) pos))))))
570 588
571;; Fixme: Is the arg necessary? 589(defun python-indent-line ()
572(defun python-indent-line (&optional arg)
573 "Indent current line as Python code. 590 "Indent current line as Python code.
574When invoked via `indent-for-tab-command', cycle through possible 591When invoked via `indent-for-tab-command', cycle through possible
575indentations for current line. The cycle is broken by a command different 592indentations for current line. The cycle is broken by a command different
@@ -586,13 +603,30 @@ from `indent-for-tab-command', i.e. successive TABs do the cycling."
586 (beginning-of-line) 603 (beginning-of-line)
587 (delete-horizontal-space) 604 (delete-horizontal-space)
588 (indent-to (car (nth python-indent-index python-indent-list))) 605 (indent-to (car (nth python-indent-index python-indent-list)))
589 (let ((text (cdr (nth python-indent-index 606 (if (python-block-end-p)
590 python-indent-list)))) 607 (let ((text (cdr (nth python-indent-index
591 (if text (message "Closes: %s" text))))) 608 python-indent-list))))
609 (if text
610 (message "Closes: %s" text))))))
592 (python-indent-line-1) 611 (python-indent-line-1)
593 (setq python-indent-list (python-indentation-levels) 612 (setq python-indent-list (python-indentation-levels)
594 python-indent-list-length (length python-indent-list) 613 python-indent-list-length (length python-indent-list)
595 python-indent-index (1- python-indent-list-length))))) 614 python-indent-index (1- python-indent-list-length)))))
615
616(defun python-block-end-p ()
617 "Non-nil if this is a line in a statement closing a block,
618or a blank line indented to where it would close a block."
619 (and (not (python-comment-line-p))
620 (or (python-close-block-statement-p t)
621 (< (current-indentation)
622 (save-excursion
623 (python-previous-statement)
624 (current-indentation))))))
625
626;; Fixme: Define an indent-region-function. It should probably leave
627;; lines alone if the indentation is already at one of the allowed
628;; levels. Otherwise, M-C-\ typically keeps indenting more deeply
629;; down a function.
596 630
597;;;; Movement. 631;;;; Movement.
598 632
@@ -629,8 +663,7 @@ start of buffer."
629 "`end-of-defun-function' for Python. 663 "`end-of-defun-function' for Python.
630Finds end of innermost nested class or method definition." 664Finds end of innermost nested class or method definition."
631 (let ((orig (point)) 665 (let ((orig (point))
632 (pattern (rx (and line-start (0+ space) 666 (pattern (rx (and line-start (0+ space) (or "def" "class") space))))
633 (or "def" "class") space))))
634 ;; Go to start of current block and check whether it's at top 667 ;; Go to start of current block and check whether it's at top
635 ;; level. If it is, and not a block start, look forward for 668 ;; level. If it is, and not a block start, look forward for
636 ;; definition statement. 669 ;; definition statement.
@@ -829,7 +862,8 @@ move and return nil. Otherwise return t."
829Makes nested Imenu menus from nested `class' and `def' statements. 862Makes nested Imenu menus from nested `class' and `def' statements.
830The nested menus are headed by an item referencing the outer 863The nested menus are headed by an item referencing the outer
831definition; it has a space prepended to the name so that it sorts 864definition; it has a space prepended to the name so that it sorts
832first with `imenu--sort-by-name'." 865first with `imenu--sort-by-name' (though, unfortunately, sub-menus
866precede it)."
833 (unless (boundp 'python-recursing) ; dynamically bound below 867 (unless (boundp 'python-recursing) ; dynamically bound below
834 (goto-char (point-min))) ; normal call from Imenu 868 (goto-char (point-min))) ; normal call from Imenu
835 (let (index-alist ; accumulated value to return 869 (let (index-alist ; accumulated value to return
@@ -914,13 +948,20 @@ See `python-check-command' for the default."
914 (file-name-nondirectory name)))))))) 948 (file-name-nondirectory name))))))))
915 (setq python-saved-check-command command) 949 (setq python-saved-check-command command)
916 (save-some-buffers (not compilation-ask-about-save) nil) 950 (save-some-buffers (not compilation-ask-about-save) nil)
917 (compilation-start command)) 951 (let ((compilation-error-regexp-alist
952 (cons '("(\\([^,]+\\), line \\([0-9]+\\))" 1 2)
953 compilation-error-regexp-alist)))
954 (compilation-start command)))
918 955
919;;;; Inferior mode stuff (following cmuscheme). 956;;;; Inferior mode stuff (following cmuscheme).
920 957
958;; Fixme: Make sure we can work with IPython.
959
921(defcustom python-python-command "python" 960(defcustom python-python-command "python"
922 "*Shell command to run Python interpreter. 961 "*Shell command to run Python interpreter.
923Any arguments can't contain whitespace." 962Any arguments can't contain whitespace.
963Note that IPython may not work properly; it must at least be used with the
964`-cl' flag, i.e. use `ipython -cl'."
924 :group 'python 965 :group 'python
925 :type 'string) 966 :type 'string)
926 967
@@ -937,40 +978,66 @@ Additional arguments are added when the command is used by `run-python'
937et al.") 978et al.")
938 979
939(defvar python-buffer nil 980(defvar python-buffer nil
940 "*The current python process buffer. 981 "The current python process buffer."
941To run multiple Python processes, start the first with \\[run-python]. 982 ;; Fixme: a single process is currently assumed, so that this doc
942It will be in a buffer named *Python*. Rename that with 983 ;; is misleading.
943\\[rename-buffer]. Now start a new process with \\[run-python]. It 984
944will be in a new buffer, named *Python*. Switch between the different 985;; "*The current python process buffer.
945process buffers with \\[switch-to-buffer]. 986;; To run multiple Python processes, start the first with \\[run-python].
946 987;; It will be in a buffer named *Python*. Rename that with
947Commands that send text from source buffers to Python processes have 988;; \\[rename-buffer]. Now start a new process with \\[run-python]. It
948to choose a process to send to. This is determined by global variable 989;; will be in a new buffer, named *Python*. Switch between the different
949`python-buffer'. Suppose you have three inferior Pythons running: 990;; process buffers with \\[switch-to-buffer].
950 Buffer Process 991
951 foo python 992;; Commands that send text from source buffers to Python processes have
952 bar python<2> 993;; to choose a process to send to. This is determined by global variable
953 *Python* python<3> 994;; `python-buffer'. Suppose you have three inferior Pythons running:
954If you do a \\[python-send-region-and-go] command on some Python source 995;; Buffer Process
955code, what process does it go to? 996;; foo python
956 997;; bar python<2>
957- In a process buffer (foo, bar, or *Python*), send it to that process. 998;; *Python* python<3>
958- In some other buffer (e.g. a source file), send it to the process 999;; If you do a \\[python-send-region-and-go] command on some Python source
959 attached to `python-buffer'. 1000;; code, what process does it go to?
960Process selection is done by function `python-proc'. 1001
961 1002;; - In a process buffer (foo, bar, or *Python*), send it to that process.
962Whenever \\[run-python] starts a new process, it resets `python-buffer' 1003;; - In some other buffer (e.g. a source file), send it to the process
963to be the new process's buffer. If you only run one process, this will 1004;; attached to `python-buffer'.
964do the right thing. If you run multiple processes, you can change 1005;; Process selection is done by function `python-proc'.
965`python-buffer' to another process buffer with \\[set-variable].") 1006
1007;; Whenever \\[run-python] starts a new process, it resets `python-buffer'
1008;; to be the new process's buffer. If you only run one process, this will
1009;; do the right thing. If you run multiple processes, you can change
1010;; `python-buffer' to another process buffer with \\[set-variable]."
1011 )
966 1012
967(defconst python-compilation-regexp-alist 1013(defconst python-compilation-regexp-alist
1014 ;; FIXME: maybe these should move to compilation-error-regexp-alist-alist.
968 `((,(rx (and line-start (1+ (any " \t")) "File \"" 1015 `((,(rx (and line-start (1+ (any " \t")) "File \""
969 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c 1016 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
970 "\", line " (group (1+ digit)))) 1017 "\", line " (group (1+ digit))))
971 1 python-compilation-line-number)) 1018 1 2)
1019 (,(rx (and " in file " (group (1+ not-newline)) " on line "
1020 (group (1+ digit))))
1021 1 2))
972 "`compilation-error-regexp-alist' for inferior Python.") 1022 "`compilation-error-regexp-alist' for inferior Python.")
973 1023
1024(defvar inferior-python-mode-map
1025 (let ((map (make-sparse-keymap)))
1026 ;; This will inherit from comint-mode-map.
1027 (define-key map "\C-c\C-l" 'python-load-file)
1028 (define-key map "\C-c\C-v" 'python-check)
1029 ;; Note that we _can_ still use these commands which send to the
1030 ;; Python process even at the prompt iff we have a normal prompt,
1031 ;; i.e. '>>> ' and not '... '. See the comment before
1032 ;; python-send-region. Fixme: uncomment these if we address that.
1033
1034 ;; (define-key map [(meta ?\t)] 'python-complete-symbol)
1035 ;; (define-key map "\C-c\C-f" 'python-describe-symbol)
1036 map))
1037
1038;; Fixme: This should inherit some stuff from python-mode, but I'm not
1039;; sure how much: at least some keybindings, like C-c C-f; syntax?;
1040;; font-locking, e.g. for triple-quoted strings?
974(define-derived-mode inferior-python-mode comint-mode "Inferior Python" 1041(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
975 "Major mode for interacting with an inferior Python process. 1042 "Major mode for interacting with an inferior Python process.
976A Python process can be started with \\[run-python]. 1043A Python process can be started with \\[run-python].
@@ -991,14 +1058,13 @@ For running multiple processes in multiple buffers, see `python-buffer'.
991 :group 'python 1058 :group 'python
992 (set-syntax-table python-mode-syntax-table) 1059 (set-syntax-table python-mode-syntax-table)
993 (setq mode-line-process '(":%s")) 1060 (setq mode-line-process '(":%s"))
994 ;; Fixme: Maybe install some python-mode bindings too. 1061 (set (make-local-variable 'comint-input-filter) 'python-input-filter)
995 (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file)
996 (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python)
997 (add-hook 'comint-input-filter-functions 'python-input-filter nil t)
998 (add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter 1062 (add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter
999 nil t) 1063 nil t)
1000 ;; Still required by `comint-redirect-send-command', for instance: 1064 ;; Still required by `comint-redirect-send-command', for instance
1001 (set (make-local-variable 'comint-prompt-regexp) "^\\([>.]\\{3\\} \\)+") 1065 ;; (and we need to match things like `>>> ... >>> '):
1066 (set (make-local-variable 'comint-prompt-regexp)
1067 (rx (and line-start (1+ (and (repeat 3 (any ">.")) ?\ )))))
1002 (set (make-local-variable 'compilation-error-regexp-alist) 1068 (set (make-local-variable 'compilation-error-regexp-alist)
1003 python-compilation-regexp-alist) 1069 python-compilation-regexp-alist)
1004 (compilation-shell-minor-mode 1)) 1070 (compilation-shell-minor-mode 1))
@@ -1009,15 +1075,9 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
1009 :type 'regexp 1075 :type 'regexp
1010 :group 'python) 1076 :group 'python)
1011 1077
1012(defvar python-orig-start nil
1013 "Marker to the start of the region passed to the inferior Python.
1014It can also be a filename.")
1015
1016(defun python-input-filter (str) 1078(defun python-input-filter (str)
1017 "`comint-input-filter' function for inferior Python. 1079 "`comint-input-filter' function for inferior Python.
1018Don't save anything for STR matching `inferior-python-filter-regexp'. 1080Don't save anything for STR matching `inferior-python-filter-regexp'."
1019Also resets variables for adjusting error messages."
1020 (setq python-orig-start nil)
1021 (not (string-match inferior-python-filter-regexp str))) 1081 (not (string-match inferior-python-filter-regexp str)))
1022 1082
1023;; Fixme: Loses with quoted whitespace. 1083;; Fixme: Loses with quoted whitespace.
@@ -1030,21 +1090,8 @@ Also resets variables for adjusting error messages."
1030 (t (let ((pos (string-match "[^ \t]" string))) 1090 (t (let ((pos (string-match "[^ \t]" string)))
1031 (if pos (python-args-to-list (substring string pos)))))))) 1091 (if pos (python-args-to-list (substring string pos))))))))
1032 1092
1033(defun python-compilation-line-number (file col)
1034 "Return error descriptor of error found for FILE, column COL.
1035Used as line-number hook function in `python-compilation-regexp-alist'."
1036 (let ((line (string-to-number (match-string 2))))
1037 (cons (point-marker)
1038 (if (and (markerp python-orig-start)
1039 (marker-buffer python-orig-start))
1040 (with-current-buffer (marker-buffer python-orig-start)
1041 (goto-char python-orig-start)
1042 (forward-line (1- line)))
1043 (list (if (stringp python-orig-start) python-orig-start file)
1044 line nil)))))
1045
1046(defvar python-preoutput-result nil 1093(defvar python-preoutput-result nil
1047 "Data from output line last `_emacs_out' line seen by the preoutput filter.") 1094 "Data from last `_emacs_out' line seen by the preoutput filter.")
1048 1095
1049(defvar python-preoutput-continuation nil 1096(defvar python-preoutput-continuation nil
1050 "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.") 1097 "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.")
@@ -1055,7 +1102,9 @@ Used as line-number hook function in `python-compilation-regexp-alist'."
1055;; `python-preoutput-continuation' if we get it. 1102;; `python-preoutput-continuation' if we get it.
1056(defun python-preoutput-filter (s) 1103(defun python-preoutput-filter (s)
1057 "`comint-preoutput-filter-functions' function: ignore prompts not at bol." 1104 "`comint-preoutput-filter-functions' function: ignore prompts not at bol."
1058 (cond ((and (string-match "\\`[.>]\\{3\\} \\'" s) 1105 (cond ((and (string-match (rx (and string-start (repeat 3 (any ".>"))
1106 " " string-end))
1107 s)
1059 (/= (let ((inhibit-field-text-motion t)) 1108 (/= (let ((inhibit-field-text-motion t))
1060 (line-beginning-position)) 1109 (line-beginning-position))
1061 (point))) 1110 (point)))
@@ -1076,10 +1125,10 @@ Used as line-number hook function in `python-compilation-regexp-alist'."
1076CMD is the Python command to run. NOSHOW non-nil means don't show the 1125CMD is the Python command to run. NOSHOW non-nil means don't show the
1077buffer automatically. 1126buffer automatically.
1078If there is a process already running in `*Python*', switch to 1127If there is a process already running in `*Python*', switch to
1079that buffer. Interactively a prefix arg, allows you to edit the initial 1128that buffer. Interactively, a prefix arg allows you to edit the initial
1080command line (default is the value of `python-command'); `-i' etc. args 1129command line (default is `python-command'); `-i' etc. args will be added
1081will be added to this as appropriate. Runs the hooks 1130to this as appropriate. Runs the hook `inferior-python-mode-hook'
1082`inferior-python-mode-hook' (after the `comint-mode-hook' is run). 1131\(after the `comint-mode-hook' is run).
1083\(Type \\[describe-mode] in the process buffer for a list of commands.)" 1132\(Type \\[describe-mode] in the process buffer for a list of commands.)"
1084 (interactive (list (if current-prefix-arg 1133 (interactive (list (if current-prefix-arg
1085 (read-string "Run Python: " python-command) 1134 (read-string "Run Python: " python-command)
@@ -1089,82 +1138,78 @@ will be added to this as appropriate. Runs the hooks
1089 ;; Fixme: Consider making `python-buffer' buffer-local as a buffer 1138 ;; Fixme: Consider making `python-buffer' buffer-local as a buffer
1090 ;; (not a name) in Python buffers from which `run-python' &c is 1139 ;; (not a name) in Python buffers from which `run-python' &c is
1091 ;; invoked. Would support multiple processes better. 1140 ;; invoked. Would support multiple processes better.
1092 (unless (comint-check-proc "*Python*") 1141 (unless (comint-check-proc python-buffer)
1093 (let ((cmdlist (append (python-args-to-list cmd) '("-i")))) 1142 (let* ((cmdlist (append (python-args-to-list cmd) '("-i")))
1143 (path (getenv "PYTHONPATH"))
1144 (process-environment ; to import emacs.py
1145 (push (concat "PYTHONPATH=" data-directory
1146 (if path (concat ":" path)))
1147 process-environment)))
1094 (set-buffer (apply 'make-comint "Python" (car cmdlist) nil 1148 (set-buffer (apply 'make-comint "Python" (car cmdlist) nil
1095 (cdr cmdlist)))) 1149 (cdr cmdlist)))
1150 (setq python-buffer "*Python*"))
1096 (inferior-python-mode) 1151 (inferior-python-mode)
1097 ;; Load function defintions we need. 1152 ;; Load function defintions we need.
1098 ;; Before the preoutput function was used, this was done via -c in 1153 ;; Before the preoutput function was used, this was done via -c in
1099 ;; cmdlist, but that loses the banner and doesn't run the startup 1154 ;; cmdlist, but that loses the banner and doesn't run the startup
1100 ;; file. 1155 ;; file. The code might be inline here, but there's enough that it
1101 (python-send-string "\ 1156 ;; seems worth putting in a separate file, and it's probably cleaner
1102def _emacs_execfile (file): # execute file and remove it 1157 ;; to put it in a module.
1103 from os import remove 1158 (python-send-string "import emacs"))
1104 try: execfile (file, globals (), globals ()) 1159 (unless noshow (pop-to-buffer python-buffer)))
1105 finally: remove (file) 1160
1106 1161;; Fixme: We typically lose if the inferior isn't in the normal REPL,
1107def _emacs_args (name): # get arglist of name for eldoc &c 1162;; e.g. prompt is `help> '. Probably raise an error if the form of
1108 import inspect 1163;; the prompt is unexpected; actually, it needs to be `>>> ', not
1109 parts = name.split ('.') 1164;; `... ', i.e. we're not inputting a block &c. However, this may not
1110 if len (parts) > 1: 1165;; be the place to do it, e.g. we might actually want to send commands
1111 try: exec 'import ' + parts[0] 1166;; having set up such a state.
1112 except: return None 1167
1113 try: exec 'func='+name # lose if name is keyword or undefined 1168(defun python-send-command (command)
1114 except: return None 1169 "Like `python-send-string' but resets `compilation-minor-mode'."
1115 if inspect.isbuiltin (func): 1170 (goto-char (point-max))
1116 doc = func.__doc__ 1171 (let ((end (marker-position (process-mark (python-proc)))))
1117 if doc.find (' ->') != -1: 1172 (compilation-forget-errors)
1118 print '_emacs_out', doc.split (' ->')[0] 1173 (python-send-string command)
1119 elif doc.find ('\\n') != -1: 1174 (set-marker compilation-parsing-end end)
1120 print '_emacs_out', doc.split ('\\n')[0] 1175 (setq compilation-last-buffer (current-buffer))))
1121 return None
1122 if inspect.ismethod (func): func = func.im_func
1123 if not inspect.isfunction (func):
1124 return None
1125 (args, varargs, varkw, defaults) = inspect.getargspec (func)
1126 print '_emacs_out', func.__name__+inspect.formatargspec (args, varargs, varkw, defaults)
1127
1128print '_emacs_ok'"))
1129 (unless noshow (pop-to-buffer (setq python-buffer "*Python*"))))
1130 1176
1131(defun python-send-region (start end) 1177(defun python-send-region (start end)
1132 "Send the region to the inferior Python process." 1178 "Send the region to the inferior Python process."
1133 ;; The region is evaluated from a temporary file. This avoids 1179 ;; The region is evaluated from a temporary file. This avoids
1134 ;; problems with blank lines, which have different semantics 1180 ;; problems with blank lines, which have different semantics
1135 ;; interactively and in files. It also saves the inferior process 1181 ;; interactively and in files. It also saves the inferior process
1136 ;; buffer filling up with interpreter prompts. We need a function 1182 ;; buffer filling up with interpreter prompts. We need a Python
1137 ;; to remove the temporary file when it has been evaluated, which 1183 ;; function to remove the temporary file when it has been evaluated
1138 ;; unfortunately means using a not-quite pristine interpreter 1184 ;; (though we could probably do it in Lisp with a Comint output
1139 ;; initially. Unfortunately we also get tracebacks which look like: 1185 ;; filter). This function also catches exceptions and truncates
1140 ;; 1186 ;; tracebacks not to mention the frame of the function itself.
1141 ;; >>> Traceback (most recent call last):
1142 ;; File "<stdin>", line 1, in ?
1143 ;; File "<string>", line 4, in _emacs_execfile
1144 ;; File "/tmp/py7734RSB", line 11
1145 ;; 1187 ;;
1146 ;; The compilation-minor-mode parsing takes care of relating the 1188 ;; The compilation-minor-mode parsing takes care of relating the
1147 ;; reference to the temporary file to the source. Fixme: 1189 ;; reference to the temporary file to the source.
1148 ;; comint-filter the first two lines of the traceback? 1190 ;;
1191 ;; Fixme: Write a `coding' header to the temp file if the region is
1192 ;; non-ASCII.
1149 (interactive "r") 1193 (interactive "r")
1150 (let* ((f (make-temp-file "py")) 1194 (let* ((f (make-temp-file "py"))
1151 (command (format "_emacs_execfile(%S)" f)) 1195 (command (format "emacs.eexecfile(%S)" f))
1152 (orig-start (copy-marker start))) 1196 (orig-start (copy-marker start)))
1153 (if (save-excursion 1197 (when (save-excursion
1154 (goto-char start) 1198 (goto-char start)
1155 (/= 0 (current-indentation))) ; need dummy block 1199 (/= 0 (current-indentation))) ; need dummy block
1156 (write-region "if True:\n" nil f nil 'nomsg)) 1200 (save-excursion
1201 (goto-char orig-start)
1202 ;; Wrong if we had indented code at buffer start.
1203 (set-marker orig-start (line-beginning-position 0)))
1204 (write-region "if True:\n" nil f nil 'nomsg))
1157 (write-region start end f t 'nomsg) 1205 (write-region start end f t 'nomsg)
1158 (when python-buffer 1206 (let ((proc (python-proc))) ;Make sure we're running a process.
1159 (with-current-buffer python-buffer 1207 (with-current-buffer python-buffer
1160 (let ((end (marker-position (process-mark (python-proc))))) 1208 (python-send-command command)
1161 (set (make-local-variable 'python-orig-start) orig-start) 1209 ;; Tell compile.el to redirect error locations in file `f' to
1162 (set (make-local-variable 'compilation-error-list) nil) 1210 ;; positions past marker `orig-start'. It has to be done *after*
1163 (let ((comint-input-filter-functions 1211 ;; python-send-command's call to compilation-forget-errors.
1164 (delete 'python-input-filter comint-input-filter-functions))) 1212 (compilation-fake-loc orig-start f)))))
1165 (python-send-string command))
1166 (set-marker compilation-parsing-end end)
1167 (setq compilation-last-buffer (current-buffer)))))))
1168 1213
1169(defun python-send-string (string) 1214(defun python-send-string (string)
1170 "Evaluate STRING in inferior Python process." 1215 "Evaluate STRING in inferior Python process."
@@ -1177,6 +1222,8 @@ print '_emacs_ok'"))
1177 (interactive) 1222 (interactive)
1178 (python-send-region (point-min) (point-max))) 1223 (python-send-region (point-min) (point-max)))
1179 1224
1225;; Fixme: Try to define the function or class within the relevant
1226;; module, not just at top level.
1180(defun python-send-defun () 1227(defun python-send-defun ()
1181 "Send the current defun (class or method) to the inferior Python process." 1228 "Send the current defun (class or method) to the inferior Python process."
1182 (interactive) 1229 (interactive)
@@ -1223,39 +1270,33 @@ function location information for debugging, and supports users of
1223module-qualified names." 1270module-qualified names."
1224 (interactive (comint-get-source "Load Python file: " python-prev-dir/file 1271 (interactive (comint-get-source "Load Python file: " python-prev-dir/file
1225 python-source-modes 1272 python-source-modes
1226 t)) ; because execfile needs exact name 1273 t)) ; because execfile needs exact name
1227 (comint-check-source file-name) ; Check to see if buffer needs saved. 1274 (comint-check-source file-name) ; Check to see if buffer needs saving.
1228 (setq python-prev-dir/file (cons (file-name-directory file-name) 1275 (setq python-prev-dir/file (cons (file-name-directory file-name)
1229 (file-name-nondirectory file-name))) 1276 (file-name-nondirectory file-name)))
1230 (when python-buffer 1277 (let ((proc (python-proc))) ;Make sure we have a process.
1231 (with-current-buffer python-buffer 1278 (with-current-buffer python-buffer
1232 (let ((end (marker-position (process-mark (python-proc))))) 1279 ;; Fixme: I'm not convinced by this logic from python-mode.el.
1233 (set (make-local-variable 'compilation-error-list) nil) 1280 (python-send-command
1234 ;; (set (make-local-variable 'compilation-old-error-list) nil) 1281 (if (string-match "\\.py\\'" file-name)
1235 (let ((comint-input-filter-functions 1282 (let ((module (file-name-sans-extension
1236 (delete 'python-input-filter comint-input-filter-functions))) 1283 (file-name-nondirectory file-name))))
1237 (python-send-string 1284 (format "emacs.eimport(%S,%S)"
1238 (if (string-match "\\.py\\'" file-name) 1285 module (file-name-directory file-name)))
1239 ;; Fixme: make sure the directory is in the path list 1286 (format "execfile(%S)" file-name)))
1240 (let ((module (file-name-sans-extension 1287 (message "%s loaded" file-name))))
1241 (file-name-nondirectory file-name)))) 1288
1242 (set (make-local-variable 'python-orig-start) nil) 1289;; Fixme: If we need to start the process, wait until we've got the OK
1243 (format "\ 1290;; from the startup.
1244if globals().has_key(%S): reload(%s)
1245else: import %s
1246" module module module))
1247 (set (make-local-variable 'python-orig-start) file-name)
1248 (format "execfile('%s')" file-name))))
1249 (set-marker compilation-parsing-end end)
1250 (setq compilation-last-buffer (current-buffer))))))
1251
1252;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.)
1253(defun python-proc () 1291(defun python-proc ()
1254 "Return the current Python process. See variable `python-buffer'." 1292 "Return the current Python process.
1255 (let ((proc (get-buffer-process (if (eq major-mode 'inferior-python-mode) 1293See variable `python-buffer'. Starts a new process if necessary."
1256 (current-buffer) 1294 (or (if python-buffer
1257 python-buffer)))) 1295 (get-buffer-process (if (eq major-mode 'inferior-python-mode)
1258 (or proc (error "No current process. See variable `python-buffer'")))) 1296 (current-buffer)
1297 python-buffer)))
1298 (progn (run-python nil t)
1299 (python-proc))))
1259 1300
1260;;;; Context-sensitive help. 1301;;;; Context-sensitive help.
1261 1302
@@ -1267,33 +1308,47 @@ else: import %s
1267 "Syntax table giving `.' symbol syntax. 1308 "Syntax table giving `.' symbol syntax.
1268Otherwise inherits from `python-mode-syntax-table'.") 1309Otherwise inherits from `python-mode-syntax-table'.")
1269 1310
1311(defvar view-return-to-alist)
1312(eval-when-compile (autoload 'help-buffer "help-fns"))
1313
1270;; Fixme: Should this actually be used instead of info-look, i.e. be 1314;; Fixme: Should this actually be used instead of info-look, i.e. be
1271;; bound to C-h S? 1315;; bound to C-h S? Can we use other pydoc stuff before python 2.2?
1272(defun python-describe-symbol (symbol) 1316(defun python-describe-symbol (symbol)
1273 "Get help on SYMBOL using `pydoc'. 1317 "Get help on SYMBOL using `help'.
1274Interactively, prompt for symbol." 1318Interactively, prompt for symbol.
1275 ;; Note that we do this in the inferior process, not a separate one to 1319
1320Symbol may be anything recognized by the interpreter's `help' command --
1321e.g. `CALLS' -- not just variables in scope.
1322This only works for Python version 2.2 or newer since earlier interpreters
1323don't support `help'."
1324 ;; Note that we do this in the inferior process, not a separate one, to
1276 ;; ensure the environment is appropriate. 1325 ;; ensure the environment is appropriate.
1277 (interactive 1326 (interactive
1278 (let ((symbol (with-syntax-table python-dotty-syntax-table 1327 (let ((symbol (with-syntax-table python-dotty-syntax-table
1279 (current-word))) 1328 (current-word)))
1280 (enable-recursive-minibuffers t) 1329 (enable-recursive-minibuffers t))
1281 val) 1330 (list (read-string (if symbol
1282 (setq val (read-string (if symbol 1331 (format "Describe symbol (default %s): " symbol)
1283 (format "Describe symbol (default %s): " 1332 "Describe symbol: ")
1284 symbol) 1333 nil nil symbol))))
1285 "Describe symbol: ")
1286 nil nil symbol))
1287 (list (or val symbol))))
1288 (if (equal symbol "") (error "No symbol")) 1334 (if (equal symbol "") (error "No symbol"))
1289 (let* ((func `(lambda () 1335 (let* ((func `(lambda ()
1290 (comint-redirect-send-command (format "help(%S)\n" ,symbol) 1336 (comint-redirect-send-command (format "emacs.ehelp(%S)\n"
1337 ,symbol)
1291 "*Help*" nil)))) 1338 "*Help*" nil))))
1292 ;; Ensure we have a suitable help buffer. 1339 ;; Ensure we have a suitable help buffer.
1293 (let (temp-buffer-show-hook) ; avoid xref stuff 1340 ;; Fixme: Maybe process `Related help topics' a la help xrefs and
1294 (with-output-to-temp-buffer "*Help*" 1341 ;; allow C-c C-f in help buffer.
1342 (let ((temp-buffer-show-hook ; avoid xref stuff
1343 (lambda ()
1344 (toggle-read-only 1)
1345 (setq view-return-to-alist
1346 (list (cons (selected-window) help-return-method))))))
1347 (help-setup-xref (list 'python-describe-symbol symbol) (interactive-p))
1348 (with-output-to-temp-buffer (help-buffer)
1295 (with-current-buffer standard-output 1349 (with-current-buffer standard-output
1296 (set (make-local-variable 'comint-redirect-subvert-readonly) t)))) 1350 (set (make-local-variable 'comint-redirect-subvert-readonly) t)
1351 (print-help-return-message))))
1297 (if (and python-buffer (get-buffer python-buffer)) 1352 (if (and python-buffer (get-buffer python-buffer))
1298 (with-current-buffer python-buffer 1353 (with-current-buffer python-buffer
1299 (funcall func)) 1354 (funcall func))
@@ -1302,6 +1357,15 @@ Interactively, prompt for symbol."
1302 1357
1303(add-to-list 'debug-ignored-errors "^No symbol") 1358(add-to-list 'debug-ignored-errors "^No symbol")
1304 1359
1360(defun python-send-receive (string)
1361 "Send STRING to inferior Python (if any) and return result.
1362The result is what follows `_emacs_out' in the output (or nil)."
1363 (let ((proc (python-proc)))
1364 (python-send-string string)
1365 (setq python-preoutput-result nil)
1366 (accept-process-output proc 5)
1367 python-preoutput-result))
1368
1305;; Fixme: try to make it work with point in the arglist. Also, is 1369;; Fixme: try to make it work with point in the arglist. Also, is
1306;; there anything reasonable we can do with random methods? 1370;; there anything reasonable we can do with random methods?
1307;; (Currently only works with functions.) 1371;; (Currently only works with functions.)
@@ -1310,14 +1374,9 @@ Interactively, prompt for symbol."
1310Only works when point is in a function name, not its arglist, for instance. 1374Only works when point is in a function name, not its arglist, for instance.
1311Assumes an inferior Python is running." 1375Assumes an inferior Python is running."
1312 (let ((symbol (with-syntax-table python-dotty-syntax-table 1376 (let ((symbol (with-syntax-table python-dotty-syntax-table
1313 (current-word))) 1377 (current-word))))
1314 (proc (and python-buffer (python-proc)))) 1378 (when symbol
1315 (when (and proc symbol) 1379 (python-send-receive (format "emacs.eargs(%S)" symbol)))))
1316 (python-send-string
1317 (format "_emacs_args(%S)" symbol))
1318 (setq python-preoutput-result nil)
1319 (accept-process-output proc 1)
1320 python-preoutput-result)))
1321 1380
1322;;;; Info-look functionality. 1381;;;; Info-look functionality.
1323 1382
@@ -1331,11 +1390,13 @@ Used with `eval-after-load'."
1331 ;; Whether info files have a Python version suffix, e.g. in Debian. 1390 ;; Whether info files have a Python version suffix, e.g. in Debian.
1332 (versioned 1391 (versioned
1333 (with-temp-buffer 1392 (with-temp-buffer
1334 (Info-mode) 1393 (with-no-warnings (Info-mode))
1335 (condition-case () 1394 (condition-case ()
1336 ;; Don't use `info' because it would pop-up a *info* buffer. 1395 ;; Don't use `info' because it would pop-up a *info* buffer.
1337 (Info-goto-node (format "(python%s-lib)Miscellaneous Index" 1396 (with-no-warnings
1338 version)) 1397 (Info-goto-node (format "(python%s-lib)Miscellaneous Index"
1398 version))
1399 t)
1339 (error nil))))) 1400 (error nil)))))
1340 (info-lookup-maybe-add-help 1401 (info-lookup-maybe-add-help
1341 :mode 'python-mode 1402 :mode 'python-mode
@@ -1401,7 +1462,7 @@ The criterion is either a match for `jython-mode' via
1401 (while (re-search-forward 1462 (while (re-search-forward
1402 (rx (and line-start (or "import" "from") (1+ space) 1463 (rx (and line-start (or "import" "from") (1+ space)
1403 (group (1+ (not (any " \t\n.")))))) 1464 (group (1+ (not (any " \t\n."))))))
1404 10000 ; Probably not worth customizing. 1465 (+ (point-min) 10000) ; Probably not worth customizing.
1405 t) 1466 t)
1406 (if (member (match-string 1) python-jython-packages) 1467 (if (member (match-string 1) python-jython-packages)
1407 (throw 'done t)))) 1468 (throw 'done t))))
@@ -1519,11 +1580,97 @@ Uses `python-beginning-of-block', `python-end-of-block'."
1519 (python-end-of-block) 1580 (python-end-of-block)
1520 (exchange-point-and-mark)) 1581 (exchange-point-and-mark))
1521 1582
1583;;;; Completion.
1584
1585(defun python-symbol-completions (symbol)
1586 "Return a list of completions of the string SYMBOL from Python process.
1587The list is sorted."
1588 (when symbol
1589 (let ((completions
1590 (condition-case ()
1591 (car (read-from-string (python-send-receive
1592 (format "emacs.complete(%S)" symbol))))
1593 (error nil))))
1594 (sort
1595 ;; We can get duplicates from the above -- don't know why.
1596 (delete-dups completions)
1597 #'string<))))
1598
1599(defun python-partial-symbol ()
1600 "Return the partial symbol before point (for completion)."
1601 (let ((end (point))
1602 (start (save-excursion
1603 (and (re-search-backward
1604 (rx (and (or buffer-start (regexp "[^[:alnum:]._]"))
1605 (group (1+ (regexp "[[:alnum:]._]")))
1606 point))
1607 nil t)
1608 (match-beginning 1)))))
1609 (if start (buffer-substring-no-properties start end))))
1610
1611;; Fixme: We should have an abstraction of this sort of thing in the
1612;; core.
1613(defun python-complete-symbol ()
1614 "Perform completion on the Python symbol preceding point.
1615Repeating the command scrolls the completion window."
1616 (interactive)
1617 (let ((window (get-buffer-window "*Completions*")))
1618 (if (and (eq last-command this-command)
1619 window (window-live-p window) (window-buffer window)
1620 (buffer-name (window-buffer window)))
1621 (with-current-buffer (window-buffer window)
1622 (if (pos-visible-in-window-p (point-max) window)
1623 (set-window-start window (point-min))
1624 (save-selected-window
1625 (select-window window)
1626 (scroll-up))))
1627 ;; Do completion.
1628 (let* ((end (point))
1629 (symbol (python-partial-symbol))
1630 (completions (python-symbol-completions symbol))
1631 (completion (if completions
1632 (try-completion symbol completions))))
1633 (when symbol
1634 (cond ((eq completion t))
1635 ((null completion)
1636 (message "Can't find completion for \"%s\"" symbol)
1637 (ding))
1638 ((not (string= symbol completion))
1639 (delete-region (- end (length symbol)) end)
1640 (insert completion))
1641 (t
1642 (message "Making completion list...")
1643 (with-output-to-temp-buffer "*Completions*"
1644 (display-completion-list completions))
1645 (message "Making completion list...%s" "done"))))))))
1646
1647(eval-when-compile (require 'hippie-exp))
1648
1649(defun python-try-complete (old)
1650 "Completion function for Python for use with `hippie-expand'."
1651 (when (eq major-mode 'python-mode) ; though we only add it locally
1652 (unless old
1653 (let ((symbol (python-partial-symbol)))
1654 (he-init-string (- (point) (length symbol)) (point))
1655 (if (not (he-string-member he-search-string he-tried-table))
1656 (push he-search-string he-tried-table))
1657 (setq he-expand-list
1658 (and symbol (python-symbol-completions symbol)))))
1659 (while (and he-expand-list
1660 (he-string-member (car he-expand-list) he-tried-table))
1661 (pop he-expand-list))
1662 (if he-expand-list
1663 (progn
1664 (he-substitute-string (pop he-expand-list))
1665 t)
1666 (if old (he-reset-string))
1667 nil)))
1668
1522;;;; Modes. 1669;;;; Modes.
1523 1670
1524(defvar outline-heading-end-regexp) 1671(defvar outline-heading-end-regexp)
1525(defvar eldoc-print-current-symbol-info-function) 1672(defvar eldoc-print-current-symbol-info-function)
1526(defvar python-mode-running) 1673
1527;;;###autoload 1674;;;###autoload
1528(define-derived-mode python-mode fundamental-mode "Python" 1675(define-derived-mode python-mode fundamental-mode "Python"
1529 "Major mode for editing Python files. 1676 "Major mode for editing Python files.
@@ -1565,11 +1712,10 @@ lines count as headers.
1565 )) 1712 ))
1566 (set (make-local-variable 'parse-sexp-lookup-properties) t) 1713 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1567 (set (make-local-variable 'comment-start) "# ") 1714 (set (make-local-variable 'comment-start) "# ")
1568 ;; Fixme: define a comment-indent-function? 1715 (set (make-local-variable 'comment-indent-function) #'python-comment-indent)
1569 (set (make-local-variable 'indent-line-function) #'python-indent-line) 1716 (set (make-local-variable 'indent-line-function) #'python-indent-line)
1570 (set (make-local-variable 'paragraph-start) "\\s-*$") 1717 (set (make-local-variable 'paragraph-start) "\\s-*$")
1571 (set (make-local-variable 'fill-paragraph-function) 1718 (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph)
1572 'python-fill-paragraph)
1573 (set (make-local-variable 'require-final-newline) t) 1719 (set (make-local-variable 'require-final-newline) t)
1574 (set (make-local-variable 'add-log-current-defun-function) 1720 (set (make-local-variable 'add-log-current-defun-function)
1575 #'python-current-defun) 1721 #'python-current-defun)
@@ -1587,6 +1733,9 @@ lines count as headers.
1587 #'python-eldoc-function) 1733 #'python-eldoc-function)
1588 (add-hook 'eldoc-mode-hook 1734 (add-hook 'eldoc-mode-hook
1589 '(lambda () (run-python 0 t)) nil t) ; need it running 1735 '(lambda () (run-python 0 t)) nil t) ; need it running
1736 (if (featurep 'hippie-exp)
1737 (set (make-local-variable 'hippie-expand-try-functions-list)
1738 (cons 'python-try-complete hippie-expand-try-functions-list)))
1590 (unless font-lock-mode (font-lock-mode 1)) 1739 (unless font-lock-mode (font-lock-mode 1))
1591 (when python-guess-indent (python-guess-indent)) 1740 (when python-guess-indent (python-guess-indent))
1592 (set (make-local-variable 'python-command) python-python-command) 1741 (set (make-local-variable 'python-command) python-python-command)
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index df2bf6803da..adb5f7b402a 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -648,7 +648,7 @@ implemented as aliases. See `sh-feature'."
648 648
649 (rc "else") 649 (rc "else")
650 650
651 (sh "do" "elif" "else" "if" "then" "trap" "type" "until" "while")) 651 (sh "!" "do" "elif" "else" "if" "then" "trap" "type" "until" "while"))
652 "*List of keywords that may be immediately followed by a builtin or keyword. 652 "*List of keywords that may be immediately followed by a builtin or keyword.
653Given some confusion between keywords and builtins depending on shell and 653Given some confusion between keywords and builtins depending on shell and
654system, the distinction here has been based on whether they influence the 654system, the distinction here has been based on whether they influence the
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 1a9251599ce..0e0d89b07e1 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -1,11 +1,12 @@
1;;; sql.el --- specialized comint.el for SQL interpreters 1;;; sql.el --- specialized comint.el for SQL interpreters
2 2
3;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 3;; Copyright (C) 1998,99,2000,01,02,03,04 Free Software Foundation, Inc.
4 4
5;; Author: Alex Schroeder <alex@gnu.org> 5;; Author: Alex Schroeder <alex@gnu.org>
6;; Maintainer: Michael Mauger <mmaug@yahoo.com> 6;; Maintainer: Michael Mauger <mmaug@yahoo.com>
7;; Version: 1.8.0 7;; Version: 2.0.1
8;; Keywords: comm languages processes 8;; Keywords: comm languages processes
9;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el
9;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode 10;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode
10 11
11;; This file is part of GNU Emacs. 12;; This file is part of GNU Emacs.
@@ -101,7 +102,7 @@
101 102
102;; (const :tag "XyzDB" xyz) 103;; (const :tag "XyzDB" xyz)
103 104
104;; 2) Add an entry to the `sql-product-support' list. 105;; 2) Add an entry to the `sql-product-alist' list.
105 106
106;; (xyz 107;; (xyz
107;; :font-lock sql-mode-xyz-font-lock-keywords 108;; :font-lock sql-mode-xyz-font-lock-keywords
@@ -136,7 +137,7 @@
136;; using ANSI keywords. See sql-mode-oracle-font-lock-keywords for 137;; using ANSI keywords. See sql-mode-oracle-font-lock-keywords for
137;; a more complex example. 138;; a more complex example.
138 139
139;; (defvar sql-mode-xyz-font-lock-keywords sql-mode-ansi-font-lock-keywords 140;; (defvar sql-mode-xyz-font-lock-keywords nil
140;; "XyzDB SQL keywords used by font-lock.") 141;; "XyzDB SQL keywords used by font-lock.")
141 142
142;; 6) Add a product highlighting function. 143;; 6) Add a product highlighting function.
@@ -192,13 +193,18 @@
192 193
193;;; Thanks to all the people who helped me out: 194;;; Thanks to all the people who helped me out:
194 195
196;; Alex Schroeder <alex@gnu.org>
195;; Kai Blauberg <kai.blauberg@metla.fi> 197;; Kai Blauberg <kai.blauberg@metla.fi>
196;; <ibalaban@dalet.com> 198;; <ibalaban@dalet.com>
197;; Yair Friedman <yfriedma@JohnBryce.Co.Il> 199;; Yair Friedman <yfriedma@JohnBryce.Co.Il>
198;; Gregor Zych <zych@pool.informatik.rwth-aachen.de> 200;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
199;; nino <nino@inform.dk> 201;; nino <nino@inform.dk>
200;; Berend de Boer <berend@pobox.com> 202;; Berend de Boer <berend@pobox.com>
201;; Michael Mauger <mmaug@yahoo.com> 203;; Adam Jenkins <adam@thejenkins.org>
204;; Michael Mauger <mmaug@yahoo.com> -- improved product support
205;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
206;; Harald Maier <maierh@myself.com> -- sql-send-string
207;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections
202 208
203 209
204 210
@@ -209,6 +215,8 @@
209(eval-when-compile 215(eval-when-compile
210 (require 'regexp-opt)) 216 (require 'regexp-opt))
211(require 'custom) 217(require 'custom)
218(eval-when-compile ;; needed in Emacs 19, 20
219 (setq max-specpdl-size 2000))
212 220
213;;; Allow customization 221;;; Allow customization
214 222
@@ -264,7 +272,7 @@ highlighted properly when you open them."
264(defvar sql-interactive-product nil 272(defvar sql-interactive-product nil
265 "Product under `sql-interactive-mode'.") 273 "Product under `sql-interactive-mode'.")
266 274
267(defvar sql-product-support 275(defvar sql-product-alist
268 '((ansi 276 '((ansi
269 :font-lock sql-mode-ansi-font-lock-keywords) 277 :font-lock sql-mode-ansi-font-lock-keywords)
270 (db2 278 (db2
@@ -319,9 +327,9 @@ highlighted properly when you open them."
319 :syntax-alist ((?$ . "w") (?# . "w"))) 327 :syntax-alist ((?$ . "w") (?# . "w")))
320 (postgres 328 (postgres
321 :font-lock sql-mode-postgres-font-lock-keywords 329 :font-lock sql-mode-postgres-font-lock-keywords
322 :sqli-login (database server) 330 :sqli-login (user database server)
323 :sqli-connect sql-connect-postgres 331 :sqli-connect sql-connect-postgres
324 :sqli-prompt-regexp "^.*> *" 332 :sqli-prompt-regexp "^.*[#>] *"
325 :sqli-prompt-length 5) 333 :sqli-prompt-length 5)
326 (solid 334 (solid
327 :font-lock sql-mode-solid-font-lock-keywords 335 :font-lock sql-mode-solid-font-lock-keywords
@@ -372,10 +380,12 @@ following:
372 database. Do product specific 380 database. Do product specific
373 configuration of comint in this function. 381 configuration of comint in this function.
374 382
375 :sqli-prompt-regexp a regular expression string that matches the 383 :sqli-prompt-regexp a regular expression string that matches
376 prompt issued by the product interpreter. 384 the prompt issued by the product
385 interpreter. (Not needed in 21.3+)
377 386
378 :sqli-prompt-length the length of the prompt on the line. 387 :sqli-prompt-length the length of the prompt on the line.(Not
388 needed in 21.3+)
379 389
380 :syntax-alist an alist of syntax table entries to enable 390 :syntax-alist an alist of syntax table entries to enable
381 special character treatment by font-lock and 391 special character treatment by font-lock and
@@ -412,14 +422,14 @@ buffer is shown using `display-buffer'."
412 422
413(defvar sql-imenu-generic-expression 423(defvar sql-imenu-generic-expression
414 ;; Items are in reverse order because they are rendered in reverse. 424 ;; Items are in reverse order because they are rendered in reverse.
415 '(("Rules/Defaults" "^\\s-*create\\s-+\\(rule\\|default\\)\\s-+\\(\\w+\\)" 2) 425 '(("Rules/Defaults" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*\\(rule\\|default\\)\\s-+\\(\\w+\\)" 3)
416 ("Sequences" "^\\s-*create\\s-+sequence\\s-+\\(\\w+\\)" 1) 426 ("Sequences" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*sequence\\s-+\\(\\w+\\)" 2)
417 ("Triggers" "^\\s-*\\(create\\s-+\\(or\\s-+replace\\s-+\\)?\\)?trigger\\s-+\\(\\w+\\)" 3) 427 ("Triggers" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*trigger\\s-+\\(\\w+\\)" 2)
418 ("Functions" "^\\s-*\\(create\\s-+\\(or\\s-+replace\\s-+\\)?\\)?function\\s-+\\(\\w+\\)" 3) 428 ("Functions" "^\\s-*\\(create\\s-+\\(\\w+\\s-+\\)*\\)?function\\s-+\\(\\w+\\)" 3)
419 ("Procedures" "^\\s-*\\(create\\s-+\\(or\\s-+replace\\s-+\\)?\\)?proc\\(edure\\)?\\s-+\\(\\w+\\)" 4) 429 ("Procedures" "^\\s-*\\(create\\s-+\\(\\w+\\s-+\\)*\\)?proc\\(edure\\)?\\s-+\\(\\w+\\)" 4)
420 ("Packages" "^\\s-*create\\s-+\\(or\\s-+replace\\s-+\\)?package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" 3) 430 ("Packages" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" 3)
421 ("Indexes" "^\\s-*create\\s-+index\\s-+\\(\\w+\\)" 1) 431 ("Indexes" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*index\\s-+\\(\\w+\\)" 2)
422 ("Tables/Views" "^\\s-*create\\s-+\\(\\(global\\s-+\\)?\\(temporary\\s-+\\)?table\\|view\\)\\s-+\\(\\w+\\)" 4)) 432 ("Tables/Views" "^\\s-*create\\s-+\\(\\w+\\s-+\\)*\\(table\\|view\\)\\s-+\\(\\w+\\)" 3))
423 "Define interesting points in the SQL buffer for `imenu'. 433 "Define interesting points in the SQL buffer for `imenu'.
424 434
425This is used to set `imenu-generic-expression' when SQL mode is 435This is used to set `imenu-generic-expression' when SQL mode is
@@ -745,6 +755,7 @@ Based on `comint-mode-map'.")
745 (let ((map (make-sparse-keymap))) 755 (let ((map (make-sparse-keymap)))
746 (define-key map (kbd "C-c C-c") 'sql-send-paragraph) 756 (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
747 (define-key map (kbd "C-c C-r") 'sql-send-region) 757 (define-key map (kbd "C-c C-r") 'sql-send-region)
758 (define-key map (kbd "C-c C-s") 'sql-send-string)
748 (define-key map (kbd "C-c C-b") 'sql-send-buffer) 759 (define-key map (kbd "C-c C-b") 'sql-send-buffer)
749 map) 760 map)
750 "Mode map used for `sql-mode'.") 761 "Mode map used for `sql-mode'.")
@@ -764,6 +775,7 @@ Based on `comint-mode-map'.")
764 (get-buffer-process sql-buffer))] 775 (get-buffer-process sql-buffer))]
765 ["Send Buffer" sql-send-buffer (and (buffer-live-p sql-buffer) 776 ["Send Buffer" sql-send-buffer (and (buffer-live-p sql-buffer)
766 (get-buffer-process sql-buffer))] 777 (get-buffer-process sql-buffer))]
778 ["Send String" sql-send-string t]
767 ["--" nil nil] 779 ["--" nil nil]
768 ["Start SQLi session" sql-product-interactive (sql-product-feature :sqli-connect)] 780 ["Start SQLi session" sql-product-interactive (sql-product-feature :sqli-connect)]
769 ["Show SQLi buffer" sql-show-sqli-buffer t] 781 ["Show SQLi buffer" sql-show-sqli-buffer t]
@@ -792,7 +804,7 @@ Based on `comint-mode-map'.")
792 ["Linter" sql-highlight-linter-keywords 804 ["Linter" sql-highlight-linter-keywords
793 :style radio 805 :style radio
794 :selected (eq sql-product 'linter)] 806 :selected (eq sql-product 'linter)]
795 ["Microsoft" sql-highlight-ms-keywords 807 ["MS SQLServer" sql-highlight-ms-keywords
796 :style radio 808 :style radio
797 :selected (eq sql-product 'ms)] 809 :selected (eq sql-product 'ms)]
798 ["MySQL" sql-highlight-mysql-keywords 810 ["MySQL" sql-highlight-mysql-keywords
@@ -828,24 +840,24 @@ Based on `comint-mode-map'.")
828 840
829(defvar sql-mode-abbrev-table nil 841(defvar sql-mode-abbrev-table nil
830 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.") 842 "Abbrev table used in `sql-mode' and `sql-interactive-mode'.")
831(if sql-mode-abbrev-table 843(unless sql-mode-abbrev-table
832 () 844 (define-abbrev-table 'sql-mode-abbrev-table nil)
833 (let ((nargs (cdr (subr-arity (symbol-function 'define-abbrev)))) 845 (mapcar
834 d-a)
835 ;; In Emacs 21.3+, provide SYSTEM-FLAG to define-abbrev. 846 ;; In Emacs 21.3+, provide SYSTEM-FLAG to define-abbrev.
836 (setq d-a 847 '(lambda (abbrev)
837 (if (>= nargs 6) 848 (let ((name (car abbrev))
838 '(lambda (name expansion) (define-abbrev sql-mode-abbrev-table name expansion nil 0 t)) 849 (expansion (cdr abbrev)))
839 '(lambda (name expansion) (define-abbrev sql-mode-abbrev-table name expansion)))) 850 (condition-case nil
840 851 (define-abbrev sql-mode-abbrev-table name expansion nil 0 t)
841 (define-abbrev-table 'sql-mode-abbrev-table nil) 852 (error
842 (funcall d-a "ins" "insert") 853 (define-abbrev sql-mode-abbrev-table name expansion)))))
843 (funcall d-a "upd" "update") 854 '(("ins" "insert")
844 (funcall d-a "del" "delete") 855 ("upd" "update")
845 (funcall d-a "sel" "select") 856 ("del" "delete")
846 (funcall d-a "proc" "procedure") 857 ("sel" "select")
847 (funcall d-a "func" "function") 858 ("proc" "procedure")
848 (funcall d-a "cr" "create"))) 859 ("func" "function")
860 ("cr" "create"))))
849 861
850;; Syntax Table 862;; Syntax Table
851 863
@@ -855,9 +867,7 @@ Based on `comint-mode-map'.")
855 (modify-syntax-entry ?/ ". 14" table) 867 (modify-syntax-entry ?/ ". 14" table)
856 (modify-syntax-entry ?* ". 23" table) 868 (modify-syntax-entry ?* ". 23" table)
857 ;; double-dash starts comment 869 ;; double-dash starts comment
858 (if (string-match "XEmacs\\|Lucid" emacs-version) 870 (modify-syntax-entry ?- ". 12b" table)
859 (modify-syntax-entry ?- ". 56" table)
860 (modify-syntax-entry ?- ". 12b" table))
861 ;; newline and formfeed end coments 871 ;; newline and formfeed end coments
862 (modify-syntax-entry ?\n "> b" table) 872 (modify-syntax-entry ?\n "> b" table)
863 (modify-syntax-entry ?\f "> b" table) 873 (modify-syntax-entry ?\f "> b" table)
@@ -871,55 +881,117 @@ Based on `comint-mode-map'.")
871;; Font lock support 881;; Font lock support
872 882
873(defvar sql-mode-font-lock-object-name 883(defvar sql-mode-font-lock-object-name
874 (list (concat "^\\s-*\\(create\\(\\s-+or\\s-+replace\\)?\\|drop\\|alter\\)?\\s-+" 884 (list (concat "^\\s-*\\(create\\|drop\\|alter\\)\\s-+" ;; lead off with CREATE, DROP or ALTER
875 "\\(\\(global\\s-+\\)?\\(temporary\\s-+\\)?table\\|view\\|package\\(\\s-+body\\)?\\|" 885 "\\(\\w+\\s-+\\)*" ;; optional intervening keywords
876 "proc\\(edure\\)?\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+\\(\\w+\\)") 886 "\\(table\\|view\\|package\\(\\s-+body\\)?\\|proc\\(edure\\)?"
877 8 'font-lock-function-name-face) 887 "\\|function\\|trigger\\|sequence\\|rule\\|default\\)\\s-+"
878 888 "\\(\\w+\\)")
879 "Pattern to match the names of top-level objects in a CREATE, 889 6 'font-lock-function-name-face)
880DROP or ALTER statement. 890
881 891 "Pattern to match the names of top-level objects.
882The format of variable should be a valid `font-lock-keywords' 892
883entry.") 893The pattern matches the name in a CREATE, DROP or ALTER
894statement. The format of variable should be a valid
895`font-lock-keywords' entry.")
896
897(defmacro sql-keywords-re (&rest keywords)
898 "Compile-time generation of regexp matching any one of KEYWORDS."
899 `(eval-when-compile
900 (concat "\\b"
901 (regexp-opt ',keywords t)
902 "\\b")))
884 903
885(defvar sql-mode-ansi-font-lock-keywords 904(defvar sql-mode-ansi-font-lock-keywords
886 (let ((ansi-keywords (eval-when-compile 905 (let ((ansi-funcs (sql-keywords-re
887 (concat "\\b" 906"abs" "avg" "bit_length" "cardinality" "cast" "char_length"
888 (regexp-opt '( 907"character_length" "coalesce" "convert" "count" "current_date"
889 908"current_path" "current_role" "current_time" "current_timestamp"
890"authorization" "avg" "begin" "close" "cobol" "commit" 909"current_user" "extract" "localtime" "localtimestamp" "lower" "max"
891"continue" "count" "declare" "double" "end" "escape" 910"min" "mod" "nullif" "octet_length" "overlay" "placing" "session_user"
892"exec" "fetch" "foreign" "fortran" "found" "go" "goto" "indicator" 911"substring" "sum" "system_user" "translate" "treat" "trim" "upper"
893"key" "language" "max" "min" "module" "numeric" "open" "pascal" "pli" 912"user"
894"precision" "primary" "procedure" "references" "rollback" 913))
895"schema" "section" "some" "sqlcode" "sqlerror" "sum" "work" 914
896 915 (ansi-non-reserved (sql-keywords-re
897) t) "\\b"))) 916"ada" "asensitive" "assignment" "asymmetric" "atomic" "between"
898 (ansi-reserved-words (eval-when-compile 917"bitvar" "called" "catalog_name" "chain" "character_set_catalog"
899 (concat "\\b" 918"character_set_name" "character_set_schema" "checked" "class_origin"
900 (regexp-opt '( 919"cobol" "collation_catalog" "collation_name" "collation_schema"
901 920"column_name" "command_function" "command_function_code" "committed"
902"all" "and" "any" "as" "asc" "between" "by" "check" "create" 921"condition_number" "connection_name" "constraint_catalog"
903"current" "default" "delete" "desc" "distinct" "exists" "float" "for" 922"constraint_name" "constraint_schema" "contains" "cursor_name"
904"from" "grant" "group" "having" "in" "insert" "into" "is" 923"datetime_interval_code" "datetime_interval_precision" "defined"
905"like" "not" "null" "of" "on" "option" "or" "order" "privileges" 924"definer" "dispatch" "dynamic_function" "dynamic_function_code"
906"public" "select" "set" "table" "to" "union" "unique" 925"existing" "exists" "final" "fortran" "generated" "granted"
907"update" "user" "values" "view" "where" "with" 926"hierarchy" "hold" "implementation" "infix" "insensitive" "instance"
908 927"instantiable" "invoker" "key_member" "key_type" "length" "m"
909) t) "\\b"))) 928"message_length" "message_octet_length" "message_text" "method" "more"
910 (ansi-types (eval-when-compile 929"mumps" "name" "nullable" "number" "options" "overlaps" "overriding"
911 (concat "\\b" 930"parameter_mode" "parameter_name" "parameter_ordinal_position"
912 (regexp-opt '( 931"parameter_specific_catalog" "parameter_specific_name"
913 932"parameter_specific_schema" "pascal" "pli" "position" "repeatable"
914;; ANSI Keywords that look like types 933"returned_length" "returned_octet_length" "returned_sqlstate"
915"character" "cursor" "dec" "int" "real" 934"routine_catalog" "routine_name" "routine_schema" "row_count" "scale"
916;; ANSI Reserved Word that look like types 935"schema_name" "security" "self" "sensitive" "serializable"
917"char" "integer" "smallint" 936"server_name" "similar" "simple" "source" "specific_name" "style"
918 937"subclass_origin" "sublist" "symmetric" "system" "table_name"
919) t) "\\b")))) 938"transaction_active" "transactions_committed"
920 (list (cons ansi-keywords 'font-lock-keyword-face) 939"transactions_rolled_back" "transform" "transforms" "trigger_catalog"
921 (cons ansi-reserved-words 'font-lock-keyword-face) 940"trigger_name" "trigger_schema" "type" "uncommitted" "unnamed"
922 (cons ansi-types 'font-lock-type-face))) 941"user_defined_type_catalog" "user_defined_type_name"
942"user_defined_type_schema"
943))
944
945 (ansi-reserved (sql-keywords-re
946"absolute" "action" "add" "admin" "after" "aggregate" "alias" "all"
947"allocate" "alter" "and" "any" "are" "as" "asc" "assertion" "at"
948"authorization" "before" "begin" "both" "breadth" "by" "call"
949"cascade" "cascaded" "case" "catalog" "check" "class" "close"
950"collate" "collation" "column" "commit" "completion" "connect"
951"connection" "constraint" "constraints" "constructor" "continue"
952"corresponding" "create" "cross" "cube" "current" "cursor" "cycle"
953"data" "day" "deallocate" "declare" "default" "deferrable" "deferred"
954"delete" "depth" "deref" "desc" "describe" "descriptor" "destroy"
955"destructor" "deterministic" "diagnostics" "dictionary" "disconnect"
956"distinct" "domain" "drop" "dynamic" "each" "else" "end" "equals"
957"escape" "every" "except" "exception" "exec" "execute" "external"
958"false" "fetch" "first" "for" "foreign" "found" "free" "from" "full"
959"function" "general" "get" "global" "go" "goto" "grant" "group"
960"grouping" "having" "host" "hour" "identity" "ignore" "immediate" "in"
961"indicator" "initialize" "initially" "inner" "inout" "input" "insert"
962"intersect" "into" "is" "isolation" "iterate" "join" "key" "language"
963"last" "lateral" "leading" "left" "less" "level" "like" "limit"
964"local" "locator" "map" "match" "minute" "modifies" "modify" "module"
965"month" "names" "natural" "new" "next" "no" "none" "not" "null" "of"
966"off" "old" "on" "only" "open" "operation" "option" "or" "order"
967"ordinality" "out" "outer" "output" "pad" "parameter" "parameters"
968"partial" "path" "postfix" "prefix" "preorder" "prepare" "preserve"
969"primary" "prior" "privileges" "procedure" "public" "read" "reads"
970"recursive" "references" "referencing" "relative" "restrict" "result"
971"return" "returns" "revoke" "right" "role" "rollback" "rollup"
972"routine" "rows" "savepoint" "schema" "scroll" "search" "second"
973"section" "select" "sequence" "session" "set" "sets" "size" "some"
974"space" "specific" "specifictype" "sql" "sqlexception" "sqlstate"
975"sqlwarning" "start" "state" "statement" "static" "structure" "table"
976"temporary" "terminate" "than" "then" "timezone_hour"
977"timezone_minute" "to" "trailing" "transaction" "translation"
978"trigger" "true" "under" "union" "unique" "unknown" "unnest" "update"
979"usage" "using" "value" "values" "variable" "view" "when" "whenever"
980"where" "with" "without" "work" "write" "year"
981))
982
983 (ansi-types (sql-keywords-re
984"array" "binary" "bit" "blob" "boolean" "char" "character" "clob"
985"date" "dec" "decimal" "double" "float" "int" "integer" "interval"
986"large" "national" "nchar" "nclob" "numeric" "object" "precision"
987"real" "ref" "row" "scope" "smallint" "time" "timestamp" "varchar"
988"varying" "zone"
989)))
990
991 `((,ansi-non-reserved . font-lock-keyword-face)
992 (,ansi-reserved . font-lock-keyword-face)
993 (,ansi-funcs . font-lock-builtin-face)
994 (,ansi-types . font-lock-type-face)))
923 995
924 "ANSI SQL keywords used by font-lock. 996 "ANSI SQL keywords used by font-lock.
925 997
@@ -930,66 +1002,156 @@ you define your own sql-mode-ansi-font-lock-keywords. You may want to
930add functions and PL/SQL keywords.") 1002add functions and PL/SQL keywords.")
931 1003
932(defvar sql-mode-oracle-font-lock-keywords 1004(defvar sql-mode-oracle-font-lock-keywords
933 (let ((oracle-keywords (eval-when-compile 1005 (let ((oracle-functions (sql-keywords-re
934 (concat "\\b" 1006"abs" "acos" "add_months" "ascii" "asciistr" "asin" "atan" "atan2"
935 (regexp-opt '( 1007"avg" "bfilename" "bin_to_num" "bitand" "cast" "ceil" "chartorowid"
936;; Oracle (+ANSI) SQL keywords 1008"chr" "coalesce" "compose" "concat" "convert" "corr" "cos" "cosh"
937 1009"count" "covar_pop" "covar_samp" "cume_dist" "current_date"
938; ANSI keywords 1010"current_timestamp" "current_user" "dbtimezone" "decode" "decompose"
939"authorization" "avg" "begin" "close" "cobol" "commit" 1011"dense_rank" "depth" "deref" "dump" "empty_clob" "existsnode" "exp"
940"continue" "count" "declare" "double" "end" "escape" 1012"extract" "extractvalue" "first" "first_value" "floor" "following"
941"exec" "fetch" "foreign" "fortran" "found" "go" "goto" "indicator" 1013"from_tz" "greatest" "group_id" "grouping_id" "hextoraw" "initcap"
942"key" "language" "max" "min" "module" "numeric" "open" "pascal" "pli" 1014"instr" "lag" "last" "last_day" "last_value" "lead" "least" "length"
943"precision" "primary" "procedure" "references" "rollback" 1015"ln" "localtimestamp" "lower" "lpad" "ltrim" "make_ref" "max" "min"
944"schema" "section" "some" "sqlcode" "sqlerror" "sum" "work" 1016"mod" "months_between" "new_time" "next_day" "nls_charset_decl_len"
945 1017"nls_charset_id" "nls_charset_name" "nls_initcap" "nls_lower"
946; ANSI reserved words 1018"nls_upper" "nlssort" "ntile" "nullif" "numtodsinterval"
947"all" "and" "any" "as" "asc" "between" "by" "check" "create" 1019"numtoyminterval" "nvl" "nvl2" "over" "path" "percent_rank"
948"current" "default" "delete" "desc" "distinct" "exists" "float" "for" 1020"percentile_cont" "percentile_disc" "power" "preceding" "rank"
949"from" "grant" "group" "having" "in" "insert" "into" "is" 1021"ratio_to_report" "rawtohex" "rawtonhex" "reftohex" "regr_"
950"like" "not" "null" "of" "on" "option" "or" "order" "privileges" 1022"regr_avgx" "regr_avgy" "regr_count" "regr_intercept" "regr_r2"
951"public" "select" "set" "table" "to" "union" "unique" 1023"regr_slope" "regr_sxx" "regr_sxy" "regr_syy" "replace" "round"
952"update" "user" "values" "view" "where" "with" 1024"row_number" "rowidtochar" "rowidtonchar" "rpad" "rtrim"
953 1025"sessiontimezone" "sign" "sin" "sinh" "soundex" "sqrt" "stddev"
954"access" "add" "admin" "after" "allocate" "alter" "analyze" "archive" 1026"stddev_pop" "stddev_samp" "substr" "sum" "sys_connect_by_path"
955"archivelog" "audit" "authid" "backup" "become" "before" "block" 1027"sys_context" "sys_dburigen" "sys_extract_utc" "sys_guid" "sys_typeid"
956"body" "cache" "cancel" "cascade" "change" "checkpoint" "cluster" 1028"sys_xmlagg" "sys_xmlgen" "sysdate" "systimestamp" "tan" "tanh"
957"comment" "compile" "compress" "compute" "connect" "constraint" 1029"to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
958"constraints" "contents" "controlfile" "cross" "currval" "cycle" 1030"to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
959"database" "datafile" "dba" "deterministic" "disable" "dismount" 1031"to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
960"drop" "dump" "each" "else" "else" "elsif" "enable" "events" "except" 1032"tz_offset" "uid" "unbounded" "unistr" "updatexml" "upper" "user"
961"exceptions" "exclusive" "execute" "exit" "explain" "extent" 1033"userenv" "var_pop" "var_samp" "variance" "vsize" "width_bucket" "xml"
962"externally" "false" "file" "flush" "force" "freelist" "freelists" 1034"xmlagg" "xmlattribute" "xmlcolattval" "xmlconcat" "xmlelement"
963"full" "function" "global" "grant" "groups" "identified" "if" 1035"xmlforest" "xmlsequence" "xmltransform"
964"immediate" "including" "increment" "index" "initial" "initrans" 1036))
965"inner" "instance" "intersect" "join" "layer" "left" "level" "link" 1037
966"lists" "lock" "logfile" "long" "loop" "manage" "manual" 1038 (oracle-keywords (sql-keywords-re
967"maxdatafiles" "maxextents" "maxinistances" "maxlogfiles" 1039"abort" "access" "accessed" "account" "activate" "add" "admin"
968"maxloghistory" "maxlogmembers" "maxtrans" "maxvalue" "merge" 1040"advise" "after" "agent" "aggregate" "all" "allocate" "allow" "alter"
969"minextents" "minus" "minvalue" "mode" "modify" "mount" "natural" 1041"always" "analyze" "ancillary" "and" "any" "apply" "archive"
970"new" "next" "nextval" "noarchivelog" "noaudit" "nocache" "nocompress" 1042"archivelog" "array" "as" "asc" "associate" "at" "attribute"
971"nocycle" "nomaxvalue" "nominvalue" "none" "noorder" "noresetlogs" 1043"attributes" "audit" "authenticated" "authid" "authorization" "auto"
972"normal" "nosort" "nowait" "off" "offline" "old" "online" "only" 1044"autoallocate" "automatic" "availability" "backup" "before" "begin"
973"optimal" "others" "out" "outer" "over" "own" "package" "parallel" 1045"behalf" "between" "binding" "bitmap" "block" "blocksize" "body"
974"parallel_enable" "pctfree" "pctincrease" "pctused" "plan" "pragma" 1046"both" "buffer_pool" "build" "by" "cache" "call" "cancel"
975"preserve" "prior" "private" "profile" "quota" "raise" "raw" "read" 1047"cascade" "case" "category" "certificate" "chained" "change" "check"
976"recover" "referencing" "rename" "replace" "resetlogs" "resource" 1048"checkpoint" "child" "chunk" "class" "clear" "clone" "close" "cluster"
977"restrict_references" "restricted" "return" "returning" "reuse" 1049"column" "column_value" "columns" "comment" "commit" "committed"
978"revoke" "right" "rnds" "rnps" "role" "roles" "row" "rowlabel" 1050"compatibility" "compile" "complete" "composite_limit" "compress"
979"rownum" "rows" "savepoint" "scn" "segment" "sequence" "session" 1051"compute" "connect" "connect_time" "consider" "consistent"
980"share" "shared" "size" "snapshot" "sort" "statement_id" "statistics" 1052"constraint" "constraints" "constructor" "contents" "context"
981"stop" "storage" "subtype" "successful" "switch" "synonym" "sysdate" 1053"continue" "controlfile" "corruption" "cost" "cpu_per_call"
982"system" "tables" "tablespace" "temporary" "then" "thread" "tracing" 1054"cpu_per_session" "create" "cross" "cube" "current" "currval" "cycle"
983"transaction" "trigger" "triggers" "true" "truncate" "type" "uid" 1055"dangling" "data" "database" "datafile" "datafiles" "day" "ddl"
984"under" "unlimited" "until" "use" "using" "validate" "when" "while" 1056"deallocate" "debug" "default" "deferrable" "deferred" "definer"
985"wnds" "wnps" "write" 1057"delay" "delete" "demand" "desc" "determines" "deterministic"
986 1058"dictionary" "dimension" "directory" "disable" "disassociate"
987) t) "\\b"))) 1059"disconnect" "distinct" "distinguished" "distributed" "dml" "drop"
988 (oracle-warning-words (eval-when-compile 1060"each" "element" "else" "enable" "end" "equals_path" "escape"
989 (concat "\\b" 1061"estimate" "except" "exceptions" "exchange" "excluding" "exists"
990 (regexp-opt '( 1062"expire" "explain" "extent" "external" "externally"
991;; PLSQL defined exceptions 1063"failed_login_attempts" "fast" "file" "final" "finish" "flush" "for"
992 1064"force" "foreign" "freelist" "freelists" "freepools" "fresh" "from"
1065"full" "function" "functions" "generated" "global" "global_name"
1066"globally" "grant" "group" "grouping" "groups" "guard" "hash"
1067"hashkeys" "having" "heap" "hierarchy" "id" "identified" "identifier"
1068"idle_time" "immediate" "in" "including" "increment" "index" "indexed"
1069"indexes" "indextype" "indextypes" "indicator" "initial" "initialized"
1070"initially" "initrans" "inner" "insert" "instance" "instantiable"
1071"instead" "intersect" "into" "invalidate" "is" "isolation" "java"
1072"join" "keep" "key" "kill" "language" "left" "less" "level"
1073"levels" "library" "like" "like2" "like4" "likec" "limit" "link"
1074"list" "lob" "local" "location" "locator" "lock" "log" "logfile"
1075"logging" "logical" "logical_reads_per_call"
1076"logical_reads_per_session" "managed" "management" "manual" "map"
1077"mapping" "master" "matched" "materialized" "maxdatafiles"
1078"maxextents" "maximize" "maxinstances" "maxlogfiles" "maxloghistory"
1079"maxlogmembers" "maxsize" "maxtrans" "maxvalue" "member" "memory"
1080"merge" "migrate" "minextents" "minimize" "minimum" "minus" "minvalue"
1081"mode" "modify" "monitoring" "month" "mount" "move" "movement" "name"
1082"named" "natural" "nested" "never" "new" "next" "nextval" "no"
1083"noarchivelog" "noaudit" "nocache" "nocompress" "nocopy" "nocycle"
1084"nodelay" "noforce" "nologging" "nomapping" "nomaxvalue" "nominimize"
1085"nominvalue" "nomonitoring" "none" "noorder" "noparallel" "norely"
1086"noresetlogs" "noreverse" "normal" "norowdependencies" "nosort"
1087"noswitch" "not" "nothing" "notimeout" "novalidate" "nowait" "null"
1088"nulls" "object" "of" "off" "offline" "oidindex" "old" "on" "online"
1089"only" "open" "operator" "optimal" "option" "or" "order"
1090"organization" "out" "outer" "outline" "overflow" "overriding"
1091"package" "packages" "parallel" "parallel_enable" "parameters"
1092"parent" "partition" "partitions" "password" "password_grace_time"
1093"password_life_time" "password_lock_time" "password_reuse_max"
1094"password_reuse_time" "password_verify_function" "pctfree"
1095"pctincrease" "pctthreshold" "pctused" "pctversion" "percent"
1096"performance" "permanent" "pfile" "physical" "pipelined" "plan"
1097"post_transaction" "pragma" "prebuilt" "preserve" "primary" "private"
1098"private_sga" "privileges" "procedure" "profile" "protection" "public"
1099"purge" "query" "quiesce" "quota" "range" "read" "reads" "rebuild"
1100"records_per_block" "recover" "recovery" "recycle" "reduced" "ref"
1101"references" "referencing" "refresh" "register" "reject" "relational"
1102"rely" "rename" "reset" "resetlogs" "resize" "resolve" "resolver"
1103"resource" "restrict" "restrict_references" "restricted" "result"
1104"resumable" "resume" "retention" "return" "returning" "reuse"
1105"reverse" "revoke" "rewrite" "right" "rnds" "rnps" "role" "roles"
1106"rollback" "rollup" "row" "rowdependencies" "rownum" "rows" "sample"
1107"savepoint" "scan" "schema" "scn" "scope" "segment" "select"
1108"selectivity" "self" "sequence" "serializable" "session"
1109"sessions_per_user" "set" "sets" "settings" "shared" "shared_pool"
1110"shrink" "shutdown" "siblings" "sid" "single" "size" "skip" "some"
1111"sort" "source" "space" "specification" "spfile" "split" "standby"
1112"start" "statement_id" "static" "statistics" "stop" "storage" "store"
1113"structure" "subpartition" "subpartitions" "substitutable"
1114"successful" "supplemental" "suspend" "switch" "switchover" "synonym"
1115"sys" "system" "table" "tables" "tablespace" "tempfile" "template"
1116"temporary" "test" "than" "then" "thread" "through" "time_zone"
1117"timeout" "to" "trace" "transaction" "trigger" "triggers" "truncate"
1118"trust" "type" "types" "unarchived" "under" "under_path" "undo"
1119"uniform" "union" "unique" "unlimited" "unlock" "unquiesce"
1120"unrecoverable" "until" "unusable" "unused" "update" "upgrade" "usage"
1121"use" "using" "validate" "validation" "value" "values" "variable"
1122"varray" "version" "view" "wait" "when" "whenever" "where" "with"
1123"without" "wnds" "wnps" "work" "write" "xmldata" "xmlschema" "xmltype"
1124))
1125
1126 (oracle-types (sql-keywords-re
1127"bfile" "blob" "byte" "char" "character" "clob" "date" "dec" "decimal"
1128"double" "float" "int" "integer" "interval" "long" "national" "nchar"
1129"nclob" "number" "numeric" "nvarchar2" "precision" "raw" "real"
1130"rowid" "second" "smallint" "time" "timestamp" "urowid" "varchar"
1131"varchar2" "varying" "year" "zone"
1132))
1133
1134 (plsql-functions (sql-keywords-re
1135"%bulk_rowcount" "%found" "%isopen" "%notfound" "%rowcount" "%rowtype"
1136"%type" "extend" "prior"
1137))
1138
1139 (plsql-keywords (sql-keywords-re
1140"autonomous_transaction" "bulk" "char_base" "collect" "constant"
1141"cursor" "declare" "do" "elsif" "exception_init" "execute" "exit"
1142"extends" "false" "fetch" "forall" "goto" "hour" "if" "interface"
1143"loop" "minute" "number_base" "ocirowid" "opaque" "others" "rowtype"
1144"separate" "serially_reusable" "sql" "sqlcode" "sqlerrm" "subtype"
1145"the" "timezone_abbr" "timezone_hour" "timezone_minute"
1146"timezone_region" "true" "varrying" "while"
1147))
1148
1149 (plsql-type (sql-keywords-re
1150"binary_integer" "boolean" "naturaln" "pls_integer" "positive"
1151"positiven" "record" "signtype" "string"
1152))
1153
1154 (plsql-warning (sql-keywords-re
993"access_into_null" "case_not_found" "collection_is_null" 1155"access_into_null" "case_not_found" "collection_is_null"
994"cursor_already_open" "dup_val_on_index" "invalid_cursor" 1156"cursor_already_open" "dup_val_on_index" "invalid_cursor"
995"invalid_number" "login_denied" "no_data_found" "not_logged_on" 1157"invalid_number" "login_denied" "no_data_found" "not_logged_on"
@@ -997,15 +1159,11 @@ add functions and PL/SQL keywords.")
997"subscript_beyond_count" "subscript_outside_limit" "sys_invalid_rowid" 1159"subscript_beyond_count" "subscript_outside_limit" "sys_invalid_rowid"
998"timeout_on_resource" "too_many_rows" "value_error" "zero_divide" 1160"timeout_on_resource" "too_many_rows" "value_error" "zero_divide"
999"exception" "notfound" 1161"exception" "notfound"
1162))
1000 1163
1001) t) "\\b"))) 1164 (sqlplus-commands
1002 1165 (eval-when-compile (concat "^\\(\\("
1003 (oracle-sqlplus-commands 1166 (regexp-opt '(
1004 (eval-when-compile
1005 (concat "^\\(\\("
1006 (regexp-opt '(
1007;; SQL*Plus commands
1008
1009"@" "@@" "accept" "append" "archive" "attribute" "break" 1167"@" "@@" "accept" "append" "archive" "attribute" "break"
1010"btitle" "change" "clear" "column" "connect" "copy" "define" 1168"btitle" "change" "clear" "column" "connect" "copy" "define"
1011"del" "describe" "disconnect" "edit" "execute" "exit" "get" "help" 1169"del" "describe" "disconnect" "edit" "execute" "exit" "get" "help"
@@ -1040,73 +1198,16 @@ add functions and PL/SQL keywords.")
1040 "timi\\(ng\\)?\\|trim\\(out\\)?\\|trims\\(pool\\)?\\|" 1198 "timi\\(ng\\)?\\|trim\\(out\\)?\\|trims\\(pool\\)?\\|"
1041 "und\\(erline\\)?\\|ver\\(ify\\)?\\|wra\\(p\\)?\\)\\)\\)" 1199 "und\\(erline\\)?\\|ver\\(ify\\)?\\|wra\\(p\\)?\\)\\)\\)"
1042 "\\b.*$" 1200 "\\b.*$"
1043 ))) 1201 ))))
1044 1202
1045 (oracle-types 1203 `((,sqlplus-commands . font-lock-doc-face)
1046 (eval-when-compile 1204 (,oracle-functions . font-lock-builtin-face)
1047 (concat "\\b" 1205 (,oracle-keywords . font-lock-keyword-face)
1048 (regexp-opt '( 1206 (,oracle-types . font-lock-type-face)
1049;; Oracle Keywords that look like types 1207 (,plsql-functions . font-lock-builtin-face)
1050;; Oracle Reserved Words that look like types 1208 (,plsql-keywords . font-lock-keyword-face)
1051 1209 (,plsql-type . font-lock-type-face)
1052"bfile" "binary_integer" "blob" "boolean" "byte" "char" "character" 1210 (,plsql-warning . font-lock-warning-face)))
1053"clob" "date" "day" "dec" "decimal" "double" "float" "int" "integer"
1054"interval" "local" "long" "month" "natural" "naturaln" "nchar" "nclob"
1055"number" "numeric" "nvarchar2" "pls_integer" "positive" "positiven"
1056"precision" "raw" "real" "rowid" "second" "signtype" "smallint"
1057"string" "time" "timestamp" "urowid" "varchar" "varchar2" "year"
1058"zone"
1059
1060) t) "\\b")))
1061 (oracle-builtin-functions (eval-when-compile
1062 (concat "\\b"
1063 (regexp-opt '(
1064;; Misc Oracle builtin functions
1065
1066"abs" "acos" "add_months" "ascii" "asciistr" "asin" "atan" "atan2"
1067"avg" "bfilename" "bin_to_num" "bitand" "case" "cast" "ceil"
1068"chartorowid" "chr" "coalesce" "compose" "concat" "convert" "corr"
1069"cos" "cosh" "count" "covar_pop" "covar_samp" "cume_dist"
1070"current_date" "current_timestamp" "current_user" "dbtimezone"
1071"decode" "decompose" "dense_rank" "depth" "deref" "dump" "empty_blob"
1072"empty_clob" "existsnode" "exp" "extract" "extractvalue" "first"
1073"first_value" "floor" "from_tz" "greatest" "group_id" "grouping"
1074"grouping_id" "hextoraw" "initcap" "instr" "lag" "last" "last_day"
1075"last_value" "lead" "least" "length" "ln" "localtimestamp" "log"
1076"lower" "lpad" "ltrim" "make_ref" "max" "min" "mod" "months_between"
1077"nchr" "new_time" "next_day" "nls_charset_decl_len" "nls_charset_id"
1078"nls_charset_name" "nls_initcap" "nls_lower" "nlssort" "nls_upper"
1079"ntile" "nullif" "numtodsinterval" "numtoyminterval" "nvl" "nvl2"
1080"path" "percent_rank" "percentile_cont" "percentile_disc" "power"
1081"rank" "ratio_to_report" "rawtohex" "rawtonhex" "ref" "reftohex"
1082"regr_slope" "regr_intercept" "regr_count" "regr_r2" "regr_avgx"
1083"regr_avgy" "regr_sxx" "regr_syy" "regr_sxy" "round"
1084"row_number" "rowidtochar" "rowidtonchar" "rpad" "rtrim"
1085"sessiontimezone" "sign" "sin" "sinh" "soundex" "sqrt" "stddev"
1086"stddev_pop" "stddev_samp" "substr" "sum" "sys_connect_by_path"
1087"sys_context" "sys_dburigen" "sys_extract_utc" "sys_guid" "sys_typeid"
1088"sys_xmlagg" "sys_xmlgen" "sysdate" "systimestamp" "tan" "tanh"
1089"to_char" "to_clob" "to_date" "to_dsinterval" "to_lob" "to_multi_byte"
1090"to_nchar" "to_nclob" "to_number" "to_single_byte" "to_timestamp"
1091"to_timestamp_tz" "to_yminterval" "translate" "treat" "trim" "trunc"
1092"tz_offset" "uid" "unistr" "updatexml" "upper" "user" "userenv"
1093"value" "var_pop" "var_samp" "variance" "vsize" "width_bucket"
1094"xmlagg" "xmlcolattval" "xmlconcat" "xmlelement" "xmlforest"
1095"xmlsequence" "xmltransform"
1096
1097) t) "\\b"))))
1098 (list (cons oracle-sqlplus-commands 'font-lock-doc-face)
1099 (cons oracle-keywords 'font-lock-keyword-face)
1100 (cons oracle-warning-words 'font-lock-warning-face)
1101 ;; XEmacs doesn't have font-lock-builtin-face
1102 (if (string-match "XEmacs\\|Lucid" emacs-version)
1103 (cons oracle-builtin-functions 'font-lock-preprocessor-face)
1104 ;; GNU Emacs 19 doesn't have it either
1105 (if (string-match "GNU Emacs 19" emacs-version)
1106 (cons oracle-builtin-functions 'font-lock-keyword-face)
1107 ;; Emacs
1108 (cons oracle-builtin-functions 'font-lock-builtin-face)))
1109 (cons oracle-types 'font-lock-type-face)))
1110 1211
1111 "Oracle SQL keywords used by font-lock. 1212 "Oracle SQL keywords used by font-lock.
1112 1213
@@ -1117,42 +1218,84 @@ you define your own sql-mode-oracle-font-lock-keywords. You may want
1117to add functions and PL/SQL keywords.") 1218to add functions and PL/SQL keywords.")
1118 1219
1119(defvar sql-mode-postgres-font-lock-keywords 1220(defvar sql-mode-postgres-font-lock-keywords
1120 (let ((postgres-reserved-words (eval-when-compile 1221 (let ((pg-funcs (sql-keywords-re
1121 (concat "\\b" 1222"abbrev" "abs" "acos" "age" "area" "ascii" "asin" "atab2" "atan"
1122 (regexp-opt '( 1223"atan2" "avg" "bit_length" "both" "broadcast" "btrim" "cbrt" "ceil"
1123"language" 1224"center" "char_length" "chr" "coalesce" "col_description" "convert"
1124) t) "\\b"))) 1225"cos" "cot" "count" "current_database" "current_date" "current_schema"
1125 (postgres-types (eval-when-compile 1226"current_schemas" "current_setting" "current_time" "current_timestamp"
1126 (concat "\\b" 1227"current_user" "currval" "date_part" "date_trunc" "decode" "degrees"
1127 (regexp-opt '( 1228"diameter" "encode" "exp" "extract" "floor" "get_bit" "get_byte"
1128 1229"has_database_privilege" "has_function_privilege"
1129"bool" "box" "circle" "char" "char2" "char4" "char8" "char16" "date" 1230"has_language_privilege" "has_schema_privilege" "has_table_privilege"
1130"float4" "float8" "int2" "int4" "int8" "line" "lseg" "money" "path" 1231"height" "host" "initcap" "isclosed" "isfinite" "isopen" "leading"
1131"point" "polygon" "serial" "text" "time" "timespan" "timestamp" "varchar" 1232"length" "ln" "localtime" "localtimestamp" "log" "lower" "lpad"
1132 1233"ltrim" "masklen" "max" "min" "mod" "netmask" "network" "nextval"
1133) t)"\\b"))) 1234"now" "npoints" "nullif" "obj_description" "octet_length" "overlay"
1134 (postgres-builtin-functions (eval-when-compile 1235"pclose" "pg_client_encoding" "pg_function_is_visible"
1135 (concat "\\b" 1236"pg_get_constraintdef" "pg_get_indexdef" "pg_get_ruledef"
1136 (regexp-opt '( 1237"pg_get_userbyid" "pg_get_viewdef" "pg_opclass_is_visible"
1137;; Misc Postgres builtin functions 1238"pg_operator_is_visible" "pg_table_is_visible" "pg_type_is_visible"
1138 1239"pi" "popen" "position" "pow" "quote_ident" "quote_literal" "radians"
1139"abstime" "age" "area" "box" "center" "date_part" "date_trunc" 1240"radius" "random" "repeat" "replace" "round" "rpad" "rtrim"
1140"datetime" "dexp" "diameter" "dpow" "float" "float4" "height" 1241"session_user" "set_bit" "set_byte" "set_config" "set_masklen"
1141"initcap" "integer" "isclosed" "isfinite" "isoldpath" "isopen" 1242"setval" "sign" "sin" "split_part" "sqrt" "stddev" "strpos" "substr"
1142"length" "lower" "lpad" "ltrim" "pclose" "point" "points" "popen" 1243"substring" "sum" "tan" "timeofday" "to_ascii" "to_char" "to_date"
1143"position" "radius" "reltime" "revertpoly" "rpad" "rtrim" "substr" 1244"to_hex" "to_number" "to_timestamp" "trailing" "translate" "trim"
1144"substring" "text" "timespan" "translate" "trim" "upgradepath" 1245"trunc" "upper" "variance" "version" "width"
1145"upgradepoly" "upper" "varchar" "width" 1246))
1146 1247
1147) t) "\\b")))) 1248 (pg-reserved (sql-keywords-re
1148 (append sql-mode-ansi-font-lock-keywords 1249"abort" "access" "add" "after" "aggregate" "alignment" "all" "alter"
1149 (list (cons postgres-reserved-words 'font-lock-keyword-face) 1250"analyze" "and" "any" "as" "asc" "assignment" "authorization"
1150 ;; XEmacs doesn't have 'font-lock-builtin-face 1251"backward" "basetype" "before" "begin" "between" "binary" "by" "cache"
1151 (if (string-match "XEmacs\\|Lucid" emacs-version) 1252"called" "cascade" "case" "cast" "characteristics" "check"
1152 (cons postgres-builtin-functions 'font-lock-preprocessor-face) 1253"checkpoint" "class" "close" "cluster" "column" "comment" "commit"
1153 ;; Emacs 1254"committed" "commutator" "constraint" "constraints" "conversion"
1154 (cons postgres-builtin-functions 'font-lock-builtin-face)) 1255"copy" "create" "createdb" "createuser" "cursor" "cycle" "database"
1155 (cons postgres-types 'font-lock-type-face)))) 1256"deallocate" "declare" "default" "deferrable" "deferred" "definer"
1257"delete" "delimiter" "desc" "distinct" "do" "domain" "drop" "each"
1258"element" "else" "encoding" "encrypted" "end" "escape" "except"
1259"exclusive" "execute" "exists" "explain" "extended" "external" "false"
1260"fetch" "finalfunc" "for" "force" "foreign" "forward" "freeze" "from"
1261"full" "function" "grant" "group" "gtcmp" "handler" "hashes" "having"
1262"immediate" "immutable" "implicit" "in" "increment" "index" "inherits"
1263"initcond" "initially" "input" "insensitive" "insert" "instead"
1264"internallength" "intersect" "into" "invoker" "is" "isnull"
1265"isolation" "join" "key" "language" "leftarg" "level" "like" "limit"
1266"listen" "load" "local" "location" "lock" "ltcmp" "main" "match"
1267"maxvalue" "merges" "minvalue" "mode" "move" "natural" "negator"
1268"next" "nocreatedb" "nocreateuser" "none" "not" "nothing" "notify"
1269"notnull" "null" "of" "offset" "oids" "on" "only" "operator" "or"
1270"order" "output" "owner" "partial" "passedbyvalue" "password" "plain"
1271"prepare" "primary" "prior" "privileges" "procedural" "procedure"
1272"public" "read" "recheck" "references" "reindex" "relative" "rename"
1273"reset" "restrict" "returns" "revoke" "rightarg" "rollback" "row"
1274"rule" "schema" "scroll" "security" "select" "sequence" "serializable"
1275"session" "set" "sfunc" "share" "show" "similar" "some" "sort1"
1276"sort2" "stable" "start" "statement" "statistics" "storage" "strict"
1277"stype" "sysid" "table" "temp" "template" "temporary" "then" "to"
1278"transaction" "trigger" "true" "truncate" "trusted" "type"
1279"unencrypted" "union" "unique" "unknown" "unlisten" "until" "update"
1280"usage" "user" "using" "vacuum" "valid" "validator" "values"
1281"variable" "verbose" "view" "volatile" "when" "where" "with" "without"
1282"work"
1283))
1284
1285 (pg-types (sql-keywords-re
1286"anyarray" "bigint" "bigserial" "bit" "boolean" "box" "bytea" "char"
1287"character" "cidr" "circle" "cstring" "date" "decimal" "double"
1288"float4" "float8" "inet" "int2" "int4" "int8" "integer" "internal"
1289"interval" "language_handler" "line" "lseg" "macaddr" "money"
1290"numeric" "oid" "opaque" "path" "point" "polygon" "precision" "real"
1291"record" "regclass" "regoper" "regoperator" "regproc" "regprocedure"
1292"regtype" "serial" "serial4" "serial8" "smallint" "text" "time"
1293"timestamp" "varchar" "varying" "void" "zone"
1294)))
1295
1296 `((,pg-funcs . font-lock-builtin-face)
1297 (,pg-reserved . font-lock-keyword-face)
1298 (,pg-types . font-lock-type-face)))
1156 1299
1157 "Postgres SQL keywords used by font-lock. 1300 "Postgres SQL keywords used by font-lock.
1158 1301
@@ -1162,10 +1305,7 @@ function `regexp-opt'. Therefore, take a look at the source before
1162you define your own sql-mode-postgres-font-lock-keywords.") 1305you define your own sql-mode-postgres-font-lock-keywords.")
1163 1306
1164(defvar sql-mode-linter-font-lock-keywords 1307(defvar sql-mode-linter-font-lock-keywords
1165 (let ((linter-keywords (eval-when-compile 1308 (let ((linter-keywords (sql-keywords-re
1166 (concat "\\b"
1167 (regexp-opt '(
1168
1169"autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel" 1309"autocommit" "autoinc" "autorowid" "cancel" "cascade" "channel"
1170"committed" "count" "countblob" "cross" "current" "data" "database" 1310"committed" "count" "countblob" "cross" "current" "data" "database"
1171"datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred" 1311"datafile" "datafiles" "datesplit" "dba" "dbname" "default" "deferred"
@@ -1190,12 +1330,9 @@ you define your own sql-mode-postgres-font-lock-keywords.")
1190"trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown" 1330"trigger_info_size" "true" "trunc" "uncommitted" "unicode" "unknown"
1191"unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes" 1331"unlimited" "unlisted" "user" "utf8" "value" "varying" "volumes"
1192"wait" "windows_code" "workspace" "write" "xml" 1332"wait" "windows_code" "workspace" "write" "xml"
1333))
1193 1334
1194) t) "\\b"))) 1335 (linter-reserved (sql-keywords-re
1195 (linter-reserved-words (eval-when-compile
1196 (concat "\\b"
1197 (regexp-opt '(
1198
1199"access" "action" "add" "address" "after" "all" "alter" "always" "and" 1336"access" "action" "add" "address" "after" "all" "alter" "always" "and"
1200"any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit" 1337"any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
1201"aud_obj_name_len" "backup" "base" "before" "between" "blobfile" 1338"aud_obj_name_len" "backup" "base" "before" "between" "blobfile"
@@ -1213,22 +1350,16 @@ you define your own sql-mode-postgres-font-lock-keywords.")
1213"start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then" 1350"start" "stop" "sync" "synchronize" "synonym" "sysdate" "table" "then"
1214"to" "union" "unique" "unlock" "until" "update" "using" "values" 1351"to" "union" "unique" "unlock" "until" "update" "using" "values"
1215"view" "when" "where" "with" "without" 1352"view" "when" "where" "with" "without"
1353))
1216 1354
1217) t) "\\b"))) 1355 (linter-types (sql-keywords-re
1218 (linter-types (eval-when-compile
1219 (concat "\\b"
1220 (regexp-opt '(
1221
1222"bigint" "bitmap" "blob" "boolean" "char" "character" "date" 1356"bigint" "bitmap" "blob" "boolean" "char" "character" "date"
1223"datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar" 1357"datetime" "dec" "decimal" "double" "float" "int" "integer" "nchar"
1224"number" "numeric" "real" "smallint" "varbyte" "varchar" "byte" 1358"number" "numeric" "real" "smallint" "varbyte" "varchar" "byte"
1225"cursor" "long" 1359"cursor" "long"
1360))
1226 1361
1227) t) "\\b"))) 1362 (linter-functions (sql-keywords-re
1228 (linter-builtin-functions (eval-when-compile
1229 (concat "\\b"
1230 (regexp-opt '(
1231
1232"abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime" 1363"abs" "acos" "asin" "atan" "atan2" "avg" "ceil" "cos" "cosh" "divtime"
1233"exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw" 1364"exp" "floor" "getbits" "getblob" "getbyte" "getlong" "getraw"
1234"getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log" 1365"getstr" "gettext" "getword" "hextoraw" "lenblob" "length" "log"
@@ -1239,20 +1370,12 @@ you define your own sql-mode-postgres-font-lock-keywords.")
1239"to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode" 1370"to_gmtime" "to_localtime" "to_number" "trim" "upper" "decode"
1240"substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap" 1371"substr" "substring" "chr" "dayname" "days" "greatest" "hex" "initcap"
1241"instr" "least" "multime" "replace" "width" 1372"instr" "least" "multime" "replace" "width"
1373)))
1242 1374
1243) t) "\\b")))) 1375 `((,linter-keywords . font-lock-keyword-face)
1244 (append sql-mode-ansi-font-lock-keywords 1376 (,linter-reserved . font-lock-keyword-face)
1245 (list (cons linter-keywords 'font-lock-keywords-face) 1377 (,linter-functions . font-lock-builtin-face)
1246 (cons linter-reserved-words 'font-lock-keyword-face) 1378 (,linter-types . font-lock-type-face)))
1247 ;; XEmacs doesn't have font-lock-builtin-face
1248 (if (string-match "XEmacs\\|Lucid" emacs-version)
1249 (cons linter-builtin-functions 'font-lock-preprocessor-face)
1250 ;; GNU Emacs 19 doesn't have it either
1251 (if (string-match "GNU Emacs 19" emacs-version)
1252 (cons linter-builtin-functions 'font-lock-keywords-face)
1253 ;; Emacs
1254 (cons linter-builtin-functions 'font-lock-builtin-face)))
1255 (cons linter-types 'font-lock-type-face))))
1256 1379
1257 "Linter SQL keywords used by font-lock. 1380 "Linter SQL keywords used by font-lock.
1258 1381
@@ -1261,21 +1384,18 @@ regular expressions are created during compilation by calling the
1261function `regexp-opt'.") 1384function `regexp-opt'.")
1262 1385
1263(defvar sql-mode-ms-font-lock-keywords 1386(defvar sql-mode-ms-font-lock-keywords
1264 (let ((ms-reserved-words (eval-when-compile 1387 (let ((ms-reserved (sql-keywords-re
1265 (concat "\\b"
1266 (regexp-opt '(
1267
1268"absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization" 1388"absolute" "add" "all" "alter" "and" "any" "as" "asc" "authorization"
1269"avg" "backup" "begin" "between" "break" "browse" "bulk" "by" 1389"avg" "backup" "begin" "between" "break" "browse" "bulk" "by"
1270"cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce" 1390"cascade" "case" "check" "checkpoint" "close" "clustered" "coalesce"
1271"column" "commit" "committed" "compute" "confirm" "constraint" 1391"column" "commit" "committed" "compute" "confirm" "constraint"
1272"contains" "containstable" "continue" "controlrow" "convert" "count" 1392"contains" "containstable" "continue" "controlrow" "convert" "count"
1273"create" "cross" "current" "current_date" "current_time" 1393"create" "cross" "current" "current_date" "current_time"
1274"current_timestamp" "current_user" "database" "deallocate" 1394"current_timestamp" "current_user" "database" "deallocate" "declare"
1275"declare" "default" "delete" "deny" "desc" "disk" "distinct" 1395"default" "delete" "deny" "desc" "disk" "distinct" "distributed"
1276"distributed" "double" "drop" "dummy" "dump" "else" "end" "errlvl" 1396"double" "drop" "dummy" "dump" "else" "end" "errlvl" "errorexit"
1277"errorexit" "escape" "except" "exec" "execute" "exists" "exit" "fetch" 1397"escape" "except" "exec" "execute" "exists" "exit" "fetch" "file"
1278"file" "fillfactor" "first" "floppy" "for" "foreign" "freetext" 1398"fillfactor" "first" "floppy" "for" "foreign" "freetext"
1279"freetexttable" "from" "full" "goto" "grant" "group" "having" 1399"freetexttable" "from" "full" "goto" "grant" "group" "having"
1280"holdlock" "identity" "identity_insert" "identitycol" "if" "in" 1400"holdlock" "identity" "identity_insert" "identitycol" "if" "in"
1281"index" "inner" "insert" "intersect" "into" "is" "isolation" "join" 1401"index" "inner" "insert" "intersect" "into" "is" "isolation" "join"
@@ -1295,29 +1415,21 @@ function `regexp-opt'.")
1295"textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate" 1415"textsize" "then" "to" "top" "tran" "transaction" "trigger" "truncate"
1296"tsequal" "uncommitted" "union" "unique" "update" "updatetext" 1416"tsequal" "uncommitted" "union" "unique" "update" "updatetext"
1297"updlock" "use" "user" "values" "view" "waitfor" "when" "where" 1417"updlock" "use" "user" "values" "view" "waitfor" "when" "where"
1298"while" "with" "work" "writetext" 1418"while" "with" "work" "writetext" "collate" "function" "openxml"
1299"collate" "function" "openxml" "returns" 1419"returns"
1300 1420))
1301) t) "\\b")))
1302 (ms-types (eval-when-compile
1303 (concat "\\b"
1304 (regexp-opt '(
1305 1421
1422 (ms-types (sql-keywords-re
1306"binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal" 1423"binary" "bit" "char" "character" "cursor" "datetime" "dec" "decimal"
1307"double" "float" "image" "int" "integer" "money" "national" "nchar" 1424"double" "float" "image" "int" "integer" "money" "national" "nchar"
1308"ntext" "numeric" "numeric" "nvarchar" "precision" "real" 1425"ntext" "numeric" "numeric" "nvarchar" "precision" "real"
1309"smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint" 1426"smalldatetime" "smallint" "smallmoney" "text" "timestamp" "tinyint"
1310"uniqueidentifier" "varbinary" "varchar" "varying" 1427"uniqueidentifier" "varbinary" "varchar" "varying"
1311 1428))
1312) t) "\\b")))
1313 1429
1314 (ms-vars "\\b@[a-zA-Z0-9_]*\\b") 1430 (ms-vars "\\b@[a-zA-Z0-9_]*\\b")
1315 1431
1316 (ms-builtin-functions (eval-when-compile 1432 (ms-functions (sql-keywords-re
1317 (concat "\\b"
1318 (regexp-opt '(
1319;; Misc MS builtin functions
1320
1321"@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts" 1433"@@connections" "@@cpu_busy" "@@cursor_rows" "@@datefirst" "@@dbts"
1322"@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy" 1434"@@error" "@@fetch_status" "@@identity" "@@idle" "@@io_busy"
1323"@@langid" "@@language" "@@lock_timeout" "@@max_connections" 1435"@@langid" "@@language" "@@lock_timeout" "@@max_connections"
@@ -1346,14 +1458,12 @@ function `regexp-opt'.")
1346"suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan" 1458"suser_id" "suser_name" "suser_sid" "suser_sname" "system_user" "tan"
1347"textptr" "textvalid" "typeproperty" "unicode" "upper" "user" 1459"textptr" "textvalid" "typeproperty" "unicode" "upper" "user"
1348"user_id" "user_name" "var" "varp" "year" 1460"user_id" "user_name" "var" "varp" "year"
1461))
1349 1462
1350) t) "\\b"))) 1463 (ms-commands
1351
1352 (ms-config-commands
1353 (eval-when-compile 1464 (eval-when-compile
1354 (concat "^\\(\\(set\\s-+\\(" 1465 (concat "^\\(\\(set\\s-+\\("
1355 (regexp-opt '( 1466 (regexp-opt '(
1356
1357"datefirst" "dateformat" "deadlock_priority" "lock_timeout" 1467"datefirst" "dateformat" "deadlock_priority" "lock_timeout"
1358"concat_null_yields_null" "cursor_close_on_commit" 1468"concat_null_yields_null" "cursor_close_on_commit"
1359"disable_def_cnst_chk" "fips_flagger" "identity_insert" "language" 1469"disable_def_cnst_chk" "fips_flagger" "identity_insert" "language"
@@ -1364,19 +1474,14 @@ function `regexp-opt'.")
1364"ansi_warnings" "forceplan" "showplan_all" "showplan_text" 1474"ansi_warnings" "forceplan" "showplan_all" "showplan_text"
1365"statistics" "implicit_transactions" "remote_proc_transactions" 1475"statistics" "implicit_transactions" "remote_proc_transactions"
1366"transaction" "xact_abort" 1476"transaction" "xact_abort"
1367
1368) t) 1477) t)
1369 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$")))) 1478 "\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$"))))
1370 1479
1371 (list (cons ms-config-commands 'font-lock-doc-face) 1480 `((,ms-commands . font-lock-doc-face)
1372 (cons ms-reserved-words 'font-lock-keyword-face) 1481 (,ms-reserved . font-lock-keyword-face)
1373 ;; XEmacs doesn't have 'font-lock-builtin-face 1482 (,ms-functions . font-lock-builtin-face)
1374 (if (string-match "XEmacs\\|Lucid" emacs-version) 1483 (,ms-vars . font-lock-variable-name-face)
1375 (cons ms-builtin-functions 'font-lock-preprocessor-face) 1484 (,ms-types . font-lock-type-face)))
1376 ;; Emacs
1377 (cons ms-builtin-functions 'font-lock-builtin-face))
1378 (cons ms-vars 'font-lock-variable-name-face)
1379 (cons ms-types 'font-lock-type-face)))
1380 1485
1381 "Microsoft SQLServer SQL keywords used by font-lock. 1486 "Microsoft SQLServer SQL keywords used by font-lock.
1382 1487
@@ -1385,7 +1490,7 @@ regular expressions are created during compilation by calling the
1385function `regexp-opt'. Therefore, take a look at the source before 1490function `regexp-opt'. Therefore, take a look at the source before
1386you define your own sql-mode-ms-font-lock-keywords.") 1491you define your own sql-mode-ms-font-lock-keywords.")
1387 1492
1388(defvar sql-mode-sybase-font-lock-keywords sql-mode-ansi-font-lock-keywords 1493(defvar sql-mode-sybase-font-lock-keywords nil
1389 "Sybase SQL keywords used by font-lock. 1494 "Sybase SQL keywords used by font-lock.
1390 1495
1391This variable is used by `sql-mode' and `sql-interactive-mode'. The 1496This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1393,7 +1498,7 @@ regular expressions are created during compilation by calling the
1393function `regexp-opt'. Therefore, take a look at the source before 1498function `regexp-opt'. Therefore, take a look at the source before
1394you define your own sql-mode-sybase-font-lock-keywords.") 1499you define your own sql-mode-sybase-font-lock-keywords.")
1395 1500
1396(defvar sql-mode-informix-font-lock-keywords sql-mode-ansi-font-lock-keywords 1501(defvar sql-mode-informix-font-lock-keywords nil
1397 "Informix SQL keywords used by font-lock. 1502 "Informix SQL keywords used by font-lock.
1398 1503
1399This variable is used by `sql-mode' and `sql-interactive-mode'. The 1504This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1401,7 +1506,7 @@ regular expressions are created during compilation by calling the
1401function `regexp-opt'. Therefore, take a look at the source before 1506function `regexp-opt'. Therefore, take a look at the source before
1402you define your own sql-mode-informix-font-lock-keywords.") 1507you define your own sql-mode-informix-font-lock-keywords.")
1403 1508
1404(defvar sql-mode-interbase-font-lock-keywords sql-mode-ansi-font-lock-keywords 1509(defvar sql-mode-interbase-font-lock-keywords nil
1405 "Interbase SQL keywords used by font-lock. 1510 "Interbase SQL keywords used by font-lock.
1406 1511
1407This variable is used by `sql-mode' and `sql-interactive-mode'. The 1512This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1409,7 +1514,7 @@ regular expressions are created during compilation by calling the
1409function `regexp-opt'. Therefore, take a look at the source before 1514function `regexp-opt'. Therefore, take a look at the source before
1410you define your own sql-mode-interbase-font-lock-keywords.") 1515you define your own sql-mode-interbase-font-lock-keywords.")
1411 1516
1412(defvar sql-mode-ingres-font-lock-keywords sql-mode-ansi-font-lock-keywords 1517(defvar sql-mode-ingres-font-lock-keywords nil
1413 "Ingres SQL keywords used by font-lock. 1518 "Ingres SQL keywords used by font-lock.
1414 1519
1415This variable is used by `sql-mode' and `sql-interactive-mode'. The 1520This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1417,7 +1522,7 @@ regular expressions are created during compilation by calling the
1417function `regexp-opt'. Therefore, take a look at the source before 1522function `regexp-opt'. Therefore, take a look at the source before
1418you define your own sql-mode-interbase-font-lock-keywords.") 1523you define your own sql-mode-interbase-font-lock-keywords.")
1419 1524
1420(defvar sql-mode-solid-font-lock-keywords sql-mode-ansi-font-lock-keywords 1525(defvar sql-mode-solid-font-lock-keywords nil
1421 "Solid SQL keywords used by font-lock. 1526 "Solid SQL keywords used by font-lock.
1422 1527
1423This variable is used by `sql-mode' and `sql-interactive-mode'. The 1528This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1425,7 +1530,76 @@ regular expressions are created during compilation by calling the
1425function `regexp-opt'. Therefore, take a look at the source before 1530function `regexp-opt'. Therefore, take a look at the source before
1426you define your own sql-mode-solid-font-lock-keywords.") 1531you define your own sql-mode-solid-font-lock-keywords.")
1427 1532
1428(defvar sql-mode-mysql-font-lock-keywords sql-mode-ansi-font-lock-keywords 1533(defvar sql-mode-mysql-font-lock-keywords
1534 (let ((mysql-funcs (sql-keywords-re
1535"ascii" "avg" "bdmpolyfromtext" "bdmpolyfromwkb" "bdpolyfromtext"
1536"bdpolyfromwkb" "benchmark" "bin" "bit_and" "bit_length" "bit_or"
1537"bit_xor" "both" "cast" "char_length" "character_length" "coalesce"
1538"concat" "concat_ws" "connection_id" "conv" "convert" "count"
1539"curdate" "current_date" "current_time" "current_timestamp" "curtime"
1540"elt" "encrypt" "export_set" "field" "find_in_set" "found_rows" "from"
1541"geomcollfromtext" "geomcollfromwkb" "geometrycollectionfromtext"
1542"geometrycollectionfromwkb" "geometryfromtext" "geometryfromwkb"
1543"geomfromtext" "geomfromwkb" "get_lock" "group_concat" "hex" "ifnull"
1544"instr" "interval" "isnull" "last_insert_id" "lcase" "leading"
1545"length" "linefromtext" "linefromwkb" "linestringfromtext"
1546"linestringfromwkb" "load_file" "locate" "lower" "lpad" "ltrim"
1547"make_set" "master_pos_wait" "max" "mid" "min" "mlinefromtext"
1548"mlinefromwkb" "mpointfromtext" "mpointfromwkb" "mpolyfromtext"
1549"mpolyfromwkb" "multilinestringfromtext" "multilinestringfromwkb"
1550"multipointfromtext" "multipointfromwkb" "multipolygonfromtext"
1551"multipolygonfromwkb" "now" "nullif" "oct" "octet_length" "ord"
1552"pointfromtext" "pointfromwkb" "polyfromtext" "polyfromwkb"
1553"polygonfromtext" "polygonfromwkb" "position" "quote" "rand"
1554"release_lock" "repeat" "replace" "reverse" "rpad" "rtrim" "soundex"
1555"space" "std" "stddev" "substring" "substring_index" "sum" "sysdate"
1556"trailing" "trim" "ucase" "unix_timestamp" "upper" "user" "variance"
1557))
1558
1559 (mysql-keywords (sql-keywords-re
1560"action" "add" "after" "against" "all" "alter" "and" "as" "asc"
1561"auto_increment" "avg_row_length" "bdb" "between" "by" "cascade"
1562"case" "change" "character" "check" "checksum" "close" "collate"
1563"collation" "column" "columns" "comment" "committed" "concurrent"
1564"constraint" "create" "cross" "data" "database" "default"
1565"delay_key_write" "delayed" "delete" "desc" "directory" "disable"
1566"distinct" "distinctrow" "do" "drop" "dumpfile" "duplicate" "else"
1567"enable" "enclosed" "end" "escaped" "exists" "fields" "first" "for"
1568"force" "foreign" "from" "full" "fulltext" "global" "group" "handler"
1569"having" "heap" "high_priority" "if" "ignore" "in" "index" "infile"
1570"inner" "insert" "insert_method" "into" "is" "isam" "isolation" "join"
1571"key" "keys" "last" "left" "level" "like" "limit" "lines" "load"
1572"local" "lock" "low_priority" "match" "max_rows" "merge" "min_rows"
1573"mode" "modify" "mrg_myisam" "myisam" "natural" "next" "no" "not"
1574"null" "offset" "oj" "on" "open" "optionally" "or" "order" "outer"
1575"outfile" "pack_keys" "partial" "password" "prev" "primary"
1576"procedure" "quick" "raid0" "raid_type" "read" "references" "rename"
1577"repeatable" "restrict" "right" "rollback" "rollup" "row_format"
1578"savepoint" "select" "separator" "serializable" "session" "set"
1579"share" "show" "sql_big_result" "sql_buffer_result" "sql_cache"
1580"sql_calc_found_rows" "sql_no_cache" "sql_small_result" "starting"
1581"straight_join" "striped" "table" "tables" "temporary" "terminated"
1582"then" "to" "transaction" "truncate" "type" "uncommitted" "union"
1583"unique" "unlock" "update" "use" "using" "values" "when" "where"
1584"with" "write" "xor"
1585))
1586
1587 (mysql-types (sql-keywords-re
1588"bigint" "binary" "bit" "blob" "bool" "boolean" "char" "curve" "date"
1589"datetime" "dec" "decimal" "double" "enum" "fixed" "float" "geometry"
1590"geometrycollection" "int" "integer" "line" "linearring" "linestring"
1591"longblob" "longtext" "mediumblob" "mediumint" "mediumtext"
1592"multicurve" "multilinestring" "multipoint" "multipolygon"
1593"multisurface" "national" "numeric" "point" "polygon" "precision"
1594"real" "smallint" "surface" "text" "time" "timestamp" "tinyblob"
1595"tinyint" "tinytext" "unsigned" "varchar" "year" "year2" "year4"
1596"zerofill"
1597)))
1598
1599 `((,mysql-funcs . font-lock-builtin-face)
1600 (,mysql-keywords . font-lock-keyword-face)
1601 (,mysql-types . font-lock-type-face)))
1602
1429 "MySQL SQL keywords used by font-lock. 1603 "MySQL SQL keywords used by font-lock.
1430 1604
1431This variable is used by `sql-mode' and `sql-interactive-mode'. The 1605This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1433,7 +1607,7 @@ regular expressions are created during compilation by calling the
1433function `regexp-opt'. Therefore, take a look at the source before 1607function `regexp-opt'. Therefore, take a look at the source before
1434you define your own sql-mode-mysql-font-lock-keywords.") 1608you define your own sql-mode-mysql-font-lock-keywords.")
1435 1609
1436(defvar sql-mode-sqlite-font-lock-keywords sql-mode-ansi-font-lock-keywords 1610(defvar sql-mode-sqlite-font-lock-keywords nil
1437 "SQLite SQL keywords used by font-lock. 1611 "SQLite SQL keywords used by font-lock.
1438 1612
1439This variable is used by `sql-mode' and `sql-interactive-mode'. The 1613This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1441,7 +1615,7 @@ regular expressions are created during compilation by calling the
1441function `regexp-opt'. Therefore, take a look at the source before 1615function `regexp-opt'. Therefore, take a look at the source before
1442you define your own sql-mode-sqlite-font-lock-keywords.") 1616you define your own sql-mode-sqlite-font-lock-keywords.")
1443 1617
1444(defvar sql-mode-db2-font-lock-keywords sql-mode-ansi-font-lock-keywords 1618(defvar sql-mode-db2-font-lock-keywords nil
1445 "DB2 SQL keywords used by font-lock. 1619 "DB2 SQL keywords used by font-lock.
1446 1620
1447This variable is used by `sql-mode' and `sql-interactive-mode'. The 1621This variable is used by `sql-mode' and `sql-interactive-mode'. The
@@ -1463,16 +1637,16 @@ highlighting rules in sql-mode.")
1463(defun sql-product-feature (feature &optional product) 1637(defun sql-product-feature (feature &optional product)
1464 "Lookup `feature' needed to support the current SQL product. 1638 "Lookup `feature' needed to support the current SQL product.
1465 1639
1466See \[sql-product-support] for a list of products and supported features." 1640See \[sql-product-alist] for a list of products and supported features."
1467 (cadr 1641 (plist-get
1468 (memq feature 1642 (cdr (assoc (or product sql-product)
1469 (assoc (or product sql-product) 1643 sql-product-alist))
1470 sql-product-support)))) 1644 feature))
1471 1645
1472(defun sql-product-font-lock (keywords-only imenu) 1646(defun sql-product-font-lock (keywords-only imenu)
1473 "Sets `font-lock-defaults' and `font-lock-keywords' based on 1647 "Sets `font-lock-defaults' and `font-lock-keywords' based on
1474the product-specific keywords and syntax-alists defined in 1648the product-specific keywords and syntax-alists defined in
1475`sql-product-support'." 1649`sql-product-alist'."
1476 (let 1650 (let
1477 ;; Get the product-specific syntax-alist. 1651 ;; Get the product-specific syntax-alist.
1478 ((syntax-alist 1652 ((syntax-alist
@@ -1483,27 +1657,69 @@ the product-specific keywords and syntax-alists defined in
1483 ;; Get the product-specific keywords. 1657 ;; Get the product-specific keywords.
1484 (setq sql-mode-font-lock-keywords 1658 (setq sql-mode-font-lock-keywords
1485 (append 1659 (append
1486 (eval (sql-product-feature :font-lock)) 1660 (unless (eq sql-product 'ansi)
1661 (eval (sql-product-feature :font-lock)))
1662 ;; Always highlight ANSI keywords
1663 (eval (sql-product-feature :font-lock 'ansi))
1664 ;; Fontify object names in CREATE, DROP and ALTER DDL
1665 ;; statements
1487 (list sql-mode-font-lock-object-name))) 1666 (list sql-mode-font-lock-object-name)))
1488 1667
1489 ;; Setup font-lock. (What is the minimum we should have to do 1668 ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
1490 ;; here?) 1669 (set (make-local-variable 'font-lock-set-defaults) nil)
1491 (setq font-lock-set-defaults nil 1670 (setq font-lock-defaults (list 'sql-mode-font-lock-keywords
1492 font-lock-keywords sql-mode-font-lock-keywords
1493 font-lock-defaults (list 'sql-mode-font-lock-keywords
1494 keywords-only t syntax-alist)) 1671 keywords-only t syntax-alist))
1495 1672
1673 ;; Force font lock to reinitialize if it is already on
1674 ;; Otherwise, we can wait until it can be started.
1675 (when (and (fboundp 'font-lock-mode)
1676 font-lock-mode)
1677 (font-lock-mode-internal nil)
1678 (font-lock-mode-internal t))
1679
1680 (add-hook 'font-lock-mode-hook
1681 (lambda ()
1682 ;; Provide defaults for new font-lock faces.
1683 (defvar font-lock-builtin-face
1684 (if (boundp 'font-lock-preprocessor-face)
1685 font-lock-preprocessor-face
1686 font-lock-keyword-face))
1687 (defvar font-lock-doc-face font-lock-string-face))
1688 nil t)
1689
1496 ;; Setup imenu; it needs the same syntax-alist. 1690 ;; Setup imenu; it needs the same syntax-alist.
1497 (when imenu 1691 (when imenu
1498 (setq imenu-syntax-alist syntax-alist)))) 1692 (setq imenu-syntax-alist syntax-alist))))
1499 1693
1500;;;###autoload 1694;;;###autoload
1501(defun sql-add-product-keywords (product keywords) 1695(defun sql-add-product-keywords (product keywords &optional append)
1502 "Append a `font-lock-keywords' entry to the existing entries defined 1696 "Add highlighting KEYWORDS for SQL PRODUCT.
1503 for the specified `product'." 1697
1504 1698PRODUCT should be a symbol, the name of a sql product, such as
1505 (let ((font-lock (sql-product-feature :font-lock product))) 1699`oracle'. KEYWORDS should be a list; see the variable
1506 (set font-lock (append (eval font-lock) (list keywords))))) 1700`font-lock-keywords'. By default they are added at the beginning
1701of the current highlighting list. If optional argument APPEND is
1702`set', they are used to replace the current highlighting list.
1703If APPEND is any other non-nil value, they are added at the end
1704of the current highlighting list.
1705
1706For example:
1707
1708 (sql-add-product-keywords 'ms
1709 '((\"\\\\b\\\\w+_t\\\\b\" . font-lock-type-face)))
1710
1711adds a fontification pattern to fontify identifiers ending in
1712`_t' as data types."
1713
1714 (let ((font-lock (sql-product-feature :font-lock product))
1715 old)
1716 (setq old (eval font-lock))
1717 (set font-lock
1718 (if (eq append 'set)
1719 keywords
1720 (if append
1721 (append old keywords)
1722 (append keywords old))))))
1507 1723
1508 1724
1509 1725
@@ -1517,10 +1733,6 @@ selected."
1517 ;; Setup font-lock 1733 ;; Setup font-lock
1518 (sql-product-font-lock nil t) 1734 (sql-product-font-lock nil t)
1519 1735
1520 ;; Force fontification, if its enabled.
1521 (if font-lock-mode
1522 (font-lock-fontify-buffer))
1523
1524 ;; Set the mode name to include the product. 1736 ;; Set the mode name to include the product.
1525 (setq mode-name (concat "SQL[" (prin1-to-string sql-product) "]")))) 1737 (setq mode-name (concat "SQL[" (prin1-to-string sql-product) "]"))))
1526 1738
@@ -1528,7 +1740,7 @@ selected."
1528 "Set `sql-product' to product and enable appropriate 1740 "Set `sql-product' to product and enable appropriate
1529highlighting." 1741highlighting."
1530 (interactive "SEnter SQL product: ") 1742 (interactive "SEnter SQL product: ")
1531 (when (not (assoc product sql-product-support)) 1743 (when (not (assoc product sql-product-alist))
1532 (error "SQL product %s is not supported; treated as ANSI" product) 1744 (error "SQL product %s is not supported; treated as ANSI" product)
1533 (setq product 'ansi)) 1745 (setq product 'ansi))
1534 1746
@@ -1952,6 +2164,19 @@ Every newline in STRING will be preceded with a space and a backslash."
1952 (interactive) 2164 (interactive)
1953 (sql-send-region (point-min) (point-max))) 2165 (sql-send-region (point-min) (point-max)))
1954 2166
2167(defun sql-send-string (str)
2168 "Send a string to the SQL process."
2169 (interactive "sSQL Text: ")
2170 (if (buffer-live-p sql-buffer)
2171 (save-excursion
2172 (comint-send-string sql-buffer str)
2173 (comint-send-string sql-buffer "\n")
2174 (message "Sent string to buffer %s." (buffer-name sql-buffer))
2175 (if sql-pop-to-buffer-after-send-region
2176 (pop-to-buffer sql-buffer)
2177 (display-buffer sql-buffer)))
2178 (message "No SQL process started.")))
2179
1955(defun sql-toggle-pop-to-buffer-after-send-region (&optional value) 2180(defun sql-toggle-pop-to-buffer-after-send-region (&optional value)
1956 "Toggle `sql-pop-to-buffer-after-send-region'. 2181 "Toggle `sql-pop-to-buffer-after-send-region'.
1957 2182
@@ -2611,6 +2836,8 @@ parameters and command options."
2611 (setq params (append params (list sql-database)))) 2836 (setq params (append params (list sql-database))))
2612 (if (not (string= "" sql-server)) 2837 (if (not (string= "" sql-server))
2613 (setq params (append (list "-h" sql-server) params))) 2838 (setq params (append (list "-h" sql-server) params)))
2839 (if (not (string= "" sql-user))
2840 (setq params (append (list "-U" sql-user) params)))
2614 (set-buffer (apply 'make-comint "SQL" sql-postgres-program 2841 (set-buffer (apply 'make-comint "SQL" sql-postgres-program
2615 nil params)))) 2842 nil params))))
2616 2843