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)
)
)