[comp.emacs] highlighting

liberte@B.CS.UIUC.EDU.UUCP (06/15/87)

Questions about how to do highlighting and proposed solutions on usenet
comp.emacs prompted me to try to repair my highlight-region hack.

This used to work with previous versions of GNU Emacs, but sometime before
18.41 the update mechanism was changed so that (sit-for 0) really does
not do an update if there is pending input.  Since there is now no
way to force and update, I tried to clear the pending input status,
but now it appears difficult to clear the pending-input status.

The following works in some limited cases and may be useful for someone.
It is interesting nevertheless.

(BTW, I learned that if you execute a null command while defining a
keyboard macro, you are thrown out of defining-keyboard-macro mode
*without notice*!! Why even terminate the mode? - just ignore the command 
and continue.)


Dan LaLiberte
liberte@a.cs.uiuc.edu
uiucdcs!liberte

p.s. I may be working on "true" highlighting for emacs this summer.


Here is highlight.el:
----------------------------------------------------
; highlight.el - fack highlighting with inverse-video
; Contains highlight-region, temporarily-highlight-region, 
; and utilities wait-for-key, gobble-input, and interp-string

(global-set-key "\eT" 'temp-highlight)

(global-set-key "\eH" 'highlight-region)



(defun temporarily-highlight-region (start end)
  "Temporarily highlight region from START to END until a keystroke is hit.
Then it unhighlights and tries to execute the input with interp-string.
Doesn't always catch multi-keystroke input if input is too slow.
Doesn't always work if START or END is off the window.
Doesn't always work with selective display.
Probably has a lot of other problems too."
  (interactive "r")
  (highlight-region start end)
;  (message "highlight on")
;  (sit-for 1) ; debug

  (wait-for-key (point))
  (sit-for 1) ; wait for all the input to come in - ha!
  ; If we dont gobble-input, sit-for 0 will not update the screen.
  ; Even if we do gobble-input, it still appears input is pending sometimes.
  ; We really need an update function to force update even with pending input.
  ; Then we wouldnt need gobble-input and interp-string.
  ; Alternatively, a stuff-input function would suffice.
  (let ((keys (gobble-input)))
    (setq keys (concat keys (gobble-input))) ; gobble more input
    (setq keys (concat keys (gobble-input)))
;    (message "about to turn highlight off with pending: %s" keys) ; debug
;    (sit-for 2) ; debug

    (highlight-region start end)
;    (message "highlight off") ; debug
;    (sit-for 2) ; debug
    (setq keys (concat keys (gobble-input)))
    (interp-string keys)
    )
  )


(defun wait-for-key (where)
  "Wait at WHERE until input is pending."
  (let ((old-pnt (point)))
    (sit-for 1)
    (while (not (input-pending-p)) ; wait for input
;      (message "waiting ...")
      (goto-char where)
      (sit-for 1)
;      (message "...")
      )
    (goto-char old-pnt)
    )
  )


(defun gobble-input ()
  "Return all pending input chars in a string"
  (let ((keys ""))
    (while (input-pending-p)
      (setq keys (concat keys (char-to-string (read-char))))
      )
    keys
    )
  )


(defun interp-string (str)
  "Interpret the STRING as if it were from input using execute-kbd-macro.
Doesn't execute a prefix sequence correctly since
it ignores keys if not a complete key sequence."
  (let (tempfunc)
    (fset tempfunc str)
    (execute-kbd-macro tempfunc)
    )
  )



(defun highlight-region (start end)
  "Temporarily highlight region by using inverse-video.
It leaves inverse-video toggled.  Use temporarily-highlight-region instead."
  (interactive "r")

  (let ((text (buffer-substring start end))
	(old-pnt (point)))

; white out the region line by line

    (if (< start end)  ; anything in region?
	(let ((i start)
	      j k start-col end-col)

	  (setq j i)
	  (goto-char i)
	  
	  (while (< i end)
	    (setq start-col (current-column))
;	    (forward-char 1)
	    (end-of-line)
	    (if (> (point) end)
	      (goto-char end)
	      )
	    (setq j (point))
	    (setq end-col (current-column))  ; to end of line or text

;	    (message "insert from %d to %d" i j) ; debug
;	    (sit-for 2) ; debug
	    
	    (goto-char i)
	    (delete-region i j)
	    (setq k (- end-col start-col)) ; number of spaces

;	    (message "insert %d spaces" k) ; debug
;	    (sit-for 1) ; debug
	    (insert-char ?\  k)

	    (forward-char 1) ; move to start of next line
	    
	    (setq end (+ end (- k (- j i)))) ; adjust for extra spaces
	    (setq i (point))  ; start of next line
	    
;	    (message "i=%d  j=%d  k=%d" i j k) ; debug
;	    (sit-for 1) ; debug
		  
	    ) ; while
	 
	  ) ; let
     
      ) ; if
    
    (goto-char old-pnt) ; make sure point is back to initial position
    (sit-for 0) ; force update to erase text

; delete white space and reinsert text with inverse-video on
;    (message "about to delete spaces") ; debug
   
    (delete-region start end)
;    (message "about to reinsert %s" text) ; debug
;    (sit-for 1)  ; debug
   
    (goto-char start)
    (setq inverse-video (not inverse-video))
    (insert text)

    (goto-char old-pnt)
    (sit-for 0) ; force update to show inverted text
   
    ) ; let
  )
 



; The following version of highlight-region does not work because 
; narrow-to-region works very strangely with large buffers.

(defun highlight-region-bad (start end)
  "Temporarily highlight region by using inverse-video."
  (interactive "r")
  (let ((text (buffer-substring start end))
	(old-pnt (point))
	)
    
      (narrow-to-region start end)
      (goto-char start)
      (replace-regexp "[^ \t\n]" " ")  ; this is slow and not even complete
      (widen)
      (goto-char old-pnt)
      (sit-for 0)

; delete white space and reinsert text inverted
   
    (delete-region start end)
;    (message "about to reinsert %s" text)
;    (sit-for 0)
   
    (goto-char start)
    (setq inverse-video (not inverse-video))
    (insert text)
    (goto-char old-pnt)
    (sit-for 0)
   
    )
  )