changeset 72508:5d642f9eff22

* emacs-lisp/timer.el (timer-set-idle-time, run-with-idle-timer): Accept internal time format for SECS arg. (timer-relative-time): Doc fix. * jit-lock.el: "Stealth fontification by requeuing timers" patch, adapted from Martin Rudalics. (jit-lock-stealth-repeat-timer, jit-lock-stealth-buffers): New vars. (jit-lock-mode): Create jit-lock-stealth-repeat-timer. (jit-lock-stealth-fontify): Reschedule as a idle timer instead of using sit-for.
author Chong Yidong <cyd@stupidchicken.com>
date Thu, 24 Aug 2006 23:40:00 +0000
parents 6f2157f30300
children 59dd12493697
files lisp/ChangeLog lisp/emacs-lisp/timer.el lisp/jit-lock.el
diffstat 3 files changed, 84 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Thu Aug 24 21:18:13 2006 +0000
+++ b/lisp/ChangeLog	Thu Aug 24 23:40:00 2006 +0000
@@ -1,3 +1,16 @@
+2006-08-24  Chong Yidong  <cyd@stupidchicken.com>
+
+	* emacs-lisp/timer.el (timer-set-idle-time, run-with-idle-timer):
+	Accept internal time format for SECS arg.
+	(timer-relative-time): Doc fix.
+
+	* jit-lock.el: "Stealth fontification by requeuing timers" patch,
+	adapted from Martin Rudalics.
+	(jit-lock-stealth-repeat-timer, jit-lock-stealth-buffers): New vars.
+	(jit-lock-mode): Create jit-lock-stealth-repeat-timer.
+	(jit-lock-stealth-fontify): Reschedule as a idle timer instead of
+	using sit-for.
+
 2006-08-24  Francesc Rocher  <francesc.rocher@gmail.com>
 
 	* cus-start.el (all): Add `overline-margin' and
--- a/lisp/emacs-lisp/timer.el	Thu Aug 24 21:18:13 2006 +0000
+++ b/lisp/emacs-lisp/timer.el	Thu Aug 24 23:40:00 2006 +0000
@@ -60,14 +60,22 @@
 
 (defun timer-set-idle-time (timer secs &optional repeat)
   "Set the trigger idle time of TIMER to SECS.
+SECS may be an integer, floating point number, or the internal
+time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'.
 If optional third argument REPEAT is non-nil, make the timer
 fire each time Emacs is idle for that many seconds."
   (or (timerp timer)
       (error "Invalid timer"))
-  (aset timer 1 0)
-  (aset timer 2 0)
-  (aset timer 3 0)
-  (timer-inc-time timer secs)
+  (if (consp secs)
+      (progn (aset timer 1 (car secs))
+	     (aset timer 2 (if (consp (cdr secs)) (car (cdr secs)) (cdr secs)))
+	     (aset timer 3 (or (and (consp (cdr secs)) (consp (cdr (cdr secs)))
+				    (nth 2 secs))
+			       0)))
+    (aset timer 1 0)
+    (aset timer 2 0)
+    (aset timer 3 0)
+    (timer-inc-time timer secs))
   (aset timer 4 repeat)
   timer)
 
@@ -104,7 +112,7 @@
 
 (defun timer-relative-time (time secs &optional usecs)
   "Advance TIME by SECS seconds and optionally USECS microseconds.
-SECS may be a fraction."
+SECS may be either an integer or a floating point number."
   (let ((high (car time))
 	(low (if (consp (cdr time)) (nth 1 time) (cdr time)))
 	(micro (if (numberp (car-safe (cdr-safe (cdr time))))
@@ -412,7 +420,8 @@
 (defun run-with-idle-timer (secs repeat function &rest args)
   "Perform an action the next time Emacs is idle for SECS seconds.
 The action is to call FUNCTION with arguments ARGS.
-SECS may be an integer or a floating point number.
+SECS may be an integer, a floating point number, or the internal
+time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'.
 If Emacs is currently idle, and has been idle for N seconds (N < SECS),
 then it will call FUNCTION in SECS - N seconds from now.
 
--- a/lisp/jit-lock.el	Thu Aug 24 21:18:13 2006 +0000
+++ b/lisp/jit-lock.el	Thu Aug 24 23:40:00 2006 +0000
@@ -171,6 +171,8 @@
 
 (defvar jit-lock-stealth-timer nil
   "Timer for stealth fontification in Just-in-time Lock mode.")
+(defvar jit-lock-stealth-repeat-timer nil
+  "Timer for repeated stealth fontification in Just-in-time Lock mode.")
 (defvar jit-lock-context-timer nil
   "Timer for context fontification in Just-in-time Lock mode.")
 (defvar jit-lock-defer-timer nil
@@ -178,6 +180,8 @@
 
 (defvar jit-lock-defer-buffers nil
   "List of buffers with pending deferred fontification.")
+(defvar jit-lock-stealth-buffers nil
+  "List of buffers that are being fontified stealthily.")
 
 ;;; JIT lock mode
 
@@ -225,6 +229,13 @@
 		 (run-with-idle-timer jit-lock-stealth-time t
 				      'jit-lock-stealth-fontify)))
 
+	 ;; Create, but do not activate, the idle timer for repeated
+	 ;; stealth fontification.
+	 (when (and jit-lock-stealth-time (null jit-lock-stealth-repeat-timer))
+	   (setq jit-lock-stealth-repeat-timer (timer-create))
+	   (timer-set-function jit-lock-stealth-repeat-timer
+			       'jit-lock-stealth-fontify '(t)))
+
 	 ;; Init deferred fontification timer.
 	 (when (and jit-lock-defer-time (null jit-lock-defer-timer))
 	   (setq jit-lock-defer-timer
@@ -443,71 +454,55 @@
 			   (t next))))
 	result))))
 
-
-(defun jit-lock-stealth-fontify ()
+(defun jit-lock-stealth-fontify (&optional repeat)
   "Fontify buffers stealthily.
-This functions is called after Emacs has been idle for
-`jit-lock-stealth-time' seconds."
-  ;; I used to check `inhibit-read-only' here, but I can't remember why.  -stef
+This function is called repeatedly after Emacs has become idle for
+`jit-lock-stealth-time' seconds.  Optional argument REPEAT is expected
+non-nil in a repeated invocation of this function."
+  ;; Cancel timer for repeated invocations.
+  (unless repeat
+    (cancel-timer jit-lock-stealth-repeat-timer))
   (unless (or executing-kbd-macro
 	      memory-full
-	      (window-minibuffer-p (selected-window)))
-    (let ((buffers (buffer-list))
-	  (outer-buffer (current-buffer))
+	      (window-minibuffer-p (selected-window))
+	      ;; For first invocation set up `jit-lock-stealth-buffers'.
+	      ;; In repeated invocations it's already been set up.
+	      (null (if repeat
+			jit-lock-stealth-buffers
+		      (setq jit-lock-stealth-buffers (buffer-list)))))
+    (let ((buffer (car jit-lock-stealth-buffers))
+	  (delay 0)
 	  minibuffer-auto-raise
-	  message-log-max)
-      (with-local-quit
-	(while (and buffers (not (input-pending-p)))
-	  (with-current-buffer (pop buffers)
-	    (when jit-lock-mode
-	      ;; This is funny.  Calling sit-for with 3rd arg non-nil
-	      ;; so that it doesn't redisplay, internally calls
-	      ;; wait_reading_process_input also with a parameter
-	      ;; saying "don't redisplay."  Since this function here
-	      ;; is called periodically, this effectively leads to
-	      ;; process output not being redisplayed at all because
-	      ;; redisplay_internal is never called.  (That didn't
-	      ;; work in the old redisplay either.)  So, we learn that
-	      ;; we mustn't call sit-for that way here.  But then, we
-	      ;; have to be cautious not to call sit-for in a widened
-	      ;; buffer, since this could display hidden parts of that
-	      ;; buffer.  This explains the seemingly weird use of
-	      ;; save-restriction/widen here.
-
-	      (with-temp-message (if jit-lock-stealth-verbose
-				     (concat "JIT stealth lock "
-					     (buffer-name)))
-
-		;; In the following code, the `sit-for' calls cause a
-		;; redisplay, so it's required that the
-		;; buffer-modified flag of a buffer that is displayed
-		;; has the right value---otherwise the mode line of
-		;; an unmodified buffer would show a `*'.
-		(let (start
-		      (nice (or jit-lock-stealth-nice 0))
-		      (point (point-min)))
-		  (while (and (setq start
-				    (jit-lock-stealth-chunk-start point))
-			      ;; In case sit-for runs any timers,
-			      ;; give them the expected current buffer.
-			      (with-current-buffer outer-buffer
-				(sit-for nice)))
-
-		    ;; fontify a block.
-		    (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
-		    ;; If stealth jit-locking is done backwards, this leads to
-		    ;; excessive O(n^2) refontification.   -stef
-		    ;; (when (>= jit-lock-context-unfontify-pos start)
-		    ;;   (setq jit-lock-context-unfontify-pos end))
-
-		    ;; Wait a little if load is too high.
-		    (when (and jit-lock-stealth-load
-			       (> (car (load-average)) jit-lock-stealth-load))
-		      ;; In case sit-for runs any timers,
-		      ;; give them the expected current buffer.
-		      (with-current-buffer outer-buffer
-			(sit-for (or jit-lock-stealth-time 30))))))))))))))
-
+	  message-log-max
+	  start)
+      (if (and jit-lock-stealth-load
+	       (> (car (load-average)) jit-lock-stealth-load))
+	  ;; Wait a little if load is too high.
+	  (setq delay jit-lock-stealth-time)
+	(if (buffer-live-p buffer)
+	    (with-current-buffer buffer
+	      (if (and jit-lock-mode
+		       (setq start (jit-lock-stealth-chunk-start (point))))
+		  ;; Fontify one block of at most `jit-lock-chunk-size'
+		  ;; characters.
+		  (with-temp-message (if jit-lock-stealth-verbose
+					 (concat "JIT stealth lock "
+						 (buffer-name)))
+		    (jit-lock-fontify-now start
+					  (+ start jit-lock-chunk-size))
+		    ;; Run again after `jit-lock-stealth-nice' seconds.
+		    (setq delay (or jit-lock-stealth-nice 0)))
+		;; Nothing to fontify here.  Remove this buffer from
+		;; `jit-lock-stealth-buffers' and run again immediately.
+		(setq jit-lock-stealth-buffers (cdr jit-lock-stealth-buffers))))
+	  ;; Buffer is no longer live.  Remove it from
+	  ;; `jit-lock-stealth-buffers' and run again immediately.
+	  (setq jit-lock-stealth-buffers (cdr jit-lock-stealth-buffers))))
+      ;; Call us again.
+      (when jit-lock-stealth-buffers
+	(timer-set-idle-time jit-lock-stealth-repeat-timer (current-idle-time))
+	(timer-inc-time jit-lock-stealth-repeat-timer delay)
+	(timer-activate-when-idle jit-lock-stealth-repeat-timer t)))))
 
 
 ;;; Deferred fontification.