(eval-last-sexp): Avoid introducing any
[bpt/emacs.git] / lisp / emacs-lisp / syntax.el
index 7bd8378..13087af 100644 (file)
@@ -1,6 +1,7 @@
 ;;; syntax.el --- helper functions to find syntactic context
 
-;; Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: internal
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;; The main exported function is `syntax-ppss'.  You might also need
 ;; to call `syntax-ppss-flush-cache' or to add it to
-;; after-change-functions'(although this is automatically done by
+;; before-change-functions'(although this is automatically done by
 ;; syntax-ppss when needed, but that might fail if syntax-ppss is
-;; called in a context where after-change-functions is temporarily
+;; called in a context where before-change-functions is temporarily
 ;; let-bound to nil).
 
 ;;; Todo:
 
 (eval-when-compile (require 'cl))
 
+(defvar font-lock-beginning-of-syntax-function)
+
 (defsubst syntax-ppss-depth (ppss)
   (nth 0 ppss))
 
+(defun syntax-ppss-toplevel-pos (ppss)
+  "Get the latest syntactically outermost position found in a syntactic scan.
+PPSS is a scan state, as returned by `partial-parse-sexp' or `syntax-ppss'.
+An \"outermost position\" means one that it is outside of any syntactic entity:
+outside of any parentheses, comments, or strings encountered in the scan.
+If no such position is recorded in PPSS (because the end of the scan was
+itself at the outermost level), return nil."
+  ;; BEWARE! We rely on the undocumented 9th field.  The 9th field currently
+  ;; contains the list of positions of the enclosing open-parens.
+  ;; I.e. those positions are outside of any string/comment and the first of
+  ;; those is outside of any paren (i.e. corresponds to a nil ppss).
+  ;; If this list is empty but we are in a string or comment, then the 8th
+  ;; field contains a similar "toplevel" position.
+  (or (car (nth 9 ppss))
+      (nth 8 ppss)))
+
 (defsubst syntax-ppss-context (ppss)
   (cond
    ((nth 3 ppss) 'string)
@@ -80,17 +99,19 @@ point (where the PPSS is equivalent to nil).")
     (setq syntax-ppss-cache (cdr syntax-ppss-cache)))
   ;; Throw away `last' value if made invalid.
   (when (< beg (or (car syntax-ppss-last) 0))
-    (if (< beg (or (car (nth 10 syntax-ppss-last))
-                  (nth 9 syntax-ppss-last)
-                  (nth 2 syntax-ppss-last)
-                  0))
+    ;; If syntax-begin-function jumped to BEG, then the old state at BEG can
+    ;; depend on the text after BEG (which is presumably changed).  So if
+    ;; BEG=(car (nth 10 syntax-ppss-last)) don't reuse that data because the
+    ;; assumed nil state at BEG may not be valid any more.
+    (if (<= beg (or (syntax-ppss-toplevel-pos (cdr syntax-ppss-last))
+                    (nth 3 syntax-ppss-last)
+                    0))
        (setq syntax-ppss-last nil)
       (setcar syntax-ppss-last nil)))
   ;; Unregister if there's no cache left.  Sadly this doesn't work
-  ;; because `after-change-functions' is temporarily bound to nil here.
+  ;; because `before-change-functions' is temporarily bound to nil here.
   ;; (unless syntax-ppss-cache
-  ;;   (remove-hook 'after-change-functions
-  ;;            'syntax-ppss-after-change-function t))
+  ;;   (remove-hook 'before-change-functions 'syntax-ppss-flush-cache t))
   )
 
 (defvar syntax-ppss-stats
@@ -102,7 +123,6 @@ point (where the PPSS is equivalent to nil).")
              (error nil)))
          syntax-ppss-stats))
 
-;;;###autoload
 (defun syntax-ppss (&optional pos)
   "Parse-Partial-Sexp State at POS.
 The returned value is the same as `parse-partial-sexp' except that
@@ -131,22 +151,14 @@ Point is at POS when this function returns."
          (cond
           ;; Use OLD-PPSS if possible and close enough.
           ((and (not old-pos) old-ppss
-                ;; BEWARE! We rely on the undocumented 9th field.  The 9th
-                ;; field currently contains the list of positions of
-                ;; open-parens of the enclosing parens.  I.e. those
-                ;; positions are outside of any string/comment
-                ;; and the first of those is outside of any paren
-                ;; (i.e. corresponds to a nil ppss).  If this list is empty
-                ;; but we are in a string or comment, then the 8th field
-                ;; contains a similar "toplevel" position.  If `pt-min' is
-                ;; too far from `pos', we could try to use other positions
-                ;; in (nth 9 old-ppss), but that doesn't seem to happen in
-                ;; practice and it would complicate this code (and the
-                ;; after-change-function code even more).  But maybe it
-                ;; would be useful in "degenerate" cases such as when the
-                ;; whole file is wrapped in a set of parenthesis.
-                (setq pt-min (or (car (nth 9 old-ppss))
-                                 (nth 8 old-ppss)
+                 ;; If `pt-min' is too far from `pos', we could try to use
+                ;; other positions in (nth 9 old-ppss), but that doesn't
+                ;; seem to happen in practice and it would complicate this
+                ;; code (and the before-change-function code even more).
+                ;; But maybe it would be useful in "degenerate" cases such
+                ;; as when the whole file is wrapped in a set
+                ;; of parentheses.
+                (setq pt-min (or (syntax-ppss-toplevel-pos old-ppss)
                                  (nth 2 old-ppss)))
                 (<= pt-min pos) (< (- pos pt-min) syntax-ppss-max-span))
            (incf (car (aref syntax-ppss-stats 1)))
@@ -170,10 +182,10 @@ Point is at POS when this function returns."
                (setq cache (cdr cache)))
              (if cache (setq pt-min (caar cache) ppss (cdar cache)))
 
-             ;; Setup the after-change function if necessary.
+             ;; Setup the before-change function if necessary.
              (unless (or syntax-ppss-cache syntax-ppss-last)
-               (add-hook 'after-change-functions
-                         'syntax-ppss-flush-cache nil t))
+               (add-hook 'before-change-functions
+                         'syntax-ppss-flush-cache t t))
 
              ;; Use the best of OLD-POS and CACHE.
              (if (or (not old-pos) (< old-pos pt-min))
@@ -289,4 +301,6 @@ Point is at POS when this function returns."
 ;;     (syntax-ppss-depth (syntax-ppss))))
 
 (provide 'syntax)
+
+;; arch-tag: 302f1eeb-e77c-4680-a8c5-c543e01161a5
 ;;; syntax.el ends here