bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#20266: Emacs doesn't respond when editing the attached c header file


From: Alan Mackenzie
Subject: bug#20266: Emacs doesn't respond when editing the attached c header file.
Date: Tue, 21 Apr 2015 16:14:42 +0000
User-agent: Mutt/1.5.23 (2014-03-12)

Hello, Netjune.

On Sun, Apr 12, 2015 at 10:15:15AM +0800, 张海君 wrote:

> > 在 2015年4月7日,23:16,Alan Mackenzie <address@hidden> 写道:

> > In article <address@hidden> you wrote:
> >> [-- text/plain, encoding 7bit, charset: us-ascii, 13 lines --]

> >> Emacs doesn't respond when editing the attached c header file.
> >> Emacs version: 24.4.

> >> ------------------------------------
> >> Run emacs with "emacs -Q test.h".
> >> M-x mark-whole-buffer
> >> M-x kill-ring-save
> >> M-x end-of-buffer
> >> M-x yank
> >> Then emacs doesn't respond for about 5 seconds.
> >> M-x scroll-down-command. 
> >> Then emacs doesn't respond for about 5 seconds too.

> > Yes.  This isn't good at all.

> >> M-x scroll-down-command.
> >> Then emacs doesn't respond for about 5 seconds too.

> > I can't actually reproduce this delay.

> Try do it more than 4 times, like: M-> M-v M-v M-v M-v M-v.
> The delay often happens at the first M-v, but not always.
> The delay is about 5 seconds on mac OSX (cpu: 1.4GHz), and is about 2 seconds 
> on linux (cpu: 2.53Ghz).

After applying the patch below, I measured a single M-v from the end of
the buffer, and it took 0.14s.  This is on GNU/Linux on a 5 year old PC
(2.6 GHz processor).

> Or try to input some text (like newline chars) at the end of buffer.
> I input a newline at the end of buffer, and emacs didn't respond about 2 
> seconds on linux.

Yes.  That is a different kettle of fish altogether.

> After apply the patch, there is no delay after yank.

Thanks.  With the following patch (instead of the first one) there
shouldn't be much delay with C-x u after having done the yank.

The patch is calculated in Emacs-24.4.  Please try it out.



--- cc-mode.el.orig     2014-03-21 05:34:40.000000000 +0000
+++ cc-mode.el  2015-04-21 14:33:55.571993081 +0000
@@ -509,6 +509,14 @@
   (set (make-local-variable 'comment-line-break-function)
        'c-indent-new-comment-line)
 
+  ;; Prevent time-wasting activity on C-y.
+  (when (boundp 'yank-handled-properties)
+    (make-local-variable 'yank-handled-properties)
+    (let ((yank-cat-handler (assq 'category yank-handled-properties)))
+      (when yank-cat-handler
+       (setq yank-handled-properties (remq yank-cat-handler
+                                           yank-handled-properties)))))
+
   ;; For the benefit of adaptive file, which otherwise mis-fills.
   (setq fill-paragraph-handle-comment nil)
 
@@ -831,6 +839,18 @@
 (defvar c-old-EOM 0)
 (make-variable-buffer-local 'c-old-EOM)
 
+(defun c-called-from-text-property-change-p ()
+  ;; Is the primitive which invoked `before-change-functions' or
+  ;; `after-change-functions' one which merely changes text properties?  This
+  ;; function must be called directly from a member of one of the above hooks.
+  ;;
+  ;; In the following call, frame 0 is `backtrace-frame', frame 1 is
+  ;; `c-called-from-text-property-change-p', frame 2 is
+  ;; `c-before/after-change', frame 3 is the primitive invoking the change
+  ;; hook.
+  (memq (cadr (backtrace-frame 3))
+       '(put-text-property remove-list-of-text-properties)))
+
 (defun c-extend-region-for-CPP (beg end)
   ;; Set c-old-BOM or c-old-EOM respectively to BEG, END, each extended to the
   ;; beginning/end of any preprocessor construct they may be in.
@@ -988,64 +1008,65 @@
   ;; it/them from the cache.  Don't worry about being inside a string
   ;; or a comment - "wrongly" removing a symbol from `c-found-types'
   ;; isn't critical.
-  (setq c-maybe-stale-found-type nil)
-  (save-restriction
-    (save-match-data
-      (widen)
-      (save-excursion
-       ;; Are we inserting/deleting stuff in the middle of an identifier?
-       (c-unfind-enclosing-token beg)
-       (c-unfind-enclosing-token end)
-       ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
-       (when (< beg end)
-         (c-unfind-coalesced-tokens beg end))
-       ;; Are we (potentially) disrupting the syntactic context which
-       ;; makes a type a type?  E.g. by inserting stuff after "foo" in
-       ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
-       ;;
-       ;; We search for appropriate c-type properties "near" the change.
-       ;; First, find an appropriate boundary for this property search.
-       (let (lim
-             type type-pos
-             marked-id term-pos
-             (end1
-              (or (and (eq (get-text-property end 'face) 
'font-lock-comment-face)
-                       (previous-single-property-change end 'face))
-                  end)))
-         (when (>= end1 beg) ; Don't hassle about changes entirely in comments.
-           ;; Find a limit for the search for a `c-type' property
-           (while
-               (and (/= (skip-chars-backward "^;{}") 0)
-                    (> (point) (point-min))
-                    (memq (c-get-char-property (1- (point)) 'face)
-                          '(font-lock-comment-face font-lock-string-face))))
-           (setq lim (max (point-min) (1- (point))))
-
-           ;; Look for the latest `c-type' property before end1
-           (when (and (> end1 (point-min))
-                      (setq type-pos
-                            (if (get-text-property (1- end1) 'c-type)
-                                end1
-                              (previous-single-property-change end1 'c-type 
nil lim))))
-             (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
-
-             (when (memq type '(c-decl-id-start c-decl-type-start))
-               ;; Get the identifier, if any, that the property is on.
-               (goto-char (1- type-pos))
-               (setq marked-id
-                     (when (looking-at "\\(\\sw\\|\\s_\\)")
-                       (c-beginning-of-current-token)
-                       (buffer-substring-no-properties (point) type-pos)))
-
-               (goto-char end1)
-               (skip-chars-forward "^;{}") ; FIXME!!!  loop for comment, maybe
-               (setq lim (point))
-               (setq term-pos
-                     (or (next-single-property-change end 'c-type nil lim) 
lim))
-               (setq c-maybe-stale-found-type
-                     (list type marked-id
-                           type-pos term-pos
-                           (buffer-substring-no-properties type-pos term-pos)
+  (unless (c-called-from-text-property-change-p)
+    (setq c-maybe-stale-found-type nil)
+    (save-restriction
+      (save-match-data
+       (widen)
+       (save-excursion
+         ;; Are we inserting/deleting stuff in the middle of an identifier?
+         (c-unfind-enclosing-token beg)
+         (c-unfind-enclosing-token end)
+         ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
+         (when (< beg end)
+           (c-unfind-coalesced-tokens beg end))
+         ;; Are we (potentially) disrupting the syntactic context which
+         ;; makes a type a type?  E.g. by inserting stuff after "foo" in
+         ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
+         ;;
+         ;; We search for appropriate c-type properties "near" the change.
+         ;; First, find an appropriate boundary for this property search.
+         (let (lim
+               type type-pos
+               marked-id term-pos
+               (end1
+                (or (and (eq (get-text-property end 'face) 
'font-lock-comment-face)
+                         (previous-single-property-change end 'face))
+                    end)))
+           (when (>= end1 beg) ; Don't hassle about changes entirely in 
comments.
+             ;; Find a limit for the search for a `c-type' property
+             (while
+                 (and (/= (skip-chars-backward "^;{}") 0)
+                      (> (point) (point-min))
+                      (memq (c-get-char-property (1- (point)) 'face)
+                            '(font-lock-comment-face font-lock-string-face))))
+             (setq lim (max (point-min) (1- (point))))
+
+             ;; Look for the latest `c-type' property before end1
+             (when (and (> end1 (point-min))
+                        (setq type-pos
+                              (if (get-text-property (1- end1) 'c-type)
+                                  end1
+                                (previous-single-property-change end1 'c-type 
nil lim))))
+               (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
+
+               (when (memq type '(c-decl-id-start c-decl-type-start))
+                 ;; Get the identifier, if any, that the property is on.
+                 (goto-char (1- type-pos))
+                 (setq marked-id
+                       (when (looking-at "\\(\\sw\\|\\s_\\)")
+                         (c-beginning-of-current-token)
+                         (buffer-substring-no-properties (point) type-pos)))
+
+                 (goto-char end1)
+                 (skip-chars-forward "^;{}") ; FIXME!!!  loop for comment, 
maybe
+                 (setq lim (point))
+                 (setq term-pos
+                       (or (next-single-property-change end 'c-type nil lim) 
lim))
+                 (setq c-maybe-stale-found-type
+                       (list type marked-id
+                             type-pos term-pos
+                             (buffer-substring-no-properties type-pos term-pos)
                              (buffer-substring-no-properties beg end)))))))
 
          (if c-get-state-before-change-functions
@@ -1056,7 +1077,7 @@
          )))
     ;; The following must be done here rather than in `c-after-change' because
     ;; newly inserted parens would foul up the invalidation algorithm.
-  (c-invalidate-state-cache beg))
+    (c-invalidate-state-cache beg)))
 
 (defvar c-in-after-change-fontification nil)
 (make-variable-buffer-local 'c-in-after-change-fontification)
@@ -1077,49 +1098,51 @@
   ;; This calls the language variable c-before-font-lock-functions, if non nil.
   ;; This typically sets `syntax-table' properties.
 
-  (c-save-buffer-state (case-fold-search open-paren-in-column-0-is-defun-start)
-    ;; When `combine-after-change-calls' is used we might get calls
-    ;; with regions outside the current narrowing.  This has been
-    ;; observed in Emacs 20.7.
-    (save-restriction
-      (save-match-data           ; c-recognize-<>-arglists changes match-data
-       (widen)
-
-       (when (> end (point-max))
-         ;; Some emacsen might return positions past the end. This has been
-         ;; observed in Emacs 20.7 when rereading a buffer changed on disk
-         ;; (haven't been able to minimize it, but Emacs 21.3 appears to
-         ;; work).
-         (setq end (point-max))
-         (when (> beg end)
-           (setq beg end)))
-
-       ;; C-y is capable of spuriously converting category properties
-       ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
-       ;; properties.  Remove these when it happens.
-       (c-clear-char-property-with-value beg end 'syntax-table
-                                         c-<-as-paren-syntax)
-       (c-clear-char-property-with-value beg end 'syntax-table
-                                         c->-as-paren-syntax)
-       (c-clear-char-property-with-value beg end 'syntax-table nil)
-
-       (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
-       (c-invalidate-sws-region-after beg end)
-       ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
-       (c-invalidate-find-decl-cache beg)
-
-       (when c-recognize-<>-arglists
-         (c-after-change-check-<>-operators beg end))
-
-       ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
-       ;; larger than (beg end).
-       (setq c-new-BEG beg
-             c-new-END end)
-       (setq c-in-after-change-fontification t)
-       (save-excursion
-         (mapc (lambda (fn)
-                 (funcall fn beg end old-len))
-               c-before-font-lock-functions))))))
+  ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
+  ;; larger than (beg end).
+  (setq c-new-BEG beg  c-new-END end)
+  
+  (unless (c-called-from-text-property-change-p)
+    (c-save-buffer-state (case-fold-search 
open-paren-in-column-0-is-defun-start)
+      ;; When `combine-after-change-calls' is used we might get calls
+      ;; with regions outside the current narrowing.  This has been
+      ;; observed in Emacs 20.7.
+      (save-restriction
+       (save-match-data  ; c-recognize-<>-arglists changes match-data
+         (widen)
+
+         (when (> end (point-max))
+           ;; Some emacsen might return positions past the end. This has been
+           ;; observed in Emacs 20.7 when rereading a buffer changed on disk
+           ;; (haven't been able to minimize it, but Emacs 21.3 appears to
+           ;; work).
+           (setq end (point-max))
+           (when (> beg end)
+             (setq beg end)))
+
+         ;; C-y is capable of spuriously converting category properties
+         ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
+         ;; properties.  Remove these when it happens.
+         (c-save-buffer-state ()
+           (c-clear-char-property-with-value beg end 'syntax-table
+                                             c-<-as-paren-syntax)
+           (c-clear-char-property-with-value beg end 'syntax-table
+                                             c->-as-paren-syntax)
+           (c-clear-char-property-with-value beg end 'syntax-table nil))
+
+         (c-trim-found-types beg end old-len) ; maybe we don't need all of 
these.
+         (c-invalidate-sws-region-after beg end)
+         ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
+         (c-invalidate-find-decl-cache beg)
+
+         (when c-recognize-<>-arglists
+           (c-after-change-check-<>-operators beg end))
+
+         (setq c-in-after-change-fontification t)
+         (save-excursion
+           (mapc (lambda (fn)
+                   (funcall fn beg end old-len))
+                 c-before-font-lock-functions)))))))
 
 (defun c-set-fl-decl-start (pos)
   ;; If the beginning of the line containing POS is in the middle of a "local"



-- 
Alan Mackenzie (Nuremberg, Germany).





reply via email to

[Prev in Thread] Current Thread [Next in Thread]